feat(webui): initial websocket integration to be more responsive #2221
34
package-lock.json
generated
34
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"json-with-bigint": "^3.4.4",
|
"json-with-bigint": "^3.4.4",
|
||||||
@ -21,7 +22,8 @@
|
|||||||
"warframe-public-export-plus": "^0.5.68",
|
"warframe-public-export-plus": "^0.5.68",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
|
"ws": "^8.18.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||||
@ -472,6 +474,15 @@
|
|||||||
"@types/webidl-conversions": "*"
|
"@types/webidl-conversions": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||||
|
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.32.0",
|
"version": "8.32.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz",
|
||||||
@ -3931,6 +3942,27 @@
|
|||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
|
||||||
|
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/express": "^5",
|
"@types/express": "^5",
|
||||||
"@types/morgan": "^1.9.9",
|
"@types/morgan": "^1.9.9",
|
||||||
|
"@types/ws": "^8.18.1",
|
||||||
"crc-32": "^1.2.2",
|
"crc-32": "^1.2.2",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"json-with-bigint": "^3.4.4",
|
"json-with-bigint": "^3.4.4",
|
||||||
@ -28,7 +29,8 @@
|
|||||||
"warframe-public-export-plus": "^0.5.68",
|
"warframe-public-export-plus": "^0.5.68",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
|
"ws": "^8.18.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||||
|
@ -2,7 +2,7 @@ import fs from "fs";
|
|||||||
import fsPromises from "fs/promises";
|
import fsPromises from "fs/promises";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { config, configPath, loadConfig } from "./configService";
|
import { config, configPath, loadConfig } from "./configService";
|
||||||
import { getWebPorts, startWebServer, stopWebServer } from "./webService";
|
import { getWebPorts, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
|
||||||
|
|
||||||
let amnesia = false;
|
let amnesia = false;
|
||||||
fs.watchFile(configPath, () => {
|
fs.watchFile(configPath, () => {
|
||||||
@ -21,7 +21,13 @@ fs.watchFile(configPath, () => {
|
|||||||
const webPorts = getWebPorts();
|
const webPorts = getWebPorts();
|
||||||
if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) {
|
if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) {
|
||||||
logger.info(`Restarting web server to apply port changes.`);
|
logger.info(`Restarting web server to apply port changes.`);
|
||||||
|
|
||||||
|
// Tell webui clients to reload with new port
|
||||||
|
sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
|
||||||
|
|
||||||
void stopWebServer().then(startWebServer);
|
void stopWebServer().then(startWebServer);
|
||||||
|
} else {
|
||||||
|
sendWsBroadcast({ config_reloaded: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -5,9 +5,12 @@ import { config } from "./configService";
|
|||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { app } from "../app";
|
import { app } from "../app";
|
||||||
import { AddressInfo } from "node:net";
|
import { AddressInfo } from "node:net";
|
||||||
|
import ws from "ws";
|
||||||
|
|
||||||
let httpServer: http.Server | undefined;
|
let httpServer: http.Server | undefined;
|
||||||
let httpsServer: https.Server | undefined;
|
let httpsServer: https.Server | undefined;
|
||||||
|
let wsServer: ws.Server | undefined;
|
||||||
|
let wssServer: ws.Server | undefined;
|
||||||
|
|
||||||
const tlsOptions = {
|
const tlsOptions = {
|
||||||
key: fs.readFileSync("static/certs/key.pem"),
|
key: fs.readFileSync("static/certs/key.pem"),
|
||||||
@ -21,10 +24,17 @@ export const startWebServer = (): void => {
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
httpServer = http.createServer(app);
|
httpServer = http.createServer(app);
|
||||||
httpServer.listen(httpPort, () => {
|
httpServer.listen(httpPort, () => {
|
||||||
|
wsServer = new ws.Server({ server: httpServer });
|
||||||
|
//wsServer.on("connection", wsOnConnect);
|
||||||
|
|
||||||
logger.info("HTTP server started on port " + httpPort);
|
logger.info("HTTP server started on port " + httpPort);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
httpsServer = https.createServer(tlsOptions, app);
|
httpsServer = https.createServer(tlsOptions, app);
|
||||||
httpsServer.listen(httpsPort, () => {
|
httpsServer.listen(httpsPort, () => {
|
||||||
|
wssServer = new ws.Server({ server: httpsServer });
|
||||||
|
//wssServer.on("connection", wsOnConnect);
|
||||||
|
|
||||||
logger.info("HTTPS server started on port " + httpsPort);
|
logger.info("HTTPS server started on port " + httpsPort);
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -61,5 +71,41 @@ export const stopWebServer = async (): Promise<void> => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (wsServer) {
|
||||||
|
promises.push(
|
||||||
|
new Promise(resolve => {
|
||||||
|
wsServer!.close(() => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (wssServer) {
|
||||||
|
promises.push(
|
||||||
|
new Promise(resolve => {
|
||||||
|
wssServer!.close(() => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*const wsOnConnect = (ws: ws, _req: http.IncomingMessage): void => {
|
||||||
|
ws.on("message", console.log);
|
||||||
|
};*/
|
||||||
|
|
||||||
|
export const sendWsBroadcast = <T>(data: T): void => {
|
||||||
|
const msg = JSON.stringify(data);
|
||||||
|
if (wsServer) {
|
||||||
|
for (const client of wsServer.clients) {
|
||||||
|
client.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wssServer) {
|
||||||
|
for (const client of wssServer.clients) {
|
||||||
|
client.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,3 +1,23 @@
|
|||||||
|
function openWebSocket() {
|
||||||
|
window.ws = new WebSocket("/custom/ws");
|
||||||
|
window.ws.onmessage = e => {
|
||||||
|
const msg = JSON.parse(e.data);
|
||||||
|
if ("ports" in msg) {
|
||||||
|
location.port = location.protocol == "https:" ? msg.ports.https : msg.ports.http;
|
||||||
|
}
|
||||||
|
if ("config_reloaded" in msg) {
|
||||||
|
//window.is_admin = undefined;
|
||||||
|
if (single.getCurrentPath() == "/webui/cheats") {
|
||||||
|
single.loadRoute("/webui/cheats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.ws.onclose = function () {
|
||||||
|
setTimeout(openWebSocket, 3000);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
openWebSocket();
|
||||||
|
|
||||||
let loginOrRegisterPending = false;
|
let loginOrRegisterPending = false;
|
||||||
window.registerSubmit = false;
|
window.registerSubmit = false;
|
||||||
|
|
||||||
@ -1812,6 +1832,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
fetch("/custom/config?" + window.authz).then(async res => {
|
fetch("/custom/config?" + window.authz).then(async res => {
|
||||||
if (res.status == 200) {
|
if (res.status == 200) {
|
||||||
|
//window.is_admin = true;
|
||||||
$("#server-settings-no-perms").addClass("d-none");
|
$("#server-settings-no-perms").addClass("d-none");
|
||||||
$("#server-settings").removeClass("d-none");
|
$("#server-settings").removeClass("d-none");
|
||||||
res.json().then(json =>
|
res.json().then(json =>
|
||||||
@ -1820,9 +1841,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
var x = document.getElementById(`${key}`);
|
var x = document.getElementById(`${key}`);
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
if (x.type == "checkbox") {
|
if (x.type == "checkbox") {
|
||||||
if (value === true) {
|
x.checked = value;
|
||||||
x.setAttribute("checked", "checked");
|
|
||||||
}
|
|
||||||
} else if (x.type == "number") {
|
} else if (x.type == "number") {
|
||||||
x.setAttribute("value", `${value}`);
|
x.setAttribute("value", `${value}`);
|
||||||
}
|
}
|
||||||
@ -1837,6 +1856,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
//window.is_admin = false;
|
||||||
$("#server-settings-no-perms").removeClass("d-none");
|
$("#server-settings-no-perms").removeClass("d-none");
|
||||||
$("#server-settings").addClass("d-none");
|
$("#server-settings").addClass("d-none");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user