360 lines
7.7 KiB
Markdown
360 lines
7.7 KiB
Markdown
# 💸 WhoPays - Who Pays Next?
|
|
|
|
Ein einfaches, elegantes Tool um zu entscheiden, wer als nächstes zahlt - mit Discord-Benachrichtigungen und PWA-Support!
|
|
|
|

|
|

|
|

|
|
|
|
## 🎯 Features
|
|
|
|
- ✅ **Wechsel zwischen zwei Personen** - Einfacher Button-Klick
|
|
- 🎨 **Individuelle Farben & Namen** - Komplett anpassbar
|
|
- 📝 **Grund-Angabe** - Optional Grund für den Wechsel angeben
|
|
- 🔔 **Discord-Benachrichtigungen** - Automatische Webhooks mit farbigen Embeds
|
|
- 💾 **Persistenter Speicher** - Letzter Grund bleibt nach Container-Restart erhalten
|
|
- 📱 **PWA-Support** - Als App auf Handy & Desktop installierbar
|
|
- 🎭 **Animierte Übergänge** - Smooth Hintergrund- und Profilbild-Wechsel
|
|
- 🐳 **Docker-Ready** - Einfache Deployment mit Docker Compose
|
|
- 🔒 **Reverse-Proxy kompatibel** - Funktioniert mit Nginx, Caddy, Traefik, etc.
|
|
|
|
---
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### Voraussetzungen
|
|
|
|
- Docker & Docker Compose
|
|
- Discord Webhook URL (optional)
|
|
- Profilbilder (a.png, b.png)
|
|
- Hintergrundbilder (bgA.jpg, bgB.jpg)
|
|
|
|
### Installation
|
|
|
|
```bash
|
|
# 1. Repository klonen oder Dateien herunterladen
|
|
git clone https://github.com/dein-username/whopays.git
|
|
cd whopays
|
|
|
|
# 2. Bilder hinzufügen
|
|
cp deine-bilder/* img/
|
|
|
|
# 3. config.js anpassen (siehe Konfiguration)
|
|
nano config.js
|
|
|
|
# 4. Docker Container starten
|
|
docker-compose up -d
|
|
|
|
# 5. Öffne http://localhost:3000
|
|
```
|
|
|
|
**Das war's!** 🎉
|
|
|
|
---
|
|
|
|
## ⚙️ Konfiguration
|
|
|
|
### config.js - Zentrale Konfiguration
|
|
|
|
Alle Einstellungen sind in **einer** Datei:
|
|
|
|
```javascript
|
|
// config.js
|
|
export const CONFIG = {
|
|
A: {
|
|
name: "Alice", // Name Person A
|
|
colorHex: "#2ecc71", // Farbe im Web (Grün)
|
|
colorDiscord: 0x2ecc71, // Farbe in Discord (gleich!)
|
|
icon: "a.png", // Profilbild
|
|
background: "bgA.jpg" // Hintergrundbild
|
|
},
|
|
B: {
|
|
name: "Bob", // Name Person B
|
|
colorHex: "#e74c3c", // Farbe im Web (Rot)
|
|
colorDiscord: 0xe74c3c, // Farbe in Discord (gleich!)
|
|
icon: "b.png", // Profilbild
|
|
background: "bgB.jpg" // Hintergrundbild
|
|
}
|
|
};
|
|
|
|
// Discord Webhook (optional)
|
|
export const DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/...";
|
|
|
|
// Öffentliche URL (für Discord Thumbnails)
|
|
export const PUBLIC_BASE_URL = "https://your-domain.com";
|
|
```
|
|
|
|
### Farben ändern
|
|
|
|
```javascript
|
|
// Blau & Orange
|
|
A: { colorHex: "#3498db", colorDiscord: 0x3498db }
|
|
B: { colorHex: "#e67e22", colorDiscord: 0xe67e22 }
|
|
|
|
// Lila & Pink
|
|
A: { colorHex: "#9b59b6", colorDiscord: 0x9b59b6 }
|
|
B: { colorHex: "#e91e63", colorDiscord: 0xe91e63 }
|
|
|
|
// Türkis & Gold
|
|
A: { colorHex: "#1abc9c", colorDiscord: 0x1abc9c }
|
|
B: { colorHex: "#f39c12", colorDiscord: 0xf39c12 }
|
|
```
|
|
|
|
**Wichtig:** Hex-Farbe muss genau 6 Zeichen haben (0-9, A-F)!
|
|
|
|
---
|
|
|
|
## 📂 Projektstruktur
|
|
|
|
```
|
|
whopays/
|
|
├── config.js # Zentrale Konfiguration
|
|
├── server.js # Express Server
|
|
├── package.json # Node.js Dependencies
|
|
├── Dockerfile # Docker Build Instructions
|
|
├── docker-compose.yml # Docker Compose Config
|
|
├── state.json # Persistent State (auto-generiert)
|
|
│
|
|
└── public/ # Statische Dateien
|
|
├── index.html # Frontend HTML
|
|
├── script.js # Frontend JavaScript
|
|
├── style.css # CSS Animationen
|
|
├── manifest.json # PWA Manifest
|
|
├── service-worker.js # PWA Service Worker
|
|
│
|
|
└── img/ # Bilder
|
|
├── a.png # Profilbild Person A
|
|
├── b.png # Profilbild Person B
|
|
├── bgA.jpg # Hintergrund Person A
|
|
├── bgB.jpg # Hintergrund Person B
|
|
├── icon-192.png # PWA Icon (192x192)
|
|
└── icon-512.png # PWA Icon (512x512)
|
|
```
|
|
|
|
---
|
|
|
|
## 🐳 Docker Deployment
|
|
|
|
### docker-compose.yml
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
|
|
services:
|
|
whopays:
|
|
build: .
|
|
ports:
|
|
- "3000:3000"
|
|
environment:
|
|
- NODE_ENV=production
|
|
- PORT=3000
|
|
- PUBLIC_BASE_URL=https://your-domain.com
|
|
- DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/...";
|
|
volumes:
|
|
# Bilder (persistent)
|
|
- ./img:/app/public/img
|
|
|
|
# State (persistent über Neustarts)
|
|
- ./state.json:/app/state.json
|
|
|
|
restart: unless-stopped
|
|
```
|
|
|
|
### Befehle
|
|
|
|
```bash
|
|
# Container starten
|
|
docker-compose up -d
|
|
|
|
# Logs anschauen
|
|
docker-compose logs -f
|
|
|
|
# Container neustarten
|
|
docker-compose restart
|
|
|
|
# Container stoppen
|
|
docker-compose down
|
|
|
|
# Neu bauen (nach Code-Änderungen)
|
|
docker-compose down
|
|
docker-compose build --no-cache
|
|
docker-compose up -d
|
|
```
|
|
|
|
---
|
|
|
|
## 📱 PWA Installation
|
|
|
|
### iOS (Safari)
|
|
|
|
1. Öffne die Website in Safari
|
|
2. Tippe auf das **Teilen**-Symbol (⎙)
|
|
3. Scrolle und tippe **"Zum Home-Bildschirm"**
|
|
4. Tippe **"Hinzufügen"**
|
|
|
|
### Android (Chrome)
|
|
|
|
1. Öffne die Website in Chrome
|
|
2. Tippe auf **Menü** (⋮)
|
|
3. Tippe **"App installieren"**
|
|
4. Tippe **"Installieren"**
|
|
|
|
### Desktop (Chrome/Edge)
|
|
|
|
1. Öffne die Website
|
|
2. Klicke auf das **⊕ Icon** in der Adressleiste
|
|
3. Oder: Menü → "WhoPays installieren"
|
|
|
|
**Wichtig:** PWA funktioniert nur über HTTPS (oder localhost)!
|
|
|
|
---
|
|
|
|
## 🔒 Reverse Proxy Setup
|
|
|
|
### Nginx
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name whopays.your-domain.com;
|
|
|
|
# PWA Files - NO AUTH
|
|
location ~ ^/(service-worker\.js|manifest\.json)$ {
|
|
proxy_pass http://localhost:3000;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
add_header Service-Worker-Allowed "/" always;
|
|
}
|
|
|
|
# Main app
|
|
location / {
|
|
proxy_pass http://localhost:3000;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Caddy (Einfachste Option!)
|
|
|
|
```caddy
|
|
whopays.your-domain.com {
|
|
reverse_proxy localhost:3000
|
|
}
|
|
```
|
|
|
|
Caddy macht automatisch HTTPS mit Let's Encrypt! ✅
|
|
|
|
---
|
|
|
|
## 🔧 API Endpoints
|
|
|
|
### GET /status
|
|
|
|
```bash
|
|
curl http://localhost:3000/status
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"current": "A",
|
|
"lastReason": "Pizza bestellt"
|
|
}
|
|
```
|
|
|
|
### POST /toggle
|
|
|
|
```bash
|
|
curl -X POST http://localhost:3000/toggle \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"reason":"Kaffee trinken"}'
|
|
```
|
|
|
|
Response:
|
|
```json
|
|
{
|
|
"current": "B",
|
|
"name": "Bob",
|
|
"lastReason": "Kaffee trinken"
|
|
}
|
|
```
|
|
|
|
### GET /config
|
|
|
|
```bash
|
|
curl http://localhost:3000/config
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### PWA lässt sich nicht installieren
|
|
|
|
- Stelle sicher, dass du HTTPS verwendest
|
|
- Prüfe ob `manifest.json` erreichbar ist
|
|
- Icons müssen existieren: `icon-192.png` und `icon-512.png`
|
|
|
|
### Discord sendet keine Benachrichtigungen
|
|
|
|
- Prüfe Webhook URL in `config.js`
|
|
- Logs prüfen: `docker-compose logs | grep Discord`
|
|
- Stelle sicher `PUBLIC_BASE_URL` ist korrekt
|
|
|
|
### Bilder werden nicht angezeigt
|
|
|
|
- Prüfe ob Bilder in `/img/` existieren
|
|
- Berechtigungen: `chmod -R 755 img/`
|
|
- Container neu starten
|
|
|
|
### Farbe in Discord ungültig (HTTP 400)
|
|
|
|
- Hex-Farbe muss genau 6 Zeichen haben
|
|
- ✅ Richtig: `0x2ecc71`
|
|
- ❌ Falsch: `0x2ecc71c` (extra Buchstabe!)
|
|
|
|
---
|
|
|
|
## 📊 Features im Detail
|
|
|
|
### Persistent Storage
|
|
|
|
```json
|
|
{
|
|
"current": "A",
|
|
"lastReason": "Restaurant bezahlt"
|
|
}
|
|
```
|
|
|
|
Bleibt erhalten durch Docker Volume Mount.
|
|
|
|
### Smooth Animations
|
|
|
|
- Rotation-Animation (0.6s)
|
|
- Background-Transition (0.6s)
|
|
- Farb-Übergang (0.3s)
|
|
- Image Preloading
|
|
|
|
---
|
|
|
|
## 📜 Lizenz
|
|
|
|
MIT License - Frei nutzbar!
|
|
|
|
---
|
|
|
|
## 💡 Tipps
|
|
|
|
### Custom Domain mit Let's Encrypt
|
|
|
|
```bash
|
|
sudo certbot --nginx -d whopays.your-domain.com
|
|
```
|
|
|
|
### Mehrere Instanzen
|
|
|
|
Unterschiedliche Ports in docker-compose.yml für mehrere Apps!
|
|
|
|
---
|
|
|
|
**Viel Spaß beim Entscheiden, wer zahlt!** 🎉💸 |