Files
whattoplay/workers/steam-proxy.js

133 lines
3.0 KiB
JavaScript

/**
* Cloudflare Worker: Steam API CORS Proxy
* Erlaubt iPhone App, Steam Web API aufzurufen
*/
export default {
async fetch(request, env, ctx) {
// CORS preflight
if (request.method === "OPTIONS") {
return handleCORS();
}
// Nur POST /api/steam/refresh erlauben
const url = new URL(request.url);
if (request.method === "POST" && url.pathname === "/api/steam/refresh") {
return handleSteamRefresh(request);
}
// 404 für alle anderen Routes
return new Response("Not Found", { status: 404 });
},
};
/**
* Handles Steam API refresh request
*/
async function handleSteamRefresh(request) {
try {
// Parse request body
const body = await request.json();
const { apiKey, steamId } = body;
if (!apiKey || !steamId) {
return jsonResponse(
{ error: "apiKey and steamId are required" },
{ status: 400 },
);
}
// Fetch games from Steam API
const { games, count } = await fetchSteamGames(apiKey, steamId);
return jsonResponse({ games, count });
} catch (error) {
console.error("Steam API Error:", error);
return jsonResponse(
{ error: error.message || "Internal Server Error" },
{ status: 500 },
);
}
}
/**
* Fetches games from Steam Web API
*/
async function fetchSteamGames(apiKey, steamId) {
// Build Steam API URL
const url = new URL(
"https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/",
);
url.searchParams.set("key", apiKey);
url.searchParams.set("steamid", steamId);
url.searchParams.set("include_appinfo", "true");
url.searchParams.set("include_played_free_games", "true");
// Call Steam API
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Steam API Error: ${response.status} ${response.statusText}`,
);
}
const data = await response.json();
const rawGames = data.response?.games ?? [];
// Format games
const games = rawGames.map((game) => ({
id: `steam-${game.appid}`,
title: game.name,
source: "steam",
sourceId: String(game.appid),
platform: "PC",
lastPlayed: game.rtime_last_played
? new Date(game.rtime_last_played * 1000).toISOString().slice(0, 10)
: null,
playtimeHours: Math.round((game.playtime_forever / 60) * 10) / 10,
url: `https://store.steampowered.com/app/${game.appid}`,
}));
return {
games,
count: games.length,
};
}
/**
* CORS preflight response
*/
function handleCORS() {
return new Response(null, {
status: 204,
headers: getCORSHeaders(),
});
}
/**
* JSON response with CORS headers
*/
function jsonResponse(data, options = {}) {
return new Response(JSON.stringify(data), {
...options,
headers: {
"Content-Type": "application/json",
...getCORSHeaders(),
...options.headers,
},
});
}
/**
* Get CORS headers for GitHub Pages
*/
function getCORSHeaders() {
return {
"Access-Control-Allow-Origin": "*", // Allow all origins (user's own worker)
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Max-Age": "86400", // 24 hours
};
}