Logo und andere kleinen Dinge

This commit is contained in:
mikka 2026-05-14 23:29:06 +02:00
parent 587f2546f9
commit 2623dfdf1a
9 changed files with 422 additions and 255 deletions

172
app.py
View file

@ -1,11 +1,13 @@
from flask import Flask, render_template, request, redirect
from glob import glob
import subprocess
import requests
import json import json
import os import os
import subprocess
from glob import glob
def wikiapi(id,field): import requests
from flask import Flask, redirect, render_template, request
def wikiapi(id, field):
if os.path.isdir("data"): if os.path.isdir("data"):
pass pass
else: else:
@ -15,39 +17,60 @@ def wikiapi(id,field):
with open(name, "r") as f: with open(name, "r") as f:
data = json.load(f) data = json.load(f)
except OSError: except OSError:
r = requests.get("https://www.wikidata.org/w/rest.php/wikibase/v1/entities/items/"+id+"?_fields="+field, headers={"user-agent":'esc/0.0(mikka@kleinrot.net)','Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhNDBhYmZjYzQxZTlkOTc2YzJiN2NmODZkYzIwMmQzZiIsImp0aSI6ImQ3ODQ4YmJhNjZlMWYzYzdhZGZmODU5NTdmZWE1YjMxODBhMzE2NTc4YWYyMWMzZGZhZGJiOTZlZmM3ZTgyMmJkMTE4YTQ4YWMzMDM2ZmQyIiwiaWF0IjoxNzc1OTE4OTc1LjkzMjQsIm5iZiI6MTc3NTkxODk3NS45MzI0MDEsImV4cCI6MzMzMzI4Mjc3NzUuOTI5NDA1LCJzdWIiOiIxMzEiLCJpc3MiOiJodHRwczovL21ldGEud2lraW1lZGlhLm9yZyIsInJhdGVsaW1pdCI6eyJyZXF1ZXN0c19wZXJfdW5pdCI6NTAwMCwidW5pdCI6IkhPVVIifSwic2NvcGVzIjpbImJhc2ljIl19.WLXRXxNjsZ1kIK2RX-Wds59W8Z1CWphbiV3UBEWvm5STWZ6uvpHZpx5d9lomK5-H56G3259_DavuTymdebQTmAwkeuCGh1gb60u9_4MzmGgspQHBPq3mWX879AUVW69uqsSz2x2zIz-ZUmt5TrZM7X3OBxE01nhVBoiDWnlW4Gt19FjwBQ9WjXzrFHsH9A7BtPzgbKROMXACRQBqh9XZXkN23PvnEV08sx63AGB0cZBkteIsnIfm49-Ht2_DTZKd4_MpEw9TZjOHSjY9odyImXidZOgy7NadT-LwAKQiVlSn6UZWTvgsG6xwP6sad_ctqU1ZupcOJLzd158DhrLAEMk_Qq9-piTQDYtLzWfLx44Jatjae6-0nilOgvrB0XQJC6cTihVk3-9Lyn6Y-e6yIDnEHIIIBj0J8PUv5IJjAojo-2uZ4w8omEzCWDEzf95_GSZmRwj_nRNCVs5jQpVhG9hFpOm2OrTrhqPgYet_dsl3QVEbvtGnlVzCw7j9sj_86axAC1hklQQso6AiAAzEmOiTfC6VyrP8sFjbnDlLBCEiTkYTvOTp5nuYRC8VdwJQm6NJIafjNn5ihp4T8OvJQyzsK1HDYlthvW54-co2gPoeIX-cBItvdrCBNDofoA9bIP3zzwGXdvy1b7lofx5WekWKAGytPCfsr7i2ZJB93xU'}) r = requests.get(
"https://www.wikidata.org/w/rest.php/wikibase/v1/entities/items/"
+ id
+ "?_fields="
+ field,
headers={
"user-agent": "esc/0.0(mikka@kleinrot.net)",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhNDBhYmZjYzQxZTlkOTc2YzJiN2NmODZkYzIwMmQzZiIsImp0aSI6ImQ3ODQ4YmJhNjZlMWYzYzdhZGZmODU5NTdmZWE1YjMxODBhMzE2NTc4YWYyMWMzZGZhZGJiOTZlZmM3ZTgyMmJkMTE4YTQ4YWMzMDM2ZmQyIiwiaWF0IjoxNzc1OTE4OTc1LjkzMjQsIm5iZiI6MTc3NTkxODk3NS45MzI0MDEsImV4cCI6MzMzMzI4Mjc3NzUuOTI5NDA1LCJzdWIiOiIxMzEiLCJpc3MiOiJodHRwczovL21ldGEud2lraW1lZGlhLm9yZyIsInJhdGVsaW1pdCI6eyJyZXF1ZXN0c19wZXJfdW5pdCI6NTAwMCwidW5pdCI6IkhPVVIifSwic2NvcGVzIjpbImJhc2ljIl19.WLXRXxNjsZ1kIK2RX-Wds59W8Z1CWphbiV3UBEWvm5STWZ6uvpHZpx5d9lomK5-H56G3259_DavuTymdebQTmAwkeuCGh1gb60u9_4MzmGgspQHBPq3mWX879AUVW69uqsSz2x2zIz-ZUmt5TrZM7X3OBxE01nhVBoiDWnlW4Gt19FjwBQ9WjXzrFHsH9A7BtPzgbKROMXACRQBqh9XZXkN23PvnEV08sx63AGB0cZBkteIsnIfm49-Ht2_DTZKd4_MpEw9TZjOHSjY9odyImXidZOgy7NadT-LwAKQiVlSn6UZWTvgsG6xwP6sad_ctqU1ZupcOJLzd158DhrLAEMk_Qq9-piTQDYtLzWfLx44Jatjae6-0nilOgvrB0XQJC6cTihVk3-9Lyn6Y-e6yIDnEHIIIBj0J8PUv5IJjAojo-2uZ4w8omEzCWDEzf95_GSZmRwj_nRNCVs5jQpVhG9hFpOm2OrTrhqPgYet_dsl3QVEbvtGnlVzCw7j9sj_86axAC1hklQQso6AiAAzEmOiTfC6VyrP8sFjbnDlLBCEiTkYTvOTp5nuYRC8VdwJQm6NJIafjNn5ihp4T8OvJQyzsK1HDYlthvW54-co2gPoeIX-cBItvdrCBNDofoA9bIP3zzwGXdvy1b7lofx5WekWKAGytPCfsr7i2ZJB93xU",
},
)
data = r.json() data = r.json()
with open(name, "x") as f: with open(name, "x") as f:
json.dump(data, f,indent=2,ensure_ascii=False) json.dump(data, f, indent=2, ensure_ascii=False)
return data[field] return data[field]
def wikisuche(text): def wikisuche(text):
mitp1344 = [] mitpartsin = []
ohnep1344 = [] ohnepartsin = []
r = requests.get("https://www.wikidata.org/w/rest.php/wikibase/v1/search/items?q="+text+"&language=en", headers={"user-agent":'esc/0.0(mikka@kleinrot.net)','Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhNDBhYmZjYzQxZTlkOTc2YzJiN2NmODZkYzIwMmQzZiIsImp0aSI6ImQ3ODQ4YmJhNjZlMWYzYzdhZGZmODU5NTdmZWE1YjMxODBhMzE2NTc4YWYyMWMzZGZhZGJiOTZlZmM3ZTgyMmJkMTE4YTQ4YWMzMDM2ZmQyIiwiaWF0IjoxNzc1OTE4OTc1LjkzMjQsIm5iZiI6MTc3NTkxODk3NS45MzI0MDEsImV4cCI6MzMzMzI4Mjc3NzUuOTI5NDA1LCJzdWIiOiIxMzEiLCJpc3MiOiJodHRwczovL21ldGEud2lraW1lZGlhLm9yZyIsInJhdGVsaW1pdCI6eyJyZXF1ZXN0c19wZXJfdW5pdCI6NTAwMCwidW5pdCI6IkhPVVIifSwic2NvcGVzIjpbImJhc2ljIl19.WLXRXxNjsZ1kIK2RX-Wds59W8Z1CWphbiV3UBEWvm5STWZ6uvpHZpx5d9lomK5-H56G3259_DavuTymdebQTmAwkeuCGh1gb60u9_4MzmGgspQHBPq3mWX879AUVW69uqsSz2x2zIz-ZUmt5TrZM7X3OBxE01nhVBoiDWnlW4Gt19FjwBQ9WjXzrFHsH9A7BtPzgbKROMXACRQBqh9XZXkN23PvnEV08sx63AGB0cZBkteIsnIfm49-Ht2_DTZKd4_MpEw9TZjOHSjY9odyImXidZOgy7NadT-LwAKQiVlSn6UZWTvgsG6xwP6sad_ctqU1ZupcOJLzd158DhrLAEMk_Qq9-piTQDYtLzWfLx44Jatjae6-0nilOgvrB0XQJC6cTihVk3-9Lyn6Y-e6yIDnEHIIIBj0J8PUv5IJjAojo-2uZ4w8omEzCWDEzf95_GSZmRwj_nRNCVs5jQpVhG9hFpOm2OrTrhqPgYet_dsl3QVEbvtGnlVzCw7j9sj_86axAC1hklQQso6AiAAzEmOiTfC6VyrP8sFjbnDlLBCEiTkYTvOTp5nuYRC8VdwJQm6NJIafjNn5ihp4T8OvJQyzsK1HDYlthvW54-co2gPoeIX-cBItvdrCBNDofoA9bIP3zzwGXdvy1b7lofx5WekWKAGytPCfsr7i2ZJB93xU'}) r = requests.get(
"https://www.wikidata.org/w/rest.php/wikibase/v1/search/items?q="
+ text
+ "&language=en",
headers={
"user-agent": "esc/0.0(mikka@kleinrot.net)",
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJhNDBhYmZjYzQxZTlkOTc2YzJiN2NmODZkYzIwMmQzZiIsImp0aSI6ImQ3ODQ4YmJhNjZlMWYzYzdhZGZmODU5NTdmZWE1YjMxODBhMzE2NTc4YWYyMWMzZGZhZGJiOTZlZmM3ZTgyMmJkMTE4YTQ4YWMzMDM2ZmQyIiwiaWF0IjoxNzc1OTE4OTc1LjkzMjQsIm5iZiI6MTc3NTkxODk3NS45MzI0MDEsImV4cCI6MzMzMzI4Mjc3NzUuOTI5NDA1LCJzdWIiOiIxMzEiLCJpc3MiOiJodHRwczovL21ldGEud2lraW1lZGlhLm9yZyIsInJhdGVsaW1pdCI6eyJyZXF1ZXN0c19wZXJfdW5pdCI6NTAwMCwidW5pdCI6IkhPVVIifSwic2NvcGVzIjpbImJhc2ljIl19.WLXRXxNjsZ1kIK2RX-Wds59W8Z1CWphbiV3UBEWvm5STWZ6uvpHZpx5d9lomK5-H56G3259_DavuTymdebQTmAwkeuCGh1gb60u9_4MzmGgspQHBPq3mWX879AUVW69uqsSz2x2zIz-ZUmt5TrZM7X3OBxE01nhVBoiDWnlW4Gt19FjwBQ9WjXzrFHsH9A7BtPzgbKROMXACRQBqh9XZXkN23PvnEV08sx63AGB0cZBkteIsnIfm49-Ht2_DTZKd4_MpEw9TZjOHSjY9odyImXidZOgy7NadT-LwAKQiVlSn6UZWTvgsG6xwP6sad_ctqU1ZupcOJLzd158DhrLAEMk_Qq9-piTQDYtLzWfLx44Jatjae6-0nilOgvrB0XQJC6cTihVk3-9Lyn6Y-e6yIDnEHIIIBj0J8PUv5IJjAojo-2uZ4w8omEzCWDEzf95_GSZmRwj_nRNCVs5jQpVhG9hFpOm2OrTrhqPgYet_dsl3QVEbvtGnlVzCw7j9sj_86axAC1hklQQso6AiAAzEmOiTfC6VyrP8sFjbnDlLBCEiTkYTvOTp5nuYRC8VdwJQm6NJIafjNn5ihp4T8OvJQyzsK1HDYlthvW54-co2gPoeIX-cBItvdrCBNDofoA9bIP3zzwGXdvy1b7lofx5WekWKAGytPCfsr7i2ZJB93xU",
},
)
for result in r.json()["results"]: for result in r.json()["results"]:
if getescedition(result["id"]): if getescedition(result["id"]):
mitp1344.append(result) mitpartsin.append(result)
else: else:
ohnep1344.append(result) ohnepartsin.append(result)
return mitp1344 + ohnep1344 return mitpartsin + ohnepartsin
def getescedition(songId): def getescedition(songId):
statements = wikiapi(songId,"statements") statements = wikiapi(songId, "statements")
if "P1344" in statements: if "partsin" in statements:
for statement in statements["P1344"]: for statement in statements["partsin"]:
id = statement["value"]["content"] id = statement["value"]["content"]
escdata = wikiapi(id,"statements") escdata = wikiapi(id, "statements")
if escdata["P31"][0]["value"]["content"] == "Q110288240": if escdata["P31"][0]["value"]["content"] == "Q110288240":
return id,statement return id, statement
def datei(id): def datei(id):
file = glob("static/"+id+".*") file = glob("static/" + id + ".*")
if file == []: if file == []:
subprocess.run(["yt-dlp",f"http://youtu.be/{id}","-x","-o",id],cwd="static") subprocess.run(
file = glob("static/"+id+".*") ["yt-dlp", f"http://youtu.be/{id}", "-x", "-o", id], cwd="static"
)
file = glob("static/" + id + ".*")
if file != []: if file != []:
audio = file[0].replace("static/", "") audio = file[0].replace("static/", "")
else: else:
@ -55,38 +78,61 @@ def datei(id):
print(audio) print(audio)
return audio return audio
def kartenGeneriren(song): def kartenGeneriren(song):
id = song["wikiid"] id = song["wikiid"]
print(id) print(id)
statements = wikiapi(id,"statements") statements = wikiapi(id, "statements")
labels = wikiapi(id,"labels") labels = wikiapi(id, "labels")
song["titel"] = statements.get("P1476",[{"value": {"content":{"text":labels["en"]}}}])[0]["value"]["content"]["text"] song["titel"] = statements.get(
song["laenge"] = int(statements.get("P2047",[{"value": {"content":{"amount":"0"}}}])[0]["value"]["content"]["amount"]) "P1476", [{"value": {"content": {"text": labels["en"]}}}]
)[0]["value"]["content"]["text"]
song["laenge"] = int(
statements.get("P2047", [{"value": {"content": {"amount": "0"}}}])[0]["value"][
"content"
]["amount"]
)
escedition = getescedition(id) escedition = getescedition(id)
if escedition: if escedition:
(escedition,statement)=escedition (escedition, statement) = escedition
song["jahrgang"] = wikiapi(escedition,"labels")["en"] song["jahrgang"] = wikiapi(escedition, "labels")["en"]
qualifiers = statement["qualifiers"] qualifiers = statement["qualifiers"]
for qualifier in qualifiers: for qualifier in qualifiers:
if qualifier["property"]["id"] == "P1352": if qualifier["property"]["id"] == "P1352":
song["plazirung"] = str(int(qualifier["value"]["content"]["amount"]))+"." song["plazirung"] = (
song["interprete"] = " x ".join(set(wikiapi(statement["value"]["content"],"labels")["en"] for statement in statements.get("P175",[]))) str(int(qualifier["value"]["content"]["amount"])) + "."
)
song["interprete"] = " x ".join(
set(
wikiapi(statement["value"]["content"], "labels")["en"]
for statement in statements.get("P175", [])
)
)
if "land" not in song and "P495" in statements:
song["land"] = wikiapi(statements["P495"][0]["value"]["content"], "labels")[
"de"
]
if "ytid" not in song and "P1651" in statements: if "ytid" not in song and "P1651" in statements:
song["ytid"] = statements["P1651"][0]["value"]["content"] song["ytid"] = statements["P1651"][0]["value"]["content"]
if "ytid" in song: if "ytid" in song:
song["datei"] = datei(song["ytid"]) song["datei"] = datei(song["ytid"])
song["img"] = f"http://img.youtube.com/vi/{ song["ytid"] }/sddefault.jpg" song["img"] = f"http://img.youtube.com/vi/{song['ytid']}/sddefault.jpg"
if "P6218" in statements: if "P6218" in statements:
song["text"] = f"//genius.com/{statements["P6218"][0]["value"]["content"]}" song["text"] = f"//genius.com/{statements['P6218'][0]['value']['content']}"
if "P18" in statements: if "P18" in statements:
song["img"] = f"https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/{statements["P18"][0]["value"]["content"]}&width=300" song["img"] = (
f"https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/{statements['P18'][0]['value']['content']}&width=300"
)
if "img" not in song: if "img" not in song:
song["img"] = "https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Eurovision_Song_Contest_heart_(20142025).svg&width=300" song["img"] = (
"https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Eurovision_Song_Contest_heart_(20142025).svg&width=300"
)
app = Flask(__name__) app = Flask(__name__)
@app.template_filter('zeit')
@app.template_filter("zeit")
def zeit(sekunden): def zeit(sekunden):
minuten = sekunden // 60 minuten = sekunden // 60
rest = sekunden - minuten * 60 rest = sekunden - minuten * 60
@ -98,31 +144,34 @@ def hello_world():
liste = request.args.get("liste") liste = request.args.get("liste")
if liste is None: if liste is None:
return redirect("/playlists") return redirect("/playlists")
with open(liste+".json","r") as f: with open(liste + ".json", "r") as f:
songs = json.load(f) songs = json.load(f)
for song in songs: for song in songs:
kartenGeneriren(song) kartenGeneriren(song)
gesamtLaenge = 0 gesamtLaenge = 0
for song in songs: for song in songs:
gesamtLaenge += song["laenge"] gesamtLaenge += song["laenge"]
return render_template('index.html', karten=songs,gesamtLaenge=gesamtLaenge,liste=liste ) return render_template(
"index.html", karten=songs, gesamtLaenge=gesamtLaenge, liste=liste
)
@app.route("/playlists") @app.route("/playlists")
def playlists(): def playlists():
listen = glob("*.json") listen = glob("*.json")
listen = (liste.replace(".json","") for liste in listen) listen = (liste.replace(".json", "") for liste in listen)
return render_template('playlists.html',lists=listen) return render_template("playlists.html", lists=listen)
@app.route("/neueliste") @app.route("/neueliste")
def neueliste(): def neueliste():
name = request.args.get("name") name = request.args.get("name")
if name is not None: if name is not None:
with open(name +".json", "x") as f: with open(name + ".json", "x") as f:
json.dump([],f) json.dump([], f)
return redirect("/?liste="+name) return redirect("/?liste=" + name)
print(liste) return render_template("neueliste.html", name=name)
return render_template('neueliste.html',name=name)
@app.route("/suche") @app.route("/suche")
def suche(): def suche():
@ -132,44 +181,51 @@ def suche():
ergebnisse = wikisuche(such) ergebnisse = wikisuche(such)
else: else:
ergebnisse = [] ergebnisse = []
return render_template('suche.html', ergebnisse=ergebnisse,anfrage=such,liste=liste) return render_template(
"suche.html", ergebnisse=ergebnisse, anfrage=such, liste=liste
)
@app.route("/suche",methods=["POST"])
@app.route("/suche", methods=["POST"])
def suche_finden(): def suche_finden():
liste = request.args.get("liste") liste = request.args.get("liste")
with open(liste +".json","r") as f: with open(liste + ".json", "r") as f:
songs = json.load(f) songs = json.load(f)
song = {"wikiid":request.form.get("id")} song = {"wikiid": request.form.get("id")}
kartenGeneriren(song) kartenGeneriren(song)
songs.append(song) songs.append(song)
with open(liste+".json","w") as f: with open(liste + ".json", "w") as f:
json.dump(songs,f,indent=2,ensure_ascii=False) json.dump(songs, f, indent=2, ensure_ascii=False)
return redirect("/suche?liste="+liste,303) return redirect("/suche?liste=" + liste, 303)
@app.route("/remove") @app.route("/remove")
def admin(): def admin():
liste = request.args.get("liste") liste = request.args.get("liste")
if liste is None: if liste is None:
return redirect("/playlists") return redirect("/playlists")
with open(liste+".json","r") as f: with open(liste + ".json", "r") as f:
songs = json.load(f) songs = json.load(f)
for song in songs: for song in songs:
kartenGeneriren(song) kartenGeneriren(song)
gesamtLaenge = 0 gesamtLaenge = 0
for song in songs: for song in songs:
gesamtLaenge += song["laenge"] gesamtLaenge += song["laenge"]
return render_template('index.html', karten=songs,gesamtLaenge=gesamtLaenge,liste=liste,admin=True) return render_template(
"index.html", karten=songs, gesamtLaenge=gesamtLaenge, liste=liste, admin=True
)
@app.route("/remove",methods=["POST"])
@app.route("/remove", methods=["POST"])
def loeschen(): def loeschen():
liste = request.args.get("liste") liste = request.args.get("liste")
song = int(request.form.get("index")) song = int(request.form.get("index"))
with open(liste+".json","r") as f: with open(liste + ".json", "r") as f:
print(liste+".json") print(liste + ".json")
songs = json.load(f) songs = json.load(f)
print(songs) print(songs)
print(songs) print(songs)
del songs[song] del songs[song]
with open(liste+".json","w") as f: with open(liste + ".json", "w") as f:
json.dump(songs,f,indent=2,ensure_ascii=False) json.dump(songs, f, indent=2, ensure_ascii=False)
return redirect("/remove?liste="+liste,303) return redirect("/remove?liste=" + liste, 303)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="125.33"
height="131.46"
version="1.1"
id="svg1"
sodipodi:docname="Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"
xml:space="preserve"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.303099"
inkscape:cx="53.449851"
inkscape:cy="50.196382"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" /><g
id="g1"
transform="matrix(0.12157124,0,0,0.23068304,12.733877,4.287877)"><path
id="path1-3"
style="fill:#990000"
d="m 14.029438,47.537215 c -1.774828,0.01827 -1.013972,0.384871 -0.03213,0.626536 0.743679,-0.164572 1.490068,-0.325118 2.23313,-0.491069 -0.72782,-0.04244 -1.783992,-0.139759 -2.200998,-0.135467 z M 142.18539,59.094266 c -4.82297,3.438254 -9.69255,6.858605 -15.85683,9.685909 -9.38162,4.990549 -19.34173,9.624906 -30.380205,13.58906 -10.698213,3.846403 -21.764589,7.384325 -33.946788,9.78751 -0.669629,0.14639 -1.339128,0.292891 -2.00821,0.440268 V 399.87063 c 4.294457,2.59538 8.563573,5.20196 12.965006,7.74704 14.479715,8.05187 30.579687,15.20504 46.076377,22.69076 10.37587,4.79197 20.82658,9.52643 30.95857,14.45267 V 61.321009 c -2.64183,-0.684628 -5.26357,-1.407695 -7.80792,-2.226743 z m 37.81862,7.5523 V 459.74716 c 2.35383,1.15862 4.67161,2.33734 7.0689,3.47135 10.48296,4.92542 21.63634,9.42235 32.74186,13.94466 11.38075,4.82918 22.73005,9.68782 33.86646,14.6728 2.23876,1.1668 4.70542,2.2195 6.71546,3.49675 2.36848,1.50499 4.77459,3.02601 6.79578,4.66515 h 2.81149 V 74.402066 c -1.52365,-0.251491 -2.99632,-0.543839 -4.41806,-0.880537 -3.44536,-0.556772 -6.89455,-1.106275 -10.31417,-1.710274 -5.17069,-0.542732 -10.36811,-1.007044 -15.53551,-1.557873 -0.97125,-0.103562 -1.88782,-0.366087 -2.87576,-0.406402 -1.61527,-0.06633 -3.23252,-0.05736 -4.85184,-0.08467 -12.33914,-0.26891 -24.68661,-0.675896 -36.91894,-1.608674 -5.06761,-0.420601 -10.09953,-0.926035 -15.08567,-1.507073 z M 29.998726,98.980908 c -8.251681,1.796042 -16.220058,3.973792 -24.9660709,5.080022 -2.0724185,0.24509 -3.4743116,0.40985 -5.02855874,0.59267 V 393.09727 C 14.640724,395.66002 26.790289,396.67245 29.998726,392.34373 v -6.23996 c -0.803728,-1.96212 -2.182488,-4.26283 -4.305603,-7.01043 -0.191081,-0.24728 -0.479549,-0.48168 -0.562298,-0.74507 -0.02734,-0.087 -8.34e-4,-0.0983 0.08033,-0.0593 0.243479,0.11718 0.860945,0.67324 1.172795,0.88054 1.184122,0.78717 2.416754,1.5504 3.614778,2.32834 z" /><path
id="path2"
style="fill:#339966"
d="M 720.00374,-0.00332762 V 316.05873 c 9.4778,-7.25273 19.5086,-14.30976 29.99463,-21.17523 V 7.1933707 c -1.61483,-1.6498815 -1.49121,-3.0052856 0,-4.1232848 V -0.00332762 Z M 810.0037,7.5235722 C 799.38514,8.2567434 788.77164,8.7962855 779.993,9.4285806 V 20.232095 c 0.31997,0.13476 0.43431,0.208138 0,0.127 V 276.57002 c 3.48903,-1.88316 6.90501,-3.814 10.98893,-5.30862 6.88074,-2.51817 12.98246,-4.39552 19.02177,-5.71503 z M 299.99859,81.522564 V 499.99787 h 29.99463 V 97.160567 c -7.9882,-2.297003 -15.07698,-5.435046 -20.85325,-9.381108 -3.34736,-2.462292 -4.5133,-3.672614 -5.88004,-4.52122 -1.05183,-0.525067 -3.05402,-1.485727 -2.98822,-1.549407 0.0574,-0.05538 0.25839,0.0053 0.43377,0.06773 -0.21331,-0.09699 -0.48098,-0.163567 -0.70689,-0.254002 z m 89.99996,17.348277 c -8.20339,1.519749 -16.83464,2.407739 -25.64083,2.683949 -1.45128,-0.0369 -2.89992,-0.0475 -4.3538,-0.0677 v 398.51082 h 7.30989 c 1.48574,-6.49571 8.87825,-13.03235 22.68474,-18.01714 z" /><path
id="path3"
style="fill:#006699"
d="m 548.35799,-0.00332762 c 1.32928,3.78920772 2.24975,7.61254682 1.73509,11.48085062 -0.42645,1.741623 -0.60851,3.502756 -1.26919,5.223956 -1.60817,4.189623 -4.62212,8.251934 -8.82006,11.929586 V 418.95458 c 0.48825,-0.36573 0.93428,-0.74589 1.42985,-1.10914 2.62333,-1.9375 6.39128,-4.76412 9.10924,-6.55322 5.85514,-3.85417 12.52594,-7.29148 19.45554,-10.59185 V -0.00332762 Z m 51.6351,0 V 387.80558 c 4.47695,-1.73687 9.00958,-3.43485 13.6719,-5.04616 11.34729,-4.17629 22.86313,-8.22255 34.17171,-12.42912 7.06298,-2.78351 14.24938,-5.59077 19.96964,-9.16097 6.93356,-4.30741 12.65281,-9.01463 17.15815,-14.15633 1.65811,-1.61121 3.36978,-3.20652 5.02856,-4.81756 V -0.00332762 Z M 509.99314,42.56726 c -0.24486,0.0606 -0.47595,0.136521 -0.72296,0.194734 -8.74713,2.061395 -18.1919,2.88136 -27.56871,3.657616 -3.65751,0.48271 -1.00651,0.112622 -4.33774,0.609603 -3.88331,0.57934 -0.059,0.157044 -0.81935,-0.169334 -0.82252,-0.353035 -2.37514,1.932431 -2.6187,0.956737 -0.49781,0.226211 -1.00074,0.448451 -1.49411,0.677336 -0.3614,0.16765 -0.97876,0.756482 -1.0764,0.508003 -0.15229,-0.387359 1.54235,-1.288175 0.89968,-1.083738 -0.21675,0.06897 -0.33904,0.201743 -0.44984,0.321734 -0.44886,0.486165 -0.81218,0.98579 -1.22099,1.481674 -4.11781,5.237277 -6.68747,10.843785 -12.82042,15.604135 -5.6807,4.605146 -11.78003,9.07912 -18.65226,13.216525 -6.17704,3.674682 -12.21316,7.410557 -19.11816,10.718847 V 475.2751 c 3.0332,-0.37853 6.17199,-0.71814 9.47875,-0.99061 5.46251,-0.4501 10.93222,-0.82713 16.4352,-1.10067 0.29359,-0.0237 5.86112,-0.5336 5.88004,-0.52493 0.12774,0.0737 -0.54025,0.2544 -0.35345,0.23706 0.44544,-0.039 0.81522,-0.20879 1.22099,-0.31326 5.07815,-1.73672 9.61583,-3.74927 13.59157,-6.1807 7.3223,-4.3773 14.00387,-9.04125 21.38343,-13.39432 7.02366,-4.4061 14.2383,-8.73866 22.36343,-12.59846 z" /></g><path
d="m12.726 58.556c0.31803-28.513 15.157-37.437 23.237-37.437 11.285 0 15.946 8.6151 16.707 12.429 0.76116 3.8111 5.0324 6.8595 6.4047 0.60798 1.3734-6.2515 14.649-25.315 30.966-25.315 14.943 0 20.119 15.41 19.671 28.518-1.2228 35.683-47.19 64.158-53.239 82.143-5.3875-10.891-44.126-26.634-43.746-60.946zm82.652-58.556c-13.42 0-29.29 9.9111-38.896 26.382-2.592-5.9483-11.827-12.43-22.805-12.43-8.8462 0-33.676 11.056-33.676 46.74 0 46.052 46.593 55.508 56.011 69.825 0.64721 0.98433 2.7319 1.728 3.5276-0.62388 7.5157-22.18 65.791-47.242 65.791-92.379-5.3e-4 -25.314-16.536-37.513-29.955-37.513z"
stroke-width=".53006"
id="path1" /><g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="DATA" /></svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -1,102 +1,98 @@
const audios = document.querySelectorAll("audio") const audios = document.querySelectorAll("audio");
const articles = document.querySelectorAll("article") const articles = document.querySelectorAll("article");
const kartenContainer = document.getElementById("flex-container") const kartenContainer = document.getElementById("flex-container");
outindex = 0 outindex = 0;
playing = false playing = false;
playcolor = "#00ff3c" playcolor = "#00ff3c";
loop = true loop = true;
function onplay(id){ function onplay(id) {
//What is id id = parseInt(id);
id = parseInt(id) if (id > 0) {
if(id>0){ articles[id - 1].style.filter = "grayscale(" + (id + 1) * 20 + "%)";
articles[id-1].style.filter = "grayscale("+(id+1)*20+"%)" articles[id - 1].style.boxShadow = "0 0 0px 0px " + playcolor;
articles[id-1].style.boxShadow = "0 0 0px 0px "+playcolor
} }
if(articles[id].offsetWidth * id == window.innerWidth/2){ if (articles[id].offsetWidth * id == window.innerWidth / 2) {
console.log(articles[id].offsetWidth) console.log(articles[id].offsetWidth);
kartenContainer.scrollWidth += articles[id].offsetWidth kartenContainer.scrollWidth += articles[id].offsetWidth;
} }
articles[id].style.filter = "grayscale(0%)" articles[id].style.filter = "grayscale(0%)";
articles[id].style.margin = "8px" articles[id].style.margin = "8px";
articles[id].style.boxShadow = "0 0 6px 1px "+playcolor articles[id].style.boxShadow = "0 0 6px 1px " + playcolor;
} }
function nächste(id){ function nächste(id) {
audios[id].pause() audios[id].pause();
id = parseInt(id) + 1 id = parseInt(id) + 1;
audios[id].play() audios[id].play();
onplay(id) onplay(id);
} }
function vorherige(id){ function vorherige(id) {
audios[id].pause() audios[id].pause();
audios[id-1].play() audios[id - 1].play();
onplay(id-1) onplay(id - 1);
} }
function looptrue(){ function looptrue() {
if(loop){ if (loop) {
loop = false loop = false;
document.querySelector("#loop").innerHTML = "Kein Loop" document.querySelector("#loop").innerHTML = "Kein Loop";
document.querySelector("#loop").style.beckground document.querySelector("#loop").style.beckground;
} } else {
else{ loop = true;
loop = true document.querySelector("#loop").innerHTML = "Loop";
document.querySelector("#loop").innerHTML = "Loop"
} }
} }
function abspielendiese(id){ function abspielendiese(id) {
if(playing){ if (playing) {
//ON PAUSE //ON PAUSE
audios[id].pause() audios[id].pause();
playing = false playing = false;
articles[id].style.margin = "0px" articles[id].style.margin = "0px";
articles[id].style.boxShadow = "0 0 0px 0px "+playcolor articles[id].style.boxShadow = "0 0 0px 0px " + playcolor;
} } else {
else{
//ON PLAY //ON PLAY
audios[id].play() audios[id].play();
playing = true playing = true;
onplay(id) onplay(id);
} }
} }
function abspielen(){ function abspielen() {
if(playing){ if (playing) {
//ON PAUSE //ON PAUSE
audios[outindex].pause() audios[outindex].pause();
playing = false playing = false;
articles[outindex].style.margin = "0px" articles[outindex].style.margin = "0px";
articles[outindex].style.boxShadow = "0 0 0px 0px "+playcolor articles[outindex].style.boxShadow = "0 0 0px 0px " + playcolor;
document.querySelector("#play").innerHTML = "Abspielen" document.querySelector("#play").innerHTML = "Abspielen";
} } else {
else{
//ON PLAY //ON PLAY
audios[outindex].play() audios[outindex].play();
playing = true playing = true;
document.querySelector("#play").innerHTML = "Pausieren" document.querySelector("#play").innerHTML = "Pausieren";
onplay(outindex) onplay(outindex);
} }
} }
for (const [index,audio] of audios.entries()){ for (const [index, audio] of audios.entries()) {
audio.addEventListener("ended", (event) => { audio.addEventListener("ended", (event) => {
if (index != audios.length -1){ if (index != audios.length - 1) {
outindex = index +1 outindex = index + 1;
audios[outindex].play() audios[outindex].play();
onplay(index+1) onplay(index + 1);
} } else {
else{
//Last song ON END //Last song ON END
articles[index].style.filter = "grayscale(80%)" articles[index].style.filter = "grayscale(80%)";
articles[index].style.boxShadow = "0 0 0px 0px "+playcolor articles[index].style.boxShadow = "0 0 0px 0px " + playcolor;
articles[index].style.margin = "8px" articles[index].style.margin = "8px";
articles[index].style.boxShadow = "0 0 6px 1px "+playcolor articles[index].style.boxShadow = "0 0 6px 1px " + playcolor;
if(loop){ if (loop) {
audios[0].play() audios[0].play();
} }
} }
}) });
} }
//Audio visualising

