Files
whattoplay/scripts/fetch-gog.mjs

113 lines
3.2 KiB
JavaScript

import { mkdir, readFile, writeFile } from "node:fs/promises";
const loadConfig = async () => {
const configUrl = new URL("../config.local.json", import.meta.url);
try {
const raw = await readFile(configUrl, "utf-8");
return JSON.parse(raw);
} catch {
return {};
}
};
const sanitizeFileName = (value) => {
const normalized = value
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
return normalized || "spiel";
};
const fetchGogGames = async ({ userId, accessToken }) => {
if (!userId || !accessToken) {
console.warn("⚠️ GOG: Keine Credentials - Überspringe");
console.log(" → Für iOS/Web: Backend mit OAuth benötigt");
console.log(" → Development: Token aus Browser DevTools kopieren\n");
return [];
}
try {
// GOG Galaxy Library API (wie Heroic Launcher)
const url = `https://galaxy-library.gog.com/users/${userId}/releases`;
const response = await fetch(url, {
headers: {
Authorization: `Bearer ${accessToken}`,
"User-Agent": "WhatToPlay/1.0",
},
});
if (!response.ok) {
throw new Error(`GOG API Fehler: ${response.status}`);
}
const payload = await response.json();
// Galaxy API gibt items zurück, nicht owned
return payload.items || [];
} catch (error) {
console.error("GOG API-Aufruf fehlgeschlagen:", error.message);
console.log("💡 Tipp: Token abgelaufen? Neu aus gog.com holen\n");
return [];
}
};
const buildGogEntry = (game) => ({
// Galaxy Library API gibt external_id (GOG Product ID)
id: String(game.external_id || game.id),
title: game.title || `GOG Game ${game.external_id}`,
platform: "PC",
lastPlayed: game.date_created
? new Date(game.date_created * 1000).toISOString()
: null,
playtimeHours: 0, // Galaxy API hat keine Spielzeit in /releases endpoint
tags: [],
url: `https://www.gog.com/game/${game.external_id}`,
});
const buildTextFile = (entry) => {
const lines = [
`Titel: ${entry.title}`,
`GOG ID: ${entry.id}`,
`Zuletzt gespielt: ${entry.lastPlayed ?? "-"}`,
`Spielzeit (h): ${entry.playtimeHours ?? 0}`,
`Store: ${entry.url}`,
"Quelle: gog",
];
return lines.join("\n") + "\n";
};
const writeOutputs = async (entries) => {
const dataDir = new URL("../public/data/", import.meta.url);
const textDir = new URL("../public/data/gog-text/", import.meta.url);
await mkdir(dataDir, { recursive: true });
await mkdir(textDir, { recursive: true });
const jsonPath = new URL("gog.json", dataDir);
await writeFile(jsonPath, JSON.stringify(entries, null, 2) + "\n", "utf-8");
await Promise.all(
entries.map(async (entry) => {
const fileName = `${sanitizeFileName(entry.title)}__${entry.id}.txt`;
const filePath = new URL(fileName, textDir);
await writeFile(filePath, buildTextFile(entry), "utf-8");
}),
);
};
const run = async () => {
const config = await loadConfig();
const userId = config.gog?.userId || process.env.GOG_USER_ID;
const accessToken = config.gog?.accessToken || process.env.GOG_ACCESS_TOKEN;
const games = await fetchGogGames({ userId, accessToken });
const entries = games.map(buildGogEntry);
await writeOutputs(entries);
console.log(`GOG-Export fertig: ${entries.length} Spiele.`);
};
run().catch((error) => {
console.error(error);
process.exit(1);
});