add new methods code in frontend

This commit is contained in:
fullgream 2025-08-17 17:55:55 +03:00
parent 9544bc70d6
commit dd9bc64f1e
6 changed files with 323 additions and 222 deletions

View File

@ -32,4 +32,4 @@ module.exports = function (req, res) {
<script src="/js/connect/main.js" type="module" defer></script> <script src="/js/connect/main.js" type="module" defer></script>
</body> </body>
</html>`); </html>`);
} };

View File

@ -5,16 +5,19 @@ const router = express.Router();
router.get("/", (req, res) => { router.get("/", (req, res) => {
res.send( res.send(
fs.readFileSync(path.join(__dirname, "pages/index.html")).toString("utf-8") fs.readFileSync(path.join(__dirname, "pages/index.html")).toString("utf-8"),
); );
}); });
router.get("/connect", (req, res) => { router.get("/connect", (req, res) => {
res.send( res.send(
fs.readFileSync(path.join(__dirname, "pages/connect.html")).toString("utf-8") fs.readFileSync(path.join(__dirname, "pages/connect.html"))
.toString("utf-8"),
); );
}); });
router.get("/*", (req, res) => res.status(404).send("<p><b>404:</b> Not finded.</p>")); router.get("/*", (req, res) =>
res.status(404).send("<p><b>404:</b> Not finded.</p>"),
);
module.exports = router; module.exports = router;

View File

@ -12,6 +12,10 @@ module.exports = (address, port) => {
app.use((req, res, next) => { app.use((req, res, next) => {
// logger.log("HTTP headers:", req.headers); // logger.log("HTTP headers:", req.headers);
if (global.server.isLocked) {
res.set("Content-Type", "plain/text");
return res.send("Server temporary on reload");
}
next(); next();
}); });
@ -47,8 +51,7 @@ module.exports = (address, port) => {
}); });
app.listen(port, address, (err) => { app.listen(port, address, (err) => {
if (err) if (err) throw err;
throw err;
logger.log(`HTTP page successful runned at port ${port}`); logger.log(`HTTP page successful runned at port ${port}`);
}); });
}; };

View File

