Files
quizify/app.py
Simon b710db210f modified: app.py
modified:   templates/quiz.html
2025-05-17 13:43:20 +02:00

238 lines
7.2 KiB
Python

__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/<playlist_id>")
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/<playlist_id>")
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)