// cookie parser function function getCookies () { return Object.fromEntries(document.cookie.split(/\s{0,};\s{0,}/gmiu).map(i => i.split(/\s{0,}=\s{0,}/gmiu))); } // translate function function translate (page) { [...document.getElementsByClassName("translate")].forEach(translateEl => { // console.log(translateEl.id); const result = tr(page, translateEl.id); // console.log(result); if (result) translateEl.innerHTML = result; }); [...document.getElementsByClassName("linked-btn")].forEach(el => { el.style.cursor = "pointer"; }); } // Get random integer number function function randint(min, max) { return Math.ceil((Math.random() * (max - min)) + min); } // Get traceId for requests to server function getTraceId() { const dict = "1234567890abcdefABCDEF"; return [...new Array(16)] .map(() => dict[randint(0, dict.length - 1)]) .join(""); } // load styles document.head.innerHTML += '\\n '; document.head.innerHTML += '\\n '; document.head.innerHTML += '\\n '; document.head.innerHTML += '\\n ' // load main page document.body.innerHTML = `
`; function checkContentWarning (successfulHandler) { const warnModal = new bootstrap.Modal(document.getElementById('warningModal'), {}); document.getElementById('accept-denial-btn').onclick = () => { document.cookie = "cw=1"; successfulHandler?.(); }; const cookies = getCookies(); if (!cookies.cw) { warnModal.show(); } else { successfulHandler?.(); } } // Fl Handlers fl.bindLoad("/connect", () => { translate("/connect"); function initNewConnectionOpen () { if (initNewConnectionOpen.interval) clearInterval(initNewConnectionOpen.interval); document.getElementById("custom-conn-address").value = ""; document.getElementById("custom-conn-port").value = 80; document.getElementById("custom-conn-encryption").checked = false; document.getElementById("custom-connect-btn").disabled = true; const connButton = document.getElementById("custom-connect-btn"); initNewConnectionOpen.interval = setInterval(() => { const address = document.getElementById("custom-conn-address"); // address.value const port = document.getElementById("custom-conn-port"); // port.value const isWSS = document.getElementById("custom-conn-encryption"); // isWSS.checked // connButton.disabled if (address.value.match(/^wss:\/\//)) { address.value = address.value.slice(6); isWSS.checked = true; } if (address.value.match(/^ws:\/\//)) { address.value = address.value.slice(5); isWSS.checked = false; } if (address.value.match(/:[0-9]{1,5}$/)) { const portSelected = +(address.value.match(/:[0-9]{1,5}$/).at(0).slice(1,)); address.value = address.value.slice(0, -1 * (":"+portSelected).length); port.value = portSelected; document.getElementById("custom-conn-port").focus(); } if (!port.value) { port.value = 80; } if (+port.value < 0) port.value = 0; if (+port.value > 65535) port.value = 65535; connButton.disabled = !address.value; }, 50); connButton.onclick = () => { const serverlist = JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []; serverlist.push({ address: document.getElementById("custom-conn-address").value, port: +document.getElementById("custom-conn-port").value, tls: document.getElementById("custom-conn-encryption").checked, }); localStorage.setItem("savedServers", JSON.stringify(serverlist)); connectServers(); } } function connectServers () { document.getElementById("loading-servers").innerHTML = `

${tr("/connect", "loading") ?? "Loading..."}

`; const xhr = new XMLHttpRequest(); xhr.open("GET", "/api/active-servers.json", true); xhr.onerror = () => { document.getElementById("loading-servers").innerHTML = `

${tr("/connect", "connection-failed") ?? "Connection failed"}


