168 lines
7.0 KiB
PHP
168 lines
7.0 KiB
PHP
<?php
|
|
|
|
namespace App\Monitor\Action\Handler;
|
|
|
|
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\Entity\Monitor;
|
|
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;
|
|
use App\User\Dto\UserPreferencesFactory;
|
|
use Carbon\Carbon;
|
|
use DateTimeImmutable;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
|
use Psr\Log\LoggerInterface;
|
|
use Symfony\Component\Messenger\MessageBusInterface;
|
|
|
|
/** @implements HandlerInterface<MonitorMovieCommand> */
|
|
readonly class MonitorTvEpisodeHandler implements HandlerInterface
|
|
{
|
|
public function __construct(
|
|
private GetTvShowOptionsHandler $getTvShowOptionsHandler,
|
|
private DownloadOptionEvaluator $downloadOptionEvaluator,
|
|
private EntityManagerInterface $entityManager,
|
|
private MessageBusInterface $bus,
|
|
private LoggerInterface $logger,
|
|
private MonitorRepository $monitorRepository,
|
|
private TmdbClient $tmdb,
|
|
private DownloadRepository $downloadRepository,
|
|
) {}
|
|
|
|
public function handle(CommandInterface $command): ResultInterface
|
|
{
|
|
try {
|
|
$monitor = $this->monitorRepository->find($command->movieMonitorId);
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] Executing MonitorTvEpisodeHandler for ' . $monitor->getTitle() . ' season ' . $monitor->getSeason() . ' episode ' . $monitor->getEpisode());
|
|
$this->refreshData($monitor);
|
|
|
|
$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) {
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] ...Episode does not have an air date, skipping for now');
|
|
return new MonitorTvEpisodeResult(
|
|
status: 'OK',
|
|
result: [
|
|
'message' => 'No change',
|
|
'monitor' => $monitor,
|
|
]
|
|
);
|
|
}
|
|
|
|
if (null === $monitor->getAirDate()) {
|
|
$monitor->setAirDate(Carbon::parse($episodeData->airDate));
|
|
}
|
|
|
|
if (Carbon::createFromTimestamp($episodeData->airDate) > Carbon::today('UTC')) {
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] ...Episode has not aired yet, skipping for now');
|
|
return new MonitorTvEpisodeResult(
|
|
status: 'OK',
|
|
result: [
|
|
'message' => 'No change',
|
|
'monitor' => $monitor,
|
|
]
|
|
);
|
|
}
|
|
|
|
$monitor->setStatus('In Progress');
|
|
$this->monitorRepository->getEntityManager()->flush();
|
|
|
|
$results = $this->getTvShowOptionsHandler->handle(
|
|
new GetTvShowOptionsCommand(
|
|
$monitor->getTmdbId(),
|
|
$monitor->getImdbId(),
|
|
$monitor->getSeason(),
|
|
$monitor->getEpisode()
|
|
)
|
|
);
|
|
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] ...Found ' . count($results->results) . ' total download options, beginning evaluation');
|
|
|
|
$result = $this->downloadOptionEvaluator->evaluateOptions($results->results, UserPreferencesFactory::createFromUser($monitor->getUser()));
|
|
|
|
if (null !== $result) {
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] ...Found 1 matching result found: dispatching DownloadMediaCommand for "' . $result->title . '"');
|
|
$download = $this->downloadRepository->insert(
|
|
user: $monitor->getUser(),
|
|
url: $result->url,
|
|
title: $monitor->getTitle(),
|
|
filename: $result->filename,
|
|
imdbId: $monitor->getImdbId(),
|
|
mediaType: 'tvshows',
|
|
episodeId: EpisodeId::fromSeasonEpisodeNumbers($monitor->getSeason(), $monitor->getEpisode()),
|
|
);
|
|
$this->bus->dispatch(new DownloadMediaCommand(
|
|
$download->getUrl(),
|
|
$download->getTitle(),
|
|
$download->getFilename(),
|
|
'tvshows',
|
|
$download->getImdbId(),
|
|
$monitor->getUser()->getId(),
|
|
$download->getId(),
|
|
));
|
|
$monitor->setStatus('Complete');
|
|
$monitor->setDownloadedAt(new DateTimeImmutable());
|
|
} else {
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] ...Found 0 matching results found, monitor will run at next interval');
|
|
$monitor->setStatus('Active');
|
|
}
|
|
} catch (\Throwable $exception) {
|
|
$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: [
|
|
'monitor' => $monitor,
|
|
]
|
|
);
|
|
}
|
|
|
|
private function refreshData(Monitor $monitor)
|
|
{
|
|
if (null === $monitor->getPoster()) {
|
|
$this->logger->info('> [MonitorTvEpisodeHandler] Refreshing poster for "' . $monitor->getTitle() . '"');
|
|
$poster = $monitor->getParent()->getPoster();
|
|
if (null !== $poster && "" !== $poster) {
|
|
$monitor->setPoster($poster);
|
|
}
|
|
}
|
|
}
|
|
}
|