347 lines
11 KiB
PHP
347 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Game;
|
|
use App\Models\Genre;
|
|
use App\Models\Platform;
|
|
use App\Models\Artwork;
|
|
use App\Models\Screenshot;
|
|
use App\Models\Video;
|
|
use Illuminate\Support\Facades\Log;
|
|
use MarcReichel\IGDBLaravel\Models\Collection;
|
|
use MarcReichel\IGDBLaravel\Models\Game as IgdbGame;
|
|
use MarcReichel\IGDBLaravel\Models\Cover;
|
|
use MarcReichel\IGDBLaravel\Models\Genre as IgdbGenre;
|
|
use MarcReichel\IGDBLaravel\Models\Platform as IgdbPlatform;
|
|
|
|
class IgdbService
|
|
{
|
|
public function get()
|
|
{
|
|
try {
|
|
$existingIds = $this->getExistingIds();
|
|
|
|
$queryBuilder = IgdbGame::select([
|
|
'id',
|
|
'name',
|
|
'summary',
|
|
'cover.url',
|
|
'slug',
|
|
'genres',
|
|
'platforms',
|
|
'first_release_date',
|
|
'rating',
|
|
'rating_count'
|
|
])
|
|
->where('rating_count', '>', 0)
|
|
->where('category', '=', 0);
|
|
|
|
if (!empty($existingIds)) {
|
|
$queryBuilder = $queryBuilder->whereNotIn('id', array_map(function($id) {
|
|
return (int)str_replace('"', '', $id);
|
|
}, $existingIds));
|
|
}
|
|
|
|
$a = $queryBuilder
|
|
->limit(50)
|
|
->get();
|
|
}catch (\Throwable $e) {
|
|
dd(
|
|
$e->getMessage(),
|
|
$e->getTrace()
|
|
);
|
|
}
|
|
|
|
return $a;
|
|
}
|
|
|
|
private function getExistingIds(): ?array
|
|
{
|
|
$existingGames = Game::get();
|
|
|
|
if (empty($existingGames)) {
|
|
return null;
|
|
}
|
|
|
|
$existingIds = [];
|
|
|
|
/** @var Game $existingGame */
|
|
foreach ($existingGames as $existingGame) {
|
|
$existingIds[] = (string)$existingGame->id;
|
|
}
|
|
|
|
return array_map(function($id) {
|
|
return '"'.$id.'"';
|
|
}, $existingIds);
|
|
}
|
|
|
|
public function searchGames(string $query, int $limit = 10, ?int $startTimestamp = null, ?int $endTimestamp = null): array
|
|
{
|
|
try {
|
|
$queryBuilder = IgdbGame::select([
|
|
'id',
|
|
'name',
|
|
'summary',
|
|
'cover',
|
|
'slug',
|
|
'genres',
|
|
'platforms',
|
|
'first_release_date',
|
|
'rating',
|
|
'rating_count'
|
|
])
|
|
->where('rating_count', '>', 0)
|
|
->where('category', '=', 0) // Only main games, no DLCs or expansions
|
|
->limit($limit)
|
|
->orderBy('rating', 'desc');
|
|
|
|
if ($startTimestamp && $endTimestamp) {
|
|
$queryBuilder->where('first_release_date', '>=', $startTimestamp)
|
|
->where('first_release_date', '<=', $endTimestamp);
|
|
}
|
|
|
|
if ($query) {
|
|
$queryBuilder->search($query);
|
|
}
|
|
|
|
return $queryBuilder->get()->toArray();
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to search games', [
|
|
'query' => $query,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
public function getGameDetails(int $igdbId): ?array
|
|
{
|
|
try {
|
|
$game = IgdbGame::select([
|
|
'id',
|
|
'name',
|
|
'summary',
|
|
'storyline',
|
|
'cover.url',
|
|
'slug',
|
|
'first_release_date',
|
|
'rating',
|
|
'rating_count',
|
|
'category',
|
|
'status',
|
|
'url',
|
|
'version_title',
|
|
'artworks.url',
|
|
'artworks.width',
|
|
'artworks.height',
|
|
'artworks.image_id',
|
|
'screenshots.url',
|
|
'screenshots.width',
|
|
'screenshots.height',
|
|
'screenshots.image_id',
|
|
'videos.name',
|
|
'videos.video_id',
|
|
'videos.url',
|
|
'videos.checksum',
|
|
'bundles.id',
|
|
'collections.id',
|
|
'dlcs.id',
|
|
'expanded_games.id',
|
|
'franchises.id',
|
|
'ports.id',
|
|
'remakes.id',
|
|
'similar_games.id'
|
|
])
|
|
->where('id', $igdbId)
|
|
->first();
|
|
|
|
if (!$game) {
|
|
return null;
|
|
}
|
|
|
|
return $game->toArray();
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to fetch game details from IGDB', [
|
|
'igdb_id' => $igdbId,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function getGameCover(int $coverId): ?string
|
|
{
|
|
try {
|
|
return Cover::select(['url'])
|
|
->where('id', $coverId)
|
|
->first()
|
|
?->url;
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to get game cover', [
|
|
'id' => $coverId,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function getGenreDetails(int $genreId): ?array
|
|
{
|
|
try {
|
|
return IgdbGenre::select(['id', 'name', 'slug'])
|
|
->where('id', $genreId)
|
|
->first()
|
|
?->toArray();
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to get genre details', [
|
|
'id' => $genreId,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function getPlatformDetails(int $platformId): ?array
|
|
{
|
|
try {
|
|
return IgdbPlatform::select(['id', 'name', 'slug', 'abbreviation'])
|
|
->where('id', $platformId)
|
|
->first()
|
|
?->toArray();
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to get platform details', [
|
|
'id' => $platformId,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public function processGameData(IgdbGame $gameData): Game
|
|
{
|
|
// Process platforms
|
|
$platforms = [];
|
|
if (isset($gameData->platforms) && is_array($gameData->platforms)) {
|
|
foreach ($gameData->platforms as $platformId) {
|
|
if ($platformDetails = $this->getPlatformDetails($platformId)) {
|
|
$platform = Platform::updateOrCreate(
|
|
['igdb_id' => $platformDetails['id']],
|
|
[
|
|
'name' => $platformDetails['name'],
|
|
'slug' => $platformDetails['slug'],
|
|
'abbreviation' => $platformDetails['abbreviation'],
|
|
]
|
|
);
|
|
$platforms[] = $platform->id;
|
|
}
|
|
}
|
|
}
|
|
// Create or update the game
|
|
$game = Game::updateOrCreate(
|
|
['igdb_id' => $gameData->id],
|
|
[
|
|
'name' => $gameData->name,
|
|
'summary' => $gameData->summary ?? null,
|
|
'cover_url' => $gameData->cover?->url ?? null,
|
|
'slug' => $gameData->slug,
|
|
'first_release_date' => $gameData->first_release_date ?? null,
|
|
'rating' => $gameData->rating ?? null,
|
|
'rating_count' => $gameData->rating_count ?? null,
|
|
]
|
|
);
|
|
|
|
// Process artworks
|
|
if (isset($gameData->artworks) && is_array($gameData->artworks)) {
|
|
foreach ($gameData->artworks as $artwork) {
|
|
Artwork::updateOrCreate(
|
|
['igdb_id' => $artwork->id],
|
|
[
|
|
'game_id' => $game->id,
|
|
'url' => $artwork->url,
|
|
'width' => $artwork->width ?? null,
|
|
'height' => $artwork->height ?? null,
|
|
'image_id' => $artwork->image_id ?? null,
|
|
]
|
|
);
|
|
}
|
|
}
|
|
// Process platforms relationship
|
|
if (!empty($platforms)) {
|
|
$game->platforms()->sync($platforms);
|
|
}
|
|
|
|
// Process screenshots
|
|
if (isset($gameData->screenshots) && is_array($gameData->screenshots)) {
|
|
foreach ($gameData->screenshots as $screenshot) {
|
|
Screenshot::updateOrCreate(
|
|
['igdb_id' => $screenshot->id],
|
|
[
|
|
'game_id' => $game->id,
|
|
'url' => $screenshot->url,
|
|
'width' => $screenshot->width ?? null,
|
|
'height' => $screenshot->height ?? null,
|
|
'image_id' => $screenshot->image_id ?? null,
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|
|
// Process videos
|
|
if (isset($gameData->videos) && is_array($gameData->videos)) {
|
|
foreach ($gameData->videos as $video) {
|
|
Video::updateOrCreate(
|
|
['igdb_id' => $video->id],
|
|
[
|
|
'game_id' => $game->id,
|
|
'name' => $video->name,
|
|
'video_id' => $video->video_id,
|
|
'url' => $video->url,
|
|
'checksum' => $video->checksum ?? null,
|
|
]
|
|
);
|
|
}
|
|
}
|
|
|
|
// Process relationships
|
|
$this->processGameRelationships($game, $gameData);
|
|
|
|
return $game;
|
|
}
|
|
|
|
private function processGameRelationships(Game $game,IgdbGame $gameData): void
|
|
{
|
|
// Ensure $gameData is an IgdbGame instance
|
|
if (!($gameData instanceof \MarcReichel\IGDBLaravel\Models\Game)) {
|
|
throw new \InvalidArgumentException('Game data must be an instance of IgdbGame');
|
|
}
|
|
|
|
$relationships = [
|
|
'bundles' => 'bundles',
|
|
'collections' => 'collections',
|
|
'dlcs' => 'dlcs',
|
|
'expanded_games' => 'expansions',
|
|
'franchises' => 'franchises',
|
|
'ports' => 'ports',
|
|
'remakes' => 'remakes',
|
|
'similar_games' => 'similarGames',
|
|
];
|
|
|
|
$collections = Collection::where('games', $gameData->identifier)->first();
|
|
|
|
dd(
|
|
$gameData,
|
|
$collections
|
|
);
|
|
|
|
foreach ($relationships as $igdbKey => $relationship) {
|
|
$relatedGames = [];
|
|
if (isset($gameData->$igdbKey) && !empty($gameData->$igdbKey)) {
|
|
$relatedIds = collect($gameData->$igdbKey)->pluck('id')->toArray();
|
|
$relatedGames = Game::whereIn('igdb_id', $relatedIds)->pluck('id')->toArray();
|
|
}
|
|
$game->$relationship()->sync($relatedGames);
|
|
}
|
|
}
|
|
}
|