'Method not allowed']); exit; } $reportCode = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['report_code'] ?? ''); $language = strtolower(trim($_POST['language'] ?? 'en')); $language = in_array($language, ['en', 'de', 'fr', 'jp'], true) ? $language : 'en'; if (strlen($reportCode) < 1) { http_response_code(400); echo json_encode(['error' => 'Missing or invalid report_code']); exit; } if (empty($_SESSION['access_token'])) { http_response_code(401); echo json_encode(['error' => 'Not authenticated', 'reauth' => true]); exit; } if (($_SESSION['token_expires'] ?? 0) <= time()) { http_response_code(401); echo json_encode(['error' => 'Token expired', 'reauth' => true]); exit; } $query = <<<'GQL' query GetReportData($reportCode: String!) { reportData { report(code: $reportCode) { title startTime endTime fights { id name startTime endTime kill difficulty bossPercentage fightPercentage averageItemLevel lastPhase phaseTransitions { id startTime } } } } } GQL; $payload = json_encode([ 'query' => $query, 'variables' => ['reportCode' => $reportCode], ]); function localized_graphql_uri(string $language): string { $host = [ 'de' => 'de.fflogs.com', 'fr' => 'fr.fflogs.com', 'jp' => 'ja.fflogs.com', ][$language] ?? 'www.fflogs.com'; return preg_replace('#https://[^/]+#', 'https://' . $host, GRAPHQL_URI); } $acceptLanguage = $language === 'jp' ? 'ja' : $language; $ch = curl_init(localized_graphql_uri($language)); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $_SESSION['access_token'], 'Accept-Language: ' . $acceptLanguage, ], CURLOPT_SSL_VERIFYPEER => !DEV_MODE, ]); $body = curl_exec($ch); $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); if ($curlError) { http_response_code(502); echo json_encode(['error' => 'Network error: ' . $curlError]); exit; } $decoded = json_decode($body, true); if ($decoded === null) { http_response_code(502); echo json_encode(['error' => 'Invalid response from FFLogs', 'raw' => substr($body, 0, 500)]); exit; } if ($httpStatus === 401) { http_response_code(401); echo json_encode(['error' => 'FFLogs rejected token', 'reauth' => true]); exit; } http_response_code($httpStatus === 200 ? 200 : $httpStatus); echo $body; exit;