diff --git a/README.md b/README.md index b5fef77..33bc2a1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Audiofy – Musikwünsche für Partys +# Playwish – Musikwünsche für Partys Gäste scannen einen QR-Code und wünschen sich Songs. Ein **Player** spielt über Spotify zufällige Titel aus einer Grund-Playlist – jeder N-te Titel ist ein Wunsch. Gibt es keine @@ -14,10 +14,10 @@ Admin-Bereich, auch vom Handy. ## Aufbau ``` -Gast-Handy ──HTTPS──▶ Server: Caddy → audiofy-web (FastAPI + SQLite) +Gast-Handy ──HTTPS──▶ Server: Caddy → playwish-web (FastAPI + SQLite) ▲ Player-API (Bearer-Token) │ nur ausgehend vom Player -Player: raspotify (Spotify Connect) + audiofy-controller +Player: raspotify (Spotify Connect) + playwish-controller └─▶ Bluetooth-Lautsprecher (BlueALSA) oder Kabel/HDMI/USB (ALSA) ``` @@ -39,7 +39,7 @@ Portfreigabe am Router. ## Spotify-App anlegen -Audiofy steuert Spotify über die offizielle Web API. Dafür braucht jede Installation eine +Playwish steuert Spotify über die offizielle Web API. Dafür braucht jede Installation eine eigene, kostenlose „App“ im Spotify-Developer-Bereich. Gäste brauchen nichts davon. **Was du brauchst:** das Spotify-Konto, das später abspielt – mit **Premium**. @@ -51,7 +51,7 @@ Die Bezeichnungen im Dashboard können sich leicht ändern; sinngemäß: | Feld | Eintrag | |---|---| - | App name | z. B. `Audiofy` | + | App name | z. B. `Playwish` | | App description | z. B. `Musikwünsche für meine Party` | | Website | leer lassen | | **Redirect URI** | **`http://127.0.0.1:8888/callback`** – genau so, dann „Add“ | @@ -75,7 +75,7 @@ Die Bezeichnungen im Dashboard können sich leicht ändern; sinngemäß: **Was der Development Mode bedeutet:** Neue Apps laufen im „Development Mode“. Dort gilt (Stand 2026): Der App-Besitzer braucht Premium, nur eingetragene Konten dürfen die App nutzen, die Suche liefert höchstens 10 Treffer, nur **eigene** Playlists sind lesbar, und -die Nutzung muss **nicht kommerziell** sein. Für Audiofy reicht das völlig – abgespielt +die Nutzung muss **nicht kommerziell** sein. Für Playwish reicht das völlig – abgespielt wird nur über dein eigenes Konto. **Typische Fehler beim Login** @@ -97,23 +97,23 @@ wird nur über dein eigenes Konto. **Per Einzeiler** – als Benutzer mit sudo-Rechten (oder als root) in einem Terminal: ``` -curl -fsSL https://git.wind8000.de/0/audiofy/raw/branch/main/install/get.sh | bash -s -- server -curl -fsSL https://git.wind8000.de/0/audiofy/raw/branch/main/install/get.sh | bash -s -- player +curl -fsSL https://git.wind8000.de/0/playwish/raw/branch/main/install/get.sh | bash -s -- server +curl -fsSL https://git.wind8000.de/0/playwish/raw/branch/main/install/get.sh | bash -s -- player ``` -Das Startskript installiert bei Bedarf `git`, holt Audiofy nach `/usr/local/src/audiofy` und +Das Startskript installiert bei Bedarf `git`, holt Playwish nach `/usr/local/src/playwish` und startet das passende Install-Skript. Später aktualisieren: denselben Befehl mit `--update` am Ende (`… | bash -s -- server --update`). Vorsichtiger – erst ansehen, dann ausführen: ``` -curl -fsSLO https://git.wind8000.de/0/audiofy/raw/branch/main/install/get.sh +curl -fsSLO https://git.wind8000.de/0/playwish/raw/branch/main/install/get.sh less get.sh bash get.sh server # bzw. player ``` -**Oder von Hand:** Repository klonen (`git clone https://git.wind8000.de/0/audiofy.git`) und +**Oder von Hand:** Repository klonen (`git clone https://git.wind8000.de/0/playwish.git`) und die Install-Skripte direkt starten: **1. Server** @@ -140,7 +140,7 @@ Spotify-Zugang und Playlist ab, installiert raspotify, koppelt auf Wunsch gleich Bluetooth-Lautsprecher und richtet den Controller als Dienst ein. Danach folgt der Spotify-Login für die Wiedergabe-Steuerung. -**3. Einmalig in der Spotify-App** das neue Gerät (Standard: „Audiofy“) auswählen – im selben +**3. Einmalig in der Spotify-App** das neue Gerät (Standard: „Playwish“) auswählen – im selben Netz wie der Player. Damit speichert raspotify seine Anmeldung und ist nach jedem Neustart von selbst wieder da. @@ -151,9 +151,9 @@ einschalten und den QR-Code zeigen oder ausdrucken. | Aufgabe | Befehl | |---|---| -| Status | `systemctl status audiofy-web` (Server) · `systemctl status audiofy-controller raspotify` (Player) | -| Logs live | `journalctl -u audiofy-web -f` · `journalctl -u audiofy-controller -f` | -| Neustart | `sudo systemctl restart audiofy-web` bzw. `audiofy-controller` | +| Status | `systemctl status playwish-web` (Server) · `systemctl status playwish-controller raspotify` (Player) | +| Logs live | `journalctl -u playwish-web -f` · `journalctl -u playwish-controller -f` | +| Neustart | `sudo systemctl restart playwish-web` bzw. `playwish-controller` | | Update | Einzeiler mit `--update` – oder im Repository `git pull && install/install-server.sh --update` bzw. `install/install-player.sh --update` | `--update` ersetzt nur Code, Python-Umgebung und Dienstdatei; Konfiguration, Datenbank, @@ -163,23 +163,23 @@ Caddy, Firewall und raspotify bleiben unverändert. | Pfad | Inhalt | |---|---| -| `/opt/audiofy/app` | Code (gehört root, der Dienst darf nur lesen) | -| `/opt/audiofy/.env` (Server) | Geheimnisse: Spotify, Admin-Passwort-Hash, Turnstile, `PLAYER_API_TOKEN` | -| `/opt/audiofy/data/audiofy.db` (Server) | Wünsche, Verlauf, Einstellungen | -| `/opt/audiofy/config/.env` (Player) | Geheimnisse: Spotify, `SERVER_URL`, `PLAYER_API_TOKEN`, Lautsprecher | +| `/opt/playwish/app` | Code (gehört root, der Dienst darf nur lesen) | +| `/opt/playwish/.env` (Server) | Geheimnisse: Spotify, Admin-Passwort-Hash, Turnstile, `PLAYER_API_TOKEN` | +| `/opt/playwish/data/playwish.db` (Server) | Wünsche, Verlauf, Einstellungen | +| `/opt/playwish/config/.env` (Player) | Geheimnisse: Spotify, `SERVER_URL`, `PLAYER_API_TOKEN`, Lautsprecher | -Die `.env`-Dateien gehören dem Dienst-Benutzer `audiofy` (Rechte 600). **Sichere sie an einem +Die `.env`-Dateien gehören dem Dienst-Benutzer `playwish` (Rechte 600). **Sichere sie an einem sicheren Ort** (z. B. Passwort-Manager) – sie stehen bewusst nicht im Repository. **Verwaltung** (interaktiv, im eigenen Terminal): ``` # Server: Admin-Passwort bzw. Turnstile-Schlüssel ändern -sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/verwaltung.py passwort --env /opt/audiofy/.env -sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/verwaltung.py turnstile --env /opt/audiofy/.env +sudo -u playwish /opt/playwish/.venv/bin/python /opt/playwish/app/verwaltung.py passwort --env /opt/playwish/.env +sudo -u playwish /opt/playwish/.venv/bin/python /opt/playwish/app/verwaltung.py turnstile --env /opt/playwish/.env # Spotify-Login erneuern – Server bzw. Player -sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/auth.py --profil server --env /opt/audiofy/.env -sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/auth.py --profil player --env /opt/audiofy/config/.env +sudo -u playwish /opt/playwish/.venv/bin/python /opt/playwish/app/auth.py --profil server --env /opt/playwish/.env +sudo -u playwish /opt/playwish/.venv/bin/python /opt/playwish/app/auth.py --profil player --env /opt/playwish/config/.env ``` Danach den jeweiligen Dienst neu starten. @@ -187,18 +187,18 @@ Danach den jeweiligen Dienst neu starten. **Datenbank sichern** (Server): ``` -sudo -u audiofy sqlite3 /opt/audiofy/data/audiofy.db ".backup /opt/audiofy/data/sicherung.db" +sudo -u playwish sqlite3 /opt/playwish/data/playwish.db ".backup /opt/playwish/data/sicherung.db" ``` ## Server härten (empfohlen, von Hand) Das Install-Skript ändert die SSH-Konfiguration bewusst **nicht** – damit sperrt man sich -leicht aus. Vorlage: `install/vorlagen/sshd-10-audiofy.conf` (anderer Port, nur Schlüssel, +leicht aus. Vorlage: `install/vorlagen/sshd-10-playwish.conf` (anderer Port, nur Schlüssel, kein root, nur ein Admin-Benutzer). Vorgehen: 1. Eigenen Admin-Benutzer mit sudo anlegen, SSH-Schlüssel hinterlegen, Login testen. 2. Neuen Port in ufw **und** einer eventuellen Cloud-Firewall öffnen. -3. Vorlage ausgefüllt nach `/etc/ssh/sshd_config.d/10-audiofy.conf` legen, `sudo sshd -t`, `sudo systemctl restart ssh`. +3. Vorlage ausgefüllt nach `/etc/ssh/sshd_config.d/10-playwish.conf` legen, `sudo sshd -t`, `sudo systemctl restart ssh`. 4. **In einer zweiten Sitzung** testen – die alte bleibt offen, bis es klappt. 5. Erst dann den alten Port in ufw/Cloud-Firewall schließen und fail2ban auf den neuen Port umstellen. @@ -209,7 +209,7 @@ kein root, nur ein Admin-Benutzer). Vorgehen: | Keine Musik, Log: „Lautsprecher nicht verbunden“ | Lautsprecher einschalten – der Player verbindet ihn neu und startet die Musik von selbst. | | Lautsprecher verbindet sich nicht mehr („Permission denied“) | Kopplung verloren. Im Admin unter Einstellungen → Lautsprecher neu suchen und verbinden (Lautsprecher im Kopplungsmodus). | | „Gerät nicht gefunden“ | `systemctl status raspotify`. Nach einer Neuinstallation einmal in der Spotify-App das Gerät auswählen. | -| Admin: „Player offline“ | `systemctl status audiofy-controller`, Internet des Players prüfen. Die Musik läuft trotzdem mit der Playlist weiter. | +| Admin: „Player offline“ | `systemctl status playwish-controller`, Internet des Players prüfen. Die Musik läuft trotzdem mit der Playlist weiter. | | Admin: „Grund-Playlist nicht lesbar“ | Nur eigene Playlists funktionieren (Spotify Development Mode). | | Befehle „No active device“ | Spotify hatte kein aktives Gerät; „Play“ startet dann die Playlist auf dem Player. | | Nach Neustart bleibt es still | Gewollt, wenn vorher pausiert oder Not-Aus aktiv war – im Admin „Play“ bzw. „Freigeben“. | @@ -231,14 +231,14 @@ cd ../player && python3 -m venv .venv && .venv/bin/pip install -r requirements.t Copyright © 2026 Dominic Alexander Windolph -Audiofy ist freie Software: Du kannst es unter den Bedingungen der **GNU General Public +Playwish ist freie Software: Du kannst es unter den Bedingungen der **GNU General Public License**, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder verändern – entweder gemäß Version 3 der Lizenz oder (nach deiner Wahl) jeder späteren Version. Der vollständige Lizenztext steht in [`LICENSE`](LICENSE). -Audiofy wird in der Hoffnung verbreitet, dass es nützlich ist, aber **ohne jede +Playwish wird in der Hoffnung verbreitet, dass es nützlich ist, aber **ohne jede Gewährleistung** – sogar ohne die implizite Gewährleistung der Marktreife oder der Eignung für einen bestimmten Zweck. Details stehen in der GNU General Public License. -Audiofy ist kein Produkt von Spotify und steht in keiner Verbindung zu Spotify AB. +Playwish ist kein Produkt von Spotify und steht in keiner Verbindung zu Spotify AB. Spotify ist eine Marke der Spotify AB. diff --git a/install/get.sh b/install/get.sh index 05e6b39..bf107cb 100755 --- a/install/get.sh +++ b/install/get.sh @@ -1,17 +1,17 @@ #!/usr/bin/env bash -# Audiofy – Installation per Einzeiler (holt das Repository und startet das passende Install-Skript): +# Playwish – Installation per Einzeiler (holt das Repository und startet das passende Install-Skript): # -# curl -fsSL https://git.wind8000.de/0/audiofy/raw/branch/main/install/get.sh | bash -s -- server -# curl -fsSL https://git.wind8000.de/0/audiofy/raw/branch/main/install/get.sh | bash -s -- player +# curl -fsSL https://git.wind8000.de/0/playwish/raw/branch/main/install/get.sh | bash -s -- server +# curl -fsSL https://git.wind8000.de/0/playwish/raw/branch/main/install/get.sh | bash -s -- player # … | bash -s -- server --update später aktualisieren (holt den neuesten Stand) # -# Die Quellen liegen danach in /usr/local/src/audiofy. Andere Quelle/Zweig: -# AUDIOFY_REPO=https://…/audiofy.git AUDIOFY_BRANCH=main +# Die Quellen liegen danach in /usr/local/src/playwish. Andere Quelle/Zweig: +# PLAYWISH_REPO=https://…/playwish.git PLAYWISH_BRANCH=main set -euo pipefail -REPO="${AUDIOFY_REPO:-https://git.wind8000.de/0/audiofy.git}" -ZWEIG="${AUDIOFY_BRANCH:-main}" -QUELLE="${AUDIOFY_SRC:-/usr/local/src/audiofy}" +REPO="${PLAYWISH_REPO:-https://git.wind8000.de/0/playwish.git}" +ZWEIG="${PLAYWISH_BRANCH:-main}" +QUELLE="${PLAYWISH_SRC:-/usr/local/src/playwish}" ROLLE="${1:-}" [ $# -gt 0 ] && shift @@ -25,7 +25,7 @@ if [ "$(id -u)" -eq 0 ]; then SUDO=""; else SUDO="sudo" fi -echo "==> Audiofy-Quellen holen ($REPO, Zweig $ZWEIG)" +echo "==> Playwish-Quellen holen ($REPO, Zweig $ZWEIG)" if ! command -v git >/dev/null; then $SUDO apt-get update -qq $SUDO env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq git >/dev/null diff --git a/install/install-player.sh b/install/install-player.sh index 329d5c8..f864e39 100755 --- a/install/install-player.sh +++ b/install/install-player.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Audiofy – Installation der Rolle "Player": Spotify-Connect-Gerät (raspotify) und Controller. +# Playwish – Installation der Rolle "Player": Spotify-Connect-Gerät (raspotify) und Controller. # # install/install-player.sh Neuinstallation (fragt alles Nötige ab) # install/install-player.sh --update nur Code, Python-Umgebung und Dienst aktualisieren @@ -20,23 +20,23 @@ for arg in "$@"; do esac done -KONFIG="$AUDIOFY_DIR/config" +KONFIG="$PLAYWISH_DIR/config" ENV_DATEI="$KONFIG/.env" RASPOTIFY_CONF=/etc/raspotify/conf -export AUDIOFY_DIR AUDIOFY_USER +export PLAYWISH_DIR PLAYWISH_USER -schritt "Audiofy-Player: $([ $UPDATE = 1 ] && echo Update || echo Neuinstallation)" +schritt "Playwish-Player: $([ $UPDATE = 1 ] && echo Update || echo Neuinstallation)" pruefe_system ARCH="$(dpkg --print-architecture)" case "$ARCH" in arm64|armhf|amd64) ;; *) abbruch "raspotify gibt es nicht für $ARCH (nur arm64, armhf, amd64)." ;; esac if [ $UPDATE = 1 ] && ! $SUDO test -f "$ENV_DATEI"; then - abbruch "Keine bestehende Installation in $AUDIOFY_DIR gefunden – ohne --update ausführen." + abbruch "Keine bestehende Installation in $PLAYWISH_DIR gefunden – ohne --update ausführen." fi # ------------------------------------------------------------------ Abfragen if [ $UPDATE = 0 ]; then schritt "Angaben" - frage GERAETENAME "Name des Spotify-Connect-Geräts" "Audiofy" + frage GERAETENAME "Name des Spotify-Connect-Geräts" "Playwish" echo " Audio-Ausgabe: 1) Bluetooth-Lautsprecher 2) Kabel/HDMI/USB (ALSA)" frage AUSGABE "Auswahl" "1" if [ "$AUSGABE" = 2 ]; then @@ -50,7 +50,7 @@ if [ $UPDATE = 0 ]; then BLUETOOTH=1 ALSA_GERAET="bluealsa:DEV=00:00:00:00:00:00,PROFILE=a2dp" # = zuletzt verbundener Lautsprecher fi - frage SERVER_URL "Adresse des Audiofy-Servers (leer = ohne Wünsche, nur Playlist)" "" + frage SERVER_URL "Adresse des Playwish-Servers (leer = ohne Wünsche, nur Playlist)" "" SERVER_URL="${SERVER_URL%/}" PLAYER_TOKEN="" [ -n "$SERVER_URL" ] && frage_geheim PLAYER_TOKEN "PLAYER_API_TOKEN vom Server (verdeckt)" @@ -102,7 +102,7 @@ if [ $UPDATE = 0 ]; then info "Name „$GERAETENAME“, Ausgabe $ALSA_GERAET" fi $SUDO install -d /etc/systemd/system/raspotify.service.d -vorlage raspotify-10-audiofy.conf /etc/systemd/system/raspotify.service.d/10-audiofy.conf +vorlage raspotify-10-playwish.conf /etc/systemd/system/raspotify.service.d/10-playwish.conf $SUDO systemctl daemon-reload $SUDO systemctl enable raspotify >/dev/null 2>&1 [ $UPDATE = 0 ] && $SUDO systemctl restart raspotify @@ -144,16 +144,16 @@ fi # ------------------------------------------------------------------ Benutzer, Ordner, Code schritt "Dienst-Benutzer, Ordner und Code" dienst_benutzer -$SUDO install -d -o root -g "$AUDIOFY_USER" -m 750 "$AUDIOFY_DIR" -$SUDO install -d -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 700 "$KONFIG" -code_kopieren "$REPO/player" "$AUDIOFY_DIR/app" -venv_einrichten "$AUDIOFY_DIR/app/requirements.txt" -info "Code in $AUDIOFY_DIR/app, Konfiguration in $KONFIG" +$SUDO install -d -o root -g "$PLAYWISH_USER" -m 750 "$PLAYWISH_DIR" +$SUDO install -d -o "$PLAYWISH_USER" -g "$PLAYWISH_USER" -m 700 "$KONFIG" +code_kopieren "$REPO/player" "$PLAYWISH_DIR/app" +venv_einrichten "$PLAYWISH_DIR/app/requirements.txt" +info "Code in $PLAYWISH_DIR/app, Konfiguration in $KONFIG" # ------------------------------------------------------------------ Konfiguration schritt "Konfiguration ($ENV_DATEI)" if [ $UPDATE = 0 ]; then - $SUDO test -f "$ENV_DATEI" || $SUDO install -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 600 /dev/null "$ENV_DATEI" + $SUDO test -f "$ENV_DATEI" || $SUDO install -o "$PLAYWISH_USER" -g "$PLAYWISH_USER" -m 600 /dev/null "$ENV_DATEI" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_ID "$SPOTIFY_CLIENT_ID" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_SECRET "$SPOTIFY_CLIENT_SECRET" env_setzen "$ENV_DATEI" SPOTIFY_REDIRECT_URI "http://127.0.0.1:8888/callback" @@ -170,7 +170,7 @@ if [ $UPDATE = 0 ]; then schritt "Spotify-Login für die Wiedergabe-Steuerung" info "Öffne gleich die angezeigte Adresse im Browser, melde dich an und füge danach die" info "Adresse aus der Adresszeile (http://127.0.0.1:8888/callback?...) hier ein." - "${ALS_DIENST[@]}" "$AUDIOFY_DIR/.venv/bin/python" "$AUDIOFY_DIR/app/auth.py" --profil player --env "$ENV_DATEI" \ + "${ALS_DIENST[@]}" "$PLAYWISH_DIR/.venv/bin/python" "$PLAYWISH_DIR/app/auth.py" --profil player --env "$ENV_DATEI" \ || warnung "Login fehlgeschlagen – später nachholen (siehe README)." else # alte Schlüsselnamen übernehmen @@ -179,18 +179,18 @@ else fi # ------------------------------------------------------------------ Dienst -schritt "Dienst audiofy-controller" -vorlage audiofy-controller.service /etc/systemd/system/audiofy-controller.service +schritt "Dienst playwish-controller" +vorlage playwish-controller.service /etc/systemd/system/playwish-controller.service $SUDO systemctl daemon-reload -$SUDO systemctl enable audiofy-controller >/dev/null 2>&1 -$SUDO systemctl restart audiofy-controller +$SUDO systemctl enable playwish-controller >/dev/null 2>&1 +$SUDO systemctl restart playwish-controller sleep 5 -systemctl is-active --quiet audiofy-controller || abbruch "audiofy-controller läuft nicht – siehe: journalctl -u audiofy-controller" -info "audiofy-controller läuft" +systemctl is-active --quiet playwish-controller || abbruch "playwish-controller läuft nicht – siehe: journalctl -u playwish-controller" +info "playwish-controller läuft" # ------------------------------------------------------------------ Zusammenfassung schritt "Fertig" -info "Logs: journalctl -u audiofy-controller -f · journalctl -u raspotify -f" +info "Logs: journalctl -u playwish-controller -f · journalctl -u raspotify -f" if [ $UPDATE = 0 ]; then info "" info "Wichtig: Wähle das Gerät „$GERAETENAME“ EINMAL in der Spotify-App aus (im selben Netz)." diff --git a/install/install-server.sh b/install/install-server.sh index 21eea54..a9a5fcc 100755 --- a/install/install-server.sh +++ b/install/install-server.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Audiofy – Installation der Rolle "Server": Website für Gäste, Admin-Bereich, Player-API. +# Playwish – Installation der Rolle "Server": Website für Gäste, Admin-Bereich, Player-API. # # install/install-server.sh Neuinstallation (fragt alles Nötige ab) # install/install-server.sh --update nur Code, Python-Umgebung und Dienst aktualisieren @@ -18,14 +18,14 @@ for arg in "$@"; do esac done -ENV_DATEI="$AUDIOFY_DIR/.env" -export AUDIOFY_DIR AUDIOFY_USER +ENV_DATEI="$PLAYWISH_DIR/.env" +export PLAYWISH_DIR PLAYWISH_USER export APP_PORT="${APP_PORT:-8000}" -schritt "Audiofy-Server: $([ $UPDATE = 1 ] && echo Update || echo Neuinstallation)" +schritt "Playwish-Server: $([ $UPDATE = 1 ] && echo Update || echo Neuinstallation)" pruefe_system if [ $UPDATE = 1 ] && ! $SUDO test -f "$ENV_DATEI"; then - abbruch "Keine bestehende Installation in $AUDIOFY_DIR gefunden – ohne --update ausführen." + abbruch "Keine bestehende Installation in $PLAYWISH_DIR gefunden – ohne --update ausführen." fi # ------------------------------------------------------------------ Abfragen @@ -67,20 +67,20 @@ pakete "${PAKETE[@]}" # ------------------------------------------------------------------ Benutzer, Ordner, Code schritt "Dienst-Benutzer, Ordner und Code" dienst_benutzer -$SUDO install -d -o root -g "$AUDIOFY_USER" -m 750 "$AUDIOFY_DIR" -$SUDO install -d -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 700 "$AUDIOFY_DIR/data" -code_kopieren "$REPO/server" "$AUDIOFY_DIR/app" -$SUDO install -o root -g "$AUDIOFY_USER" -m 640 "$REPO/player/auth.py" "$AUDIOFY_DIR/app/auth.py" -venv_einrichten "$AUDIOFY_DIR/app/requirements.txt" -info "Code in $AUDIOFY_DIR/app, Python-Umgebung in $AUDIOFY_DIR/.venv" +$SUDO install -d -o root -g "$PLAYWISH_USER" -m 750 "$PLAYWISH_DIR" +$SUDO install -d -o "$PLAYWISH_USER" -g "$PLAYWISH_USER" -m 700 "$PLAYWISH_DIR/data" +code_kopieren "$REPO/server" "$PLAYWISH_DIR/app" +$SUDO install -o root -g "$PLAYWISH_USER" -m 640 "$REPO/player/auth.py" "$PLAYWISH_DIR/app/auth.py" +venv_einrichten "$PLAYWISH_DIR/app/requirements.txt" +info "Code in $PLAYWISH_DIR/app, Python-Umgebung in $PLAYWISH_DIR/.venv" # ------------------------------------------------------------------ Konfiguration schritt "Konfiguration ($ENV_DATEI)" -$SUDO test -f "$ENV_DATEI" || $SUDO install -o "$AUDIOFY_USER" -g "$AUDIOFY_USER" -m 600 /dev/null "$ENV_DATEI" -VERWALTUNG=("${ALS_DIENST[@]}" "$AUDIOFY_DIR/.venv/bin/python" "$AUDIOFY_DIR/app/verwaltung.py") +$SUDO test -f "$ENV_DATEI" || $SUDO install -o "$PLAYWISH_USER" -g "$PLAYWISH_USER" -m 600 /dev/null "$ENV_DATEI" +VERWALTUNG=("${ALS_DIENST[@]}" "$PLAYWISH_DIR/.venv/bin/python" "$PLAYWISH_DIR/app/verwaltung.py") "${VERWALTUNG[@]}" geheimnisse --env "$ENV_DATEI" | sed 's/^/ /' if [ $UPDATE = 0 ]; then - env_setzen "$ENV_DATEI" DB_PATH "$AUDIOFY_DIR/data/audiofy.db" + env_setzen "$ENV_DATEI" DB_PATH "$PLAYWISH_DIR/data/playwish.db" env_setzen "$ENV_DATEI" PUBLIC_URL "https://$DOMAIN" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_ID "$SPOTIFY_CLIENT_ID" env_setzen "$ENV_DATEI" SPOTIFY_CLIENT_SECRET "$SPOTIFY_CLIENT_SECRET" @@ -91,7 +91,7 @@ if [ $UPDATE = 0 ]; then info "Öffne gleich die angezeigte Adresse im Browser, melde dich an und füge danach die" info "Adresse aus der Adresszeile (http://127.0.0.1:8888/callback?...) hier ein." if ja_nein "Jetzt anmelden?" j; then - "${ALS_DIENST[@]}" "$AUDIOFY_DIR/.venv/bin/python" "$AUDIOFY_DIR/app/auth.py" --profil server --env "$ENV_DATEI" \ + "${ALS_DIENST[@]}" "$PLAYWISH_DIR/.venv/bin/python" "$PLAYWISH_DIR/app/auth.py" --profil server --env "$ENV_DATEI" \ || warnung "Login fehlgeschlagen – später nachholen (siehe README)." fi @@ -103,19 +103,19 @@ if [ $UPDATE = 0 ]; then fi # ------------------------------------------------------------------ Dienst -schritt "Dienst audiofy-web" -vorlage audiofy-web.service /etc/systemd/system/audiofy-web.service +schritt "Dienst playwish-web" +vorlage playwish-web.service /etc/systemd/system/playwish-web.service $SUDO systemctl daemon-reload -$SUDO systemctl enable audiofy-web >/dev/null 2>&1 -$SUDO systemctl restart audiofy-web +$SUDO systemctl enable playwish-web >/dev/null 2>&1 +$SUDO systemctl restart playwish-web sleep 3 -systemctl is-active --quiet audiofy-web || abbruch "audiofy-web läuft nicht – siehe: journalctl -u audiofy-web" -curl -fsS "http://127.0.0.1:$APP_PORT/healthz" >/dev/null && info "audiofy-web läuft" +systemctl is-active --quiet playwish-web || abbruch "playwish-web läuft nicht – siehe: journalctl -u playwish-web" +curl -fsS "http://127.0.0.1:$APP_PORT/healthz" >/dev/null && info "playwish-web läuft" # ------------------------------------------------------------------ Caddy & Schutz (nur Neuinstallation) if [ $UPDATE = 0 ]; then schritt "Caddy (HTTPS)" - if $SUDO grep -q "Audiofy" /etc/caddy/Caddyfile 2>/dev/null || $SUDO grep -q "/usr/share/caddy" /etc/caddy/Caddyfile 2>/dev/null; then + if $SUDO grep -q "Playwish" /etc/caddy/Caddyfile 2>/dev/null || $SUDO grep -q "/usr/share/caddy" /etc/caddy/Caddyfile 2>/dev/null; then vorlage Caddyfile /etc/caddy/Caddyfile $SUDO caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null 2>&1 || abbruch "Caddyfile ungültig" $SUDO systemctl enable caddy >/dev/null 2>&1 @@ -138,7 +138,7 @@ if [ $UPDATE = 0 ]; then fi if [ $FAIL2BAN = 1 ]; then schritt "fail2ban" - vorlage fail2ban-audiofy.conf /etc/fail2ban/jail.d/audiofy.conf + vorlage fail2ban-playwish.conf /etc/fail2ban/jail.d/playwish.conf $SUDO systemctl enable fail2ban >/dev/null 2>&1 $SUDO systemctl restart fail2ban info "SSH-Schutz auf Port $SSH_PORT aktiv" @@ -150,7 +150,7 @@ if [ $UPDATE = 0 ]; then fi schritt "Logs begrenzen" $SUDO install -d /etc/systemd/journald.conf.d - vorlage journald-10-audiofy.conf /etc/systemd/journald.conf.d/10-audiofy.conf + vorlage journald-10-playwish.conf /etc/systemd/journald.conf.d/10-playwish.conf $SUDO systemctl restart systemd-journald info "journald max. 200 MB" fi @@ -160,11 +160,11 @@ schritt "Fertig" URL="$(env_wert "$ENV_DATEI" PUBLIC_URL)" info "Website: $URL (Gäste nur mit Einladungslink/QR-Code)" info "Admin: $URL/admin" -info "Logs: journalctl -u audiofy-web -f" +info "Logs: journalctl -u playwish-web -f" if [ $UPDATE = 0 ]; then info "" info "Für die Player-Installation brauchst du:" info " Server-Adresse: $URL" - info " Player-Token: sudo -u $AUDIOFY_USER grep PLAYER_API_TOKEN $ENV_DATEI" + info " Player-Token: sudo -u $PLAYWISH_USER grep PLAYER_API_TOKEN $ENV_DATEI" info "Gastzugang ist anfangs aus – im Admin unter „Gäste“ einschalten." fi diff --git a/install/lib.sh b/install/lib.sh index cb9b4ac..e08d185 100644 --- a/install/lib.sh +++ b/install/lib.sh @@ -1,17 +1,17 @@ -# Audiofy – gemeinsame Hilfsfunktionen für die Install-Skripte (wird per "source" geladen) +# Playwish – gemeinsame Hilfsfunktionen für die Install-Skripte (wird per "source" geladen) # shellcheck shell=bash -AUDIOFY_DIR="${AUDIOFY_DIR:-/opt/audiofy}" -AUDIOFY_USER="${AUDIOFY_USER:-audiofy}" +PLAYWISH_DIR="${PLAYWISH_DIR:-/opt/playwish}" +PLAYWISH_USER="${PLAYWISH_USER:-playwish}" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" VORLAGEN="$REPO/install/vorlagen" if [ "$(id -u)" -eq 0 ]; then SUDO="" - ALS_DIENST=(runuser -u "$AUDIOFY_USER" --) + ALS_DIENST=(runuser -u "$PLAYWISH_USER" --) else SUDO="sudo" - ALS_DIENST=(sudo -u "$AUDIOFY_USER") + ALS_DIENST=(sudo -u "$PLAYWISH_USER") fi # --- Ausgabe ------------------------------------------------------------------ @@ -67,31 +67,31 @@ pakete() { } dienst_benutzer() { - if ! id "$AUDIOFY_USER" >/dev/null 2>&1; then - $SUDO useradd --system --home-dir "$AUDIOFY_DIR" --no-create-home --shell /usr/sbin/nologin "$AUDIOFY_USER" - info "Dienst-Benutzer '$AUDIOFY_USER' angelegt (ohne Login, ohne sudo)" + if ! id "$PLAYWISH_USER" >/dev/null 2>&1; then + $SUDO useradd --system --home-dir "$PLAYWISH_DIR" --no-create-home --shell /usr/sbin/nologin "$PLAYWISH_USER" + info "Dienst-Benutzer '$PLAYWISH_USER' angelegt (ohne Login, ohne sudo)" fi } # code_kopieren QUELLE ZIEL – ersetzt den Inhalt von ZIEL (gehört root, Dienst darf nur lesen) code_kopieren() { local quelle="$1" ziel="$2" - $SUDO install -d -o root -g "$AUDIOFY_USER" -m 750 "$ziel" + $SUDO install -d -o root -g "$PLAYWISH_USER" -m 750 "$ziel" $SUDO find "$ziel" -mindepth 1 -delete tar -C "$quelle" --exclude='__pycache__' --exclude='.venv' --exclude='.pytest_cache' --exclude='tests' -cf - . \ | $SUDO tar -C "$ziel" --no-same-owner -xf - - $SUDO chown -R root:"$AUDIOFY_USER" "$ziel" + $SUDO chown -R root:"$PLAYWISH_USER" "$ziel" $SUDO find "$ziel" -type d -exec chmod 750 {} + $SUDO find "$ziel" -type f -exec chmod 640 {} + } # venv_einrichten REQUIREMENTS venv_einrichten() { - local venv="$AUDIOFY_DIR/.venv" + local venv="$PLAYWISH_DIR/.venv" [ -x "$venv/bin/python" ] || $SUDO python3 -m venv "$venv" $SUDO "$venv/bin/pip" install -q --upgrade pip $SUDO "$venv/bin/pip" install -q -r "$1" - $SUDO chown -R root:"$AUDIOFY_USER" "$venv" + $SUDO chown -R root:"$PLAYWISH_USER" "$venv" $SUDO chmod -R g+rX,o-rwx "$venv" } diff --git a/install/vorlagen/Caddyfile b/install/vorlagen/Caddyfile index 308bc96..252d413 100644 --- a/install/vorlagen/Caddyfile +++ b/install/vorlagen/Caddyfile @@ -1,4 +1,4 @@ -# Audiofy – Caddy-Konfiguration (erzeugt von install-server.sh) +# Playwish – Caddy-Konfiguration (erzeugt von install-server.sh) { email {{ACME_EMAIL}} servers { diff --git a/install/vorlagen/audiofy-web.service b/install/vorlagen/audiofy-web.service deleted file mode 100644 index 6d82f4f..0000000 --- a/install/vorlagen/audiofy-web.service +++ /dev/null @@ -1,30 +0,0 @@ -[Unit] -Description=Audiofy – Website, Admin-Bereich und Player-API -After=network-online.target -Wants=network-online.target - -[Service] -User={{AUDIOFY_USER}} -Group={{AUDIOFY_USER}} -WorkingDirectory={{AUDIOFY_DIR}}/app -Environment=AUDIOFY_ENV={{AUDIOFY_DIR}}/.env -ExecStart={{AUDIOFY_DIR}}/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port {{APP_PORT}} --workers 1 --no-access-log --proxy-headers --forwarded-allow-ips 127.0.0.1 -Restart=always -RestartSec=3 -UMask=0077 -# Härtung -NoNewPrivileges=yes -ProtectSystem=strict -ProtectHome=yes -ReadWritePaths={{AUDIOFY_DIR}}/data {{AUDIOFY_DIR}}/.env -PrivateTmp=yes -PrivateDevices=yes -ProtectKernelTunables=yes -ProtectKernelModules=yes -ProtectControlGroups=yes -RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX -LockPersonality=yes -MemoryMax=300M - -[Install] -WantedBy=multi-user.target diff --git a/install/vorlagen/fail2ban-audiofy.conf b/install/vorlagen/fail2ban-playwish.conf similarity index 68% rename from install/vorlagen/fail2ban-audiofy.conf rename to install/vorlagen/fail2ban-playwish.conf index a8a9f95..5261c5d 100644 --- a/install/vorlagen/fail2ban-audiofy.conf +++ b/install/vorlagen/fail2ban-playwish.conf @@ -1,4 +1,4 @@ -# Audiofy – SSH gegen Passwort-Raten schützen +# Playwish – SSH gegen Passwort-Raten schützen [sshd] enabled = true port = {{SSH_PORT}} diff --git a/install/vorlagen/journald-10-audiofy.conf b/install/vorlagen/journald-10-playwish.conf similarity index 100% rename from install/vorlagen/journald-10-audiofy.conf rename to install/vorlagen/journald-10-playwish.conf diff --git a/install/vorlagen/audiofy-controller.service b/install/vorlagen/playwish-controller.service similarity index 63% rename from install/vorlagen/audiofy-controller.service rename to install/vorlagen/playwish-controller.service index e6235e0..f9fb52d 100644 --- a/install/vorlagen/audiofy-controller.service +++ b/install/vorlagen/playwish-controller.service @@ -1,15 +1,15 @@ [Unit] -Description=Audiofy – Controller (Spotify-Steuerung, Wünsche vom Server) +Description=Playwish – Controller (Spotify-Steuerung, Wünsche vom Server) After=network-online.target bluetooth.target raspotify.service Wants=network-online.target raspotify.service # nie aufgeben, immer wieder neu starten StartLimitIntervalSec=0 [Service] -User={{AUDIOFY_USER}} -Group={{AUDIOFY_USER}} -WorkingDirectory={{AUDIOFY_DIR}}/app -ExecStart={{AUDIOFY_DIR}}/.venv/bin/python -u {{AUDIOFY_DIR}}/app/controller.py --env {{AUDIOFY_DIR}}/config/.env +User={{PLAYWISH_USER}} +Group={{PLAYWISH_USER}} +WorkingDirectory={{PLAYWISH_DIR}}/app +ExecStart={{PLAYWISH_DIR}}/.venv/bin/python -u {{PLAYWISH_DIR}}/app/controller.py --env {{PLAYWISH_DIR}}/config/.env Restart=always RestartSec=5 UMask=0077 @@ -17,7 +17,7 @@ UMask=0077 NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes -ReadWritePaths={{AUDIOFY_DIR}}/config +ReadWritePaths={{PLAYWISH_DIR}}/config PrivateTmp=yes PrivateDevices=yes ProtectKernelTunables=yes diff --git a/install/vorlagen/playwish-web.service b/install/vorlagen/playwish-web.service new file mode 100644 index 0000000..5b79305 --- /dev/null +++ b/install/vorlagen/playwish-web.service @@ -0,0 +1,30 @@ +[Unit] +Description=Playwish – Website, Admin-Bereich und Player-API +After=network-online.target +Wants=network-online.target + +[Service] +User={{PLAYWISH_USER}} +Group={{PLAYWISH_USER}} +WorkingDirectory={{PLAYWISH_DIR}}/app +Environment=PLAYWISH_ENV={{PLAYWISH_DIR}}/.env +ExecStart={{PLAYWISH_DIR}}/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port {{APP_PORT}} --workers 1 --no-access-log --proxy-headers --forwarded-allow-ips 127.0.0.1 +Restart=always +RestartSec=3 +UMask=0077 +# Härtung +NoNewPrivileges=yes +ProtectSystem=strict +ProtectHome=yes +ReadWritePaths={{PLAYWISH_DIR}}/data {{PLAYWISH_DIR}}/.env +PrivateTmp=yes +PrivateDevices=yes +ProtectKernelTunables=yes +ProtectKernelModules=yes +ProtectControlGroups=yes +RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX +LockPersonality=yes +MemoryMax=300M + +[Install] +WantedBy=multi-user.target diff --git a/install/vorlagen/raspotify-10-audiofy.conf b/install/vorlagen/raspotify-10-playwish.conf similarity index 57% rename from install/vorlagen/raspotify-10-audiofy.conf rename to install/vorlagen/raspotify-10-playwish.conf index c3ebbfb..f10ca8f 100644 --- a/install/vorlagen/raspotify-10-audiofy.conf +++ b/install/vorlagen/raspotify-10-playwish.conf @@ -1,4 +1,4 @@ -# Audiofy: raspotify nie endgültig aufgeben (z. B. wenn der Lautsprecher kurz fehlt +# Playwish: raspotify nie endgültig aufgeben (z. B. wenn der Lautsprecher kurz fehlt # oder das Netz beim Start noch nicht da ist) [Unit] StartLimitIntervalSec=0 diff --git a/install/vorlagen/sshd-10-audiofy.conf b/install/vorlagen/sshd-10-playwish.conf similarity index 71% rename from install/vorlagen/sshd-10-audiofy.conf rename to install/vorlagen/sshd-10-playwish.conf index de3e196..45d7989 100644 --- a/install/vorlagen/sshd-10-audiofy.conf +++ b/install/vorlagen/sshd-10-playwish.conf @@ -1,4 +1,4 @@ -# Audiofy – SSH-Härtung (NICHT automatisch installiert, siehe README „Server härten“) +# Playwish – SSH-Härtung (NICHT automatisch installiert, siehe README „Server härten“) # Erst einsetzen, wenn der Login per Schlüssel für {{ADMIN_USER}} nachweislich klappt! Port {{SSH_PORT}} PermitRootLogin no diff --git a/player/auth.py b/player/auth.py index 5c33d7d..d643c27 100755 --- a/player/auth.py +++ b/player/auth.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Audiofy – einmaliger Spotify-Login (Authorization Code Flow). +"""Playwish – einmaliger Spotify-Login (Authorization Code Flow). Holt einen Refresh-Token für das eigene Spotify-Konto und schreibt ihn in die .env-Datei. Funktioniert ohne Browser auf dem Gerät selbst: @@ -11,8 +11,8 @@ Holt einen Refresh-Token für das eigene Spotify-Konto und schreibt ihn in die und hier einfügen. Aufruf: - python3 auth.py --env /opt/audiofy/config/.env # Player (Wiedergabe steuern) - python3 auth.py --profil server --env /opt/audiofy/.env # Server (nur Suche) + python3 auth.py --env /opt/playwish/config/.env # Player (Wiedergabe steuern) + python3 auth.py --profil server --env /opt/playwish/.env # Server (nur Suche) Benötigte Einträge in der .env: SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET, optional SPOTIFY_REDIRECT_URI. Nur Python-Standardbibliothek, kein venv nötig. @@ -75,7 +75,7 @@ def env_setzen(pfad: Path, key: str, wert: str) -> None: inhalt = "\n".join(neu) + "\n" if not os.access(pfad.parent, os.W_OK): - # z. B. Server: /opt/audiofy gehört root, nur die .env selbst dem Dienst-Benutzer + # z. B. Server: /opt/playwish gehört root, nur die .env selbst dem Dienst-Benutzer fd = os.open(pfad, os.O_WRONLY | os.O_TRUNC) with os.fdopen(fd, "w") as f: f.write(inhalt) @@ -112,7 +112,7 @@ def me_abfragen(access_token: str) -> dict: def main() -> None: - parser = argparse.ArgumentParser(description="Audiofy – Spotify-Login, schreibt den Refresh-Token in die .env") + parser = argparse.ArgumentParser(description="Playwish – Spotify-Login, schreibt den Refresh-Token in die .env") parser.add_argument("--profil", choices=SCOPES, default="player", help="Scope-Satz (Standard: player)") parser.add_argument("--env", type=Path, default=Path(__file__).resolve().parent / ".env", help="Pfad zur .env (Standard: neben dem Skript)") diff --git a/player/controller.py b/player/controller.py index 365e93d..1dddba3 100644 --- a/player/controller.py +++ b/player/controller.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -"""Audiofy – Controller (Player). +"""Playwish – Controller (Player). Spielt zufällige Titel aus der Grund-Playlist auf dem Spotify-Connect-Gerät -"Audiofy" und schiebt nach jeweils N-1 Playlist-Titeln einen Wunsch ein. +"Playwish" und schiebt nach jeweils N-1 Playlist-Titeln einen Wunsch ein. Spotify bekommt immer nur den jeweils nächsten Titel (POST /me/player/queue, ca. 15 s vor Titelende); die Reihenfolge verwaltet ausschließlich der Controller. @@ -14,7 +14,7 @@ Ist der Server nicht erreichbar, läuft einfach die Grund-Playlist weiter. Bedienung über die Spotify-App bleibt möglich: Fremde Titel werden erkannt und geduldet, eine Pause durch den Besitzer (App oder Admin-Bereich) wird respektiert. -Aufruf: .venv/bin/python controller.py --env /opt/audiofy/config/.env +Aufruf: .venv/bin/python controller.py --env /opt/playwish/config/.env """ import argparse @@ -38,7 +38,7 @@ from auth import env_lesen, env_setzen from spotify_client import SpotifyClient, SpotifyFehler from server_client import ServerVerbindung, Wunsch -log = logging.getLogger("audiofy.controller") +log = logging.getLogger("playwish.controller") ORDNER = Path(__file__).resolve().parent POLL_S = 3 # Abfrageintervall /me/player und Server @@ -289,7 +289,7 @@ class Controller: return None def starten(self) -> None: - """Wiedergabe auf dem Gerät "Audiofy" (neu) starten.""" + """Wiedergabe auf dem Gerät "Playwish" (neu) starten.""" gid = self.geraet_id() if not gid: # Warnung beim ersten Mal, danach höchstens einmal pro Minute @@ -547,7 +547,7 @@ class Controller: log.info("Als Nächstes eingereiht: %s [%s]", eintrag.uri, eintrag.quelle) return - # --- es läuft nichts (auf Audiofy) --- + # --- es läuft nichts (auf Playwish) --- if self.bt_pause: # librespot pausiert bei Audiofehlern selbst – nach Neuverbindung fortsetzen if self.lautsprecher_bereit(): @@ -558,13 +558,13 @@ class Controller: log.info("Lautsprecher wieder da – Wiedergabe fortgesetzt") return if vorher is None: - # Controller-Start: pausierter Titel auf Audiofy = Besitzer-Pause, sonst starten + # Controller-Start: pausierter Titel auf Playwish = Besitzer-Pause, sonst starten if st and unser and item and fortschritt >= PAUSE_MIN_MS: if not self._bt_pruefen_jetzt(): - log.warning("Audiofy pausiert und Lautsprecher getrennt – geht nach Neuverbindung weiter") + log.warning("Playwish pausiert und Lautsprecher getrennt – geht nach Neuverbindung weiter") self.bt_pause = True else: - log.info("Audiofy ist pausiert – warte, bis der Besitzer fortsetzt") + log.info("Playwish ist pausiert – warte, bis der Besitzer fortsetzt") self.besitzer_pause = True else: self.neustart = True @@ -708,7 +708,7 @@ class Controller: def main() -> None: - parser = argparse.ArgumentParser(description="Audiofy-Controller") + parser = argparse.ArgumentParser(description="Playwish-Controller") parser.add_argument("--env", type=Path, default=ORDNER / ".env") args = parser.parse_args() @@ -741,7 +741,7 @@ def main() -> None: Playlist(sp, env.get("SPOTIFY_PLAYLIST_ID", ""), int(env.get("PLAYLIST_REPEAT_PERCENT") or 50)), server, n=int(env.get("WISH_EVERY_N") or 3), - geraetename=env.get("DEVICE_NAME") or "Audiofy", + geraetename=env.get("DEVICE_NAME") or "Playwish", bt_mac=env.get("BT_SPEAKER_MAC") or None, zustand_pfad=args.env.parent / "zustand.json", env_pfad=args.env, diff --git a/player/lautsprecher.py b/player/lautsprecher.py index 2660d53..a935707 100644 --- a/player/lautsprecher.py +++ b/player/lautsprecher.py @@ -1,4 +1,4 @@ -"""Audiofy – Bluetooth-Lautsprecher suchen, koppeln und verbinden (bluetoothctl, ohne sudo). +"""Playwish – Bluetooth-Lautsprecher suchen, koppeln und verbinden (bluetoothctl, ohne sudo). Gekoppelt wird immer MIT Agent in derselben bluetoothctl-Sitzung – sonst speichert BlueZ den Schlüssel nicht dauerhaft ("Bonded: no"), und der Lautsprecher lässt sich @@ -11,7 +11,7 @@ import shutil import subprocess import time -log = logging.getLogger("audiofy.lautsprecher") +log = logging.getLogger("playwish.lautsprecher") MAC_RE = re.compile(r"^([0-9A-F]{2}:){5}[0-9A-F]{2}$") SUCHDAUER_S = 15 diff --git a/player/server_client.py b/player/server_client.py index b66f050..aed2098 100644 --- a/player/server_client.py +++ b/player/server_client.py @@ -1,4 +1,4 @@ -"""Audiofy – Verbindung Player → Server (Player-API mit Bearer-Token, nur ausgehend). +"""Playwish – Verbindung Player → Server (Player-API mit Bearer-Token, nur ausgehend). Alle Aufrufe fangen Fehler selbst ab: Ist der Server nicht erreichbar, liefern sie None/False, und der Controller spielt einfach die Grund-Playlist weiter. Im @@ -11,7 +11,7 @@ from dataclasses import dataclass import httpx -log = logging.getLogger("audiofy.server") +log = logging.getLogger("playwish.server") OFFLINE_RETRY_S = 15 TIMEOUT_S = 5 diff --git a/player/spotify_client.py b/player/spotify_client.py index 51fbb84..b33d4b4 100644 --- a/player/spotify_client.py +++ b/player/spotify_client.py @@ -1,4 +1,4 @@ -"""Audiofy – schlanker Spotify-Web-API-Client für den Controller (httpx). +"""Playwish – schlanker Spotify-Web-API-Client für den Controller (httpx). Erneuert den Access-Token selbst per Refresh-Token. Fehler werden als SpotifyFehler geworfen (bei 429 mit retry_after); Netzwerkfehler kommen als @@ -12,7 +12,7 @@ from collections.abc import Callable import httpx -log = logging.getLogger("audiofy.spotify") +log = logging.getLogger("playwish.spotify") API = "https://api.spotify.com/v1" TOKEN_URL = "https://accounts.spotify.com/api/token" diff --git a/player/tests/test_playlist.py b/player/tests/test_playlist.py index b14ae80..a7f1453 100644 --- a/player/tests/test_playlist.py +++ b/player/tests/test_playlist.py @@ -93,7 +93,7 @@ def test_ein_titel_bleibt_immer_frei(): def test_zustand_speichert_zuletzt(tmp_path): datei = tmp_path / "zustand.json" neu = lambda: Controller(sp=None, playlist=Playlist(FakeSpotify(TITEL), "liste", 50), server=None, # noqa: E731 - n=3, geraetename="Audiofy", bt_mac=None, zustand_pfad=datei) + n=3, geraetename="Playwish", bt_mac=None, zustand_pfad=datei) c = neu() c.playlist.gespielt(TITEL[3]) c.playlist.gespielt(TITEL[4]) diff --git a/player/tests/test_robustheit.py b/player/tests/test_robustheit.py index 9451774..60f9404 100644 --- a/player/tests/test_robustheit.py +++ b/player/tests/test_robustheit.py @@ -42,7 +42,7 @@ class FakeServer: def controller(sp, server): - c = Controller(sp=sp, playlist=Playlist(sp, "liste"), server=server, n=1, geraetename="Audiofy", bt_mac=None) + c = Controller(sp=sp, playlist=Playlist(sp, "liste"), server=server, n=1, geraetename="Playwish", bt_mac=None) return c diff --git a/server/app/__init__.py b/server/app/__init__.py index 78c5ed9..34a4573 100644 --- a/server/app/__init__.py +++ b/server/app/__init__.py @@ -1 +1 @@ -"""Audiofy-Web – Website, Admin-Bereich und Player-API (läuft auf dem Server).""" +"""Playwish-Web – Website, Admin-Bereich und Player-API (läuft auf dem Server).""" diff --git a/server/app/admin.py b/server/app/admin.py index 7456bce..c0c574a 100644 --- a/server/app/admin.py +++ b/server/app/admin.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – Admin-Bereich (/admin): der Besitzer steuert alles, auch vom Handy. +"""Playwish-Web – Admin-Bereich (/admin): der Besitzer steuert alles, auch vom Handy. Zugang: - Passwort als argon2-Hash in der .env (ADMIN_PASSWORD_HASH, gesetzt per verwaltung.py) @@ -36,7 +36,7 @@ from .spotify import Spotify, SpotifyFehler, spotify router = APIRouter() -ADMIN_COOKIE = "audiofy_admin" +ADMIN_COOKIE = "playwish_admin" SITZUNG_TAGE = 14 login_drossel = Drossel(5, 15 * 60) _hasher = PasswordHasher() @@ -390,7 +390,7 @@ def zugang_qr(request: Request, format: Literal["svg", "png"] = "svg", if format == "png": qr.save(puffer, kind="png", scale=16, border=3) return Response(puffer.getvalue(), media_type="image/png", headers={ - "Content-Disposition": 'attachment; filename="audiofy-einladung.png"', "Cache-Control": "no-store"}) + "Content-Disposition": 'attachment; filename="playwish-einladung.png"', "Cache-Control": "no-store"}) qr.save(puffer, kind="svg", scale=8, border=2, xmldecl=False, svgns=True) return Response(puffer.getvalue(), media_type="image/svg+xml", headers={"Cache-Control": "no-store"}) diff --git a/server/app/config.py b/server/app/config.py index 1951b02..af23d17 100644 --- a/server/app/config.py +++ b/server/app/config.py @@ -1,6 +1,6 @@ -"""Audiofy-Web – Konfiguration aus der .env. +"""Playwish-Web – Konfiguration aus der .env. -Pfad über die Umgebungsvariable AUDIOFY_ENV, Standard /opt/audiofy/.env. +Pfad über die Umgebungsvariable PLAYWISH_ENV, Standard /opt/playwish/.env. Geheimnisse stehen nur dort (Rechte 600), nie im Code oder in Logs. """ @@ -51,11 +51,11 @@ def env_wert_setzen(pfad: Path, key: str, wert: str) -> None: @lru_cache def konfig() -> Konfig: - pfad = Path(os.environ.get("AUDIOFY_ENV", "/opt/audiofy/.env")) + pfad = Path(os.environ.get("PLAYWISH_ENV", "/opt/playwish/.env")) werte = env_lesen(pfad) if pfad.is_file() else {} return Konfig( env_pfad=pfad, - db_pfad=Path(werte.get("DB_PATH") or "/opt/audiofy/data/audiofy.db"), + db_pfad=Path(werte.get("DB_PATH") or "/opt/playwish/data/playwish.db"), player_api_token=werte.get("PLAYER_API_TOKEN") or werte.get("PI_API_TOKEN", ""), # alter Name spotify_client_id=werte.get("SPOTIFY_CLIENT_ID", ""), spotify_client_secret=werte.get("SPOTIFY_CLIENT_SECRET", ""), diff --git a/server/app/db.py b/server/app/db.py index b018802..bf5689a 100644 --- a/server/app/db.py +++ b/server/app/db.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – SQLite-Datenbank (audiofy.db): Schema, Einstellungen, Hilfsfunktionen. +"""Playwish-Web – SQLite-Datenbank (playwish.db): Schema, Einstellungen, Hilfsfunktionen. Zeitstempel sind UTC im ISO-Format (lexikografisch vergleichbar). """ diff --git a/server/app/gaeste.py b/server/app/gaeste.py index 954bed4..96e5f75 100644 --- a/server/app/gaeste.py +++ b/server/app/gaeste.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – Gastseite: Suche, Wünschen, "Läuft gerade" und Warteschlange. +"""Playwish-Web – Gastseite: Suche, Wünschen, "Läuft gerade" und Warteschlange. Zugang nur mit Einladung: Der Link /z/ (auch als QR-Code im Admin-Bereich) setzt ein Zugangs-Cookie. Ohne gültigen Zugang gibt es nur eine Hinweisseite, die @@ -42,8 +42,8 @@ from .spotify import Spotify, SpotifyFehler, spotify router = APIRouter() STATIC = Path(__file__).parent / "static" -GAST_COOKIE = "audiofy_gast" -ZUGANG_COOKIE = "audiofy_zugang" +GAST_COOKIE = "playwish_gast" +ZUGANG_COOKIE = "playwish_zugang" ZUGANG_TAGE = 30 GAST_RE = re.compile(r"^[A-Za-z0-9_-]{22}$") PLAYER_OFFLINE_S = 30 # ohne Lebenszeichen gilt der Player als offline @@ -92,7 +92,7 @@ def gast_cookie_setzen(response: Response, gid: str) -> None: def _geheimnis() -> bytes: - return (konfig().session_secret or "audiofy").encode() + return (konfig().session_secret or "playwish").encode() def zugangs_wert(token: str) -> str: diff --git a/server/app/main.py b/server/app/main.py index ae1868d..e37e15d 100644 --- a/server/app/main.py +++ b/server/app/main.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – FastAPI-Anwendung. +"""Playwish-Web – FastAPI-Anwendung. Start (Server): uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 1 --no-access-log Caddy terminiert HTTPS und leitet an 127.0.0.1:8000 weiter. @@ -26,7 +26,7 @@ async def lifespan(app: FastAPI): # Keine automatische API-Doku öffentlich ausliefern -app = FastAPI(title="Audiofy – Musikwünsche", lifespan=lifespan, docs_url=None, redoc_url=None, openapi_url=None) +app = FastAPI(title="Playwish – Musikwünsche", lifespan=lifespan, docs_url=None, redoc_url=None, openapi_url=None) @app.middleware("http") diff --git a/server/app/player_api.py b/server/app/player_api.py index cb628dd..35bf61d 100644 --- a/server/app/player_api.py +++ b/server/app/player_api.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – Player-API (/api/player/…), geschützt per Bearer-Token (PLAYER_API_TOKEN). +"""Playwish-Web – Player-API (/api/player/…), geschützt per Bearer-Token (PLAYER_API_TOKEN). Der Player baut nur ausgehende Verbindungen auf und fragt hier ca. alle 3 s nach: GET /api/player/config Einstellungen + offene Befehle (Ziel: Reaktion < 3 s) @@ -53,7 +53,7 @@ class JetztLaeuft(BaseModel): source: Literal["playlist", "wish", "owner", "fremd"] | None = None wish_id: int | None = None next: Titel | None = None # bereits eingereihter nächster Titel - device_ok: bool = True # Gerät "Audiofy" erreichbar + device_ok: bool = True # Gerät "Playwish" erreichbar speaker_ok: bool = True # Bluetooth-Lautsprecher verbunden stopped: bool = False # Controller im Not-Aus volume_percent: int | None = Field(default=None, ge=0, le=100) diff --git a/server/app/spotify.py b/server/app/spotify.py index 0555eb6..75f37f3 100644 --- a/server/app/spotify.py +++ b/server/app/spotify.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – Spotify-Zugriff für Suche und Titelinfos. +"""Playwish-Web – Spotify-Zugriff für Suche und Titelinfos. Eigener Refresh-Token des Servers (auth.py --profil server, keine Scopes nötig). Im Development Mode liefert die Suche höchstens 10 Treffer. @@ -14,7 +14,7 @@ import httpx from .config import Konfig, env_wert_setzen, konfig -log = logging.getLogger("audiofy.spotify") +log = logging.getLogger("playwish.spotify") API = "https://api.spotify.com/v1" TOKEN_URL = "https://accounts.spotify.com/api/token" diff --git a/server/app/static/admin.css b/server/app/static/admin.css index b2bfd2c..fe0804c 100644 --- a/server/app/static/admin.css +++ b/server/app/static/admin.css @@ -1,4 +1,4 @@ -/* Audiofy – Admin-Bereich (ergänzt app.css) */ +/* Playwish – Admin-Bereich (ergänzt app.css) */ .kopf { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 4px 0 12px; } .kopf h1 { font-size: 1.4rem; } diff --git a/server/app/static/admin.html b/server/app/static/admin.html index 2e11d15..02ea6eb 100644 --- a/server/app/static/admin.html +++ b/server/app/static/admin.html @@ -5,7 +5,7 @@ - Audiofy – Admin + Playwish – Admin @@ -13,7 +13,7 @@
-

