[#2] work on tv series processing

This commit is contained in:
2025-01-07 23:39:22 +02:00
parent 8f2c48d847
commit da6d92ec65
9 changed files with 210 additions and 3 deletions
+5
View File
@@ -27,4 +27,9 @@ class Episode extends Model
'show_id',
'season_id',
];
protected $casts = [
'crew' => 'array',
'guest_stars' => 'array',
];
}
+3
View File
@@ -18,5 +18,8 @@ class ExternalId extends Model
'facebook_id',
'instagram_id',
'twitter_id',
'tvdb_id',
'freebase_id',
'tvrage_id',
];
}
+10
View File
@@ -45,4 +45,14 @@ class Show extends Model
{
return $this->belongsToMany(Person::class, 'show_crew', 'show_id', 'person_id');
}
public function images()
{
return $this->belongsToMany(Image::class, 'show_images', 'show_id', 'image_id');
}
public function videos()
{
return $this->belongsToMany(Video::class, 'show_videos', 'show_id', 'video_id');
}
}
@@ -3,11 +3,14 @@
namespace App\Service\MediaProcessing;
use App\Models\Episode;
use App\Models\ExternalId;
use App\Models\Image;
use App\Models\ItemToFetchJobs;
use App\Models\Person;
use App\Models\Season;
use App\Models\Show;
use App\Models\ShowAlternativeTitle;
use App\Models\Video;
use App\Service\TMDBApi\PersonApi;
use App\Service\TMDBApi\ShowsApi;
use Illuminate\Support\Str;
@@ -48,10 +51,13 @@ 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['languages'] = json_encode($tmdbShow['languages']);
$tmdbShow['origin_country'] = reset($tmdbShow['origin_country']);
$show = Show::create($tmdbShow);
@@ -59,6 +65,11 @@ class ShowProcessingService implements ProcessingInterface
$this->processSeasons($show, $tmdbShow['seasons']);
}
// @todo process genres
// @todo process networks
// @todo process production countries
// @todo process production companies
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_DETAILS);
}
@@ -106,6 +117,117 @@ class ShowProcessingService implements ProcessingInterface
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_CREDITS);
}
private function getExternalIds($item)
{
$tmdbExternalIds = $this->showsApi->getExternalIds($item->tmdb_id);
if (empty($tmdbExternalIds)) {
return;
}
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
if (!$show) {
return;
}
$externalId = ExternalId::where('entity_id', $show->id)
->where('entity_type', ExternalId::TYPE_SHOW)
->first();
if (!$externalId) {
$externalIds['tmdb_id'] = $tmdbExternalIds['id'];
//$externalIds['show_id'] = $show->id;
unset($externalIds['id']);
$externalIds['entity_id'] = $show->id;
$externalIds['entity_type'] = ExternalId::TYPE_SHOW;
ExternalId::create($externalIds);
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_EXTERNAL_IDS);
}
private function getImages($item)
{
$tmdbImages = $this->showsApi->getImages($item->tmdb_id);
if (empty($tmdbImages)) {
return;
}
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
foreach ($tmdbImages as $type => $images) {
if (!is_array($images)) {
continue;
}
foreach ($images as $image) {
$imageExists = Image::where('type', $type)
->where('file_path', $image['file_path'])
->first();
if (!$imageExists) {
$image['iso'] = $image['iso_639_1'];
$image['type'] = $type;
$imageExists = Image::create($image);
}
if ($show->whereHas('images', function ($query) use ($imageExists) {
$query->where('type', $imageExists->type)
->where('file_path', $imageExists->file_path);
})->exists()) {
return;
} else {
$show->images()->attach($imageExists);
}
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_IMAGES);
}
private function getVideos($item)
{
$show = Show::where('tmdb_id', $item->tmdb_id)->first();
$tmdbVideos = $this->showsApi->getVideos($item->tmdb_id);
if (empty($tmdbVideos) || empty($tmdbVideos['results'])) {
return;
}
foreach ($tmdbVideos['results'] as $tmdbVideo) {
$videoExists = Video::where('tmdb_id', $tmdbVideo['id'])->first();
if (!$videoExists) {
$videoExists = Video::create([
'iso_639' => $tmdbVideo['iso_639_1'],
'iso_3166' => $tmdbVideo['iso_3166_1'],
'name' => $tmdbVideo['name'],
'key' => $tmdbVideo['key'],
'site' => $tmdbVideo['site'],
'size' => $tmdbVideo['size'],
'type' => $tmdbVideo['type'],
'official' => $tmdbVideo['official'],
'published_at' => $tmdbVideo['published_at'] ? new \DateTime($tmdbVideo['published_at']) : null,
'tmdb_id' => $tmdbVideo['id'],
]);
}
if ($show->whereHas('videos', function ($query) use ($show) {
$query->where('show_id', $show->id);
})->exists()) {
return;
} else {
$show->videos()->attach($videoExists);
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_VIDEOS);
}
private function processSeasons(Show $show, array $seasons)
{
foreach ($seasons as $season) {
@@ -114,6 +236,7 @@ class ShowProcessingService implements ProcessingInterface
->first();
if (!$showSeason) {
$season['show_id'] = $show->id;
$showSeason = Season::create($season);
$tmdbSeasonDetails = $this->showsApi->getSeasonDetails($show->tmdb_id, $season['season_number']);
@@ -139,6 +262,11 @@ class ShowProcessingService implements ProcessingInterface
$tmdbEpisode['tmdb_id'] = $tmdbEpisode['id'];
$tmdbEpisode['slug'] = Str::slug($tmdbEpisode['name']);
$tmdbEpisode['tmdb_show_id'] = $tmdbEpisode['show_id'];
$tmdbEpisode['season_id'] = $season->id;
// $tmdbEpisode['crew'] = $tmdbEpisode['crew'];
// $tmdbEpisode['guest_stars'] = $tmdbEpisode['guest_stars'];
$tmdbEpisode['show_id'] = $show->id;
$tmdbEpisode['tmdb_id'] = $season->id;
@@ -21,6 +21,9 @@ return new class extends Migration
$table->string('facebook_id')->nullable();
$table->string('instagram_id')->nullable();
$table->string('twitter_id')->nullable();
$table->string('tvdb_id')->nullable();
$table->string('freebase_id')->nullable();
$table->string('tvrage_id')->nullable();
$table->timestamps();
});
}
@@ -15,7 +15,7 @@ return new class extends Migration
$table->id();
$table->date('air_date')->nullable();
$table->integer('episode_count')->nullable();
$table->bigInteger('tmdb_id');
$table->bigInteger('tmdb_id')->nullable();
$table->string('name')->nullable();
$table->string('slug')->nullable();
$table->text('overview')->nullable();
@@ -23,7 +23,7 @@ return new class extends Migration
$table->string('production_code')->nullable();
$table->integer('runtime')->nullable();
$table->integer('season_number')->nullable();
$table->show_id('tmdb_show_id')->nullable();
$table->bigInteger('tmdb_show_id')->nullable();
$table->string('still_path', 500)->nullable();
$table->decimal('vote_average', 10, 2)->nullable();
$table->integer('vote_count')->nullable();
@@ -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_images', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->unsignedBigInteger('image_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_images');
}
};
@@ -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_videos', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('show_id');
$table->unsignedBigInteger('video_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('show_videos');
}
};