feat: notifies user of bad RD download (failed for copyright, etc.)
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 13s
Some checks failed
SonarQube Scan / SonarQube Trigger (push) Failing after 13s
This commit is contained in:
@@ -24,10 +24,10 @@ readonly class Broadcaster
|
|||||||
private LoggerInterface $logger,
|
private LoggerInterface $logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function alert(string $title, string $message, string $type = "success", bool $sendPush = false): void
|
public function alert(string $title, string $message, string $type = "success", bool $sendPush = false, ?string $mercureAlertTopic = null): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$userAlertTopic = $this->requestStack->getCurrentRequest()->getSession()->get('mercure_alert_topic');
|
$userAlertTopic = $mercureAlertTopic ?? $this->requestStack->getCurrentRequest()->getSession()->get('mercure_alert_topic');
|
||||||
$update = new Update(
|
$update = new Update(
|
||||||
$userAlertTopic,
|
$userAlertTopic,
|
||||||
$this->renderer->render('broadcast/Alert.stream.html.twig', [
|
$this->renderer->render('broadcast/Alert.stream.html.twig', [
|
||||||
@@ -39,7 +39,7 @@ readonly class Broadcaster
|
|||||||
);
|
);
|
||||||
$this->hub->publish($update);
|
$this->hub->publish($update);
|
||||||
} catch (\Throwable $exception) {
|
} catch (\Throwable $exception) {
|
||||||
// ToDo: look for better handling to get message to end user
|
$this->logger->error('Unable to publish alert: ' . $exception->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true === $sendPush && in_array($this->notificationTransport, ['ntfy'])) {
|
if (true === $sendPush && in_array($this->notificationTransport, ['ntfy'])) {
|
||||||
|
|||||||
@@ -17,5 +17,6 @@ class DownloadMediaCommand implements CommandInterface
|
|||||||
public string $imdbId,
|
public string $imdbId,
|
||||||
public int $userId,
|
public int $userId,
|
||||||
public ?int $downloadId = null,
|
public ?int $downloadId = null,
|
||||||
|
public ?string $mercureAlertTopic = null,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
namespace App\Download\Action\Handler;
|
namespace App\Download\Action\Handler;
|
||||||
|
|
||||||
|
use App\Base\Enum\MediaType;
|
||||||
|
use App\Base\Service\Broadcaster;
|
||||||
use App\Download\Action\Command\DownloadMediaCommand;
|
use App\Download\Action\Command\DownloadMediaCommand;
|
||||||
use App\Download\Action\Result\DownloadMediaResult;
|
use App\Download\Action\Result\DownloadMediaResult;
|
||||||
use App\Download\DownloadEvents;
|
use App\Download\DownloadEvents;
|
||||||
|
use App\Download\Framework\Entity\Download;
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\Download\Downloader\DownloaderInterface;
|
use App\Download\Downloader\DownloaderInterface;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
use App\EventLog\Action\Command\AddEventLogCommand;
|
||||||
@@ -22,7 +25,7 @@ readonly class DownloadMediaHandler implements HandlerInterface
|
|||||||
private MessageBusInterface $bus,
|
private MessageBusInterface $bus,
|
||||||
private DownloaderInterface $downloader,
|
private DownloaderInterface $downloader,
|
||||||
private DownloadRepository $downloadRepository,
|
private DownloadRepository $downloadRepository,
|
||||||
private UserRepository $userRepository,
|
private UserRepository $userRepository, private Broadcaster $broadcaster,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function handle(CommandInterface $command): ResultInterface
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
@@ -49,6 +52,16 @@ readonly class DownloadMediaHandler implements HandlerInterface
|
|||||||
$download = $this->downloadRepository->find($command->downloadId);
|
$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 {
|
try {
|
||||||
if ($download->getStatus() !== 'Paused') {
|
if ($download->getStatus() !== 'Paused') {
|
||||||
$this->downloadRepository->updateStatus($download->getId(), 'In Progress');
|
$this->downloadRepository->updateStatus($download->getId(), 'In Progress');
|
||||||
@@ -77,4 +90,30 @@ readonly class DownloadMediaHandler implements HandlerInterface
|
|||||||
));
|
));
|
||||||
return new DownloadMediaResult(200, "Success.");
|
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.',
|
||||||
|
];
|
||||||
|
|
||||||
|
$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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ use OneToMany\RichBundle\Contract\InputInterface;
|
|||||||
/** @implements InputInterface<DownloadMediaInput> */
|
/** @implements InputInterface<DownloadMediaInput> */
|
||||||
class DownloadMediaInput implements InputInterface
|
class DownloadMediaInput implements InputInterface
|
||||||
{
|
{
|
||||||
|
public ?string $mercureAlertTopic = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[SourceRequest('url')]
|
#[SourceRequest('url')]
|
||||||
public string $url,
|
public string $url,
|
||||||
@@ -44,6 +46,7 @@ class DownloadMediaInput implements InputInterface
|
|||||||
$this->imdbId,
|
$this->imdbId,
|
||||||
$this->userId,
|
$this->userId,
|
||||||
$this->downloadId,
|
$this->downloadId,
|
||||||
|
$this->mercureAlertTopic,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ use App\Download\DownloadEvents;
|
|||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
use App\EventLog\Action\Command\AddEventLogCommand;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
@@ -24,7 +25,7 @@ class ApiController extends AbstractController
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private DownloadRepository $downloadRepository,
|
private DownloadRepository $downloadRepository,
|
||||||
private MessageBusInterface $bus,
|
private MessageBusInterface $bus,
|
||||||
private readonly Broadcaster $broadcaster,
|
private readonly Broadcaster $broadcaster, private readonly RequestStack $requestStack,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
#[Route('/api/download', name: 'api_download', methods: ['POST'])]
|
#[Route('/api/download', name: 'api_download', methods: ['POST'])]
|
||||||
@@ -42,6 +43,7 @@ class ApiController extends AbstractController
|
|||||||
);
|
);
|
||||||
$input->downloadId = $download->getId();
|
$input->downloadId = $download->getId();
|
||||||
$input->userId = $this->getUser()->getId();
|
$input->userId = $this->getUser()->getId();
|
||||||
|
$input->mercureAlertTopic = $this->requestStack->getSession()->get('mercure_alert_topic');
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
$this->bus->dispatch(new AddEventLogCommand(
|
||||||
$this->getUser(),
|
$this->getUser(),
|
||||||
|
|||||||
@@ -98,6 +98,14 @@ class DownloadRepository extends ServiceEntityRepository
|
|||||||
return $download;
|
return $download;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function updateProgress(int $id, int $progress): Download
|
||||||
|
{
|
||||||
|
$download = $this->find($id);
|
||||||
|
$download->setProgress($progress);
|
||||||
|
$this->getEntityManager()->flush();
|
||||||
|
return $download;
|
||||||
|
}
|
||||||
|
|
||||||
public function delete(int $id)
|
public function delete(int $id)
|
||||||
{
|
{
|
||||||
$entity = $this->find($id);
|
$entity = $this->find($id);
|
||||||
|
|||||||
Reference in New Issue
Block a user