diff --git a/src/Monitor/Action/Handler/AddMonitorHandler.php b/src/Monitor/Action/Handler/AddMonitorHandler.php index 36e4205..7a2ab54 100644 --- a/src/Monitor/Action/Handler/AddMonitorHandler.php +++ b/src/Monitor/Action/Handler/AddMonitorHandler.php @@ -2,20 +2,24 @@ namespace App\Monitor\Action\Handler; +use App\EventLog\Action\Command\AddEventLogCommand; use App\Monitor\Action\Command\AddMonitorCommand; use App\Monitor\Action\Result\AddMonitorResult; use App\Monitor\Framework\Entity\Monitor; use App\Monitor\Framework\Repository\MonitorRepository; +use App\Monitor\MonitorEvents; use App\User\Framework\Repository\UserRepository; use DateTimeImmutable; use OneToMany\RichBundle\Contract\CommandInterface; use OneToMany\RichBundle\Contract\HandlerInterface; use OneToMany\RichBundle\Contract\ResultInterface; +use Symfony\Component\Messenger\MessageBusInterface; /** @implements HandlerInterface */ readonly class AddMonitorHandler implements HandlerInterface { public function __construct( + private MessageBusInterface $bus, private MonitorRepository $movieMonitorRepository, private UserRepository $userRepository, ) {} @@ -35,6 +39,13 @@ readonly class AddMonitorHandler implements HandlerInterface ->setSearchCount(0) ->setStatus('New'); + $this->bus->dispatch(new AddEventLogCommand( + $user, + MonitorEvents::MONITOR_ADDED->type(), + MonitorEvents::MONITOR_ADDED->message(), + (array) $monitor + )); + $this->movieMonitorRepository->getEntityManager()->persist($monitor); $this->movieMonitorRepository->getEntityManager()->flush(); diff --git a/src/Monitor/Action/Handler/DeleteMonitorHandler.php b/src/Monitor/Action/Handler/DeleteMonitorHandler.php index 78258e7..5013380 100644 --- a/src/Monitor/Action/Handler/DeleteMonitorHandler.php +++ b/src/Monitor/Action/Handler/DeleteMonitorHandler.php @@ -2,22 +2,22 @@ namespace App\Monitor\Action\Handler; -use App\Monitor\Action\Command\AddMonitorCommand; +use App\Download\DownloadEvents; +use App\EventLog\Action\Command\AddEventLogCommand; use App\Monitor\Action\Command\DeleteMonitorCommand; -use App\Monitor\Action\Result\AddMonitorResult; use App\Monitor\Action\Result\DeleteMonitorResult; -use App\Monitor\Framework\Entity\Monitor; use App\Monitor\Framework\Repository\MonitorRepository; -use App\User\Framework\Repository\UserRepository; -use DateTimeImmutable; +use App\Monitor\MonitorEvents; use OneToMany\RichBundle\Contract\CommandInterface; use OneToMany\RichBundle\Contract\HandlerInterface; use OneToMany\RichBundle\Contract\ResultInterface; +use Symfony\Component\Messenger\MessageBusInterface; /** @implements HandlerInterface */ readonly class DeleteMonitorHandler implements HandlerInterface { public function __construct( + private MessageBusInterface $bus, private MonitorRepository $monitorRepository, ) {} @@ -27,6 +27,13 @@ readonly class DeleteMonitorHandler implements HandlerInterface $this->monitorRepository->getEntityManager()->remove($monitor); $this->monitorRepository->getEntityManager()->flush(); + $this->bus->dispatch(new AddEventLogCommand( + $monitor->getUser(), + MonitorEvents::MONITOR_DELETED->type(), + MonitorEvents::MONITOR_DELETED->message(), + (array) $monitor + )); + return new DeleteMonitorResult( status: 'OK', result: [], diff --git a/src/Monitor/Action/Handler/MonitorTvEpisodeHandler.php b/src/Monitor/Action/Handler/MonitorTvEpisodeHandler.php index 664b1d3..d8b4a8f 100644 --- a/src/Monitor/Action/Handler/MonitorTvEpisodeHandler.php +++ b/src/Monitor/Action/Handler/MonitorTvEpisodeHandler.php @@ -6,9 +6,11 @@ use App\Base\Util\EpisodeId; use App\Download\Action\Command\DownloadMediaCommand; use App\Download\DownloadOptionEvaluator; use App\Download\Framework\Repository\DownloadRepository; +use App\EventLog\Action\Command\AddEventLogCommand; use App\Monitor\Action\Command\MonitorMovieCommand; use App\Monitor\Action\Result\MonitorTvEpisodeResult; use App\Monitor\Framework\Repository\MonitorRepository; +use App\Monitor\MonitorEvents; use App\Tmdb\TmdbClient; use App\Torrentio\Action\Command\GetTvShowOptionsCommand; use App\Torrentio\Action\Handler\GetTvShowOptionsHandler; @@ -42,6 +44,13 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface $monitor = $this->monitorRepository->find($command->movieMonitorId); $this->logger->info('> [MonitorTvEpisodeHandler] Executing MonitorTvEpisodeHandler for ' . $monitor->getTitle() . ' season ' . $monitor->getSeason() . ' episode ' . $monitor->getEpisode()); + $this->bus->dispatch(new AddEventLogCommand( + $monitor->getUser(), + MonitorEvents::MONITOR_STARTED->type(), + MonitorEvents::MONITOR_STARTED->message(), + (array) $command + )); + $episodeData = $this->tmdb->tvEpisodeDetails($monitor->getTmdbId(), $monitor->getImdbId(), $monitor->getSeason(), $monitor->getEpisode()); if (null === $episodeData->airDate || "" === $episodeData->airDate) { @@ -116,12 +125,25 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface $this->logger->error('> [MonitorTvEpisodeHandler] ...Exception thrown: ' . $exception->getMessage()); $this->logger->error($exception->getMessage()); $monitor->setStatus('Active'); + $this->bus->dispatch(new AddEventLogCommand( + $monitor->getUser(), + MonitorEvents::MONITOR_ERROR->type(), + MonitorEvents::MONITOR_ERROR->message() . ': ' . $exception->getMessage(), + (array) $monitor + )); } $monitor->setLastSearch(new DateTimeImmutable()); $monitor->setSearchCount($monitor->getSearchCount() + 1); $this->monitorRepository->getEntityManager()->flush(); + $this->bus->dispatch(new AddEventLogCommand( + $monitor->getUser(), + MonitorEvents::MONITOR_FINISHED->type(), + MonitorEvents::MONITOR_FINISHED->message(), + (array) $monitor + )); + return new MonitorTvEpisodeResult( status: 'OK', result: [ diff --git a/src/Monitor/MonitorEvents.php b/src/Monitor/MonitorEvents.php new file mode 100644 index 0000000..0729c03 --- /dev/null +++ b/src/Monitor/MonitorEvents.php @@ -0,0 +1,34 @@ + 'monitor_added', + self::MONITOR_STARTED => 'monitor_started', + self::MONITOR_FINISHED => 'monitor_finished', + self::MONITOR_DELETED => 'monitor_deleted', + self::MONITOR_ERROR => 'monitor_error', + }; + } + + public function message(): string + { + return match ($this) { + self::MONITOR_ADDED => 'A new monitor has been added.', + self::MONITOR_STARTED => 'A monitor has started.', + self::MONITOR_FINISHED => 'A monitor has finished.', + self::MONITOR_DELETED => 'A monitor has been deleted', + self::MONITOR_ERROR => 'A monitor has encountered an error.', + }; + } +} diff --git a/src/User/Framework/Entity/User.php b/src/User/Framework/Entity/User.php index 680ac2a..168336d 100644 --- a/src/User/Framework/Entity/User.php +++ b/src/User/Framework/Entity/User.php @@ -4,6 +4,7 @@ namespace App\User\Framework\Entity; use Aimeos\Map; use App\Download\Framework\Entity\Download; +use App\EventLog\Framework\Entity\EventLog; use App\Monitor\Framework\Entity\Monitor; use App\User\Framework\Repository\UserRepository; use Doctrine\Common\Collections\ArrayCollection; @@ -56,11 +57,18 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\OneToMany(targetEntity: Download::class, mappedBy: 'user')] private Collection $downloads; + /** + * @var Collection + */ + #[ORM\OneToMany(targetEntity: EventLog::class, mappedBy: 'user')] + private Collection $eventLogs; + public function __construct() { $this->userPreferences = new ArrayCollection(); $this->monitors = new ArrayCollection(); $this->downloads = new ArrayCollection(); + $this->eventLogs = new ArrayCollection(); } public function getId(): ?int @@ -342,4 +350,34 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this->hasUserPreference('enable_ical_up_ep') && (bool) $this->getUserPreference('enable_ical_up_ep')->getPreferenceValue() === true; } + + /** + * @return Collection + */ + public function getEventLogs(): Collection + { + return $this->eventLogs; + } + + public function addEventLog(EventLog $eventLog): static + { + if (!$this->eventLogs->contains($eventLog)) { + $this->eventLogs->add($eventLog); + $eventLog->setUser($this); + } + + return $this; + } + + public function removeEventLog(EventLog $eventLog): static + { + if ($this->eventLogs->removeElement($eventLog)) { + // set the owning side to null (unless already changed) + if ($eventLog->getUser() === $this) { + $eventLog->setUser(null); + } + } + + return $this; + } }