diff --git a/config.js b/config.js new file mode 100644 index 0000000..32d8d97 --- /dev/null +++ b/config.js @@ -0,0 +1,51 @@ +// config.js - Zentrale Konfiguration für WhoPays App + +export const CONFIG = { + A: { + name: "Lumpia", // Name Marc + colorHex: "#6495ED", // Farbe: Blau + colorDiscord: 0x6495ed, // Discord Embed + icon: "a.png", // Profilbild + background: "bgA.jpg" // Hintergrundbild + }, + B: { + name: "Pierogi", // Name Laila + colorHex: "#3C0061", // Farbe: Lila + colorDiscord: 0x3C0061c, // Discord Embed + icon: "b.png", // Profilbild + background: "bgB.jpg" // Hintergrundbild + } +}; + +// Discord Webhook URL +export const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL + || "https://discord.com/api/webhooks/1450872860607381515/zRbiXOykKPUfLJ_H87wD2OxQJPLdro6yQzU2T48Pg4fxSNaXEqBFgxdHGTiIDmmKGHIF"; + +// Server URL (für Discord Thumbnails) +export const PUBLIC_BASE_URL = process.env.PUBLIC_BASE_URL + || "http://localhost:3000"; + +// Port +export const PORT = process.env.PORT || 3000; + +/* + * ANLEITUNG ZUM ANPASSEN: + * + * 1. Namen ändern: + * name: "DeinName" + * + * 2. Farben ändern (Web und Discord müssen gleich sein): + * colorHex: "#3498db" // Hex-Format für Web + * colorDiscord: 0x3498db // Hex ohne # für Discord + * + * Beispiele: + * Blau: colorHex: "#3498db", colorDiscord: 0x3498db + * Lila: colorHex: "#9b59b6", colorDiscord: 0x9b59b6 + * Orange: colorHex: "#e67e22", colorDiscord: 0xe67e22 + * Pink: colorHex: "#e91e63", colorDiscord: 0xe91e63 + * + * 3. Bilder ändern: + * icon: "mein-bild.png" + * background: "mein-hintergrund.jpg" + * (Dateien müssen in /root/whopays/img/ liegen!) + */ \ No newline at end of file diff --git a/public/index.html b/public/index.html index 193d65b..6157700 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,6 @@ - diff --git a/public/script.js b/public/script.js index cc960a8..3a6e843 100644 --- a/public/script.js +++ b/public/script.js @@ -6,6 +6,9 @@ const lastReasonBox = document.getElementById("lastReasonBox"); const lastReasonText = document.getElementById("lastReasonText"); const mainContent = document.getElementById("mainContent"); +// Config wird vom Server geladen +let CONFIG = null; + // Preload images to prevent flickering const imageCache = {}; function preloadImage(src) { @@ -25,14 +28,44 @@ function preloadImage(src) { }); } +// Config vom Server laden +async function loadConfig() { + try { + const res = await fetch("/config"); + CONFIG = await res.json(); + console.log("✅ Config geladen:", CONFIG); + return CONFIG; + } catch (err) { + console.error("❌ Fehler beim Laden der Config:", err); + // Fallback zur alten Konfiguration + CONFIG = { + A: { + name: "Honey", + colorHex: "#2ecc71", + icon: "a.png", + background: "bgA.jpg" + }, + B: { + name: "Kirby", + colorHex: "#e74c3c", + icon: "b.png", + background: "bgB.jpg" + } + }; + return CONFIG; + } +} + // Preload all images on page load async function preloadAllImages() { + if (!CONFIG) await loadConfig(); + try { await Promise.all([ - preloadImage('img/a.png'), - preloadImage('img/b.png'), - preloadImage('img/bgA.jpg'), - preloadImage('img/bgB.jpg') + preloadImage(`img/${CONFIG.A.icon}`), + preloadImage(`img/${CONFIG.B.icon}`), + preloadImage(`img/${CONFIG.A.background}`), + preloadImage(`img/${CONFIG.B.background}`) ]); console.log("✅ Alle Bilder vorgeladen"); } catch (err) { @@ -41,7 +74,8 @@ async function preloadAllImages() { } async function loadStatus() { - // Preload images first + // Config und Bilder laden + await loadConfig(); await preloadAllImages(); const res = await fetch("/status"); @@ -63,10 +97,16 @@ async function loadStatus() { } function setBackgroundAndImage(person, animate = true) { - const file = person === "A" ? "img/a.png" : "img/b.png"; - const label = person === "A" ? "Lumpia" : "Pierogi"; - const bgImage = person === "A" ? "url('img/bgA.jpg')" : "url('img/bgB.jpg')"; - const nameColor = person === "A" ? "#4B0082" : "#DAA520"; + if (!CONFIG) { + console.error("Config nicht geladen!"); + return; + } + + const personConfig = CONFIG[person]; + const file = `img/${personConfig.icon}`; + const label = personConfig.name; + const bgImage = `url('img/${personConfig.background}')`; + const nameColor = personConfig.colorHex; // Set background immediately (smooth transition via CSS) document.body.style.backgroundImage = bgImage; diff --git a/server.js b/server.js index bb91c11..cf07632 100644 --- a/server.js +++ b/server.js @@ -2,6 +2,7 @@ import express from "express"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; +import { CONFIG, DISCORD_WEBHOOK_URL, PUBLIC_BASE_URL, PORT } from "./config.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -37,25 +38,6 @@ app.use(express.static(path.join(__dirname, "public"), { const stateFile = path.join(__dirname, "state.json"); -// -------------------- -// Konfiguration -// -------------------- -const CONFIG = { - A: { - name: "Marc", - color: 0x2ecc71, - icon: "a.png" - }, - B: { - name: "Laila", - color: 0xe74c3c, - icon: "b.png" - } -}; - -const PUBLIC_BASE_URL = process.env.PUBLIC_BASE_URL || "http://localhost:3000"; -const DISCORD_WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL || "https://discord.com/api/webhooks/1450872860607381515/zRbiXOykKPUfLJ_H87wD2OxQJPLdro6yQzU2T48Pg4fxSNaXEqBFgxdHGTiIDmmKGHIF"; - // -------------------- // State Handling - MIT PERSISTENT lastReason // -------------------- @@ -107,12 +89,12 @@ async function sendDiscordEmbed(previousKey, currentKey, reason) { const fields = [ { - name: "Payed", + name: "Paid", value: previous.name, inline: true }, { - name: "Nows turn", + name: "Now's turn", value: current.name, inline: true } @@ -128,8 +110,8 @@ async function sendDiscordEmbed(previousKey, currentKey, reason) { const embed = { title: "💸 Pay-Switch", - description: `*${current.name}** turn`, - color: current.color, + description: `**${current.name}**'s turn`, + color: current.colorDiscord, // ← Verwendet colorDiscord aus config.js thumbnail: { url: `${PUBLIC_BASE_URL}/img/${current.icon}` }, @@ -155,6 +137,26 @@ async function sendDiscordEmbed(previousKey, currentKey, reason) { // API Routes // -------------------- +// Config API endpoint - sendet Config an Frontend +app.get("/config", (req, res) => { + // Nur relevante Daten fürs Frontend senden + const frontendConfig = { + A: { + name: CONFIG.A.name, + colorHex: CONFIG.A.colorHex, + icon: CONFIG.A.icon, + background: CONFIG.A.background + }, + B: { + name: CONFIG.B.name, + colorHex: CONFIG.B.colorHex, + icon: CONFIG.B.icon, + background: CONFIG.B.background + } + }; + res.json(frontendConfig); +}); + app.get("/status", (req, res) => { const state = getState(); res.json(state); @@ -221,7 +223,6 @@ app.use((err, req, res, next) => { // -------------------- // Start // -------------------- -const PORT = process.env.PORT || 3000; app.listen(PORT, "0.0.0.0", () => { console.log(`\n✅ WhoPays läuft auf http://0.0.0.0:${PORT}\n`); console.log(`📁 Static files directory: ${path.join(__dirname, "public")}`); @@ -233,6 +234,10 @@ app.listen(PORT, "0.0.0.0", () => { console.log(` 👤 Wer zahlt: ${CONFIG[initialState.current].name}`); console.log(` 📝 Letzter Grund: ${initialState.lastReason || 'Keiner gespeichert'}`); + console.log(`\n👥 Konfigurierte Personen:`); + console.log(` A: ${CONFIG.A.name} (${CONFIG.A.colorHex})`); + console.log(` B: ${CONFIG.B.name} (${CONFIG.B.colorHex})`); + // Verify critical files exist const criticalFiles = [ 'public/index.html',