diff --git a/README.md b/README.md index 96e0e13..c5cba18 100644 --- a/README.md +++ b/README.md @@ -1,300 +1,222 @@ -# Jukebox 420 – Discord Soundboard (v1.1.2) +# Jukebox Vibe – Discord Soundboard -A modern, self‑hosted Discord soundboard with a slick web UI and a Discord bot that plays sounds into your voice channels. Easy to run via Docker, fun to use with friends. +Self-hosted Discord Soundboard mit Web-UI. Spielt Sounds in Discord Voice Channels, verwaltet per Browser. Dockerized, ein Container, fertig. -![Version](https://img.shields.io/badge/version-1.1.2-blue) -![Docker](https://img.shields.io/badge/docker-ready-green) -![Discord](https://img.shields.io/badge/discord-bot-purple) +## Tech Stack -## ✨ Features +| Komponente | Technologie | +|---|---| +| **Backend** | Node.js 20, Express, TypeScript, discord.js 14 | +| **Voice** | @discordjs/voice 0.19, @discordjs/opus, DAVE E2EE (@snazzah/davey) | +| **Frontend** | React 18, Vite, TypeScript, Custom CSS | +| **Audio** | ffmpeg (EBU R128 Loudnorm), yt-dlp | +| **Deployment** | Multi-Stage Dockerfile, GitLab CI/CD (Kaniko) | -- Web UI (Vite + React + TypeScript), 3 themes (Dark, Rainbow, 420) -- Discord bot (discord.js + @discordjs/voice) -- MP3 & WAV playback, ffmpeg normalization -- Favorites, search, folders view (auto counters) -- Live counters and a clean header/footer -- Admin area: bulk delete, inline rename, categories (CRUD) + bulk assign, remove custom badges -- Partymode: server‑side random playback every 30–90 seconds, globally synced via SSE; Panic stops for everyone -- Persistent state: volumes, plays, totalPlays, categories, badges in `/data/sounds/state.json` -- Entrance/Exit sounds: per‑user sounds played when joining/leaving voice; users set them via DM (`?entrance`, `?exit`); Exit plays only on disconnect (not on channel switch) +## Features -## 🚀 Quick start +### Soundboard +- **MP3/WAV Playback** in Discord Voice Channels +- **Loudness Normalization** (EBU R128) mit PCM-Cache fuer Instant-Playback +- **Per-Guild Volume** (0-100%), live adjustable, persistiert +- **Party Mode** – zufaellige Sounds alle 30-90 Sekunden +- **Stop/Panic** – sofortiger Playback-Stop fuer alle -### 1. Requirements -- Docker & Docker Compose -- Discord bot token with intents: `Guilds`, `GuildVoiceStates`, `DirectMessages` +### Discord Bot +- **Entrance Sounds** – persoenlicher Sound beim Channel-Join +- **Exit Sounds** – Sound beim Disconnect (nicht bei Channel-Wechsel) +- **DM Upload** – Sounds per Direktnachricht an den Bot hochladen +- **Voice Resilience** – 3-Tier Reconnect mit Exponential Backoff + +### Web-UI +- **Sound Grid** mit klickbaren Cards +- **Suche** mit optionalem Fuzzy-Matching +- **Ordner-Filter** mit farbigen Chips +- **Favoriten** (Cookie-basiert) +- **Kategorien** und **Badges** (Admin-verwaltet) +- **Channel-Selector** gruppiert nach Guild +- **Now Playing** Anzeige mit Wellenform-Animation +- **5 Themes** – Discord, Midnight, Forest, Sunset, Ocean +- **Card-Size Slider** (80-160px) +- **Drag & Drop Upload** (Admin) +- **MP3-URL Import** – direkter Download und Playback +- **Real-Time Sync** via Server-Sent Events (SSE) + +### Admin +- **Login** mit HMAC-SHA256 Token (HttpOnly Cookie, 7 Tage) +- **Bulk Delete / Rename** von Sounds +- **Upload** bis zu 20 Dateien (je max. 50MB) +- **Kategorien** erstellen, bearbeiten, loeschen, zuweisen +- **Custom Badges** zuweisen/entfernen + +## Quickstart + +### Voraussetzungen +- Docker +- Discord Bot Token mit Intents: `Guilds`, `GuildVoiceStates`, `GuildMembers`, `DirectMessages`, `MessageContent` + +### Setup -### 2. Setup ```bash -# Clone repository -git clone https://github.com/flex420/jukebox-vibe.git +git clone https://git.daddelolymp.de/root/jukebox-vibe.git cd jukebox-vibe - -# Create .env cp .env.example .env +# .env anpassen (DISCORD_TOKEN, ADMIN_PWD) +docker compose up -d ``` -### 3. Configuration -```env -# Edit the .env file -DISCORD_TOKEN=your_discord_bot_token_here -ADMIN_PWD=choose-a-strong-password -PORT=8080 -SOUNDS_DIR=/data/sounds +### Docker Run (ohne Compose) -# Optionally restrict allowed guilds -ALLOWED_GUILD_IDS=GUILD_ID_1,GUILD_ID_2 -``` - -### 4. Deployment -```bash -# Start container -docker compose up --build -d - -# Logs -docker compose logs -f - -# Status -docker compose ps -``` - -### 5. Access -- **Web-Interface**: `http://localhost:8199` -- **Health Check**: `http://localhost:8199/api/health` - -## 🎯 Usage - -### **Getting started** -1. Invite the Discord bot with voice permissions -2. Upload sounds via DM to the bot (MP3/WAV) -3. Open the web UI and choose a theme -4. Select a voice channel and play sounds - -### **Admin panel** -1. Log in with the admin password -2. Select sounds via checkboxes -3. Perform bulk delete or rename -4. Logout to finish - -### **URL downloads** -- Enter MP3/WAV links into the URL field -- Click Download -- The file will be added automatically to the soundboard - -## 🎨 Themes - -### **Dark Theme** -- Klassisches dunkles Design -- Blaue Akzente (#0a84ff) -- Glassmorphism-Effekte - -### **Rainbow Theme** -- Animierter Regenbogen-Hintergrund -- Bunte Borders und Effekte -- 15s Animation-Loop - -### **420 Theme** -- Cannabis-grüne Farbpalette -- Trippy animierte Gradienten -- 20s Animation-Loop -- Grüne Glow-Effekte - -## 📊 API endpoints - -### **Public Endpoints** -```http -GET /api/health # Health Check + Statistiken -GET /api/sounds # Sound-Liste mit Ordner-Struktur -GET /api/channels # Voice-Channel Liste -POST /api/play # Sound abspielen -POST /api/play-url # URL downloaden & abspielen -POST /api/stop # Aktuellen Sound stoppen -GET /api/volume # Volume abrufen -POST /api/volume # Volume setzen -``` - -### **Admin endpoints** -```http -POST /api/admin/login # Admin-Login -POST /api/admin/logout # Admin-Logout -GET /api/admin/status # Login-Status -POST /api/admin/sounds/delete # Sounds löschen -POST /api/admin/sounds/rename # Sound umbenennen -``` - -## 🔧 Discord bot commands - -### **DM commands** -- `?help` – show help -- `?list` – list all sounds -- `?entrance | remove` – set or remove your entrance sound -- `?exit | remove` – set or remove your exit sound - -### **Upload via DM** -- Send MP3/WAV files directly to the bot -- Files are stored under `/data/sounds` -- Immediately available in the frontend - -## 🐳 Docker deployment - -### **Docker Compose (Empfohlen)** -```yaml -# docker-compose.yml -services: - app: - build: . - container_name: discord-soundboard - ports: - - "8199:8080" - env_file: - - .env - volumes: - - ./data/sounds:/data/sounds - restart: unless-stopped -``` - -### **Docker Run** ```bash docker run -d \ - --name jukebox-420 \ + --name jukebox \ -p 8199:8080 \ - --env-file .env \ - -v $(pwd)/data/sounds:/data/sounds \ - flex420/jukebox-vibe:latest + -e DISCORD_TOKEN=dein_token \ + -e ADMIN_PWD=dein_passwort \ + -v $(pwd)/sounds:/data/sounds \ + --restart unless-stopped \ + git.daddelolymp.de/root/jukebox-vibe:latest ``` -### **Docker Hub** -```bash -# Image pullen -docker pull flex420/jukebox-vibe:latest +## Konfiguration -# Container starten -docker run -d --name jukebox-420 -p 8199:8080 --env-file .env -v $(pwd)/data/sounds:/data/sounds flex420/jukebox-vibe:latest +| Variable | Default | Beschreibung | +|---|---|---| +| `DISCORD_TOKEN` | *erforderlich* | Discord Bot Token | +| `ADMIN_PWD` | `''` | Admin-Passwort fuer Web-UI | +| `PORT` | `8080` | Server Port | +| `SOUNDS_DIR` | `/data/sounds` | Sound-Verzeichnis (Docker Volume) | +| `ALLOWED_GUILD_IDS` | `''` | Komma-getrennte Guild-IDs (leer = alle) | +| `NORMALIZE_ENABLE` | `true` | Loudness Normalization an/aus | +| `NORMALIZE_I` | `-16` | Ziel-Lautstaerke in LUFS | +| `NORMALIZE_LRA` | `11` | Loudness Range | +| `NORMALIZE_TP` | `-1.5` | True Peak in dBTP | +| `NORM_CONCURRENCY` | `2` | Parallele ffmpeg-Prozesse | + +## Bot Commands + +Alle Commands per DM an den Bot oder im Server-Chat: + +| Command | Beschreibung | +|---|---| +| `?help` | Hilfe anzeigen | +| `?list` | Alle Sounds auflisten | +| `?entrance ` | Entrance-Sound setzen | +| `?entrance remove` | Entrance-Sound entfernen | +| `?exit ` | Exit-Sound setzen | +| `?exit remove` | Exit-Sound entfernen | + +**Upload via DM:** MP3/WAV als Anhang an den Bot senden – wird automatisch gespeichert und normalisiert. + +## API + +### Public + +``` +GET /api/health Healthcheck + Stats +GET /api/sounds Sound-Liste (query: q, folder, categoryId, fuzzy) +GET /api/analytics Top 10 Most Played, Gesamt-Plays +GET /api/channels Verfuegbare Voice Channels +GET /api/selected-channels Gespeicherte Channel-Auswahl +POST /api/selected-channel Channel-Auswahl setzen +POST /api/play Sound abspielen (body: soundName, guildId, channelId) +POST /api/play-url MP3-URL downloaden und abspielen +POST /api/stop Playback stoppen +GET /api/volume Volume abfragen +POST /api/volume Volume setzen (0-1) +POST /api/party/start Party Mode starten +POST /api/party/stop Party Mode stoppen +GET /api/events SSE Stream (Real-Time Updates) ``` -## 🔒 SSL/HTTPS Hinweis (wichtig für Discord) +### Admin (Cookie-Auth) -- Das Web-Frontend MUSS hinter HTTPS (SSL) ausgeliefert werden. Empfohlen ist ein Domain‑Mapping (Reverse Proxy) mit gültigem Zertifikat (z. B. Traefik, Nginx, Caddy, Cloudflare). -- Hintergrund: Ohne TLS kann es zu Verschlüsselungs-/Encrypt‑Fehlern kommen, und Audio wird in Discord nicht korrekt wiedergegeben. -- Praxis: Richte eine Domain wie `https://soundboard.deinedomain.tld` auf das Frontend ein und aktiviere SSL (Let’s Encrypt). Danach sollten Uploads/Playback stabil funktionieren. +``` +POST /api/admin/login Login (body: password) +POST /api/admin/logout Logout +GET /api/admin/status Auth-Status pruefen +POST /api/upload Dateien hochladen (multipart, max 20x50MB) +POST /api/admin/sounds/delete Sounds loeschen (body: paths[]) +POST /api/admin/sounds/rename Sound umbenennen +GET /api/categories Kategorien auflisten +POST /api/categories Kategorie erstellen +PATCH /api/categories/:id Kategorie bearbeiten +DELETE /api/categories/:id Kategorie loeschen +POST /api/categories/assign Kategorien zuweisen +POST /api/badges/assign Badges zuweisen +POST /api/badges/clear Badges entfernen +``` -## 📁 Project structure +## Sound-Dateien + +``` +/data/sounds/ + state.json # Persistierter State (Volumes, Plays, Kategorien, etc.) + .norm-cache/ # Normalisierte PCM-Caches + airhorn.mp3 # Sounds im Root + memes/ # Ordner-Struktur (1 Ebene) + bruh.mp3 + oof.wav +``` + +- Formate: `.mp3`, `.wav` +- Ordner werden als Filter-Chips im Frontend angezeigt +- `.norm-cache/` wird automatisch verwaltet (Cache-Invalidierung bei Datei-Aenderung) + +## Loudness Normalization + +Alle Sounds werden per ffmpeg `loudnorm` (EBU R128) normalisiert: + +1. **Startup:** Hintergrund-Sync normalisiert alle uncached Sounds +2. **Cache Hit:** Gecachte PCM-Datei wird direkt gestreamt (kein ffmpeg, instant) +3. **Cache Miss:** ffmpeg streamt live zum Player UND schreibt gleichzeitig in Cache +4. **Upload:** Neue Dateien werden sofort im Hintergrund normalisiert + +## Voice Connection + +3-stufiges Recovery bei Verbindungsproblemen: + +1. **Wait for Ready** (15s Timeout) +2. **Rejoin** im selben Channel (15s Timeout) +3. **Destroy + Fresh Join** (15s Timeout) + +Lifecycle-Handler mit: +- Max 3 Reconnect-Versuche mit Exponential Backoff +- Anti-Reentrancy Guard gegen Endlosschleifen +- Automatisches State-Cleanup bei totalem Verbindungsverlust + +## Projektstruktur ``` jukebox-vibe/ -├── server/ # Backend (Node.js/Express) -│ ├── src/ -│ │ ├── index.ts # Main Server + Discord Bot -│ │ └── types/ # TypeScript Definitions -│ ├── package.json -│ └── tsconfig.json -├── web/ # Frontend (React/Vite) -│ ├── src/ -│ │ ├── App.tsx # Main React Component -│ │ ├── api.ts # API Client -│ │ ├── styles.css # Theme Styles -│ │ └── types.ts # TypeScript Types -│ ├── package.json -│ └── index.html -├── docker-compose.yml # Docker Compose Config -├── Dockerfile # Multi-Stage Build -├── .env.example # Environment Template -└── README.md # Diese Datei + server/ + src/index.ts # Server + Discord Bot (Hauptdatei) + package.json + tsconfig.json + web/ + src/ + App.tsx # React SPA + styles.css # Themes + Layout + types.ts # TypeScript Types + package.json + vite.config.ts + Dockerfile # Multi-Stage Build (web + server + runtime) + docker-compose.yml + .gitlab-ci.yml # CI/CD Pipeline (Kaniko) + .env.example ``` -## 🔧 Development - -### **Lokale Entwicklung** -```bash -# Backend -cd server -npm install -npm run dev - -# Frontend (neues Terminal) -cd web -npm install -npm run dev -``` - -### **Build** -```bash -# Production Build -docker build -t jukebox-vibe . - -# Development Build -docker build --target development -t jukebox-vibe:dev . -``` - -## 📈 Stats - -### **Persistent data** -- Sounds: `/data/sounds/` (volume mount) -- State: `/data/sounds/state.json` (volume, channel, plays) -- Favorites: browser cookies -- Theme: browser localStorage - -### **Monitoring** -- Health check: `/api/health` -- Docker logs: `docker compose logs -f` -- Container status: `docker compose ps` - -## 🛠️ Troubleshooting - -### **Häufige Probleme** - -**Bot does not join the voice channel:** -- Check bot permissions (Connect, Speak, Request to Speak for Stage) -- Verify gateway intents in the Discord Developer Portal (GuildVoiceStates, DirectMessages, MessageContent) -- Check network/firewall - -**Sounds do not show up:** -- Verify volume mount `/data/sounds` -- Check file permissions -- Confirm uploads via DM - -**Admin login fails:** -- Check browser cookies -- Confirm admin password -- Inspect server logs - -### **Logs anzeigen** -```bash -# Docker Compose Logs -docker compose logs -f - -# Container-spezifische Logs -docker compose logs -f app - -# Letzte 100 Zeilen -docker compose logs --tail=100 app -``` - -## 🤝 Contributing - -1. **Fork** das Repository -2. **Feature Branch** erstellen (`git checkout -b feature/AmazingFeature`) -3. **Commit** Änderungen (`git commit -m 'Add AmazingFeature'`) -4. **Push** zum Branch (`git push origin feature/AmazingFeature`) -5. **Pull Request** erstellen - -## 📄 Lizenz - -Dieses Projekt ist unter der MIT Lizenz lizenziert - siehe [LICENSE](LICENSE) Datei für Details. - -## 🙏 Credits - -- **Discord.js** für Bot-Funktionalität -- **React** für das Frontend -- **Vite** für Build-Tooling -- **Docker** für Containerisierung -- **Tailwind CSS** für Styling - ---- - -**🎵 Jukebox 420** - Dein ultimatives Discord Soundboard! 🚀 +## CI/CD +GitLab CI baut automatisch bei jedem Push: +| Branch | Image Tag | +|---|---| +| `main` | `:main`, `:latest`, `:sha` | +| `nightly` | `:nightly`, `:sha` | +| andere | `:`, `:sha` | +Registry: `git.daddelolymp.de/root/jukebox-vibe` +## Lizenz +MIT