Skip to content

Commit

Permalink
Merge pull request #305 from sparcs-kaist/#273-안-읽은-메세지-확인
Browse files Browse the repository at this point in the history
#270 안 읽은 메세지 확인
  • Loading branch information
chlehdwon authored Sep 24, 2023
2 parents cffb806 + 9bdbbc4 commit c5cf10a
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/modules/auths/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const login = (req, sid, id, oid, name) => {
const logout = (req) => {
// 로그아웃 전 socket.io 소켓들 연결부터 끊기
const io = req.app.get("io");
if (io) io.in(req.session.id).disconnectSockets(true);
if (io) io.in(`session-${req.session.id}`).disconnectSockets(true);

req.session.destroy((err) => {
if (err) logger.error(err);
Expand Down
5 changes: 3 additions & 2 deletions src/modules/populates/rooms.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const roomPopulateOption = [
{ path: "to", select: "_id koName enName" },
{
path: "part",
select: "-_id user settlementStatus",
select: "-_id user settlementStatus readAt",
populate: { path: "user", select: "_id id name nickname profileImageUrl" },
},
];
Expand All @@ -29,13 +29,14 @@ const formatSettlement = (
roomObject.part = roomObject.part.map((participantSubDocument) => {
const { _id, name, nickname, profileImageUrl } =
participantSubDocument.user;
const { settlementStatus } = participantSubDocument;
const { settlementStatus, readAt } = participantSubDocument;
return {
_id,
name,
nickname,
profileImageUrl,
isSettlement: includeSettlement ? settlementStatus : undefined,
readAt: readAt ?? roomObject.madeat,
};
});
roomObject.settlementTotal = includeSettlement
Expand Down
25 changes: 25 additions & 0 deletions src/modules/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,30 @@ const emitChatEvent = async (io, chat) => {
}
};

const emitUpdateEvent = async (io, roomId) => {
try {
// 방의 모든 사용자에게 socket 메세지 업데이트 이벤트를 발생시킵니다.
if (!io || !roomId) {
throw new IllegalArgumentsException();
}

const { name, part } = await roomModel.findById(roomId, "name part");

if (!name || !part) {
throw new IllegalArgumentsException();
}

part.forEach(({ user }) => io.in(`user-${user}`).emit("chat_update"), {
roomId,
});

return true;
} catch (err) {
logger.error(err);
return false;
}
};

// https://socket.io/how-to/use-with-express-session 참고
const startSocketServer = (server) => {
const io = new Server(server, {
Expand Down Expand Up @@ -266,5 +290,6 @@ const startSocketServer = (server) => {
module.exports = {
transformChatsForRoom,
emitChatEvent,
emitUpdateEvent,
startSocketServer,
};
2 changes: 2 additions & 0 deletions src/modules/stores/mongo.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const participantSchema = Schema({
enum: ["not-departed", "paid", "send-required", "sent"],
default: "not-departed",
},
readAt: { type: Date },
});

const deviceTokenSchema = Schema({
Expand Down Expand Up @@ -118,6 +119,7 @@ const locationSchema = Schema({
latitude: { type: Number }, // 이후 required: true 로 수정 필요
longitude: { type: Number }, // 이후 required: true 로 수정 필요
});

const chatSchema = Schema({
roomId: { type: Schema.Types.ObjectId, ref: "Room", required: true },
type: {
Expand Down
11 changes: 11 additions & 0 deletions src/routes/chats.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ router.post(
chatsHandlers.sendChatHandler
);

/**
* 채팅 읽은 시각 업데이트 요청을 처리합니다.
* 같은 방에 있는 user들에게 업데이트를 요청합니다.
*/
router.post(
"/read",
body("roomId").isMongoId(),
validator,
chatsHandlers.readChatHandler
);

// 채팅 이미지를 업로드할 수 있는 Presigned-url을 발급합니다.
router.post(
"/uploadChatImg/getPUrl",
Expand Down
53 changes: 52 additions & 1 deletion src/services/chats.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const { chatModel, userModel, roomModel } = require("../modules/stores/mongo");
const { chatPopulateOption } = require("../modules/populates/chats");
const { roomPopulateOption } = require("../modules/populates/rooms");
const aws = require("../modules/stores/aws");
const { transformChatsForRoom, emitChatEvent } = require("../modules/socket");
const {
transformChatsForRoom,
emitChatEvent,
emitUpdateEvent,
} = require("../modules/socket");
const logger = require("../modules/logger");

const chatCount = 60;
Expand Down Expand Up @@ -170,6 +175,51 @@ const sendChatHandler = async (req, res) => {
}
};

const readChatHandler = async (req, res) => {
try {
const io = req.app.get("io");
const { userId } = req;
const { roomId } = req.body;
const user = await userModel.findOne({ id: userId });

if (!userId || !user) {
return res.status(500).send("Chat/read : internal server error");
}
if (!io) {
return res.status(403).send("Chat/read : socket did not connected");
}

const roomObject = await roomModel
.findOneAndUpdate(
{
_id: roomId,
part: {
$elemMatch: {
user: user._id,
},
},
},
{
$set: { "part.$[updater].readAt": req.timestamp },
},
{
new: true,
arrayFilters: [{ "updater.user": { $eq: user._id } }],
}
)
.lean();

if (!roomObject) {
return res.status(404).send("Chat/read : cannot find room info");
}

if (await emitUpdateEvent(io, roomId)) res.json({ result: true });
else res.status(500).send("Chat/read : failed to emit socket events");
} catch (e) {
res.status(500).send("Chat/read : internal server error");
}
};

const uploadChatImgGetPUrlHandler = async (req, res) => {
try {
const { type, roomId } = req.body;
Expand Down Expand Up @@ -284,4 +334,5 @@ module.exports = {
sendChatHandler,
uploadChatImgGetPUrlHandler,
uploadChatImgDoneHandler,
readChatHandler,
};

0 comments on commit c5cf10a

Please sign in to comment.