Audiofy Admin

+

Playwish Admin

diff --git a/server/app/static/admin.js b/server/app/static/admin.js index 2cb5bbf..b6098bf 100644 --- a/server/app/static/admin.js +++ b/server/app/static/admin.js @@ -1,4 +1,4 @@ -// Audiofy – Admin-Bereich. Daten nur per textContent einsetzen (kein innerHTML mit fremden Inhalten). +// Playwish – Admin-Bereich. Daten nur per textContent einsetzen (kein innerHTML mit fremden Inhalten). "use strict"; const ABFRAGE_MS = 3000; diff --git a/server/app/static/app.css b/server/app/static/app.css index 00d23c2..7750dd4 100644 --- a/server/app/static/app.css +++ b/server/app/static/app.css @@ -1,4 +1,4 @@ -/* Audiofy – Gastseite (mobil zuerst) */ +/* Playwish – Gastseite (mobil zuerst) */ :root { --bg: #121212; --karte: #1e1e1e; diff --git a/server/app/static/app.js b/server/app/static/app.js index 58fcccf..75ea293 100644 --- a/server/app/static/app.js +++ b/server/app/static/app.js @@ -1,4 +1,4 @@ -// Audiofy – Gastseite. Daten nur per textContent einsetzen (kein innerHTML mit fremden Inhalten). +// Playwish – Gastseite. Daten nur per textContent einsetzen (kein innerHTML mit fremden Inhalten). "use strict"; const STATUS_ALLE_MS = 5000; @@ -193,7 +193,7 @@ async function suchen(q) { async function wuenschen(titel, knopf) { knopf.disabled = true; const name = $("name").value.trim(); - try { localStorage.setItem("audiofy-name", name); } catch (_) { /* privat */ } + try { localStorage.setItem("playwish-name", name); } catch (_) { /* privat */ } try { if (!schutz.bereit()) knopf.textContent = "Prüfung …"; const turnstile = await schutz.token(); @@ -214,7 +214,7 @@ async function wuenschen(titel, knopf) { } function start() { - try { $("name").value = localStorage.getItem("audiofy-name") || ""; } catch (_) { /* privat */ } + try { $("name").value = localStorage.getItem("playwish-name") || ""; } catch (_) { /* privat */ } $("suchfeld").addEventListener("input", (ereignis) => { clearTimeout(sucheTimer); @@ -226,7 +226,7 @@ function start() { if (ereignis.key === "Enter") { ereignis.target.blur(); } // Tastatur auf dem Handy schließen }); - window.AudiofyTurnstile.einrichten($("turnstile"), "wish").then((s) => { schutz = s; }); + window.PlaywishTurnstile.einrichten($("turnstile"), "wish").then((s) => { schutz = s; }); ladeStatus(); setInterval(() => { if (!document.hidden) ladeStatus(); }, STATUS_ALLE_MS); diff --git a/server/app/static/index.html b/server/app/static/index.html index e89f204..f05c588 100644 --- a/server/app/static/index.html +++ b/server/app/static/index.html @@ -4,7 +4,7 @@ - Audiofy – Musikwünsche + Playwish – Musikwünsche @@ -13,7 +13,7 @@
-

