2025-04-09 23:03:16 +03:00
|
|
|
<?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)) {
|
2025-04-10 00:44:55 +03:00
|
|
|
$platformData = IgdbPlatform::select(['id', 'name', 'slug', 'abbreviation'])
|
|
|
|
|
->whereIn('id', $gameData->platforms)
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
foreach ($platformData as $platformDetails) {
|
|
|
|
|
$platform = Platform::updateOrCreate(
|
|
|
|
|
['igdb_id' => $platformDetails->id],
|
|
|
|
|
[
|
|
|
|
|
'name' => $platformDetails->name,
|
|
|
|
|
'slug' => $platformDetails->slug,
|
|
|
|
|
'abbreviation' => $platformDetails->abbreviation,
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$platforms[] = $platform->id;
|
2025-04-09 23:03:16 +03:00
|
|
|
}
|
|
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
|
2025-04-09 23:03:16 +03:00
|
|
|
// 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
|
2025-04-10 00:44:55 +03:00
|
|
|
try {
|
|
|
|
|
$artworks = \MarcReichel\IGDBLaravel\Models\Artwork::select([
|
|
|
|
|
'id',
|
|
|
|
|
'url',
|
|
|
|
|
'width',
|
|
|
|
|
'height',
|
|
|
|
|
'image_id'
|
|
|
|
|
])
|
|
|
|
|
->where('game', '=', $gameData->id)
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
foreach ($artworks as $artworkData) {
|
2025-04-09 23:03:16 +03:00
|
|
|
Artwork::updateOrCreate(
|
2025-04-10 00:44:55 +03:00
|
|
|
['igdb_id' => $artworkData->id],
|
2025-04-09 23:03:16 +03:00
|
|
|
[
|
|
|
|
|
'game_id' => $game->id,
|
2025-04-10 00:44:55 +03:00
|
|
|
'url' => $artworkData->url,
|
|
|
|
|
'width' => $artworkData->width ?? null,
|
|
|
|
|
'height' => $artworkData->height ?? null,
|
|
|
|
|
'image_id' => $artworkData->image_id ?? null,
|
2025-04-09 23:03:16 +03:00
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
Log::error('Failed to get artworks for game', [
|
|
|
|
|
'game_id' => $game->id,
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
]);
|
2025-04-09 23:03:16 +03:00
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
|
2025-04-09 23:03:16 +03:00
|
|
|
// Process platforms relationship
|
|
|
|
|
if (!empty($platforms)) {
|
|
|
|
|
$game->platforms()->sync($platforms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process screenshots
|
2025-04-10 00:44:55 +03:00
|
|
|
try {
|
|
|
|
|
$screenshots = \MarcReichel\IGDBLaravel\Models\Screenshot::select([
|
|
|
|
|
'id',
|
|
|
|
|
'url',
|
|
|
|
|
'width',
|
|
|
|
|
'height',
|
|
|
|
|
'image_id'
|
|
|
|
|
])
|
|
|
|
|
->where('game', '=', $gameData->id)
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
foreach ($screenshots as $screenshotData) {
|
2025-04-09 23:03:16 +03:00
|
|
|
Screenshot::updateOrCreate(
|
2025-04-10 00:44:55 +03:00
|
|
|
['igdb_id' => $screenshotData->id],
|
2025-04-09 23:03:16 +03:00
|
|
|
[
|
|
|
|
|
'game_id' => $game->id,
|
2025-04-10 00:44:55 +03:00
|
|
|
'url' => $screenshotData->url,
|
|
|
|
|
'width' => $screenshotData->width ?? null,
|
|
|
|
|
'height' => $screenshotData->height ?? null,
|
|
|
|
|
'image_id' => $screenshotData->image_id ?? null,
|
2025-04-09 23:03:16 +03:00
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
Log::error('Failed to get screenshots for game', [
|
|
|
|
|
'game_id' => $game->id,
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
]);
|
2025-04-09 23:03:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process videos
|
2025-04-10 00:44:55 +03:00
|
|
|
try {
|
|
|
|
|
$videos = \MarcReichel\IGDBLaravel\Models\GameVideo::select([
|
|
|
|
|
'id',
|
|
|
|
|
'name',
|
|
|
|
|
'video_id',
|
|
|
|
|
'url',
|
|
|
|
|
'checksum'
|
|
|
|
|
])
|
|
|
|
|
->where('game', '=', $gameData->id)
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
foreach ($videos as $videoData) {
|
2025-04-09 23:03:16 +03:00
|
|
|
Video::updateOrCreate(
|
2025-04-10 00:44:55 +03:00
|
|
|
['igdb_id' => $videoData->id],
|
2025-04-09 23:03:16 +03:00
|
|
|
[
|
|
|
|
|
'game_id' => $game->id,
|
2025-04-10 00:44:55 +03:00
|
|
|
'name' => $videoData->name,
|
|
|
|
|
'video_id' => $videoData->video_id,
|
|
|
|
|
'url' => $videoData->url,
|
|
|
|
|
'checksum' => $videoData->checksum ?? null,
|
2025-04-09 23:03:16 +03:00
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
Log::error('Failed to get videos for game', [
|
|
|
|
|
'game_id' => $game->id,
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
]);
|
2025-04-09 23:03:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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');
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-10 00:44:55 +03:00
|
|
|
// Fetch related games data using IGDB API
|
2025-04-09 23:03:16 +03:00
|
|
|
$relationships = [
|
2025-04-10 00:44:55 +03:00
|
|
|
'bundles' => IgdbGame::select(['id'])->where('id', 'in', $gameData->bundles ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'collections' => IgdbGame::select(['id'])->where('id', 'in', $gameData->collections ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'dlcs' => IgdbGame::select(['id'])->where('id', 'in', $gameData->dlcs ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'expanded_games' => IgdbGame::select(['id'])->where('id', 'in', $gameData->expanded_games ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'franchises' => IgdbGame::select(['id'])->where('id', 'in', $gameData->franchises ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'ports' => IgdbGame::select(['id'])->where('id', 'in', $gameData->ports ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'remakes' => IgdbGame::select(['id'])->where('id', 'in', $gameData->remakes ?? [])->get()->pluck('id')->toArray(),
|
|
|
|
|
'similar_games' => IgdbGame::select(['id'])->where('id', 'in', $gameData->similar_games ?? [])->get()->pluck('id')->toArray(),
|
2025-04-09 23:03:16 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-10 00:44:55 +03:00
|
|
|
|
|
|
|
|
public function processGenreData(array $genreData): void
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
Genre::updateOrCreate(
|
|
|
|
|
['igdb_id' => $genreData['id']],
|
|
|
|
|
[
|
|
|
|
|
'name' => $genreData['name'],
|
|
|
|
|
'slug' => $genreData['slug'],
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
Log::error('Failed to process genre data', [
|
|
|
|
|
'genre_id' => $genreData['id'],
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
]);
|
|
|
|
|
throw $e;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function processPlatformData(array $platformData): void
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
Platform::updateOrCreate(
|
|
|
|
|
['igdb_id' => $platformData['id']],
|
|
|
|
|
[
|
|
|
|
|
'name' => $platformData['name'],
|
|
|
|
|
'slug' => $platformData['slug'],
|
|
|
|
|
'abbreviation' => $platformData['abbreviation'] ?? null,
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
Log::error('Failed to process platform data', [
|
|
|
|
|
'platform_id' => $platformData['id'],
|
|
|
|
|
'error' => $e->getMessage()
|
|
|
|
|
]);
|
|
|
|
|
throw $e;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-09 23:03:16 +03:00
|
|
|
}
|