- Клиентская часть Vue 3 + Vite - Серверная часть Node.js + WebSocket - Система авторизации и смен - Управление игровыми портами - Поддержка тем (светлая/темная) - Адаптивный дизайн 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
374 lines
16 KiB
JavaScript
374 lines
16 KiB
JavaScript
"use strict";
|
||
|
||
let mob; if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) mob=true; else mob=false;
|
||
Object.defineProperties(window,{"mobyle":{ get:()=>{return mob} }})
|
||
|
||
// Определение поддержки тачскрина
|
||
// let touch = ('ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0);
|
||
// Object.defineProperties(window, { "isTouch": { get: () => { return touch; } } });
|
||
|
||
// // Функция для проверки, является ли устройство Android
|
||
// function isAndroid() {
|
||
// return /Android/i.test(navigator.userAgent);
|
||
// }
|
||
|
||
// Функция показа виртуальной клавиатуры
|
||
// const showKeyboard = () => {
|
||
// if (isTouch) { // Только если устройство с тачскрином, но не Android
|
||
// try {
|
||
// // Запускаем Onboard (только на устройствах с Linux, например, Orange Pi)
|
||
// const iframe = document.createElement('iframe');
|
||
// iframe.style.display = 'none';
|
||
// document.body.appendChild(iframe);
|
||
|
||
// // Выполняем команду в iframe (можно заменить на системный вызов для запуска Onboard)
|
||
// const iframeDocument = iframe.contentWindow.document;
|
||
// iframeDocument.open();
|
||
// iframeDocument.write('<script>window.parent.postMessage("keyboard-command", "*");</script>');
|
||
// iframeDocument.close();
|
||
|
||
// // Обрабатываем сообщение от iframe
|
||
// window.addEventListener('message', (event) => {
|
||
// if (event.data === 'keyboard-command') {
|
||
// // Используем exec() или другой метод для запуска клавиатуры Onboard
|
||
// if (window.showVirtualKeyboard) {
|
||
// window.showVirtualKeyboard();
|
||
// } else if (navigator?.virtualKeyboard?.show) {
|
||
// navigator.virtualKeyboard.show();
|
||
// } else {
|
||
// // Для Linux (например, Orange Pi), используем exec для запуска Onboard
|
||
// if (typeof window !== "undefined" && window.process && window.process.versions) {
|
||
// const { exec } = require('child_process'); // Node.js API
|
||
// exec('onboard &', (err, stdout, stderr) => {
|
||
// if (err) {
|
||
// console.error('Ошибка при запуске Onboard:', err);
|
||
// return;
|
||
// }
|
||
// console.log('Onboard успешно запущен');
|
||
// });
|
||
// }
|
||
// }
|
||
// }
|
||
// }, { once: true });
|
||
// } catch (e) {
|
||
// console.error('Failed to show keyboard:', e);
|
||
// }
|
||
// }
|
||
// };
|
||
|
||
// // Функция скрытия виртуальной клавиатуры
|
||
// const hideKeyboard = () => {
|
||
// if (isTouch) {
|
||
// try {
|
||
// // Закрыть Onboard (для этого можно использовать команду pkill или другой метод)
|
||
// const iframe = document.createElement('iframe');
|
||
// iframe.style.display = 'none';
|
||
// document.body.appendChild(iframe);
|
||
|
||
// const iframeDocument = iframe.contentWindow.document;
|
||
// iframeDocument.open();
|
||
// iframeDocument.write('<script>window.parent.postMessage("keyboard-hide", "*");</script>');
|
||
// iframeDocument.close();
|
||
|
||
// window.addEventListener('message', (event) => {
|
||
// if (event.data === 'keyboard-hide') {
|
||
// // Используем exec() или другой метод для скрытия клавиатуры
|
||
// if (typeof window !== "undefined" && window.process && window.process.versions) {
|
||
// const { exec } = require('child_process'); // Node.js API
|
||
// exec('pkill onboard', (err, stdout, stderr) => {
|
||
// if (err) {
|
||
// console.error('Ошибка при закрытии Onboard:', err);
|
||
// return;
|
||
// }
|
||
// console.log('Onboard успешно закрыт');
|
||
// });
|
||
// }
|
||
// }
|
||
// }, { once: true });
|
||
// } catch (e) {
|
||
// console.error('Failed to hide keyboard:', e);
|
||
// }
|
||
// }
|
||
// };
|
||
|
||
// // Функция инициализации обработчиков для клавиатуры
|
||
// const initKeyboardHandlers = () => {
|
||
// if (!isTouch) return;
|
||
|
||
// // Глобальный обработчик фокуса на полях ввода
|
||
// document.addEventListener('focusin', (event) => {
|
||
// if (event.target.tagName === 'INPUT' ||
|
||
// event.target.tagName === 'TEXTAREA' ||
|
||
// event.target.isContentEditable) {
|
||
// showKeyboard();
|
||
// }
|
||
// });
|
||
|
||
// // Глобальный обработчик потери фокуса
|
||
// document.addEventListener('focusout', (event) => {
|
||
// if (event.target.tagName === 'INPUT' ||
|
||
// event.target.tagName === 'TEXTAREA' ||
|
||
// event.target.isContentEditable) {
|
||
// hideKeyboard();
|
||
// }
|
||
// });
|
||
|
||
// // Экспортируем функции в глобальный объект
|
||
// window.showKeyboard = showKeyboard;
|
||
// window.hideKeyboard = hideKeyboard;
|
||
// };
|
||
|
||
|
||
const load = async ()=>{
|
||
// защита св-ва Object.defineProperties(window,{"dop":{ get:()=>{return m} }})
|
||
|
||
let element = document.createElement("link");
|
||
element.setAttribute("rel", "stylesheet");
|
||
element.setAttribute("type", "text/css");
|
||
if (mobyle) element.setAttribute("href", "/css/style-mobyle.css"); else element.setAttribute("href", "/css/style-pc.css");
|
||
document.getElementsByTagName("head")[0].appendChild(element);
|
||
|
||
|
||
|
||
|
||
//import("/template/elements/over/over.js").then((m)=>window.elements=m);
|
||
//import("/js/dop.js").then((m)=>window.dop=m);
|
||
|
||
window.avt=JSON.parse(sessionStorage.getItem('avt'));
|
||
import("./date.js").then((m)=>window.MY_date=m);
|
||
|
||
import("/start.js").then((m)=>m.print(document.body));
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
window.addEventListener("error", function(e) { // перехват ошибок window.error=f...
|
||
e.target.onerror=null; }, true);
|
||
// Блокировать вперед назад браузера
|
||
history.pushState(null, null, document.title);
|
||
window.addEventListener('popstate', function () {history.pushState(null, null, document.title); });
|
||
|
||
|
||
// if ('serviceWorker' in navigator) { //Офлайн сайт
|
||
// window.addEventListener('load', function() { navigator.serviceWorker.register('/ofline.js').then(function(registration) {
|
||
// console.log('ServiceWorker зарегестрирован: ', registration.scope);
|
||
// }, function(err) { console.log('ServiceWorker ОШИБКА!!!: ', err); }); });
|
||
// }
|
||
|
||
|
||
|
||
|
||
|
||
}
|
||
|
||
const bid={}; // ссылка на элементы (bid.{name}=DIVe; потом в любом месте ссылаться bid.{name} !!! )
|
||
const hideshow=(el_h,el_s) => { el_h.classList.add("hide"); el_s.classList.remove("hide");}
|
||
const hideshowFlex=(el_h,el_s) => { el_h.classList.remove("flex");el_h.classList.add("hidden"); el_s.classList.remove("hidden");el_s.classList.add("flex");}
|
||
const clear= (el) => {
|
||
// if(el.unmount) {el.unmount();}
|
||
while (el.firstChild) {el.removeChild(el.firstChild);}
|
||
}
|
||
const sleep=(ms)=> { return new Promise(resolve => setTimeout(resolve, ms)); }
|
||
|
||
let CurrentPage;
|
||
const showPage= async(_page, showD=true, cfg=null) => {
|
||
if (_page==CurrentPage || !_page) return;
|
||
if ( CurrentPage.closed) CurrentPage.closed(cfg);
|
||
|
||
// динамическая подгрузка
|
||
if (_page.dataUrl) { await import(_page.dataUrl).then((m)=>m.print(_page)); delete _page.dataUrl; }
|
||
|
||
if (CurrentPage) CurrentPage.classList.add("hide");
|
||
_page.classList.remove("hide"); CurrentPage=_page;
|
||
if (_page.show) _page.show(cfg);
|
||
if (showD) {
|
||
page.header.classList.remove("hide");
|
||
// Не показываем меню по умолчанию, оно будет вызываться через бургер
|
||
page.menu.classList.add("hide");
|
||
} else {
|
||
page.header.classList.add("hide");
|
||
page.menu.classList.add("hide");
|
||
}
|
||
}
|
||
|
||
|
||
function todatetime(datetime) {
|
||
const dt = new Date(datetime);
|
||
dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset());
|
||
return dt.toISOString().slice(0, 16);
|
||
}
|
||
|
||
const gid=(id,el=document) => el.querySelector("#"+id);
|
||
const oid=(zn,el=document) => typeof(zn)=='string' ? el.querySelector("#"+zn) : zn ;
|
||
const css=(el, style)=> {for (const P in style) el.style[P] = style[P];}
|
||
|
||
const _lt = (D, O, P) => { let E = document.createTextNode(""); D.append(E); linktxt(O,P,E); return E; }
|
||
const _t = (D, T) => { let E = document.createTextNode(T); D.append(E); return E; }
|
||
const _i = (D, T) => { let E = document.createComment(T); D.append(E); return E; }
|
||
const _c = async (DIVe, tag, att = [], js) => {
|
||
let DIV=DIVe._r || DIVe; if (DIV.finish) DIV.finish.start++;
|
||
let _e,_n=false;
|
||
if (tag=='svg' || DIVe.svg) {
|
||
if (tag=='svg' && DIVe.svg) _e=DIVe; else {_e = document.createElementNS("http://www.w3.org/2000/svg",tag); _n=true; _e.svg=true; }
|
||
} else {_e = document.createElement(tag); _n=true; }
|
||
|
||
if (typeof (att) === 'function') { att = await att(); }
|
||
for (let a of att) {
|
||
if (a[0].substring(0, 2) == 'on') {
|
||
if (typeof(a[1]) === 'string') _e.addEventListener(a[0].substring(2), (e) => { eval(a[1]) });
|
||
else _e.addEventListener(a[0].substring(2), a[1]);
|
||
} else _e.setAttribute(a[0], a[1]);
|
||
}
|
||
_e._r=DIV;
|
||
|
||
if (_n) {
|
||
let _tmp= document.createComment('-load-'); DIVe.append(_tmp);
|
||
if (js) { await js(_e); }
|
||
_tmp.replaceWith(_e); _tmp.remove();
|
||
} else {
|
||
if (js) { await js(_e); }
|
||
}
|
||
|
||
if (DIV.finish) dop.finish.go(DIV);
|
||
return _e;
|
||
}
|
||
const _p = (DIVe, tag, att = []) => {
|
||
|
||
let _e;
|
||
|
||
if (DIVe.svg) _e = document.createElementNS("http://www.w3.org/2000/svg",tag); else
|
||
_e= document.createElement(tag);
|
||
|
||
if (typeof (att) === 'function') { att = att(); }
|
||
for (let a of att) {
|
||
if (a[0].substring(0, 2) == 'on') {
|
||
if (typeof(a[1]) === 'string') _e.addEventListener(a[0].substring(2), (e) => { eval(a[1]) });
|
||
else _e.addEventListener(a[0].substring(2), a[1]);
|
||
} else _e.setAttribute(a[0], a[1]);
|
||
}
|
||
DIVe.append(_e);
|
||
return _e;
|
||
}
|
||
|
||
|
||
//const ServUrl = 'moygig-api.moygig.ru';
|
||
|
||
const getBD = (_method, _url, _body = null) => {
|
||
return new Promise((resolve, reject) => {
|
||
if (avt?.user?._id ) {
|
||
let _opt = '_id=' + avt.user._id + '&hash=' + avt.user.hash + '&sesid=' + sesid;
|
||
_url.includes('?') ? _url += '&' + _opt : _url += '?' + _opt;
|
||
}
|
||
const conn = new XMLHttpRequest();
|
||
conn.withCredentials = true; conn.responseType = 'json';
|
||
conn.onload = () => resolve(conn.response);
|
||
conn.onerror = () => reject(conn.response);
|
||
conn.ontimeout = () => reject(conn.response);
|
||
conn.open(_method, _url); //'https://' + location.hostname +
|
||
conn.send(JSON.stringify(_body));
|
||
});
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
const str_rnd = (count) => {
|
||
let str = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890';
|
||
let ret = "RND"+str[Math.round(Math.random() * (str.length - 1))];
|
||
for (let i = 1; i < count; i++) {
|
||
ret += str[Math.round(Math.random() * (str.length - 1))];;
|
||
}
|
||
return ret;
|
||
};
|
||
const sesid=str_rnd(10); // ID текущей вкладки
|
||
|
||
|
||
|
||
|
||
const codeMD5 = (function() {
|
||
|
||
var MD5 = function(d) {
|
||
d = unescape(encodeURIComponent(d));
|
||
let result = M(V(Y(X(d), 8 * d.length)));
|
||
return result.toLowerCase();
|
||
};
|
||
|
||
function M(d) {
|
||
for (var _, m = "0123456789ABCDEF", f = "", r = 0; r < d.length; r++) _ = d.charCodeAt(r), f += m.charAt(_ >>> 4 & 15) + m.charAt(15 & _);
|
||
return f
|
||
}
|
||
|
||
function X(d) {
|
||
for (var _ = Array(d.length >> 2), m = 0; m < _.length; m++) _[m] = 0;
|
||
for (m = 0; m < 8 * d.length; m += 8) _[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32;
|
||
return _
|
||
}
|
||
|
||
function V(d) {
|
||
for (var _ = "", m = 0; m < 32 * d.length; m += 8) _ += String.fromCharCode(d[m >> 5] >>> m % 32 & 255);
|
||
return _
|
||
}
|
||
|
||
function Y(d, _) {
|
||
d[_ >> 5] |= 128 << _ % 32, d[14 + (_ + 64 >>> 9 << 4)] = _;
|
||
for (var m = 1732584193, f = -271733879, r = -1732584194, i = 271733878, n = 0; n < d.length; n += 16) {
|
||
var h = m,
|
||
t = f,
|
||
g = r,
|
||
e = i;
|
||
f = md5_ii(f = md5_ii(f = md5_ii(f = md5_ii(f = md5_hh(f = md5_hh(f = md5_hh(f = md5_hh(f = md5_gg(f = md5_gg(f = md5_gg(f = md5_gg(f = md5_ff(f = md5_ff(f = md5_ff(f = md5_ff(f, r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 0], 7, -680876936), f, r, d[n + 1], 12, -389564586), m, f, d[n + 2], 17, 606105819), i, m, d[n + 3], 22, -1044525330), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 4], 7, -176418897), f, r, d[n + 5], 12, 1200080426), m, f, d[n + 6], 17, -1473231341), i, m, d[n + 7], 22, -45705983), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 8], 7, 1770035416), f, r, d[n + 9], 12, -1958414417), m, f, d[n + 10], 17, -42063), i, m, d[n + 11], 22, -1990404162), r = md5_ff(r, i = md5_ff(i, m = md5_ff(m, f, r, i, d[n + 12], 7, 1804603682), f, r, d[n + 13], 12, -40341101), m, f, d[n + 14], 17, -1502002290), i, m, d[n + 15], 22, 1236535329), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 1], 5, -165796510), f, r, d[n + 6], 9, -1069501632), m, f, d[n + 11], 14, 643717713), i, m, d[n + 0], 20, -373897302), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 5], 5, -701558691), f, r, d[n + 10], 9, 38016083), m, f, d[n + 15], 14, -660478335), i, m, d[n + 4], 20, -405537848), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 9], 5, 568446438), f, r, d[n + 14], 9, -1019803690), m, f, d[n + 3], 14, -187363961), i, m, d[n + 8], 20, 1163531501), r = md5_gg(r, i = md5_gg(i, m = md5_gg(m, f, r, i, d[n + 13], 5, -1444681467), f, r, d[n + 2], 9, -51403784), m, f, d[n + 7], 14, 1735328473), i, m, d[n + 12], 20, -1926607734), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 5], 4, -378558), f, r, d[n + 8], 11, -2022574463), m, f, d[n + 11], 16, 1839030562), i, m, d[n + 14], 23, -35309556), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 1], 4, -1530992060), f, r, d[n + 4], 11, 1272893353), m, f, d[n + 7], 16, -155497632), i, m, d[n + 10], 23, -1094730640), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 13], 4, 681279174), f, r, d[n + 0], 11, -358537222), m, f, d[n + 3], 16, -722521979), i, m, d[n + 6], 23, 76029189), r = md5_hh(r, i = md5_hh(i, m = md5_hh(m, f, r, i, d[n + 9], 4, -640364487), f, r, d[n + 12], 11, -421815835), m, f, d[n + 15], 16, 530742520), i, m, d[n + 2], 23, -995338651), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 0], 6, -198630844), f, r, d[n + 7], 10, 1126891415), m, f, d[n + 14], 15, -1416354905), i, m, d[n + 5], 21, -57434055), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 12], 6, 1700485571), f, r, d[n + 3], 10, -1894986606), m, f, d[n + 10], 15, -1051523), i, m, d[n + 1], 21, -2054922799), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 8], 6, 1873313359), f, r, d[n + 15], 10, -30611744), m, f, d[n + 6], 15, -1560198380), i, m, d[n + 13], 21, 1309151649), r = md5_ii(r, i = md5_ii(i, m = md5_ii(m, f, r, i, d[n + 4], 6, -145523070), f, r, d[n + 11], 10, -1120210379), m, f, d[n + 2], 15, 718787259), i, m, d[n + 9], 21, -343485551), m = safe_add(m, h), f = safe_add(f, t), r = safe_add(r, g), i = safe_add(i, e)
|
||
}
|
||
return Array(m, f, r, i)
|
||
}
|
||
|
||
function md5_cmn(d, _, m, f, r, i) {
|
||
return safe_add(bit_rol(safe_add(safe_add(_, d), safe_add(f, i)), r), m)
|
||
}
|
||
|
||
function md5_ff(d, _, m, f, r, i, n) {
|
||
return md5_cmn(_ & m | ~_ & f, d, _, r, i, n)
|
||
}
|
||
|
||
function md5_gg(d, _, m, f, r, i, n) {
|
||
return md5_cmn(_ & f | m & ~f, d, _, r, i, n)
|
||
}
|
||
|
||
function md5_hh(d, _, m, f, r, i, n) {
|
||
return md5_cmn(_ ^ m ^ f, d, _, r, i, n)
|
||
}
|
||
|
||
function md5_ii(d, _, m, f, r, i, n) {
|
||
return md5_cmn(m ^ (_ | ~f), d, _, r, i, n)
|
||
}
|
||
|
||
function safe_add(d, _) {
|
||
var m = (65535 & d) + (65535 & _);
|
||
return (d >> 16) + (_ >> 16) + (m >> 16) << 16 | 65535 & m
|
||
}
|
||
|
||
function bit_rol(d, _) {
|
||
return d << _ | d >>> 32 - _
|
||
}
|
||
|
||
/************************
|
||
* Public functions *
|
||
************************/
|
||
return {
|
||
get: MD5,
|
||
}
|
||
|
||
})();
|
||
|
||
// Добавляем инициализацию клавиатуры для сенсорных устройств
|
||
// initKeyboardHandlers();
|