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