Start implementation of channel save data

This commit is contained in:
Hri7566 2024-08-03 20:00:19 -04:00
parent 7edabc7748
commit a32f47f432
4 changed files with 132 additions and 5 deletions

View File

@ -37,14 +37,14 @@ enableAdminEval: true
# The token validation scheme. Valid values are "none", "jwt" and "uuid". # The token validation scheme. Valid values are "none", "jwt" and "uuid".
# This server will still validate existing tokens generated with other schemes if not set to "none", mimicking MPP.net's server. # This server will still validate existing tokens generated with other schemes if not set to "none", mimicking MPP.net's server.
# This is set to "none" by default because MPP.com does not have a token system. # This is set to "none" by default because MPP.com does not have a token system.
tokenAuth: jwt tokenAuth: none
# The browser challenge scheme. Valid options are "none", "obf" and "basic". # The browser challenge scheme. Valid options are "none", "obf" and "basic".
# This is to change what is sent in the "b" message. # This is to change what is sent in the "b" message.
# "none" will disable the browser challenge, # "none" will disable the browser challenge,
# "obf" will sent an obfuscated function to the client, # "obf" will sent an obfuscated function to the client,
# and "basic" will just send a simple function that expects a boolean. # and "basic" will just send a simple function that expects a boolean.
browserChallenge: basic browserChallenge: none
# Scheme for generating user IDs. # Scheme for generating user IDs.
# Valid options are "random", "sha256", "mpp" and "uuid". # Valid options are "random", "sha256", "mpp" and "uuid".

View File

@ -25,3 +25,10 @@ model ChatHistory {
id String @id @unique @map("_id") id String @id @unique @map("_id")
messages String @default("[]") // JSON messages messages String @default("[]") // JSON messages
} }
model Channel {
id String @id @unique @map("_id")
settings String @default("{}") // JSON channel settings
forceload Boolean @default(false) // Whether the channel is forceloaded
flags String @default("{}") // JSON flags object
}

View File

@ -22,6 +22,8 @@ import { saveChatHistory, getChatHistory, deleteChatHistory } from "../data/hist
import { mixin, darken } from "../util/helpers"; import { mixin, darken } from "../util/helpers";
import { User } from "@prisma/client"; import { User } from "@prisma/client";
import { heapStats } from "bun:jsc"; import { heapStats } from "bun:jsc";
import { deleteSavedChannel, getSavedChannel, saveChannel } from "../data/channel";
import { forceloadChannel } from "./forceLoad";
interface CachedKickban { interface CachedKickban {
userId: string; userId: string;
@ -59,6 +61,53 @@ export class Channel extends EventEmitter {
} catch (err) { } } catch (err) { }
} }
private async deleteData() {
try {
await deleteSavedChannel(this.getID());
} catch (err) { }
}
private async save() {
this.logger.debug("Saving channel data");
try {
const info = this.getInfo();
const data = {
id: info._id,
settings: JSON.stringify(info.settings),
flags: JSON.stringify(this.flags)
};
this.logger.debug("Channel data to save:", data);
await saveChannel(this.getID(), data);
} catch (err) {
this.logger.debug("Error saving cannel:", err);
}
}
private async load() {
this.logger.debug("Loading saved data");
try {
const data = await getSavedChannel(this.getID());
if (data) {
try {
this.changeSettings(JSON.parse(data.settings));
this.setFlags(JSON.parse(data.flags));
this.loadChatHistory();
if (data.forceload) {
forceloadChannel(this.getID());
}
this.logger.debug("Loaded channel data:", data);
} catch (err) {
this.logger.debug("Error loading channel data:", err);
}
}
} catch (err) { }
}
public logger: Logger; public logger: Logger;
public bans = new Array<CachedKickban>(); public bans = new Array<CachedKickban>();
public cursorCache = new Array<{ x: string | number; y: string | number; id: string }>(); public cursorCache = new Array<{ x: string | number; y: string | number; id: string }>();
@ -121,8 +170,7 @@ export class Channel extends EventEmitter {
this.bindEventListeners(); this.bindEventListeners();
ChannelList.add(this); ChannelList.add(this);
// TODO implement owner_id this.settings.owner_id = this.flags["owner_id"];
this.settings.owner_id = owner_id;
this.logger.info("Created"); this.logger.info("Created");
@ -138,7 +186,8 @@ export class Channel extends EventEmitter {
private bindEventListeners() { private bindEventListeners() {
if (this.alreadyBound) return; if (this.alreadyBound) return;
this.alreadyBound = true; this.alreadyBound = true;
this.loadChatHistory(); this.load();
this.save();
this.logger.info("Loaded chat history"); this.logger.info("Loaded chat history");
this.on("update", (self, uuid) => { this.on("update", (self, uuid) => {
@ -422,6 +471,9 @@ export class Channel extends EventEmitter {
*/ */
//this.logger.debug("Update from changeSettings"); //this.logger.debug("Update from changeSettings");
(async () => {
await this.save();
})();
this.emit("update", this); this.emit("update", this);
} }
@ -806,6 +858,7 @@ export class Channel extends EventEmitter {
ChannelList.remove(this); ChannelList.remove(this);
this.deleteChatHistory(); this.deleteChatHistory();
this.deleteData();
this.logger.info("Destroyed"); this.logger.info("Destroyed");
} }
@ -1148,6 +1201,16 @@ export class Channel extends EventEmitter {
return this.flags[key]; return this.flags[key];
} }
/**
* Set the flags on this channel
* @param flags Flags to set
**/
public setFlags(flags: Record<string, any>) {
this.flags = flags;
this.save();
this.emit("update", this);
}
/** /**
* Get the ID of the next lobby, useful if this channel is full and is also a lobby * Get the ID of the next lobby, useful if this channel is full and is also a lobby
* @returns ID of the next lobby in numeric succession * @returns ID of the next lobby in numeric succession
@ -1176,6 +1239,9 @@ export class Channel extends EventEmitter {
} }
} }
/**
* Print the amount of memory the server is using in chat
**/
public printMemoryInChat() { public printMemoryInChat() {
const mem = heapStats(); const mem = heapStats();
this.sendChatAdmin(`Used: ${(mem.heapSize / 1000 / 1000).toFixed(2)}M / Allocated: ${(mem.heapCapacity / 1000 / 1000).toFixed(2)}M`); this.sendChatAdmin(`Used: ${(mem.heapSize / 1000 / 1000).toFixed(2)}M / Allocated: ${(mem.heapCapacity / 1000 / 1000).toFixed(2)}M`);

54
src/data/channel.ts Normal file
View File

@ -0,0 +1,54 @@
import { Prisma } from "@prisma/client";
import { prisma } from "./prisma";
/**
* Get saved channel data from the database
* @param channelId ID of channel to get
* @returns Saved channel data
*/
export async function getSavedChannel(channelId: string) {
try {
return await prisma.channel.findUnique({
where: {
id: channelId
}
});
} catch (e) {
return null;
}
}
/**
* Save channel data to the database (update if already exists)
* @param channelId ID of channel to save
* @param channel Channel data to save
*/
export async function saveChannel(channelId: string, channel: Prisma.ChannelUpdateInput & Prisma.ChannelCreateInput) {
try {
return await prisma.channel.upsert({
where: {
id: channelId
},
update: channel,
create: channel
});
} catch (e) {
console.error(e);
}
}
/**
* Delete channel data from the database
* @param channelId ID of channel to delete
*/
export async function deleteSavedChannel(channelId: string) {
try {
return await prisma.channel.delete({
where: {
id: channelId
}
});
} catch (e) {
console.error(e);
}
}