mirror of
https://github.com/HDInnovations/UNIT3D-Community-Edition.git
synced 2026-01-29 07:19:32 -06:00
Igdb for some reason excludes a field if it's null, even if it's explicitly selected. This obviously breaks the api when it expects a field that isn't there. fixes #4736
166 lines
5.4 KiB
PHP
166 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* NOTICE OF LICENSE.
|
|
*
|
|
* UNIT3D is open-sourced software licensed under the GNU Affero General Public License v3.0
|
|
* The details is bundled with this project in the file LICENSE.txt.
|
|
*
|
|
* @project UNIT3D
|
|
*
|
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
|
* @author HDVinnie
|
|
*/
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Enums\GlobalRateLimit;
|
|
use App\Models\IgdbCompany;
|
|
use App\Models\IgdbGame;
|
|
use App\Models\IgdbGenre;
|
|
use App\Models\IgdbPlatform;
|
|
use DateTime;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\Middleware\RateLimited;
|
|
use Illuminate\Queue\Middleware\Skip;
|
|
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use MarcReichel\IGDBLaravel\Models\Game;
|
|
|
|
class ProcessIgdbGameJob implements ShouldQueue
|
|
{
|
|
use Dispatchable;
|
|
use InteractsWithQueue;
|
|
use Queueable;
|
|
use SerializesModels;
|
|
|
|
/**
|
|
* ProcessIgdbGameJob constructor.
|
|
*/
|
|
public function __construct(public int $id)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Get the middleware the job should pass through.
|
|
*
|
|
* @return array<int, object>
|
|
*/
|
|
public function middleware(): array
|
|
{
|
|
return [
|
|
Skip::when(cache()->has("igdb-game-scraper:{$this->id}")),
|
|
new WithoutOverlapping((string) $this->id)->dontRelease()->expireAfter(30),
|
|
new RateLimited(GlobalRateLimit::IGDB),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Determine the time at which the job should timeout.
|
|
*/
|
|
public function retryUntil(): DateTime
|
|
{
|
|
return now()->addDay();
|
|
}
|
|
|
|
public function handle(): void
|
|
{
|
|
$fetchedGame = Game::select([
|
|
'id',
|
|
'name',
|
|
'summary',
|
|
'first_release_date',
|
|
'url',
|
|
'rating',
|
|
'rating_count',
|
|
])
|
|
->with([
|
|
'cover' => ['image_id'],
|
|
'artworks' => ['image_id'],
|
|
'genres' => ['id', 'name'],
|
|
'videos' => ['video_id', 'name'],
|
|
'involved_companies.company' => ['id', 'name', 'url'],
|
|
'involved_companies.company.logo' => ['image_id'],
|
|
'platforms' => ['id', 'name'],
|
|
'platforms.platform_logo' => ['image_id']
|
|
])
|
|
->findOrFail($this->id);
|
|
|
|
IgdbGame::query()->upsert([[
|
|
'id' => $this->id,
|
|
'name' => $fetchedGame['name'] ?? null,
|
|
'summary' => $fetchedGame['summary'] ?? '',
|
|
'first_artwork_image_id' => $fetchedGame['artworks'][0]['image_id'] ?? null,
|
|
'first_release_date' => $fetchedGame['first_release_date'] ?? null,
|
|
'cover_image_id' => $fetchedGame['cover']['image_id'] ?? null,
|
|
'url' => $fetchedGame['url'] ?? null,
|
|
'rating' => $fetchedGame['rating'] ?? null,
|
|
'rating_count' => $fetchedGame['rating_count'] ?? null,
|
|
'first_video_video_id' => $fetchedGame['videos'][0]['video_id'] ?? null,
|
|
]], ['id']);
|
|
|
|
$game = IgdbGame::query()->findOrFail($this->id);
|
|
|
|
$genres = [];
|
|
|
|
foreach ($fetchedGame->genres ?? [] as $genre) {
|
|
if ($genre['id'] === null || $genre['name'] === null) {
|
|
continue;
|
|
}
|
|
|
|
$genres[] = [
|
|
'id' => $genre['id'],
|
|
'name' => $genre['name'],
|
|
];
|
|
}
|
|
|
|
IgdbGenre::query()->upsert($genres, ['id']);
|
|
$game->genres()->sync(array_unique(array_column($genres, 'id')));
|
|
|
|
$platforms = [];
|
|
|
|
foreach ($fetchedGame->platforms ?? [] as $platform) {
|
|
if ($platform['id'] === null || $platform['name'] === null) {
|
|
continue;
|
|
}
|
|
|
|
$platforms[] = [
|
|
'id' => $platform['id'],
|
|
'name' => $platform['name'],
|
|
'platform_logo_image_id' => $platform['platform_logo']['image_id'] ?? null,
|
|
];
|
|
}
|
|
|
|
IgdbPlatform::query()->upsert($platforms, ['id']);
|
|
$game->platforms()->sync(array_unique(array_column($platforms, 'id')));
|
|
|
|
$companies = [];
|
|
|
|
foreach ($fetchedGame->involved_companies ?? [] as $company) {
|
|
if ($company['company']['id'] === null || $company['company']['name'] === null) {
|
|
continue;
|
|
}
|
|
|
|
$companies[] = [
|
|
'id' => $company['company']['id'],
|
|
'name' => $company['company']['name'],
|
|
'url' => $company['company']['url'] ?? null,
|
|
'logo_image_id' => $company['company']['logo']['image_id'] ?? null,
|
|
];
|
|
}
|
|
|
|
IgdbCompany::query()->upsert($companies, ['id']);
|
|
$game->companies()->sync(array_unique(array_column($companies, 'id')));
|
|
|
|
// Although IGDB doesn't publicly state they cache their api responses,
|
|
// use the same value as tmdb to not abuse them with too many requests
|
|
|
|
cache()->put("igdb-game-scraper:{$this->id}", now(), 8 * 3600);
|
|
}
|
|
}
|