View file

@ -1,21 +1,23 @@
<style> <style>
#flex-container{ #flex-container {
overflow: auto; overflow: auto;
scroll-snap-type: x mandatory; scroll-snap-type: x mandatory;
display: flex; display: flex;
border: none; border: none;
gap: 5px; gap: 5px;
} }
article{ article {
flex-wrap: row nowrap; flex-wrap: row nowrap;
border: none; border: none;
flex: 0 0 30rem; flex: 0 0 30rem;
} }
a,h1,h2{ a,
h1,
h2 {
display: block; display: block;
text-align: center; text-align: center;
} }
article{ article {
border: 2px solid; border: 2px solid;
border-radius: 15px; border-radius: 15px;
border-color: black; border-color: black;
@ -23,43 +25,65 @@
width: 100%; width: 100%;
padding: 20px; padding: 20px;
} }
#kursive{ #kursive {
font-style: italic; font-style: italic;
} }
img{ img {
border-radius: 2%; border-radius: 2%;
width: 100%; width: 100%;
aspect-ratio: 4/3; aspect-ratio: 4/3;
object-fit: contain; object-fit: contain;
} }
a{ a {
color: black; color: black;
} }
h2{ h2 {
text-align: center; text-align: center;
} }
article > a{ #gray {
font-size: 0.75rem; font-size: 0.75rem;
display: block; display: block;
text-align: center; text-align: center;
color: rgb(181, 181, 181); color: rgb(181, 181, 181);
} }
button{ button {
padding: 10px; padding: 10px;
margin: 5px; margin: 5px;
border: black; border: black;
border-radius: 20px; border-radius: 20px;
} }
#logo{
object-fit: scale-down;
}
#logocontaner{
margin: 0 auto;
height: 25%;
width: 25%;
}
#logo{
height: 105%;
scale: 150%;
}
#logocontaner{
margin: 0 auto;
}
</style> </style>
<a href="/" id="logocontaner"><img id="logo" src="/static/Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"></img></a>
<h1>ESC Playlist</h1> <h1>ESC Playlist</h1>
<h2>2026</h2> <a href="/suche?liste={{liste}}"
<a href="/suche?liste={{liste}}">Du willst ein weiteres Lied in der Playlist?</a> >Du willst ein weiteres Lied in der Playlist?</a
<p>Die Playlist {{liste}} ist insgesamt {{ gesamtLaenge | zeit }} lang und enthält {{ karten|length }} Lieder</p> >
<p><button id="play" onclick="abspielen()">Abspielen</button><button id="loop" onclick="looptrue()">Loop</button></p> <p>
<div id = "flex-container"> Die Playlist {{liste}} ist insgesamt {{ gesamtLaenge | zeit }} lang und
{% for karte in karten %} enthält {{ karten|length }} Lieder
{% set karte_loop = loop %} </p>
{% include "karte.html" %} <p>
{% endfor %} <button id="play" onclick="abspielen()">Abspielen</button
><button id="loop" onclick="looptrue()">Loop</button>
</p>
<div id="flex-container">
{% for karte in karten %} {% set karte_loop = loop %} {% include
"karte.html" %} {% endfor %}
</div> </div>
<script src="static/script.js"></script> <script src="static/script.js"></script>

