*/ readonly class DownloadMediaHandler implements HandlerInterface { public function __construct( private MessageBusInterface $bus, private DownloaderInterface $downloader, private DownloadRepository $downloadRepository, private UserRepository $userRepository, private Broadcaster $broadcaster, ) {} public function handle(CommandInterface $command): ResultInterface { $user = $this->userRepository->find($command->userId); $this->bus->dispatch(new AddEventLogCommand( $user, DownloadEvents::DOWNLOAD_STARTED->type(), DownloadEvents::DOWNLOAD_STARTED->message(), (array) $command )); if (null === $command->downloadId) { $download = $this->downloadRepository->insert( $user, $command->url, $command->title, $command->filename, $command->imdbId, $command->mediaType, "" ); } else { $download = $this->downloadRepository->find($command->downloadId); } try { $this->validateDownloadUrl($download->getUrl()); } catch (\Throwable $exception) { $download->setProgress(100); $download->setStatus('Failed'); $this->downloadRepository->getEntityManager()->flush(); $this->sendFailedDownloadAlert($download, $command->mercureAlertTopic, $exception->getMessage()); return new DownloadMediaResult(400, $exception->getMessage()); } try { if ($download->getStatus() !== 'Paused') { $this->downloadRepository->updateStatus($download->getId(), 'In Progress'); } $this->downloader->download( $command->mediaType, $command->title, $command->url, $download->getId() ); if ($download->getStatus() !== 'Paused') { $this->downloadRepository->updateStatus($download->getId(), 'Complete'); } } catch (\Throwable $exception) { throw new UnrecoverableMessageHandlingException($exception->getMessage(), 500); } $this->bus->dispatch(new AddEventLogCommand( $user, DownloadEvents::DOWNLOAD_FINISHED->type(), DownloadEvents::DOWNLOAD_FINISHED->message(), (array) $command )); return new DownloadMediaResult(200, "Success."); } public function validateDownloadUrl(string $downloadUrl) { $badFileSizes = [ 2119075, // copyright infringement ]; $badFileLocations = [ 'https://torrentio.strem.fun/videos/failed_infringement_v2.mp4' => 'Removed for Copyright Infringement.', 'https://torrentio.strem.fun/videos/downloading_v2.mp4' => 'Your torrent is downloading to your debrid provider.' ]; $headers = get_headers($downloadUrl, true); if (array_key_exists($headers['Location'], $badFileLocations)) { throw new \Exception($badFileLocations[$headers['Location']]); } } private function sendFailedDownloadAlert(Download $download, string $mercureAlertTopic, ?string $message = null): void { $this->broadcaster->alert( title: 'Download Failed', message: $message ?? "{$download->getTitle()} failed to download.", type: 'warning', mercureAlertTopic: $mercureAlertTopic ); } }