diff --git a/apps/meteor/app/threads/server/functions.ts b/apps/meteor/app/threads/server/functions.ts index b747a8d5d9555..7906f33ba77b0 100644 --- a/apps/meteor/app/threads/server/functions.ts +++ b/apps/meteor/app/threads/server/functions.ts @@ -1,6 +1,6 @@ -import type { IMessage } from '@rocket.chat/core-typings'; +import type { IMessage, IRoom } from '@rocket.chat/core-typings'; import { isEditedMessage } from '@rocket.chat/core-typings'; -import { Messages, Subscriptions, ReadReceipts, NotificationQueue } from '@rocket.chat/models'; +import { Messages, Subscriptions, ReadReceipts, NotificationQueue, Rooms } from '@rocket.chat/models'; import { notifyOnSubscriptionChangedByRoomIdAndUserIds, @@ -8,57 +8,90 @@ import { } from '../../lib/server/lib/notifyListener'; import { getMentions, getUserIdsFromHighlights } from '../../lib/server/lib/notifyUsersOnMessage'; +const filterUsersInRoom = async ({ roomId, userIds, room }: { roomId: string; userIds: string[]; room: IRoom | null }) => { + if (!userIds.length || !room) { + return []; + } + + if (room.t === 'd') { + return userIds.filter((userId) => room.uids?.includes(userId)); + } + + if (room.t === 'p' || room.t === 'c') { + const subscriptions = await Subscriptions.findByRoomIdAndUserIds(roomId, userIds, { + projection: { u: 1 }, + }).toArray(); + + return subscriptions.map((sub) => sub.u._id); + } + + return []; +}; + export async function reply({ tmid }: { tmid?: string }, message: IMessage, parentMessage: IMessage, followers: string[]) { if (!tmid || isEditedMessage(message)) { return false; } const { rid, ts, u } = message; + const room = await Rooms.findOneById(rid); const { toAll, toHere, mentionIds } = await getMentions(message); - const addToReplies = [ - ...new Set([ - ...followers, - ...mentionIds, - ...(Array.isArray(parentMessage.replies) && parentMessage.replies.length ? [u._id] : [parentMessage.u._id, u._id]), - ]), - ]; - - await Messages.updateRepliesByThreadId(tmid, addToReplies, ts); - const [highlightsUids, threadFollowers] = await Promise.all([ getUserIdsFromHighlights(rid, message), Messages.getThreadFollowsByThreadId(tmid), ]); - const threadFollowersUids = threadFollowers?.filter((userId) => userId !== u._id && !mentionIds.includes(userId)) || []; + const [followersInRoom, mentionIdsInRoom, highlightsUidsInRoom, threadFollowersInRoom] = await Promise.all([ + filterUsersInRoom({ roomId: rid, userIds: followers, room }), + filterUsersInRoom({ roomId: rid, userIds: mentionIds, room }), + filterUsersInRoom({ roomId: rid, userIds: highlightsUids, room }), + filterUsersInRoom({ roomId: rid, userIds: threadFollowers || [], room }), + ]); + + const baseReplyUsers = Array.isArray(parentMessage.replies) && parentMessage.replies.length ? [u._id] : [parentMessage.u._id, u._id]; + + const baseReplyUsersInRoom = await filterUsersInRoom({ + roomId: rid, + userIds: baseReplyUsers, + room, + }); + + const addToReplies = [...new Set([...followersInRoom, ...mentionIdsInRoom, ...baseReplyUsersInRoom])]; + + await Messages.updateRepliesByThreadId(tmid, addToReplies, ts); + + const threadFollowersUids = threadFollowersInRoom.filter((userId) => userId !== u._id && !mentionIdsInRoom.includes(userId)); - // Notify everyone involved in the thread const notifyOptions = toAll || toHere ? { groupMention: true } : {}; - // Notify message mentioned users and highlights - const mentionedUsers = [...new Set([...mentionIds, ...highlightsUids])]; + // Notify everyone involved in the thread + const mentionedUsers = [...new Set([...mentionIdsInRoom, ...highlightsUidsInRoom])]; - const promises = [ + const promises: Promise[] = [ ReadReceipts.setAsThreadById(tmid), Subscriptions.addUnreadThreadByRoomIdAndUserIds(rid, threadFollowersUids, tmid, notifyOptions), ]; if (mentionedUsers.length) { - promises.push(Subscriptions.addUnreadThreadByRoomIdAndUserIds(rid, mentionedUsers, tmid, { userMention: true })); + promises.push( + Subscriptions.addUnreadThreadByRoomIdAndUserIds(rid, mentionedUsers, tmid, { + userMention: true, + }), + ); } - if (highlightsUids.length) { + if (highlightsUidsInRoom.length) { promises.push( - Subscriptions.setAlertForRoomIdAndUserIds(rid, highlightsUids), - Subscriptions.setOpenForRoomIdAndUserIds(rid, highlightsUids), + Subscriptions.setAlertForRoomIdAndUserIds(rid, highlightsUidsInRoom), + Subscriptions.setOpenForRoomIdAndUserIds(rid, highlightsUidsInRoom), ); } await Promise.allSettled(promises); - void notifyOnSubscriptionChangedByRoomIdAndUserIds(rid, [...threadFollowersUids, ...mentionedUsers, ...highlightsUids]); + void notifyOnSubscriptionChangedByRoomIdAndUserIds(rid, [...threadFollowersUids, ...mentionedUsers, ...highlightsUidsInRoom]); } export async function follow({ tmid, uid }: { tmid: string; uid: string }) {