Fix memory issues and insert unhinged comments
This commit is contained in:
parent
8ab74266e2
commit
828443cb93
|
@ -7,6 +7,11 @@ import { ChannelList } from "./ChannelList";
|
||||||
|
|
||||||
const logger = new Logger("Channel Forceloader");
|
const logger = new Logger("Channel Forceloader");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forceloads a channel
|
||||||
|
* @param id The channel ID
|
||||||
|
* @returns Whether the channel was loaded
|
||||||
|
*/
|
||||||
export function forceloadChannel(id: string) {
|
export function forceloadChannel(id: string) {
|
||||||
try {
|
try {
|
||||||
logger.info("Forceloading", id);
|
logger.info("Forceloading", id);
|
||||||
|
@ -17,6 +22,11 @@ export function forceloadChannel(id: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unforceloads a channel
|
||||||
|
* @param id The channel ID
|
||||||
|
* @returns Whether the channel was unloaded
|
||||||
|
*/
|
||||||
export function unforceloadChannel(id: string) {
|
export function unforceloadChannel(id: string) {
|
||||||
const ch = ChannelList.getList().find(ch => ch.getID() == id);
|
const ch = ChannelList.getList().find(ch => ch.getID() == id);
|
||||||
if (!ch) return false;
|
if (!ch) return false;
|
||||||
|
@ -27,6 +37,10 @@ export function unforceloadChannel(id: string) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forceloads all forceload-configured channels
|
||||||
|
* This is meant to be called on startup
|
||||||
|
**/
|
||||||
export function loadForcedStartupChannels() {
|
export function loadForcedStartupChannels() {
|
||||||
let hasFullChannel = false;
|
let hasFullChannel = false;
|
||||||
|
|
||||||
|
|
32
src/index.ts
32
src/index.ts
|
@ -4,15 +4,47 @@
|
||||||
* by Hri7566
|
* by Hri7566
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// There are a lot of unhinged bs comments in this repo
|
||||||
|
// Pay no attention to the ones that cuss you out
|
||||||
|
|
||||||
// If you don't load the server first, bun will literally segfault
|
// If you don't load the server first, bun will literally segfault
|
||||||
import "./ws/server";
|
import "./ws/server";
|
||||||
import { loadForcedStartupChannels } from "./channel/forceLoad";
|
import { loadForcedStartupChannels } from "./channel/forceLoad";
|
||||||
import { Logger } from "./util/Logger";
|
import { Logger } from "./util/Logger";
|
||||||
|
|
||||||
|
// Let's construct an entire object just for one thing to be printed
|
||||||
|
// and then keep it in memory for the entirety of runtime
|
||||||
const logger = new Logger("Main");
|
const logger = new Logger("Main");
|
||||||
logger.info("Forceloading startup channels...");
|
logger.info("Forceloading startup channels...");
|
||||||
loadForcedStartupChannels();
|
loadForcedStartupChannels();
|
||||||
|
|
||||||
|
// This literally breaks editors and they stick all the imports here instead of at the top
|
||||||
import "./util/readline";
|
import "./util/readline";
|
||||||
|
import { Socket, socketsBySocketID } from "./ws/Socket";
|
||||||
|
import { createSocketID } from "./util/id";
|
||||||
|
|
||||||
|
// Nevermind we use it twice
|
||||||
logger.info("Ready");
|
logger.info("Ready");
|
||||||
|
|
||||||
|
// Connect 5 sockets
|
||||||
|
const sockets = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
setTimeout(() => {
|
||||||
|
const socket = new Socket(undefined, createSocketID());
|
||||||
|
|
||||||
|
socket.on("ready", () => {
|
||||||
|
logger.info(`Socket ${i} is ready`);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.setChannel("lobby");
|
||||||
|
|
||||||
|
sockets.push(socket);
|
||||||
|
|
||||||
|
if (socket.socketID == undefined) {
|
||||||
|
socket.socketID = createSocketID();
|
||||||
|
}
|
||||||
|
|
||||||
|
socketsBySocketID.set(socket.socketID, socket);
|
||||||
|
}, i * 5000);
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { padNum, unimportant } from "./helpers";
|
import { padNum, unimportant } from "./helpers";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logger that doesn't fuck with the readline prompt
|
||||||
|
* timestamps are likely wrong because of js timezones
|
||||||
|
**/
|
||||||
export class Logger {
|
export class Logger {
|
||||||
private static log(method: string, ...args: any[]) {
|
private static log(method: string, ...args: any[]) {
|
||||||
// Clear current line
|
// Un-fuck the readline prompt
|
||||||
process.stdout.write("\x1b[2K\r");
|
process.stdout.write("\x1b[2K\r");
|
||||||
|
|
||||||
// Log our stuff
|
// Log
|
||||||
(console as unknown as Record<string, (..._args: any[]) => any>)[
|
(console as unknown as Record<string, (..._args: any[]) => any>)[
|
||||||
method
|
method
|
||||||
](
|
](
|
||||||
|
@ -14,7 +18,7 @@ export class Logger {
|
||||||
...args
|
...args
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fix the readline prompt (spooky cringe code)
|
// Re-print the readline prompt (spooky cringe global variable)
|
||||||
if ((globalThis as unknown as any).rl)
|
if ((globalThis as unknown as any).rl)
|
||||||
(globalThis as unknown as any).rl.prompt();
|
(globalThis as unknown as any).rl.prompt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
// Gray console text
|
/**
|
||||||
|
* Gray console text maker
|
||||||
|
* @param str String to gray
|
||||||
|
* @returns Gray string to put in console
|
||||||
|
**/
|
||||||
export function unimportant(str: string) {
|
export function unimportant(str: string) {
|
||||||
return `\x1b[90m${str}\x1b[0m`;
|
return `\x1b[90m${str}\x1b[0m`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pad time strings
|
/**
|
||||||
|
* Pad time strings
|
||||||
|
* @param num Number to pad
|
||||||
|
* @param padAmount Amount of padding
|
||||||
|
* @param padChar Character to pad with
|
||||||
|
* @param left Whether to pad left or right
|
||||||
|
* @returns Padded string
|
||||||
|
**/
|
||||||
export function padNum(
|
export function padNum(
|
||||||
num: number,
|
num: number,
|
||||||
padAmount: number,
|
padAmount: number,
|
||||||
|
@ -21,6 +32,9 @@ export const encoder = new TextEncoder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if an object has a property
|
* Check if an object has a property
|
||||||
|
* @param obj Object to check
|
||||||
|
* @param property Property to check
|
||||||
|
* @returns Whether the object has the property
|
||||||
**/
|
**/
|
||||||
export function hasOwn(obj: any, property: string | number | Symbol) {
|
export function hasOwn(obj: any, property: string | number | Symbol) {
|
||||||
return (Object as unknown as any).hasOwn(obj, property);
|
return (Object as unknown as any).hasOwn(obj, property);
|
||||||
|
@ -47,7 +61,15 @@ export function darken(color: string, amount = 0x40) {
|
||||||
|
|
||||||
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
|
||||||
}
|
}
|
||||||
// Brandon made this literally eons ago and it's fucking hilarious
|
|
||||||
|
// spooky.jsaurus
|
||||||
|
// NOT the same as poop_text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make text spoopy
|
||||||
|
* @param message Message to spoop
|
||||||
|
* @returns Spooped message
|
||||||
|
**/
|
||||||
export function spoop_text(message: string) {
|
export function spoop_text(message: string) {
|
||||||
var old = message;
|
var old = message;
|
||||||
message = "";
|
message = "";
|
||||||
|
@ -64,6 +86,11 @@ export function spoop_text(message: string) {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mix two objects
|
||||||
|
* @param obj1 Object to mix into
|
||||||
|
* @param obj2 Object to mix
|
||||||
|
**/
|
||||||
export function mixin(obj1: any, obj2: any) {
|
export function mixin(obj1: any, obj2: any) {
|
||||||
for (const key of Object.keys(obj2)) {
|
for (const key of Object.keys(obj2)) {
|
||||||
obj1[key] = obj2[key];
|
obj1[key] = obj2[key];
|
||||||
|
|
|
@ -75,3 +75,49 @@ Command.addCommand(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Command.addCommand(
|
||||||
|
new Command(["js", "eval"], "js <code>", async msg => {
|
||||||
|
function roughSizeOfObject(object: any) {
|
||||||
|
const objectList: any[] = [];
|
||||||
|
const stack = [object];
|
||||||
|
let bytes = 0;
|
||||||
|
|
||||||
|
while (stack.length) {
|
||||||
|
const value = stack.pop();
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'boolean':
|
||||||
|
bytes += 4;
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
bytes += value.length * 2;
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
bytes += 8;
|
||||||
|
break;
|
||||||
|
case 'object':
|
||||||
|
if (!objectList.includes(value)) {
|
||||||
|
objectList.push(value);
|
||||||
|
for (const prop in value) {
|
||||||
|
if (value.hasOwnProperty(prop)) {
|
||||||
|
stack.push(value[prop]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
if (msg.args.length > 1) {
|
||||||
|
try {
|
||||||
|
const output = eval(msg.args[1]);
|
||||||
|
return output;
|
||||||
|
} catch (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
|
@ -36,6 +36,11 @@ const logger = new Logger("Sockets");
|
||||||
|
|
||||||
type CursorValue = string | number;
|
type CursorValue = string | number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended websocket thing
|
||||||
|
* Most poeple call this "Client" but it's not on the client...
|
||||||
|
* This is likely the source of my memory leaks
|
||||||
|
**/
|
||||||
export class Socket extends EventEmitter {
|
export class Socket extends EventEmitter {
|
||||||
private id: string;
|
private id: string;
|
||||||
private _id: string;
|
private _id: string;
|
||||||
|
@ -65,6 +70,7 @@ export class Socket extends EventEmitter {
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
// real user?
|
||||||
if (ws) {
|
if (ws) {
|
||||||
// Real user
|
// Real user
|
||||||
this.ip = ws.data.ip;
|
this.ip = ws.data.ip;
|
||||||
|
@ -82,13 +88,18 @@ export class Socket extends EventEmitter {
|
||||||
let foundSocket;
|
let foundSocket;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
|
// big boi loop
|
||||||
for (const socket of socketsBySocketID.values()) {
|
for (const socket of socketsBySocketID.values()) {
|
||||||
|
// Skip us
|
||||||
if (socket.socketID == this.socketID) continue;
|
if (socket.socketID == this.socketID) continue;
|
||||||
|
|
||||||
|
// Are they real?
|
||||||
if (socket.ws) {
|
if (socket.ws) {
|
||||||
|
// Are they connected?
|
||||||
if (socket.ws.readyState !== 1) continue;
|
if (socket.ws.readyState !== 1) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same user ID?
|
||||||
if (socket.getUserID() == this.getUserID()) {
|
if (socket.getUserID() == this.getUserID()) {
|
||||||
foundSocket = socket;
|
foundSocket = socket;
|
||||||
count++;
|
count++;
|
||||||
|
@ -96,11 +107,14 @@ export class Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count >= 4) {
|
if (count >= 4) {
|
||||||
|
// Too many go away
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// logger.debug("Found socket?", foundSocket);
|
// logger.debug("Found socket?", foundSocket);
|
||||||
|
|
||||||
|
// If there is another socket, use their ID for some reason I forgot
|
||||||
|
// otherwise, make a new one
|
||||||
if (!foundSocket) {
|
if (!foundSocket) {
|
||||||
// Use new session ID
|
// Use new session ID
|
||||||
this.id = createID();
|
this.id = createID();
|
||||||
|
@ -109,18 +123,24 @@ export class Socket extends EventEmitter {
|
||||||
this.id = foundSocket.id;
|
this.id = foundSocket.id;
|
||||||
|
|
||||||
// Break us off
|
// Break us off
|
||||||
|
// didn't work nvm
|
||||||
//this.id = "broken";
|
//this.id = "broken";
|
||||||
//this.destroy();
|
//this.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load stuff
|
||||||
(async () => {
|
(async () => {
|
||||||
|
// Load our user data
|
||||||
await this.loadUser();
|
await this.loadUser();
|
||||||
|
|
||||||
|
// Set our rate limits
|
||||||
this.resetRateLimits();
|
this.resetRateLimits();
|
||||||
this.setNoteQuota(NoteQuota.PARAMS_RIDICULOUS);
|
this.setNoteQuota(NoteQuota.PARAMS_RIDICULOUS);
|
||||||
|
|
||||||
|
// Bind a bunch of our event listeners so we do stuff when told to
|
||||||
this.bindEventListeners();
|
this.bindEventListeners();
|
||||||
|
|
||||||
|
// Send a challenge to the browser for MPP.net frontends
|
||||||
if (config.browserChallenge == "basic") {
|
if (config.browserChallenge == "basic") {
|
||||||
this.sendArray([{
|
this.sendArray([{
|
||||||
m: "b",
|
m: "b",
|
||||||
|
@ -131,6 +151,7 @@ export class Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// all done
|
||||||
this.emit("ready");
|
this.emit("ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +164,7 @@ export class Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the user ID of this socket
|
* Get the user ID (_id) of this socket
|
||||||
* @returns User ID
|
* @returns User ID
|
||||||
**/
|
**/
|
||||||
public getUserID() {
|
public getUserID() {
|
||||||
|
@ -151,7 +172,7 @@ export class Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the participant ID of this socket
|
* Get the participant ID (id) of this socket
|
||||||
* @returns Participant ID
|
* @returns Participant ID
|
||||||
**/
|
**/
|
||||||
public getParticipantID() {
|
public getParticipantID() {
|
||||||
|
@ -744,6 +765,9 @@ export class Socket extends EventEmitter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ban this socket's user for doing bad things
|
* Ban this socket's user for doing bad things
|
||||||
|
* this doesn't actually ban the user, it just sends a notification right now FIXME
|
||||||
|
* @param duration Duration of the ban in milliseconds
|
||||||
|
* @param reason Reason for the ban
|
||||||
**/
|
**/
|
||||||
public ban(duration: number, reason: string) {
|
public ban(duration: number, reason: string) {
|
||||||
// TODO cleaner ban system
|
// TODO cleaner ban system
|
||||||
|
@ -763,13 +787,26 @@ export class Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const socketsBySocketID = new Map<string, Socket>();
|
export const socketsBySocketID = new Map<string, Socket>();
|
||||||
|
(globalThis as any).socketsBySocketID = socketsBySocketID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a socket by their participant ID
|
||||||
|
* bad don't use for unique sockets
|
||||||
|
* @param id Participant ID to find
|
||||||
|
* @returns Socket object
|
||||||
|
**/
|
||||||
export function findSocketByPartID(id: string) {
|
export function findSocketByPartID(id: string) {
|
||||||
for (const socket of socketsBySocketID.values()) {
|
for (const socket of socketsBySocketID.values()) {
|
||||||
if (socket.getParticipantID() == id) return socket;
|
if (socket.getParticipantID() == id) return socket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all sockets by their user ID
|
||||||
|
* also not unique
|
||||||
|
* @param _id User ID to find
|
||||||
|
* @returns Socket objects
|
||||||
|
**/
|
||||||
export function findSocketsByUserID(_id: string) {
|
export function findSocketsByUserID(_id: string) {
|
||||||
const sockets = [];
|
const sockets = [];
|
||||||
|
|
||||||
|
@ -781,6 +818,12 @@ export function findSocketsByUserID(_id: string) {
|
||||||
return sockets;
|
return sockets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a socket by their IP
|
||||||
|
* probably not unique if they're on different tabs
|
||||||
|
* @param ip IP to find
|
||||||
|
* @returns Socket object
|
||||||
|
**/
|
||||||
export function findSocketByIP(ip: string) {
|
export function findSocketByIP(ip: string) {
|
||||||
for (const socket of socketsBySocketID.values()) {
|
for (const socket of socketsBySocketID.values()) {
|
||||||
if (socket.getIP() == ip) {
|
if (socket.getIP() == ip) {
|
||||||
|
|
|
@ -22,18 +22,18 @@ export const adminLimits: RateLimitConstructorList = {
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.admin.chains.userset.interval,
|
config.admin.chains.userset.num,
|
||||||
config.admin.chains.userset.num
|
config.admin.chains.userset.interval
|
||||||
),
|
),
|
||||||
chset: () =>
|
chset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.admin.chains.chset.interval,
|
config.admin.chains.chset.num,
|
||||||
config.admin.chains.userset.num
|
config.admin.chains.userset.interval
|
||||||
),
|
),
|
||||||
n: () =>
|
n: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.admin.chains.n.interval,
|
config.admin.chains.n.num,
|
||||||
config.admin.chains.userset.num
|
config.admin.chains.userset.interval
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,18 +22,18 @@ export const crownLimits: RateLimitConstructorList = {
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.crown.chains.userset.interval,
|
config.crown.chains.userset.num,
|
||||||
config.crown.chains.userset.num
|
config.crown.chains.userset.interval
|
||||||
),
|
),
|
||||||
chset: () =>
|
chset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.crown.chains.chset.interval,
|
config.crown.chains.chset.num,
|
||||||
config.crown.chains.userset.num
|
config.crown.chains.userset.interval
|
||||||
),
|
),
|
||||||
n: () =>
|
n: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.crown.chains.n.interval,
|
config.crown.chains.n.num,
|
||||||
config.crown.chains.userset.num
|
config.crown.chains.userset.interval
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,18 +22,18 @@ export const userLimits: RateLimitConstructorList = {
|
||||||
chains: {
|
chains: {
|
||||||
userset: () =>
|
userset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.user.chains.userset.interval,
|
config.user.chains.userset.num,
|
||||||
config.user.chains.userset.num
|
config.user.chains.userset.interval
|
||||||
),
|
),
|
||||||
chset: () =>
|
chset: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.user.chains.chset.interval,
|
config.user.chains.chset.num,
|
||||||
config.user.chains.userset.num
|
config.user.chains.userset.interval
|
||||||
),
|
),
|
||||||
n: () =>
|
n: () =>
|
||||||
new RateLimitChain(
|
new RateLimitChain(
|
||||||
config.user.chains.n.interval,
|
config.user.chains.n.num,
|
||||||
config.user.chains.userset.num
|
config.user.chains.userset.interval
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@ async function getIndex() {
|
||||||
// nobody realistically uses templates in 2024 and documents
|
// nobody realistically uses templates in 2024 and documents
|
||||||
// it well enough to say what library they used
|
// it well enough to say what library they used
|
||||||
|
|
||||||
|
// I totally forget if this even works
|
||||||
|
|
||||||
const index = Bun.file("./public/index.html");
|
const index = Bun.file("./public/index.html");
|
||||||
|
|
||||||
const rendered = nunjucks.renderString(await index.text(), {
|
const rendered = nunjucks.renderString(await index.text(), {
|
||||||
|
@ -91,11 +93,15 @@ export const app = Bun.serve<{ ip: string }>({
|
||||||
// logger.debug("Connection at " + socket.getIP());
|
// logger.debug("Connection at " + socket.getIP());
|
||||||
|
|
||||||
// Let's put it in the dinner bucket.
|
// Let's put it in the dinner bucket.
|
||||||
socketsBySocketID.set((socket.socketID as any), socket);
|
if (socket.socketID == undefined) {
|
||||||
|
socket.socketID = createSocketID();
|
||||||
|
}
|
||||||
|
|
||||||
|
socketsBySocketID.set(socket.socketID, socket);
|
||||||
},
|
},
|
||||||
|
|
||||||
message: (ws, message) => {
|
message: (ws, message) => {
|
||||||
// "Let's make it binary" said all websocket developers for some reason
|
// Fucking string
|
||||||
const msg = message.toString();
|
const msg = message.toString();
|
||||||
|
|
||||||
// Let's find out wtf they even sent
|
// Let's find out wtf they even sent
|
||||||
|
@ -103,8 +109,6 @@ export const app = Bun.serve<{ ip: string }>({
|
||||||
},
|
},
|
||||||
|
|
||||||
close: (ws, code, message) => {
|
close: (ws, code, message) => {
|
||||||
// logger.debug("Close called");
|
|
||||||
|
|
||||||
// This usually gets called when someone leaves,
|
// This usually gets called when someone leaves,
|
||||||
// but it's also used internally just in case
|
// but it's also used internally just in case
|
||||||
// some dickhead can't close their tab like a
|
// some dickhead can't close their tab like a
|
||||||
|
|
Loading…
Reference in New Issue