Audiofy

+

Playwish

Musikwünsche

diff --git a/server/app/static/login.html b/server/app/static/login.html index 832de76..ab5a8c1 100644 --- a/server/app/static/login.html +++ b/server/app/static/login.html @@ -5,7 +5,7 @@ - Audiofy – Admin + Playwish – Admin @@ -15,7 +15,7 @@
-

Audiofy

+

Playwish

Admin-Bereich

diff --git a/server/app/static/login.js b/server/app/static/login.js index c1c6d0c..f29d124 100644 --- a/server/app/static/login.js +++ b/server/app/static/login.js @@ -1,8 +1,8 @@ -// Audiofy – Admin-Login +// Playwish – Admin-Login "use strict"; let schutz = { token: async () => null, reset() {}, bereit: () => true }; // Turnstile (falls aktiv) -window.AudiofyTurnstile.einrichten(document.getElementById("turnstile"), "login").then((s) => { schutz = s; }); +window.PlaywishTurnstile.einrichten(document.getElementById("turnstile"), "login").then((s) => { schutz = s; }); document.getElementById("login").addEventListener("submit", async (ereignis) => { ereignis.preventDefault(); diff --git a/server/app/static/turnstile.js b/server/app/static/turnstile.js index d6f6f67..1c10be6 100644 --- a/server/app/static/turnstile.js +++ b/server/app/static/turnstile.js @@ -1,7 +1,7 @@ -// Audiofy – Cloudflare Turnstile (Bot-Schutz). Lädt das Widget nur, wenn der Server einen Site-Key liefert. +// Playwish – Cloudflare Turnstile (Bot-Schutz). Lädt das Widget nur, wenn der Server einen Site-Key liefert. "use strict"; -window.AudiofyTurnstile = (() => { +window.PlaywishTurnstile = (() => { let ladeVersprechen = null; function skriptLaden() { diff --git a/server/app/static/zugang.html b/server/app/static/zugang.html index 5dcfce3..311af69 100644 --- a/server/app/static/zugang.html +++ b/server/app/static/zugang.html @@ -5,13 +5,13 @@ - Audiofy – Musikwünsche + Playwish – Musikwünsche
-

