This commit is contained in:
2024-12-30 22:41:34 +02:00
parent 6abcbe2a84
commit e60058c1c0
11 changed files with 264 additions and 5 deletions
@@ -7,6 +7,7 @@ use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class RegisterController extends Controller class RegisterController extends Controller
{ {
@@ -65,6 +66,7 @@ class RegisterController extends Controller
{ {
return User::create([ return User::create([
'name' => $data['name'], 'name' => $data['name'],
'slug' => Str::slug($data['name']),
'email' => $data['email'], 'email' => $data['email'],
'password' => Hash::make($data['password']), 'password' => Hash::make($data['password']),
]); ]);
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MediaList extends Model
{
protected $fillable = [
'description',
'favorites_count',
'tmdb_id',
'item_count',
'iso_639_1',
'iso_3166_1',
'list_type',
'name',
'poster_path',
];
}
+15
View File
@@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MediaListItem extends Model
{
protected $fillable = [
'media_list_id',
'item_id',
'item_type',
'tmdb_id',
];
}
+7
View File
@@ -19,8 +19,10 @@ class User extends Authenticatable
*/ */
protected $fillable = [ protected $fillable = [
'name', 'name',
'slug',
'email', 'email',
'password', 'password',
'is_dummy_account',
]; ];
/** /**
@@ -45,4 +47,9 @@ class User extends Authenticatable
'password' => 'hashed', 'password' => 'hashed',
]; ];
} }
public function mediaLists()
{
return $this->belongsToMany(MediaList::class, 'user_media_lists', 'user_id', 'media_list_id');
}
} }
@@ -6,16 +6,21 @@ use App\Models\Comment;
use App\Models\ExternalId; use App\Models\ExternalId;
use App\Models\Genre; use App\Models\Genre;
use App\Models\Image; use App\Models\Image;
use App\Models\ItemToFetch;
use App\Models\ItemToFetchJobs; use App\Models\ItemToFetchJobs;
use App\Models\Keyword; use App\Models\Keyword;
use App\Models\MediaList;
use App\Models\MediaListItem;
use App\Models\Movie; use App\Models\Movie;
use App\Models\MovieAlternativeTitle; use App\Models\MovieAlternativeTitle;
use App\Models\MovieCollection; use App\Models\MovieCollection;
use App\Models\Person; use App\Models\Person;
use App\Models\ReleaseDate; use App\Models\ReleaseDate;
use App\Models\Translation; use App\Models\Translation;
use App\Models\User;
use App\Models\Video; use App\Models\Video;
use App\Models\WatchProvider; use App\Models\WatchProvider;
use App\Service\TMDBApi\ListApi;
use App\Service\TMDBApi\MoviesApi; use App\Service\TMDBApi\MoviesApi;
use App\Service\TMDBApi\PersonApi; use App\Service\TMDBApi\PersonApi;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@@ -24,13 +29,16 @@ class MovieProcessingService implements ProcessingInterface
{ {
private MoviesApi $moviesApi; private MoviesApi $moviesApi;
private PersonApi $personApi; private PersonApi $personApi;
private ListApi $listApi;
public function __construct( public function __construct(
MoviesApi $moviesApi, MoviesApi $moviesApi,
PersonApi $personApi PersonApi $personApi,
ListApi $listApi
) { ) {
$this->moviesApi = $moviesApi; $this->moviesApi = $moviesApi;
$this->personApi = $personApi; $this->personApi = $personApi;
$this->listApi = $listApi;
} }
public function process($item, $job) public function process($item, $job)
@@ -409,6 +417,87 @@ class MovieProcessingService implements ProcessingInterface
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_VIDEOS); $this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_VIDEOS);
} }
public function getLists($item)
{
$tmdbLists = $this->moviesApi->getLists($item->tmdb_id);
if (empty($tmdbLists) || empty($tmdbLists['results'])) {
return;
}
foreach ($tmdbLists['results'] as $tmdbList) {
$list = MediaList::where('tmdb_id', $tmdbList['id'])->first();
$tmdbList['tmdb_id'] = $tmdbList['id'];
unset($tmdbList['id']);
if (!$list) {
$list = MediaList::create($tmdbList);
}
$listDetails = $this->listApi->details($tmdbList['tmdb_id']);
if (empty($listDetails)) {
continue;
}
$user = User::where('name', $listDetails['created_by'])->first();
if (!$user) {
$user = User::create([
'name' => $listDetails['created_by'],
'slug' => Str::slug($listDetails['created_by']),
'email' => $listDetails['created_by'].'@nowhere.wtf',
'password' => 'no_password_neeeded_here',
'is_dummy_account' => true,
]);
}
if (!$user->whereHas('mediaLists', function ($query) use ($list) {
$query->where('media_list_id', $list->id);
})->exists()) {
$user->mediaLists()->attach($list);
}
foreach ($tmdbList['items'] as $tmdbListItem) {
$mediaListItem = MediaListItem::where('media_list_id', $list->id)
->where('tmdb_id', $tmdbListItem['id'])
->first();
if (!$mediaListItem) {
$movie = Movie::where('tmdb_id', $item->tmdb_id)->first();
if (!$movie) {
$itemToFetch = ItemToFetch::where('tmdb_id', $item->tmdb_id)->first();
if (!$itemToFetch) {
$itemToFetch = ItemToFetch::create([
'tmdb_id' => $item->tmdb_id,
'type' => ItemToFetch::TYPE_MOVIE,
]);
$jobs = ItemToFetchJobs::JOBS;
$jobs[] = "Details";
ItemToFetchJobs::create([
'tmdb_id' => $item->tmdb_id,
'type' => ItemToFetch::TYPE_MOVIE,
'remaining_jobs' => json_encode($jobs),
]);
}
MediaListItem::create([
'media_list_id' => $list->id,
'item_type' => ItemToFetch::TYPE_MOVIE,
'tmdb_id' => $item->tmdb_id,
]);
}
}
}
}
$this->removeElementFromRemainingJobs($item->tmdb_id, ItemToFetchJobs::JOB_LISTS);
}
private function processMovieCollection(int $movieId, $belongsToCollection) private function processMovieCollection(int $movieId, $belongsToCollection)
{ {
$movieCollection = MovieCollection::where('tmdb_id', $belongsToCollection['id'])->first(); $movieCollection = MovieCollection::where('tmdb_id', $belongsToCollection['id'])->first();
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Service\TMDBApi;
class ListApi extends AbstractApiService
{
public function details($listId)
{
sleep(1);
return $this->get("list/" . $listId);
}
}
@@ -14,9 +14,11 @@ return new class extends Migration
Schema::create('users', function (Blueprint $table) { Schema::create('users', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name'); $table->string('name');
$table->string('slug');
$table->string('email')->unique(); $table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable(); $table->timestamp('email_verified_at')->nullable();
$table->string('password'); $table->string('password');
$table->boolean('is_dummy_account')->default(0);
$table->rememberToken(); $table->rememberToken();
$table->timestamps(); $table->timestamps();
}); });
@@ -0,0 +1,36 @@
<?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('media_lists', function (Blueprint $table) {
$table->id();
$table->text('description')->nullable();
$table->integer('favorites_count')->default(0);
$table->unsignedBigInteger('tmdb_id');
$table->integer('item_count')->default(0);
$table->string('iso_639_1', 2);
$table->string('iso_3166_1', 2);
$table->string('list_type', 15);
$table->string('name', 550);
$table->string('poster_path', 550);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('media_lists');
}
};
@@ -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('user_media_lists', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('media_list_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('user_media_lists');
}
};
@@ -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('media_list_items', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('media_list_id');
$table->unsignedBigInteger('item_id');
$table->enum('item_type', ['movie', 'show']);
$table->unsignedBigInteger('tmdb_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('media_list_items');
}
};
+20 -4
View File
@@ -12,11 +12,27 @@ Artisan::command('inspire', function () {
})->purpose('Display an inspiring quote')->hourly(); })->purpose('Display an inspiring quote')->hourly();
// fetch export every week, saturday at 8 and 9 // fetch export every week, saturday at 8 and 9
Schedule::command(FetchExportCommand::class, ['type', 'movies'])->weeklyOn(6, '8:00'); Schedule::command(FetchExportCommand::class, ['movies'])->weeklyOn(6, '8:00');
Schedule::command(FetchExportCommand::class, ['type', 'tv_series'])->weeklyOn(6, '9:00'); Schedule::command(FetchExportCommand::class, ['tv_series'])->weeklyOn(6, '9:00');
Schedule::command(FetchExportItemsCommand::class, ['movie'])->twiceDaily(17,19);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'AlternativeTitles'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Credits'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Images'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Keywords'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Releases'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Translations'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Similar'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Recommendations'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Reviews'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Lists'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Changes'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'Videos'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'WatchProviders'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['movie', '50', 'ExternalIds'])->twiceDaily(14,23);
Schedule::command(FetchExportItemsCommand::class, ['tv_series'])->twiceDaily(17,19);
Schedule::command(FetchExportItemsCommand::class, ['type', 'movie'])->twiceDaily(17,19);
Schedule::command(FetchExportItemsCommand::class, ['type', 'tv_series'])->twiceDaily(17,19);
// fetch items data // fetch items data
Schedule::command(FetchItemDataCommand::class)->twiceDaily(18,20); Schedule::command(FetchItemDataCommand::class)->twiceDaily(18,20);