Audiofy – Musikwünsche für Partys
Server (Website, Admin-Bereich, Player-API) und Player (raspotify + Controller) mit Install-Skripten für Debian-Systeme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""Audiofy-Web – Konfiguration aus der .env.
|
||||
|
||||
Pfad über die Umgebungsvariable AUDIOFY_ENV, Standard /opt/audiofy/.env.
|
||||
Geheimnisse stehen nur dort (Rechte 600), nie im Code oder in Logs.
|
||||
"""
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def env_lesen(pfad: Path) -> dict:
|
||||
"""Einfacher KEY=VALUE-Parser (Kommentare und Anführungszeichen erlaubt)."""
|
||||
werte = {}
|
||||
for zeile in pfad.read_text().splitlines():
|
||||
zeile = zeile.strip()
|
||||
if not zeile or zeile.startswith("#") or "=" not in zeile:
|
||||
continue
|
||||
key, _, wert = zeile.partition("=")
|
||||
werte[key.strip()] = wert.strip().strip('"').strip("'")
|
||||
return werte
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Konfig:
|
||||
env_pfad: Path
|
||||
db_pfad: Path
|
||||
player_api_token: str
|
||||
spotify_client_id: str
|
||||
spotify_client_secret: str
|
||||
spotify_refresh_token: str
|
||||
admin_passwort_hash: str
|
||||
session_secret: str
|
||||
playlist_id: str # nur Startwert – danach gilt die Einstellung in der Datenbank
|
||||
cookie_secure: bool = True # nur für lokale Tests über http auf 0 setzen
|
||||
public_url: str = "" # z. B. https://musik.example.org (für Einladungslink/QR-Code)
|
||||
turnstile_site_key: str = "" # Cloudflare Turnstile (öffentlich)
|
||||
turnstile_secret: str = "" # Cloudflare Turnstile (geheim)
|
||||
|
||||
|
||||
def env_wert_setzen(pfad: Path, key: str, wert: str) -> None:
|
||||
"""Setzt KEY=wert in der .env – direkt in der Datei (der Ordner ist für den Dienst nicht beschreibbar)."""
|
||||
zeilen = pfad.read_text().splitlines() if pfad.is_file() else []
|
||||
neu = [z for z in zeilen if not z.strip().startswith(f"{key}=")]
|
||||
neu.append(f"{key}={wert}")
|
||||
fd = os.open(pfad, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
|
||||
with os.fdopen(fd, "w") as f:
|
||||
f.write("\n".join(neu) + "\n")
|
||||
|
||||
|
||||
@lru_cache
|
||||
def konfig() -> Konfig:
|
||||
pfad = Path(os.environ.get("AUDIOFY_ENV", "/opt/audiofy/.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"),
|
||||
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", ""),
|
||||
spotify_refresh_token=werte.get("SPOTIFY_REFRESH_TOKEN", ""),
|
||||
admin_passwort_hash=werte.get("ADMIN_PASSWORD_HASH", ""),
|
||||
session_secret=werte.get("SESSION_SECRET", ""),
|
||||
playlist_id=werte.get("SPOTIFY_PLAYLIST_ID", ""),
|
||||
cookie_secure=werte.get("COOKIE_SECURE", "1") != "0",
|
||||
public_url=werte.get("PUBLIC_URL", "").rstrip("/"),
|
||||
turnstile_site_key=werte.get("TURNSTILE_SITE_KEY", ""),
|
||||
turnstile_secret=werte.get("TURNSTILE_SECRET_KEY", ""),
|
||||
)
|
||||
Reference in New Issue
Block a user