__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 import re 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() def clean_title(title): # Entfernt alles in () oder [] return re.sub(r"(\s*[\(\[][^)\]]*[\)\]])", "", title).strip() @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 item.get("track")] if not tracks: return "Keine Tracks verfügbar!" played_tracks = session.get(f'played_tracks_{playlist_id}', []) score = session.get(f'score_{playlist_id}', 0) available_tracks = [t for t in tracks if t["id"] not in played_tracks] if not available_tracks: played_tracks = [] available_tracks = tracks score = 0 # Score zurücksetzen, wenn alle gespielt track = random.choice(available_tracks) played_tracks.append(track["id"]) session[f'played_tracks_{playlist_id}'] = played_tracks session[f'score_{playlist_id}'] = score token_info = session.get('token_info', None) if not token_info: return redirect('/login') access_token = token_info['access_token'] 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] } 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, question_number=len(played_tracks), total_questions=len(tracks), score=score ) @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": []} # Suche nach bereinigtem Titel und Künstler results = [] for track in all_tracks: cleaned_name = clean_title(track["name"]) cleaned_query = clean_title(query) name_similarity = similarity(cleaned_query, cleaned_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') playlist_id = data.get('playlist_id') if game_mode == 'title': guess = clean_title(guess) correct_answer = clean_title(correct_answer) if game_mode == 'year': is_correct = guess == correct_answer else: is_correct = similarity(guess, correct_answer) >= 0.9 # Score erhöhen, wenn richtig if is_correct and playlist_id: key = f'score_{playlist_id}' session[key] = session.get(key, 0) + 1 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() # Playback-Status für das richtige Gerät prüfen current_playback = sp.current_playback() is_playing = False if current_playback and current_playback.get('device', {}).get('id') == device_id: is_playing = current_playback.get('is_playing', False) if 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) @app.route("/reset_quiz/") def reset_quiz(playlist_id): session.pop(f'played_tracks_{playlist_id}', None) session.pop(f'score_{playlist_id}', None) next_mode = request.args.get('next_mode') if next_mode: return redirect(url_for('quiz', playlist_id=playlist_id, mode=next_mode)) return redirect(url_for('playlists')) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)