WatchList::class, '_api_operation_name' => 'get_all_mine', ], methods: ['GET'] )] public function getWatchLists(): Collection { /** @var User $user */ $user = $this->getUser(); return $user->getWatchLists(); } /** * @throws ParseException * @throws EofException * @throws InvalidDataException * @throws \Exception */ #[Route( path: '/api/watchlists/{token}/calendar', name: 'watchlist_calendar', defaults: [ '_api_resource_class' => WatchList::class, '_api_operation_name' => 'calendar', ] )] public function getWatchlistCalendar(string $token): Response { /** @var WatchList $watchList */ $watchList = $this->watchListRepository->findOneBy(['token' => $token]); $calendar = new Calendar(); /** @var Domain $domain */ foreach ($watchList->getDomains()->getIterator() as $domain) { foreach ($domain->getDomainCalendarEvents() as $event) { $calendar->addEvent($event); } } $calendarResponse = (new CalendarFactory())->createCalendar($calendar); $calendarName = $watchList->getName(); if (null !== $calendarName) { $calendarResponse->withProperty(new Property('X-WR-CALNAME', new TextValue($calendarName))); } return new Response($calendarResponse, Response::HTTP_OK, [ 'Content-Type' => 'text/calendar; charset=utf-8', ]); } /** * @throws \Exception */ #[Route( path: '/api/tracked', name: 'watchlist_get_tracked_domains', defaults: [ '_api_resource_class' => WatchList::class, '_api_operation_name' => 'get_tracked_domains', ] )] public function getTrackedDomains(): array { /** @var User $user */ $user = $this->getUser(); $domains = []; /** @var WatchList $watchList */ foreach ($user->getWatchLists()->getIterator() as $watchList) { /** @var Domain $domain */ foreach ($watchList->getDomains()->getIterator() as $domain) { /** @var DomainEvent|null $exp */ $exp = $this->domainEventRepository->createQueryBuilder('de') ->select() ->where('de.domain = :domain') ->andWhere('de.action = \'expiration\'') ->andWhere('de.deleted = FALSE') ->setParameter('domain', $domain) ->orderBy('de.date', 'DESC') ->setMaxResults(1) ->getQuery() ->getOneOrNullResult(); if (!$domain->getDeleted() && null !== $exp && !in_array($domain, $domains)) { $domains[] = $domain; } } } usort($domains, fn (Domain $d1, Domain $d2) => $d1->getExpiresInDays() - $d2->getExpiresInDays()); return $domains; } /** * @throws \Exception */ #[Route( path: '/api/watchlists/{token}/rss/events', name: 'watchlist_rss_events', defaults: [ '_api_resource_class' => WatchList::class, '_api_operation_name' => 'rss_events', ] )] public function getWatchlistRssEventsFeed(string $token, Request $request): Response { /** @var WatchList $watchlist */ $watchlist = $this->watchListRepository->findOneBy(['token' => $token]); $feed = (new Feed()) ->setLanguage('en') ->setCopyright('Domain Watchdog makes this information available "as is," and does not guarantee its accuracy.') ->setTitle('Domain events ('.$watchlist->getName().')') ->setGenerator('Domain Watchdog - RSS Feed', null, 'https://github.com/maelgangloff/domain-watchdog') ->setDescription('The latest events for domain names in your Watchlist') ->setLink($request->getSchemeAndHttpHost().'/#/tracking/watchlist') ->setFeedLink($request->getSchemeAndHttpHost().'/api/watchlists/'.$token.'/rss/events', 'atom') ->setDateCreated($watchlist->getCreatedAt()); /** @var Domain $domain */ foreach ($watchlist->getDomains()->getIterator() as $domain) { foreach ($this->getRssEventEntries($request->getSchemeAndHttpHost(), $domain) as $entry) { $feed->addEntry($entry); } } return new Response($feed->export('atom'), Response::HTTP_OK, [ 'Content-Type' => 'application/atom+xml; charset=utf-8', ]); } /** * @throws \Exception */ #[Route( path: '/api/watchlists/{token}/rss/status', name: 'watchlist_rss_status', defaults: [ '_api_resource_class' => WatchList::class, '_api_operation_name' => 'rss_status', ] )] public function getWatchlistRssStatusFeed(string $token, Request $request): Response { /** @var WatchList $watchlist */ $watchlist = $this->watchListRepository->findOneBy(['token' => $token]); $feed = (new Feed()) ->setLanguage('en') ->setCopyright('Domain Watchdog makes this information available "as is," and does not guarantee its accuracy.') ->setTitle('Domain EPP status ('.$watchlist->getName().')') ->setGenerator('Domain Watchdog - RSS Feed', null, 'https://github.com/maelgangloff/domain-watchdog') ->setDescription('The latest changes to the EPP status of the domain names in your Watchlist') ->setLink($request->getSchemeAndHttpHost().'/#/tracking/watchlist') ->setFeedLink($request->getSchemeAndHttpHost().'/api/watchlists/'.$token.'/rss/status', 'atom') ->setDateCreated($watchlist->getCreatedAt()); /** @var Domain $domain */ foreach ($watchlist->getDomains()->getIterator() as $domain) { foreach ($this->getRssStatusEntries($request->getSchemeAndHttpHost(), $domain) as $entry) { $feed->addEntry($entry); } } return new Response($feed->export('atom'), Response::HTTP_OK, [ 'Content-Type' => 'application/atom+xml; charset=utf-8', ]); } /** * @throws \Exception */ private function getRssEventEntries(string $baseUrl, Domain $domain): array { $entries = []; foreach ($domain->getEvents()->filter(fn (DomainEvent $e) => $e->getDate()->diff(new \DateTimeImmutable('now'))->y <= 10)->getIterator() as $event) { $entries[] = (new Entry()) ->setId($baseUrl.'/api/domains/'.$domain->getLdhName().'#events-'.$event->getId()) ->setTitle($domain->getLdhName().': '.$event->getAction().' - event update') ->setDescription('Domain name event') ->setLink($baseUrl.'/#/search/domain/'.$domain->getLdhName()) ->setContent($this->render('rss/event_entry.html.twig', [ 'event' => $event, ])->getContent()) ->setDateModified($event->getDate()) ->addAuthor(['name' => strtoupper($domain->getTld()->getTld()).' Registry']); } return $entries; } /** * @throws \Exception */ private function getRssStatusEntries(string $baseUrl, Domain $domain): array { $entries = []; foreach ($domain->getDomainStatuses()->filter(fn (DomainStatus $e) => $e->getDate()->diff(new \DateTimeImmutable('now'))->y <= 10)->getIterator() as $domainStatus) { $authors = [['name' => strtoupper($domain->getTld()->getTld()).' Registry']]; /** @var string $status */ foreach ([...$domainStatus->getAddStatus(), ...$domainStatus->getDeleteStatus()] as $status) { if (str_starts_with($status, 'client')) { $authors[] = ['name' => 'Registrar']; break; } } $entries[] = (new Entry()) ->setId($baseUrl.'/api/domains/'.$domain->getLdhName().'#status-'.$domainStatus->getId()) ->setTitle($domain->getLdhName().' - EPP status update') ->setDescription('There has been a change in the EPP status of the domain name.') ->setLink($baseUrl.'/#/search/domain/'.$domain->getLdhName()) ->setContent($this->render('rss/status_entry.html.twig', [ 'domainStatus' => $domainStatus, ])->getContent()) ->setDateCreated($domainStatus->getCreatedAt()) ->setDateModified($domainStatus->getDate()) ->addCategory(['term' => $domain->getLdhName()]) ->addCategory(['term' => strtoupper($domain->getTld()->getTld())]) ->addAuthors($authors) ; } return $entries; } }