@ -83,6 +83,12 @@ class ApiMethods extends ProtoApiMethods {
gtf gtf
}); });
} }
async characters () {
return await super._protoMethod({
method: "characters"
});
}
} }
class ApiHTML { class ApiHTML {
@ -102,6 +108,9 @@ class ApiHTML {
document.getElementById("server.area").innerHTML = ''; document.getElementById("server.area").innerHTML = '';
$(document.getElementById("server.area")).append(ServerAuth.mainMenuForm); $(document.getElementById("server.area")).append(ServerAuth.mainMenuForm);
// JS-Events
const charactersEvents = await this.api.methods.characters();
console.debug({ charactersEvents });
} }
async renderAuth (authMode, bgUrl = null, favicon = null) { async renderAuth (authMode, bgUrl = null, favicon = null) {

View File

@ -1,26 +1,29 @@
// cookie parser function // cookie parser function
function getCookies () { function getCookies() {
return Object.fromEntries(document.cookie.split(/\s{0,};\s{0,}/gmiu).map(i => i.split(/\s{0,}=\s{0,}/gmiu))); return Object.fromEntries(
document.cookie
.split(/\s{0,};\s{0,}/gimu)
.map((i) => i.split(/\s{0,}=\s{0,}/gimu)),
);
} }
// translate function // translate function
function translate (page) { function translate(page) {
[...document.getElementsByClassName("translate")].forEach(translateEl => { [...document.getElementsByClassName("translate")].forEach((translateEl) => {
// console.log(translateEl.id); // console.log(translateEl.id);
const result = tr(page, translateEl.id); const result = tr(page, translateEl.id);
// console.log(result); // console.log(result);
if (result) if (result) translateEl.innerHTML = result;
translateEl.innerHTML = result;
}); });
[...document.getElementsByClassName("linked-btn")].forEach(el => { [...document.getElementsByClassName("linked-btn")].forEach((el) => {
el.style.cursor = "pointer"; el.style.cursor = "pointer";
}); });
} }
// Get random integer number function // Get random integer number function
function randint(min, max) { function randint(min, max) {
return Math.ceil((Math.random() * (max - min)) + min); return Math.ceil(Math.random() * (max - min) + min);
} }
// Get traceId for requests to server // Get traceId for requests to server
@ -32,10 +35,12 @@ function getTraceId() {
} }
// load styles // load styles
document.head.innerHTML += '\\n <link href="/bootstrap/bootstrap.min.css" rel="stylesheet">'; document.head.innerHTML +=
'\\n <link href="/bootstrap/bootstrap.min.css" rel="stylesheet">';
document.head.innerHTML += '\\n <link href="/css/main.css" rel="stylesheet">'; document.head.innerHTML += '\\n <link href="/css/main.css" rel="stylesheet">';
document.head.innerHTML += '\\n <link href="/font-awesome/css/all.css" rel="stylesheet">'; document.head.innerHTML +=
document.head.innerHTML += '\\n <link rel="icon" href="/favicon.png">' '\\n <link href="/font-awesome/css/all.css" rel="stylesheet">';
document.head.innerHTML += '\\n <link rel="icon" href="/favicon.png">';
// load main page // load main page
document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-expand-lg navbar-dark bg-dark"><div class="container-fluid"> document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-expand-lg navbar-dark bg-dark"><div class="container-fluid">
@ -59,9 +64,12 @@ document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-expand-lg
</div>`; </div>`;
function checkContentWarning (successfulHandler) { function checkContentWarning(successfulHandler) {
const warnModal = new bootstrap.Modal(document.getElementById('warningModal'), {}); const warnModal = new bootstrap.Modal(
document.getElementById('accept-denial-btn').onclick = () => { document.getElementById("warningModal"),
{},
);
document.getElementById("accept-denial-btn").onclick = () => {
document.cookie = "cw=1"; document.cookie = "cw=1";
successfulHandler?.(); successfulHandler?.();
}; };
@ -78,7 +86,7 @@ function checkContentWarning (successfulHandler) {
fl.bindLoad("/connect", () => { fl.bindLoad("/connect", () => {
translate("/connect"); translate("/connect");
function initNewConnectionOpen () { function initNewConnectionOpen() {
if (initNewConnectionOpen.interval) if (initNewConnectionOpen.interval)
clearInterval(initNewConnectionOpen.interval); clearInterval(initNewConnectionOpen.interval);
document.getElementById("custom-conn-address").value = ""; document.getElementById("custom-conn-address").value = "";
@ -106,8 +114,14 @@ fl.bindLoad("/connect", () => {
isWSS.checked = false; isWSS.checked = false;
} }
if (address.value.match(/:[0-9]{1,5}$/)) { if (address.value.match(/:[0-9]{1,5}$/)) {
const portSelected = +(address.value.match(/:[0-9]{1,5}$/).at(0).slice(1,)); const portSelected = +address.value
address.value = address.value.slice(0, -1 * (":"+portSelected).length); .match(/:[0-9]{1,5}$/)
.at(0)
.slice(1);
address.value = address.value.slice(
0,
-1 * (":" + portSelected).length,
);
port.value = portSelected; port.value = portSelected;
document.getElementById("custom-conn-port").focus(); document.getElementById("custom-conn-port").focus();
} }
@ -115,16 +129,15 @@ fl.bindLoad("/connect", () => {
if (!port.value) { if (!port.value) {
port.value = 80; port.value = 80;
} }
if (+port.value < 0) if (+port.value < 0) port.value = 0;
port.value = 0; if (+port.value > 65535) port.value = 65535;
if (+port.value > 65535)
port.value = 65535;
connButton.disabled = !address.value; connButton.disabled = !address.value;
}, 50); }, 50);
connButton.onclick = () => { connButton.onclick = () => {
const serverlist = JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []; const serverlist =
JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? [];
serverlist.push({ serverlist.push({
address: document.getElementById("custom-conn-address").value, address: document.getElementById("custom-conn-address").value,
port: +document.getElementById("custom-conn-port").value, port: +document.getElementById("custom-conn-port").value,
@ -132,11 +145,12 @@ fl.bindLoad("/connect", () => {
}); });
localStorage.setItem("savedServers", JSON.stringify(serverlist)); localStorage.setItem("savedServers", JSON.stringify(serverlist));
connectServers(); connectServers();
} };
} }
function connectServers () { function connectServers() {
document.getElementById("loading-servers").innerHTML = `<center><p>${tr("/connect", "loading") ?? "Loading..."}</p></center>`; document.getElementById("loading-servers").innerHTML =
`<center><p>${tr("/connect", "loading") ?? "Loading..."}</p></center>`;
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();
xhr.open("GET", "/api/active-servers.json", true); xhr.open("GET", "/api/active-servers.json", true);
@ -146,26 +160,39 @@ fl.bindLoad("/connect", () => {
<h3>${tr("/connect", "connection-failed") ?? "Connection failed"}</h3><hr> <h3>${tr("/connect", "connection-failed") ?? "Connection failed"}</h3><hr>
<button type="button" class="btn btn-primary translate" id="retry-connecting">${tr("/connect", "retry-connecting") ?? "Retry"}</button> <button type="button" class="btn btn-primary translate" id="retry-connecting">${tr("/connect", "retry-connecting") ?? "Retry"}</button>
</center>`; </center>`;
document.getElementById("retry-connecting").onclick = () => connectServers(); document.getElementById("retry-connecting").onclick = () =>
} connectServers();
};
xhr.onload = async () => { xhr.onload = async () => {
if (xhr.status === 200) { if (xhr.status === 200) {
const localServers = (JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []).map(x => { x.fromLocal = true; return x }); 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 servers = localServers.concat(
JSON.parse(xhr.response).result.map((x) => {
x.fromLocal = false;
return x;
}),
);
const serversByItemID = new Object(); const serversByItemID = new Object();
const serversByAddress = new Object(); const serversByAddress = new Object();
const items = []; const items = [];
const itemIDs = []; const itemIDs = [];
const mp = servers.map(async serverItem => { const mp = servers.map(async (serverItem) => {
const promise = new Promise((resolve, reject) => { const promise = new Promise((resolve, reject) => {
console.log("serverItem:", serverItem); console.log("serverItem:", serverItem);
const trace_id = getTraceId(); const trace_id = getTraceId();
const socket = new WebSocket(`${!serverItem.tls ? "ws" : "wss"}://${serverItem.address}:${serverItem.port}`); const socket = new WebSocket(
`${!serverItem.tls ? "ws" : "wss"}://${serverItem.address}:${serverItem.port}`,
);
let ping = new Date(); let ping = new Date();
socket.onopen = () => { socket.onopen = () => {
ping = (new Date()) - ping; ping = new Date() - ping;
socket.onmessage = (ev) => { socket.onmessage = (ev) => {
const data = JSON.parse(ev.data).result; const data = JSON.parse(ev.data).result;
console.debug("data:", data); console.debug("data:", data);
@ -176,22 +203,31 @@ fl.bindLoad("/connect", () => {
deleteID: `remove-con:${serverItem.address}:${serverItem.port}`, deleteID: `remove-con:${serverItem.address}:${serverItem.port}`,
address: `${serverItem.address}:${serverItem.port}`, address: `${serverItem.address}:${serverItem.port}`,
}); });
serversByItemID[`con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`] = { data, serverItem }; serversByItemID[
serversByAddress[`${serverItem.address}:${serverItem.port}`] = { data, serverItem }; `con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`
resolve(items.push(`<tr${!data.tls ? ' style="background-color: #7F6003"' : ""}> ] = { data, serverItem };
serversByAddress[`${serverItem.address}:${serverItem.port}`] = {
data,
serverItem,
};
resolve(
items.push(`<tr${!data.tls ? ' style="background-color: #7F6003"' : ""}>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${data.name}</td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${data.name}</td>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${serverItem.address}:${serverItem.port}</td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${serverItem.address}:${serverItem.port}</td>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${!data.tls ? '<font color="red"><i class="fas fa-exclamation-triangle"></i></font>' : '<font color="green"><i class="fas fa-lock"></i></font>'}</td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${!data.tls ? '<font color="red"><i class="fas fa-exclamation-triangle"></i></font>' : '<font color="green"><i class="fas fa-lock"></i></font>'}</td>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${ping}</td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}>${ping}</td>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}><button class="btn btn-secondary" id="con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}">${tr("/connect", "connect-to-server-btn") ?? "Connect"}</button></td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}><button class="btn btn-secondary" id="con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}">${tr("/connect", "connect-to-server-btn") ?? "Connect"}</button></td>
<td${!data.tls ? ' style="background-color: #7F6003"' : ""}><button class="btn btn-outline-danger" id="remove-con:${serverItem.address}:${serverItem.port}"${!serverItem.fromLocal ? ' disabled' : ''}><i class="fas fa-trash"></i></button></td> <td${!data.tls ? ' style="background-color: #7F6003"' : ""}><button class="btn btn-outline-danger" id="remove-con:${serverItem.address}:${serverItem.port}"${!serverItem.fromLocal ? " disabled" : ""}><i class="fas fa-trash"></i></button></td>
</tr>`)); </tr>`),
);
}; };
socket.send(JSON.stringify({ socket.send(
JSON.stringify({
method: "info", method: "info",
fields: "name,tag", fields: "name,tag",
trace_id trace_id,
})); }),
);
}; };
socket.onerror = (err) => { socket.onerror = (err) => {
console.error(err); console.error(err);
@ -199,23 +235,30 @@ fl.bindLoad("/connect", () => {
deleteID: `remove-con:${serverItem.address}:${serverItem.port}`, deleteID: `remove-con:${serverItem.address}:${serverItem.port}`,
address: `${serverItem.address}:${serverItem.port}`, address: `${serverItem.address}:${serverItem.port}`,
}); });
serversByAddress[`${serverItem.address}:${serverItem.port}`] = { serverItem }; serversByAddress[`${serverItem.address}:${serverItem.port}`] = {
resolve(items.push(`<tr> serverItem,
};
resolve(
items.push(`<tr>
<td style="background-color: #7F0000"><font color="red">${tr("/connect", "offline-server") ?? "Offline"}</font></td> <td style="background-color: #7F0000"><font color="red">${tr("/connect", "offline-server") ?? "Offline"}</font></td>
<td style="background-color: #7F0000">${serverItem.address}:${serverItem.port}</td> <td style="background-color: #7F0000">${serverItem.address}:${serverItem.port}</td>
<td style="background-color: #7F0000"><font color="red"><i class="fas fa-exclamation-triangle"></i></font></td> <td style="background-color: #7F0000"><font color="red"><i class="fas fa-exclamation-triangle"></i></font></td>
<td style="background-color: #7F0000"><font color="red">${tr("/connect", "offline-server") ?? "Offline"}</font></td> <td style="background-color: #7F0000"><font color="red">${tr("/connect", "offline-server") ?? "Offline"}</font></td>
<td style="background-color: #7F0000"><button class="btn btn-danger" disabled>${tr("/connect", "offline-server") ?? "Offline"}</button></td> <td style="background-color: #7F0000"><button class="btn btn-danger" disabled>${tr("/connect", "offline-server") ?? "Offline"}</button></td>
<td style="background-color: #7F0000"><button class="btn btn-outline-danger" id="remove-con:${serverItem.address}:${serverItem.port}"${!serverItem.fromLocal ? ' disabled' : ''}><i class="fas fa-trash"></i></button></td> <td style="background-color: #7F0000"><button class="btn btn-outline-danger" id="remove-con:${serverItem.address}:${serverItem.port}"${!serverItem.fromLocal ? " disabled" : ""}><i class="fas fa-trash"></i></button></td>
</tr>`)); </tr>`),
);
}; };
}); });
return await promise; return await promise;
}); });
await Promise.all(mp); await Promise.all(mp);
items.push(`<tr><td colspan="6"><center><button class="btn btn-primary" id="conn-to-custom">${tr("/connect", "add-custon-server") ?? "Connect to custom server"}</button></center></td></tr>`); items.push(
document.getElementById("loading-servers").innerHTML = `<table class="table table-dark"> `<tr><td colspan="6"><center><button class="btn btn-primary" id="conn-to-custom">${tr("/connect", "add-custon-server") ?? "Connect to custom server"}</button></center></td></tr>`,
);
document.getElementById("loading-servers").innerHTML =
`<table class="table table-dark">
<thead> <thead>
<th scope="col">${tr("/connect", "server-name-tbl") ?? "Name"}</th> <th scope="col">${tr("/connect", "server-name-tbl") ?? "Name"}</th>
<th scope="col">${tr("/connect", "server-address") ?? "Address"}</th> <th scope="col">${tr("/connect", "server-address") ?? "Address"}</th>
@ -229,22 +272,28 @@ fl.bindLoad("/connect", () => {
</tbody> </tbody>
</table>`; </table>`;
itemIDs.forEach(btn => { itemIDs.forEach((btn) => {
//console.log("btn:", btn); //console.log("btn:", btn);
if (btn.itemID) if (btn.itemID)
document.getElementById(btn.itemID).onclick = () => { document.getElementById(btn.itemID).onclick = () => {
checkContentWarning(() => { checkContentWarning(() => {
const serverInfo = serversByItemID[btn.itemID].serverItem; const serverInfo = serversByItemID[btn.itemID].serverItem;
window.open(`/connect-area?server=${serverInfo.address}:${serverInfo.port}&encrypted=${serverInfo.tls ? "true" : "false"}`); window.open(
`/connect-area?server=${serverInfo.address}:${serverInfo.port}&encrypted=${serverInfo.tls ? "true" : "false"}`,
);
}); });
}; };
document.getElementById(btn.deleteID).onclick = () => { document.getElementById(btn.deleteID).onclick = () => {
const serverInfo = serversByAddress[btn.address].serverItem; const serverInfo = serversByAddress[btn.address].serverItem;
console.log("serverInfo:", serverInfo); console.log("serverInfo:", serverInfo);
const savedServers = (JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []) const savedServers = (
.filter(server => { JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []
return !(server.address === serverInfo.address && server.port === serverInfo.port) ).filter((server) => {
return !(
server.address === serverInfo.address &&
server.port === serverInfo.port
);
}); });
localStorage.setItem("savedServers", JSON.stringify(savedServers)); localStorage.setItem("savedServers", JSON.stringify(savedServers));
connectServers(); connectServers();
@ -252,10 +301,13 @@ fl.bindLoad("/connect", () => {
}); });
document.getElementById("conn-to-custom").onclick = function () { document.getElementById("conn-to-custom").onclick = function () {
const connectModal = new bootstrap.Modal(document.getElementById('connectModal'), {}); const connectModal = new bootstrap.Modal(
document.getElementById("connectModal"),
{},
);
initNewConnectionOpen(); initNewConnectionOpen();
connectModal.show(); connectModal.show();
} };
} }
}; };
@ -264,7 +316,10 @@ fl.bindLoad("/connect", () => {
const cookies = getCookies(); const cookies = getCookies();
console.log(cookies); console.log(cookies);
const cookiesModal = new bootstrap.Modal(document.getElementById('cookiesModal'), {}); const cookiesModal = new bootstrap.Modal(
document.getElementById("cookiesModal"),
{},
);
if (!cookies.accept_cookies) { if (!cookies.accept_cookies) {
cookiesModal.show(); cookiesModal.show();
@ -286,34 +341,41 @@ fl.bindLoad("", () => {
translate("/"); translate("/");
// carousel // carousel
function onMouse (condition) { function onMouse(condition) {
return; return;
[...document.getElementsByClassName("card-img")].forEach(img => { [...document.getElementsByClassName("card-img")].forEach((img) => {
img.style.filter = `blur(${!condition ? 5 : 0}px)`; img.style.filter = `blur(${!condition ? 5 : 0}px)`;
}); });
} }
onMouse(false); onMouse(false);
[...document.getElementsByClassName("carousel-item")].forEach(item => { [...document.getElementsByClassName("carousel-item")].forEach((item) => {
item.onmouseout = () => onMouse(false); item.onmouseout = () => onMouse(false);
item.onmouseover = () => onMouse(true); item.onmouseover = () => onMouse(true);
}); });
[...document.getElementsByClassName("btn-card")].forEach(item => { [...document.getElementsByClassName("btn-card")].forEach((item) => {
item.onmouseout = () => onMouse(true); item.onmouseout = () => onMouse(true);
item.onmouseover = () => onMouse(false); item.onmouseover = () => onMouse(false);
}); });
const interval = setInterval(() => { const interval = setInterval(() => {
const navbarHeight = +(document.getElementById("navbar-main")?.offsetHeight); const navbarHeight = +document.getElementById("navbar-main")?.offsetHeight;
/*if (document.getElementById('main_img1')?.src) { /*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_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_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"; 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]; const selectedCSS = Object.entries(document.styleSheets).filter(
Object.entries(selectedCSS.rules).filter(([key, rule]) => rule.selectorText == '.carousel > .carousel-inner > .carousel-item > img')[0][1].style.height = `calc(100vh - ${navbarHeight}px)`; ([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'); // console.log('ok');
}, 1); }, 1);

View File

@ -15,52 +15,64 @@ const translationTree = {
"/": { "/": {
"en-US": { "en-US": {
"intro-1": "Welcome to Adventure AI Labs!", "intro-1": "Welcome to Adventure AI Labs!",
"description-1": "Embark on an unforgettable adventure with your favorite characters and friends! Visit familiar and unfamiliar locations..", "description-1":
"Embark on an unforgettable adventure with your favorite characters and friends! Visit familiar and unfamiliar locations..",
"button-1": '<i class="fas fa-users"></i> Start the adventure', "button-1": '<i class="fas fa-users"></i> Start the adventure',
"intro-2": "Become a gamemaster", "intro-2": "Become a gamemaster",
"description-2": "Or you can become the gamemaster of the party and lead the plot of the characters and players like a creator god who tells an amazing story.", "description-2":
"Or you can become the gamemaster of the party and lead the plot of the characters and players like a creator god who tells an amazing story.",
"button-2": '<i class="fas fa-book"></i> Documentation', "button-2": '<i class="fas fa-book"></i> Documentation',
"intro-3": "Needed a more gold..", "intro-3": "Needed a more gold..",
"description-3": "The project exists purely on a voluntary basis and the enthusiasm of the author, so if you want to help financially, then it will be very cool (:", "description-3":
"The project exists purely on a voluntary basis and the enthusiasm of the author, so if you want to help financially, then it will be very cool (:",
"button-3": '<i class="fab fa-bitcoin"></i> Donate', "button-3": '<i class="fab fa-bitcoin"></i> Donate',
}, },
"ru-RU": { "ru-RU": {
"intro-1": "Добро пожаловать в Adventure AI Labs!", "intro-1": "Добро пожаловать в Adventure AI Labs!",
"description-1": "Отправьтесь в незабываемое приключение вместе со своими любимыми персонажами и друзьями! Посетите знакомые и незнакомые вам локации..", "description-1":
"Отправьтесь в незабываемое приключение вместе со своими любимыми персонажами и друзьями! Посетите знакомые и незнакомые вам локации..",
"button-1": '<i class="fas fa-users"></i> Начать приключение', "button-1": '<i class="fas fa-users"></i> Начать приключение',
"intro-2": "Стань мастером партии", "intro-2": "Стань мастером партии",
"description-2": "Либо же ты можешь стать мастером партии и вести сюжет персонажей и игроков словно бог-творец, который рассказывает удивительную историю.", "description-2":
"Либо же ты можешь стать мастером партии и вести сюжет персонажей и игроков словно бог-творец, который рассказывает удивительную историю.",
"button-2": '<i class="fas fa-book"></i> Документация', "button-2": '<i class="fas fa-book"></i> Документация',
"intro-3": "Нужно больше золота..", "intro-3": "Нужно больше золота..",
"description-3": "Проект существует сугубо на добровольном начале и энтузиазме автора, поэтому если вы захотите помочь финансово, то это будет очень круто (:", "description-3":
"Проект существует сугубо на добровольном начале и энтузиазме автора, поэтому если вы захотите помочь финансово, то это будет очень круто (:",
"button-3": '<i class="fab fa-bitcoin"></i> Задонатить', "button-3": '<i class="fab fa-bitcoin"></i> Задонатить',
} },
}, },
"/connect": { "/connect": {
"en-US": { "en-US": {
title: "Server list", title: "Server list",
"enable-cookie-cnt": "Enable Cookie!", "enable-cookie-cnt": "Enable Cookie!",
"enable-cookie-text-cnt": "To work with servers, accept the cookie agreement", "enable-cookie-text-cnt":
"To work with servers, accept the cookie agreement",
"accept-cookie-show-btn": "Show", "accept-cookie-show-btn": "Show",
exampleModalLabel: "<i class=\"fas fa-cookie\"></i> Accept cookies", exampleModalLabel: '<i class="fas fa-cookie"></i> Accept cookies',
cookiesText: "We are obliged to warn you that the AI Adventure Labs protocol client uses cookies for: authorization, storage of session keys and user consent to the use of cookies", cookiesText:
"We are obliged to warn you that the AI Adventure Labs protocol client uses cookies for: authorization, storage of session keys and user consent to the use of cookies",
"accept-cookie-btn": "Accept", "accept-cookie-btn": "Accept",
loading: "Loading of servers...", loading: "Loading of servers...",
titleDenial: '<i class="fas fa-exclamation-triangle"></i> Denial of responsibility', titleDenial:
denialText: 'The server data does not belong to a centrally moderated foundation, community or individual, as well as to the developer of the software, program interface (protocol client), or protocol developer. Any content posted on servers is posted by the server administrator and can be absolutely anything. <b>You assume all risks for the content and connect to the server at your own peril and risk!</b>', '<i class="fas fa-exclamation-triangle"></i> Denial of responsibility',
denialText:
"The server data does not belong to a centrally moderated foundation, community or individual, as well as to the developer of the software, program interface (protocol client), or protocol developer. Any content posted on servers is posted by the server administrator and can be absolutely anything. <b>You assume all risks for the content and connect to the server at your own peril and risk!</b>",
"accept-denial-btn": "Accept", "accept-denial-btn": "Accept",
titleCustomServerConnect: '<i class="fas fa-wifi"></i> Connect to remote server', titleCustomServerConnect:
titleCustomConnect: 'Connection Data', '<i class="fas fa-wifi"></i> Connect to remote server',
addressCustomConnect: 'Enter address of server (without ws(s):// and port)', titleCustomConnect: "Connection Data",
portCustomConnect: 'Enter port of server', addressCustomConnect:
tlsCustomConnect: 'Check this if server use TLS (wss:// connection):', "Enter address of server (without ws(s):// and port)",
portCustomConnect: "Enter port of server",
tlsCustomConnect: "Check this if server use TLS (wss:// connection):",
"custom-connect-btn": "Connect", "custom-connect-btn": "Connect",
"server-name-tbl": "Name", "server-name-tbl": "Name",
@ -77,23 +89,28 @@ const translationTree = {
"ru-RU": { "ru-RU": {
title: "Список серверов", title: "Список серверов",
"enable-cookie-cnt": "Примите соглашение о Cookie!", "enable-cookie-cnt": "Примите соглашение о Cookie!",
"enable-cookie-text-cnt": "Для работы с серверами, примите соглашение об использовании файлов Cookie", "enable-cookie-text-cnt":
"Для работы с серверами, примите соглашение об использовании файлов Cookie",
"accept-cookie-show-btn": "Посмотреть", "accept-cookie-show-btn": "Посмотреть",
exampleModalLabel: "<i class=\"fas fa-cookie\"></i> Вопрос с печеньками", exampleModalLabel: '<i class="fas fa-cookie"></i> Вопрос с печеньками',
cookiesText: "Мы обязаны вас предупредить, что клиент протокола AI Adventure Labs использует файлы куки для: авторизации, хранения ключей сессии и согласия пользователя на использование куки", cookiesText:
"Мы обязаны вас предупредить, что клиент протокола AI Adventure Labs использует файлы куки для: авторизации, хранения ключей сессии и согласия пользователя на использование куки",
"accept-cookie-btn": "Принять", "accept-cookie-btn": "Принять",
loading: "Загрузка серверов...", loading: "Загрузка серверов...",
titleDenial: '<i class="fas fa-exclamation-triangle"></i> Отказ от отвественности', titleDenial:
denialText: 'Данные сервера не принадлежат централизованно-модерируемому фонду, сообществу или частному лицу, а также разработчику программного обеспечения, програмного интерфейса (клиента протокола), разработчику протокола. Любой размещённый на серверах контент размещается администратором сервера и может быть абсолютно любым. <b>Все риски за контент вы берёте полностью на себя и подключаетесь к серверу на свой страх и риск!</b>', '<i class="fas fa-exclamation-triangle"></i> Отказ от отвественности',
denialText:
"Данные сервера не принадлежат централизованно-модерируемому фонду, сообществу или частному лицу, а также разработчику программного обеспечения, програмного интерфейса (клиента протокола), разработчику протокола. Любой размещённый на серверах контент размещается администратором сервера и может быть абсолютно любым. <b>Все риски за контент вы берёте полностью на себя и подключаетесь к серверу на свой страх и риск!</b>",
"accept-denial-btn": "Принять", "accept-denial-btn": "Принять",
titleCustomServerConnect: '<i class="fas fa-wifi"></i> Прямое подключение к серверу', titleCustomServerConnect:
titleCustomConnect: 'Данные подключения', '<i class="fas fa-wifi"></i> Прямое подключение к серверу',
addressCustomConnect: 'Адрес сервера (без порта и ws(s)://)', titleCustomConnect: "Данные подключения",
portCustomConnect: 'Порт сервера', addressCustomConnect: "Адрес сервера (без порта и ws(s)://)",
tlsCustomConnect: 'Использовать защищённое соединение (TLS) (wss://):', portCustomConnect: "Порт сервера",
tlsCustomConnect: "Использовать защищённое соединение (TLS) (wss://):",
"custom-connect-btn": "Подключиться", "custom-connect-btn": "Подключиться",
"server-name-tbl": "Имя сервера", "server-name-tbl": "Имя сервера",
@ -106,33 +123,40 @@ const translationTree = {
"connect-to-server-btn": "Подключиться", "connect-to-server-btn": "Подключиться",
"connection-failed": "Соединение оборвалось", "connection-failed": "Соединение оборвалось",
"retry-connecting": "Повторить попытку", "retry-connecting": "Повторить попытку",
} },
}, },
"/connect-area": { "/connect-area": {
"en-US": {}, "en-US": {},
"ru-RU": {} "ru-RU": {},
} },
} };
Object.entries(translationTree).forEach(([page, langs]) => { Object.entries(translationTree).forEach(([page, langs]) => {
Object.entries(langs).forEach(([lang]) => { Object.entries(langs).forEach(([lang]) => {
translationTree[page][lang] = {...translationTree[page][lang], ...metaTranslate[lang]}; translationTree[page][lang] = {
...translationTree[page][lang],
...metaTranslate[lang],
};
}); });
}); });
console.log(translationTree); console.log(translationTree);
const simpleLangTags = { const simpleLangTags = {
"ru": "ru-RU", ru: "ru-RU",
"en": "en-US", en: "en-US",
}; };
function tr (page, id) { function tr(page, id) {
let lang = navigator.language || navigator.userLanguage; let lang = navigator.language || navigator.userLanguage;
lang = lang.split("-").length === 1 ? (simpleLangTags[lang] ?? "en-US") : lang; lang =
lang.split("-").length === 1 ? (simpleLangTags[lang] ?? "en-US") : lang;
// Britains sucks, Sir Keir Starmer (Sir Dicksucker) is faggot, he is sucking a muslim's dicks. // Britains sucks, Sir Keir Starmer (Sir Dicksucker) is faggot, he is sucking a muslim's dicks.
if (lang === "en-UK") if (lang === "en-UK") lang = "en-US";
lang = "en-US";
// console.log("lang is", lang); // console.log("lang is", lang);
return (translationTree[page]?.[lang]?.[id] ?? translationTree[page]?.["en-US"][id]) ?? null return (
translationTree[page]?.[lang]?.[id] ??
translationTree[page]?.["en-US"][id] ??
null
);
} }