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

330
app.py
View file

@ -1,175 +1,231 @@
from flask import Flask, render_template, request, redirect
from glob import glob
import subprocess
import requests
import json
import os
import subprocess
from glob import glob
import requests
from flask import Flask, redirect, render_template, request
def wikiapi(id, field):
if os.path.isdir("data"):
pass
else:
os.mkdir("data")
name = f"data/{id}_{field}.json"
try:
with open(name, "r") as f:
data = json.load(f)
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",
},
)
data = r.json()
with open(name, "x") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return data[field]
def wikiapi(id,field):
if os.path.isdir("data"):
pass
else:
os.mkdir("data")
name = f"data/{id}_{field}.json"
try:
with open(name, "r") as f:
data = json.load(f)
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'})
data = r.json()
with open(name, "x") as f:
json.dump(data, f,indent=2,ensure_ascii=False)
return data[field]
def wikisuche(text):
mitp1344 = []
ohnep1344 = []
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"]:
if getescedition(result["id"]):
mitp1344.append(result)
else:
ohnep1344.append(result)
return mitp1344 + ohnep1344
mitpartsin = []
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",
},
)
for result in r.json()["results"]:
if getescedition(result["id"]):
mitpartsin.append(result)
else:
ohnepartsin.append(result)
return mitpartsin + ohnepartsin
def getescedition(songId):
statements = wikiapi(songId,"statements")
if "P1344" in statements:
for statement in statements["P1344"]:
id = statement["value"]["content"]
escdata = wikiapi(id,"statements")
if escdata["P31"][0]["value"]["content"] == "Q110288240":
return id,statement
statements = wikiapi(songId, "statements")
if "partsin" in statements:
for statement in statements["partsin"]:
id = statement["value"]["content"]
escdata = wikiapi(id, "statements")
if escdata["P31"][0]["value"]["content"] == "Q110288240":
return id, statement
def datei(id):
file = glob("static/"+id+".*")
file = glob("static/" + id + ".*")
if file == []:
subprocess.run(
["yt-dlp", f"http://youtu.be/{id}", "-x", "-o", id], cwd="static"
)
file = glob("static/" + id + ".*")
if file != []:
audio = file[0].replace("static/", "")
else:
audio = None
print(audio)
return audio
if file == []:
subprocess.run(["yt-dlp",f"http://youtu.be/{id}","-x","-o",id],cwd="static")
file = glob("static/"+id+".*")
if file != []:
audio = file[0].replace("static/", "")
else:
audio = None
print(audio)
return audio
def kartenGeneriren(song):
id = song["wikiid"]
print(id)
statements = wikiapi(id,"statements")
labels = wikiapi(id,"labels")
song["titel"] = statements.get("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)
if escedition:
(escedition,statement)=escedition
song["jahrgang"] = wikiapi(escedition,"labels")["en"]
qualifiers = statement["qualifiers"]
for qualifier in qualifiers:
if qualifier["property"]["id"] == "P1352":
song["plazirung"] = str(int(qualifier["value"]["content"]["amount"]))+"."
song["interprete"] = " x ".join(set(wikiapi(statement["value"]["content"],"labels")["en"] for statement in statements.get("P175",[])))
if "ytid" not in song and "P1651" in statements:
song["ytid"] = statements["P1651"][0]["value"]["content"]
if "ytid" in song:
song["datei"] = datei(song["ytid"])
song["img"] = f"http://img.youtube.com/vi/{ song["ytid"] }/sddefault.jpg"
if "P6218" in statements:
song["text"] = f"//genius.com/{statements["P6218"][0]["value"]["content"]}"
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"
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"
id = song["wikiid"]
print(id)
statements = wikiapi(id, "statements")
labels = wikiapi(id, "labels")
song["titel"] = statements.get(
"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)
if escedition:
(escedition, statement) = escedition
song["jahrgang"] = wikiapi(escedition, "labels")["en"]
qualifiers = statement["qualifiers"]
for qualifier in qualifiers:
if qualifier["property"]["id"] == "P1352":
song["plazirung"] = (
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:
song["ytid"] = statements["P1651"][0]["value"]["content"]
if "ytid" in song:
song["datei"] = datei(song["ytid"])
song["img"] = f"http://img.youtube.com/vi/{song['ytid']}/sddefault.jpg"
if "P6218" in statements:
song["text"] = f"//genius.com/{statements['P6218'][0]['value']['content']}"
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"
)
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"
)
app = Flask(__name__)
@app.template_filter('zeit')
@app.template_filter("zeit")
def zeit(sekunden):
minuten = sekunden // 60
rest = sekunden - minuten * 60
return f"{minuten}:{rest:02}"
minuten = sekunden // 60
rest = sekunden - minuten * 60
return f"{minuten}:{rest:02}"
@app.route("/")
def hello_world():
liste = request.args.get("liste")
if liste is None:
return redirect("/playlists")
with open(liste+".json","r") as f:
songs = json.load(f)
for song in songs:
kartenGeneriren(song)
gesamtLaenge = 0
for song in songs:
gesamtLaenge += song["laenge"]
return render_template('index.html', karten=songs,gesamtLaenge=gesamtLaenge,liste=liste )
liste = request.args.get("liste")
if liste is None:
return redirect("/playlists")
with open(liste + ".json", "r") as f:
songs = json.load(f)
for song in songs:
kartenGeneriren(song)
gesamtLaenge = 0
for song in songs:
gesamtLaenge += song["laenge"]
return render_template(
"index.html", karten=songs, gesamtLaenge=gesamtLaenge, liste=liste
)
@app.route("/playlists")
def playlists():
listen = glob("*.json")
listen = (liste.replace(".json","") for liste in listen)
return render_template('playlists.html',lists=listen)
listen = glob("*.json")
listen = (liste.replace(".json", "") for liste in listen)
return render_template("playlists.html", lists=listen)
@app.route("/neueliste")
def neueliste():
name = request.args.get("name")
if name is not None:
with open(name +".json", "x") as f:
json.dump([],f)
return redirect("/?liste="+name)
print(liste)
return render_template('neueliste.html',name=name)
name = request.args.get("name")
if name is not None:
with open(name + ".json", "x") as f:
json.dump([], f)
return redirect("/?liste=" + name)
return render_template("neueliste.html", name=name)
@app.route("/suche")
def suche():
such = request.args.get("suche")
liste = request.args.get("liste")
if such is not None:
ergebnisse = wikisuche(such)
else:
ergebnisse = []
return render_template('suche.html', ergebnisse=ergebnisse,anfrage=such,liste=liste)
such = request.args.get("suche")
liste = request.args.get("liste")
if such is not None:
ergebnisse = wikisuche(such)
else:
ergebnisse = []
return render_template(
"suche.html", ergebnisse=ergebnisse, anfrage=such, liste=liste
)
@app.route("/suche",methods=["POST"])
@app.route("/suche", methods=["POST"])
def suche_finden():
liste = request.args.get("liste")
with open(liste +".json","r") as f:
songs = json.load(f)
song = {"wikiid":request.form.get("id")}
kartenGeneriren(song)
songs.append(song)
with open(liste+".json","w") as f:
json.dump(songs,f,indent=2,ensure_ascii=False)
return redirect("/suche?liste="+liste,303)
liste = request.args.get("liste")
with open(liste + ".json", "r") as f:
songs = json.load(f)
song = {"wikiid": request.form.get("id")}
kartenGeneriren(song)
songs.append(song)
with open(liste + ".json", "w") as f:
json.dump(songs, f, indent=2, ensure_ascii=False)
return redirect("/suche?liste=" + liste, 303)
@app.route("/remove")
def admin():
liste = request.args.get("liste")
if liste is None:
return redirect("/playlists")
with open(liste+".json","r") as f:
songs = json.load(f)
for song in songs:
kartenGeneriren(song)
gesamtLaenge = 0
for song in songs:
gesamtLaenge += song["laenge"]
return render_template('index.html', karten=songs,gesamtLaenge=gesamtLaenge,liste=liste,admin=True)
liste = request.args.get("liste")
if liste is None:
return redirect("/playlists")
with open(liste + ".json", "r") as f:
songs = json.load(f)
for song in songs:
kartenGeneriren(song)
gesamtLaenge = 0
for song in songs:
gesamtLaenge += song["laenge"]
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():
liste = request.args.get("liste")
song = int(request.form.get("index"))
with open(liste+".json","r") as f:
print(liste+".json")
songs = json.load(f)
print(songs)
print(songs)
del songs[song]
with open(liste+".json","w") as f:
json.dump(songs,f,indent=2,ensure_ascii=False)
return redirect("/remove?liste="+liste,303)
liste = request.args.get("liste")
song = int(request.form.get("index"))
with open(liste + ".json", "r") as f:
print(liste + ".json")
songs = json.load(f)
print(songs)
print(songs)
del songs[song]
with open(liste + ".json", "w") as f:
json.dump(songs, f, indent=2, ensure_ascii=False)
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 articles = document.querySelectorAll("article")
const kartenContainer = document.getElementById("flex-container")
outindex = 0
playing = false
playcolor = "#00ff3c"
loop = true
const audios = document.querySelectorAll("audio");
const articles = document.querySelectorAll("article");
const kartenContainer = document.getElementById("flex-container");
outindex = 0;
playing = false;
playcolor = "#00ff3c";
loop = true;
function onplay(id){
//What is id
id = parseInt(id)
if(id>0){
articles[id-1].style.filter = "grayscale("+(id+1)*20+"%)"
articles[id-1].style.boxShadow = "0 0 0px 0px "+playcolor
function onplay(id) {
id = parseInt(id);
if (id > 0) {
articles[id - 1].style.filter = "grayscale(" + (id + 1) * 20 + "%)";
articles[id - 1].style.boxShadow = "0 0 0px 0px " + playcolor;
}
if(articles[id].offsetWidth * id == window.innerWidth/2){
console.log(articles[id].offsetWidth)
kartenContainer.scrollWidth += articles[id].offsetWidth
if (articles[id].offsetWidth * id == window.innerWidth / 2) {
console.log(articles[id].offsetWidth);
kartenContainer.scrollWidth += articles[id].offsetWidth;
}
articles[id].style.filter = "grayscale(0%)"
articles[id].style.margin = "8px"
articles[id].style.boxShadow = "0 0 6px 1px "+playcolor
articles[id].style.filter = "grayscale(0%)";
articles[id].style.margin = "8px";
articles[id].style.boxShadow = "0 0 6px 1px " + playcolor;
}
function nächste(id){
audios[id].pause()
id = parseInt(id) + 1
audios[id].play()
onplay(id)
function nächste(id) {
audios[id].pause();
id = parseInt(id) + 1;
audios[id].play();
onplay(id);
}
function vorherige(id){
audios[id].pause()
audios[id-1].play()
onplay(id-1)
function vorherige(id) {
audios[id].pause();
audios[id - 1].play();
onplay(id - 1);
}
function looptrue(){
if(loop){
loop = false
document.querySelector("#loop").innerHTML = "Kein Loop"
document.querySelector("#loop").style.beckground
}
else{
loop = true
document.querySelector("#loop").innerHTML = "Loop"
function looptrue() {
if (loop) {
loop = false;
document.querySelector("#loop").innerHTML = "Kein Loop";
document.querySelector("#loop").style.beckground;
} else {
loop = true;
document.querySelector("#loop").innerHTML = "Loop";
}
}
function abspielendiese(id){
if(playing){
function abspielendiese(id) {
if (playing) {
//ON PAUSE
audios[id].pause()
playing = false
articles[id].style.margin = "0px"
articles[id].style.boxShadow = "0 0 0px 0px "+playcolor
}
else{
audios[id].pause();
playing = false;
articles[id].style.margin = "0px";
articles[id].style.boxShadow = "0 0 0px 0px " + playcolor;
} else {
//ON PLAY
audios[id].play()
playing = true
onplay(id)
audios[id].play();
playing = true;
onplay(id);
}
}
function abspielen(){
if(playing){
function abspielen() {
if (playing) {
//ON PAUSE
audios[outindex].pause()
playing = false
articles[outindex].style.margin = "0px"
articles[outindex].style.boxShadow = "0 0 0px 0px "+playcolor
document.querySelector("#play").innerHTML = "Abspielen"
}
else{
audios[outindex].pause();
playing = false;
articles[outindex].style.margin = "0px";
articles[outindex].style.boxShadow = "0 0 0px 0px " + playcolor;
document.querySelector("#play").innerHTML = "Abspielen";
} else {
//ON PLAY
audios[outindex].play()
playing = true
document.querySelector("#play").innerHTML = "Pausieren"
onplay(outindex)
audios[outindex].play();
playing = true;
document.querySelector("#play").innerHTML = "Pausieren";
onplay(outindex);
}
}
for (const [index,audio] of audios.entries()){
audio.addEventListener("ended", (event) => {
if (index != audios.length -1){
outindex = index +1
audios[outindex].play()
onplay(index+1)
}
else{
//Last song ON END
articles[index].style.filter = "grayscale(80%)"
articles[index].style.boxShadow = "0 0 0px 0px "+playcolor
articles[index].style.margin = "8px"
articles[index].style.boxShadow = "0 0 6px 1px "+playcolor
if(loop){
audios[0].play()
for (const [index, audio] of audios.entries()) {
audio.addEventListener("ended", (event) => {
if (index != audios.length - 1) {
outindex = index + 1;
audios[outindex].play();
onplay(index + 1);
} else {
//Last song ON END
articles[index].style.filter = "grayscale(80%)";
articles[index].style.boxShadow = "0 0 0px 0px " + playcolor;
articles[index].style.margin = "8px";
articles[index].style.boxShadow = "0 0 6px 1px " + playcolor;
if (loop) {
audios[0].play();
}
}
}
})
});
}
//Audio visualising

View file

@ -1,21 +1,23 @@
<style>
#flex-container{
#flex-container {
overflow: auto;
scroll-snap-type: x mandatory;
display: flex;
border: none;
gap: 5px;
}
article{
article {
flex-wrap: row nowrap;
border: none;
flex: 0 0 30rem;
}
a,h1,h2{
a,
h1,
h2 {
display: block;
text-align: center;
}
article{
article {
border: 2px solid;
border-radius: 15px;
border-color: black;
@ -23,43 +25,65 @@
width: 100%;
padding: 20px;
}
#kursive{
font-style: italic;
#kursive {
font-style: italic;
}
img{
img {
border-radius: 2%;
width: 100%;
aspect-ratio: 4/3;
object-fit: contain;
}
a{
a {
color: black;
}
h2{
h2 {
text-align: center;
}
article > a{
#gray {
font-size: 0.75rem;
display: block;
text-align: center;
color: rgb(181, 181, 181);
}
button{
button {
padding: 10px;
margin: 5px;
border: black;
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>
<a href="/" id="logocontaner"><img id="logo" src="/static/Eurovision_Song_Contest_heart_Wikidata_(20142025).svg"></img></a>
<h1>ESC Playlist</h1>
<h2>2026</h2>
<a href="/suche?liste={{liste}}">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>
<div id = "flex-container">
{% for karte in karten %}
{% set karte_loop = loop %}
{% include "karte.html" %}
{% endfor %}
<a href="/suche?liste={{liste}}"
>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>
<div id="flex-container">
{% for karte in karten %} {% set karte_loop = loop %} {% include
"karte.html" %} {% endfor %}
</div>
<script src="static/script.js"></script>
<script src="static/script.js"></script>

View file

@ -1,24 +1,42 @@
<article>
<img src="{{ karte.img }}"/>
<img src="{{ karte.img }}" />
{% 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>
<audio controls src="/static/{{karte.datei}}"></audio>
<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>
<audio src="/static/{{karte.datei}}"></audio>
{% endif %}
<h2>{{ karte.titel}}</h2>
<p><b>Übersetzter Titel:</b>{{ karte.uetitel}}</p>
<p><b>Interpreten:</b>{{ karte.interprete}}</p>
{% if karte.jahrgang %}
<p><b>Jahrgang:</b> {{ karte.jahrgang }}</p>
{% endif %}
{% if karte.plazirung%}
<p><b>Plazirung:</b> {{ karte.plazirung }}</p>
{% endif %}
<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>
{% if karte.text %}
<a href="{{ karte.text }}" target="_blank">Original Text</a>
{% if karte.jahrgang %}
<p><b>Jahrgang:</b> {{ karte.jahrgang }}</p>
{% endif %} {% if karte.plazirung%}
<p><b>Plazirung:</b> {{ karte.plazirung }}</p>
{% endif %} {% if karte.land %}
<p><b>Antretent für:</b> {{karte.land}}</p>
{% endif %}
<p><b>Interpret(en):</b> {{ karte.interprete}}</p>
<p><b>Länge:</b> {{karte.laenge|zeit}}</p>
<p id="gray">
{% if karte.text %}
<a id="gray" href="{{ karte.text }}" target="_blank">Original Text</a>
{% endif %}
<a id="gray" href="https://www.wikidata.org/entity/{{karte.wikiid}}"
>Q-id:{{karte.wikiid}}</a
>
</p>
{% 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 %}
</article>

View file

@ -1,8 +1,19 @@
<style>
body{
display: block;
text-align: center;
}
form{
display: block;
text-align: center;
color: black;
}
#logo{
object-fit: scale-down;
}
#logocontaner{
margin: 3px;
}
</style>
<form><input name="name" value={{name}} placeholder="Name der Playlist"></form>
<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>

View file

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

View file

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