domain-watchdog/src/Controller/WatchListController.php

257 lines
9.6 KiB
PHP
Raw Normal View History

2024-07-18 13:40:49 +02:00
<?php
namespace App\Controller;
use App\Entity\Domain;
2024-08-01 14:37:23 +02:00
use App\Entity\DomainEvent;
2025-04-27 12:13:06 +02:00
use App\Entity\DomainStatus;
2024-07-18 13:40:49 +02:00
use App\Entity\User;
use App\Entity\WatchList;
2024-08-01 14:37:23 +02:00
use App\Repository\WatchListRepository;
2024-07-18 13:40:49 +02:00
use Doctrine\Common\Collections\Collection;
2024-08-01 14:37:23 +02:00
use Eluceo\iCal\Domain\Entity\Calendar;
2024-08-03 18:05:05 +02:00
use Eluceo\iCal\Presentation\Component\Property;
use Eluceo\iCal\Presentation\Component\Property\Value\TextValue;
2024-08-01 14:37:23 +02:00
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
2025-04-27 12:13:06 +02:00
use Laminas\Feed\Writer\Entry;
use Laminas\Feed\Writer\Feed;
2024-08-01 14:37:23 +02:00
use Sabre\VObject\EofException;
use Sabre\VObject\InvalidDataException;
use Sabre\VObject\ParseException;
2024-07-18 13:40:49 +02:00
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
2024-08-01 14:37:23 +02:00
use Symfony\Component\HttpFoundation\Response;
2024-07-18 13:40:49 +02:00
use Symfony\Component\Routing\Attribute\Route;
class WatchListController extends AbstractController
{
public function __construct(
2024-08-04 14:45:27 +02:00
private readonly WatchListRepository $watchListRepository,
2024-08-02 23:24:52 +02:00
) {
2024-07-18 13:40:49 +02:00
}
#[Route(
path: '/api/watchlists',
2024-08-15 03:04:31 +02:00
name: 'watchlist_get_all_mine',
defaults: [
'_api_resource_class' => WatchList::class,
2024-08-15 03:04:31 +02:00
'_api_operation_name' => 'get_all_mine',
],
2024-08-15 03:04:31 +02:00
methods: ['GET']
)]
2024-08-15 03:04:31 +02:00
public function getWatchLists(): Collection
{
2024-08-15 03:04:31 +02:00
/** @var User $user */
$user = $this->getUser();
2024-08-15 03:04:31 +02:00
return $user->getWatchLists();
}
2024-08-01 14:37:23 +02:00
/**
* @throws ParseException
* @throws EofException
* @throws InvalidDataException
2024-08-02 23:24:52 +02:00
* @throws \Exception
2024-08-01 14:37:23 +02:00
*/
#[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
{
2024-08-02 01:06:49 +02:00
/** @var WatchList $watchList */
2024-08-02 23:24:52 +02:00
$watchList = $this->watchListRepository->findOneBy(['token' => $token]);
2024-08-01 14:37:23 +02:00
$calendar = new Calendar();
/** @var Domain $domain */
2024-08-01 14:37:23 +02:00
foreach ($watchList->getDomains()->getIterator() as $domain) {
2025-08-06 19:44:11 +02:00
foreach ($domain->getDomainCalendarEvents() as $event) {
$calendar->addEvent($event);
2024-08-01 14:37:23 +02:00
}
}
2024-08-03 18:05:05 +02:00
$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, [
2024-08-02 23:24:52 +02:00
'Content-Type' => 'text/calendar; charset=utf-8',
2024-08-01 14:37:23 +02:00
]);
}
2024-09-09 11:31:33 +02:00
/**
* @throws \Exception
*/
2024-08-01 14:37:23 +02:00
#[Route(
2024-09-09 11:31:33 +02:00
path: '/api/tracked',
name: 'watchlist_get_tracked_domains',
2024-08-01 14:37:23 +02:00
defaults: [
'_api_resource_class' => WatchList::class,
2024-09-09 11:31:33 +02:00
'_api_operation_name' => 'get_tracked_domains',
]
2024-08-01 14:37:23 +02:00
)]
2024-09-09 11:31:33 +02:00
public function getTrackedDomains(): array
2024-08-01 14:37:23 +02:00
{
/** @var User $user */
$user = $this->getUser();
2024-08-02 23:24:52 +02:00
2024-09-09 11:31:33 +02:00
$domains = [];
/** @var WatchList $watchList */
foreach ($user->getWatchLists()->getIterator() as $watchList) {
/** @var Domain $domain */
foreach ($watchList->getDomains()->getIterator() as $domain) {
/** @var DomainEvent|null $exp */
$exp = $domain->getEvents()->findFirst(fn (int $key, DomainEvent $e) => !$e->getDeleted() && 'expiration' === $e->getAction());
if (!$domain->getDeleted() && null !== $exp && !in_array($domain, $domains)) {
2024-09-09 11:31:33 +02:00
$domains[] = $domain;
}
}
}
usort($domains, fn (Domain $d1, Domain $d2) => $d1->getExpiresInDays() - $d2->getExpiresInDays());
2024-09-09 11:31:33 +02:00
return $domains;
2024-08-01 14:37:23 +02:00
}
2025-04-27 12:13:06 +02:00
/**
2025-05-21 13:20:04 +02:00
* @throws \Exception
2025-04-27 12:13:06 +02:00
*/
#[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.')
2025-05-21 13:20:04 +02:00
->setTitle('Domain events ('.$watchlist->getName().')')
->setGenerator('Domain Watchdog - RSS Feed', null, 'https://github.com/maelgangloff/domain-watchdog')
2025-04-27 12:13:06 +02:00
->setDescription('The latest events for domain names in your Watchlist')
2025-05-21 13:20:04 +02:00
->setLink($request->getSchemeAndHttpHost().'/#/tracking/watchlist')
->setFeedLink($request->getSchemeAndHttpHost().'/api/watchlists/'.$token.'/rss/events', 'atom')
2025-04-27 12:13:06 +02:00
->setDateCreated($watchlist->getCreatedAt());
/** @var Domain $domain */
foreach ($watchlist->getDomains()->getIterator() as $domain) {
foreach ($this->getRssEventEntries($request->getSchemeAndHttpHost(), $domain) as $entry) {
$feed->addEntry($entry);
}
}
2025-05-21 13:20:04 +02:00
return new Response($feed->export('atom'), Response::HTTP_OK, [
2025-04-27 12:13:06 +02:00
'Content-Type' => 'application/atom+xml; charset=utf-8',
]);
}
/**
2025-05-21 13:20:04 +02:00
* @throws \Exception
2025-04-27 12:13:06 +02:00
*/
#[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.')
2025-05-21 13:20:04 +02:00
->setTitle('Domain EPP status ('.$watchlist->getName().')')
->setGenerator('Domain Watchdog - RSS Feed', null, 'https://github.com/maelgangloff/domain-watchdog')
2025-04-27 12:13:06 +02:00
->setDescription('The latest changes to the EPP status of the domain names in your Watchlist')
2025-05-21 13:20:04 +02:00
->setLink($request->getSchemeAndHttpHost().'/#/tracking/watchlist')
->setFeedLink($request->getSchemeAndHttpHost().'/api/watchlists/'.$token.'/rss/status', 'atom')
2025-04-27 12:13:06 +02:00
->setDateCreated($watchlist->getCreatedAt());
/** @var Domain $domain */
foreach ($watchlist->getDomains()->getIterator() as $domain) {
foreach ($this->getRssStatusEntries($request->getSchemeAndHttpHost(), $domain) as $entry) {
$feed->addEntry($entry);
}
}
2025-05-21 13:20:04 +02:00
return new Response($feed->export('atom'), Response::HTTP_OK, [
2025-04-27 12:13:06 +02:00
'Content-Type' => 'application/atom+xml; charset=utf-8',
]);
}
/**
2025-05-21 13:20:04 +02:00
* @throws \Exception
2025-04-27 12:13:06 +02:00
*/
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())
2025-05-21 13:20:04 +02:00
->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())
2025-04-27 12:13:06 +02:00
->setContent($this->render('rss/event_entry.html.twig', [
2025-05-21 13:20:04 +02:00
'event' => $event,
2025-04-27 12:13:06 +02:00
])->getContent())
->setDateModified($event->getDate())
2025-05-21 13:20:04 +02:00
->addAuthor(['name' => strtoupper($domain->getTld()->getTld()).' Registry']);
2025-04-27 12:13:06 +02:00
}
return $entries;
}
/**
2025-05-21 13:20:04 +02:00
* @throws \Exception
2025-04-27 12:13:06 +02:00
*/
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) {
2025-05-21 13:20:04 +02:00
$authors = [['name' => strtoupper($domain->getTld()->getTld()).' Registry']];
2025-04-27 12:13:06 +02:00
/** @var string $status */
foreach ([...$domainStatus->getAddStatus(), ...$domainStatus->getDeleteStatus()] as $status) {
2025-05-21 13:20:04 +02:00
if (str_starts_with($status, 'client')) {
$authors[] = ['name' => 'Registrar'];
2025-04-27 12:13:06 +02:00
break;
}
}
$entries[] = (new Entry())
2025-05-21 13:20:04 +02:00
->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())
2025-04-27 12:13:06 +02:00
->setContent($this->render('rss/status_entry.html.twig', [
2025-05-21 13:20:04 +02:00
'domainStatus' => $domainStatus,
2025-04-27 12:13:06 +02:00
])->getContent())
->setDateCreated($domainStatus->getCreatedAt())
->setDateModified($domainStatus->getDate())
2025-05-21 13:20:04 +02:00
->addCategory(['term' => $domain->getLdhName()])
->addCategory(['term' => strtoupper($domain->getTld()->getTld())])
2025-04-27 12:13:06 +02:00
->addAuthors($authors)
;
}
return $entries;
}
2024-08-02 23:24:52 +02:00
}