Continue write code of connect area

This commit is contained in:
FullGreaM 2025-02-07 18:53:12 +03:00
parent 643ea3efa5
commit e7000c9abf
12 changed files with 12065 additions and 63 deletions

View File

@ -9,6 +9,5 @@ module.exports = {
name: global.config.server.info.name,
tag: global.config.server.info.tag,
authMode: authModes[global.config.server["auth-mode"] ?? 1],
secureMode: global.config.server.secureMode,
...(global.config.server.secureMode ? {cert: global.openSSH.cert.toString("utf8")} : {})
secureMode: global.config.server.secureMode ?? false,
};

View File

@ -69,12 +69,12 @@
<p><b class="translate" id="addressCustomConnect">Enter address of server (without ws(s):// and port)</b></p>
<p><input class="bg-dark text-white form-control" type="text" placeholder="ai.example.org" id="custom-conn-address"></p>
<p><b class="translate" id="portCustomConnect">Enter port of server</b></p>
<p><input class="bg-dark text-white form-control" type="number" value="80" min="1" max="25565" placeholder="80" id="custom-conn-port"></p>
<p><input class="bg-dark text-white form-control" type="number" value="80" min="0" max="65535" placeholder="80" id="custom-conn-port"></p>
<p><b class="translate" id="tlsCustomConnect">Check this if server use TLS (wss:// connection):</b>
<input class="bg-dark text-white form-check-input" type="checkbox" id="custom-conn-encryption"></p>
</div>
<div class="modal-footer"><center>
<button type="button" class="btn btn-primary translate" data-bs-dismiss="modal" id="accept-denial-btn">Accept</button>
<button type="button" class="btn btn-primary translate" data-bs-dismiss="modal" id="custom-connect-btn" disabled>Connect</button>
<!-- <button type="button" class="btn btn-primary">Сохранить изменения</button> -->
</center></div>
</div>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,112 @@
.carousel > .carousel-inner > .carousel-item > img {
width : 100vh;
height : calc(100vh - 56px);
/* height : 10vh; */
}
/*.main-window-alt {
width : 100vh;
height : calc(100vh - 56px);
}*/
.centered-el {
padding-top : 45vh;
}
.bg {
background-color : #212529;
}
.release-menu {
/* Margin */
margin-left : 35vh;
margin-right : 35vh;
margin-top : 5vh;
/* Padding */
padding-left : 5vh;
padding-right : 5vh;
padding-top : 5vh;
padding-bottom : 5vh;
/* Style */
border-radius : 2.0vh;
background-color : #212529;
}
.release-item {
/* Margin */
margin-left : 5vh;
margin-right : 45vh;
margin-top : 5vh;
/* Padding */
padding-left : 5vh;
padding-right : 5vh;
padding-top : 5vh;
padding-bottom : 5vh;
/* Style */
border-radius : 2.0vh;
background-color : #252525;
}
.sys-win-img {
margin-top: 24vh;
margin-bottom: 1vh;
width : 25vh;
height : 25vh;
}
.blog-post-card {
border-radius : 25px;
background-color: #212121;
min-width: 250px;
min-height : 250px;
margin-left : 25%;
margin-right : 25%;
}
.blog-post-image-carousel {
margin-left: 10%;
margin-right: 10%;
max-height: 512px;
overflow: hidden;
}
.blog-post-image-carousel img {
object-fit: cover;
}
.modal-img-view {
width: 1920px;
margin: auto;
}
.password-manger-form {
margin-left : 30%;
margin-right : 30%;
padding : 10px;
padding-left : 65px;
padding-right : 65px;
border-radius : 15px;
}
.navbar-connect-dark {
color: #ffffff;
--bs-bg-opacity: 1;
background-color: #09638A !important;
}
.text-navbar-connect-dark {
color: #fff !important;
background-color: #09638A !important;
}
/* $accordion-color:green; */
/* $accordion-padding-y:1.3rem; */
/* $accordion-padding-x:2.5rem; */
/* $accordion-border-color:black; */
/* $accordion-border-width:3.5px; */
/* $accordion-border-radius: 3rem; */
/* $accordion-button-color:white; */
/* $accordion-button-bg:green; */
/* $accordion-button-active-bg: white; */
/* $accordion-button-active-color:green; */
/* @import "./node_modules/bootstrap/scss/bootstrap" */

View File

@ -0,0 +1,46 @@
import { ServerAuth } from "/js/connect/auth.js";
class ApiMethods {
constructor (api) {
this.api = api;
}
async info () {
const socket = this.api.socket;
const promise = new Promise((rs, rj) => {
socket.onmessage = (ev) => {
const data = JSON.parse(ev.data).result;
rs(data);
};
socket.onerror = (err) => rj(err);
});
socket.send(
JSON.stringify({
method: "info",
}),
);
return await promise;
}
}
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);
}
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;
}
}

View File

