205 lines
5.7 KiB
JavaScript
205 lines
5.7 KiB
JavaScript
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;
|
|
};
|