*/ readonly class DownloadSeasonHandler implements HandlerInterface { public function __construct( private MediaFiles $mediaFiles, private LoggerInterface $logger, private TmdbClient $tmdb, private MessageBusInterface $bus, private DownloadOptionEvaluator $downloadOptionEvaluator, private GetTvShowOptionsHandler $getTvShowOptionsHandler, private UserRepository $userRepository, private DownloadRepository $downloadRepository, ) {} public function handle(CommandInterface $command): ResultInterface { $series = $this->tmdb->tvshowDetails($command->imdbId); $this->logger->info('> [DownloadTvSeasonHandler] Executing DownloadTvSeasonHandler for "' . $series->title . '" season ' . $command->season); $episodesInSeason = Map::from($series->episodes[$command->season]); $this->logger->info('> [DownloadTvSeasonHandler] ...Found ' . count($episodesInSeason) . ' episodes in season ' . $command->season); $downloadCommands = []; foreach ($episodesInSeason as $episode) { $this->logger->info('> [DownloadTvSeasonHandler] ...Evaluating episode ' . $episode->episodeNumber); $results = $this->getTvShowOptionsHandler->handle( new GetTvShowOptionsCommand( $series->tmdbId, $command->imdbId, $command->season, $episode->episodeNumber ) ); $this->logger->info('> [DownloadTvSeasonHandler] ......Found ' . count($results->results) . ' total download options, beginning evaluation'); $userPreferences = UserPreferencesFactory::createFromUser( $this->userRepository->findOneBy(['id' => $command->userId]) ); $result = $this->downloadOptionEvaluator->evaluateOptions($results->results, $userPreferences); if (null !== $result) { $this->logger->info('> [DownloadTvSeasonHandler] ......Found 1 matching result'); $this->logger->info('> [DownloadTvSeasonHandler] ......Dispatching DownloadMediaCommand for "' . $series->title . '" season ' . $command->season . ' episode ' . $episode->episodeNumber); $download = $this->createDownload($command, $result->url, $series->title, $result->filename, $episode->episodeNumber); $this->logger->info('> [DownloadTvSeasonHandler] ......Created Download entity with id ' . $download->getId()); $downloadCommand = new DownloadMediaCommand( $download->getUrl(), $download->getTitle(), $download->getFilename(), $download->getMediaType(), $download->getImdbId(), $download->getUser()->getId(), $download->getId() ); $this->bus->dispatch($downloadCommand); $downloadCommands[] = $downloadCommand; } else { $this->logger->info('> [DownloadTvSeasonHandler] ......Found 0 matching results'); } } return new DownloadSeasonResult( status: 200, message: 'Success', data: ['downloads' => $downloadCommands], ); } private function createDownload(DownloadSeasonCommand $command, string $url, string $title, string $filename, int $episodeNumber): Download { $download = new Download(); $download->setUrl($url); $download->setTitle($title); $download->setFilename($filename); $download->setImdbId($command->imdbId); $download->setMediaType(MediaType::TvShow->value); $download->setEpisodeId($this->getEpisodeNumber($command->season, $episodeNumber)); $download->setUser($this->userRepository->find($command->userId)); $this->downloadRepository->getEntityManager()->persist($download); $this->downloadRepository->getEntityManager()->flush(); return $download; } private function getEpisodeNumber(int $season, int $episode): string { return sprintf( "S%sE%s", str_pad($season, 2, "0", STR_PAD_LEFT), str_pad($episode, 2, "0", STR_PAD_LEFT) ); } }