# Spotify Roulette IDK für wen das ist, aber hier ist ein Guide, wie man das bei sich selbst aufsetzt, weil Spotify kein extended quota mode für Privatpersonen mehr erlaubt (sprich: man muss jeden Mitspieler manuell im Usermanagement eintragen). ## Wichtig vorab - Für Spotify‑Login und Playback brauchst du eine Domain mit HTTPS. Nur IP ohne Domain funktioniert für Spotify OAuth nicht. - Jeder Spieler muss sich einmal mit Spotify anmelden. Spotify Playback erfordert in der Regel Premium. - Tokens und Spielzustand werden im Speicher gehalten. Neustart der App ⇒ erneute Logins nötig. ## 1\) Voraussetzungen - Server mit Ubuntu 22\.04 \(oder ähnlich\), SSH‑Zugang. - Domain, A‑Record zeigt auf deine Server‑IP. - Spotify Developer Konto: - App anlegen, Client ID und Client Secret notieren. - Redirect‑URI setzen, z\.B. `https://deine-domain.tld/callback` - Jeden Mitspieler in der Spotify‑App als „User“ hinzufügen \(\*ohne extended quota\*\). ## 2\) Server vorbereiten ```bash # System aktualisieren sudo apt update && sudo apt upgrade -y # Java (z.B. Temurin 21), Maven, Git, Nginx, Certbot sudo apt install -y wget gnupg2 ca-certificates lsb-release apt-transport-https sudo apt install -y openjdk-21-jre maven git nginx certbot python3-certbot-nginx # Java prüfen java -version ``` ## 3\) Projekt beziehen und bauen ```bash # In ein Verzeichnis deiner Wahl wechseln cd /opt sudo git clone spotify-roulette cd spotify-roulette # Build (ohne Tests) mvn -DskipTests package # Das erzeugte JAR liegt meist unter: target/-.jar ls -lh target ``` ## 4\) Spotify‑Konfiguration eintragen - Suche, wo `SpotifyAuthService` erzeugt wird \(Workspace‑Suche nach `new SpotifyAuthService(`\). - Trage dort `clientId`, `clientSecret` und `redirectUri` für deine Domain ein \(oder lies sie aus Umgebungsvariablen\). - Redirect‑URI muss exakt zur Spotify Developer Console passen \(Schema, Host, Pfad\), z\.B. `https://deine-domain.tld/callback`. Hinweis: - Die App speichert pro Benutzer eine `SpotifyApi`\-Instanz im Speicher. `exchangeCode` im Callback muss aufgerufen werden, damit `getRecentTracks` und Playback funktionieren. - `GameService` lädt pro Spieler die zuletzt gehörten Tracks beim Beitritt \(`getRecentTracks`\) und cached sie pro Spieler. ## 5\) App als Systemdienst einrichten Kurz erklärt: Systemd startet deine Java‑App beim Booten neu und hält sie am Laufen. ```ini # /etc/systemd/system/spotify-roulette.service [Unit] Description=Spotify Roulette After=network.target [Service] User=www-data WorkingDirectory=/opt/spotify-roulette Environment=SPOTIFY_CLIENT_ID= Environment=SPOTIFY_CLIENT_SECRET= Environment=APP_BASE_URL=https://deine-domain.tld # Falls deine App Umgebungsvariablen liest, nutzt sie. Andernfalls Werte direkt im Code setzen. ExecStart=/usr/bin/java -jar /opt/spotify-roulette/target/.jar Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` Aktivieren und starten: ```bash sudo systemctl daemon-reload sudo systemctl enable spotify-roulette sudo systemctl start spotify-roulette sudo systemctl status spotify-roulette --no-pager ``` ## 6\) Reverse Proxy mit Nginx und HTTPS Proxy leitet Port 80/443 auf deine App \(typisch Port 8080\). WebSockets brauchen Upgrade‑Header. ```nginx # /etc/nginx/sites-available/spotify-roulette.conf map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 80; server_name deine-domain.tld; location / { proxy_pass http://127.0.0.1:8080; # ggf. Port an deine App anpassen proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_read_timeout 3600; } } ``` Aktivieren: ```bash sudo ln -s /etc/nginx/sites-available/spotify-roulette.conf /etc/nginx/sites-enabled/spotify-roulette.conf sudo nginx -t sudo systemctl reload nginx ``` TLS Zertifikat: ```bash sudo certbot --nginx -d deine-domain.tld --redirect ``` ## 7\) Firewall \(falls aktiv\) ```bash sudo ufw allow OpenSSH sudo ufw allow 'Nginx Full' sudo ufw enable sudo ufw status ``` ## 8\) Start lokal \(Dev\) - Spotify erlaubt `http://localhost` als Redirect‑URI. Füge z\.B. `http://localhost:8080/callback` in der Developer Console hinzu und setze denselben Wert im Code. - Start: ```bash mvn -DskipTests package java -jar target/.jar ``` ## 9\) Spielablauf \(UI\) - Öffne `https://deine-domain.tld`. - Spiel erstellen/beitreten. - Jeder Spieler meldet sich mit Spotify an \(erforderliche Scopes: `user-read-recently-played`, `user-library-read`, `user-modify-playback-state`, `user-read-playback-state`, `streaming`\). - Songliste lädt automatisch \(`getRecentTracks` + Fallback `getUsersSavedTracks`\). - „Runde starten“ löst über WebSocket den Start aus. Es wird ein zufälliger Owner und ein Song aus dessen Tracks gewählt. - Guesses über die Kreis‑Optionen \(Mehrfachauswahl möglich\). Scoring: - +3, wenn der ausgeählte den Song gehört hat - −1 pro falschem Tipp - +1 Bonus, wenn kein falscher Tipp \(fehlerfrei\) - Ab 30 Punkten und eindeutiger Spitze: Spielende, Overlay mit Leaderboard, Scores werden auf 0 zurückgesetzt. ## 10\) Geräte & Playback - Geräte laden: `GET /api/spotify/devices?username=` - Abspielen: `POST /api/spotify/play` mit JSON `{ "username": "", "device_id": "", "track_uri": "spotify:track:..." }` - Der Track wird ab der Hälfte gestartet \(`position_ms = duration_ms / 2`\). ## 11\) API \& WS Übersicht - `POST /api/create-game` ⇒ `{ username }` → erstellt Spiel, fügt Spieler hinzu. - `POST /api/join-game` ⇒ `{ username, gameId }` → Spieler tritt bei. - `GET /api/game/{gameId}/players` ⇒ Liste der Spieler. - `POST /api/game/{gameId}/start-round` ⇒ Broadcast des Rundenstarts \(Fallback, primär via WebSocket `type: "start-round"`\). - `POST /api/game/{gameId}/guess` ⇒ `{ username, guess }` \(Legacy Single‑Guess; UI nutzt Multi‑Guess via WS\). - WebSocket: Route mit Pfadparam `gameId` und Query `username` \(Client sendet `type: "start-round" | "submit-guesses" | "requestPlayers" | "next-round"`\). - Server pusht `round-start`, `round-result`, `game-end`. ## 12\) Häufige Stolpersteine - 404 oder OAuth Fehler: Redirect‑URI in Spotify Console muss exakt passen \(Schema, Host, Pfad\). - Kein Start der Runde: Spieler ohne geladene Tracks → sicherstellen, dass Spotify Login erfolgreich war. - WebSockets brechen ab: Nginx Upgrade/Connection Header wie oben setzen. - HTTP statt HTTPS: Spotify akzeptiert im Internet i\.d\.R. nur HTTPS \(keine reine IP\). - Tokens verloren nach Neustart: App speichert nur im Speicher. Spieler müssen sich erneut anmelden. - manchmal kriegt man einen 24h ratelimit bann von alle oder bestimmte features von spotify nicht funktionieren ```