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',