@ -0,0 +1,19 @@
export class ServerAuth {
constructor (address, port, tlsEnabled) {
this.address = address;
this.port = port;
this.isTLSenabled = !!tlsEnabled;
}
getAuth () {
const serverdata = JSON.parse(localStorage.getItem(`server:${
!!this.isTLSenabled ? "wss" : "ws"
}:${address}:${port}`) ?? "null");
if (!serverdata) return null;
}
renderAuth (type) {
}
}

View File

@ -1,52 +1,32 @@
import { ApiSocket } from "/js/connect/api.js";
// load styles
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/connect/main.css" rel="stylesheet">';
document.head.innerHTML += '\\n <link href="/font-awesome/css/all.css" rel="stylesheet">';
document.head.innerHTML += '\\n <link rel="icon" href="/favicon.png">'
// load main page
document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-dark bg-dark navbar-expand-lg noselect" style="background-color: #e3f2fd;">
<a style="padding-left:10px" class="navbar-brand linked-btn" onclick="fl.go('/');">
Подключение...
document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-connect-dark navbar-dark navbar-expand-lg noselect" style="background-color: #e3f2fd;">
<a style="padding-left:10px" class="navbar-brand linked-btn" id="server-name" onclick="fl.go('/');">
Connection...
</a>
<div class="collapse navbar-collapse noselect" id="navbarNav"><ul class="navbar-nav"><ul class="navbar-nav">
<div class="vr"></div>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/');" id="nav-home-btn"><i class="fas fa-home"></i> Главная</a>
<a class="nav-link translate linked-btn noselect" aria-current="page" id="nav-home-btn"><i class="fas fa-home"></i> Home</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/blog');" id="nav-docs-btn"><i class="fab fa-microblog"></i> Мой блог</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/contacts');" id="nav-docs-btn"><i class="fas fa-address-book"></i> Контакты</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/projects');" id="nav-docs-btn"><i class="fas fa-folder-open"></i> Проекты</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/knowledge-base');" id="nav-docs-btn"><i class="fas fa-book"></i> База знаний</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.goToLocation('https://git.fullgream.tech/fullgream?tab=activity');" id="nav-docs-btn"><i class="fab fa-git-alt"></i> Мой git</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/price');" id="nav-docs-btn"><i class="fas fa-coins"></i> Услуги</a>
</li>
<li class="nav-item">
<a class="nav-link translate linked-btn noselect" aria-current="page" onclick="fl.go('/dnd');" id="nav-docs-btn"><i class="fas fa-dice-d20"></i> D&D</a>
<a class="nav-link translate linked-btn noselect" aria-current="page" id="nav-docs-btn"><i class="fas fa-dice-d20"></i> Games</a>
</li>
</ul></div>
<div class="vr" style="margin-right:5px"></div>
<div class="d-flex" style="margin-right:10px" id="navbar-user-menu">
<div id="fp-condition-div">
<button id="fp-condition" class="btn btn-outline-secondary" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><i class="fas fa-fingerprint"></i></button>
</div>
<div class="vr" style="margin-right:5px; margin-left: 5px"></div>
<button onclick="fl.go('/auth');" class="btn btn-outline-secondary" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><i class="fas fa-key"></i> Авторизация</button>
<button id="toggle-theme" class="btn btn-outline-light" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><i class="far fa-eye"></i> Light theme</button>
</div>
</nav>
<div id="fl.area">
<div id="server.area">
<div style='margin-top: 30vh'>
<center>
<h1>Connection to server...</h1>
@ -55,4 +35,29 @@ document.body.innerHTML = `<nav id="navbar-main" class="navbar navbar-dark bg-da
</div>
</div>`;
//document <i class="fas fa-sync-alt"></i>
//document <i class="fas fa-sync-alt"></i>
const curUrl = new URL(location.href);
const [address, port] = curUrl.searchParams.get("server").split(/:/);
const isTLSmode = curUrl.searchParams.get("encrypted") === "true";
const socket = new ApiSocket({
isTLSmode, address, port
});
socket.run()
.then(data => {
console.log("socket sends:", data);
document.getElementById("server-name").innerHTML = data.name;
document.title = data.name;
})
.catch(err => {
console.error(err);
document.title = "Connection error";
document.getElementById("server-name").innerHTML = "Error";
document.getElementById("server.area").innerHTML = `<div style='margin-top: 30vh'>
<center>
<h1>Connection errored</h1>
<p>Connection errored</p>
</center>
</div>`;
});

View File

@ -65,6 +65,62 @@ function checkContentWarning (successfulHandler) {
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;
}
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 = `<center><p>${tr("/connect", "loading") ?? "Loading..."}</p></center>`;
@ -81,33 +137,33 @@ fl.bindLoad("/connect", () => {
xhr.onload = async () => {
if (xhr.status === 200) {
const localServers = JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? [];
const localServers = (JSON.parse(localStorage.getItem("savedServers") ?? "null") ?? []).map(x => { x.fromLocal = true; return x });
const servers = localServers.concat(JSON.parse(xhr.response).result);
const servers = localServers.concat(JSON.parse(xhr.response).result.map(x => { x.fromLocal = false; return x }));
const serversByItemID = new Object();
const items = [];
const itemIDs = [];
const mp = servers.map(async serverItem => {
const promise = new Promise((resolve, reject) => {
console.log("serverItem:", serverItem);
const socket = new WebSocket(`${!serverItem.secureMode ? "ws" : "wss"}://${serverItem.address}:${serverItem.port}`);
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.secureMode = serverItem.secureMode;
data.tls = serverItem.tls;
itemIDs.push({
...data,
itemID: `con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`
});
serversByItemID[`con-btn-to:${data.tag}:${serverItem.address}:${serverItem.port}`] = { data, serverItem };
resolve(items.push(`<tr${!data.secureMode ? ' style="background-color: #7F6003"' : ""}>
<td${!data.secureMode ? ' style="background-color: #7F6003"' : ""}>${data.name}</td>
<td${!data.secureMode ? ' style="background-color: #7F6003"' : ""}>${serverItem.address}:${serverItem.port}</td>
<td${!data.secureMode ? ' style="background-color: #7F6003"' : ""}>${!data.secureMode ? '<font color="red"><i class="fas fa-exclamation-triangle"></i></font>' : '<font color="green"><i class="fas fa-lock"></i></font>'}</td>
<td${!data.secureMode ? ' style="background-color: #7F6003"' : ""}>${ping}</td>
<td${!data.secureMode ? ' 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>
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"' : ""}>${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"' : ""}>${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>
</tr>`));
};
socket.send(JSON.stringify({
@ -147,13 +203,14 @@ fl.bindLoad("/connect", () => {
document.getElementById(btn.itemID).onclick = () => {
checkContentWarning(() => {
const serverInfo = serversByItemID[btn.itemID].serverItem;
window.open(`/connect-area?server=${serverInfo.address}:${serverInfo.port}&encrypted=${serverInfo.secureMode ? "true" : "false"}`);
window.open(`/connect-area?server=${serverInfo.address}:${serverInfo.port}&encrypted=${serverInfo.tls ? "true" : "false"}`);
});
};
});
document.getElementById("conn-to-custom").onclick = function () {
const connectModal = new bootstrap.Modal(document.getElementById('connectModal'), {});
initNewConnectionOpen();
connectModal.show();
}
}

View File

@ -61,6 +61,7 @@ const translationTree = {
addressCustomConnect: '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",
"server-name-tbl": "Name",
"server-address": "Address",
@ -93,6 +94,7 @@ const translationTree = {
addressCustomConnect: 'Адрес сервера (без порта и ws(s)://)',
portCustomConnect: 'Порт сервера',
tlsCustomConnect: 'Использовать защищённое соединение (TLS) (wss://):',
"custom-connect-btn": "Подключиться",
"server-name-tbl": "Имя сервера",
"server-address": "Адрес",

View File

@ -3,11 +3,7 @@ module.exports = async function (req, res) {
result: [{
address: global.config.server.address === "0.0.0.0" ? req.headers.host.split(":").at(0) : global.config.server.address,
port: global.config.server.port,
secureMode: false
}, {
address: "offline.example.org",
port: 8891,
secureMode: false,
}]
tls: false
}]
});
}

View File

@ -20,7 +20,7 @@ module.exports = async (bytes) => {
const packet = bytes.toString("utf8");
const isHTTP = packet.match(/(GET|POST|PUT|DELETE|OPTIONS|HEAD|PATCH|TRACE|CONNECT)\s{1,}\/[a-zA-Z0-9_\-\.\/?=&%:]{0,}\s{1,}HTTP(S|)\/(1\.0|1\.1|2\.0)(\n|\r)/gmu)?.length > 0 ?? false;
console.log({ isHTTP });
//console.log({ isHTTP });
let isWebSocket = false;
if (isHTTP) {
const headers = simpleParseHeaders(packet);

View File

@ -40,10 +40,10 @@ class Server extends EventEmitter {
this.websocket = websocket("127.0.0.1", wsPort, this.api);
this.server = net.createServer((srvSocket) => {
srvSocket.on("error", (err) => {
logger.log("Caught server socket error: ");
logger.log(err.stack);
});
srvSocket.on("error", (err) => {
logger.log("Caught server socket error: ");
logger.log(err.stack);
});
});
function socketErrHanler (err) {
@ -144,13 +144,13 @@ class Server extends EventEmitter {
});
this.server.on('error', (err) => {
logger.log("Error of server");
logger.log(err.stack);
logger.log("Error of server");
logger.log(err.stack);
});
this.server.listen(this.port, this.address, (err) => {
if (err) throw err;
logger.log(`TCP server for ai-adventure labs connected on ${this.address}:${this.port}`);
if (err) throw err;
logger.log(`TCP server for ai-adventure labs connected on ${this.address}:${this.port}`);
});
}
}