Newer
Older
const ChatRoom = require('../models/chatRooms');
const { v4: uuidv4 } = require('uuid');
class ChatService {
// 채팅방 생성
async createChatRoom({ meeting_id, participants, chatRoomName }) {
try {
const chatRoomId = uuidv4();
const newRoom = new ChatRoom({
chatRoomId,
chatRoomName,
meeting_id,
messages: [],
});
const joinMessage = {
message: `${participants[0].name}님이 번개 모임을 생성했습니다.`,
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');
const rooms = await ChatRoom.find({}, { chatRoomId: 1, chatRoomName: 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, "participants.name": nickname },
{ $set: { [`isOnline.${nickname}`]: isOnline } }
);
}
// 읽음 상태 업데이트
async updateReadStatus(chatRoomId, nickname) {
const now = new Date();
await ChatRoom.updateOne(
{ chatRoomId, "participants.name": nickname },
{ $set: { [`lastReadAt.${nickname}`]: now } }
);
}
// 읽지 않은 메시지 조회
async getUnreadMessages(nickname) {
const chatRooms = await ChatRoom.find({ "participants.name": 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(participant => chatRoom.lastReadLogId.has(participant.name)) // Map에 존재하는 키만 처리
.map(participant => chatRoom.lastReadLogId.get(participant.name)) // lastReadLogId 값 추출
acc[logId] = (acc[logId] || 0) + 1; // logId 기준으로 등장 횟수 누적
const sortedUnreadCounts = Object.entries(unreadCounts)
.sort(([logId1], [logId2]) => logId1.localeCompare(logId2)) // logId 기준 오름차순 정렬
count += value; // 누적 합계
acc[count] = logId; // 누적 합계를 키로 저장
}
// 읽은 메시지 로그 ID 업데이트
async updateReadLogId(chatRoomId, nickname, logId) {
await ChatRoom.updateOne(
{ chatRoomId, "participants.name": nickname },
{ $set: { [`lastReadLogId.${nickname}`]: logId } }
);
}
// FCM 토큰 업데이트
async updateFcmToken(chatRoomId, nickname, fcmToken) {
const chatRoom = await ChatRoom.findOne({ chatRoomId, "participants.name": nickname });
if (!chatRoom) {
throw new Error('Chat room or participant not found');
}
const participant = chatRoom.participants.find(p => p.name === nickname);
if (participant) {
if (!participant.fcmTokens.includes(fcmToken)) {
participant.fcmTokens.push(fcmToken);
await chatRoom.save();
}
}
}
// 상태와 로그 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, "participants.name": nickname },
{
$set: {
[`isOnline.${nickname}`]: isOnline,
[`lastReadLogId.${nickname}`]: isOnline ? null : finalLogId,
},
}
);
}
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// 메시지 전송
async sendMessage(chatRoomId, sender, messageContent) {
try {
// 채팅방 조회
const chatRoom = await ChatRoom.findOne({ chatRoomId });
if (!chatRoom) {
throw new Error('Chat room not found');
}
// 메시지 추가
const newMessage = {
sender,
message: messageContent,
timestamp: new Date(),
type: 'message',
};
chatRoom.messages.push(newMessage);
await chatRoom.save();
// 오프라인 사용자 찾기
const offlineParticipants = chatRoom.participants.filter(
participant => !chatRoom.isOnline[participant.name]
);
// 오프라인 사용자들에게 FCM 푸시 알림 전송
for (const participant of offlineParticipants) {
const tokens = participant.fcmTokens || [];
if (tokens.length > 0) {
const message = {
notification: {
title: `새 메시지: ${chatRoom.chatRoomName}`,
body: `${sender}: ${messageContent}`,
},
tokens,
};
try {
const response = await admin.messaging().sendMulticast(message);
console.log(
`푸시 알림 전송 성공 (${participant.name}):`,
response.successCount
);
} catch (error) {
console.error(
`푸시 알림 전송 실패 (${participant.name}):`,
error
);
}
}
}
return newMessage;
} catch (error) {
console.error('Error sending message:', error);
throw new Error('Failed to send message');
}
}