[#2] tv series progress

This commit is contained in:
2025-01-08 01:25:21 +02:00
parent da6d92ec65
commit 929954ebd9
11 changed files with 512 additions and 2 deletions
+2
View File
@@ -21,6 +21,7 @@ class ItemToFetchJobs extends Model
public const JOB_WATCH_PROVIDERS = 'WatchProviders';
public const JOB_EXTERNAL_IDS = 'ExternalIds';
public const JOB_DETAILS = 'Details';
public const JOB_CONTENT_RATINGS = 'ContentRatings';
public const JOBS = [
self::JOB_ALTERNVATIVE_TITLES,
@@ -37,6 +38,7 @@ class ItemToFetchJobs extends Model
self::JOB_VIDEOS,
self::JOB_WATCH_PROVIDERS,
self::JOB_EXTERNAL_IDS,
self::JOB_CONTENT_RATINGS,
];
protected $fillable = [
+10
View File
@@ -55,4 +55,14 @@ class Show extends Model
{
return $this->belongsToMany(Video::class, 'show_videos', 'show_id', 'video_id');
}
public function keywords()
{
return $this->belongsToMany(Keyword::class, 'show_keywords', 'show_id', 'keyword_id');
}
public function watchProviders()
{
return $this->belongsToMany(WatchProvider::class, 'show_watch_providers', 'show_id', 'watch_provider_id');
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ShowRecommendation extends Model
{
protected $fillable = [
'show_id',
'recommended_show_id',
];
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ShowSimilar extends Model
{
protected $fillable = [
'show_id',
'similar_show_id',
];
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ShowTranslation extends Model
{
protected $fillable = [
'show_id',
'iso_3166',
'iso_639',
'name',
'english_name',
'homepage',
'overview',
'runtime',
'tagline',
'title',
];
}
@@ -2,15 +2,23 @@
namespace App\Service\MediaProcessing;
use App\Models\Comment;
use App\Models\Episode;
use App\Models\ExternalId;
use App\Models\Image;
use App\Models\ItemToFetch;
use App\Models\ItemToFetchJobs;
use App\Models\Keyword;
use App\Models\Person;
use App\Models\Season;
use App\Models\Show;
use App\Models\ShowAlternativeTitle;
use App\Models\ShowRecommendation;
use App\Models\ShowSimilar;
use App\Models\ShowTranslation;
use App\Models\Translation;
use App\Models\Video;
use App\Models\WatchProvider;
use App\Service\TMDBApi\PersonApi;
use App\Service\TMDBApi\ShowsApi;
use Illuminate\Support\Str;
@@ -51,13 +59,14 @@ class ShowProcessingService implements ProcessingInterface
if ($show) {
return;
}
//dd($tmdbShow);
$tmdbShow['slug'] = Str::slug($tmdbShow['name'].'-'.$tmdbShow['tmdb_id']);
$tmdbShow['first_air_date'] = $tmdbShow['first_air_date'] ? new \DateTime($tmdbShow['first_air_date']) : null;
$tmdbShow['last_air_date'] = $tmdbShow['last_air_date'] ? new \DateTime($tmdbShow['last_air_date']) : null;
$tmdbShow['episode_run_time'] = reset($tmdbShow['episode_run_time']);
$tmdbShow['episode_run_time'] = reset($tmdbShow['episode_run_time']);
$tmdbShow['languages'] = json_encode($tmdbShow['languages']);
$tmdbShow['origin_country'] = reset($tmdbShow['origin_country']);
$tmdbShow['number_of_episodes'] = $tmdbShow['number_of_episodes'] ?? 0;
$show = Show::create($tmdbShow);
@@ -228,6 +237,263 @@ class ShowProcessingService implements ProcessingInterface
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_VIDEOS);
}
private function getKeywords($item)
{
$tmdbKeywords = $this->showsApi->getKeywords($item->tmdb_id);
if (empty($tmdbKeywords) || !isset($tmdbKeywords['results'])) {
return;
}
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
foreach ($tmdbKeywords['results'] as $tmdbKeyword) {
$existingKeyword = Keyword::where('tmdb_id', $tmdbKeyword['id'])->first();
if (!$existingKeyword) {
$existingKeyword = Keyword::create([
'name' => $tmdbKeyword['name'],
'tmdb_id' => $tmdbKeyword['id'],
]);
}
if ($show->whereHas('keywords', function ($query) use ($existingKeyword) {
$query->where('tmdb_id', $existingKeyword->tmdb_id);
})->exists()) {
return;
} else {
$show->keywords()->attach($existingKeyword);
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_KEYWORDS);
}
private function getTranslations($item)
{
$tmdbMovieTranslations = $this->showsApi->getTranslations($item->tmdb_id);
if (!$tmdbMovieTranslations || !isset($tmdbMovieTranslations['translations'])) {
return;
}
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
foreach ($tmdbMovieTranslations['translations'] as $tmdbTranslation) {
$existingTranslation = ShowTranslation::where('show_id', $show->id)
->where('name', $tmdbTranslation['name'])
->first();
if (!$existingTranslation) {
ShowTranslation::create([
'show_id' => $show->id,
'iso_3166' => $tmdbTranslation['iso_3166_1'],
'iso_639' => $tmdbTranslation['iso_639_1'],
'name' => $tmdbTranslation['name'],
'english_name' => $tmdbTranslation['english_name'],
'homepage' => $tmdbTranslation['data']['homepage'],
'overview' => $tmdbTranslation['data']['overview'],
'runtime' => $tmdbTranslation['data']['runtime'] ?? 0,
'tagline' => $tmdbTranslation['data']['tagline'],
'title' => $tmdbTranslation['data']['title'] ?? '',
]);
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_TRANSLATIONS);
}
private function getWatchProviders($item)
{
$tmdbWatchProviders = $this->showsApi->getWatchProviders($item->tmdb_id);
if (empty($tmdbWatchProviders) || empty($tmdbWatchProviders['results'])) {
return;
}
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
if (!$show) {
$itemToFetch = $this->createJob($item->tmdb_id);
$this->getDetails($itemToFetch);
return;
}
$types = [
'flatrate',
'rent',
'buy',
];
foreach ($tmdbWatchProviders['results'] as $locale => $tmdbWatchProvider) {
foreach ($types as $type) {
if (!isset($tmdbWatchProvider[$type])) {
continue;
}
$providerInfo = $tmdbWatchProvider[$type];
$providerInfo = reset($providerInfo);
if (!isset($providerInfo['provider_id'])) {
continue;
}
$existingWatchProvider = WatchProvider::where('tmdb_provider_id', $providerInfo['provider_id'])->first();
if(!$existingWatchProvider) {
$existingWatchProvider = WatchProvider::create([
'type' => $type,
'logo_path' => $providerInfo['logo_path'],
'tmdb_provider_id' => $providerInfo['provider_id'],
'provider_name' => $providerInfo['provider_name'],
'display_priority' => $providerInfo['display_priority'],
]);
}
if (!$show->whereHas('watchProviders', function ($query) use ($show) {
$query->where('show_id', $show->id);
})->exists()) {
$show->watchProviders()->attach($existingWatchProvider, [
'locale' => $locale,
'tmdb_url' => $tmdbWatchProvider['link'],
]);
}
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_WATCH_PROVIDERS);
}
private function getRecommendations($item)
{
$tmdbRecommendations = $this->showsApi->getRecommendations($item->tmdb_id);
if (empty($tmdbRecommendations) || empty($tmdbRecommendations['results'])) {
return;
}
$initialShow = Show::where('tmdb_id', $item->tmdb_id)->first();
foreach ($tmdbRecommendations['results'] as $tmdbRecommendation) {
$itemToFetch = ItemToFetch::where('tmdb_id', $tmdbRecommendation['id'])->where('type', ItemToFetch::TYPE_TV_SERIES)->first();
if ($itemToFetch) {
$this->getDetails($itemToFetch);
continue;
}
$show = Show::where('tmdb_id', $tmdbRecommendation['id'])->first();
if ($show) {
$recommendationLink = ShowRecommendation::where('show_id', $initialShow->id)
->where('recommended_show_id', $show->id)
->first();
if (!$recommendationLink) {
ShowRecommendation::create([
'show_id' => $initialShow->id,
'recommended_show_id' => $show->id,
]);
}
continue;
} else {
$itemToFetch = ItemToFetch::create([
'tmdb_id' => $tmdbRecommendation['id'],
'type' => ItemToFetch::TYPE_TV_SERIES,
]);
$jobs = ItemToFetchJobs::JOBS;
$jobs[] = "Details";
ItemToFetchJobs::create([
'tmdb_id' => $tmdbRecommendation['id'],
'type' => ItemToFetch::TYPE_TV_SERIES,
'remaining_jobs' => json_encode($jobs),
]);
$this->getDetails($itemToFetch);
}
$recommendedShow = Show::where('tmdb_id', $tmdbRecommendation['id'])->first();
ShowRecommendation::create([
'show_id' => $initialShow->id,
'recommended_show_id' => $recommendedShow->id,
]);
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_RECOMMNDATION);
}
private function getSimilar($item)
{
$tmdbSimilarMovies = $this->showsApi->getSimilar($item->tmdb_id);
if (empty($tmdbSimilarMovies) || empty($tmdbSimilarMovies['results'])) {
return;
}
$initialShow = Show::where('tmdb_id', $item->tmdb_id)->first();
foreach ($tmdbSimilarMovies['results'] as $tmdbSimilarMovie) {
$itemToFetch = ItemToFetch::where('tmdb_id', $tmdbSimilarMovie['id'])->where('type', ItemToFetch::TYPE_TV_SERIES)->first();
if ($itemToFetch) {
$this->getDetails($itemToFetch);
continue;
}
$similarShow = Show::where('tmdb_id', $tmdbSimilarMovie['id'])->first();
if ($similarShow) {
$similarLink = ShowSimilar::where('show_id', $initialShow->id)
->where('similar_show_id', $similarShow->id)
->first();
if (!$similarLink) {
ShowSimilar::create([
'show_id' => $initialShow->id,
'similar_show_id' => $similarShow->id,
]);
}
continue;
}
$itemToFetch = ItemToFetch::create([
'tmdb_id' => $tmdbSimilarMovie['id'],
'type' => ItemToFetch::TYPE_TV_SERIES,
]);
$jobs = ItemToFetchJobs::JOBS;
$jobs[] = "Details";
ItemToFetchJobs::create([
'tmdb_id' => $tmdbSimilarMovie['id'],
'type' => ItemToFetch::TYPE_TV_SERIES,
'remaining_jobs' => json_encode($jobs),
]);
$this->getDetails($itemToFetch);
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
$similarShow = Show::where('tmdb_id', $tmdbSimilarMovie['id'])->first();
ShowSimilar::create([
'show_id' => $show->id,
'similar_show_id' => $similarShow->id,
]);
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_SIMILAR);
}
private function getContentRatings($item)
{
}
private function processSeasons(Show $show, array $seasons)
{
foreach ($seasons as $season) {
@@ -402,4 +668,34 @@ class ShowProcessingService implements ProcessingInterface
}
}
}
private function createJob($tmdbId)
{
$itemToFetch = ItemToFetch::where('tmdb_id', $tmdbId)->where('type', ItemToFetch::TYPE_TV_SERIES)->first();
if ($itemToFetch) {
return $itemToFetch;
}
$show = Show::where('tmdb_id', $tmdbId)->first();
if ($show) {
return;
}
$itemToFetch = ItemToFetch::create([
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_TV_SERIES,
]);
$jobs = ItemToFetchJobs::JOBS;
$jobs[] = "Details";
ItemToFetchJobs::create([
'tmdb_id' => $tmdbId,
'type' => ItemToFetch::TYPE_TV_SERIES,
'remaining_jobs' => json_encode($jobs),
]);
return $itemToFetch;
}
}
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('show_keywords', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->unsignedBigInteger('keyword_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_keywords');
}
};
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('show_translations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->string('iso_3166', 10);
$table->string('iso_639', 10);
$table->string('name');
$table->string('english_name');
$table->string('homepage', 500);
$table->text('overview');
$table->integer('runtime');
$table->string('tagline', 500);
$table->string('title', 500);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_translations');
}
};
@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('show_watch_providers', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->integer('watch_provider_id');
$table->string('locale');
$table->string('tmdb_url');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_watch_providers');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('show_recommendations', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->unsignedBigInteger('recommended_show_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_recommendations');
}
};
@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('show_similars', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->unsignedBigInteger('similar_show_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_similars');
}
};