From 6c685f5f0dee754426e84c3473374bdf88d28148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=AC=EC=9E=AC=EC=97=BD?= <jysim0326@ajou.ac.kr> Date: Tue, 19 Nov 2024 18:18:38 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=B1=84=ED=8C=85=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- services/chatService.js | 149 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 services/chatService.js diff --git a/services/chatService.js b/services/chatService.js new file mode 100644 index 0000000..4135d15 --- /dev/null +++ b/services/chatService.js @@ -0,0 +1,149 @@ +const ChatRoom = require('../models/chatRooms'); +const { v4: uuidv4 } = require('uuid'); + +class ChatService { + + // 채팅방 생성 + async createChatRoom({ meeting_id, participants }) { + try { + const chatRoomId = uuidv4(); + const newRoom = new ChatRoom({ + chatRoomId: chatRoomId, + meeting_id, + participants, + messages: [], + lastReadAt: participants.reduce((acc, user) => { + acc[user] = new Date(); + return acc; + }, {}), + lastReadLogId: participants.reduce((acc, user) => { + acc[user] = null; + return acc; + }, {}), + isOnline: participants.reduce((acc, user) => { + acc[user] = true; + return acc; + }, {}), + }); + + const joinMessage = { + message: `${participants[0]}님이 번개 모임을 생성했습니다.`, + timestamp: new Date(), + type: 'join', + }; + + newRoom.messages.push(joinMessage); + await newRoom.save(); + + return { success: true, chatRoomId }; + } catch (err) { + console.error('Error creating chat room:', err); + throw new Error('Failed to create chat room'); + } + } + + // 채팅방 목록 조회 + async getChatRooms() { + const rooms = await ChatRoom.find({}, { chatRoomId: 1, messages: { $slice: -1 } }); + return rooms.map(room => { + const lastMessage = room.messages[0] || {}; + return { + chatRoomId: room.chatRoomId, + lastMessage: { + sender: lastMessage.sender || '없음', + message: lastMessage.message || '메시지 없음', + timestamp: lastMessage.timestamp || null, + } + }; + }); + } + + // 사용자 상태 업데이트 + async updateStatus(chatRoomId, nickname, isOnline) { + await ChatRoom.updateOne( + { chatRoomId }, + { $set: { [`isOnline.${nickname}`]: isOnline } } + ); + } + + // 읽음 상태 업데이트 + async updateReadStatus(chatRoomId, nickname) { + const now = new Date(); + await ChatRoom.updateOne( + { chatRoomId }, + { $set: { [`lastReadAt.${nickname}`]: now } } + ); + } + + // 읽지 않은 메시지 조회 + async getUnreadMessages(nickname) { + const chatRooms = await ChatRoom.find({ participants: nickname }); + return await Promise.all(chatRooms.map(async (chatRoom) => { + const lastReadAt = chatRoom.lastReadAt.get(nickname) || new Date(0); + const unreadMessagesCount = chatRoom.messages.filter(message => + message.timestamp > lastReadAt + ).length; + return { + chatRoomId: chatRoom.chatRoomId, + unreadCount: unreadMessagesCount, + }; + })); + } + + // 읽지 않은 메시지 수 조회 + async getUnreadCount(chatRoomId) { + const chatRoom = await ChatRoom.findOne({ chatRoomId }); + if (!chatRoom) { + throw new Error('Chat room not found'); + } + + const unreadCounts = chatRoom.participants + .filter(user => chatRoom.lastReadLogId.get(user)) + .map(user => chatRoom.lastReadLogId.get(user)) + .reduce((acc, logId) => { + acc[logId] = (acc[logId] || 0) + 1; + return acc; + }, {}); + + let count = 0; + return Object.entries(unreadCounts) + .sort(([logId1], [logId2]) => logId1.localeCompare(logId2)) + .reduce((acc, [logId, value]) => { + count += value; + acc[count] = logId; + return acc; + }, {}); + } + + // 읽은 메시지 로그 ID 업데이트 + async updateReadLogId(chatRoomId, nickname, logId) { + await ChatRoom.updateOne( + { chatRoomId }, + { $set: { [`lastReadLogId.${nickname}`]: logId } } + ); + } + + // 상태와 로그 ID 동시 업데이트 + async updateStatusAndLogId(chatRoomId, nickname, isOnline, logId) { + let finalLogId = logId; + + if (!isOnline && logId === null) { + const chatRoom = await ChatRoom.findOne({ chatRoomId }); + if (chatRoom && chatRoom.messages.length > 0) { + finalLogId = chatRoom.messages[chatRoom.messages.length - 1]._id; + } + } + + await ChatRoom.updateOne( + { chatRoomId }, + { + $set: { + [`isOnline.${nickname}`]: isOnline, + [`lastReadLogId.${nickname}`]: isOnline ? null : finalLogId, + }, + } + ); + } +} + +module.exports = new ChatService(); -- GitLab