Skip to content

Commit 519c3c3

Browse files
committed
added new endpoint for marking the message as seen + added new field for the message model seenBy array holding the emails who seeing the message!
1 parent 5579cf8 commit 519c3c3

File tree

7 files changed

+176
-6
lines changed

7 files changed

+176
-6
lines changed

src/controllers/message.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,20 @@ export const deleteMessage = async (req, res, next) => {
5353
next(error);
5454
}
5555
};
56+
57+
export const markMessageAsSeen = async (req, res, next) => {
58+
try {
59+
const { email, chatID, messageID } = req.params;
60+
await authorize(req, res, next, email);
61+
await MessageService.markMessageAsSeen(email, chatID, messageID);
62+
return res
63+
.status(200)
64+
.json({
65+
body: null,
66+
message: "Message marked as seen successfully",
67+
status: 200,
68+
});
69+
} catch (error) {
70+
next(error);
71+
}
72+
};

src/db/models/message.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ const messageSchema = new Schema({
3636
type: Object,
3737
default: null,
3838
},
39+
seenBy: {
40+
type: [String],
41+
default: [],
42+
},
3943
},
4044
{ timestamps: true }
4145
);

src/helpers/sockets.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ dotenv.config();
44
export let loggedInUsers = []//{email: [array of socket ids]}
55
let io
66

7+
console.log(loggedInUsers);
78

89
const addLoggedInUser = (email, socketId) => {
910
const user = loggedInUsers.find(user => user.email === email)
@@ -43,10 +44,15 @@ export const socketConnection = (server) => {
4344

4445
socket.on("successfulLogin", ({ email }) => {
4546
addLoggedInUser(email, socket.id);
47+
console.log(loggedInUsers);
48+
4649
});
47-
socket.on("succesfulLogout", ({ email }) => {
50+
51+
socket.on("successfulLogout", ({ email }) => {
4852
removeLoggedInUser(email, socket.id);
53+
console.log(loggedInUsers);
4954
});
55+
5056
socket.on("disconnect", () => {
5157
loggedInUsers = loggedInUsers
5258
.map((user) => {
@@ -55,5 +61,28 @@ export const socketConnection = (server) => {
5561
})
5662
.filter((user) => user.socketId.length > 0);
5763
});
64+
65+
// // Handle message seen event
66+
// socket.on("messageSeen", ({ chatID, messageID, email }) => {
67+
// // Notify other users in the chat that the message has been seen
68+
// const user = loggedInUsers.find(user => user.email === email);
69+
// if (user) {
70+
// user.socketId.forEach((receiverSocket) => {
71+
// io.to(receiverSocket).emit("messageSeen", { chatID, messageID });
72+
// });
73+
// }
74+
// });
75+
76+
// // Handle typing status event
77+
// socket.on("typingStatus", ({ chatID, email, isTyping }) => {
78+
// // Broadcast typing status to other users in the chat
79+
// const user = loggedInUsers.find(user => user.email === email);
80+
// if (user) {
81+
// user.socketId.forEach((receiverSocket) => {
82+
// io.to(receiverSocket).emit("typingStatus", { chatID, email, isTyping });
83+
// });
84+
// }
85+
// });
86+
5887
});
5988
};

src/middlewares/validator/schemas/userSchema.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,23 @@ export const chatIDSchema = Joi.object({
204204
"string.empty": "Chat ID cannot be empty",
205205
"any.required": "Chat ID is required",
206206
}),
207+
});
208+
209+
export const markMessageAsSeenURLSchema = Joi.object({
210+
email: Joi.string().email().required().messages({
211+
"string.base": "Sender email must be a string",
212+
"string.empty": "Sender email cannot be empty",
213+
"string.email": "Sender email must be a valid email",
214+
"any.required": "Sender email is required",
215+
}),
216+
chatID: Joi.string().required().messages({
217+
"string.base": "Chat ID must be a string",
218+
"string.empty": "Chat ID cannot be empty",
219+
"any.required": "Chat ID is required",
220+
}),
221+
messageID: Joi.string().required().messages({
222+
"string.base": "Message ID must be a string",
223+
"string.empty": "Message ID cannot be empty",
224+
"any.required": "Message ID is required",
225+
}),
207226
});

src/routes/message.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,62 @@ router.delete(
151151
messageController.deleteMessage // Controller to handle the logic
152152
);
153153

