Spaces:
Runtime error
Runtime error
Download apps/server/src/modules/chat/chat.socket.js from moustafa7/flwo: direct link, hf CLI and curl.
- Browser
- Download file 2.62 kB
-
https://huggingface.co/spaces/moustafa7/flwo/resolve/main/apps/server/src/modules/chat/chat.socket.js
- Command line
-
hf download hf://spaces/moustafa7/flwo/apps/server/src/modules/chat/chat.socket.js
-
curl -L -o chat.socket.js https://huggingface.co/spaces/moustafa7/flwo/resolve/main/apps/server/src/modules/chat/chat.socket.js
2.62 kB
| import { prisma } from '../../config/database.js' | |
| import { saveMessage } from './chat.service.js' | |
| import { STAFF_ROLES } from '../../lib/constants.js' | |
| import { handleClientMessage } from './bot.service.js' | |
| const msgRateLimiter = new Map() | |
| function checkMsgRateLimit(userId) { | |
| const now = Date.now() | |
| const history = (msgRateLimiter.get(userId) || []).filter(t => now - t < 60000) | |
| if (history.length >= 30) return false | |
| msgRateLimiter.set(userId, [...history, now]) | |
| return true | |
| } | |
| setInterval(() => msgRateLimiter.clear(), 5 * 60 * 1000) | |
| export function setupChatSocket(io) { | |
| io.on('connection', (socket) => { | |
| const userId = socket.userId | |
| if (!userId) return socket.disconnect() | |
| socket.join(`user:${userId}`) | |
| socket.on('chat:join', async (conversationId) => { | |
| try { | |
| const conversation = await prisma.conversation.findUnique({ | |
| where: { id: conversationId }, | |
| include: { order: { select: { userId: true } } } | |
| }) | |
| if (!conversation) return | |
| const isAdmin = STAFF_ROLES.includes(socket.userRole) | |
| const isOwner = conversation.order?.userId === userId | |
| const isClient = conversation.clientId === userId | |
| if (isAdmin || isOwner || isClient) { | |
| socket.join(`conversation:${conversationId}`) | |
| } | |
| } catch { /* silently fail */ } | |
| }) | |
| socket.on('chat:message', async (data) => { | |
| try { | |
| if (!checkMsgRateLimit(userId)) return | |
| const { conversationId, content } = data || {} | |
| if (!content?.trim() || typeof content !== 'string') return | |
| if (content.length > 2000) return | |
| const { message, ownerId } = await saveMessage(conversationId, userId, content.trim()) | |
| io.to(`conversation:${conversationId}`).emit('chat:newMessage', message) | |
| if (ownerId !== userId) { | |
| io.to(`user:${ownerId}`).emit('chat:newMessage', message) | |
| } | |
| // ูู ุงูู ุฑุณู ุนู ูู (ู ุด ุฃุฏู ู) โ ุดูู ูู ู ุญุชุงุฌ ุฑุฏ ุชููุงุฆู | |
| if (!STAFF_ROLES.includes(socket.userRole)) { | |
| const botMsg = await handleClientMessage(conversationId, content.trim()) | |
| if (botMsg) { | |
| io.to(`conversation:${conversationId}`).emit('chat:newMessage', botMsg) | |
| } | |
| } | |
| } catch { /* fail silently */ } | |
| }) | |
| socket.on('typing', ({ conversationId, isTyping }) => { | |
| if (!conversationId) return | |
| const room = socket.rooms?.has(`conversation:${conversationId}`) | |
| if (!room) return | |
| socket.to(`conversation:${conversationId}`).emit('typing', { userId, isTyping }) | |
| }) | |
| }) | |
| } | |