"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handleConnection = void 0; const database_js_1 = require("../config/database.js"); const rateLimiter_js_1 = require("../middleware/rateLimiter.js"); const chatService_js_1 = require("../services/chatService.js"); const messageService_js_1 = require("../services/messageService.js"); const handleConnection = async (io, socket) => { console.log(`User connected: ${socket.user.username} (${socket.user.id})`); await updateUserOnlineStatus(socket.userId, true); const onlineUsers = await database_js_1.prisma.user.findMany({ where: { isOnline: true }, select: { id: true, username: true }, }); socket.emit("online_users", onlineUsers); await joinUserRooms(socket); socket.on("send_message", (data) => handleSendMessage(io, socket, data)); socket.on("delete_message", (data) => handleDeleteMessage(io, socket, data)); socket.on("react_to_message", (data) => handleReactToMessage(io, socket, data)); socket.on("typing_start", (data) => handleTypingStart(io, socket, data)); socket.on("typing_stop", (data) => handleTypingStop(io, socket, data)); socket.on("join_room", (roomId) => handleJoinRoom(socket, roomId)); socket.on("leave_room", (roomId) => handleLeaveRoom(socket, roomId)); socket.on("messages_seen", (data) => handleMessagesSeen(io, socket, data)); socket.on("disconnect", () => handleDisconnect(socket)); }; exports.handleConnection = handleConnection; const handleTypingStart = async (io, socket, data) => { try { const isMember = await chatService_js_1.ChatService.checkRoomMembership(socket.userId, data.roomId); if (!isMember) return; io.to(data.roomId).emit("user_typing", { roomId: data.roomId, username: data.username, }); } catch (error) { console.error(`Error handling typing start: ${error}`); } }; const handleTypingStop = async (io, socket, data) => { try { const isMember = await chatService_js_1.ChatService.checkRoomMembership(socket.userId, data.roomId); if (!isMember) return; io.to(data.roomId).emit("user_stopped_typing", { roomId: data.roomId, username: data.username, }); } catch (error) { console.error(`Error handling typing stop: ${error}`); } }; const updateUserOnlineStatus = async (userId, isOnline) => { try { await database_js_1.prisma.user.update({ where: { id: userId }, data: { isOnline, lastSeen: new Date(), }, }); } catch (error) { console.error(`Error updating user online status: ${error}`); } }; const joinUserRooms = async (socket) => { try { const userRooms = await database_js_1.prisma.chatRoomMember.findMany({ where: { userId: socket.userId }, include: { room: true }, }); userRooms.forEach(async (member) => { await socket.join(member.roomId); socket.to(member.roomId).emit("user_online", { userId: socket.userId, username: socket.user.username, }); }); } catch (error) { console.error(`Error joining user rooms: ${error}`); } }; const handleSendMessage = async (io, socket, data) => { try { if (!data.roomId) { socket.emit("error", { message: "Room ID is required to send a message" }); return; } if (data.image && data.image.length > 2 * 1024 * 1024) { socket.emit("error", { message: "Image size exceeds 2MB limit" }); return; } if (!data.content && !data.image) { socket.emit("error", { message: "Message cannot be empty" }); return; } if (!(0, rateLimiter_js_1.checkMessageRateLimit)(socket)) return; const isMember = await chatService_js_1.ChatService.checkRoomMembership(socket.userId, data.roomId); if (!isMember) { socket.emit("error", { message: "Not authorized to send messages to this room" }); return; } const result = await messageService_js_1.MessageService.sendMessage(socket.userId, data); if (result.success) { io.to(data.roomId).emit("new_message", result.data); io.to(data.roomId).emit("user_stopped_typing", { roomId: data.roomId, username: socket.user.username, }); } else { socket.emit("error", { message: "Failed to send message" }); } } catch (error) { console.error(`Error handling send message: ${error}`); socket.emit("error", { message: "Failed to send message" }); } }; const handleDeleteMessage = async (io, socket, data) => { try { const result = await messageService_js_1.MessageService.deleteMessage(socket.userId, data.messageId, data.roomId); if (result.success) { io.to(data.roomId).emit("message_deleted", { messageId: data.messageId, roomId: data.roomId, }); } else { socket.emit("error", { message: result.error }); } } catch (error) { console.error(`Error handling delete message: ${error}`); socket.emit("error", { message: "Failed to delete message" }); } }; const handleReactToMessage = async (io, socket, data) => { try { const result = await messageService_js_1.MessageService.reactToMessage(socket.userId, data); if (result.success) { const message = await database_js_1.prisma.message.findUnique({ where: { id: data.messageId }, select: { roomId: true }, }); if (message) { io.to(message.roomId).emit("message_reaction_updated", result.data); } } else { socket.emit("error", { message: result.error }); } } catch (error) { console.error(`Error handling react to message: ${error}`); socket.emit("error", { message: "Failed to react to message" }); } }; const handleMessagesSeen = async (io, socket, data) => { try { const isMember = await chatService_js_1.ChatService.checkRoomMembership(socket.userId, data.roomId); if (!isMember) { socket.emit("error", { message: "Not authorized to access this room" }); return; } const messagesInRoom = await database_js_1.prisma.message.findMany({ where: { id: { in: data.messageIds }, roomId: data.roomId, }, }); const validMessageIds = messagesInRoom.map((msg) => msg.id); if (validMessageIds.length === 0) return; const result = await messageService_js_1.MessageService.markMessagesAsSeen(socket.userId, validMessageIds); if (result.success && result.data) { for (const item of result.data) { io.to(data.roomId).emit("message_seen_update", { messageId: item.messageId, seenBy: item.seenBy, }); } } } catch (error) { console.error(`Error handling messages seen: ${error}`); socket.emit("error", { message: "Failed to mark messages as seen" }); } }; const handleJoinRoom = async (socket, roomId) => { await socket.join(roomId); }; const handleLeaveRoom = async (socket, roomId) => { await socket.leave(roomId); }; const handleDisconnect = async (socket) => { console.log(`User disconnected: ${socket.user.username}`); await updateUserOnlineStatus(socket.userId, false); try { const userRooms = await database_js_1.prisma.chatRoomMember.findMany({ where: { userId: socket.userId, }, }); userRooms.forEach((member) => { socket.to(member.roomId).emit("user_offline", { userId: socket.userId, username: socket.user.username, }); socket.to(member.roomId).emit("user_stopped_typing", { roomId: member.roomId, username: socket.user.username, }); }); } catch (error) { console.error(`Error handling user disconnect: ${error}`); } };