move websocket stuff into its own service
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build / build (pull_request) Successful in 48s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build / build (pull_request) Successful in 48s
				
			This commit is contained in:
		
							parent
							
								
									6ff32aa9db
								
							
						
					
					
						commit
						31523ddd19
					
				@ -8,7 +8,7 @@ import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } f
 | 
				
			|||||||
import { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "@/src/types/loginTypes";
 | 
					import { IDatabaseAccountJson, ILoginRequest, ILoginResponse } from "@/src/types/loginTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
					import { version_compare } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const loginController: RequestHandler = async (request, response) => {
 | 
					export const loginController: RequestHandler = async (request, response) => {
 | 
				
			||||||
    const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
 | 
					    const loginRequest = JSON.parse(String(request.body)) as ILoginRequest; // parse octet stream of json data to json object
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import {
 | 
				
			|||||||
} from "@/src/services/loginRewardService";
 | 
					} from "@/src/services/loginRewardService";
 | 
				
			||||||
import { getInventory } from "@/src/services/inventoryService";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
					export const loginRewardsController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ import {
 | 
				
			|||||||
} from "@/src/services/loginRewardService";
 | 
					} from "@/src/services/loginRewardService";
 | 
				
			||||||
import { getAccountForRequest } from "@/src/services/loginService";
 | 
					import { getAccountForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
					import { handleStoreItemAcquisition } from "@/src/services/purchaseService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import { Account } from "@/src/models/loginModel";
 | 
					import { Account } from "@/src/models/loginModel";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const logoutController: RequestHandler = async (req, res) => {
 | 
					export const logoutController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    if (!req.query.accountId) {
 | 
					    if (!req.query.accountId) {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import { getInventory } from "@/src/services/inventoryService";
 | 
				
			|||||||
import { getInventoryResponse } from "./inventoryController";
 | 
					import { getInventoryResponse } from "./inventoryController";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
 | 
					import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
import { generateRewardSeed } from "@/src/services/rngService";
 | 
					import { generateRewardSeed } from "@/src/services/rngService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			|||||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
					import { getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface INameWeaponRequest {
 | 
					interface INameWeaponRequest {
 | 
				
			||||||
    ItemName: string;
 | 
					    ItemName: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			|||||||
import { IPurchaseRequest } from "@/src/types/purchaseTypes";
 | 
					import { IPurchaseRequest } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { handlePurchase } from "@/src/services/purchaseService";
 | 
					import { handlePurchase } from "@/src/services/purchaseService";
 | 
				
			||||||
import { getInventory } from "@/src/services/inventoryService";
 | 
					import { getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const purchaseController: RequestHandler = async (req, res) => {
 | 
					export const purchaseController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
 | 
					    const purchaseRequest = JSON.parse(String(req.body)) as IPurchaseRequest;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
					import { getInventory, updateCurrency } from "@/src/services/inventoryService";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			|||||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
 | 
					import { ExportDojoRecipes } from "warframe-public-export-plus";
 | 
				
			||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
					import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const sellController: RequestHandler = async (req, res) => {
 | 
					export const sellController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const payload = JSON.parse(String(req.body)) as ISellRequest;
 | 
					    const payload = JSON.parse(String(req.body)) as ISellRequest;
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ import { getRecipeByResult } from "@/src/services/itemDataService";
 | 
				
			|||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService";
 | 
					import { addInfestedFoundryXP, applyCheatsToInfestedFoundry } from "@/src/services/infestedFoundryService";
 | 
				
			||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { sendWsBroadcastTo } from "@/src/services/webService";
 | 
					import { sendWsBroadcastTo } from "@/src/services/wsService";
 | 
				
			||||||
import { EquipmentFeatures, IEquipmentDatabase } from "@/src/types/equipmentTypes";
 | 
					import { EquipmentFeatures, IEquipmentDatabase } from "@/src/types/equipmentTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const upgradesController: RequestHandler = async (req, res) => {
 | 
					export const upgradesController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ import { RequestHandler } from "express";
 | 
				
			|||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
					import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
 | 
				
			||||||
import { saveConfig } from "@/src/services/configWatcherService";
 | 
					import { saveConfig } from "@/src/services/configWatcherService";
 | 
				
			||||||
import { sendWsBroadcastExcept } from "@/src/services/webService";
 | 
					import { sendWsBroadcastExcept } from "@/src/services/wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getConfigController: RequestHandler = async (req, res) => {
 | 
					export const getConfigController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const account = await getAccountForRequest(req);
 | 
					    const account = await getAccountForRequest(req);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { args } from "@/src/helpers/commandLineArguments";
 | 
					import { args } from "@/src/helpers/commandLineArguments";
 | 
				
			||||||
import { sendWsBroadcast } from "@/src/services/webService";
 | 
					import { sendWsBroadcast } from "@/src/services/wsService";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
 | 
					export const webuiFileChangeDetectedController: RequestHandler = (req, res) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,8 @@ import chokidar from "chokidar";
 | 
				
			|||||||
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, sendWsBroadcast, startWebServer, stopWebServer } from "./webService";
 | 
					import { getWebPorts, startWebServer, stopWebServer } from "./webService";
 | 
				
			||||||
 | 
					import { sendWsBroadcast } from "./wsService";
 | 
				
			||||||
import { Inbox } from "../models/inboxModel";
 | 
					import { Inbox } from "../models/inboxModel";
 | 
				
			||||||
import varzia from "@/static/fixed_responses/worldState/varzia.json";
 | 
					import varzia from "@/static/fixed_responses/worldState/varzia.json";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,17 +5,11 @@ 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";
 | 
					 | 
				
			||||||
import { Account } from "../models/loginModel";
 | 
					 | 
				
			||||||
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
 | 
					 | 
				
			||||||
import { IDatabaseAccountJson } from "../types/loginTypes";
 | 
					 | 
				
			||||||
import { HydratedDocument } from "mongoose";
 | 
					 | 
				
			||||||
import { Agent, WebSocket as UnidiciWebSocket } from "undici";
 | 
					import { Agent, WebSocket as UnidiciWebSocket } from "undici";
 | 
				
			||||||
 | 
					import { startWsServer, startWssServer, stopWsServers } from "./wsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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"),
 | 
				
			||||||
@ -29,16 +23,14 @@ 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 });
 | 
					        startWsServer(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 });
 | 
					            startWssServer(httpsServer!);
 | 
				
			||||||
            wssServer.on("connection", wsOnConnect);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            logger.info("HTTPS server started on port " + httpsPort);
 | 
					            logger.info("HTTPS server started on port " + httpsPort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -115,182 +107,6 @@ export const stopWebServer = async (): Promise<void> => {
 | 
				
			|||||||
            })
 | 
					            })
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (wsServer) {
 | 
					    stopWsServers(promises);
 | 
				
			||||||
        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);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
let lastWsid: number = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IWsCustomData extends ws {
 | 
					 | 
				
			||||||
    id?: number;
 | 
					 | 
				
			||||||
    accountId?: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IWsMsgFromClient {
 | 
					 | 
				
			||||||
    auth?: {
 | 
					 | 
				
			||||||
        email: string;
 | 
					 | 
				
			||||||
        password: string;
 | 
					 | 
				
			||||||
        isRegister: boolean;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    logout?: boolean;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface IWsMsgToClient {
 | 
					 | 
				
			||||||
    //wsid?: number;
 | 
					 | 
				
			||||||
    reload?: boolean;
 | 
					 | 
				
			||||||
    ports?: {
 | 
					 | 
				
			||||||
        http: number | undefined;
 | 
					 | 
				
			||||||
        https: number | undefined;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    config_reloaded?: boolean;
 | 
					 | 
				
			||||||
    auth_succ?: {
 | 
					 | 
				
			||||||
        id: string;
 | 
					 | 
				
			||||||
        DisplayName: string;
 | 
					 | 
				
			||||||
        Nonce: number;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    auth_fail?: {
 | 
					 | 
				
			||||||
        isRegister: boolean;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    logged_out?: boolean;
 | 
					 | 
				
			||||||
    update_inventory?: boolean;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
 | 
					 | 
				
			||||||
    if (req.url == "/custom/selftest") {
 | 
					 | 
				
			||||||
        ws.send("SpaceNinjaServer");
 | 
					 | 
				
			||||||
        ws.close();
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    (ws as IWsCustomData).id = ++lastWsid;
 | 
					 | 
				
			||||||
    ws.send(JSON.stringify({ wsid: lastWsid }));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
					 | 
				
			||||||
    ws.on("message", async msg => {
 | 
					 | 
				
			||||||
        const data = JSON.parse(String(msg)) as IWsMsgFromClient;
 | 
					 | 
				
			||||||
        if (data.auth) {
 | 
					 | 
				
			||||||
            let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email });
 | 
					 | 
				
			||||||
            if (account) {
 | 
					 | 
				
			||||||
                if (isCorrectPassword(data.auth.password, account.password)) {
 | 
					 | 
				
			||||||
                    if (!account.Nonce) {
 | 
					 | 
				
			||||||
                        account.ClientType = "webui";
 | 
					 | 
				
			||||||
                        account.Nonce = createNonce();
 | 
					 | 
				
			||||||
                        await (account as HydratedDocument<IDatabaseAccountJson>).save();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    account = null;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else if (data.auth.isRegister) {
 | 
					 | 
				
			||||||
                const name = await getUsernameFromEmail(data.auth.email);
 | 
					 | 
				
			||||||
                account = await createAccount({
 | 
					 | 
				
			||||||
                    email: data.auth.email,
 | 
					 | 
				
			||||||
                    password: data.auth.password,
 | 
					 | 
				
			||||||
                    ClientType: "webui",
 | 
					 | 
				
			||||||
                    LastLogin: new Date(),
 | 
					 | 
				
			||||||
                    DisplayName: name,
 | 
					 | 
				
			||||||
                    Nonce: createNonce()
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (account) {
 | 
					 | 
				
			||||||
                (ws as IWsCustomData).accountId = account.id;
 | 
					 | 
				
			||||||
                ws.send(
 | 
					 | 
				
			||||||
                    JSON.stringify({
 | 
					 | 
				
			||||||
                        auth_succ: {
 | 
					 | 
				
			||||||
                            id: account.id,
 | 
					 | 
				
			||||||
                            DisplayName: account.DisplayName,
 | 
					 | 
				
			||||||
                            Nonce: account.Nonce
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    } satisfies IWsMsgToClient)
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                ws.send(
 | 
					 | 
				
			||||||
                    JSON.stringify({
 | 
					 | 
				
			||||||
                        auth_fail: {
 | 
					 | 
				
			||||||
                            isRegister: data.auth.isRegister
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    } satisfies IWsMsgToClient)
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (data.logout) {
 | 
					 | 
				
			||||||
            const accountId = (ws as IWsCustomData).accountId;
 | 
					 | 
				
			||||||
            (ws as IWsCustomData).accountId = undefined;
 | 
					 | 
				
			||||||
            await Account.updateOne(
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    _id: accountId,
 | 
					 | 
				
			||||||
                    ClientType: "webui"
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    Nonce: 0
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const sendWsBroadcast = (data: IWsMsgToClient): 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);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const sendWsBroadcastTo = (accountId: string, data: IWsMsgToClient): void => {
 | 
					 | 
				
			||||||
    const msg = JSON.stringify(data);
 | 
					 | 
				
			||||||
    if (wsServer) {
 | 
					 | 
				
			||||||
        for (const client of wsServer.clients) {
 | 
					 | 
				
			||||||
            if ((client as IWsCustomData).accountId == accountId) {
 | 
					 | 
				
			||||||
                client.send(msg);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (wssServer) {
 | 
					 | 
				
			||||||
        for (const client of wssServer.clients) {
 | 
					 | 
				
			||||||
            if ((client as IWsCustomData).accountId == accountId) {
 | 
					 | 
				
			||||||
                client.send(msg);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const sendWsBroadcastExcept = (wsid: number | undefined, data: IWsMsgToClient): void => {
 | 
					 | 
				
			||||||
    const msg = JSON.stringify(data);
 | 
					 | 
				
			||||||
    if (wsServer) {
 | 
					 | 
				
			||||||
        for (const client of wsServer.clients) {
 | 
					 | 
				
			||||||
            if ((client as IWsCustomData).id != wsid) {
 | 
					 | 
				
			||||||
                client.send(msg);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (wssServer) {
 | 
					 | 
				
			||||||
        for (const client of wssServer.clients) {
 | 
					 | 
				
			||||||
            if ((client as IWsCustomData).id != wsid) {
 | 
					 | 
				
			||||||
                client.send(msg);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										200
									
								
								src/services/wsService.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								src/services/wsService.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,200 @@
 | 
				
			|||||||
 | 
					import http from "http";
 | 
				
			||||||
 | 
					import https from "https";
 | 
				
			||||||
 | 
					import ws from "ws";
 | 
				
			||||||
 | 
					import { Account } from "../models/loginModel";
 | 
				
			||||||
 | 
					import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "./loginService";
 | 
				
			||||||
 | 
					import { IDatabaseAccountJson } from "../types/loginTypes";
 | 
				
			||||||
 | 
					import { HydratedDocument } from "mongoose";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let wsServer: ws.Server | undefined;
 | 
				
			||||||
 | 
					let wssServer: ws.Server | undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const startWsServer = (httpServer: http.Server): void => {
 | 
				
			||||||
 | 
					    wsServer = new ws.Server({ server: httpServer });
 | 
				
			||||||
 | 
					    wsServer.on("connection", wsOnConnect);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const startWssServer = (httpsServer: https.Server): void => {
 | 
				
			||||||
 | 
					    wssServer = new ws.Server({ server: httpsServer });
 | 
				
			||||||
 | 
					    wssServer.on("connection", wsOnConnect);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const stopWsServers = (promises: Promise<void>[]): void => {
 | 
				
			||||||
 | 
					    if (wsServer) {
 | 
				
			||||||
 | 
					        promises.push(
 | 
				
			||||||
 | 
					            new Promise(resolve => {
 | 
				
			||||||
 | 
					                wsServer!.close(() => {
 | 
				
			||||||
 | 
					                    resolve();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (wssServer) {
 | 
				
			||||||
 | 
					        promises.push(
 | 
				
			||||||
 | 
					            new Promise(resolve => {
 | 
				
			||||||
 | 
					                wssServer!.close(() => {
 | 
				
			||||||
 | 
					                    resolve();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let lastWsid: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IWsCustomData extends ws {
 | 
				
			||||||
 | 
					    id?: number;
 | 
				
			||||||
 | 
					    accountId?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IWsMsgFromClient {
 | 
				
			||||||
 | 
					    auth?: {
 | 
				
			||||||
 | 
					        email: string;
 | 
				
			||||||
 | 
					        password: string;
 | 
				
			||||||
 | 
					        isRegister: boolean;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    logout?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IWsMsgToClient {
 | 
				
			||||||
 | 
					    //wsid?: number;
 | 
				
			||||||
 | 
					    reload?: boolean;
 | 
				
			||||||
 | 
					    ports?: {
 | 
				
			||||||
 | 
					        http: number | undefined;
 | 
				
			||||||
 | 
					        https: number | undefined;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    config_reloaded?: boolean;
 | 
				
			||||||
 | 
					    auth_succ?: {
 | 
				
			||||||
 | 
					        id: string;
 | 
				
			||||||
 | 
					        DisplayName: string;
 | 
				
			||||||
 | 
					        Nonce: number;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    auth_fail?: {
 | 
				
			||||||
 | 
					        isRegister: boolean;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    logged_out?: boolean;
 | 
				
			||||||
 | 
					    update_inventory?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
 | 
				
			||||||
 | 
					    if (req.url == "/custom/selftest") {
 | 
				
			||||||
 | 
					        ws.send("SpaceNinjaServer");
 | 
				
			||||||
 | 
					        ws.close();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (ws as IWsCustomData).id = ++lastWsid;
 | 
				
			||||||
 | 
					    ws.send(JSON.stringify({ wsid: lastWsid }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
				
			||||||
 | 
					    ws.on("message", async msg => {
 | 
				
			||||||
 | 
					        const data = JSON.parse(String(msg)) as IWsMsgFromClient;
 | 
				
			||||||
 | 
					        if (data.auth) {
 | 
				
			||||||
 | 
					            let account: IDatabaseAccountJson | null = await Account.findOne({ email: data.auth.email });
 | 
				
			||||||
 | 
					            if (account) {
 | 
				
			||||||
 | 
					                if (isCorrectPassword(data.auth.password, account.password)) {
 | 
				
			||||||
 | 
					                    if (!account.Nonce) {
 | 
				
			||||||
 | 
					                        account.ClientType = "webui";
 | 
				
			||||||
 | 
					                        account.Nonce = createNonce();
 | 
				
			||||||
 | 
					                        await (account as HydratedDocument<IDatabaseAccountJson>).save();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    account = null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else if (data.auth.isRegister) {
 | 
				
			||||||
 | 
					                const name = await getUsernameFromEmail(data.auth.email);
 | 
				
			||||||
 | 
					                account = await createAccount({
 | 
				
			||||||
 | 
					                    email: data.auth.email,
 | 
				
			||||||
 | 
					                    password: data.auth.password,
 | 
				
			||||||
 | 
					                    ClientType: "webui",
 | 
				
			||||||
 | 
					                    LastLogin: new Date(),
 | 
				
			||||||
 | 
					                    DisplayName: name,
 | 
				
			||||||
 | 
					                    Nonce: createNonce()
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (account) {
 | 
				
			||||||
 | 
					                (ws as IWsCustomData).accountId = account.id;
 | 
				
			||||||
 | 
					                ws.send(
 | 
				
			||||||
 | 
					                    JSON.stringify({
 | 
				
			||||||
 | 
					                        auth_succ: {
 | 
				
			||||||
 | 
					                            id: account.id,
 | 
				
			||||||
 | 
					                            DisplayName: account.DisplayName,
 | 
				
			||||||
 | 
					                            Nonce: account.Nonce
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } satisfies IWsMsgToClient)
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ws.send(
 | 
				
			||||||
 | 
					                    JSON.stringify({
 | 
				
			||||||
 | 
					                        auth_fail: {
 | 
				
			||||||
 | 
					                            isRegister: data.auth.isRegister
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } satisfies IWsMsgToClient)
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (data.logout) {
 | 
				
			||||||
 | 
					            const accountId = (ws as IWsCustomData).accountId;
 | 
				
			||||||
 | 
					            (ws as IWsCustomData).accountId = undefined;
 | 
				
			||||||
 | 
					            await Account.updateOne(
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    _id: accountId,
 | 
				
			||||||
 | 
					                    ClientType: "webui"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Nonce: 0
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sendWsBroadcast = (data: IWsMsgToClient): 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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sendWsBroadcastTo = (accountId: string, data: IWsMsgToClient): void => {
 | 
				
			||||||
 | 
					    const msg = JSON.stringify(data);
 | 
				
			||||||
 | 
					    if (wsServer) {
 | 
				
			||||||
 | 
					        for (const client of wsServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).accountId == accountId) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (wssServer) {
 | 
				
			||||||
 | 
					        for (const client of wssServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).accountId == accountId) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const sendWsBroadcastExcept = (wsid: number | undefined, data: IWsMsgToClient): void => {
 | 
				
			||||||
 | 
					    const msg = JSON.stringify(data);
 | 
				
			||||||
 | 
					    if (wsServer) {
 | 
				
			||||||
 | 
					        for (const client of wsServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).id != wsid) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (wssServer) {
 | 
				
			||||||
 | 
					        for (const client of wssServer.clients) {
 | 
				
			||||||
 | 
					            if ((client as IWsCustomData).id != wsid) {
 | 
				
			||||||
 | 
					                client.send(msg);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user