1
0
mirror of https://github.com/ragestudio/comty.git synced 2025-07-10 17:54:16 +00:00
This commit is contained in:
SrGooglo 2025-02-25 23:10:13 +00:00
parent 52dd4ecffd
commit fa83c55264

@ -1,185 +1,200 @@
import buildFunctionHandler from "@utils/buildFunctionHandler" import buildFunctionHandler from "@utils/buildFunctionHandler"
import { Snowflake } from "nodejs-snowflake"
import { ChatMessage } from "@db_models" import { ChatMessage } from "@db_models"
export default class Room { export default class Room {
constructor(io, roomID, options) { constructor(io, roomID, options) {
if (!io) { if (!io) {
throw new OperationError(500, "io is required") throw new OperationError(500, "io is required")
} }
this.io = io this.io = io
if (!roomID) { if (!roomID) {
throw new OperationError(500, "roomID is required") throw new OperationError(500, "roomID is required")
} }
this.roomID = `room:${roomID}` this.roomID = `room:${roomID}`
this.roomSocket = this.io.to(`room:${this.roomID}`) this.roomSocket = this.io.to(`room:${this.roomID}`)
this.options = { this.options = {
owner_user_id: null, owner_user_id: null,
...options, ...options,
} }
} }
connections = new Set() connections = new Set()
limitations = { limitations = {
maxMessageLength: 540, maxMessageLength: 540,
} }
roomEvents = { roomEvents = {
"room:change:owner": async (client, payload) => { "room:change:owner": async (client, payload) => {
throw new OperationError(500, "Not implemented") throw new OperationError(500, "Not implemented")
}, },
"room:send:message": async (client, payload) => { "room:send:message": async (client, payload) => {
console.log(`[${this.roomID}] [@${client.userData.username}] sent message >`, payload) console.log(
`[${this.roomID}] [@${client.userData.username}] sent message >`,
payload,
)
let { message } = payload let { message } = payload
if (!message || typeof message !== "string") { if (!message || typeof message !== "string") {
throw new Error("Invalid message") throw new Error("Invalid message")
} }
if (message.length > this.limitations.maxMessageLength) { if (message.length > this.limitations.maxMessageLength) {
message = message.substring(0, this.limitations.maxMessageLength) message = message.substring(
} 0,
this.limitations.maxMessageLength,
)
}
const created_at = new Date().getTime() const created_at = new Date().getTime()
const id = `msg:${client.userData._id}:${created_at}` const id = `msg:${client.userData._id}:${created_at}`
this.handlers.broadcastToMembers("room:message", { this.handlers.broadcastToMembers("room:message", {
_id: id, _id: id,
timestamp: payload.timestamp ?? Date.now(), timestamp: payload.timestamp ?? Date.now(),
content: String(message), content: String(message),
user: { user: {
user_id: client.userData._id, user_id: client.userData._id,
username: client.userData.username, username: client.userData.username,
fullName: client.userData.fullName, fullName: client.userData.fullName,
avatar: client.userData.avatar, avatar: client.userData.avatar,
}, },
}) })
if (payload.route) { if (payload.route) {
const routeValues = payload.route.split(":") const routeValues = payload.route.split(":")
console.log(routeValues) console.log(routeValues)
if (routeValues.length > 0) { if (routeValues.length > 0) {
const [type, to_id] = routeValues const [type, to_id] = routeValues
switch (type) { switch (type) {
case "user": { case "user": {
const doc = await ChatMessage.create({ const doc = await ChatMessage.create({
type: type, type: type,
from_user_id: client.userData._id, from_user_id: client.userData._id,
to_user_id: to_id, to_user_id: to_id,
content: message, content: message,
created_at: created_at, created_at: created_at,
}) })
console.log(doc) console.log(doc)
} }
default: default:
break; break
} }
} }
} }
} },
} }
handlers = { handlers = {
join: (client) => { join: (client) => {
if (client.connectedRoomID) { if (client.connectedRoomID) {
console.warn(`[${client.id}][@${client.userData.username}] already connected to room ${client.connectedRoomID}`) console.warn(
`[${client.id}][@${client.userData.username}] already connected to room ${client.connectedRoomID}`,
)
client.leave(client.connectedRoomID) client.leave(client.connectedRoomID)
} }
console.log(`[${client.id}][@${client.userData.username}] joined room ${this.roomID}`) console.log(
`[${client.id}][@${client.userData.username}] joined room ${this.roomID}`,
)
client.connectedRoomID = this.roomID client.connectedRoomID = this.roomID
this.connections.add(client) this.connections.add(client)
for (let [event, handler] of Object.entries(this.roomEvents)) { for (let [event, handler] of Object.entries(this.roomEvents)) {
handler = buildFunctionHandler(handler, client) handler = buildFunctionHandler(handler, client)
if (!Array.isArray(client.handlers)) { if (!Array.isArray(client.handlers)) {
client.handlers = [] client.handlers = []
} }
client.handlers.push([event, handler]) client.handlers.push([event, handler])
client.on(event, handler) client.on(event, handler)
} }
// emit to self // emit to self
client.emit("room:joined", { client.emit("room:joined", {
roomID: this.roomID, roomID: this.roomID,
limitations: this.limitations, limitations: this.limitations,
connectedUsers: this.getConnectedUsers(), connectedUsers: this.getConnectedUsers(),
}) })
// emit to others // emit to others
this.roomSocket.emit("room:user:joined", { this.roomSocket.emit("room:user:joined", {
user: { user: {
user_id: client.userData._id, user_id: client.userData._id,
username: client.userData.username, username: client.userData.username,
fullName: client.userData.fullName, fullName: client.userData.fullName,
avatar: client.userData.avatar, avatar: client.userData.avatar,
} },
}) })
}, },
leave: (client) => { leave: (client) => {
if (!client.connectedRoomID) { if (!client.connectedRoomID) {
console.warn(`[${client.id}][@${client.userData.username}] not connected to any room`) console.warn(
return `[${client.id}][@${client.userData.username}] not connected to any room`,
} )
return
}
if (client.connectedRoomID !== this.roomID) { if (client.connectedRoomID !== this.roomID) {
console.warn(`[${client.id}][@${client.userData.username}] not connected to room ${this.roomID}, cannot leave`) console.warn(
return false `[${client.id}][@${client.userData.username}] not connected to room ${this.roomID}, cannot leave`,
} )
return false
}
this.connections.delete(client) this.connections.delete(client)
client.emit("room:left", { client.emit("room:left", {
room: this.roomID, room: this.roomID,
}) })
this.roomSocket.emit("room:user:left", { this.roomSocket.emit("room:user:left", {
user: { user: {
user_id: client.userData._id, user_id: client.userData._id,
username: client.userData.username, username: client.userData.username,
fullName: client.userData.fullName, fullName: client.userData.fullName,
avatar: client.userData.avatar, avatar: client.userData.avatar,
} },
}) })
for (const [event, handler] of client.handlers) { for (const [event, handler] of client.handlers) {
client.off(event, handler) client.off(event, handler)
} }
console.log(`[${client.id}][@${client.userData.username}] left room ${this.roomID}`) console.log(
}, `[${client.id}][@${client.userData.username}] left room ${this.roomID}`,
broadcastToMembers: (event, payload) => { )
for (const client of this.connections) { },
client.emit(event, payload) broadcastToMembers: (event, payload) => {
} for (const client of this.connections) {
} client.emit(event, payload)
} }
},
}
getConnectedUsers = () => { getConnectedUsers = () => {
let users = {} let users = {}
for (const client of this.connections) { for (const client of this.connections) {
users[client.userData._id] = client.userData users[client.userData._id] = client.userData
} }
return users return users
} }
} }