fix(admin): add missing constraints to resource queries in backfill anime actions (#396)

This commit is contained in:
paranarimasu
2022-06-07 23:39:03 -05:00
committed by GitHub
parent 3ed878ab46
commit 899d01fada
11 changed files with 12 additions and 823 deletions
@@ -9,6 +9,7 @@ use App\Models\Auth\User;
use App\Models\Wiki\ExternalResource;
use App\Pivots\AnimeResource;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Log;
@@ -60,9 +61,9 @@ abstract class BackfillAnimeResource extends BackfillAnimePipe
protected function getOrCreateResource(int $id, string $slug = null): ExternalResource
{
$resource = ExternalResource::query()
->select([ExternalResource::ATTRIBUTE_ID, ExternalResource::ATTRIBUTE_LINK])
->where(ExternalResource::ATTRIBUTE_SITE, $this->getSite()->value)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $id)
->whereHas(ExternalResource::RELATION_ANIME, fn (Builder $animeQuery) => $animeQuery->whereKey($this->anime->getKey()))
->first();
if ($resource === null) {
@@ -11,6 +11,7 @@ use App\Models\Wiki\Studio;
use App\Pipes\Wiki\Anime\BackfillAnimePipe;
use App\Pivots\StudioResource;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config;
@@ -335,6 +336,7 @@ class BackfillAnimeStudios extends BackfillAnimePipe
$studioResource = ExternalResource::query()
->where(ExternalResource::ATTRIBUTE_SITE, $site->value)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $id)
->whereHas(ExternalResource::RELATION_STUDIOS, fn (Builder $studioQuery) => $studioQuery->whereKey($studio))
->first();
if (! $studioResource instanceof ExternalResource) {
-97
View File
@@ -1,97 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Pivots\AnimeResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
/**
* Class AniDbResourceSeeder.
*/
class AniDbResourceSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get anime that have MAL resource but do not have AniDB resource
$animes = Anime::query()
->select([Anime::ATTRIBUTE_ID, Anime::ATTRIBUTE_NAME])
->whereHas(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
})->whereDoesntHave(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANIDB);
})
->get();
foreach ($animes as $anime) {
if (! $anime instanceof Anime) {
continue;
}
$malResource = $anime->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
if ($malResource instanceof ExternalResource && $malResource->external_id !== null) {
// Try not to upset Yuna
sleep(rand(2, 5));
// Yuna api call
try {
$response = Http::get('https://relations.yuna.moe/api/ids', [
'source' => 'myanimelist',
'id' => $malResource->external_id,
])
->throw()
->json();
$anidbId = Arr::get($response, 'anidb');
// Only proceed if we have a match
if ($anidbId !== null) {
// Check if AniDB resource already exists
$anidbResource = ExternalResource::query()
->select([ExternalResource::ATTRIBUTE_ID, ExternalResource::ATTRIBUTE_LINK])
->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANIDB)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $anidbId)
->first();
// Create AniDB resource if it doesn't already exist
if ($anidbResource === null) {
Log::info("Creating anidb resource '$anidbId' for anime '$anime->name'");
$anidbResource = ExternalResource::factory()->createOne([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $anidbId,
ExternalResource::ATTRIBUTE_LINK => "https://anidb.net/anime/$anidbId",
ExternalResource::ATTRIBUTE_SITE => ResourceSite::ANIDB,
]);
}
// Attach AniDB resource to anime
if (AnimeResource::query()
->where($anime->getKeyName(), $anime->getKey())
->where($anidbResource->getKeyName(), $anidbResource->getKey())
->doesntExist()
) {
Log::info("Attaching resource '$anidbResource->link' to anime '$anime->name'");
$anidbResource->anime()->attach($anime);
}
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}
@@ -1,109 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Pivots\AnimeResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
/**
* Class AnilistAnimeResourceSeeder.
*/
class AnilistAnimeResourceSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get anime that have MAL resource but do not have Anilist resource
$animes = Anime::query()
->select([Anime::ATTRIBUTE_ID, Anime::ATTRIBUTE_NAME])
->whereHas(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
})->whereDoesntHave(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
})
->get();
foreach ($animes as $anime) {
if (! $anime instanceof Anime) {
continue;
}
$malResource = $anime->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
if ($malResource instanceof ExternalResource && $malResource->external_id !== null) {
// Try not to upset Anilist
sleep(rand(2, 5));
// Anilist graphql query
$query = '
query ($id: Int) {
Media (idMal: $id, type: ANIME) {
id
}
}
';
// Anilist graphql variables
$variables = [
'id' => $malResource->external_id,
];
// Anilist graphql api call
try {
$response = Http::post('https://graphql.anilist.co', [
'query' => $query,
'variables' => $variables,
])
->throw()
->json();
$anilistId = Arr::get($response, 'data.Media.id');
// Check if Anilist resource already exists
$anilistResource = ExternalResource::query()
->select([ExternalResource::ATTRIBUTE_ID, ExternalResource::ATTRIBUTE_LINK])
->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $anilistId)
->first();
// Create Anilist resource if it doesn't already exist
if ($anilistResource === null) {
Log::info("Creating anilist resource '$anilistId' for anime '$anime->name'");
$anilistResource = ExternalResource::factory()->createOne([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $anilistId,
ExternalResource::ATTRIBUTE_LINK => "https://anilist.co/anime/$anilistId/",
ExternalResource::ATTRIBUTE_SITE => ResourceSite::ANILIST,
]);
}
// Attach Anilist resource to anime
if (
AnimeResource::query()
->where($anime->getKeyName(), $anime->getKey())
->where($anilistResource->getKeyName(), $anilistResource->getKey())
->doesntExist()
) {
Log::info("Attaching resource '$anilistResource->link' to anime '$anime->name'");
$anilistResource->anime()->attach($anime);
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}
@@ -1,106 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Artist;
use App\Models\Wiki\ExternalResource;
use App\Pivots\ArtistResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
/**
* Class AnilistArtistResourceSeeder.
*/
class AnilistArtistResourceSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get artists that have MAL resource but do not have Anilist resource
$artists = Artist::query()
->select([Artist::ATTRIBUTE_ID, Artist::ATTRIBUTE_NAME])
->whereDoesntHave(Artist::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
})
->get();
foreach ($artists as $artist) {
if (! $artist instanceof Artist) {
continue;
}
// Try not to upset Anilist
sleep(rand(2, 5));
// Anilist graphql query
$query = '
query ($artistQuery: String) {
Staff (search: $artistQuery) {
id
}
}
';
// Anilist graphql variables
$variables = [
'artistQuery' => $artist->name,
];
// Anilist graphql api call
try {
$response = Http::post('https://graphql.anilist.co', [
'query' => $query,
'variables' => $variables,
])
->throw()
->json();
$anilistId = Arr::get($response, 'data.Staff.id');
// Check if Anilist resource already exists
$anilistResource = ExternalResource::query()
->select([ExternalResource::ATTRIBUTE_ID, ExternalResource::ATTRIBUTE_LINK])
->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $anilistId)
->first();
// Create Anilist resource if it doesn't already exist
if ($anilistResource === null) {
Log::info("Creating anilist resource '$anilistId' for artist '$artist->name'");
$anilistResource = ExternalResource::factory()->createOne([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $anilistId,
ExternalResource::ATTRIBUTE_LINK => "https://anilist.co/staff/$anilistId/",
ExternalResource::ATTRIBUTE_SITE => ResourceSite::ANILIST,
]);
}
// Attach Anilist resource to artist
if (
ArtistResource::query()
->where($artist->getKeyName(), $artist->getKey())
->where($anilistResource->getKeyName(), $anilistResource->getKey())
->doesntExist()
) {
Log::info("Attaching resource '$anilistResource->link' to artist '$artist->name'");
$anilistResource->artists()->attach($artist);
}
} catch (RequestException $e) {
Log::info($e->getMessage());
return;
}
}
}
}
-126
View File
@@ -1,126 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ImageFacet;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Artist;
use App\Models\Wiki\ExternalResource;
use App\Models\Wiki\Image;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
/**
* Class ArtistCoverSeeder.
*/
class ArtistCoverSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get artists that have MAL resource but not both cover images
$artists = Artist::query()
->select([Artist::ATTRIBUTE_ID, Artist::ATTRIBUTE_NAME])
->whereHas(Artist::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
})->whereDoesntHave(Artist::RELATION_IMAGES, function (Builder $imageQuery) {
$imageQuery->whereIn(Image::ATTRIBUTE_FACET, [ImageFacet::COVER_LARGE, ImageFacet::COVER_SMALL]);
})
->get();
$fs = Storage::disk('images');
foreach ($artists as $artist) {
if (! $artist instanceof Artist) {
continue;
}
$anilistResource = $artist->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
if ($anilistResource instanceof ExternalResource && $anilistResource->external_id !== null) {
$artistCoverLarge = $artist->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_LARGE)->first();
$artistCoverSmall = $artist->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_SMALL)->first();
// Try not to upset Anilist
sleep(rand(2, 5));
// Anilist graphql query
$query = '
query ($id: Int) {
Staff (id: $id) {
image {
large
medium
}
}
}
';
// Anilist graphql variables
$variables = [
'id' => $anilistResource->external_id,
];
// Anilist graphql api call
try {
$response = Http::post('https://graphql.anilist.co', [
'query' => $query,
'variables' => $variables,
])
->throw()
->json();
$anilistCoverLarge = Arr::get($response, 'data.Staff.image.large');
$anilistCoverSmall = Arr::get($response, 'data.Staff.image.medium');
// Create large cover image
if ($anilistCoverLarge !== null && $artistCoverLarge === null) {
$coverImageResponse = Http::get($anilistCoverLarge);
$coverImage = $coverImageResponse->body();
$coverFile = File::createWithContent(basename($anilistCoverLarge), $coverImage);
$coverLarge = $fs->putFile('', $coverFile);
$coverLargeImage = Image::factory()->createOne([
Image::ATTRIBUTE_FACET => ImageFacet::COVER_LARGE,
Image::ATTRIBUTE_PATH => $coverLarge,
]);
// Attach large cover to artist
Log::info("Attaching image '$coverLargeImage->path' to artist '$artist->name'");
$coverLargeImage->artists()->attach($artist);
}
// Create small cover image
if ($anilistCoverSmall !== null && $artistCoverSmall === null) {
$coverImageResponse = Http::get($anilistCoverSmall);
$coverImage = $coverImageResponse->body();
$coverFile = File::createWithContent(basename($anilistCoverSmall), $coverImage);
$coverSmall = $fs->putFile('', $coverFile);
$coverSmallImage = Image::factory()->createOne([
Image::ATTRIBUTE_FACET => ImageFacet::COVER_SMALL,
Image::ATTRIBUTE_PATH => $coverSmall,
]);
// Attach large cover to artist
Log::info("Attaching image '$coverSmallImage->path' to artist '$artist->name'");
$coverSmallImage->artists()->attach($artist);
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}
+2 -7
View File
@@ -18,13 +18,8 @@ class DatabaseSeeder extends Seeder
*/
public function run(): void
{
$this->call(DigitalOceanTransactionSeeder::class);
$this->call(PermissionSeeder::class);
$this->call(VideoSeeder::class);
$this->call(AnilistAnimeResourceSeeder::class);
$this->call(SynopsisCoverSeeder::class);
$this->call(AniDbResourceSeeder::class);
$this->call(AnilistArtistResourceSeeder::class);
$this->call(ArtistCoverSeeder::class);
$this->call(KitsuResourceSeeder::class);
$this->call(StudioSeeder::class);
}
}
-106
View File
@@ -1,106 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Pivots\AnimeResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
/**
* Class KitsuResourceSeeder.
*/
class KitsuResourceSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get anime that have MAL resource but do not have Kitsu resource
$animes = Anime::query()
->select([Anime::ATTRIBUTE_ID, Anime::ATTRIBUTE_NAME])
->whereHas(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
})->whereDoesntHave(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::KITSU);
})
->get();
foreach ($animes as $anime) {
if (! $anime instanceof Anime) {
continue;
}
$malResource = $anime->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
if ($malResource instanceof ExternalResource && $malResource->external_id !== null) {
// Try not to upset Kitsu
sleep(rand(2, 5));
// Kitsu api call
try {
$response = Http::contentType('application/vnd.api+json')
->accept('application/vnd.api+json')
->get('https://kitsu.io/api/edge/mappings', [
'include' => 'item',
'filter' => [
'externalSite' => 'myanimelist/anime',
'externalId' => $malResource->external_id,
],
])
->throw()
->json();
$kitsuResourceData = Arr::get($response, 'data', []);
$kitsuResourceIncluded = Arr::get($response, 'included', []);
// Only proceed if we have a single match
if (count($kitsuResourceData) === 1 && count($kitsuResourceIncluded) === 1) {
$kitsuId = $kitsuResourceIncluded[0]['id'];
$kitsuSlug = $kitsuResourceIncluded[0]['attributes']['slug'];
// Check if Kitsu resource already exists
$kitsuResource = ExternalResource::query()
->select([ExternalResource::ATTRIBUTE_ID, ExternalResource::ATTRIBUTE_LINK])
->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::KITSU)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $kitsuId)
->first();
// Create Kitsu resource if it doesn't already exist
if ($kitsuResource === null) {
Log::info("Creating kitsu resource '$kitsuId' for anime '$anime->name'");
$kitsuResource = ExternalResource::factory()->createOne([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $kitsuId,
ExternalResource::ATTRIBUTE_LINK => "https://kitsu.io/anime/$kitsuSlug",
ExternalResource::ATTRIBUTE_SITE => ResourceSite::KITSU,
]);
}
// Attach Kitsu resource to anime
if (AnimeResource::query()
->where($anime->getKeyName(), $anime->getKey())
->where($kitsuResource->getKeyName(), $kitsuResource->getKey())
->doesntExist()
) {
Log::info("Attaching resource '$kitsuResource->link' to anime '$anime->name'");
$kitsuResource->anime()->attach($anime);
}
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}
+6 -8
View File
@@ -7,7 +7,6 @@ namespace Database\Seeders;
use App\Models\Auth\Permission;
use App\Models\Auth\Role;
use Illuminate\Database\Seeder;
use RuntimeException;
/**
* Class PermissionSeeder.
@@ -21,15 +20,14 @@ class PermissionSeeder extends Seeder
*/
public function run(): void
{
// Roles
/** @var Role */
$admin = Role::findOrCreate('Admin');
$wikiEditor = Role::findOrCreate('Wiki Editor');
$wikiViewer = Role::findOrCreate('Wiki Viewer');
// Spatie pls.
if (! $admin instanceof Role || ! $wikiEditor instanceof Role || ! $wikiViewer instanceof Role) {
throw new RuntimeException('Could not create roles');
}
/** @var Role */
$wikiEditor = Role::findOrCreate('Wiki Editor');
/** @var Role */
$wikiViewer = Role::findOrCreate('Wiki Viewer');
// Admin Resources
$this->configureAdminResourcePermissions($admin, 'announcement', true);
-128
View File
@@ -1,128 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Http\Api\Filter\ComparisonOperator;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Models\Wiki\Studio;
use App\Pivots\AnimeStudio;
use App\Pivots\StudioResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
/**
* Class StudioSeeder.
*/
class StudioSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Do not proceed if we do not have authorization to the MAL API
$malClientID = Config::get('services.mal.client');
if ($malClientID === null) {
Log::error('MAL_CLIENT_ID must be configured in your env file.');
return;
}
$animes = Anime::query()
->select([Anime::ATTRIBUTE_ID, Anime::ATTRIBUTE_NAME])
->whereDoesntHave(Anime::RELATION_STUDIOS)
->whereHas(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
})
->get();
foreach ($animes as $anime) {
if (! $anime instanceof Anime) {
continue;
}
$malResource = $anime->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL);
if ($malResource instanceof ExternalResource && $malResource->external_id !== null) {
// Try not to upset MAL
sleep(rand(2, 5));
try {
$response = Http::withHeaders(['X-MAL-CLIENT-ID' => $malClientID])
->get("https://api.myanimelist.net/v2/anime/$malResource->external_id", [
'fields' => 'studios',
])
->throw()
->json();
$malStudios = Arr::get($response, 'studios', []);
foreach ($malStudios as $malStudio) {
$name = Arr::get($malStudio, 'name');
$id = Arr::get($malStudio, 'id');
if (empty($name) || empty($id)) {
continue;
}
$studio = Studio::query()->firstWhere(Studio::ATTRIBUTE_NAME, $name);
if (! $studio instanceof Studio) {
Log::info("Creating studio '$name'");
$studio = Studio::factory()->createOne([
Studio::ATTRIBUTE_NAME => $name,
Studio::ATTRIBUTE_SLUG => Str::slug($name, '_'),
]);
}
$studioResource = ExternalResource::query()
->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::MAL)
->where(ExternalResource::ATTRIBUTE_EXTERNAL_ID, $id)
->where(ExternalResource::ATTRIBUTE_LINK, ComparisonOperator::LIKE, 'https://myanimelist.net/anime/producer/%')
->first();
if (! $studioResource instanceof ExternalResource) {
Log::info("Creating studio resource with id '$id' and name '$name'");
$studioResource = ExternalResource::factory()->createOne([
ExternalResource::ATTRIBUTE_EXTERNAL_ID => $id,
ExternalResource::ATTRIBUTE_LINK => "https://myanimelist.net/anime/producer/$id/",
ExternalResource::ATTRIBUTE_SITE => ResourceSite::MAL,
]);
}
if (StudioResource::query()
->where($studio->getKeyName(), $studio->getKey())
->where($studioResource->getKeyName(), $studioResource->getKey())
->doesntExist()
) {
Log::info("Attaching resource '$studioResource->link' to studio '{$studio->getName()}'");
$studioResource->studios()->attach($studio);
}
if (AnimeStudio::query()
->where($anime->getKeyName(), $anime->getKey())
->where($studio->getKeyName(), $studio->getKey())
->doesntExist()
) {
Log::info("Attaching studio '$name' to anime '{$anime->getName()}'");
$anime->studios()->attach($studio);
}
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}
-135
View File
@@ -1,135 +0,0 @@
<?php
declare(strict_types=1);
namespace Database\Seeders;
use App\Enums\Models\Wiki\ImageFacet;
use App\Enums\Models\Wiki\ResourceSite;
use App\Models\Wiki\Anime;
use App\Models\Wiki\ExternalResource;
use App\Models\Wiki\Image;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Seeder;
use Illuminate\Http\Client\RequestException;
use Illuminate\Http\Testing\File;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
/**
* Class SynopsisCoverSeeder.
*/
class SynopsisCoverSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run(): void
{
// Get anime that have MAL resource but not both cover images
$animes = Anime::query()
->select([Anime::ATTRIBUTE_ID, Anime::ATTRIBUTE_NAME, Anime::ATTRIBUTE_SYNOPSIS])
->whereHas(Anime::RELATION_RESOURCES, function (Builder $resourceQuery) {
$resourceQuery->where(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
})->whereDoesntHave(Anime::RELATION_IMAGES, function (Builder $imageQuery) {
$imageQuery->whereIn(Image::ATTRIBUTE_FACET, [ImageFacet::COVER_LARGE, ImageFacet::COVER_SMALL]);
})
->get();
$fs = Storage::disk('images');
foreach ($animes as $anime) {
if (! $anime instanceof Anime) {
continue;
}
$anilistResource = $anime->resources()->firstWhere(ExternalResource::ATTRIBUTE_SITE, ResourceSite::ANILIST);
if ($anilistResource instanceof ExternalResource && $anilistResource->external_id !== null) {
$animeCoverLarge = $anime->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_LARGE)->first();
$animeCoverSmall = $anime->images()->where(Image::ATTRIBUTE_FACET, ImageFacet::COVER_SMALL)->first();
// Try not to upset Anilist
sleep(rand(2, 5));
// Anilist graphql query
$query = '
query ($id: Int) {
Media (id: $id, type: ANIME) {
description
coverImage {
extraLarge
medium
}
}
}
';
// Anilist graphql variables
$variables = [
'id' => $anilistResource->external_id,
];
// Anilist graphql api call
try {
$response = Http::post('https://graphql.anilist.co', [
'query' => $query,
'variables' => $variables,
])
->throw()
->json();
$anilistSynopsis = Arr::get($response, 'data.Media.description');
$anilistCoverLarge = Arr::get($response, 'data.Media.coverImage.extraLarge');
$anilistCoverSmall = Arr::get($response, 'data.Media.coverImage.medium');
// Set Anime synopsis
if ($anilistSynopsis !== null && $anime->synopsis === null) {
Log::info("Setting synopsis for anime '$anime->name'");
$anime->synopsis = $anilistSynopsis;
$anime->save();
}
// Create large cover image
if ($anilistCoverLarge !== null && $animeCoverLarge === null) {
$coverImageResponse = Http::get($anilistCoverLarge);
$coverImage = $coverImageResponse->body();
$coverFile = File::createWithContent(basename($anilistCoverLarge), $coverImage);
$coverLarge = $fs->putFile('', $coverFile);
$coverLargeImage = Image::factory()->createOne([
Image::ATTRIBUTE_FACET => ImageFacet::COVER_LARGE,
Image::ATTRIBUTE_PATH => $coverLarge,
]);
// Attach large cover to anime
Log::info("Attaching image '$coverLargeImage->path' to anime '$anime->name'");
$coverLargeImage->anime()->attach($anime);
}
// Create small cover image
if ($anilistCoverSmall !== null && $animeCoverSmall === null) {
$coverImageResponse = Http::get($anilistCoverSmall);
$coverImage = $coverImageResponse->body();
$coverFile = File::createWithContent(basename($anilistCoverSmall), $coverImage);
$coverSmall = $fs->putFile('', $coverFile);
$coverSmallImage = Image::factory()->createOne([
Image::ATTRIBUTE_FACET => ImageFacet::COVER_SMALL,
Image::ATTRIBUTE_PATH => $coverSmall,
]);
// Attach large cover to anime
Log::info("Attaching image '$coverSmallImage->path' to anime '$anime->name'");
$coverSmallImage->anime()->attach($anime);
}
} catch (RequestException $e) {
Log::info($e->getMessage());
}
}
}
}
}