Audiofy – Musikwünsche für Partys
Server (Website, Admin-Bereich, Player-API) und Player (raspotify + Controller) mit Install-Skripten für Debian-Systeme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
// Audiofy – Cloudflare Turnstile (Bot-Schutz). Lädt das Widget nur, wenn der Server einen Site-Key liefert.
|
||||
"use strict";
|
||||
|
||||
window.AudiofyTurnstile = (() => {
|
||||
let ladeVersprechen = null;
|
||||
|
||||
function skriptLaden() {
|
||||
if (!ladeVersprechen) {
|
||||
ladeVersprechen = new Promise((fertig, fehler) => {
|
||||
const s = document.createElement("script");
|
||||
s.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
||||
s.async = true;
|
||||
s.onload = () => fertig(window.turnstile);
|
||||
s.onerror = () => fehler(new Error("Turnstile konnte nicht geladen werden"));
|
||||
document.head.append(s);
|
||||
});
|
||||
}
|
||||
return ladeVersprechen;
|
||||
}
|
||||
|
||||
const LEER = { token: async () => null, reset() {}, bereit: () => true };
|
||||
|
||||
// Liefert {token(): Promise<string|null>, reset(), bereit()} – ohne Site-Key ein "leerer" Schutz.
|
||||
async function einrichten(container, aktion) {
|
||||
// Site-Key und Cloudflare-Skript gleichzeitig holen (spart einen Umlauf)
|
||||
const skript = skriptLaden().catch(() => null);
|
||||
let siteKey = null;
|
||||
try {
|
||||
siteKey = (await (await fetch("/api/turnstile", { credentials: "same-origin" })).json()).site_key;
|
||||
} catch (_) { /* ohne Site-Key weiter */ }
|
||||
if (!siteKey) return LEER;
|
||||
|
||||
let aktuell = null;
|
||||
let warten = [];
|
||||
const melden = (wert) => { aktuell = wert; warten.forEach((f) => f(wert)); warten = []; };
|
||||
let ts = null;
|
||||
let id = null;
|
||||
try {
|
||||
ts = await skript;
|
||||
if (!ts) return LEER; // Skript nicht ladbar → Server entscheidet
|
||||
id = ts.render(container, {
|
||||
sitekey: siteKey,
|
||||
action: aktion,
|
||||
appearance: "interaction-only", // nur sichtbar, wenn Cloudflare eine Bestätigung braucht
|
||||
language: "de",
|
||||
callback: (t) => melden(t),
|
||||
"expired-callback": () => { aktuell = null; },
|
||||
"error-callback": () => { melden(null); },
|
||||
});
|
||||
} catch (_) {
|
||||
return LEER; // Server entscheidet dann
|
||||
}
|
||||
|
||||
return {
|
||||
bereit: () => !!aktuell,
|
||||
// wartet bis zu 15 s auf ein Token
|
||||
token() {
|
||||
if (aktuell) return Promise.resolve(aktuell);
|
||||
return new Promise((fertig) => {
|
||||
warten.push(fertig);
|
||||
setTimeout(() => fertig(null), 15000);
|
||||
});
|
||||
},
|
||||
// jedes Token gilt nur einmal → nach jeder Anfrage ein neues holen
|
||||
reset() {
|
||||
aktuell = null;
|
||||
try { ts.reset(id); } catch (_) { /* egal */ }
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return { einrichten };
|
||||
})();
|
||||
Reference in New Issue
Block a user