From ea282cb42f16e0888eb29d9f59c7f0f5e14b6729 Mon Sep 17 00:00:00 2001 From: BillyOutlast <172061051+BillyOutlast@users.noreply.github.com> Date: Sun, 31 Aug 2025 21:23:36 -0400 Subject: [PATCH] TO lost in sauce for the day, need to rethink my stragegy --- app/Jobs/ProcessPornJob.php | 130 ++++++++++++++++++ app/Jobs/StashBoxSceneScraper.php | 89 ++++++++++++ app/Jobs/ThePornDBVideoScraper.php | 88 ++++++++++++ app/Models/FansdbMeta.php | 15 ++ app/Models/PornJavMeta.php | 15 ++ app/Models/PornMovieMeta.php | 15 ++ app/Models/PornSceneMeta.php | 15 ++ app/Models/StashdbMeta.php | 15 ++ app/Models/ThePornDbSceneMeta.php | 16 +++ ...0001_add_porn_meta_to_categories_table.php | 27 ++++ ..._000002_add_porn_ids_to_torrents_table.php | 37 +++++ ...31_000100_create_porn_scene_meta_table.php | 27 ++++ ...31_000101_create_porn_movie_meta_table.php | 27 ++++ ...8_31_000102_create_porn_jav_meta_table.php | 27 ++++ ...08_31_000103_create_stashdb_meta_table.php | 27 ++++ ..._08_31_000104_create_fansdb_meta_table.php | 27 ++++ ...000_create_theporndb_scene_metas_table.php | 23 ++++ database/seeders/EnablePornCategorySeeder.php | 26 ++++ 18 files changed, 646 insertions(+) create mode 100644 app/Jobs/ProcessPornJob.php create mode 100644 app/Jobs/StashBoxSceneScraper.php create mode 100644 app/Jobs/ThePornDBVideoScraper.php create mode 100644 app/Models/FansdbMeta.php create mode 100644 app/Models/PornJavMeta.php create mode 100644 app/Models/PornMovieMeta.php create mode 100644 app/Models/PornSceneMeta.php create mode 100644 app/Models/StashdbMeta.php create mode 100644 app/Models/ThePornDbSceneMeta.php create mode 100644 database/migrations/2025_08_31_000001_add_porn_meta_to_categories_table.php create mode 100644 database/migrations/2025_08_31_000002_add_porn_ids_to_torrents_table.php create mode 100644 database/migrations/2025_08_31_000100_create_porn_scene_meta_table.php create mode 100644 database/migrations/2025_08_31_000101_create_porn_movie_meta_table.php create mode 100644 database/migrations/2025_08_31_000102_create_porn_jav_meta_table.php create mode 100644 database/migrations/2025_08_31_000103_create_stashdb_meta_table.php create mode 100644 database/migrations/2025_08_31_000104_create_fansdb_meta_table.php create mode 100644 database/migrations/2025_09_01_000000_create_theporndb_scene_metas_table.php create mode 100644 database/seeders/EnablePornCategorySeeder.php diff --git a/app/Jobs/ProcessPornJob.php b/app/Jobs/ProcessPornJob.php new file mode 100644 index 000000000..b8e3abc0a --- /dev/null +++ b/app/Jobs/ProcessPornJob.php @@ -0,0 +1,130 @@ +has("porn-meta-job:{$this->torrentId}")), + new WithoutOverlapping((string) $this->torrentId)->dontRelease()->expireAfter(30), + new RateLimited('porn-meta'), + ]; + } + + public function retryUntil(): DateTime + { + return now()->addDay(); + } + + public function handle(): void + { + $torrent = Torrent::find($this->torrentId); + \Log::debug('ProcessPornJob: Torrent debug data', [ + 'torrent_id' => $this->torrentId, + 'torrent' => $torrent, + ]); + if (! $torrent || $torrent->category_id !== 3) { + \Log::error('ProcessPornJob: Torrent not found or not category_id 3', ['torrent_id' => $this->torrentId]); + return; + } + + // Example: Gather metadata for each ID + $pornMeta = [ + 'theporndb_scene_id' => $torrent->theporndb_scene_id, + 'theporndb_movie_id' => $torrent->theporndb_movie_id, + 'theporndb_jav_id' => $torrent->theporndb_jav_id, + 'stashdb_id' => $torrent->stashdb_id, + 'fansdb_id' => $torrent->fansdb_id, + ]; + + foreach ($pornMeta as $key => $id) { + if ($id) { + // Example: Call external API for $key/$id and store metadata + \Log::info('ProcessPornJob: Fetching metadata', ['key' => $key, 'id' => $id]); + $metadata = null; + if ($key === 'theporndb_scene_id') { + dispatch(new \App\Jobs\ThePornDBVideoScraper($id, 'scenes', $torrent->id)); + // $metadata = fetchThePornDbScene($id); // Your scraper logic + \App\Models\ThePornDbSceneMeta::updateOrCreate([ + 'theporndb_scene_id' => $id, + 'torrent_id' => $torrent->id, + ], [ + 'raw' => $metadata, + ]); + } elseif ($key === 'theporndb_movie_id') { + dispatch(new \App\Jobs\ThePornDBVideoScraper($id, 'movies', $torrent->id)); + // $metadata = fetchThePornDbMovie($id); + \App\Models\PornMovieMeta::updateOrCreate([ + 'movie_id' => $id, + 'torrent_id' => $torrent->id, + ], [ + 'title' => $metadata['title'] ?? null, + 'release_date' => $metadata['release_date'] ?? null, + 'studio' => $metadata['studio'] ?? null, + 'performers' => $metadata['performers'] ?? null, + 'urls' => $metadata['urls'] ?? null, + 'details' => $metadata['details'] ?? null, + 'director' => $metadata['director'] ?? null, + 'raw' => $metadata, + ]); + } elseif ($key === 'theporndb_jav_id') { + dispatch(new \App\Jobs\ThePornDBVideoScraper($id, 'jave', $torrent->id)); + // $metadata = fetchThePornDbJav($id); + \App\Models\PornJavMeta::updateOrCreate([ + 'jav_id' => $id, + 'torrent_id' => $torrent->id, + ], [ + 'title' => $metadata['title'] ?? null, + 'release_date' => $metadata['release_date'] ?? null, + 'studio' => $metadata['studio'] ?? null, + 'performers' => $metadata['performers'] ?? null, + 'urls' => $metadata['urls'] ?? null, + 'details' => $metadata['details'] ?? null, + 'director' => $metadata['director'] ?? null, + 'raw' => $metadata, + ]); + } elseif ($key === 'stashdb_id') { + $endpoint = 'https://stashdb.org/graphql'; + dispatch(new \App\Jobs\StashBoxSceneScraper($id, $endpoint, $torrent->id)); + } elseif ($key === 'fansdb_id') { + $endpoint = 'https://fansdb.cc/graphql'; + dispatch(new \App\Jobs\StashBoxSceneScraper($id, $endpoint, $torrent->id)); + } + } + } + + cache()->put("porn-meta-job:{$this->torrentId}", now(), 8 * 3600); + \Log::info('ProcessPornJob: Completed', ['torrent_id' => $this->torrentId]); + } + + public function failed($exception): void + { + \Log::error('ProcessPornJob permanently failed', [ + 'torrent_id' => $this->torrentId, + 'exception' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), + ]); + } +} diff --git a/app/Jobs/StashBoxSceneScraper.php b/app/Jobs/StashBoxSceneScraper.php new file mode 100644 index 000000000..76e4b63b1 --- /dev/null +++ b/app/Jobs/StashBoxSceneScraper.php @@ -0,0 +1,89 @@ +sceneId = $sceneId; + $this->endpoint = $endpoint; + $this->torrentId = $torrentId; + } + + /** + * Execute the job. + */ + public function handle(): void + { + $query = <<<'GRAPHQL' + query MyQuery { + findScene(id: "%s") { + id + title + release_date + studio { id name } + performers { performer { id name disambiguation } } + urls { type url } + details + director + } + } + GRAPHQL; + + $graphqlQuery = sprintf($query, $this->sceneId); + $response = Http::post($this->endpoint, [ + 'query' => $graphqlQuery, + ]); + + if ($response->successful()) { + $scene = $response->json()['data']['findScene'] ?? []; + if ($this->endpoint === 'https://stashdb.org/graphql') { + \App\Models\StashdbMeta::updateOrCreate([ + 'stashdb_id' => $this->sceneId, + 'torrent_id' => $this->torrentId, + ], [ + 'title' => $scene['title'] ?? null, + 'release_date' => $scene['release_date'] ?? null, + 'studio' => $scene['studio']['name'] ?? null, + 'performers' => $scene['performers'] ?? null, + 'urls' => $scene['urls'] ?? null, + 'details' => $scene['details'] ?? null, + 'director' => $scene['director'] ?? null, + 'raw' => $scene, + ]); + } elseif ($this->endpoint === 'https://fansdb.cc/graphql') { + \App\Models\FansdbMeta::updateOrCreate([ + 'fansdb_id' => $this->sceneId, + 'torrent_id' => $this->torrentId, + ], [ + 'title' => $scene['title'] ?? null, + 'release_date' => $scene['release_date'] ?? null, + 'studio' => $scene['studio']['name'] ?? null, + 'performers' => $scene['performers'] ?? null, + 'urls' => $scene['urls'] ?? null, + 'details' => $scene['details'] ?? null, + 'director' => $scene['director'] ?? null, + 'raw' => $scene, + ]); + } + } + } +} diff --git a/app/Jobs/ThePornDBVideoScraper.php b/app/Jobs/ThePornDBVideoScraper.php new file mode 100644 index 000000000..593219d9b --- /dev/null +++ b/app/Jobs/ThePornDBVideoScraper.php @@ -0,0 +1,88 @@ +id = $id; + $this->type = $type; // 'scenes', 'movies', or 'jave' + $this->torrentId = $torrentId; + } + + /** + * Execute the job. + */ + public function handle(): void + { + $endpoint = sprintf('https://api.theporndb.net/%s/%s?add_to_collection=false', $this->type, $this->id); + $response = Http::get($endpoint); + + if ($response->successful()) { + $data = $response->json(); + if ($this->type === 'scenes') { + \App\Models\PornSceneMeta::updateOrCreate([ + 'scene_id' => $this->id, + 'torrent_id' => $this->torrentId, + ], [ + 'title' => $data['title'] ?? null, + 'release_date' => $data['release_date'] ?? null, + 'studio' => $data['studio'] ?? null, + 'performers' => $data['performers'] ?? null, + 'urls' => $data['urls'] ?? null, + 'details' => $data['details'] ?? null, + 'director' => $data['director'] ?? null, + 'raw' => $data, + ]); + } elseif ($this->type === 'movies') { + \App\Models\PornMovieMeta::updateOrCreate([ + 'movie_id' => $this->id, + 'torrent_id' => $this->torrentId, + ], [ + 'title' => $data['title'] ?? null, + 'release_date' => $data['release_date'] ?? null, + 'studio' => $data['studio'] ?? null, + 'performers' => $data['performers'] ?? null, + 'urls' => $data['urls'] ?? null, + 'details' => $data['details'] ?? null, + 'director' => $data['director'] ?? null, + 'raw' => $data, + ]); + } elseif ($this->type === 'jave') { + \App\Models\PornJavMeta::updateOrCreate([ + 'jav_id' => $this->id, + 'torrent_id' => $this->torrentId, + ], [ + 'title' => $data['title'] ?? null, + 'release_date' => $data['release_date'] ?? null, + 'studio' => $data['studio'] ?? null, + 'performers' => $data['performers'] ?? null, + 'urls' => $data['urls'] ?? null, + 'details' => $data['details'] ?? null, + 'director' => $data['director'] ?? null, + 'raw' => $data, + ]); + } + } else { + Log::error('ThePornDBVideoScraper failed', ['id' => $this->id, 'type' => $this->type, 'response' => $response->body()]); + } + } +} diff --git a/app/Models/FansdbMeta.php b/app/Models/FansdbMeta.php new file mode 100644 index 000000000..cb0a1eb9c --- /dev/null +++ b/app/Models/FansdbMeta.php @@ -0,0 +1,15 @@ +belongsTo(Torrent::class); + } +} diff --git a/app/Models/PornJavMeta.php b/app/Models/PornJavMeta.php new file mode 100644 index 000000000..a66b9c3e3 --- /dev/null +++ b/app/Models/PornJavMeta.php @@ -0,0 +1,15 @@ +belongsTo(Torrent::class); + } +} diff --git a/app/Models/PornMovieMeta.php b/app/Models/PornMovieMeta.php new file mode 100644 index 000000000..a7888c610 --- /dev/null +++ b/app/Models/PornMovieMeta.php @@ -0,0 +1,15 @@ +belongsTo(Torrent::class); + } +} diff --git a/app/Models/PornSceneMeta.php b/app/Models/PornSceneMeta.php new file mode 100644 index 000000000..102a834e9 --- /dev/null +++ b/app/Models/PornSceneMeta.php @@ -0,0 +1,15 @@ +belongsTo(Torrent::class); + } +} diff --git a/app/Models/StashdbMeta.php b/app/Models/StashdbMeta.php new file mode 100644 index 000000000..d602afe62 --- /dev/null +++ b/app/Models/StashdbMeta.php @@ -0,0 +1,15 @@ +belongsTo(Torrent::class); + } +} diff --git a/app/Models/ThePornDbSceneMeta.php b/app/Models/ThePornDbSceneMeta.php new file mode 100644 index 000000000..af8f33962 --- /dev/null +++ b/app/Models/ThePornDbSceneMeta.php @@ -0,0 +1,16 @@ +belongsTo(Torrent::class); + } +} diff --git a/database/migrations/2025_08_31_000001_add_porn_meta_to_categories_table.php b/database/migrations/2025_08_31_000001_add_porn_meta_to_categories_table.php new file mode 100644 index 000000000..a22ee3d74 --- /dev/null +++ b/database/migrations/2025_08_31_000001_add_porn_meta_to_categories_table.php @@ -0,0 +1,27 @@ +boolean('porn_meta')->default(false)->after('movie_meta'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('categories', function (Blueprint $table) { + $table->dropColumn('porn_meta'); + }); + } +}; diff --git a/database/migrations/2025_08_31_000002_add_porn_ids_to_torrents_table.php b/database/migrations/2025_08_31_000002_add_porn_ids_to_torrents_table.php new file mode 100644 index 000000000..7bf161458 --- /dev/null +++ b/database/migrations/2025_08_31_000002_add_porn_ids_to_torrents_table.php @@ -0,0 +1,37 @@ +string('theporndb_scene_id')->nullable()->after('igdb'); + $table->string('theporndb_movie_id')->nullable()->after('theporndb_scene_id'); + $table->string('theporndb_jav_id')->nullable()->after('theporndb_movie_id'); + $table->string('stashdb_id')->nullable()->after('theporndb_jav_id'); + $table->string('fansdb_id')->nullable()->after('stashdb_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('torrents', function (Blueprint $table) { + $table->dropColumn([ + 'theporndb_scene_id', + 'theporndb_movie_id', + 'theporndb_jav_id', + 'stashdb_id', + 'fansdb_id', + ]); + }); + } +}; diff --git a/database/migrations/2025_08_31_000100_create_porn_scene_meta_table.php b/database/migrations/2025_08_31_000100_create_porn_scene_meta_table.php new file mode 100644 index 000000000..a3a167ef3 --- /dev/null +++ b/database/migrations/2025_08_31_000100_create_porn_scene_meta_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('scene_id')->unique(); + $table->foreignId('torrent_id')->constrained()->onDelete('cascade'); + $table->string('title')->nullable(); + $table->date('release_date')->nullable(); + $table->string('studio')->nullable(); + $table->json('performers')->nullable(); + $table->json('urls')->nullable(); + $table->text('details')->nullable(); + $table->string('director')->nullable(); + $table->json('raw')->nullable(); + }); + } + public function down(): void + { + Schema::dropIfExists('porn_scene_meta'); + } +}; diff --git a/database/migrations/2025_08_31_000101_create_porn_movie_meta_table.php b/database/migrations/2025_08_31_000101_create_porn_movie_meta_table.php new file mode 100644 index 000000000..88194cea9 --- /dev/null +++ b/database/migrations/2025_08_31_000101_create_porn_movie_meta_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('movie_id')->unique(); + $table->foreignId('torrent_id')->constrained()->onDelete('cascade'); + $table->string('title')->nullable(); + $table->date('release_date')->nullable(); + $table->string('studio')->nullable(); + $table->json('performers')->nullable(); + $table->json('urls')->nullable(); + $table->text('details')->nullable(); + $table->string('director')->nullable(); + $table->json('raw')->nullable(); + }); + } + public function down(): void + { + Schema::dropIfExists('porn_movie_meta'); + } +}; diff --git a/database/migrations/2025_08_31_000102_create_porn_jav_meta_table.php b/database/migrations/2025_08_31_000102_create_porn_jav_meta_table.php new file mode 100644 index 000000000..66925402a --- /dev/null +++ b/database/migrations/2025_08_31_000102_create_porn_jav_meta_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('jav_id')->unique(); + $table->foreignId('torrent_id')->constrained()->onDelete('cascade'); + $table->string('title')->nullable(); + $table->date('release_date')->nullable(); + $table->string('studio')->nullable(); + $table->json('performers')->nullable(); + $table->json('urls')->nullable(); + $table->text('details')->nullable(); + $table->string('director')->nullable(); + $table->json('raw')->nullable(); + }); + } + public function down(): void + { + Schema::dropIfExists('porn_jav_meta'); + } +}; diff --git a/database/migrations/2025_08_31_000103_create_stashdb_meta_table.php b/database/migrations/2025_08_31_000103_create_stashdb_meta_table.php new file mode 100644 index 000000000..391a3c5fb --- /dev/null +++ b/database/migrations/2025_08_31_000103_create_stashdb_meta_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('stashdb_id')->unique(); + $table->foreignId('torrent_id')->constrained()->onDelete('cascade'); + $table->string('title')->nullable(); + $table->date('release_date')->nullable(); + $table->string('studio')->nullable(); + $table->json('performers')->nullable(); + $table->json('urls')->nullable(); + $table->text('details')->nullable(); + $table->string('director')->nullable(); + $table->json('raw')->nullable(); + }); + } + public function down(): void + { + Schema::dropIfExists('stashdb_meta'); + } +}; diff --git a/database/migrations/2025_08_31_000104_create_fansdb_meta_table.php b/database/migrations/2025_08_31_000104_create_fansdb_meta_table.php new file mode 100644 index 000000000..ee9293500 --- /dev/null +++ b/database/migrations/2025_08_31_000104_create_fansdb_meta_table.php @@ -0,0 +1,27 @@ +id(); + $table->string('fansdb_id')->unique(); + $table->foreignId('torrent_id')->constrained()->onDelete('cascade'); + $table->string('title')->nullable(); + $table->date('release_date')->nullable(); + $table->string('studio')->nullable(); + $table->json('performers')->nullable(); + $table->json('urls')->nullable(); + $table->text('details')->nullable(); + $table->string('director')->nullable(); + $table->json('raw')->nullable(); + }); + } + public function down(): void + { + Schema::dropIfExists('fansdb_meta'); + } +}; diff --git a/database/migrations/2025_09_01_000000_create_theporndb_scene_metas_table.php b/database/migrations/2025_09_01_000000_create_theporndb_scene_metas_table.php new file mode 100644 index 000000000..99868d354 --- /dev/null +++ b/database/migrations/2025_09_01_000000_create_theporndb_scene_metas_table.php @@ -0,0 +1,23 @@ +id(); + $table->string('theporndb_scene_id')->index(); + $table->unsignedBigInteger('torrent_id'); + $table->json('raw')->nullable(); + $table->timestamps(); + + $table->foreign('torrent_id')->references('id')->on('torrents')->onDelete('cascade'); + }); + } + public function down(): void + { + Schema::dropIfExists('theporndb_scene_metas'); + } +}; diff --git a/database/seeders/EnablePornCategorySeeder.php b/database/seeders/EnablePornCategorySeeder.php new file mode 100644 index 000000000..14c27a940 --- /dev/null +++ b/database/seeders/EnablePornCategorySeeder.php @@ -0,0 +1,26 @@ +updateOrInsert( + ['name' => 'Porn'], + [ + 'icon' => 'fa-mars', + 'position' => 99, + 'porn_meta' => true, + 'movie_meta' => false, + 'tv_meta' => false, + 'game_meta' => false, + 'music_meta' => false, + 'no_meta' => false, + ] + ); + } +}