No description
Find a file
2026-03-10 22:21:58 +00:00
.forgejo/workflows ci: mirror Docker images to daddelolymp registry 2026-03-10 22:28:31 +01:00
electron chore(electron): sync version to 1.8.15 2026-03-10 23:20:49 +01:00
server feat: add Steam OpenID login 2026-03-10 22:18:44 +01:00
tools Optimize build: Kaniko cache flags, split Dockerfile stages, install-tools script 2026-03-07 15:39:01 +01:00
web feat: add Steam OpenID login 2026-03-10 22:18:44 +01:00
.dockerignore Initial commit: Gaming Hub foundation 2026-03-05 22:52:13 +01:00
.gitlab-ci.yml CI: docker image prune nach jedem Deploy 2026-03-09 21:37:36 +01:00
Dockerfile Optimize build: Kaniko cache flags, split Dockerfile stages, install-tools script 2026-03-07 15:39:01 +01:00
README.md v1.8.0: README aktualisiert + Version Bump 2026-03-09 00:20:07 +01:00
VERSION v1.8.17 [skip ci] 2026-03-10 22:21:58 +00:00

Gaming Hub

Plugin-basierte Discord-Bot-Plattform mit Web-Dashboard und Electron Desktop App. Drei Bots (Jukebox, Radio, Notifications) laufen parallel mit eigenem Discord-Token und eigener Voice-Connection pro Guild.

Architektur

gaming-hub/
├── server/                 # Backend (Node.js + Express + TypeScript)
│   └── src/
│       ├── index.ts        # Entry Point, SSE, Plugin-Loader, WebSocket
│       ├── core/
│       │   ├── discord.ts      # Discord.js Client Factory (Multi-Bot)
│       │   ├── plugin.ts       # Plugin-System + Voice Claims
│       │   ├── sse.ts          # Server-Sent Events Broadcasting
│       │   └── persistence.ts  # JSON State auf Disk (Atomic Writes)
│       └── plugins/
│           ├── radio/          # World Radio (3D Globe + FFmpeg)
│           ├── soundboard/     # Jukebox / Soundboard (PCM Cache)
│           ├── lolstats/       # League of Legends Statistiken
│           ├── streaming/      # P2P Live-Streaming (WebRTC)
│           ├── watch-together/ # Synchron Video schauen
│           ├── game-library/   # Steam + GOG Spielebibliothek
│           └── notifications/  # Discord Benachrichtigungen
│
├── web/                    # Frontend (React 19 + Vite + TypeScript)
│   └── src/
│       ├── App.tsx             # Root, Tab-Navigation, SSE-Handler
│       ├── styles.css          # Globale Styles
│       └── plugins/
│           ├── radio/          # 3D Globe UI (Three.js Sprites)
│           ├── soundboard/     # Sound Grid UI + Admin Panel
│           ├── lolstats/       # Summoner-Suche + Match History
│           ├── streaming/      # Stream-Erstellung + Viewer
│           ├── watch-together/ # Raeume, Queue, Chat, Voting
│           └── game-library/   # Spielebibliothek Grid
│
├── electron/               # Desktop App (Windows, Squirrel Installer)
│   ├── main.js             # BrowserWindow, Auto-Updater, Ad-Blocker
│   ├── preload.js           # IPC Bridge (contextBridge)
│   ├── ad-blocker.js        # Request-Filter + Filterliste
│   └── forge.config.js      # Electron Forge (Squirrel.Windows)
│
├── Dockerfile              # Multi-Stage Production Build (4 Stages)
├── .gitlab-ci.yml          # CI/CD (Kaniko Build + Deploy + Electron Build)
└── VERSION                 # Aktuelle Version (SemVer)

Tech Stack

Komponente Technologie Version
Runtime Node.js 24 (slim)
Backend Express 5.x
Frontend React + Vite 19.x / 6.x
Discord discord.js + @discordjs/voice 14.x / 0.19.x
3D Globe globe.gl + three.js 2.35 / 0.172
Audio FFmpeg (GPL Build) + @discordjs/opus latest / 0.10.x
Streaming WebSocket (ws) + WebRTC (Browser) 8.x
Desktop Electron + Squirrel.Windows 33.x
TypeScript tsc 5.9.x
CI/CD GitLab + Kaniko v1.23.2

Plugins

Radio (radio)

  • 3D-Globus mit 30.000+ Radiosendern weltweit (Radio Garden API)
  • NASA Blue Marble Globus-Textur (statisches Satellitenbild)
  • Sender als Sprite-Partikel mit radialer Gradient-Textur (Theme-Farbe)
  • Server-seitiger Tile-Proxy mit In-Memory Cache (max 500 Tiles)
  • FFmpeg PCM-Streaming in Discord Voice Channels
  • Per-Guild Lautstaerke, Favoriten, Suche
  • Voice Stats (Ping, Status, Uptime) via SSE

Soundboard / Jukebox (soundboard)

  • Sound-Upload (MP3/WAV) mit Drag & Drop
  • Automatische Audio-Normalisierung (LUFS, FFmpeg)
  • PCM Memory Cache (Standard 512 MB) fuer sofortige Wiedergabe
  • Kategorien, Badges, Statistiken, Entrance/Exit Sounds
  • Admin-Panel mit HMAC-Token-Authentifizierung
  • Party-Modus (Chaos Mode)

LoL Stats (lolstats)

  • League of Legends Spielerstatistiken via op.gg
  • Summoner-Suche nach Game Name + Tag Line + Region
  • Match History mit Detail-Analyse
  • Letzte Suchen (max 10) persistent gespeichert
  • Unterstuetzte Regionen: NA, EUW, EUNE, KR, JP, BR, LAN, LAS, OCE, TR, RU, PH, SG, TH, TW, VN

Streaming (streaming)

  • Peer-to-Peer Live-Streaming via WebRTC (kein Media-Server noetig)
  • WebSocket-Signaling fuer Offer/Answer/ICE-Austausch
  • Qualitaets-Presets: 720p30, 1080p30, 1080p60, 1440p60, 4K60, 4K165 Ultra
  • Einstellbare Bitrate (2.5 Mbit/s bis 50 Mbit/s je nach Preset)
  • Optionaler Passwortschutz (Server-seitige Verifikation)
  • Viewer-Liste mit Echtzeit-Updates
  • Discord-Benachrichtigungen bei Stream-Start/-Ende (via Notifications Plugin)
  • Stream-Link Auto-Join aus Discord (?viewStream=UUID)
  • Heartbeat-basierte Client-Erkennung (5s Intervall)

Watch Together (watch-together)

  • Synchronisiertes Video-Schauen in Raeumen
  • Video-Queue mit URL-Eingabe
  • Demokratisches Voting (Skip, Pause)
  • Integrierter Chat pro Raum
  • Raum-Passwortschutz
  • Playback-Sync alle 2.5 Sekunden
  • Host/Member-Rollen
  • Auto-Cleanup nach 30s Inaktivitaet

Game Library (game-library)

  • Multi-Plattform Spielebibliothek (Steam + GOG)
  • Steam API Integration (Spielzeit-Tracking)
  • GOG OAuth2 Login Flow (mit Token-Refresh)
  • IGDB Game-Enrichment (Metadaten, Cover-Bilder)
  • Mehrere Benutzerprofile pro Instanz
  • Spiele-Caching mit Ablaufzeit

Notifications (notifications)

  • Discord Embed-Benachrichtigungen fuer andere Plugins
  • Kanal-Abonnement-Verwaltung pro Guild
  • Event-Filterung (stream_start, stream_end, etc.)
  • Konfigurierbare Ziel-Kanaele pro Event-Typ
  • Klickbare Stream-Links in Benachrichtigungen

Electron Desktop App

  • Native Windows-Anwendung (Squirrel.Windows Installer)
  • Automatische Updates via /downloads Endpoint
  • Integrierter Ad-Blocker (Request-Filter + Filterliste)
  • Screen Capture Picker (getDisplayMedia mit nativem Dialog)
  • GOG OAuth Redirect-Handling in Child Windows
  • Stream-Warnung beim Schliessen (wenn Broadcast aktiv)
  • Windows Toast Notifications
  • Custom User-Agent (GamingHubDesktop/{version})

Environment Variables

Erforderlich

Variable Beschreibung
DISCORD_TOKEN_JUKEBOX Discord Bot Token fuer Soundboard/Jukebox
DISCORD_TOKEN_RADIO Discord Bot Token fuer Radio
DISCORD_TOKEN_NOTIFICATIONS Discord Bot Token fuer Benachrichtigungen

Alle drei Bots muessen im Discord Developer Portal separat erstellt werden. Jeder braucht die Intents: GUILDS, GUILD_VOICE_STATES, GUILD_MEMBERS.

Optional

Variable Default Beschreibung
PORT 8080 HTTP Server Port
DATA_DIR /data Persistenter Speicher (State, Sounds)
ADMIN_PWD (leer) Admin-Passwort fuer geschuetzte Bereiche
ALLOWED_GUILD_IDS (leer) Komma-separierte Guild-IDs (Whitelist, leer = alle)
PUBLIC_URL (leer) Oeffentliche URL fuer Notification-Links (z.B. https://hub.example.de)
STEAM_API_KEY (leer) Steam Web API Key fuer Game Library
DISCORD_TOKEN (leer) Legacy Fallback fuer Jukebox

Soundboard-spezifisch

Variable Default Beschreibung
SOUNDS_DIR /data/sounds Verzeichnis fuer Sound-Dateien
NORMALIZE_ENABLE true Audio-Normalisierung aktivieren
NORMALIZE_I -16 LUFS Integrated Loudness
NORMALIZE_LRA 11 LUFS Loudness Range
NORMALIZE_TP -1.5 LUFS True Peak
NORM_CONCURRENCY 2 Parallele Normalisierungs-Threads
PCM_CACHE_MAX_MB 512 Max. PCM Memory Cache in MB

Build-Time (Vite)

Variable Default Beschreibung
VITE_APP_VERSION 1.0.0-dev Angezeigte Version im Frontend
VITE_BUILD_CHANNEL dev Release-Kanal (stable / nightly / dev)

Docker

Image bauen

docker build -t gaming-hub:latest .

Container starten

docker run -d \
  --name gaming-hub \
  --restart unless-stopped \
  -p 8080:8080 \
  -v gaming-hub-data:/data \
  -e DISCORD_TOKEN_JUKEBOX="dein-jukebox-token" \
  -e DISCORD_TOKEN_RADIO="dein-radio-token" \
  -e DISCORD_TOKEN_NOTIFICATIONS="dein-notifications-token" \
  -e ADMIN_PWD="dein-admin-passwort" \
  -e PUBLIC_URL="https://hub.example.de" \
  gaming-hub:latest

Docker Compose

version: "3.8"

services:
  gaming-hub:
    image: gaming-hub:latest
    container_name: gaming-hub
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - gaming-hub-data:/data
    environment:
      # Erforderlich
      - DISCORD_TOKEN_JUKEBOX=dein-jukebox-token
      - DISCORD_TOKEN_RADIO=dein-radio-token
      - DISCORD_TOKEN_NOTIFICATIONS=dein-notifications-token
      # Optional
      - ADMIN_PWD=dein-admin-passwort
      - PUBLIC_URL=https://hub.example.de
      - STEAM_API_KEY=dein-steam-api-key
      - ALLOWED_GUILD_IDS=
      # Soundboard Tuning
      - PCM_CACHE_MAX_MB=512
      - NORMALIZE_ENABLE=true

volumes:
  gaming-hub-data:

Unraid Docker Template

<?xml version="1.0"?>
<Container version="2">
  <Name>gaming-hub</Name>
  <Repository>192.168.1.100:5050/root/gaming-hub:latest</Repository>
  <Registry>http://192.168.1.100:9080/</Registry>
  <Network>bridge</Network>
  <Privileged>false</Privileged>
  <Support/>
  <Overview>Discord Gaming Hub - Soundboard, Radio, Streaming, LoL Stats, Watch Together, Game Library</Overview>
  <Category>MediaApp:Other</Category>
  <WebUI>http://[IP]:[PORT:8080]/</WebUI>
  <ExtraParams>--restart unless-stopped</ExtraParams>
  <Config Name="Web UI Port" Target="8080" Default="8080" Mode="tcp" Description="Web Dashboard Port" Type="Port" Display="always" Required="true" Mask="false">8080</Config>
  <Config Name="Data" Target="/data" Default="/mnt/user/appdata/gaming-hub" Mode="rw" Description="Persistenter Speicher" Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/gaming-hub</Config>
  <Config Name="Discord Token Jukebox" Target="DISCORD_TOKEN_JUKEBOX" Default="" Mode="" Description="Discord Bot Token fuer Soundboard" Type="Variable" Display="always" Required="true" Mask="true"/>
  <Config Name="Discord Token Radio" Target="DISCORD_TOKEN_RADIO" Default="" Mode="" Description="Discord Bot Token fuer Radio" Type="Variable" Display="always" Required="true" Mask="true"/>
  <Config Name="Discord Token Notifications" Target="DISCORD_TOKEN_NOTIFICATIONS" Default="" Mode="" Description="Discord Bot Token fuer Benachrichtigungen" Type="Variable" Display="always" Required="true" Mask="true"/>
  <Config Name="Admin Passwort" Target="ADMIN_PWD" Default="" Mode="" Description="Admin-Passwort" Type="Variable" Display="always" Required="false" Mask="true"/>
  <Config Name="Public URL" Target="PUBLIC_URL" Default="" Mode="" Description="Oeffentliche URL fuer Notification-Links" Type="Variable" Display="always" Required="false" Mask="false"/>
  <Config Name="Steam API Key" Target="STEAM_API_KEY" Default="" Mode="" Description="Steam Web API Key fuer Game Library" Type="Variable" Display="advanced" Required="false" Mask="true"/>
  <Config Name="Erlaubte Guild IDs" Target="ALLOWED_GUILD_IDS" Default="" Mode="" Description="Komma-separierte Guild-IDs (leer = alle)" Type="Variable" Display="advanced" Required="false" Mask="false"/>
  <Config Name="PCM Cache MB" Target="PCM_CACHE_MAX_MB" Default="512" Mode="" Description="Max. PCM Memory Cache in MB" Type="Variable" Display="advanced" Required="false" Mask="false">512</Config>
  <Config Name="Normalisierung" Target="NORMALIZE_ENABLE" Default="true" Mode="" Description="Audio-Normalisierung aktivieren" Type="Variable" Display="advanced" Required="false" Mask="false">true</Config>
  <Config Name="Sound-Verzeichnis" Target="SOUNDS_DIR" Default="/data/sounds" Mode="" Description="Sound-Dateien Pfad im Container" Type="Variable" Display="advanced" Required="false" Mask="false">/data/sounds</Config>
</Container>

Lokale Entwicklung

Voraussetzungen

  • Node.js 20+
  • FFmpeg im PATH
  • Drei Discord Bot Tokens

Setup

git clone http://192.168.1.100:9080/root/gaming-hub.git
cd gaming-hub

# Server Dependencies
cd server && npm install && cd ..

# Web Dependencies
cd web && npm install && cd ..

Dev Server starten

# Terminal 1: Backend
cd server
DISCORD_TOKEN_JUKEBOX="..." \
DISCORD_TOKEN_RADIO="..." \
DISCORD_TOKEN_NOTIFICATIONS="..." \
ADMIN_PWD="test" \
DATA_DIR="./data" \
npm run dev

# Terminal 2: Frontend (Proxy auf localhost:8080)
cd web
npm run dev

Backend laeuft auf http://localhost:8080, Frontend auf http://localhost:5173 (mit API-Proxy).

Electron Desktop App (Windows)

cd electron
npm install
npm start

Build fuer Distribution:

cd electron
npx electron-forge make

Erzeugt einen Squirrel.Windows Installer unter electron/out/make/.

Production Build

cd server && npm run build    # -> server/dist/
cd ../web && npm run build    # -> web/dist/

# Starten
cd ../server
NODE_ENV=production node dist/index.js

API Endpoints

Core

Method Pfad Beschreibung
GET /api/health Server-Status, Plugins, Bots, SSE-Clients
GET /api/plugins Plugin-Liste (Name, Version, Description)
GET /api/events SSE-Stream (Snapshot + Live-Updates)
POST /api/admin/login Admin-Login (Body: { password })

Radio Plugin

Method Pfad Beschreibung
GET /api/radio/places Alle Orte fuer den Globus
GET /api/radio/place/:id/channels Sender an einem Ort
GET /api/radio/search?q=... Sender/Orte suchen
GET /api/radio/guilds Verfuegbare Guilds + Voice Channels
POST /api/radio/play Stream starten
POST /api/radio/stop Stream stoppen
POST /api/radio/volume Lautstaerke setzen (0-1)
GET /api/radio/favorites Favoriten lesen
POST /api/radio/favorites Favorit togglen
GET /api/radio/status Aktueller Wiedergabestatus
GET /api/radio/tile/:z/:x/:y Tile-Proxy (Fallback Satellitenbild)

Soundboard Plugin

Method Pfad Beschreibung
GET /api/soundboard/channels Voice Channels aller Guilds
GET /api/soundboard/sounds Sound-Liste (mit Filter/Suche)
POST /api/soundboard/play Sound abspielen
POST /api/soundboard/stop Wiedergabe stoppen
POST /api/soundboard/volume Lautstaerke setzen
POST /api/soundboard/upload Sound hochladen (Multipart)

Streaming Plugin

Method Pfad Beschreibung
WebSocket /ws Signaling (offer, answer, ice, viewer_joined, stream_ended)

Watch Together Plugin

Method Pfad Beschreibung
WebSocket /ws Raum-Sync (create, join, queue, vote, chat, playback)

Game Library Plugin

Method Pfad Beschreibung
GET /api/game-library/profiles Benutzerprofile
POST /api/game-library/profiles Profil erstellen/aktualisieren
GET /api/game-library/games Spieleliste (Steam + GOG)
POST /api/game-library/gog/exchange GOG OAuth Code Exchange

Notifications Plugin

Method Pfad Beschreibung
GET /api/notifications/config Kanal-Konfiguration lesen
POST /api/notifications/config Kanal-Konfiguration speichern

CI/CD Pipeline

GitLab CI mit Kaniko (.gitlab-ci.yml):

Stage Job Beschreibung
build docker-build Kaniko Multi-Platform Image Build
deploy deploy Docker Pull + Run auf adriahub
deploy electron-build Squirrel.Windows Installer + .nupkg + .exe
bump-version bump-version PATCH-Version in VERSION auto-inkrementieren
Branch Tags Version Channel
main latest, main 1.8.0 stable
nightly nightly x.y.z-nightly nightly
andere branch-name x.y.z-dev dev

Registry: 192.168.1.100:5050/root/gaming-hub

SSE Event Types

Alle Clients empfangen Events ueber GET /api/events:

Event Type Plugin Beschreibung
snapshot - Initialer Gesamtstatus beim Connect
radio radio Wiedergabestatus (playing/stopped)
radio_volume radio Lautstaerkeaenderung
radio_voicestats radio Voice-Ping, Gateway-Ping, Status, Uptime
radio_favorites radio Favoriten-Update
soundboard_voicestats soundboard Voice-Verbindungsdetails
soundboard_nowplaying soundboard Aktuell gespielter Sound
soundboard_volume soundboard Lautstaerkeaenderung
soundboard_channel soundboard Channel-Wechsel
soundboard_party soundboard Party-Modus Status

Discord Bot Setup

  1. Discord Developer Portal oeffnen
  2. Drei Applications erstellen (z.B. "Jukebox Bot", "Radio Bot", "Notifications Bot")
  3. Fuer jede Application:
    • Bot erstellen unter "Bot"
    • Token kopieren
    • Privileged Gateway Intents aktivieren:
      • Server Members Intent
      • Message Content Intent (optional)
    • Unter "OAuth2 > URL Generator":
      • Scopes: bot
      • Bot Permissions: Connect, Speak, Use Voice Activity, Send Messages, Embed Links
    • Generierte URL im Browser oeffnen, Bot zum Server einladen
  4. Tokens als DISCORD_TOKEN_JUKEBOX, DISCORD_TOKEN_RADIO und DISCORD_TOKEN_NOTIFICATIONS setzen

Persistenz

Alle Daten werden im DATA_DIR (/data) gespeichert:

/data/
├── sounds/
│   ├── hub-state.json  # Plugin-State (Volumes, Favorites, Channels, Profiles, ...)
│   ├── sound1.mp3
│   ├── subfolder/
│   │   └── sound2.wav
│   └── ...

State wird automatisch bei Aenderungen geschrieben (Atomic Writes mit .tmp + .bak Rotation) und beim Start geladen.

Dockerfile (Multi-Stage)

4 Build-Stages:

  1. web-build - React/Vite Frontend kompilieren
  2. server-deps - npm install + native Build-Tools (python3, make, g++)
  3. server-build - TypeScript Backend kompilieren + Dev-Dependencies entfernen
  4. runtime - Finales Image (node:24-slim) mit FFmpeg + kompiliertem Code

Finales Image enthaelt nur Production Dependencies, kein TypeScript/Dev-Tooling.

Streaming Qualitaets-Presets

Der Streamer kann vor dem Broadcast ein Preset waehlen:

Preset Aufloesung FPS Bitrate
720p30 1280x720 30 2.5 Mbit/s
1080p30 1920x1080 30 5 Mbit/s
1080p60 1920x1080 60 8 Mbit/s
1440p60 2560x1440 60 14 Mbit/s
4K60 3840x2160 60 25 Mbit/s
4K165 Ultra 3840x2160 165 50 Mbit/s

Standard: 1080p60. Das Dropdown ist waehrend eines aktiven Broadcasts deaktiviert.