123 lines
4.7 KiB
JavaScript
123 lines
4.7 KiB
JavaScript
const tokenInput = document.querySelector('#token');
|
|
const rememberTokenCheckbox = document.querySelector('#remember-token');
|
|
const setTokenButton = document.querySelector('#set-token');
|
|
const lessonInput = document.querySelector('#lesson-query');
|
|
const getLessonButton = document.querySelector('#get-lesson');
|
|
let token = localStorage.getItem('token') || '';
|
|
|
|
if (token !== '') {
|
|
tokenInput.value = token;
|
|
rememberTokenCheckbox.checked = true;
|
|
fetch("/api/v1/token", {
|
|
method: 'POST',
|
|
body: token,
|
|
}).then(rsp => {
|
|
if (rsp.status !== 200) {
|
|
setTokenButton.innerHTML = `:( (${rsp.status})`;
|
|
}
|
|
});
|
|
}
|
|
|
|
function randomString(length) {
|
|
return `a${Math.random().toString(36).slice(2, length + 2)}`;
|
|
}
|
|
|
|
// React simulator
|
|
function getResult(id) {
|
|
const element = document.createElement("div");
|
|
element.className = "block";
|
|
document.body.appendChild(document.createElement("br"));
|
|
document.body.appendChild(element);
|
|
return element;
|
|
}
|
|
|
|
setTokenButton.addEventListener('click', async () => {
|
|
token = tokenInput.value;
|
|
const rsp = await fetch("/api/v1/token", {
|
|
method: 'POST',
|
|
body: token,
|
|
});
|
|
if (rsp.status !== 200) {
|
|
setTokenButton.innerHTML = `:( (${rsp.status})`;
|
|
return;
|
|
}
|
|
if (rememberTokenCheckbox.checked) {
|
|
localStorage.setItem('token', token);
|
|
} else {
|
|
localStorage.removeItem('token');
|
|
}
|
|
});
|
|
|
|
getLessonButton.addEventListener('click', async () => {
|
|
const input = lessonInput.value;
|
|
let id = Number.parseInt(input);
|
|
if (Number.isNaN(id)) {
|
|
const url = input.split('/');
|
|
url.pop();
|
|
id = Number.parseInt(url.pop());
|
|
}
|
|
const rsp = await fetch(`/api/v1/lessons/${id}`);
|
|
const result = getResult("lesson");
|
|
const data = await rsp.json();
|
|
const ids = {};
|
|
// React :nerd:
|
|
result.innerHTML = "<h2>Lesson Information</h2>\n";
|
|
result.innerHTML += `Name: ${decodeURIComponent(data.name)}`;
|
|
result.innerHTML += "<h3>Videos available</h3>";
|
|
for (const video of data.videos) {
|
|
const uniqueId = randomString(15);
|
|
ids[uniqueId] = video;
|
|
result.innerHTML += `
|
|
<input type="checkbox" id="${uniqueId}" name="${uniqueId}" value="${uniqueId}">
|
|
<label for="${uniqueId}">${decodeURIComponent(video.name)}</label>
|
|
<br>`;
|
|
}
|
|
let videoDlResult = null;
|
|
const downloadSelectedButton = document.createElement("button");
|
|
downloadSelectedButton.innerHTML = "Download Selected";
|
|
downloadSelectedButton.addEventListener('click', async () => {
|
|
for (const [id, video] of Object.entries(ids)) {
|
|
const checkbox = document.querySelector(`#${id}`);
|
|
if (!checkbox.checked) {
|
|
continue;
|
|
}
|
|
const videoRsp = await fetch(`/api/v1/videos/${video.id}`);
|
|
if (videoRsp.status !== 200) {
|
|
console.error(`Failed to get video ${video.name}`);
|
|
continue;
|
|
}
|
|
const videoData = await videoRsp.json();
|
|
if (videoDlResult === null) {
|
|
result.appendChild(document.createElement("br"));
|
|
result.appendChild(document.createElement("br"));
|
|
videoDlResult = document.createElement("div");
|
|
videoDlResult.className = "block";
|
|
result.appendChild(videoDlResult);
|
|
}
|
|
const progressId = randomString(15);
|
|
const progressStrId = randomString(15);
|
|
videoDlResult.innerHTML += `<span>${video.name}.mp4 <progress id="${progressId}" value="0" max="100"></progress> <span id="${progressStrId}">0%</span></span>`
|
|
const rsp = await fetch(`/api/v1/download-video?${new URLSearchParams({
|
|
url: encodeURIComponent(videoData.m3u8),
|
|
output: encodeURIComponent(`videos/${video.name}.mp4`),
|
|
})}`);
|
|
const reader = rsp.body.getReader();
|
|
while (true) {
|
|
// wait for next encoded chunk
|
|
const { done, value } = await reader.read();
|
|
// check if stream is done
|
|
if (done) break;
|
|
// Decodes data chunk and yields it
|
|
const progress = Math.floor(Number.parseFloat(new TextDecoder().decode(value)));
|
|
document.querySelector(`#${progressId}`).value = progress;
|
|
document.querySelector(`#${progressStrId}`).innerText = `${progress}%`;
|
|
}
|
|
if (rsp.status !== 200) {
|
|
console.error(`Failed to download ${video.name}`);
|
|
}
|
|
}
|
|
});
|
|
result.appendChild(downloadSelectedButton);
|
|
// result.innerHTML += "<button>Download All</button>";
|
|
|
|
}); |