__version__ = "pre-dev" __all__ = ["quizify"] __author__ = "SimolZimol" from flask import Flask, redirect, request, session, url_for, render_template import os import spotipy from spotipy.oauth2 import SpotifyOAuth import random from difflib import SequenceMatcher app = Flask(__name__) app.secret_key = os.getenv("SECRET_KEY") # Erweiterte Berechtigungen für Web Playback SDK SCOPE = "user-library-read playlist-read-private streaming user-read-email user-read-private" def get_spotify_client(): return spotipy.Spotify(auth_manager=SpotifyOAuth( client_id=os.getenv("SPOTIPY_CLIENT_ID"), client_secret=os.getenv("SPOTIPY_CLIENT_SECRET"), redirect_uri=os.getenv("SPOTIPY_REDIRECT_URI"), scope=SCOPE, cache_path=".cache" )) def similarity(a, b): return SequenceMatcher(None, a.lower(), b.lower()).ratio() @app.route("/") def home(): return render_template("login.html") @app.route("/login") def login(): sp_oauth = SpotifyOAuth( client_id=os.getenv("SPOTIPY_CLIENT_ID"), client_secret=os.getenv("SPOTIPY_CLIENT_SECRET"), redirect_uri=os.getenv("SPOTIPY_REDIRECT_URI"), scope=SCOPE ) auth_url = sp_oauth.get_authorize_url() return redirect(auth_url) @app.route("/callback") def callback(): sp_oauth = SpotifyOAuth( client_id=os.getenv("SPOTIPY_CLIENT_ID"), client_secret=os.getenv("SPOTIPY_CLIENT_SECRET"), redirect_uri=os.getenv("SPOTIPY_REDIRECT_URI"), scope=SCOPE ) session.clear() code = request.args.get('code') token_info = sp_oauth.get_access_token(code) session["token_info"] = token_info return redirect("/playlists") @app.route("/playlists") def playlists(): sp = get_spotify_client() playlists = sp.current_user_playlists()["items"] return render_template("playlists.html", playlists=playlists) @app.route("/quiz/") def quiz(playlist_id): game_mode = request.args.get('mode', 'artist') sp = get_spotify_client() items = sp.playlist_items(playlist_id, additional_types=["track"])["items"] tracks = [item["track"] for item in items] if not tracks: return "Keine Tracks verfügbar!" track = random.choice(tracks) # Token aus der Sitzung holen für das Web Playback SDK token_info = session.get('token_info', None) if not token_info: return redirect('/login') # Zugriff auf access_token access_token = token_info['access_token'] # Alle Tracks für die Suchfunktion (für title und artist mode) all_tracks = [] for item in tracks: track_info = { "id": item["id"], "name": item["name"], "artist": item["artists"][0]["name"], "uri": item["uri"], "release_date": item.get("album", {}).get("release_date", "Unbekannt")[:4] # Nur das Jahr } all_tracks.append(track_info) return render_template( "quiz.html", track=track, access_token=access_token, playlist_id=playlist_id, game_mode=game_mode, all_tracks=all_tracks ) @app.route("/search_track", methods=["POST"]) def search_track(): data = request.json query = data.get('query', '').lower() all_tracks = data.get('all_tracks', []) if not query or not all_tracks: return {"results": []} # Tracks nach Ähnlichkeit filtern (80% Übereinstimmung) results = [] for track in all_tracks: name_similarity = similarity(query, track["name"]) artist_similarity = similarity(query, track["artist"]) # Wenn Name oder Künstler zu 80% übereinstimmt if name_similarity >= 0.8 or artist_similarity >= 0.8: results.append({ "id": track["id"], "name": track["name"], "artist": track["artist"], "uri": track["uri"], "similarity": max(name_similarity, artist_similarity) }) # Nach Ähnlichkeit sortieren results.sort(key=lambda x: x["similarity"], reverse=True) return {"results": results} @app.route("/check_answer", methods=["POST"]) def check_answer(): data = request.json guess = data.get('guess', '').lower() correct_answer = data.get('correct_answer', '').lower() game_mode = data.get('game_mode', 'artist') # Bei Jahr-Modus: Exakte Übereinstimmung prüfen if game_mode == 'year': is_correct = guess == correct_answer else: # Bei anderen Modi: Ähnlichkeitsprüfung (90% Übereinstimmung gilt als korrekt) is_correct = similarity(guess, correct_answer) >= 0.9 return { "correct": is_correct, "correct_answer": correct_answer } @app.route("/play_track", methods=["POST"]) def play_track(): device_id = request.args.get('device_id') track_uri = request.args.get('track_uri') if not device_id or not track_uri: return {"error": "Missing device_id or track_uri"}, 400 sp = get_spotify_client() sp.start_playback(device_id=device_id, uris=[track_uri]) return {"success": True} @app.route("/toggle_playback", methods=["POST"]) def toggle_playback(): data = request.json device_id = data.get('device_id') if not device_id: return {"error": "Missing device_id"}, 400 sp = get_spotify_client() # Aktuellen Playback-Status abrufen current_playback = sp.current_playback() if current_playback and current_playback.get('is_playing'): sp.pause_playback(device_id=device_id) else: sp.start_playback(device_id=device_id) return {"success": True} @app.route('/logout') def logout(): session.pop('user', None) return redirect(url_for('index')) @app.route('/') def index(): user = session.get('user') # Benutzerinfos aus der Session holen, falls vorhanden return render_template('index.html', user=user) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)