import { ServerAuth } from "/js/connect/auth.js"; function randint(min, max) { return Math.ceil((Math.random() * (max - min)) + min); } function getTraceId() { const dict = "1234567890abcdefABCDEF"; return [...new Array(16)] .map(() => dict[randint(0, dict.length - 1)]) .join(""); } const curUrl = new URL(location.href); const [address, port] = curUrl.searchParams.get("server").split(/:/); const isTLSmode = curUrl.searchParams.get("encrypted") === "true"; class ProtoApiMethods { constructor (api) { this.api = api; } async _protoMethod (rqdata, threadcb = null) { const socket = this.api.socket; const trace_id = getTraceId() const promise = new Promise((rs, rj) => { socket.onmessage = (ev) => { ev = JSON.parse(ev.data); const data = ev.result; console.debug("Method sended:", ev); if (ev.trace_id === trace_id) if (ev.warning) console.warn("Method warning:", ev.warning, "\ndetails:", ev); if (!!ev.ended) return rs(data); if (typeof threadcb === 'function') threadcb(data); }; socket.onerror = (err) => rj(err); }); console.debug("Client send:", { trace_id, ...rqdata }); socket.send( JSON.stringify({ trace_id, ...rqdata }), ); return await promise; } } class ApiMethods extends ProtoApiMethods { async _protoMethod (rqdata) { throw new Error("_protoMethod allowed only into abstract class"); } constructor (api) { super(api); } async info (fields = null, fieldsExtSource = null) { return await super._protoMethod({ method: "info", fields: fields?.join(",") ?? "*", fieldsExtSource: fieldsExtSource?.join(",") ?? "*", }); } async authed () { return await super._protoMethod({ method: "authed", }); } async token (token) { return await super._protoMethod({ method: "token", token }); } async login (username, password, gtf = false) { return await super._protoMethod({ method: "login", username, password, gtf }); } } class ApiHTML { constructor (api) { this.api = api; } async renderMainMenu (user, bgUrl = null, favicon = null) { bgUrl = bgUrl ?? "assets/hello/1.png"; favicon = favicon ?? "favicon.png"; document.body.style.backgroundImage = `url(${ JSON.stringify(bgUrl) })`; document.body.style.backgroundSize = `${screen.width}px ${screen.height}px`; $.find('link[rel="icon"]')[0].href = favicon; document.getElementById("server.area").innerHTML = ''; $(document.getElementById("server.area")).append(ServerAuth.mainMenuForm); } async renderAuth (authMode, bgUrl = null, favicon = null) { bgUrl = bgUrl ?? "assets/hello/1.png"; favicon = favicon ?? "favicon.png"; document.body.style.backgroundImage = `url(${ JSON.stringify(bgUrl) })`; document.body.style.backgroundSize = `${screen.width}px ${screen.height}px`; $.find('link[rel="icon"]')[0].href = favicon; document.getElementById("server.area").innerHTML = ''; $(document.getElementById("server.area")).append(ServerAuth.authForm); $.find("#server-code-form")[0].hidden = authMode !== "password"; [...$.find(".auth-act-item")].forEach(authEl => { const authElJQ = $(authEl); const isHidden = authEl.hidden; authEl.hidden = false; const buttonBlock = authElJQ.find(".btn-auth-block")[0]; const paramsBlock = authElJQ.find(".params-auth")[0]; buttonBlock.style.marginTop = `calc(100% - ${paramsBlock.offsetHeight}px)`; authEl.hidden = isHidden; }); $.find("#menu-log-in")[0].onclick = function () { $.find("#log-in")[0].hidden = false; $.find("#register")[0].hidden = true; } $.find("#menu-register")[0].onclick = function () { $.find("#log-in")[0].hidden = true; $.find("#register")[0].hidden = false; } $.find("#auth-btn")[0].onclick = () => { this.api.methods.login( $.find("#username")[0].value, $.find("#password")[0].value, true ) .then(user => { const { token } = user; localStorage.setItem(`my-token>${!isTLSmode ? "ws" : "wss"}://${address}:${port}`, token); this.renderMainMenu(user, bgUrl, favicon); }); } $.find("#reg-btn")[0].onclick = () => { } } } export class ApiSocket { constructor ({ isTLSmode, address, port }) { this.tlsMode = isTLSmode; this.address = address; this.port = port; this.socket = new WebSocket(`${!isTLSmode ? "ws" : "wss"}://${address}:${port}`); this.methods = new ApiMethods(this); this.user = null; this.html = new ApiHTML(this); } async run () { const socket = this.socket; const promise = new Promise((rs, rj) => { socket.onopen = () => this.methods.info().then(data => rs(data)); socket.onerror = (err) => rj(err); }); return await promise; } }