You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
893 lines
25 KiB
PHP
893 lines
25 KiB
PHP
<?php
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', '1');
|
|
|
|
// igdb.php
|
|
|
|
require_once __DIR__ . '/igdb-settings.php';
|
|
|
|
if (!defined('WIKI_DE_API_URL')) {
|
|
define('WIKI_DE_API_URL', 'https://de.wikipedia.org/w/api.php');
|
|
}
|
|
|
|
if (!defined('WIKI_USER_AGENT')) {
|
|
define('WIKI_USER_AGENT', 'MultimediaFlutter/1.0 (https://windesign.at; Herwig.Birke@windesign.at)');
|
|
}
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
// =====================================================
|
|
// CORS HANDLING
|
|
// =====================================================
|
|
|
|
function origin_allowed(string $origin): bool
|
|
{
|
|
if (!defined('IGDB_ALLOWED_ORIGINS')) {
|
|
return false;
|
|
}
|
|
|
|
foreach (IGDB_ALLOWED_ORIGINS as $allowed) {
|
|
|
|
// Wildcards verarbeiten: *.domain.tld oder localhost:*
|
|
if (strpos($allowed, '*') !== false) {
|
|
$pattern = '#^' . str_replace(
|
|
['*', '.', ':'],
|
|
['.*', '\.', '\:'],
|
|
$allowed
|
|
) . '$#i';
|
|
|
|
if (preg_match($pattern, $origin)) {
|
|
return true;
|
|
}
|
|
} else {
|
|
if (strcasecmp($allowed, $origin) === 0) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Set CORS headers if origin matches
|
|
$origin = $_SERVER['HTTP_ORIGIN'] ?? null;
|
|
if ($origin && origin_allowed($origin)) {
|
|
header('Access-Control-Allow-Origin: ' . $origin);
|
|
header('Vary: Origin');
|
|
}
|
|
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
|
|
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
|
|
|
|
// Preflight
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
http_response_code(204);
|
|
exit;
|
|
}
|
|
|
|
// =====================================================
|
|
// HELPERS
|
|
// =====================================================
|
|
|
|
function respond($data, int $status = 200): void
|
|
{
|
|
http_response_code($status);
|
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
|
exit;
|
|
}
|
|
|
|
function error_response($msg, int $status = 400): void
|
|
{
|
|
if (is_string($msg)) {
|
|
$msg = ['error' => $msg];
|
|
}
|
|
respond($msg, $status);
|
|
}
|
|
|
|
// =====================================================
|
|
// DATABASE
|
|
// =====================================================
|
|
|
|
function getDb(): PDO
|
|
{
|
|
static $pdo = null;
|
|
if ($pdo !== null) {
|
|
return $pdo;
|
|
}
|
|
|
|
$dsn = sprintf(
|
|
'mysql:host=%s;dbname=%s;charset=utf8mb4',
|
|
DATABASE_HOST,
|
|
DATABASE_NAME
|
|
);
|
|
|
|
try {
|
|
$pdo = new PDO($dsn, DATABASE_USER, DATABASE_PASSWORD, [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
]);
|
|
} catch (PDOException $e) {
|
|
error_response('DB connection failed: ' . $e->getMessage(), 500);
|
|
}
|
|
|
|
return $pdo;
|
|
}
|
|
|
|
// =====================================================
|
|
// LOCALIZATION SUPPORT (Tabelle igdb_localizations)
|
|
// =====================================================
|
|
|
|
function getLocalization(int $igdbId, string $lang = 'de'): ?array
|
|
{
|
|
$pdo = getDb();
|
|
$stmt = $pdo->prepare(
|
|
'SELECT * FROM igdb_localizations WHERE igdb_id = :id AND lang = :lang LIMIT 1'
|
|
);
|
|
$stmt->execute([
|
|
':id' => $igdbId,
|
|
':lang' => $lang,
|
|
]);
|
|
$row = $stmt->fetch();
|
|
return $row ?: null;
|
|
}
|
|
|
|
function saveLocalization(
|
|
int $igdbId,
|
|
string $lang,
|
|
?string $title,
|
|
?string $summary,
|
|
?string $storyline,
|
|
?int $userId
|
|
): array {
|
|
$pdo = getDb();
|
|
|
|
$sql = '
|
|
INSERT INTO igdb_localizations (igdb_id, lang, title, summary, storyline, user_id)
|
|
VALUES (:id, :lang, :title, :summary, :storyline, :user_id)
|
|
ON DUPLICATE KEY UPDATE
|
|
title = VALUES(title),
|
|
summary = VALUES(summary),
|
|
storyline = VALUES(storyline),
|
|
user_id = VALUES(user_id),
|
|
updated_at = CURRENT_TIMESTAMP
|
|
';
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute([
|
|
':id' => $igdbId,
|
|
':lang' => $lang,
|
|
':title' => $title,
|
|
':summary' => $summary,
|
|
':storyline' => $storyline,
|
|
':user_id' => $userId,
|
|
]);
|
|
|
|
return getLocalization($igdbId, $lang);
|
|
}
|
|
|
|
// =====================================================
|
|
// GAMES IN MULTIMEDIAFLUTTER (Tabelle game)
|
|
// =====================================================
|
|
|
|
function saveGameStatus(
|
|
int $igdbId,
|
|
string $name,
|
|
?string $originalName,
|
|
int $status,
|
|
?string $note = null
|
|
): array {
|
|
$pdo = getDb();
|
|
|
|
$sql = '
|
|
INSERT INTO game (igdb_id, name, original_name, status, note)
|
|
VALUES (:igdb_id, :name, :original_name, :status, :note)
|
|
ON DUPLICATE KEY UPDATE
|
|
name = VALUES(name),
|
|
original_name = VALUES(original_name),
|
|
status = VALUES(status),
|
|
note = VALUES(note),
|
|
updated_at = CURRENT_TIMESTAMP
|
|
';
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute([
|
|
':igdb_id' => $igdbId,
|
|
':name' => $name,
|
|
':original_name'=> $originalName,
|
|
':status' => $status,
|
|
':note' => $note,
|
|
]);
|
|
|
|
$stmt = $pdo->prepare('SELECT * FROM game WHERE igdb_id = :id LIMIT 1');
|
|
$stmt->execute([':id' => $igdbId]);
|
|
return $stmt->fetch() ?: [];
|
|
}
|
|
|
|
function getGameByIgdbId(int $igdbId): ?array
|
|
{
|
|
$pdo = getDb();
|
|
$stmt = $pdo->prepare('SELECT * FROM game WHERE igdb_id = :id LIMIT 1');
|
|
$stmt->execute([':id' => $igdbId]);
|
|
return $stmt->fetch() ?: null;
|
|
}
|
|
|
|
// =====================================================
|
|
// IMAGE URL BUILDER
|
|
// =====================================================
|
|
|
|
function igdbImageUrl(?string $imageId, string $sizeTag = 't_cover_big'): ?string
|
|
{
|
|
if (!$imageId) {
|
|
return null;
|
|
}
|
|
|
|
return sprintf(
|
|
'https://images.igdb.com/igdb/image/upload/%s/%s.jpg',
|
|
$sizeTag,
|
|
$imageId
|
|
);
|
|
}
|
|
|
|
// =====================================================
|
|
// TWITCH TOKEN + IGDB REQUEST
|
|
// =====================================================
|
|
|
|
function getCachedToken(): ?array
|
|
{
|
|
if (!file_exists(IGDB_TOKEN_CACHE_FILE)) {
|
|
return null;
|
|
}
|
|
|
|
$json = file_get_contents(IGDB_TOKEN_CACHE_FILE);
|
|
$data = json_decode($json, true);
|
|
|
|
if (!$data || time() >= ($data['expires_at'] ?? 0)) {
|
|
return null;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
function saveToken(array $tokenData): void
|
|
{
|
|
$expiresIn = (int)($tokenData['expires_in'] ?? 0);
|
|
$tokenData['expires_at'] = time() + $expiresIn - 60; // 60s Puffer
|
|
|
|
file_put_contents(
|
|
IGDB_TOKEN_CACHE_FILE,
|
|
json_encode($tokenData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
|
|
);
|
|
}
|
|
|
|
function fetchNewToken(): array
|
|
{
|
|
$postFields = [
|
|
'client_id' => TWITCH_CLIENT_ID,
|
|
'client_secret' => TWITCH_CLIENT_SECRET,
|
|
'grant_type' => 'client_credentials',
|
|
];
|
|
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => TWITCH_TOKEN_URL,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => http_build_query($postFields),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
$data = json_decode($response, true);
|
|
|
|
if ($status !== 200) {
|
|
error_response([
|
|
'message' => 'Failed to fetch token from Twitch',
|
|
'status' => $status,
|
|
'body' => $data,
|
|
], 500);
|
|
}
|
|
|
|
saveToken($data);
|
|
return $data;
|
|
}
|
|
|
|
function getAccessToken(): string
|
|
{
|
|
$cached = getCachedToken();
|
|
if ($cached) {
|
|
return $cached['access_token'];
|
|
}
|
|
|
|
$new = fetchNewToken();
|
|
return $new['access_token'];
|
|
}
|
|
|
|
function igdbRequest(string $endpoint, string $body)
|
|
{
|
|
$accessToken = getAccessToken();
|
|
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => IGDB_BASE_URL . $endpoint,
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => $body,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Client-ID: ' . TWITCH_CLIENT_ID,
|
|
'Authorization: Bearer ' . $accessToken,
|
|
'Accept: application/json',
|
|
],
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
$data = json_decode($response, true);
|
|
|
|
if ($status !== 200) {
|
|
error_response([
|
|
'message' => 'IGDB returned error',
|
|
'status' => $status,
|
|
'body' => $data,
|
|
], 500);
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
/**
|
|
* Interne Hilfsfunktion: macht einen Wikipedia-API-Call mit einem Suchstring
|
|
* und gibt das erste Page-Objekt (inkl. extract) zurück.
|
|
*/
|
|
function wikiApiSearchWithExtract(string $searchQuery): ?array
|
|
{
|
|
$params = [
|
|
'action' => 'query',
|
|
'generator' => 'search',
|
|
'gsrsearch' => $searchQuery,
|
|
'gsrlimit' => 1,
|
|
'prop' => 'extracts',
|
|
'exintro' => 1,
|
|
'explaintext' => 1,
|
|
'format' => 'json',
|
|
'utf8' => 1,
|
|
];
|
|
|
|
$url = WIKI_DE_API_URL . '?' . http_build_query($params, '', '&');
|
|
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_HTTPHEADER => [
|
|
'User-Agent: ' . WIKI_USER_AGENT,
|
|
],
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
if ($response === false) {
|
|
curl_close($ch);
|
|
return null;
|
|
}
|
|
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($status !== 200) {
|
|
return null;
|
|
}
|
|
|
|
$data = json_decode($response, true);
|
|
if (!is_array($data) || empty($data['query']['pages'])) {
|
|
return null;
|
|
}
|
|
|
|
$pages = $data['query']['pages'];
|
|
$page = reset($pages);
|
|
|
|
if (empty($page['extract'])) {
|
|
return null;
|
|
}
|
|
|
|
// debug_url zum leichteren Debuggen
|
|
$page['debug_url'] = $url;
|
|
|
|
return $page;
|
|
}
|
|
|
|
/**
|
|
* Hochwertige DE-Zusammenfassung für einen Spieltitel holen.
|
|
*
|
|
* - Probiert mehrere Suchvarianten (Videospiel, Computerspiel, etc.)
|
|
* - Schneidet den Text auf ~600 Zeichen
|
|
* - Liefert Titel, Extract, URL + debug_url
|
|
*/
|
|
function wikiFetchGermanSummaryForTitle(string $gameTitle): ?array
|
|
{
|
|
$gameTitleTrimmed = trim($gameTitle);
|
|
|
|
// Verschiedene Suchmuster, um Spiele sauber zu treffen
|
|
$patterns = [
|
|
$gameTitleTrimmed . ' (Computerspiel)',
|
|
$gameTitleTrimmed . ' (Videospiel)',
|
|
$gameTitleTrimmed . ' Videospiel',
|
|
$gameTitleTrimmed, // Fallback: purer Titel
|
|
];
|
|
|
|
foreach ($patterns as $pattern) {
|
|
$page = wikiApiSearchWithExtract($pattern);
|
|
if ($page === null || empty($page['extract'])) {
|
|
continue;
|
|
}
|
|
|
|
$pageTitle = $page['title'] ?? $gameTitleTrimmed;
|
|
|
|
// einfache Heuristik: Title ohne Klammern vergleichen
|
|
$canonicalPageTitle = mb_strtolower(preg_replace('/\s*\(.*?\)\s*/u', '', $pageTitle), 'UTF-8');
|
|
$canonicalGameTitle = mb_strtolower($gameTitleTrimmed, 'UTF-8');
|
|
|
|
// Wenn der Titel gar nicht passt, nächsten Versuch → verbessert Qualität
|
|
if (mb_strpos($canonicalPageTitle, $canonicalGameTitle) === false &&
|
|
mb_strpos($canonicalGameTitle, $canonicalPageTitle) === false) {
|
|
// könnte z.B. „Zelda (Band)“ sein → skip
|
|
continue;
|
|
}
|
|
|
|
$extract = $page['extract'];
|
|
$short = mb_substr($extract, 0, 600, 'UTF-8');
|
|
|
|
return [
|
|
'pageid' => (int)($page['pageid'] ?? 0),
|
|
'title' => $pageTitle,
|
|
'extract' => $short,
|
|
'url' => 'https://de.wikipedia.org/?curid=' . (int)($page['pageid'] ?? 0),
|
|
'debug_url' => $page['debug_url'] ?? null,
|
|
];
|
|
}
|
|
|
|
// Keine passende Seite gefunden
|
|
return null;
|
|
}
|
|
|
|
// =====================================================
|
|
// ROUTING
|
|
// =====================================================
|
|
|
|
$action = $_GET['action'] ?? 'ping';
|
|
|
|
switch ($action) {
|
|
|
|
// ---------------------------------------
|
|
case 'ping':
|
|
respond(['status' => 'ok']);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'search':
|
|
$query = $_GET['query'] ?? '';
|
|
$limit = (int)($_GET['limit'] ?? 10);
|
|
$page = (int)($_GET['page'] ?? 1);
|
|
$lang = $_GET['lang'] ?? 'en';
|
|
|
|
$checkExternal = isset($_GET['check_external'])
|
|
? ((int)$_GET['check_external'] === 1)
|
|
: false;
|
|
|
|
$debug = isset($_GET['debug'])
|
|
? ((int)$_GET['debug'] === 1)
|
|
: false;
|
|
|
|
if ($query === '') {
|
|
error_response('Missing "query"', 400);
|
|
}
|
|
|
|
if ($limit < 1 || $limit > 50) {
|
|
$limit = 10;
|
|
}
|
|
if ($page < 1) {
|
|
$page = 1;
|
|
}
|
|
|
|
$offset = ($page - 1) * $limit;
|
|
|
|
$safeQuery = str_replace('"', '\\"', $query);
|
|
$body = sprintf(
|
|
'fields id,name,summary,first_release_date,cover.image_id; ' .
|
|
'limit %d; offset %d; search "%s";',
|
|
$limit,
|
|
$offset,
|
|
$safeQuery
|
|
);
|
|
|
|
$results = igdbRequest('/games', $body);
|
|
|
|
foreach ($results as &$g) {
|
|
// Cover-URL
|
|
$g['cover_url'] = isset($g['cover']['image_id'])
|
|
? igdbImageUrl($g['cover']['image_id'], 't_cover_big')
|
|
: null;
|
|
|
|
// eigener Status aus game-Tabelle
|
|
$localGame = getGameByIgdbId($g['id']);
|
|
$g['my_status'] = $localGame['status'] ?? null;
|
|
|
|
// eig. Lokalisierung aus DB (z.B. de)
|
|
$hasLoc = false;
|
|
if ($lang !== 'en') {
|
|
$loc = getLocalization($g['id'], $lang);
|
|
if ($loc !== null) {
|
|
$hasLoc = true;
|
|
|
|
if (!empty($loc['title'])) {
|
|
$g['name'] = $loc['title'];
|
|
}
|
|
if (!empty($loc['summary'])) {
|
|
$g['summary'] = $loc['summary'];
|
|
}
|
|
}
|
|
}
|
|
$g['has_localization'] = $hasLoc;
|
|
|
|
// Wikipedia-Felder vorbereiten
|
|
$g['has_external_de'] = false;
|
|
$g['external_de_source'] = null;
|
|
$g['external_de_summary'] = null;
|
|
$g['external_de_url'] = null;
|
|
|
|
if ($debug) {
|
|
$g['wiki_debug'] = [];
|
|
}
|
|
|
|
// Wikipedia nur bei lang=de, wenn keine eigene Lokalisierung da ist
|
|
if ($checkExternal && $lang === 'de' && !$hasLoc) {
|
|
$wiki = wikiFetchGermanSummaryForTitle($g['name']);
|
|
|
|
if ($debug) {
|
|
$g['wiki_debug']['used_title'] = $g['name'];
|
|
$g['wiki_debug']['wiki_result'] = $wiki;
|
|
}
|
|
|
|
if ($wiki !== null && !empty($wiki['extract'])) {
|
|
$g['has_external_de'] = true;
|
|
$g['external_de_source'] = 'wikipedia';
|
|
$g['external_de_summary'] = $wiki['extract'];
|
|
$g['external_de_url'] = $wiki['url'];
|
|
|
|
// Direkt als Summary verwenden (Qualitäts-Boost)
|
|
$g['summary'] = $wiki['extract'];
|
|
|
|
// OPTIONAL: den Titel auf Wikipedia-Titel setzen:
|
|
// $g['name'] = $wiki['title'];
|
|
}
|
|
}
|
|
}
|
|
unset($g);
|
|
|
|
respond([
|
|
'source' => 'igdb',
|
|
'mode' => 'search',
|
|
'lang' => $lang,
|
|
'query' => $query,
|
|
'page' => $page,
|
|
'limit' => $limit,
|
|
'offset' => $offset,
|
|
'results_count' => count($results),
|
|
'results' => $results,
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'details':
|
|
$idParam = $_GET['id'] ?? '';
|
|
$lang = $_GET['lang'] ?? 'en';
|
|
|
|
$checkExternal = isset($_GET['check_external'])
|
|
? ((int)$_GET['check_external'] === 1)
|
|
: false;
|
|
|
|
if ($idParam === '') {
|
|
error_response('Missing "id"', 400);
|
|
}
|
|
|
|
$id = (int)$idParam;
|
|
if ($id <= 0) {
|
|
error_response('Invalid "id"', 400);
|
|
}
|
|
|
|
$body = sprintf(
|
|
'fields ' .
|
|
'id,' .
|
|
'name,' .
|
|
'summary,' .
|
|
'storyline,' .
|
|
'first_release_date,' .
|
|
'genres.name,' .
|
|
'platforms.name,' .
|
|
'cover.image_id,' .
|
|
'screenshots.image_id,' .
|
|
'involved_companies.company.name,' .
|
|
'websites.url,' .
|
|
'websites.category,' .
|
|
'age_ratings.rating,' .
|
|
'age_ratings.category,' .
|
|
'language_supports.language;' .
|
|
' where id = %d;',
|
|
$id
|
|
);
|
|
|
|
$results = igdbRequest('/games', $body);
|
|
|
|
if (empty($results)) {
|
|
error_response('Game not found', 404);
|
|
}
|
|
|
|
$game = $results[0];
|
|
|
|
// Cover-URL
|
|
$game['cover_url'] = isset($game['cover']['image_id'])
|
|
? igdbImageUrl($game['cover']['image_id'], 't_cover_big')
|
|
: null;
|
|
|
|
// Screenshot-URLs
|
|
$game['screenshot_urls'] = [];
|
|
if (!empty($game['screenshots']) && is_array($game['screenshots'])) {
|
|
foreach ($game['screenshots'] as $s) {
|
|
if (!empty($s['image_id'])) {
|
|
$game['screenshot_urls'][] =
|
|
igdbImageUrl($s['image_id'], 't_screenshot_big');
|
|
}
|
|
}
|
|
}
|
|
|
|
// eigener Status / Notiz
|
|
$localGame = getGameByIgdbId($id);
|
|
if ($localGame !== null) {
|
|
$game['my_status'] = (int)$localGame['status'];
|
|
$game['my_note'] = $localGame['note'];
|
|
} else {
|
|
$game['my_status'] = null;
|
|
$game['my_note'] = null;
|
|
}
|
|
|
|
// eigene Lokalisierung (DB)
|
|
$hasLoc = false;
|
|
if ($lang !== 'en') {
|
|
$loc = getLocalization($id, $lang);
|
|
if ($loc !== null) {
|
|
$hasLoc = true;
|
|
|
|
if (!empty($loc['title'])) {
|
|
$game['name'] = $loc['title'];
|
|
}
|
|
if (!empty($loc['summary'])) {
|
|
$game['summary'] = $loc['summary'];
|
|
}
|
|
if (!empty($loc['storyline'])) {
|
|
$game['storyline'] = $loc['storyline'];
|
|
}
|
|
|
|
$game['localization'] = [
|
|
'lang' => $lang,
|
|
'source' => 'custom',
|
|
'id' => $loc['id'],
|
|
];
|
|
}
|
|
}
|
|
$game['has_localization'] = $hasLoc;
|
|
|
|
// Wikipedia-Fallback (DE), wenn keine eigene Lokalisierung existiert
|
|
$game['has_external_de'] = false;
|
|
$game['external_de_source'] = null;
|
|
$game['external_de_summary'] = null;
|
|
$game['external_de_url'] = null;
|
|
|
|
if ($checkExternal && $lang === 'de' && !$hasLoc) {
|
|
$wiki = wikiFetchGermanSummaryForTitle($game['name']);
|
|
|
|
if ($wiki !== null && !empty($wiki['extract'])) {
|
|
$game['has_external_de'] = true;
|
|
$game['external_de_source'] = 'wikipedia';
|
|
$game['external_de_summary'] = $wiki['extract'];
|
|
$game['external_de_url'] = $wiki['url'];
|
|
|
|
// Summary-Fallback auf DE-Text
|
|
$game['summary'] = $wiki['extract'];
|
|
|
|
// OPTIONAL: Name anpassen
|
|
// $game['name'] = $wiki['title'];
|
|
}
|
|
}
|
|
|
|
respond([
|
|
'source' => 'igdb',
|
|
'mode' => 'details',
|
|
'lang' => $lang,
|
|
'id' => $id,
|
|
'game' => $game,
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'get_localization':
|
|
$idParam = $_GET['id'] ?? '';
|
|
$lang = $_GET['lang'] ?? 'de';
|
|
|
|
if ($idParam === '') {
|
|
error_response('Missing "id"', 400);
|
|
}
|
|
|
|
$igdbId = (int)$idParam;
|
|
if ($igdbId <= 0) {
|
|
error_response('Invalid "id"', 400);
|
|
}
|
|
|
|
$loc = getLocalization($igdbId, $lang);
|
|
|
|
respond([
|
|
'found' => (bool)$loc,
|
|
'localization' => $loc,
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'submit_localization':
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
error_response('Use POST', 405);
|
|
}
|
|
|
|
$raw = file_get_contents('php://input');
|
|
$data = json_decode($raw, true);
|
|
if (!is_array($data)) {
|
|
error_response('Invalid JSON body', 400);
|
|
}
|
|
|
|
$igdbId = (int)($data['igdb_id'] ?? 0);
|
|
$lang = trim($data['lang'] ?? 'de');
|
|
$title = isset($data['title']) ? trim($data['title']) : '';
|
|
$summary= isset($data['summary']) ? trim($data['summary']) : '';
|
|
$story = isset($data['storyline']) ? trim($data['storyline']) : '';
|
|
$userId = isset($data['user_id']) ? (int)$data['user_id'] : null;
|
|
|
|
if ($igdbId <= 0) {
|
|
error_response('Invalid "igdb_id"', 400);
|
|
}
|
|
|
|
if ($lang === '') {
|
|
$lang = 'de';
|
|
}
|
|
|
|
$loc = saveLocalization(
|
|
$igdbId,
|
|
$lang,
|
|
$title ?: null,
|
|
$summary ?: null,
|
|
$story ?: null,
|
|
$userId
|
|
);
|
|
|
|
respond([
|
|
'success' => true,
|
|
'localization' => $loc,
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'set_game_status':
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
error_response('Use POST', 405);
|
|
}
|
|
|
|
$raw = file_get_contents('php://input');
|
|
$data = json_decode($raw, true);
|
|
if (!is_array($data)) {
|
|
error_response('Invalid JSON body', 400);
|
|
}
|
|
|
|
$igdbId = (int)($data['igdb_id'] ?? 0);
|
|
$name = isset($data['name']) ? trim($data['name']) : '';
|
|
$orig = isset($data['original_name']) ? trim($data['original_name']) : '';
|
|
$status = (int)($data['status'] ?? 0);
|
|
$note = isset($data['note']) ? trim($data['note']) : '';
|
|
|
|
if ($igdbId <= 0) {
|
|
error_response('Invalid "igdb_id"', 400);
|
|
}
|
|
if ($name === '') {
|
|
error_response('Missing "name"', 400);
|
|
}
|
|
if ($status < 0 || $status > 2) {
|
|
error_response('Invalid "status" (0, 1, 2 allowed)', 400);
|
|
}
|
|
|
|
$game = saveGameStatus(
|
|
$igdbId,
|
|
$name,
|
|
$orig !== '' ? $orig : null,
|
|
$status,
|
|
$note !== '' ? $note : null
|
|
);
|
|
|
|
respond([
|
|
'success' => true,
|
|
'game' => $game,
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
case 'get_game':
|
|
$idParam = $_GET['igdb_id'] ?? '';
|
|
if ($idParam === '') {
|
|
error_response('Missing "igdb_id"', 400);
|
|
}
|
|
|
|
$igdbId = (int)$idParam;
|
|
if ($igdbId <= 0) {
|
|
error_response('Invalid "igdb_id"', 400);
|
|
}
|
|
|
|
$game = getGameByIgdbId($igdbId);
|
|
|
|
respond([
|
|
'found' => (bool)$game,
|
|
'game' => $game,
|
|
]);
|
|
break;
|
|
|
|
case 'wiki_test':
|
|
$title = $_GET['title'] ?? '';
|
|
if ($title === '') {
|
|
error_response('Missing "title"', 400);
|
|
}
|
|
|
|
// Wir bauen die URL sichtbar zusammen
|
|
$params = [
|
|
'action' => 'query',
|
|
'generator' => 'search',
|
|
'gsrsearch' => $title . ' Videospiel',
|
|
'gsrlimit' => 1,
|
|
'prop' => 'extracts',
|
|
'exintro' => 1,
|
|
'explaintext' => 1,
|
|
'format' => 'json',
|
|
'utf8' => 1,
|
|
];
|
|
|
|
$url = WIKI_DE_API_URL . '?' . http_build_query($params, '', '&');
|
|
|
|
// Wikipedia anfragen
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_URL => $url,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_HTTPHEADER => [
|
|
'User-Agent: ' . WIKI_USER_AGENT,
|
|
],
|
|
]);
|
|
|
|
$response = curl_exec($ch);
|
|
$curlErr = curl_error($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
// Parse versuchen
|
|
$json = json_decode($response, true);
|
|
|
|
respond([
|
|
'title' => $title,
|
|
'used_url' => $url, // <- DIE WICHTIGE URL
|
|
'http_status' => $status,
|
|
'curl_error' => $curlErr,
|
|
'raw_response' => $response, // <- Rohdaten
|
|
'parsed_json' => $json, // <- Versuch zu decodieren
|
|
]);
|
|
break;
|
|
|
|
// ---------------------------------------
|
|
default:
|
|
error_response('Unknown action: ' . $action, 404);
|
|
}
|