new file: .gitignore

new file:   Dockerfile
	new file:   app.py
	new file:   requirements.txt
	new file:   start.bat
	new file:   templates/login.html
	new file:   templates/playlists.html
	new file:   templates/quiz.html
This commit is contained in:
SimolZimol
2025-05-15 21:58:50 +02:00
parent 8954b97b70
commit 447402ab75
8 changed files with 365 additions and 0 deletions

164
.gitignore vendored Normal file
View File

@@ -0,0 +1,164 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
ven/
logs/
cache/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

18
Dockerfile Normal file
View File

@@ -0,0 +1,18 @@
# --- Stage 1: Dependencies installieren ---
FROM python:3.10-slim AS base
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# --- Stage 2: Code kopieren & starten ---
FROM base AS run
WORKDIR /app
COPY . /app
# Port, den Coolify erwartet
EXPOSE 5000
# Starten mit Gunicorn für Production
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

72
app.py Normal file
View File

@@ -0,0 +1,72 @@
from flask import Flask, redirect, request, session, url_for, render_template
import os
from dotenv import load_dotenv
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import random
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv("SECRET_KEY")
SCOPE = "user-library-read playlist-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"
))
@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):
sp = get_spotify_client()
items = sp.playlist_items(playlist_id, additional_types=["track"])["items"]
tracks = [item["track"] for item in items if item["track"]["preview_url"]]
if not tracks:
return "Keine Tracks mit Vorschau verfügbar!"
track = random.choice(tracks)
return render_template("quiz.html", track=track)
if __name__ == "__main__":
app.run(debug=True)

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
Flask
yt-dlp
spotipy

75
start.bat Normal file
View File

@@ -0,0 +1,75 @@
@echo off
:: Save the current directory
set CURRENT_DIR=%cd%
:: Check for administrator rights
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
if '%errorlevel%' NEQ '0' (
echo Requesting administrator rights...
goto UACPrompt
) else ( goto AdminRights )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "cmd.exe", "/c cd /d %CURRENT_DIR% && %~s0 %*", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
del "%temp%\getadmin.vbs"
exit /B
:AdminRights
echo Administrator rights confirmed.
:: Change to the directory where the script is located
cd /d %CURRENT_DIR%
REM Set the directory for the virtual environment
set VENV_DIR=ven
REM Check if the virtual environment directory exists
if not exist %VENV_DIR% (
echo Virtual environment not found. Creating virtual environment...
python -m venv %VENV_DIR%
if %errorlevel% neq 0 (
echo Error: Failed to create virtual environment.
pause
exit /B %errorlevel%
)
)
REM Activate the virtual environment
call %VENV_DIR%\Scripts\activate
if %errorlevel% neq 0 (
echo Error: Failed to activate virtual environment.
pause
exit /B %errorlevel%
)
REM Check and install required packages
echo Installing required packages from requirements.txt...
pip install -r requirements.txt
if %errorlevel% neq 0 (
echo Error: Failed to install required packages.
pause
exit /B %errorlevel%
)
REM Start the bot
echo Starting the bot...
python app.py
if %errorlevel% neq 0 (
echo Error: Failed to start the bot.
pause
exit /B %errorlevel%
)
REM Deactivate the virtual environment after the bot stops
deactivate
if %errorlevel% neq 0 (
echo Error: Failed to deactivate virtual environment.
pause
exit /B %errorlevel%
)
echo Bot stopped. Press any key to close the window.
pause

8
templates/login.html Normal file
View File

@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head><title>Login mit Spotify</title></head>
<body>
<h1>Musik Quiz</h1>
<a href="/login">Mit Spotify einloggen</a>
</body>
</html>

12
templates/playlists.html Normal file
View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head><title>Deine Playlists</title></head>
<body>
<h2>Wähle eine Playlist:</h2>
<ul>
{% for pl in playlists %}
<li><a href="/quiz/{{ pl.id }}">{{ pl.name }}</a></li>
{% endfor %}
</ul>
</body>
</html>

13
templates/quiz.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head><title>Musik Quiz</title></head>
<body>
<h2>Wer ist der Künstler dieses Songs?</h2>
<audio controls autoplay>
<source src="{{ track.preview_url }}" type="audio/mpeg">
Dein Browser unterstützt keine Audio-Wiedergabe.
</audio>
<p><strong>Antwort:</strong> {{ track.artists[0].name }} (für Demo-Zwecke)</p>
<a href="/quiz/{{ track.id }}">Neue Frage</a>
</body>
</html>