83 lines
1.7 KiB
TypeScript
83 lines
1.7 KiB
TypeScript
import { randomUUID } from 'node:crypto'
|
|
|
|
export type LiveChatMessage = {
|
|
id: string
|
|
username: string
|
|
text: string
|
|
createdAt: number
|
|
}
|
|
|
|
type LiveChatRoom = {
|
|
messages: LiveChatMessage[]
|
|
sockets: Set<string>
|
|
}
|
|
|
|
const MAX_MESSAGES_PER_ROOM = 100
|
|
|
|
export class LiveChatStore {
|
|
private readonly rooms = new Map<string, LiveChatRoom>()
|
|
|
|
joinRoom (streamKey: string, socketId: string) {
|
|
const room = this.getOrCreateRoom(streamKey)
|
|
|
|
room.sockets.add(socketId)
|
|
|
|
return room
|
|
}
|
|
|
|
leaveRoom (streamKey: string, socketId: string) {
|
|
const room = this.rooms.get(streamKey)
|
|
if (!room) return
|
|
|
|
room.sockets.delete(socketId)
|
|
|
|
if (room.sockets.size === 0 && room.messages.length === 0) {
|
|
this.rooms.delete(streamKey)
|
|
}
|
|
}
|
|
|
|
addMessage (streamKey: string, username: string, text: string) {
|
|
const room = this.getOrCreateRoom(streamKey)
|
|
const message: LiveChatMessage = {
|
|
id: randomUUID(),
|
|
username,
|
|
text,
|
|
createdAt: Date.now()
|
|
}
|
|
|
|
room.messages.push(message)
|
|
if (room.messages.length > MAX_MESSAGES_PER_ROOM) {
|
|
room.messages.splice(0, room.messages.length - MAX_MESSAGES_PER_ROOM)
|
|
}
|
|
|
|
return message
|
|
}
|
|
|
|
getRecentMessages (streamKey: string) {
|
|
return [ ...(this.rooms.get(streamKey)?.messages || []) ]
|
|
}
|
|
|
|
getPresenceCount (streamKey: string) {
|
|
return this.rooms.get(streamKey)?.sockets.size || 0
|
|
}
|
|
|
|
deleteRoom (streamKey: string) {
|
|
return this.rooms.delete(streamKey)
|
|
}
|
|
|
|
private getOrCreateRoom (streamKey: string) {
|
|
let room = this.rooms.get(streamKey)
|
|
|
|
if (!room) {
|
|
room = {
|
|
messages: [],
|
|
sockets: new Set<string>()
|
|
}
|
|
|
|
this.rooms.set(streamKey, room)
|
|
}
|
|
|
|
return room
|
|
}
|
|
}
|