| 
					
				 | 
			
			
				@@ -2,7 +2,7 @@ import config from "config"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import express from "express"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import http, { Server, IncomingMessage } from "node:http"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { RawData, WebSocketServer } from "ws"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { Types } from "mongoose"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Types, isObjectIdOrHexString } from "mongoose"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import BaseModule from "@/BaseModule"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { UniqueMethods } from "@/types/Modules"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import WebSocket from "@/WebSocket"; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -10,6 +10,7 @@ import JobContext from "@/JobContext"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Job from "@/Job"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ModuleManager from "@/ModuleManager"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import JobQueue from "@/JobQueue"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import DataModule from "./DataModule"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	private _httpServer?: Server; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -24,12 +25,7 @@ export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	public constructor() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		super("websocket"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		this._jobConfigDefault = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		this._jobConfig = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			getSocket: "disabled", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			getSockets: "disabled" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		this._jobConfigDefault = "disabled"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -99,10 +95,73 @@ export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const readyData = await new Job("prepareWebsocket", "api", { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			socket, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			request 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}).execute(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		socket.setSocketId(request.headers["sec-websocket-key"]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		let sessionId; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		let user; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (request.headers.cookie) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sessionId = request.headers.cookie 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				.split("; ") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				.find( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					cookie => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						cookie.substring(0, cookie.indexOf("=")) === 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						config.get<string>("cookie") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sessionId = sessionId?.substring( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				sessionId.indexOf("=") + 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				sessionId.length 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (sessionId && isObjectIdOrHexString(sessionId)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			socket.setSessionId(sessionId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			const Session = await DataModule.getModel("sessions"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			const session = await Session.findByIdAndUpdate(sessionId, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				updatedAt: Date.now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (session) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const User = await DataModule.getModel("users"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				user = await User.findById(session.userId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		const readyData = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			config: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				cookie: config.get("cookie"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				sitename: config.get("sitename"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				recaptcha: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					enabled: config.get("apis.recaptcha.enabled"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					key: config.get("apis.recaptcha.key") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				githubAuthentication: config.get("apis.github.enabled"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				messages: config.get("messages"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				christmas: config.get("christmas"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				footerLinks: config.get("footerLinks"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				shortcutOverrides: config.get("shortcutOverrides"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				registrationDisabled: config.get("registrationDisabled"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mailEnabled: config.get("mail.enabled"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				discogsEnabled: config.get("apis.discogs.enabled"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				experimental: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					changable_listen_mode: config.get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						"experimental.changable_listen_mode" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					media_session: config.get("experimental.media_session"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					disable_youtube_search: config.get( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						"experimental.disable_youtube_search" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					station_history: config.get("experimental.station_history"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					soundcloud: config.get("experimental.soundcloud"), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					spotify: config.get("experimental.spotify") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			user 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		socket.log({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			type: "debug", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -118,6 +177,15 @@ export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		socket.on("close", async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			await JobQueue.runJob( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"api", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				"unsubscribeAll", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socketId: socket.getSocketId() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			socket.log({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				type: "debug", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				message: `WebSocket closed #${socket.getSocketId()}` 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -163,18 +231,29 @@ export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			const job = module.getJob(jobName); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			if (!job.api) throw new Error(`Job "${jobName}" not found.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			const res = await JobQueue.runJob("api", "runJob", { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			let session; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (socket.getSessionId()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				const Session = await DataModule.getModel("sessions"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				session = await Session.findByIdAndUpdate( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socket.getSessionId(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						updatedAt: Date.now() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			await JobQueue.queueJob( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				moduleName, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				jobName, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				payload, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				sessionId: socket.getSessionId(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				socketId: socket.getSocketId() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			socket.dispatch("jobCallback", callbackRef, { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				status: "success", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				data: res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{}, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					session, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					socketId: socket.getSocketId(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					callbackRef 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			const message = error?.message ?? error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -218,20 +297,11 @@ export class WebSocketModule extends BaseModule { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 * dispatch - Dispatch message to socket 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	 */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	public async dispatch( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		context: JobContext, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			socketId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			channel, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		}: { socketId: string; channel: string; value?: any } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	public async dispatch(socketId: string, channel: string, ...values) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		const socket = await this.getSocket(socketId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if (!socket) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		const values = Array.isArray(value) ? value : [value]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		socket.dispatch(channel, ...values); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |