fix-feat: ajax download call
This commit is contained in:
37
assets/controllers/download_button_controller.js
Normal file
37
assets/controllers/download_button_controller.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
/*
|
||||
* The following line makes this controller "lazy": it won't be downloaded until needed
|
||||
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
|
||||
*/
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
url: String,
|
||||
title: String,
|
||||
filename: String,
|
||||
mediaType: String,
|
||||
imdbId: String,
|
||||
}
|
||||
|
||||
download() {
|
||||
fetch('/download', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
url: this.urlValue,
|
||||
title: this.titleValue,
|
||||
filename: this.filenameValue,
|
||||
mediaType: this.mediaTypeValue,
|
||||
imdbId: this.imdbIdValue
|
||||
})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(json => {
|
||||
console.log(json)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { Controller } from '@hotwired/stimulus';
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
tmdbId: String,
|
||||
imdbId: String
|
||||
};
|
||||
|
||||
@@ -20,7 +21,7 @@ export default class extends Controller {
|
||||
|
||||
async setOptions() {
|
||||
if (this.options.length === 0) {
|
||||
await fetch(`/torrentio/movies/${this.imdbIdValue}`)
|
||||
await fetch(`/torrentio/movies/${this.tmdbIdValue}/${this.imdbIdValue}`)
|
||||
.then(res => res.text())
|
||||
.then(response => {
|
||||
this.element.innerHTML = response;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"php-tmdb/api": "^4.1",
|
||||
"symfony/asset": "7.2.*",
|
||||
"symfony/console": "7.2.*",
|
||||
"symfony/doctrine-messenger": "7.2.*",
|
||||
"symfony/dotenv": "7.2.*",
|
||||
"symfony/flex": "^2",
|
||||
"symfony/form": "7.2.*",
|
||||
|
||||
74
composer.lock
generated
74
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "eeaaf3d88479bdcd00dcb637222408f4",
|
||||
"content-hash": "0448ecb537f5d169d81a56ba2b3c2cc6",
|
||||
"packages": [
|
||||
{
|
||||
"name": "1tomany/data-uri",
|
||||
@@ -3469,6 +3469,78 @@
|
||||
],
|
||||
"time": "2025-03-25T15:54:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/doctrine-messenger",
|
||||
"version": "v7.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/doctrine-messenger.git",
|
||||
"reference": "c353e6ee6b41748d8ea6faa2d0b84ac501e3ec0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/c353e6ee6b41748d8ea6faa2d0b84ac501e3ec0c",
|
||||
"reference": "c353e6ee6b41748d8ea6faa2d0b84ac501e3ec0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/dbal": "^3.6|^4",
|
||||
"php": ">=8.2",
|
||||
"symfony/messenger": "^6.4|^7.0",
|
||||
"symfony/service-contracts": "^2.5|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/persistence": "<1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/persistence": "^1.3|^2|^3",
|
||||
"symfony/property-access": "^6.4|^7.0",
|
||||
"symfony/serializer": "^6.4|^7.0"
|
||||
},
|
||||
"type": "symfony-messenger-bridge",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Doctrine Messenger Bridge",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/doctrine-messenger/tree/v7.2.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-25T15:54:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/dotenv",
|
||||
"version": "v7.2.0",
|
||||
|
||||
@@ -5,14 +5,7 @@ framework:
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 1
|
||||
multiplier: 1
|
||||
async: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
|
||||
default_bus: messenger.bus.default
|
||||
|
||||
@@ -18,7 +18,11 @@ class DownloadController extends AbstractController
|
||||
public function download(
|
||||
DownloadMediaInput $input,
|
||||
): Response {
|
||||
$this->bus->dispatch($input->toCommand());
|
||||
try {
|
||||
$this->bus->dispatch($input->toCommand());
|
||||
} catch (\Throwable $exception) {
|
||||
return $this->json(['error' => $exception->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return $this->json(['status' => 200, 'message' => 'Added to Queue']);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ final class TorrentioController extends AbstractController
|
||||
private readonly GetTvShowOptionsHandler $getTvShowOptionsHandler,
|
||||
) {}
|
||||
|
||||
#[Route('/torrentio/movies/{imdbId}', name: 'app_torrentio_movies')]
|
||||
#[Route('/torrentio/movies/{tmdbId}/{imdbId}', name: 'app_torrentio_movies')]
|
||||
public function movieOptions(GetMovieOptionsInput $input): Response
|
||||
{
|
||||
$results = $this->getMovieOptionsHandler->handle($input->toCommand());
|
||||
|
||||
@@ -7,6 +7,7 @@ use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
class GetMovieOptionsCommand implements CommandInterface
|
||||
{
|
||||
public function __construct(
|
||||
public string $tmdbId,
|
||||
public string $imdbId,
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Torrentio\Action\Handler;
|
||||
|
||||
use App\Tmdb\Tmdb;
|
||||
use App\Torrentio\Action\Result\GetMovieOptionsResult;
|
||||
use App\Torrentio\Client\Torrentio;
|
||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||
@@ -11,13 +12,15 @@ use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
class GetMovieOptionsHandler implements HandlerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Tmdb $tmdb,
|
||||
private readonly Torrentio $torrentio,
|
||||
) {}
|
||||
|
||||
public function handle(CommandInterface $command): ResultInterface
|
||||
{
|
||||
return new GetMovieOptionsResult(
|
||||
results: $this->torrentio->search($command->imdbId, 'movies')
|
||||
media: $this->tmdb->mediaDetails($command->tmdbId, 'movies'),
|
||||
results: $this->torrentio->search($command->imdbId, 'movies'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,15 @@ use OneToMany\RichBundle\Contract\InputInterface;
|
||||
class GetMovieOptionsInput implements InputInterface
|
||||
{
|
||||
public function __construct(
|
||||
#[SourceRoute('tmdbId')]
|
||||
public string $tmdbId,
|
||||
|
||||
#[SourceRoute('imdbId')]
|
||||
public string $imdbId,
|
||||
) {}
|
||||
|
||||
public function toCommand(): CommandInterface
|
||||
{
|
||||
return new GetMovieOptionsCommand($this->imdbId);
|
||||
return new GetMovieOptionsCommand($this->tmdbId, $this->imdbId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace App\Torrentio\Action\Result;
|
||||
|
||||
use App\Tmdb\TmdbResult;
|
||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||
|
||||
class GetMovieOptionsResult implements ResultInterface
|
||||
{
|
||||
public function __construct(
|
||||
public TmdbResult $media,
|
||||
public array $results
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,8 @@ class ResultFactory
|
||||
$ptn = (object) (new PTN())->parse($title);
|
||||
return new TorrentioResult(
|
||||
self::trimTitle($title),
|
||||
$url,
|
||||
urldecode($url),
|
||||
self::setFilename($url),
|
||||
self::setSize($title),
|
||||
self::setSeeders($title),
|
||||
self::setProvider($title),
|
||||
@@ -33,6 +34,12 @@ class ResultFactory
|
||||
);
|
||||
}
|
||||
|
||||
public static function setFilename(string $url)
|
||||
{
|
||||
$file = explode("/", urldecode($url));
|
||||
return end($file);
|
||||
}
|
||||
|
||||
public static function setSize(string $title): string
|
||||
{
|
||||
$sizeMatch = [];
|
||||
|
||||
@@ -7,6 +7,7 @@ class TorrentioResult
|
||||
public function __construct(
|
||||
public ?string $title = "-",
|
||||
public ?string $url = "-",
|
||||
public ?string $filename = "-",
|
||||
public ?string $size = "-",
|
||||
public ?string $seeders = "-",
|
||||
public ?string $provider = "-",
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
{{ include('search/partial/filter.html.twig') }}
|
||||
|
||||
{% if "movies" == results.media.mediaType %}
|
||||
<div class="results" {{ stimulus_controller('movie_results', {imdbId: results.media.imdbId}) }}>
|
||||
<div class="results" {{ stimulus_controller('movie_results', {tmdbId: results.media.tmdbId, imdbId: results.media.imdbId}) }}>
|
||||
</div>
|
||||
{% elseif "tvshows" == results.media.mediaType %}
|
||||
{% for season, episodes in results.media.episodes %}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 hidden"
|
||||
<table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 {{ results.media.mediaType == "tvshows" ? "hidden" }}"
|
||||
{{ stimulus_target(controller, "list") }}
|
||||
>
|
||||
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||
@@ -34,7 +34,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for result in results.results %}
|
||||
<tr class="bg-white border-b dark:bg-slate-700 dark:border-gray-600 border-gray-200" data-languages="{{ result.languages|json_encode }}" data-season="{{ results.season }}">
|
||||
<tr class="bg-white border-b dark:bg-slate-700 dark:border-gray-600 border-gray-200" data-languages="{{ result.languages|json_encode }}" {% if "tvshows" == results.media.mediaType %} data-season="{{ results.season }} {% endif %}">
|
||||
<td id="size" class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||
{{ result.size }}
|
||||
</td>
|
||||
@@ -54,7 +54,16 @@
|
||||
{{ result.languageFlags|raw }}
|
||||
</td>
|
||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-end text-gray-800 dark:text-gray-50 flex flex-row gap-2 items-center justify-end">
|
||||
<button class="p-1.5 bg-green-600 rounded-md text-gray-50">
|
||||
<button class="p-1.5 bg-green-600 rounded-md text-gray-50"
|
||||
{{ stimulus_controller('download_button', {
|
||||
url: result.url,
|
||||
title: result.title,
|
||||
filename: result.filename,
|
||||
mediaType: results.media.mediaType,
|
||||
imdbId: results.media.imdbId
|
||||
}) }}
|
||||
{{ stimulus_action('download_button', 'download', 'click') }}
|
||||
>
|
||||
Download
|
||||
</button>
|
||||
<label for="select">
|
||||
|
||||
Reference in New Issue
Block a user