View file

@ -1,24 +1,42 @@
<article> <article>
<img src="{{ karte.img }}"/> <img src="{{ karte.img }}" />
{% if karte.ytid %} {% if karte.ytid %}
<p><button id="{{karte_loop.index0}}" onclick="vorherige(this.id)">Vorherige</button><button id="{{karte_loop.index0}}" onclick="abspielendiese(this.id)">Abspielen</button><button id="{{karte_loop.index0}}" onclick="nächste(this.id)">Nächstes</button></p> <p>
<audio controls src="/static/{{karte.datei}}"></audio> <button id="{{karte_loop.index0}}" onclick="vorherige(this.id)">
Vorherige</button
><button id="{{karte_loop.index0}}" onclick="abspielendiese(this.id)">
Abspielen</button
><button id="{{karte_loop.index0}}" onclick="nächste(this.id)">
Nächstes
</button>
</p>
<audio src="/static/{{karte.datei}}"></audio>
{% endif %} {% endif %}
<h2>{{ karte.titel}}</h2> <h2>{{ karte.titel}}</h2>
<p><b>Übersetzter Titel:</b>{{ karte.uetitel}}</p>
<p><b>Interpreten:</b>{{ karte.interprete}}</p>
{% if karte.jahrgang %} {% if karte.jahrgang %}
<p><b>Jahrgang:</b> {{ karte.jahrgang }}</p> <p><b>Jahrgang:</b> {{ karte.jahrgang }}</p>
{% endif %} {% endif %} {% if karte.plazirung%}
{% if karte.plazirung%}
<p><b>Plazirung:</b> {{ karte.plazirung }}</p> <p><b>Plazirung:</b> {{ karte.plazirung }}</p>
{% endif %} {% if karte.land %}
<p><b>Antretent für:</b> {{karte.land}}</p>
{% endif %} {% endif %}
<p><b>Interpret(en):</b> {{ karte.interprete}}</p>
<p><b>Länge:</b> {{karte.laenge|zeit}}</p> <p><b>Länge:</b> {{karte.laenge|zeit}}</p>
<p><a href="https://www.wikidata.org/entity/{{karte.wikiid}}">Q-id:</a> {{karte.wikiid}}</p> <p id="gray">
{% if karte.text %} {% if karte.text %}
<a href="{{ karte.text }}" target="_blank">Original Text</a> <a id="gray" href="{{ karte.text }}" target="_blank">Original Text</a>
{% endif %} {% endif %}
<a id="gray" href="https://www.wikidata.org/entity/{{karte.wikiid}}"
>Q-id:{{karte.wikiid}}</a
>
</p>
{% if admin %} {% if admin %}
<form method="post"><button name="index" value="{{karte_loop.index0}}">&lt;X&gt;</button></form> <form method="post">
<button name="index" value="{{karte_loop.index0}}">&lt;X&gt;</button>
</form>
{% endif %} {% endif %}
</article> </article>

View file

@ -1,8 +1,19 @@
<style> <style>
body{
display: block;
text-align: center;
}
form{ form{
display: block; display: block;
text-align: center; text-align: center;
color: black; color: black;
} }
#logo{
object-fit: scale-down;
}
#logocontaner{
margin: 3px;
}
</style> </style>
<a href="/" id="logocontaner"><img src="/static/Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"></img></a>
<form><input name="name" value={{name}} placeholder="Name der Playlist"></form> <form><input name="name" value={{name}} placeholder="Name der Playlist"></form>

View file

@ -11,7 +11,14 @@
text-align: center; text-align: center;
font-size: smaller; font-size: smaller;
} }
#logo{
object-fit: scale-down;
}
#logocontaner{
margin: 3px;
}
</style> </style>
<a id="logocontaner"><img src="/static/Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"></img></a>
{% for list in lists %} {% for list in lists %}
<a id="playlist" href="/?liste={{list}}"> {{list}} </a> <a id="playlist" href="/?liste={{list}}"> {{list}} </a>
{% endfor %} {% endfor %}

View file

@ -4,7 +4,14 @@
text-align: center; text-align: center;
color: black; color: black;
} }
#logo{
object-fit: scale-down;
}
#logocontaner{
margin: 3px;
}
</style> </style>
<a href="/" id="logocontaner"><img src="/static/Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"></img></a>
{% if liste == empty %} {% if liste == empty %}
<p>Du musst etwas in die Playlist Screiben</p> <p>Du musst etwas in die Playlist Screiben</p>
{% endif %} {% endif %}