Skip to content
Snippets Groups Projects
Commit 72516146 authored by 심재엽's avatar 심재엽
Browse files

refactor: fcm 채팅 푸시 알림 추가, 메시지 읽음 수 확인 로직 수정

parent acaba97c
No related branches found
No related tags found
2 merge requests!31Develop,!25[#17] 채팅 푸시알림 추가
......@@ -2,58 +2,46 @@ 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',
};
async createChatRoom({ meeting_id, participants, chatRoomName }) {
try {
const chatRoomId = uuidv4();
const newRoom = new ChatRoom({
chatRoomId,
chatRoomName,
meeting_id,
messages: [],
});
newRoom.messages.push(joinMessage);
await newRoom.save();
const joinMessage = {
message: `${participants[0].name}님이 번개 모임을 생성했습니다.`,
timestamp: new Date(),
type: 'join',
};
return { success: true, chatRoomId };
} catch (err) {
console.error('Error creating chat room:', err);
throw new Error('Failed to create chat room');
}
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 } });
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,
chatRoomName: room.chatRoomName,
lastMessage: {
sender: lastMessage.sender || '없음',
message: lastMessage.message || '메시지 없음',
timestamp: lastMessage.timestamp || null,
}
},
};
});
}
......@@ -61,7 +49,7 @@ class ChatService {
// 사용자 상태 업데이트
async updateStatus(chatRoomId, nickname, isOnline) {
await ChatRoom.updateOne(
{ chatRoomId },
{ chatRoomId, "participants.name": nickname },
{ $set: { [`isOnline.${nickname}`]: isOnline } }
);
}
......@@ -70,14 +58,14 @@ class ChatService {
async updateReadStatus(chatRoomId, nickname) {
const now = new Date();
await ChatRoom.updateOne(
{ chatRoomId },
{ chatRoomId, "participants.name": nickname },
{ $set: { [`lastReadAt.${nickname}`]: now } }
);
}
// 읽지 않은 메시지 조회
async getUnreadMessages(nickname) {
const chatRooms = await ChatRoom.find({ participants: 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 =>
......@@ -98,31 +86,49 @@ class ChatService {
}
const unreadCounts = chatRoom.participants
.filter(user => chatRoom.lastReadLogId.get(user))
.map(user => chatRoom.lastReadLogId.get(user))
.filter(participant => chatRoom.lastReadLogId.has(participant.name)) // Map에 존재하는 키만 처리
.map(participant => chatRoom.lastReadLogId.get(participant.name)) // lastReadLogId 값 추출
.reduce((acc, logId) => {
acc[logId] = (acc[logId] || 0) + 1;
acc[logId] = (acc[logId] || 0) + 1; // logId 기준으로 등장 횟수 누적
return acc;
}, {});
let count = 0;
return Object.entries(unreadCounts)
.sort(([logId1], [logId2]) => logId1.localeCompare(logId2))
const sortedUnreadCounts = Object.entries(unreadCounts)
.sort(([logId1], [logId2]) => logId1.localeCompare(logId2)) // logId 기준 오름차순 정렬
.reduce((acc, [logId, value]) => {
count += value;
acc[count] = logId;
count += value; // 누적 합계
acc[count] = logId; // 누적 합계를 키로 저장
return acc;
}, {});
return sortedUnreadCounts;
}
// 읽은 메시지 로그 ID 업데이트
async updateReadLogId(chatRoomId, nickname, logId) {
await ChatRoom.updateOne(
{ chatRoomId },
{ 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;
......@@ -135,7 +141,7 @@ class ChatService {
}
await ChatRoom.updateOne(
{ chatRoomId },
{ chatRoomId, "participants.name": nickname },
{
$set: {
[`isOnline.${nickname}`]: isOnline,
......@@ -144,6 +150,65 @@ class ChatService {
}
);
}
// 메시지 전송
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');
}
}
}
module.exports = new ChatService();
module.exports = new ChatService();
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment