const genRanHex = (size) => [...Array(size)] .map(() => Math.floor(Math.random() * 16).toString(16)) .join(""); const sessionStr = () => { if (!localStorage.getItem("session")) localStorage.setItem("session", genRanHex(64)); return localStorage.getItem("session"); }; const sessionState = async () => { const response = await fetch(`/state/?session=${sessionStr()}`); return await response.json(); }; const sessionStatus = (() => { let task; return async () => { if (task === undefined) { task = (async () => { const response = await fetch(`/status/?session=${sessionStr()}`); return await response.json(); })(); } return await task; }; })(); const root = document.querySelector("#root"); const logEl = (msg) => { const el = document.createElement("pre"); el.innerText = msg; root.append(el); }; const sessionClient = async () => { const session = await sessionStatus(); return session && session["client"]; }; const sessionUser = async () => { const client = await sessionClient(); return client && client["user"]; }; const userAvatarUrl = async () => { const user = await sessionUser(); return user && user["avatar"]; }; const userUsername = async () => { const user = await sessionUser(); return user && user["username"]; }; const userAvatarImg = async () => { const avatar = await userAvatarUrl(); if (avatar) { const img = document.createElement("img"); img.src = avatar; img.width = 64; img.height = 64; img.alt = await userUsername(); return img; } else { return baseEl("span"); } }; const userId = async () => { const user = await sessionUser(); return user && user["id"]; }; const baseEl = (tag, ...appended) => { const element = document.createElement(tag); element.append(...appended); return element; }; const aLogin = () => { const a = document.createElement("a"); a.href = "/login/"; a.innerText = "login"; return a; }; const aAuthLink = async () => { const response = await fetch("/authlink/"); return await response.text(); }; const aAuth = async () => { const a = document.createElement("a"); const [authlink, sessionstate] = await Promise.all([ aAuthLink(), sessionState(), ]); a.href = authlink + "&state=" + sessionstate; a.innerText = "auth"; return a; }; const aApi = async (request) => { const response = await fetch(`/api/?session=${sessionStr()}`, { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json", }, body: JSON.stringify(request), }); return await response.json(); }; const aGuilds = async () => { return await aApi({ type: "guilds" }); }; const aQueue = async () => { const requests = {}; for (const guild of await aGuilds()) { requests[guild] = { type: "*", guild, voice: null, main: null, catches: { "you are not connected to voice": null, "*": null }, requests: { volume: {}, playing: {}, queueformat: {}, queuejson: {} }, }; } const responses = await aApi({ type: "*", requests }); for (const [guild, response] of Object.entries(responses)) { if (response !== null && response.error === undefined) { response.guild = guild; response.time = Date.now() / 1000; response.delta = () => Date.now() / 1000 - response.time; let index = 0; for (const audio of response.queuejson) { audio.playing = response.playing && index === 0; audio.delta = () => (audio.playing ? response.delta() : 0); audio.now = () => audio.seconds + audio.delta(); audio.ts = () => { const seconds_total = Math.round(audio.now()); const seconds = seconds_total % 60; const minutes_total = (seconds_total - seconds) / 60; const minutes = minutes_total % 60; const hours = (minutes_total - minutes) / 60; return `${hours}:${("00" + minutes).slice(-2)}:${( "00" + seconds ).slice(-2)}`; }; index += 1; } return response; } } return null; }; const sleep = (s) => { return new Promise((resolve) => setTimeout(resolve, 1000 * s)); }; const audioWidget = (audio) => { const description = baseEl("span", audio.description); const timecode = baseEl("span", audio.timecode); const duration = baseEl("span", audio.duration); audio.tce = timecode; return baseEl("div", "audio", " ", timecode, "/", duration, " ", description); }; const aUpdateQueueOnce = async (queue, el) => { el.innerHTML = ""; if (queue !== null) { for (const audio of queue.queuejson) { el.append(audioWidget(audio)); } } }; const aUpdateQueueSetup = async (el) => { let queue = await aQueue(); await aUpdateQueueOnce(queue, el); (async () => { while (true) { await sleep(2); if (queue !== null && queue.queuejson.length > 100) { await sleep((queue.queuejson.length - 100) / 200); } const newQueue = await aQueue(); await aUpdateQueueOnce(newQueue, el); queue = newQueue; } })(); (async () => { while (true) { await sleep(0.25); if (queue !== null) { for (const audio of queue.queuejson) { audio.tce.innerText = audio.ts(); break; } } } })(); }; const aQueueWidget = async () => { const el = baseEl("div"); if (await sessionUser()) await aUpdateQueueSetup(el); return el; }; const pageHome = async () => { const el = document.createElement("div"); el.append( baseEl("div", aLogin()), baseEl("div", await userAvatarImg()), baseEl("div", await userId()), baseEl("div", await userUsername()), baseEl("div", await aQueueWidget()) ); el.id = "homeroot"; return el; };