diff --git a/services/cloudflare-workers/servers-api/README.md b/services/cloudflare-workers/servers-api/README.md new file mode 100644 index 0000000..b4316f9 --- /dev/null +++ b/services/cloudflare-workers/servers-api/README.md @@ -0,0 +1,27 @@ +# servers-api Cloudflare Worker + +Proxies Pterodactyl server status to the Firefrost website with CORS support. + +## What it does +- Fetches all servers from Pterodactyl Panel API +- Returns online/offline status and player counts +- Handles CORS for firefrostgaming.com + +## Environment Variables (set in Cloudflare dashboard) +- `PANEL_URL` — https://panel.firefrostgaming.com +- `CLIENT_API_KEY` — Pterodactyl client API key + +## Deploy +```bash +wrangler deploy --name servers-api +``` +Or via API: +```bash +curl -X PUT "https://api.cloudflare.com/client/v4/accounts/b253db7a7ff86b35307206dac9476c89/workers/scripts/servers-api" \ + -H "Authorization: Bearer cfat_PIavSCe5FFNwv3Iu38phwlMz6634QXeXWRIJgtfh91a42940" \ + -F "index.js=@src/index.js;type=application/javascript+module" +``` + +## Recovered +Recovered from Cloudflare dashboard by Chronicler #91 on April 15, 2026. +Previously only existed in the dashboard — never in git (known gap). diff --git a/services/cloudflare-workers/servers-api/src/index.js b/services/cloudflare-workers/servers-api/src/index.js new file mode 100644 index 0000000..5661f07 --- /dev/null +++ b/services/cloudflare-workers/servers-api/src/index.js @@ -0,0 +1,84 @@ +export default { + async fetch(request, env) { + // Determine allowed origin + const origin = request.headers.get('Origin'); + const allowedOrigins = [ + 'https://firefrostgaming.com', + 'https://firefrost-website.pages.dev' + ]; + const allowedOrigin = allowedOrigins.includes(origin) ? origin : 'https://firefrostgaming.com'; + + // Handle CORS preflight + if (request.method === 'OPTIONS') { + return new Response(null, { + headers: { + 'Access-Control-Allow-Origin': allowedOrigin, + 'Access-Control-Allow-Methods': 'GET, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type' + } + }); + } + + const PANEL_URL = env.PANEL_URL; + const API_KEY = env.CLIENT_API_KEY; + + try { + // Fetch server list + const listResponse = await fetch(`${PANEL_URL}/api/client`, { + headers: { + 'Authorization': `Bearer ${API_KEY}`, + 'Accept': 'application/json' + } + }); + + const listData = await listResponse.json(); + + if (!listData.data) throw new Error("Failed to fetch server list"); + + // Fetch live stats for all servers + const serverPromises = listData.data.map(async (server) => { + const id = server.attributes.identifier; + + const statsResponse = await fetch(`${PANEL_URL}/api/client/servers/${id}/resources`, { + headers: { + 'Authorization': `Bearer ${API_KEY}`, + 'Accept': 'application/json' + } + }); + + const stats = await statsResponse.json(); + const isRunning = stats.attributes?.current_state === 'running'; + + return { + id: id, + name: server.attributes.name, + status: isRunning ? 'Online' : 'Offline', + players: isRunning ? (stats.attributes?.resources?.players || 0) : 0, + description: server.attributes.description + }; + }); + + const finalServers = await Promise.all(serverPromises); + + return new Response(JSON.stringify({ servers: finalServers }), { + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': allowedOrigin, + 'Cache-Control': 'public, s-maxage=60, max-age=60' + } + }); + + } catch (error) { + return new Response(JSON.stringify({ + error: "Servers temporarily unreachable", + servers: [] + }), { + status: 500, + headers: { + 'Content-Type': 'application/json', + 'Access-Control-Allow-Origin': allowedOrigin + } + }); + } + } +} diff --git a/services/cloudflare-workers/servers-api/wrangler.toml b/services/cloudflare-workers/servers-api/wrangler.toml new file mode 100644 index 0000000..893a3c5 --- /dev/null +++ b/services/cloudflare-workers/servers-api/wrangler.toml @@ -0,0 +1,7 @@ +name = "servers-api" +main = "src/index.js" +compatibility_date = "2024-01-01" + +# Environment variables set in Cloudflare dashboard: +# PANEL_URL = https://panel.firefrostgaming.com +# CLIENT_API_KEY = ptlc_vudB5oRaeoJGPip4fH5PDiymgi28uc39OjJsCbTDVEK