trillium/server/src/routes/ws/Room.ts
2024-05-22 11:35:43 +03:00

155 lines
No EOL
4.3 KiB
TypeScript

import { client } from "../../db";
import { Client } from "./Client";
import { Participiant } from "./Participiant";
import {exists} from "fs/promises";
export class Room {
participiants: Map<string, Participiant> = new Map();
name: string;
hidden: boolean;
messageHistory: {
userID: string;
content: string;
images?: string[] | undefined;
username: string;
time: number;
}[] = [];
timeout?: number;
constructor(name: string, hidden: boolean) {
this.name = name;
this.hidden = hidden;
}
async addMessage(
message: { message: string; images: string[] },
part: Participiant
) {
if (message.message.length > 200) return;
if (message.message.length < 1) return;
let validImages: string[] = [];
for (const image of message.images) {
if (!/^[a-z0-9]{1,16}$/gm.test(image)) continue;
if (await exists("static/images/" + image)) {
validImages.push(image);
}
}
const punishments = await client.punishment.findMany({
where: {
punishedUserId: part.user.id,
type: "mute",
},
});
for (const punishment of punishments) {
if (punishment.time == -1) punishment.time = Infinity;
const diff =
punishment.at.getTime() + punishment.time - new Date().getTime();
if (diff > 0) {
// punishment is valid
const punishedBy = await client.user.findFirst({
where: {
id: punishment.staffId,
},
});
part.broadcast({
type: "notification",
message: `You've been muted by ${punishedBy?.username}. There are ${diff}ms left in your mute. You were muted at ${punishment.at}. The reason you were muted is "${punishment.reason}"`,
});
return;
}
}
const msg = {
content: message.message,
images: validImages,
time: Date.now(),
userID: part.user.id,
username: part.user.username,
};
for (const part of this.participiants) {
part[1].broadcast({
type: "message",
message: msg,
});
}
this.messageHistory.push(msg);
}
addClient(client: Client) {
let part = this.participiants.get(client.userId);
if (part) {
part.room = this.name;
part.addClient(client);
} else {
part = client.makeParticipiant();
part.room = this.name;
part.addClient(client);
this.participiants.set(part.user.id, part);
}
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = undefined;
client.send({
type: "notification",
message: `You saved ${this.name}! Thank you!`,
});
}
client.send({
type: "history",
messages: this.messageHistory,
});
client.send({
type: "room",
room: this.name,
});
this.updatePeople();
}
removeClient(client: Client, timeoutFunction: () => void) {
let part = this.participiants.get(client.userId);
if (!part) return;
part.clients = part.clients.filter((z) => z.id !== client.id);
if (part.clients.length == 0) {
this.participiants.delete(client.userId);
}
if (this.participiants.size == 0) {
client.send({
type: "notification",
message:
this.name +
" has 0 users left! If nobody joins in 15 seconds, the room's history will be deleted.",
});
this.timeout = setTimeout(timeoutFunction, 15000) as unknown as number;
}
this.updatePeople();
return part.clients.length == 0;
}
sendPeople(z: Client) {
z.send({
type: "people",
people: [...this.participiants.values()].map((z) => {
return { username: z.user?.username, id: z.user?.id, status: z.user?.status };
}),
});
}
updatePeople() {
this.participiants.forEach((z) => {
z.broadcast({
type: "people",
people: [...this.participiants.values()].map((z) => {
return { username: z.user?.username, id: z.user?.id, status: z.user?.status };
}),
});
});
}
}