返回提交历史
Modified
package-lock.json
+33
-1
Modified
package.json
+3
-1
Modified
src/services/configWatcherService.ts
+7
-1
Modified
src/services/webService.ts
+46
-0
Modified
static/webui/script.js
+23
-3
XFEstudio/XFESpaceNinjaServer
feat(webui): initial websocket integration to be more responsive (#2221)
For now just handles changes to config.json but in the future might keep the inventory tabs up-to-date with in-game actions. Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2221 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
4cb0f8b1
代码差异
5 个文件
+112
-6
@@ -11,6 +11,7 @@
11
11
"dependencies": {
12
12
"@types/express": "^5",
13
13
"@types/morgan": "^1.9.9",
14
"@types/ws": "^8.18.1",
14
15
"crc-32": "^1.2.2",
15
16
"express": "^5",
16
17
"json-with-bigint": "^3.4.4",
@@ -21,7 +22,8 @@
21
22
"warframe-public-export-plus": "^0.5.68",
22
23
"warframe-riven-info": "^0.1.2",
23
24
"winston": "^3.17.0",
24
"winston-daily-rotate-file": "^5.0.0"
25
"winston-daily-rotate-file": "^5.0.0",
26
"ws": "^8.18.2"
25
27
},
26
28
"devDependencies": {
27
29
"@typescript-eslint/eslint-plugin": "^8.28.0",
@@ -472,6 +474,15 @@
472
474
"@types/webidl-conversions": "*"
473
475
}
474
476
},
477
"node_modules/@types/ws": {
478
"version": "8.18.1",
479
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
480
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
481
"license": "MIT",
482
"dependencies": {
483
"@types/node": "*"
484
}
485
},
475
486
"node_modules/@typescript-eslint/eslint-plugin": {
476
487
"version": "8.32.0",
477
488
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.0.tgz",
@@ -3931,6 +3942,27 @@
3931
3942
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
3932
3943
"license": "ISC"
3933
3944
},
3945
"node_modules/ws": {
3946
"version": "8.18.2",
3947
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
3948
"integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
3949
"license": "MIT",
3950
"engines": {
3951
"node": ">=10.0.0"
3952
},
3953
"peerDependencies": {
3954
"bufferutil": "^4.0.1",
3955
"utf-8-validate": ">=5.0.2"
3956
},
3957
"peerDependenciesMeta": {
3958
"bufferutil": {
3959
"optional": true
3960
},
3961
"utf-8-validate": {
3962
"optional": true
3963
}
3964
}
3965
},
3934
3966
"node_modules/xtend": {
3935
3967
"version": "4.0.2",
3936
3968
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -18,6 +18,7 @@
18
18
"dependencies": {
19
19
"@types/express": "^5",
20
20
"@types/morgan": "^1.9.9",
21
"@types/ws": "^8.18.1",
21
22
"crc-32": "^1.2.2",
22
23
"express": "^5",
23
24
"json-with-bigint": "^3.4.4",
@@ -28,7 +29,8 @@
28
29
"warframe-public-export-plus": "^0.5.68",
29
30
"warframe-riven-info": "^0.1.2",
30
31
"winston": "^3.17.0",
31
"winston-daily-rotate-file": "^5.0.0"
32
"winston-daily-rotate-file": "^5.0.0",
33
"ws": "^8.18.2"
32
34
},
33
35
"devDependencies": {
34
36
"@typescript-eslint/eslint-plugin": "^8.28.0",
@@ -2,7 +2,7 @@ import fs from "fs";
2
2
import fsPromises from "fs/promises";
3
3
import { logger } from "../utils/logger";
4
4
import { config, configPath, loadConfig } from "./configService";
5
import { getWebPorts, startWebServer, stopWebServer } from "./webService";
5
import { getWebPorts, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
6
6
7
7
let amnesia = false;
8
8
fs.watchFile(configPath, () => {
@@ -21,7 +21,13 @@ fs.watchFile(configPath, () => {
21
21
const webPorts = getWebPorts();
22
22
if (config.httpPort != webPorts.http || config.httpsPort != webPorts.https) {
23
23
logger.info(`Restarting web server to apply port changes.`);
24
25
// Tell webui clients to reload with new port
26
sendWsBroadcast({ ports: { http: config.httpPort, https: config.httpsPort } });
27
24
28
void stopWebServer().then(startWebServer);
29
} else {
30
sendWsBroadcast({ config_reloaded: true });
25
31
}
26
32
}
27
33
});
@@ -5,9 +5,12 @@ import { config } from "./configService";
5
5
import { logger } from "../utils/logger";
6
6
import { app } from "../app";
7
7
import { AddressInfo } from "node:net";
8
import ws from "ws";
8
9
9
10
let httpServer: http.Server | undefined;
10
11
let httpsServer: https.Server | undefined;
12
let wsServer: ws.Server | undefined;
13
let wssServer: ws.Server | undefined;
11
14
12
15
const tlsOptions = {
13
16
key: fs.readFileSync("static/certs/key.pem"),
@@ -21,10 +24,17 @@ export const startWebServer = (): void => {
21
24
// eslint-disable-next-line @typescript-eslint/no-misused-promises
22
25
httpServer = http.createServer(app);
23
26
httpServer.listen(httpPort, () => {
27
wsServer = new ws.Server({ server: httpServer });
28
//wsServer.on("connection", wsOnConnect);
29
24
30
logger.info("HTTP server started on port " + httpPort);
31
25
32
// eslint-disable-next-line @typescript-eslint/no-misused-promises
26
33
httpsServer = https.createServer(tlsOptions, app);
27
34
httpsServer.listen(httpsPort, () => {
35
wssServer = new ws.Server({ server: httpsServer });
36
//wssServer.on("connection", wsOnConnect);
37
28
38
logger.info("HTTPS server started on port " + httpsPort);
29
39
30
40
logger.info(
@@ -61,5 +71,41 @@ export const stopWebServer = async (): Promise<void> => {
61
71
})
62
72
);
63
73
}
74
if (wsServer) {
75
promises.push(
76
new Promise(resolve => {
77
wsServer!.close(() => {
78
resolve();
79
});
80
})
81
);
82
}
83
if (wssServer) {
84
promises.push(
85
new Promise(resolve => {
86
wssServer!.close(() => {
87
resolve();
88
});
89
})
90
);
91
}
64
92
await Promise.all(promises);
65
93
};
94
95
/*const wsOnConnect = (ws: ws, _req: http.IncomingMessage): void => {
96
ws.on("message", console.log);
97
};*/
98
99
export const sendWsBroadcast = <T>(data: T): void => {
100
const msg = JSON.stringify(data);
101
if (wsServer) {
102
for (const client of wsServer.clients) {
103
client.send(msg);
104
}
105
}
106
if (wssServer) {
107
for (const client of wssServer.clients) {
108
client.send(msg);
109
}
110
}
111
};
@@ -1,3 +1,23 @@
1
function openWebSocket() {
2
window.ws = new WebSocket("/custom/ws");
3
window.ws.onmessage = e => {
4
const msg = JSON.parse(e.data);
5
if ("ports" in msg) {
6
location.port = location.protocol == "https:" ? msg.ports.https : msg.ports.http;
7
}
8
if ("config_reloaded" in msg) {
9
//window.is_admin = undefined;
10
if (single.getCurrentPath() == "/webui/cheats") {
11
single.loadRoute("/webui/cheats");
12
}
13
}
14
};
15
window.ws.onclose = function () {
16
setTimeout(openWebSocket, 3000);
17
};
18
}
19
openWebSocket();
20
1
21
let loginOrRegisterPending = false;
2
22
window.registerSubmit = false;
3
23
@@ -1822,6 +1842,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
1822
1842
clearInterval(interval);
1823
1843
fetch("/custom/config?" + window.authz).then(async res => {
1824
1844
if (res.status == 200) {
1845
//window.is_admin = true;
1825
1846
$("#server-settings-no-perms").addClass("d-none");
1826
1847
$("#server-settings").removeClass("d-none");
1827
1848
res.json().then(json =>
@@ -1830,9 +1851,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
1830
1851
var x = document.getElementById(`${key}`);
1831
1852
if (x != null) {
1832
1853
if (x.type == "checkbox") {
1833
if (value === true) {
1834
x.setAttribute("checked", "checked");
1835
}
1854
x.checked = value;
1836
1855
} else if (x.type == "number") {
1837
1856
x.setAttribute("value", `${value}`);
1838
1857
}
@@ -1847,6 +1866,7 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
1847
1866
}
1848
1867
});
1849
1868
} else {
1869
//window.is_admin = false;
1850
1870
$("#server-settings-no-perms").removeClass("d-none");
1851
1871
$("#server-settings").addClass("d-none");
1852
1872
}