let isIOS = navigator.userAgent.toLowerCase().match("iphone os"); let isFirefox = navigator.userAgent.toLowerCase().match("firefox/"); let version = 8; let regex = new RegExp(/https:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/); let switchers = { "theme": ["auto", "light", "dark"], "ytFormat": ["webm", "mp4"], "quality": ["max", "hig", "mid", "low"], "audioFormat": ["best", "mp3", "ogg", "wav", "opus"] } let checkboxes = ["disableTikTokWatermark", "fullTikTokAudio"]; if (!isFirefox) checkboxes.push("disableClipboardButton"); let exceptions = { // used solely for ios devices, because they're less capable than everything else. "ytFormat": "mp4", "audioFormat": "mp3" } function eid(id) { return document.getElementById(id) } function sGet(id) { return localStorage.getItem(id) } function sSet(id, value) { localStorage.setItem(id, value) } function enable(id) { eid(id).dataset.enabled = "true"; } function disable(id) { eid(id).dataset.enabled = "false"; } function vis(state) { return (state === 1) ? "visible" : "hidden"; } function opposite(state) { return state == "true" ? "false" : "true"; } function changeDownloadButton(action, text) { switch (action) { case 0: eid("download-button").disabled = true if (sGet("alwaysVisibleButton") == "true") { eid("download-button").value = text eid("download-button").style.padding = '0 1rem' } else { eid("download-button").value = '' eid("download-button").style.padding = '0' } break; case 1: eid("download-button").disabled = false eid("download-button").value = text eid("download-button").style.padding = '0 1rem' break; case 2: eid("download-button").disabled = true eid("download-button").value = text eid("download-button").style.padding = '0 1rem' break; } } document.addEventListener("keydown", (event) => { if (event.key == "Tab") { eid("download-button").value = '>>' eid("download-button").style.padding = '0 1rem' } }) function button() { let regexTest = regex.test(eid("url-input-area").value); if ((eid("url-input-area").value).length > 0) { eid("url-clear").style.display = "block"; } else { eid("url-clear").style.display = "none"; } regexTest ? changeDownloadButton(1, '>>') : changeDownloadButton(0, '>>'); } function clearInput() { eid("url-input-area").value = ''; button(); } function copy(id, data) { let e = document.getElementById(id); e.classList.add("text-backdrop"); data ? navigator.clipboard.writeText(data) : navigator.clipboard.writeText(e.innerText); setTimeout(() => { e.classList.remove("text-backdrop") }, 600); } function detectColorScheme() { let theme = "auto"; let localTheme = sGet("theme"); if (localTheme) { theme = localTheme; } else if (!window.matchMedia) { theme = "dark" } document.documentElement.setAttribute("data-theme", theme); } function changeTab(evnt, tabId, tabClass) { let tabcontent = document.getElementsByClassName(`tab-content-${tabClass}`); let tablinks = document.getElementsByClassName(`tab-${tabClass}`); for (let i = 0; i < tabcontent.length; i++) { tabcontent[i].style.display = "none"; } for (let i = 0; i < tablinks.length; i++) { tablinks[i].dataset.enabled = "false"; } eid(tabId).style.display = "block"; evnt.currentTarget.dataset.enabled = "true"; } function hideAllPopups() { let filter = document.getElementsByClassName('popup'); for (let i = 0; i < filter.length; i++) { filter[i].style.visibility = "hidden"; } eid("imagepicker-holder").innerHTML = ''; eid("imagepicker-download").href = '/'; eid("popup-backdrop").style.visibility = "hidden"; } function popup(type, action, text) { if (action == 1) hideAllPopups(); eid("popup-backdrop").style.visibility = vis(action); switch (type) { case "about": let tabId = text ? text : "changelog"; if (tabId == "changelog") { sSet("changelogStatus", version) } eid(`tab-button-${type}-${tabId}`).click(); eid("popup-about").style.visibility = vis(action); if (!sGet("seenAbout")) sSet("seenAbout", "true"); break; case "settings": eid(`tab-button-${type}-video`).click(); eid("popup-settings").style.visibility = vis(action); break; case "error": eid("desc-error").innerHTML = text; eid("popup-error").style.visibility = vis(action); break; case "download": if (action == 1) { eid("pd-download").href = text; eid("pd-copy").setAttribute("onClick", `copy('pd-copy', '${text}')`); } eid("popup-download").style.visibility = vis(action); break; case "imagePicker": switch (action) { case 1: eid("imagepicker-download").href = text.url; for (let i in text.images) { eid("imagepicker-holder").innerHTML += `
` } break; case 0: eid("imagepicker-download").href = '/'; eid("imagepicker-holder").innerHTML = '' break; } eid("popup-imagePicker").style.visibility = vis(action); break; default: eid(`popup-${type}`).style.visibility = vis(action); break; } } function changeSwitcher(li, b) { if (b) { sSet(li, b); for (let i in switchers[li]) { (switchers[li][i] == b) ? enable(`${li}-${b}`) : disable(`${li}-${switchers[li][i]}`) } if (li == "theme") detectColorScheme(); } else { let pref = switchers[li][0]; if (isIOS && exceptions[li]) pref = exceptions[li]; sSet(li, pref); for (let i in switchers[li]) { (switchers[li][i] == pref) ? enable(`${li}-${pref}`) : disable(`${li}-${switchers[li][i]}`) } } } function internetError() { eid("url-input-area").disabled = false changeDownloadButton(2, '!!'); popup("error", 1, loc.noInternet); } function checkbox(action) { if (eid(action).checked) { sSet(action, "true"); if (action == "alwaysVisibleButton") button(); if (action == "disableClipboardButton") eid("pasteFromClipboard").style.display = "none"; } else { sSet(action, "false"); if (action == "alwaysVisibleButton") button(); if (action == "disableClipboardButton") eid("pasteFromClipboard").style.display = "flex"; } } function updateToggle(toggl, state) { switch(state) { case "true": eid(toggl).innerHTML = loc.toggleAudio; break; case "false": eid(toggl).innerHTML = loc.toggleDefault; break; } } function toggle(toggl) { let state = sGet(toggl); if (state) { sSet(toggl, opposite(state)) if (opposite(state) == "true") sSet(`${toggl}ToggledOnce`, "true"); } else { sSet(toggl, "false") } updateToggle(toggl, sGet(toggl)) } function loadSettings() { if (sGet("disableClipboardButton") == "true" && !isFirefox) eid("pasteFromClipboard").style.display = "none"; if (sGet("alwaysVisibleButton") == "true") { eid("alwaysVisibleButton").checked = true; eid("download-button").value = '>>' eid("download-button").style.padding = '0 1rem'; } if (sGet("downloadPopup") == "true" && !isIOS) { eid("downloadPopup").checked = true; } if (!sGet("audioMode")) { toggle("audioMode") } for (let i = 0; i < checkboxes.length; i++) { if (sGet(checkboxes[i]) == "true") eid(checkboxes[i]).checked = true; } updateToggle("audioMode", sGet("audioMode")); for (let i in switchers) { changeSwitcher(i, sGet(i)) } } async function pasteClipboard() { let t = await navigator.clipboard.readText(); if (regex.test(t)) { eid("url-input-area").value = t; download(eid("url-input-area").value); } } async function download(url) { changeDownloadButton(2, '...'); eid("url-clear").style.display = "none"; eid("url-input-area").disabled = true; let audioMode = sGet("audioMode"); let format = ``; if (audioMode == "false") { if (url.includes("youtube.com/") || url.includes("/youtu.be/")) { format = `&format=${sGet("ytFormat")}` } else if ((url.includes("tiktok.com/") || url.includes("douyin.com/")) && sGet("disableTikTokWatermark") == "true") { format = `&nw=true` } } else { format = `&nw=true` if (sGet("fullTikTokAudio") == "true") format += `&ttfull=true` } let mode = (sGet("audioMode") == "true") ? `audio=true` : `quality=${sGet("quality")}` await fetch(`/api/json?audioFormat=${sGet("audioFormat")}&${mode}${format}&url=${encodeURIComponent(url)}`).then(async (r) => { let j = await r.json(); if (j.status != "error" && j.status != "rate-limit") { if (j.url) { switch (j.status) { case "redirect": changeDownloadButton(2, '>>>') setTimeout(() => { changeDownloadButton(1, '>>'); eid("url-clear").style.display = "block"; eid("url-input-area").disabled = false }, 3000) if (sGet("downloadPopup") == "true") { popup('download', 1, j.url) } else { window.open(j.url, '_blank'); } break; case "images": case "stream": changeDownloadButton(2, '?..') fetch(`${j.url}&p=1&origin=front`).then(async (res) => { let jp = await res.json(); if (jp.status == "continue") { changeDownloadButton(2, '>>>') if (j.status === "images") { popup('imagePicker', 1, { url: j.url, images: j.images }) } else { window.location.href = j.url } setTimeout(() => { changeDownloadButton(1, '>>'); eid("url-clear").style.display = "block"; eid("url-input-area").disabled = false }, 5000) } else { eid("url-input-area").disabled = false changeDownloadButton(2, '!!'); eid("url-clear").style.display = "block"; popup("error", 1, jp.text); } }).catch((error) => internetError()); break; default: eid("url-input-area").disabled = false changeDownloadButton(2, '!!'); eid("url-clear").style.display = "block"; popup("error", 1, loc.unknownStatus); break; } } else { eid("url-input-area").disabled = false eid("url-clear").style.display = "block"; changeDownloadButton(2, '!!') popup("error", 1, loc.noURLReturned); } } else { eid("url-input-area").disabled = false eid("url-clear").style.display = "block"; changeDownloadButton(2, '!!') popup("error", 1, j.text); } }).catch((error) => internetError()); } async function loadOnDemand(elementId, blockId) { let store = eid(elementId).innerHTML; eid(elementId).innerHTML = "..." await fetch(`/api/onDemand?blockId=${blockId}`).then(async (r) => { let j = await r.json(); if (j.status == "success" && j.status != "rate-limit") { if (j.text) { eid(elementId).innerHTML = j.text; } else { throw new Error() } } else { throw new Error() } }).catch((error) => { eid(elementId).innerHTML = store; internetError() }); } window.onload = () => { loadSettings(); detectColorScheme(); changeDownloadButton(0, '>>'); eid("cobalt-main-box").style.visibility = 'visible'; eid("footer").style.visibility = 'visible'; eid("url-input-area").value = ""; if (!sGet("seenAbout")) { popup('about', 1, "about"); } else if (sGet("changelogStatus") != `${version}` && sGet("disableChangelog") != "true") { popup('about', 1, "changelog"); } if (isIOS) sSet("downloadPopup", "true"); let urlQuery = new URLSearchParams(window.location.search).get("u"); if (urlQuery !== null) { eid("url-input-area").value = urlQuery; button(); } } eid("url-input-area").addEventListener("keydown", (event) => { if (event.key === 'Escape') eid("url-input-area").value = ''; button(); }) eid("url-input-area").addEventListener("keyup", (event) => { if (event.key === 'Enter') eid("download-button").click(); }) document.onkeydown = (event) => { if (event.key == "Tab" || event.ctrlKey) eid("url-input-area").focus(); if (event.key === 'Escape') hideAllPopups(); };