feat: torrentio api for movie results
This commit is contained in:
@@ -32,12 +32,10 @@ final class SearchController extends AbstractController
|
|||||||
public function result(
|
public function result(
|
||||||
GetMediaInfoInput $getDownloadOptionsInput,
|
GetMediaInfoInput $getDownloadOptionsInput,
|
||||||
): Response {
|
): Response {
|
||||||
$result = $this->getMediaInfoHandler->handle(
|
$result = $this->getMediaInfoHandler->handle($getDownloadOptionsInput->toCommand());
|
||||||
$getDownloadOptionsInput->toCommand()
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->render('search/result.html.twig', [
|
return $this->render('search/result.html.twig', [
|
||||||
'result' => $result,
|
'results' => $result,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/Controller/TorrentioController.php
Normal file
26
src/Controller/TorrentioController.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Torrentio\Action\Handler\GetMovieOptionsHandler;
|
||||||
|
use App\Torrentio\Action\Input\GetMovieOptionsInput;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
|
final class TorrentioController extends AbstractController
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly GetMovieOptionsHandler $getMovieOptionsHandler,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[Route('/torrentio/movies/{imdbId}', name: 'app_torrentio')]
|
||||||
|
public function index(GetMovieOptionsInput $input): Response
|
||||||
|
{
|
||||||
|
$results = $this->getMovieOptionsHandler->handle($input->toCommand());
|
||||||
|
|
||||||
|
return $this->render('torrentio/movies.html.twig', [
|
||||||
|
'results' => $results,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Download\Action\Handler;
|
namespace App\Download\Action\Handler;
|
||||||
|
|
||||||
use App\Tmdb\Tmdb;
|
use App\Tmdb\Tmdb;
|
||||||
use App\Torrentio\Torrentio;
|
use App\Torrentio\Client\Torrentio;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|||||||
12
src/Torrentio/Action/Command/GetMovieOptionsCommand.php
Normal file
12
src/Torrentio/Action/Command/GetMovieOptionsCommand.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Command;
|
||||||
|
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
|
||||||
|
class GetMovieOptionsCommand implements CommandInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $imdbId,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
23
src/Torrentio/Action/Handler/GetMovieOptionsHandler.php
Normal file
23
src/Torrentio/Action/Handler/GetMovieOptionsHandler.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Handler;
|
||||||
|
|
||||||
|
use App\Torrentio\Action\Result\GetMovieOptionsResult;
|
||||||
|
use App\Torrentio\Client\Torrentio;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
|
class GetMovieOptionsHandler implements HandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Torrentio $torrentio,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
|
{
|
||||||
|
return new GetMovieOptionsResult(
|
||||||
|
results: $this->torrentio->search($command->imdbId, 'movies')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/Torrentio/Action/Input/GetMovieOptionsInput.php
Normal file
21
src/Torrentio/Action/Input/GetMovieOptionsInput.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Input;
|
||||||
|
|
||||||
|
use App\Torrentio\Action\Command\GetMovieOptionsCommand;
|
||||||
|
use OneToMany\RichBundle\Attribute\SourceRoute;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\InputInterface;
|
||||||
|
|
||||||
|
class GetMovieOptionsInput implements InputInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[SourceRoute('imdbId')]
|
||||||
|
public string $imdbId,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function toCommand(): CommandInterface
|
||||||
|
{
|
||||||
|
return new GetMovieOptionsCommand($this->imdbId);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Torrentio/Action/Result/GetMovieOptionsResult.php
Normal file
12
src/Torrentio/Action/Result/GetMovieOptionsResult.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Action\Result;
|
||||||
|
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
|
class GetMovieOptionsResult implements ResultInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public array $results
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Torrentio\Rule\DownloadOptionFilter;
|
namespace App\Torrentio\Client\Rule\DownloadOptionFilter;
|
||||||
|
|
||||||
use App\Torrentio\Result\ResultFactory;
|
use App\Torrentio\Result\ResultFactory;
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Torrentio\Rule;
|
namespace App\Torrentio\Client\Rule;
|
||||||
|
|
||||||
class RuleEngine
|
class RuleEngine
|
||||||
{
|
{
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Torrentio;
|
namespace App\Torrentio\Client;
|
||||||
|
|
||||||
use App\Torrentio\Rule\DownloadOptionFilter\Resolution;
|
use App\Torrentio\Client\Rule\DownloadOptionFilter\Resolution;
|
||||||
use App\Torrentio\Rule\RuleEngine;
|
use App\Torrentio\Client\Rule\RuleEngine;
|
||||||
|
use App\Torrentio\MediaResult;
|
||||||
use App\Torrentio\Result\ResultFactory;
|
use App\Torrentio\Result\ResultFactory;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
use Symfony\Contracts\Cache\CacheInterface;
|
use Symfony\Contracts\Cache\CacheInterface;
|
||||||
@@ -1,12 +1,26 @@
|
|||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block title %}Search Results &mdash - Torsearch{% endblock %}
|
{% block title %}{{ results.media.title }} — Download Options — Torsearch{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="p-4 flex flex-col grow gap-4">
|
<div class="p-4 flex flex-col grow gap-4">
|
||||||
<h2 class="mb-2 text-3xl font-bold text-gray-50">Search Results</h2>
|
<h2 class="mb-2 text-3xl font-bold text-gray-50">Media Results</h2>
|
||||||
<div class="flex flex-row w-full gap-2">
|
<div class="flex flex-row w-full gap-2">
|
||||||
<twig:Card title="{{ result.media.title }}" contentClass="flex flex-col gap-4 justify-between w-full">
|
<twig:Card title="" contentClass="flex flex-col gap-4 justify-between w-full text-gray-50">
|
||||||
|
<div class="p-4 flex flex-row gap-6">
|
||||||
|
<img class="w-24" src="{{ results.media.poster }}" />
|
||||||
|
<div class="w-full flex flex-col">
|
||||||
|
<h3 class="mb-4 text-xl font-medium leading-tight font-bold text-gray-50">
|
||||||
|
{{ results.media.title }} - {{ results.media.year }}
|
||||||
|
</h3>
|
||||||
|
<p class="text-gray-50">
|
||||||
|
{{ results.media.description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="results">
|
||||||
|
</div>
|
||||||
|
|
||||||
</twig:Card>
|
</twig:Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
20
templates/torrentio/index.html.twig
Normal file
20
templates/torrentio/index.html.twig
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Hello TorrentioController!{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<style>
|
||||||
|
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||||
|
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="example-wrapper">
|
||||||
|
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||||
|
|
||||||
|
This friendly message is coming from:
|
||||||
|
<ul>
|
||||||
|
<li>Your controller at <code>/var/www/src/Controller/TorrentioController.php</code></li>
|
||||||
|
<li>Your template at <code>/var/www/templates/torrentio/index.html.twig</code></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
67
templates/torrentio/movies.html.twig
Normal file
67
templates/torrentio/movies.html.twig
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<div class="p-2 flex flex-col gap-6 bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-md bg-opacity-60 rounded-md">
|
||||||
|
<table class="divide-y divide-gray-200 dark:divide-gray-50 dark:bg-transparent rounded-lg">
|
||||||
|
<thead>
|
||||||
|
<tr class="dark:bg-stone-600 overflow-hidden rounded-md">
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-stone-500 uppercase dark:text-gray-50">
|
||||||
|
Size
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
Resolution
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
Codec
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
Seeders
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
Provider
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
Language
|
||||||
|
</th>
|
||||||
|
<th scope="col"
|
||||||
|
class="px-6 py-3 text-start text-xs font-medium text-gray-500 uppercase dark:text-gray-50">
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-50">
|
||||||
|
{% for result in results.results %}
|
||||||
|
<tr>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.size }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.resolution }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.codec }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.seeders }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.provider }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-800 dark:text-gray-50">
|
||||||
|
{{ result.languageFlags }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-end text-gray-800 dark:text-gray-50">
|
||||||
|
<span class="p-1.5 bg-green-600 rounded-md">
|
||||||
|
<span class="text-gray-50">Download</span>
|
||||||
|
</span>
|
||||||
|
<input class="ml-1" type="checkbox" name="select" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
3
templates/torrentio/tvshows.html.twig
Normal file
3
templates/torrentio/tvshows.html.twig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="p-2 flex flex-row gap-6 bg-orange-500 bg-clip-padding backdrop-filter backdrop-blur-md bg-opacity-60 rounded-md">
|
||||||
|
<h3 class="text-md">Episodes</h3>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user