Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 662e2600f6 | |||
| aa042e8275 | |||
| 57498b1abf | |||
| fed1e1e122 |
47
migrations/Version20250831013403.php
Normal file
47
migrations/Version20250831013403.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250831013403 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP TABLE sessions
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE download CHANGE created_at created_at DATETIME NOT NULL, CHANGE updated_at updated_at DATETIME NOT NULL
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(1024) DEFAULT NULL
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
CREATE TABLE sessions (sess_id VARBINARY(128) NOT NULL, sess_data LONGBLOB NOT NULL, sess_lifetime INT UNSIGNED NOT NULL, sess_time INT UNSIGNED NOT NULL, INDEX sess_lifetime_idx (sess_lifetime), PRIMARY KEY(sess_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_bin` ENGINE = InnoDB COMMENT = ''
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE download CHANGE created_at created_at DATETIME DEFAULT NULL, CHANGE updated_at updated_at DATETIME DEFAULT NULL
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(255) DEFAULT NULL
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
55
src/Torrentio/Client/HttpClient.php
Normal file
55
src/Torrentio/Client/HttpClient.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Torrentio\Client;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use GuzzleHttp\Client as GuzzleClient;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
use Symfony\Contracts\Cache\ItemInterface;
|
||||||
|
use Symfony\Contracts\Cache\TagAwareCacheInterface;
|
||||||
|
|
||||||
|
class HttpClient
|
||||||
|
{
|
||||||
|
private GuzzleClient $client;
|
||||||
|
|
||||||
|
private string $baseUrl = 'https://torrentio.strem.fun/realdebrid=%s/';
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(env: 'REAL_DEBRID_KEY')] private string $realDebridKey,
|
||||||
|
private TagAwareCacheInterface $cache,
|
||||||
|
private LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
$this->client = new GuzzleClient([
|
||||||
|
'base_uri' => sprintf($this->baseUrl, $this->realDebridKey),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $imdbId, array $cacheTags = []): array
|
||||||
|
{
|
||||||
|
$cacheKey = str_replace(":", ".", "torrentio.{$imdbId}");
|
||||||
|
|
||||||
|
return $this->cache->get($cacheKey, function (ItemInterface $item) use ($imdbId, $cacheTags) {
|
||||||
|
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
|
||||||
|
if (count($cacheTags) > 0) {
|
||||||
|
$item->tag($cacheTags);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$response = $this->client->get("stream/movie/$imdbId.json");
|
||||||
|
return json_decode(
|
||||||
|
$response->getBody()->getContents(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
dd($exception);
|
||||||
|
if ($exception->getCode() === 429) {
|
||||||
|
$this->logger->warning("> [TorrentioClient] Rate limit exceeded");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->error("> [TorrentioClient] Request error: " . $response->getStatusCode() . " - " . $response->getBody()->getContents());
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,59 +2,19 @@
|
|||||||
|
|
||||||
namespace App\Torrentio\Client;
|
namespace App\Torrentio\Client;
|
||||||
|
|
||||||
use App\Torrentio\Client\Rule\DownloadOptionFilter\Resolution;
|
|
||||||
use App\Torrentio\Client\Rule\RuleEngine;
|
|
||||||
use App\Torrentio\Result\ResultFactory;
|
use App\Torrentio\Result\ResultFactory;
|
||||||
use Carbon\Carbon;
|
|
||||||
use App\Torrentio\Exception\TorrentioRateLimitException;
|
use App\Torrentio\Exception\TorrentioRateLimitException;
|
||||||
use GuzzleHttp\Client;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
|
||||||
use Symfony\Contracts\Cache\ItemInterface;
|
|
||||||
use Symfony\Contracts\Cache\TagAwareCacheInterface;
|
|
||||||
|
|
||||||
class Torrentio
|
class Torrentio
|
||||||
{
|
{
|
||||||
private string $baseUrl = 'https://torrentio.strem.fun/providers%253Dyts%252Ceztv%252Crarbg%252C1337x%252Cthepiratebay%252Ckickasstorrents%252Ctorrentgalaxy%252Cmagnetdl%252Chorriblesubs%252Cnyaasi%7Csort%253Dqualitysize%7Cqualityfilter%253D480p%252Cscr%252Ccam%7Crealdebrid={realDebridKey}/stream/movie';
|
|
||||||
|
|
||||||
private string $searchUrl;
|
|
||||||
|
|
||||||
private Client $client;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[Autowire(env: 'REAL_DEBRID_KEY')] private string $realDebridKey,
|
private readonly HttpClient $client,
|
||||||
private TagAwareCacheInterface $cache,
|
) {}
|
||||||
private LoggerInterface $logger,
|
|
||||||
) {
|
|
||||||
$this->searchUrl = str_replace('{realDebridKey}', $this->realDebridKey, $this->baseUrl);
|
|
||||||
$this->client = new Client([
|
|
||||||
'base_uri' => $this->searchUrl,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function search(string $imdbCode, string $type, bool $parseResults = true): array
|
public function search(string $imdbCode, string $type, bool $parseResults = true): array
|
||||||
{
|
{
|
||||||
$cacheKey = "torrentio.{$imdbCode}";
|
$cacheTags = ['torrentio', $type, $imdbCode];
|
||||||
|
$results = $this->client->get($imdbCode, $cacheTags);
|
||||||
$results = $this->cache->get($cacheKey, function (ItemInterface $item) use ($imdbCode, $type) {
|
|
||||||
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
|
|
||||||
$item->tag(['torrentio', $type, $imdbCode]);
|
|
||||||
try {
|
|
||||||
$response = $this->client->get("$this->searchUrl/$imdbCode.json");
|
|
||||||
return json_decode(
|
|
||||||
$response->getBody()->getContents(),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
} catch (\Throwable $exception) {
|
|
||||||
if ($exception->getCode() === 429) {
|
|
||||||
$this->logger->warning("> [TorrentioClient] Rate limit exceeded");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->logger->error("> [TorrentioClient] Request error: " . $response->getStatusCode() . " - " . $response->getBody()->getContents());
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (true === $parseResults) {
|
if (true === $parseResults) {
|
||||||
return $this->parse($results);
|
return $this->parse($results);
|
||||||
@@ -65,26 +25,8 @@ class Torrentio
|
|||||||
|
|
||||||
public function fetchEpisodeResults(string $imdbId, int $season, int $episode, bool $parseResults = true): array
|
public function fetchEpisodeResults(string $imdbId, int $season, int $episode, bool $parseResults = true): array
|
||||||
{
|
{
|
||||||
$cacheKey = "torrentio.$imdbId.$season.$episode";
|
$cacheTags = ['torrentio', 'tvshows', 'torrentio.tvshows', $imdbId, "torrentio.$imdbId", "$imdbId.$season", "torrentio.$imdbId.$season", "$imdbId.$season.$episode", "torrentio.$imdbId.$season.$episode"];
|
||||||
$results = $this->cache->get($cacheKey, function (ItemInterface $item) use ($imdbId, $season, $episode) {
|
$results = $this->client->get("$imdbId:$season:$episode", $cacheTags);
|
||||||
$item->expiresAt(Carbon::now()->addHour()->setMinute(0)->setSecond(0));
|
|
||||||
$item->tag(['torrentio', 'tvshows', 'torrentio.tvshows', $imdbId, "torrentio.$imdbId", "$imdbId.$season", "torrentio.$imdbId.$season", "$imdbId.$season.$episode", "torrentio.$imdbId.$season.$episode"]);
|
|
||||||
try {
|
|
||||||
$response = $this->client->get("$this->searchUrl/$imdbId:$season:$episode.json");
|
|
||||||
return json_decode(
|
|
||||||
$response->getBody()->getContents(),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
} catch (\Throwable $exception) {
|
|
||||||
if ($exception->getCode() === 429) {
|
|
||||||
$this->logger->warning("> [TorrentioClient] Rate limit exceeded");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->logger->error("> [TorrentioClient] Request error: " . $response->getStatusCode() . " - " . $response->getBody()->getContents());
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (null === $results) {
|
if (null === $results) {
|
||||||
throw new TorrentioRateLimitException();
|
throw new TorrentioRateLimitException();
|
||||||
|
|||||||
Reference in New Issue
Block a user