= 400) { http_response_code($httpCode); echo json_encode(['error' => "HTTP $httpCode"]); exit; } return $result; } $panelHeaders = [ "Authorization: Bearer {$config['panel_key']}", "Accept: application/json" ]; if ($action === 'servers') { // List all servers header('Content-Type: application/json'); echo makeRequest("{$config['panel_url']}/api/client/servers", $panelHeaders); } elseif ($action === 'files') { // List files in server root header('Content-Type: application/json'); $id = urlencode($_GET['server'] ?? ''); echo makeRequest("{$config['panel_url']}/api/client/servers/{$id}/files/list", $panelHeaders); } elseif ($action === 'read') { // Read a specific file from server filesystem // Note: Pterodactyl returns raw text here, not JSON header('Content-Type: text/plain'); $id = urlencode($_GET['server'] ?? ''); $file = urlencode($_GET['file'] ?? ''); echo makeRequest("{$config['panel_url']}/api/client/servers/{$id}/files/contents?file={$file}", $panelHeaders); } elseif ($action === 'curseforge') { // Get latest CurseForge mod files (API key stays server-side) header('Content-Type: application/json'); $projectId = urlencode($_GET['project'] ?? ''); $cfHeaders = [ "x-api-key: {$config['cf_key']}", "Accept: application/json" ]; echo makeRequest("https://api.curseforge.com/v1/mods/{$projectId}/files?pageSize=1&sortField=5&sortOrder=desc", $cfHeaders); } else { header('Content-Type: application/json'); http_response_code(400); echo json_encode(['error' => 'Invalid action']); }