Audiofy

+

Playwish

Musikwünsche

diff --git a/server/app/turnstile.py b/server/app/turnstile.py index f72c9f8..fe88655 100644 --- a/server/app/turnstile.py +++ b/server/app/turnstile.py @@ -1,4 +1,4 @@ -"""Audiofy-Web – Cloudflare Turnstile: Bot-Schutz für Admin-Login und Wünsche. +"""Playwish-Web – Cloudflare Turnstile: Bot-Schutz für Admin-Login und Wünsche. Kein Domain-Umzug nötig: Der Browser holt sich bei Cloudflare ein Token, der Server prüft es per siteverify. Ohne TURNSTILE_SITE_KEY/TURNSTILE_SECRET_KEY in @@ -16,7 +16,7 @@ from fastapi import HTTPException, Request from .config import konfig -log = logging.getLogger("audiofy.turnstile") +log = logging.getLogger("playwish.turnstile") VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify" diff --git a/server/tests/test_admin.py b/server/tests/test_admin.py index e87ae2e..23b3dad 100644 --- a/server/tests/test_admin.py +++ b/server/tests/test_admin.py @@ -14,9 +14,9 @@ PASSWORT = "richtig-langes-passwort" @pytest.fixture def client(tmp_path, monkeypatch): env = tmp_path / ".env" - env.write_text(f"DB_PATH={tmp_path / 'audiofy.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n" + env.write_text(f"DB_PATH={tmp_path / 'playwish.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n" f"PUBLIC_URL=https://musik.example.de\nADMIN_PASSWORD_HASH={PasswordHasher().hash(PASSWORT)}\n") - monkeypatch.setenv("AUDIOFY_ENV", str(env)) + monkeypatch.setenv("PLAYWISH_ENV", str(env)) config.konfig.cache_clear() for name in ("suche_drossel", "wunsch_drossel", "einladung_drossel"): monkeypatch.setattr(gaeste, name, gaeste.Drossel(1000, 60)) diff --git a/server/tests/test_gaeste.py b/server/tests/test_gaeste.py index 366088e..a7ea0fa 100644 --- a/server/tests/test_gaeste.py +++ b/server/tests/test_gaeste.py @@ -35,8 +35,8 @@ class FakeSpotify: @pytest.fixture def client(tmp_path, monkeypatch): env = tmp_path / ".env" - env.write_text(f"DB_PATH={tmp_path / 'audiofy.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n") - monkeypatch.setenv("AUDIOFY_ENV", str(env)) + env.write_text(f"DB_PATH={tmp_path / 'playwish.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n") + monkeypatch.setenv("PLAYWISH_ENV", str(env)) config.konfig.cache_clear() for name in ("suche_drossel", "wunsch_drossel", "einladung_drossel"): monkeypatch.setattr(gaeste, name, gaeste.Drossel(1000, 60)) diff --git a/server/tests/test_player_api.py b/server/tests/test_player_api.py index 9cfa866..d04a667 100644 --- a/server/tests/test_player_api.py +++ b/server/tests/test_player_api.py @@ -15,8 +15,8 @@ URI_C = "spotify:track:" + "C" * 22 @pytest.fixture def client(tmp_path, monkeypatch): env = tmp_path / ".env" - env.write_text(f"PLAYER_API_TOKEN={TOKEN}\nDB_PATH={tmp_path / 'audiofy.db'}\nSPOTIFY_PLAYLIST_ID=startliste\n") - monkeypatch.setenv("AUDIOFY_ENV", str(env)) + env.write_text(f"PLAYER_API_TOKEN={TOKEN}\nDB_PATH={tmp_path / 'playwish.db'}\nSPOTIFY_PLAYLIST_ID=startliste\n") + monkeypatch.setenv("PLAYWISH_ENV", str(env)) config.konfig.cache_clear() from app.main import app with TestClient(app) as c: diff --git a/server/tests/test_turnstile.py b/server/tests/test_turnstile.py index c88638f..25ac314 100644 --- a/server/tests/test_turnstile.py +++ b/server/tests/test_turnstile.py @@ -30,10 +30,10 @@ def antworten(monkeypatch): @pytest.fixture def client(tmp_path, monkeypatch, antworten): env = tmp_path / ".env" - env.write_text(f"DB_PATH={tmp_path / 'audiofy.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n" + env.write_text(f"DB_PATH={tmp_path / 'playwish.db'}\nSESSION_SECRET=geheim\nCOOKIE_SECURE=0\n" f"PUBLIC_URL=https://musik.example.de\nADMIN_PASSWORD_HASH={PasswordHasher().hash(PASSWORT)}\n" "TURNSTILE_SITE_KEY=site-oeffentlich\nTURNSTILE_SECRET_KEY=secret-geheim\n") - monkeypatch.setenv("AUDIOFY_ENV", str(env)) + monkeypatch.setenv("PLAYWISH_ENV", str(env)) config.konfig.cache_clear() for name in ("suche_drossel", "wunsch_drossel", "einladung_drossel"): monkeypatch.setattr(gaeste, name, gaeste.Drossel(1000, 60)) diff --git a/server/verwaltung.py b/server/verwaltung.py index 6d2d342..e031b82 100644 --- a/server/verwaltung.py +++ b/server/verwaltung.py @@ -1,12 +1,12 @@ #!/usr/bin/env python3 -"""Audiofy-Web – Verwaltung auf der Kommandozeile. +"""Playwish-Web – Verwaltung auf der Kommandozeile. geheimnisse SESSION_SECRET und PLAYER_API_TOKEN erzeugen (nur falls noch nicht vorhanden) passwort Admin-Passwort setzen (verdeckte Eingabe, gespeichert wird nur der argon2-Hash) turnstile Cloudflare-Turnstile-Schlüssel setzen (Secret-Key verdeckt) Auf dem Server als Dienst-Benutzer ausführen, damit die .env ihm gehört: - sudo -u audiofy /opt/audiofy/.venv/bin/python /opt/audiofy/app/verwaltung.py passwort + sudo -u playwish /opt/playwish/.venv/bin/python /opt/playwish/app/verwaltung.py passwort """ import argparse @@ -46,7 +46,7 @@ def passwort(env: Path) -> None: if getpass.getpass("Wiederholen: ") != erstes: sys.exit("Die Eingaben stimmen nicht überein.") env_wert_setzen(env, "ADMIN_PASSWORD_HASH", PasswordHasher().hash(erstes)) - print(f"Passwort-Hash in {env} gespeichert. Bitte den Dienst neu starten (audiofy-web.service).") + print(f"Passwort-Hash in {env} gespeichert. Bitte den Dienst neu starten (playwish-web.service).") def turnstile(env: Path) -> None: @@ -56,13 +56,13 @@ def turnstile(env: Path) -> None: sys.exit("Beide Schlüssel sind nötig.") env_wert_setzen(env, "TURNSTILE_SITE_KEY", site_key) env_wert_setzen(env, "TURNSTILE_SECRET_KEY", secret) - print(f"Turnstile-Schlüssel in {env} gespeichert. Bitte den Dienst neu starten (audiofy-web.service).") + print(f"Turnstile-Schlüssel in {env} gespeichert. Bitte den Dienst neu starten (playwish-web.service).") def main() -> None: - parser = argparse.ArgumentParser(description="Audiofy-Web – Verwaltung") + parser = argparse.ArgumentParser(description="Playwish-Web – Verwaltung") parser.add_argument("aktion", choices=("geheimnisse", "passwort", "turnstile")) - parser.add_argument("--env", type=Path, default=Path(os.environ.get("AUDIOFY_ENV", "/opt/audiofy/.env"))) + parser.add_argument("--env", type=Path, default=Path(os.environ.get("PLAYWISH_ENV", "/opt/playwish/.env"))) args = parser.parse_args() {"geheimnisse": geheimnisse, "passwort": passwort, "turnstile": turnstile}[args.aktion](args.env)