225
app/Services/Data/Tmdb/TmdbApi.php
Executable file
225
app/Services/Data/Tmdb/TmdbApi.php
Executable file
@@ -0,0 +1,225 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Data\Tmdb;
|
||||
|
||||
use App\Actions\People\DeletePeople;
|
||||
use App\Actions\Titles\DeleteSeasons;
|
||||
use App\Actions\Titles\DeleteTitles;
|
||||
use App\Models\Person;
|
||||
use App\Models\Title;
|
||||
use Common\Core\HttpClient;
|
||||
use Common\Settings\Settings;
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TmdbApi
|
||||
{
|
||||
public const TMDB_BASE = 'https://api.themoviedb.org/3/';
|
||||
public const DEFAULT_TMDB_LANGUAGE = 'en-US';
|
||||
|
||||
protected bool $includeAdult = false;
|
||||
protected string $language = self::DEFAULT_TMDB_LANGUAGE;
|
||||
protected HttpClient $http;
|
||||
|
||||
public function __construct(private Settings $settings)
|
||||
{
|
||||
$this->http = new HttpClient(['exceptions' => true]);
|
||||
|
||||
$this->language = $this->settings->get(
|
||||
'tmdb.language',
|
||||
self::DEFAULT_TMDB_LANGUAGE,
|
||||
);
|
||||
$this->includeAdult = $this->settings->get('tmdb.includeAdult', false);
|
||||
}
|
||||
|
||||
public function getPerson(Person $person): array|null
|
||||
{
|
||||
$appends = [];
|
||||
|
||||
// only import filmography if it's set by user
|
||||
if ($this->settings->get('content.automate_filmography')) {
|
||||
$appends[] = 'combined_credits';
|
||||
}
|
||||
|
||||
$response = $this->call("person/{$person->tmdb_id}", [
|
||||
'append_to_response' => implode(',', $appends),
|
||||
]);
|
||||
|
||||
// person does not exist anymore on themoviedb
|
||||
if (
|
||||
Arr::get($response, 'success') === false &&
|
||||
Arr::get($response, 'status_code') === 34
|
||||
) {
|
||||
if (config('common.site.tmdb_delete_when_sync')) {
|
||||
app(DeletePeople::class)->execute([$person->id]);
|
||||
return null;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$response['fully_synced'] = true;
|
||||
|
||||
return app(TransformData::class)
|
||||
->execute([$response])
|
||||
->first();
|
||||
}
|
||||
|
||||
public function getSeason(Title $title, $seasonNumber)
|
||||
{
|
||||
if (!$title->tmdb_id) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$response = $this->call("tv/{$title->tmdb_id}/season/{$seasonNumber}", [
|
||||
'append_to_response' => 'credits',
|
||||
]);
|
||||
|
||||
// season does not exist anymore on themoviedb
|
||||
if (
|
||||
Arr::get($response, 'success') === false &&
|
||||
Arr::get($response, 'status_code') === 34
|
||||
) {
|
||||
if (config('common.site.tmdb_delete_when_sync')) {
|
||||
$seasonId = $title
|
||||
->seasons()
|
||||
->where('number', $seasonNumber)
|
||||
->value('id');
|
||||
app(DeleteSeasons::class)->execute([$seasonId]);
|
||||
return null;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$data = app(TransformData::class)
|
||||
->execute([$response])
|
||||
->first();
|
||||
$data['fully_synced'] = true;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getTitle(Title $title): array|null
|
||||
{
|
||||
$appends = [
|
||||
'credits',
|
||||
'external_ids',
|
||||
'images',
|
||||
'content_ratings',
|
||||
'keywords',
|
||||
'release_dates',
|
||||
'videos',
|
||||
'seasons',
|
||||
];
|
||||
|
||||
$uri = $title->is_series ? 'tv' : 'movie';
|
||||
|
||||
$response = $this->call("$uri/{$title->tmdb_id}", [
|
||||
'append_to_response' => implode(',', $appends),
|
||||
]);
|
||||
|
||||
// title does not exist anymore on themoviedb
|
||||
if (
|
||||
Arr::get($response, 'success') === false &&
|
||||
Arr::get($response, 'status_code') === 34
|
||||
) {
|
||||
if (config('common.site.tmdb_delete_when_sync')) {
|
||||
app(DeleteTitles::class)->execute([$title->id]);
|
||||
return null;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$data = app(TransformData::class)
|
||||
->execute([$response])
|
||||
->first();
|
||||
|
||||
// fall back to english videos if there are no videos in the current language
|
||||
if (!Str::startsWith($this->language, 'en') && empty($data['videos'])) {
|
||||
$videos = $this->call("$uri/{$title->tmdb_id}/videos", [
|
||||
'language' => 'en-US',
|
||||
]);
|
||||
$videos = app(TransformData::class)->formatVideos(
|
||||
$videos['results'],
|
||||
);
|
||||
$data['videos'] = $videos;
|
||||
}
|
||||
|
||||
$data['fully_synced'] = true;
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function search(string $query, array $params = []): Collection
|
||||
{
|
||||
$response = $this->call('search/multi', ['query' => $query]);
|
||||
$results = app(TransformData::class)->execute($response['results']);
|
||||
|
||||
$type = Arr::get($params, 'type');
|
||||
$limit = Arr::get($params, 'limit', 8);
|
||||
|
||||
if ($type) {
|
||||
$results = $results->filter(
|
||||
fn($result) => $result['type'] === $type,
|
||||
);
|
||||
}
|
||||
|
||||
return $results
|
||||
->sortByDesc('popularity')
|
||||
->slice(0, $limit)
|
||||
->values();
|
||||
}
|
||||
|
||||
public function browse($page = 1, $type = 'movie', $queryParams = []): array
|
||||
{
|
||||
if ($page > 500) {
|
||||
throw new Exception('Maximum page is 500');
|
||||
}
|
||||
|
||||
if ($type === 'series') {
|
||||
$type = 'tv';
|
||||
}
|
||||
|
||||
$apiParams = array_merge(
|
||||
['sort_by' => 'popularity.desc', 'page' => $page],
|
||||
$queryParams,
|
||||
);
|
||||
|
||||
$response = $this->call("discover/$type", $apiParams);
|
||||
$response['results'] = app(TransformData::class)->execute(
|
||||
$response['results'],
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function trendingPeople(): Collection
|
||||
{
|
||||
$response = $this->call('person/popular');
|
||||
return app(TransformData::class)->execute($response['results']);
|
||||
}
|
||||
|
||||
protected function call(string $uri, array $queryParams = []): array
|
||||
{
|
||||
$key = config('services.tmdb.key');
|
||||
$url = self::TMDB_BASE . "$uri?api_key=$key";
|
||||
|
||||
$queryParams = array_merge(
|
||||
[
|
||||
// need to send "true" and not "1" otherwise tmdb will not work
|
||||
'include_adult' => $this->includeAdult ? 'true' : 'false',
|
||||
'language' => $this->language,
|
||||
'region' => 'US',
|
||||
'include_image_language' => 'en,null',
|
||||
],
|
||||
$queryParams,
|
||||
);
|
||||
$url .= '&' . urldecode(http_build_query($queryParams));
|
||||
return $this->http->get($url, [
|
||||
'verify' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user