154+
/**
155+
* @swagger
156+
* /mark-as-seen/{email}/{chatID}/{messageID}:
157+
* patch:
158+
* summary: Mark a message as seen in a chat
159+
* tags: [Messages]
160+
* parameters:
161+
* - in: path
162+
* name: email
163+
* schema:
164+
* type: string
165+
* required: true
166+
* description: Email of the user marking the message as seen
167+
* - in: path
168+
* name: chatID
169+
* schema:
170+
* type: string
171+
* required: true
172+
* description: ID of the chat containing the message
173+
* - in: path
174+
* name: messageID
175+
* schema:
176+
* type: string
177+
* required: true
178+
* description: ID of the message to mark as seen
179+
* responses:
180+
* 200:
181+
* description: Message marked as seen successfully
182+
* content:
183+
* application/json:
184+
* schema:
185+
* type: object
186+
* properties:
187+
* chatID:
188+
* type: string
189+
* description: ID of the chat
190+
* messageID:
191+
* type: string
192+
* description: ID of the message marked as seen
193+
* seenBy:
194+
* type: array
195+
* items:
196+
* type: string
197+
* description: List of users who have seen the message
198+
* 404:
199+
* description: Chat or message not found
200+
* 400:
201+
* description: Invalid input
202+
*/
203+
204+
// Route to handle marking a message as seen
205+
router.patch(
206+
"/mark-as-seen/:email/:chatID/:messageID",
207+
validate(schemas.markMessageAsSeenURLSchema, false), // Validate URL parameters
208+
messageController.markMessageAsSeen // Controller to handle the logic
209+
);
210+
154211
// Export the router to be used in the application
155212
export default router;

src/services/chat.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ export const addUserToGroupChat = async (adminEmail, userEmail, chatID) => {
105105
await chat.save();
106106
};
107107

108-
109108
export const getUserGroupChats = async (email, token) => {
110109
const user = await User.findOne({ email: email });
111110
if (!user)
@@ -118,7 +117,6 @@ export const getUserGroupChats = async (email, token) => {
118117
return chats;
119118
}
120119

121-
122120
export const getGroupChatDetails = async (id, token) => {
123121
// check if chat_id is valid mongoose
124122
if (!mongoose.isValidObjectId(id)) {
@@ -153,3 +151,23 @@ export const deleteGroupChat = async (adminEmail, chatID) => {
153151
await chat.deleteOne();
154152
await groupChat.deleteOne();
155153
};
154+
155+
export const updateTypingStatus = async (email, chatID, isTyping) => {
156+
// Validate the chat
157+
const chat = await Chat.findOne({ _id: chatID });
158+
if (!chat) {
159+
throw createCustomError("Chat not found!", 404, null);
160+
}
161+
162+
// Emit the "typingStatus" event to notify other users
163+
const receiversEmails = chat.users.filter((user) => user !== email);
164+
receiversEmails.forEach((receiverEmail) => {
165+
sockets.sendToOnlineReceivers(
166+
{ chatID, email, isTyping },
167+
receiverEmail,
168+
"typingStatus"
169+
);
170+
});
171+
172+
return { chatID, email, isTyping };
173+
};

src/services/message.js

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,36 @@ export const deleteMessage = async (senderEmail, chatID, messageID) => {
152152
await chat.save();
153153
};
154154

155-
const findMessageById = async (messageID) => {
156-
let message = await Message.findById(messageID).select("-__v -createdAt -updatedAt");
155+
export const markMessageAsSeen = async (email, chatID, messageID) => {
156+
157+
// Find the chat
158+
const chat = await Chat.findOne({ _id: chatID });
159+
160+
if (!chat) {
161+
throw createCustomError("Chat not found!", 404, null);
162+
}
163+
164+
// Find the message in the chat
165+
const message = chat.messages.find((msg) => msg._id.toString() === messageID);
166+
157167
if (!message) {
158168
throw createCustomError("Message not found!", 404, null);
159169
}
170+
171+
// Mark the message as seen
172+
if (!message.seenBy.includes(email)) {
173+
message.seenBy.push(email);
174+
}
175+
176+
// Save the updated chat
177+
await chat.save();
178+
179+
// Emit the "messageSeen" event to notify other users
180+
sockets.sendToOnlineReceivers(
181+
{ chatID, messageID },
182+
email,
183+
"messageSeen"
184+
);
185+
160186
return message;
161-
}
187+
};

0 commit comments

Comments
 (0)