Files
RetroHub/app/Features/Scraper/Services/IGDBCoverScraper.php
T

121 lines
3.3 KiB
PHP

<?php
namespace App\Features\Scraper\Services;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
class IGDBCoverScraper implements CoverScraperInterface
{
private string $clientId;
private string $clientSecret;
private ?string $accessToken = null;
public function __construct()
{
$this->clientId = config('services.igdb.client_id', '');
$this->clientSecret = config('services.igdb.client_secret', '');
}
public function search(string $query, ?int $consoleId = null): Collection
{
if (empty($this->clientId) || empty($this->clientSecret)) {
return collect();
}
$body = "search \"{$query}\"; fields name,cover.url,platforms,release_dates.year;";
if ($consoleId) {
$body .= " where platforms = [{$consoleId}];";
}
$response = $this->makeRequest('/games', $body);
return collect($response)->map(fn ($game) => [
'id' => $game['id'],
'title' => $game['name'],
'cover_url' => isset($game['cover']['url'])
? str_replace('thumb', 'cover_big', $game['cover']['url'])
: null,
'year' => $game['release_dates'][0]['year'] ?? null,
'source' => 'igdb',
]);
}
public function getCoverUrl(int $externalId): ?string
{
if (empty($this->clientId) || empty($this->clientSecret)) {
return null;
}
$response = $this->makeRequest(
'/covers',
"fields url; where game = {$externalId};"
);
if (! empty($response[0]['url'])) {
return str_replace('thumb', 'cover_big', $response[0]['url']);
}
return null;
}
public function getScreenshotUrl(int $externalId): ?string
{
if (empty($this->clientId) || empty($this->clientSecret)) {
return null;
}
$response = $this->makeRequest(
'/screenshots',
"fields url; where game = {$externalId};"
);
return $response[0]['url'] ?? null;
}
public function getImages(int $externalId): array
{
return array_filter([
'cover' => $this->getCoverUrl($externalId),
'screenshot' => $this->getScreenshotUrl($externalId),
]);
}
private function makeRequest(string $endpoint, string $body): array
{
try {
$this->ensureAccessToken();
$response = Http::withHeaders([
'Client-ID' => $this->clientId,
'Authorization' => "Bearer {$this->accessToken}",
])->timeout(10)->post("https://api.igdb.com/v4{$endpoint}", $body);
if ($response->successful()) {
return $response->json();
}
} catch (\Exception $e) {
// Log error
}
return [];
}
private function ensureAccessToken(): void
{
if ($this->accessToken) {
return;
}
$response = Http::asForm()->post('https://id.twitch.tv/oauth2/token', [
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'grant_type' => 'client_credentials',
]);
$this->accessToken = $response->json('access_token');
}
}