`; document.getElementById("retry-connecting").onclick = () => connectServers(); } xhr.onload = async () => { if (xhr.status === 200) { const localServers = (JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []).map(x => { x.fromLocal = true; return x }); const servers = localServers.concat(JSON.parse(xhr.response).result.map(x => { x.fromLocal = false; return x })); const serversByItemID = new Object(); const serversByAddress = new Object(); const items = []; const itemIDs = []; const mp = servers.map(async serverItem => { const promise = new Promise((resolve, reject) => { console.log("serverItem:", serverItem); const trace_id = getTraceId(); const socket = new WebSocket(`${!serverItem.tls ? "ws" : "wss"}://${serverItem.address}:${serverItem.port}`); let ping = new Date(); socket.onopen = () => { ping = (new Date()) - ping; socket.onmessage = (ev) => { const data = JSON.parse(ev.data).result; data.tls = serverItem.tls; itemIDs.push({ ...data, itemID: `con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`, deleteID: `remove-con:${serverItem.address}:${serverItem.port}`, address: `${serverItem.address}:${serverItem.port}`, }); serversByItemID[`con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`] = { data, serverItem }; serversByAddress[`${serverItem.address}:${serverItem.port}`] = { data, serverItem }; resolve(items.push(` ${data.name} ${serverItem.address}:${serverItem.port} ${!data.tls ? '' : ''} ${ping} `)); }; socket.send(JSON.stringify({ method: "info", trace_id })); }; socket.onerror = (err) => { console.error(err); itemIDs.push({ deleteID: `remove-con:${serverItem.address}:${serverItem.port}`, address: `${serverItem.address}:${serverItem.port}`, }); serversByAddress[`${serverItem.address}:${serverItem.port}`] = { serverItem }; resolve(items.push(` ${tr("/connect", "offline-server") ?? "Offline"} ${serverItem.address}:${serverItem.port} ${tr("/connect", "offline-server") ?? "Offline"} `)); }; }); return await promise; }); await Promise.all(mp); items.push(`
`); document.getElementById("loading-servers").innerHTML = ` ${items.join("\n")}
${tr("/connect", "server-name-tbl") ?? "Name"} ${tr("/connect", "server-address") ?? "Address"} ${tr("/connect", "server-encryption") ?? "Encrypted"} ${tr("/connect", "server-ping") ?? "Ping"} ${tr("/connect", "server-action") ?? "Action"}
`; itemIDs.forEach(btn => { //console.log("btn:", btn); if (btn.itemID) document.getElementById(btn.itemID).onclick = () => { checkContentWarning(() => { const serverInfo = serversByItemID[btn.itemID].serverItem; window.open(`/connect-area?server=${serverInfo.address}:${serverInfo.port}&encrypted=${serverInfo.tls ? "true" : "false"}`); }); }; document.getElementById(btn.deleteID).onclick = () => { const serverInfo = serversByAddress[btn.address].serverItem; console.log("serverInfo:", serverInfo); const savedServers = (JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []) .filter(server => { return !(server.address === serverInfo.address && server.port === serverInfo.port) }); localStorage.setItem("savedServers", JSON.stringify(savedServers)); connectServers(); }; }); document.getElementById("conn-to-custom").onclick = function () { const connectModal = new bootstrap.Modal(document.getElementById('connectModal'), {}); initNewConnectionOpen(); connectModal.show(); } } }; xhr.send(); } const cookies = getCookies(); console.log(cookies); const cookiesModal = new bootstrap.Modal(document.getElementById('cookiesModal'), {}); if (!cookies.accept_cookies) { cookiesModal.show(); } else { connectServers(); } document.getElementById("accept-cookie-btn").onclick = () => { document.cookie = "accept_cookies=1"; connectServers(); }; /*document.getElementById("enable-cookie-cnt").onclick = () => { cookiesModal.show(); };*/ }); fl.bindLoad("", () => { translate("/"); // carousel function onMouse (condition) { return; [...document.getElementsByClassName("card-img")].forEach(img => { img.style.filter = `blur(${!condition ? 5 : 0}px)`; }); } onMouse(false); [...document.getElementsByClassName("carousel-item")].forEach(item => { item.onmouseout = () => onMouse(false); item.onmouseover = () => onMouse(true); }); [...document.getElementsByClassName("btn-card")].forEach(item => { item.onmouseout = () => onMouse(true); item.onmouseover = () => onMouse(false); }); const interval = setInterval(() => { const navbarHeight = +(document.getElementById("navbar-main")?.offsetHeight); /*if (document.getElementById('main_img1')?.src) { document.getElementById('main_img1').src = window.screen.availWidth / window.screen.availHeight > 1.45 ? "/assets/hello/1.png" : "/assets/hello/m/1.png"; document.getElementById('main_img2').src = window.screen.availWidth / window.screen.availHeight > 1.45 ? "/assets/hello/2.png" : "/assets/hello/m/2.png"; document.getElementById('main_img3').src = window.screen.availWidth / window.screen.availHeight > 1.45 ? "/assets/hello/3.png" : "/assets/hello/m/3.png"; }*/ const selectedCSS = Object.entries(document.styleSheets).filter(([key, cssFileObject]) => cssFileObject.href === `${location.origin}/css/main.css`)[0][1]; Object.entries(selectedCSS.rules).filter(([key, rule]) => rule.selectorText == '.carousel > .carousel-inner > .carousel-item > img')[0][1].style.height = `calc(100vh - ${navbarHeight}px)`; // console.log('ok'); }, 1); fl.bindUnload("/", () => { clearInterval(interval); }); }); // Go to current page fl.goJust(window.location.pathname);