import { client } from "../../db"; import { Client } from "./Client"; import { Participiant } from "./Participiant"; import {exists} from "fs/promises"; export class Room { participiants: Map = 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 }; }), }); }); } }