mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-20 19:55:52 +00:00
* [PoE2] - Relics broken again #444 * test prettier and add npm script * add format/lint support to main * Fix defineProps macro * Run speed v0.8.0 - Russian. #447 * fix negative gold * fix hunters t7 accuracy * fix note in ko * fix dumb bow skills with curly braces * version bump
150 lines
4.2 KiB
TypeScript
150 lines
4.2 KiB
TypeScript
import { WebSocketServer, type WebSocket } from "ws";
|
|
import { type AddressInfo } from "net";
|
|
import { createServer } from "http";
|
|
import { EventEmitter } from "events";
|
|
import * as fs from "fs";
|
|
import * as path from "path";
|
|
import { app } from "electron";
|
|
import { IpcEvent, IpcEventPayload, HostState } from "../../ipc/types";
|
|
import { ConfigStore } from "./host-files/ConfigStore";
|
|
import { addFileUploadRoutes } from "./host-files/file-uploads";
|
|
import type { AppUpdater } from "./AppUpdater";
|
|
import type { Logger } from "./RemoteLogger";
|
|
|
|
export const server = createServer();
|
|
const websocketServer = new WebSocketServer({ noServer: true });
|
|
let lastActiveClient: WebSocket;
|
|
|
|
addFileUploadRoutes(server);
|
|
|
|
if (!process.env.VITE_DEV_SERVER_URL) {
|
|
server.addListener("request", (req, res) => {
|
|
if (
|
|
req.url?.startsWith("/config") ||
|
|
req.url?.startsWith("/uploads") ||
|
|
req.url?.startsWith("/proxy")
|
|
)
|
|
return;
|
|
|
|
const filePath = req.url === "/" ? "/index.html" : req.url!;
|
|
switch (path.extname(filePath)) {
|
|
case ".html":
|
|
res.setHeader("content-type", "text/html");
|
|
break;
|
|
case ".js":
|
|
res.setHeader("content-type", "text/javascript");
|
|
break;
|
|
case ".json":
|
|
res.setHeader("content-type", "application/json");
|
|
break;
|
|
case ".svg":
|
|
res.setHeader("content-type", "image/svg+xml");
|
|
break;
|
|
}
|
|
|
|
fs.createReadStream(path.join(__dirname, filePath)).pipe(res);
|
|
});
|
|
}
|
|
|
|
const evBus = new EventEmitter();
|
|
|
|
export function onEventAnyClient<Name extends IpcEvent["name"]>(
|
|
name: Name,
|
|
cb: (payload: IpcEventPayload<Name>) => void,
|
|
) {
|
|
evBus.on(name, cb);
|
|
}
|
|
|
|
export function sendEventTo(
|
|
target: "last-active" | "any" | "broadcast",
|
|
event: IpcEvent,
|
|
) {
|
|
const msg = JSON.stringify(event);
|
|
if (target === "broadcast") {
|
|
for (const client of websocketServer.clients) {
|
|
client.send(msg);
|
|
}
|
|
} else {
|
|
lastActiveClient.send(msg);
|
|
}
|
|
}
|
|
|
|
export interface ServerEvents {
|
|
onEventAnyClient: typeof onEventAnyClient;
|
|
sendEventTo: typeof sendEventTo;
|
|
}
|
|
export const eventPipe = {
|
|
onEventAnyClient,
|
|
sendEventTo,
|
|
};
|
|
|
|
server.on("upgrade", (req, socket, head) => {
|
|
if (req.url !== "/events") {
|
|
return req.destroy();
|
|
}
|
|
websocketServer.handleUpgrade(req, socket, head, (ws) => {
|
|
websocketServer.emit("connection", ws, req);
|
|
});
|
|
});
|
|
|
|
export async function startServer(
|
|
appUpdater: AppUpdater,
|
|
logger: Logger,
|
|
): Promise<number> {
|
|
const configStore = new ConfigStore(eventPipe);
|
|
|
|
websocketServer.on("connection", (socket) => {
|
|
lastActiveClient = socket;
|
|
socket.on("message", (bytes) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
const event = JSON.parse(bytes.toString("utf-8")) as IpcEvent;
|
|
if (event.name === "CLIENT->MAIN::used-recently") {
|
|
lastActiveClient = socket;
|
|
}
|
|
evBus.emit(event.name, event.payload);
|
|
});
|
|
socket.on("close", () => {
|
|
const clients = websocketServer.clients;
|
|
if (clients.size === 1) {
|
|
lastActiveClient = clients.values().next().value!;
|
|
evBus.emit("CLIENT->MAIN::used-recently", { isOverlay: true });
|
|
}
|
|
});
|
|
sendEventTo("last-active", {
|
|
name: "MAIN->CLIENT::log-entry",
|
|
payload: { message: logger.history },
|
|
});
|
|
});
|
|
|
|
server.addListener("request", async (req, res) => {
|
|
if (req.url === "/config") {
|
|
res.setHeader("content-type", "application/json");
|
|
const resBody: HostState = {
|
|
version: app.getVersion(),
|
|
updater: appUpdater.info,
|
|
contents: await configStore.load(),
|
|
};
|
|
res.end(JSON.stringify(resBody));
|
|
}
|
|
});
|
|
|
|
let port = process.env.VITE_DEV_SERVER_URL ? 8584 : 0;
|
|
let host = "127.0.0.1";
|
|
// --listen=[host][:port]
|
|
const listenOpt = process.argv.find((arg) => arg.startsWith("--listen"));
|
|
if (listenOpt) {
|
|
const [hostArg, portArg] = listenOpt.split("=")[1].split(":");
|
|
if (hostArg) host = hostArg;
|
|
if (portArg) port = parseInt(portArg, 10);
|
|
}
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
server
|
|
.listen({ port, host })
|
|
.once("error", reject)
|
|
.once("listening", () => {
|
|
resolve((server.address() as AddressInfo).port);
|
|
});
|
|
});
|
|
}
|