Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2e68af4
refactor: migrate notifyUsersOnMessage to typescript
ricardogarim Mar 1, 2024
f6ad177
refactor: remove useless loops on beforeGetMentions
ricardogarim Mar 1, 2024
6835ee6
refactor: rename beforeGetMentions to beforeGetTeamMentions
ricardogarim Mar 1, 2024
edee67b
chore: remove unnecessary comment
ricardogarim Mar 4, 2024
60aac2c
fix: add type importing on interfaces and types loading
ricardogarim Mar 4, 2024
2c18390
fix: isolate teamsMentions into a new array filter
ricardogarim Mar 4, 2024
08111f5
chore: add UnreadCountType type checking
ricardogarim Mar 4, 2024
a6d0be8
chore: update setLastReplyForRoomIdAndUserIds signature to comply wit…
ricardogarim Mar 4, 2024
359e5dc
chore: update notifyUsersOnMessage message input type from IMessage t…
ricardogarim Mar 4, 2024
f263593
chore: update incMsgCountAndSetLastMessageById signature to accept me…
ricardogarim Mar 4, 2024
24287f1
chore: update getMentionedTeamMembers signature
ricardogarim Mar 4, 2024
8692b50
chore: update updateThreadUsersSubscriptions and notifyUsersOnReply s…
ricardogarim Mar 4, 2024
df50912
fix: add message related imports to fix packages building
ricardogarim Mar 4, 2024
5f39dfc
fix: eslint and typecheck minors
ricardogarim Mar 4, 2024
500a401
Merge branch 'develop' into refactor/migrate-notifyUsersOnMessage-to-…
Mar 5, 2024
3465796
chore: add callback beforeGetTeamMentions types definition
ricardogarim Mar 5, 2024
ebae2c9
fix: rewrite beforeGetTeamMentions length check and remove useless ty…
ricardogarim Mar 6, 2024
1575b2a
revert: changes out of js > ts migration scope
ricardogarim Mar 6, 2024
e902254
undo some changes
sampaiodiego Mar 7, 2024
cfac4bf
Merge branch 'develop' into refactor/migrate-notifyUsersOnMessage-to-…
ricardogarim Mar 7, 2024
31ccfce
Merge branch 'develop' into refactor/migrate-notifyUsersOnMessage-to-…
ricardogarim Mar 7, 2024
2781ec8
Merge branch 'develop' into refactor/migrate-notifyUsersOnMessage-to-…
ricardogarim Mar 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
import moment from 'moment';

import type { IMessage, IRoom, RoomType } from '@rocket.chat/core-typings';
import { Subscriptions, Rooms } from '@rocket.chat/models';
import { escapeRegExp } from '@rocket.chat/string-helpers';
import moment from 'moment';

import { callbacks } from '../../../../lib/callbacks';
import { settings } from '../../../settings/server';

/**
* Chechs if a messages contains a user highlight
*
* @param {string} message
* @param {array|undefined} highlights
*
* @returns {boolean}
*/
function messageContainsHighlight(message, highlights) {
if (!highlights || highlights.length === 0) {
return false;
}
function messageContainsHighlight(message: IMessage, highlights: string[]): boolean {
if (!highlights || highlights.length === 0) return false;

return highlights.some((highlight) => {
return highlights.some((highlight: string) => {
const regexp = new RegExp(escapeRegExp(highlight), 'i');
return regexp.test(message.msg);
});
}

export async function getMentions(message) {
export async function getMentions(message: IMessage): Promise<{ toAll: boolean; toHere: boolean; mentionIds: string[] }> {
const {
mentions,
u: { _id: senderId },
Expand All @@ -41,16 +33,19 @@ export async function getMentions(message) {
const toAll = mentions.some(({ _id }) => _id === 'all');
const toHere = mentions.some(({ _id }) => _id === 'here');

const userMentions = mentions.filter((mention) => !mention.type || mention.type === 'user');
const otherMentions = mentions.filter((mention) => mention?.type !== 'user');

const filteredMentions = userMentions.filter(({ _id }) => _id !== senderId && !['all', 'here'].includes(_id)).map(({ _id }) => _id);

const mentionIds = await callbacks.run('beforeGetMentions', filteredMentions, {
userMentions,
otherMentions,
message,
});
let teamsMentions = [] as any[];
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
const filteredMentions = mentions
.filter((mention) => {
if (mention.type === 'team') { teamsMentions.push(mention); }
return !mention.type || mention.type === 'user';
})
.filter(({ _id }) => _id !== senderId && !['all', 'here'].includes(_id))
.map(({ _id }) => _id);

let mentionIds = filteredMentions;
if (teamsMentions.length > 0) {
mentionIds = await callbacks.run('beforeGetTeamMentions', filteredMentions, teamsMentions);
}

return {
toAll,
Expand All @@ -59,52 +54,40 @@ export async function getMentions(message) {
};
}

const incGroupMentions = async (rid, roomType, excludeUserId, unreadCount) => {
const incGroupMentions = async (rid: string, roomType: RoomType, excludeUserId: string, unreadCount: string): Promise<void> => {
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
const incUnreadByGroup = ['all_messages', 'group_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByGroup ? 1 : 0;

await Subscriptions.incGroupMentionsAndUnreadForRoomIdExcludingUserId(rid, excludeUserId, 1, incUnread);
};

const incUserMentions = async (rid, roomType, uids, unreadCount) => {
const incUserMentions = async (rid: string, roomType: RoomType, uids: string[], unreadCount: string): Promise<void> => {
const incUnreadByUser = ['all_messages', 'user_mentions_only', 'user_and_group_mentions_only'].includes(unreadCount);
const incUnread = roomType === 'd' || roomType === 'l' || incUnreadByUser ? 1 : 0;

await Subscriptions.incUserMentionsAndUnreadForRoomIdAndUserIds(rid, uids, 1, incUnread);
};

export const getUserIdsFromHighlights = async (rid, message) => {
export const getUserIdsFromHighlights = async (rid: string, message: IMessage): Promise<string[]> => {
const highlightOptions = { projection: { 'userHighlights': 1, 'u._id': 1 } };
const subs = await Subscriptions.findByRoomWithUserHighlights(rid, highlightOptions).toArray();

return subs
.filter(
({ userHighlights, u: { _id: uid } }) => userHighlights && messageContainsHighlight(message, userHighlights) && uid !== message.u._id,
)
.filter(({ userHighlights, u: { _id: uid } }) => userHighlights && messageContainsHighlight(message, userHighlights) && uid !== message.u._id)
.map(({ u: { _id: uid } }) => uid);
};

/*
* {IRoom['t']} roomType - The type of the room
* @returns {string} - The setting value for unread count
*/
const getUnreadSettingCount = (roomType) => {
const getUnreadSettingCount = (roomType: RoomType): string => {
let unreadSetting = 'Unread_Count';
switch (roomType) {
case 'd': {
unreadSetting = 'Unread_Count_DM';
break;
}
case 'l': {
unreadSetting = 'Unread_Count_Omni';
break;
}
if (roomType === 'd') {
unreadSetting = 'Unread_Count_DM';
} else if (roomType === 'l') {
unreadSetting = 'Unread_Count_Omni';
}

return settings.get(unreadSetting);
};

async function updateUsersSubscriptions(message, room) {

async function updateUsersSubscriptions(message: IMessage, room: IRoom): Promise<void> {
// Don't increase unread counter on thread messages
if (room != null && !message.tmid) {
const { toAll, toHere, mentionIds } = await getMentions(message);
Expand All @@ -115,16 +98,15 @@ async function updateUsersSubscriptions(message, room) {

(await getUserIdsFromHighlights(room._id, message)).forEach((uid) => userIds.add(uid));

// give priority to user mentions over group mentions
Comment thread
ricardogarim marked this conversation as resolved.
if (userIds.size > 0) {
await incUserMentions(room._id, room.t, [...userIds], unreadCount);
} else if (toAll || toHere) {
await incGroupMentions(room._id, room.t, message.u._id, unreadCount);
}

// this shouldn't run only if has group mentions because it will already exclude mentioned users from the query
// This shouldn't run only if has group mentions because it will already exclude mentioned users from the query
if (!toAll && !toHere && unreadCount === 'all_messages') {
await Subscriptions.incUnreadForRoomIdExcludingUserIds(room._id, [...userIds, message.u._id]);
await Subscriptions.incUnreadForRoomIdExcludingUserIds(room._id, [...userIds, message.u._id], 1);
}
}

Expand All @@ -137,9 +119,8 @@ async function updateUsersSubscriptions(message, room) {
]);
}

export async function updateThreadUsersSubscriptions(message, room, replies) {
export async function updateThreadUsersSubscriptions(message: IMessage, room: IRoom, replies: string[]): Promise<void> {
// const unreadCount = settings.get('Unread_Count');

// incUserMentions(room._id, room.t, replies, unreadCount);

await Subscriptions.setAlertForRoomIdAndUserIds(message.rid, replies);
Expand All @@ -148,13 +129,14 @@ export async function updateThreadUsersSubscriptions(message, room, replies) {

await Subscriptions.setOpenForRoomIdAndUserIds(message.rid, repliesPlusSender);

await Subscriptions.setLastReplyForRoomIdAndUserIds(message.rid, repliesPlusSender, new Date());
// TODO: Fix this cause is waiting for a single string and it should (?!) be an array
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
await Subscriptions.setLastReplyForRoomIdAndUserIds(message.rid, repliesPlusSender as unknown as string, new Date());
}

export async function notifyUsersOnMessage(message, room) {
export async function notifyUsersOnMessage(message: IMessage & { editedAt?: Date | undefined }, room: IRoom): Promise<IMessage> {
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
// skips this callback if the message was edited and increments it if the edit was way in the past (aka imported)
if (message.editedAt) {
if (Math.abs(moment(message.editedAt).diff()) > 60000) {
if (Math.abs(moment(message.editedAt).diff(Date.now())) > 60000) {
// TODO: Review as I am not sure how else to get around this as the incrementing of the msgs count shouldn't be in this callback
await Rooms.incMsgCountById(message.rid, 1);
return message;
Expand All @@ -172,7 +154,7 @@ export async function notifyUsersOnMessage(message, room) {
return message;
}

if (message.ts && Math.abs(moment(message.ts).diff()) > 60000) {
if (message.ts && Math.abs(moment(message.ts).diff(Date.now())) > 60000) {
await Rooms.incMsgCountById(message.rid, 1);
return message;
}
Expand All @@ -184,8 +166,7 @@ export async function notifyUsersOnMessage(message, room) {
}

// Update all the room activity tracker fields
await Rooms.incMsgCountAndSetLastMessageById(message.rid, 1, message.ts, settings.get('Store_Last_Message') && message);

await Rooms.incMsgCountAndSetLastMessageById(message.rid, 1, message.ts, settings.get('Store_Last_Message') ? (message as IMessage) : undefined);
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
await updateUsersSubscriptions(message, room);

return message;
Expand Down
36 changes: 14 additions & 22 deletions apps/meteor/app/mentions/server/getMentionedTeamMembers.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,27 @@
import { Team } from '@rocket.chat/core-services';
import type { IMessage } from '@rocket.chat/core-typings';

import { callbacks } from '../../../lib/callbacks';
import { settings } from '../../settings/server';

interface IExtraDataForNotification {
userMentions: any[];
otherMentions: any[];
message: IMessage;
interface ITeamMention {
_id: string;
name: string;
type: string;
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
}

const beforeGetMentions = async (mentionIds: string[], extra?: IExtraDataForNotification) => {
const { otherMentions } = extra ?? {};

const teamIds = otherMentions?.filter(({ type }) => type === 'team').map(({ _id }) => _id);

if (!teamIds?.length) {
return mentionIds;
}

const members = await Team.getMembersByTeamIds(teamIds, { projection: { userId: 1 } });
mentionIds.push(...new Set(members.map(({ userId }) => userId).filter((userId) => !mentionIds.includes(userId))));

return mentionIds;
const beforeGetTeamMentions = async (mentionIds: string[], teamMentions: ITeamMention[]): Promise<string[]> => {
Comment thread
ricardogarim marked this conversation as resolved.
Outdated
const teamsIds = teamMentions.map(({ _id }) => _id);
Comment thread
ricardogarim marked this conversation as resolved.
const members = await Team.getMembersByTeamIds(teamsIds, { projection: { userId: 1 } });
return [...new Set([...mentionIds, ...members.map(({ userId }) => userId)])];
};

settings.watch<boolean>('Troubleshoot_Disable_Teams_Mention', (value) => {
if (value) {
callbacks.remove('beforeGetMentions', 'before-get-mentions-get-teams');
return;
callbacks.remove('beforeGetTeamMentions', 'before-get-mentions-get-teams');
} else {
callbacks.add('beforeGetTeamMentions',
beforeGetTeamMentions,
callbacks.priority.MEDIUM,
'before-get-team-mentions-get-teams');
}

callbacks.add('beforeGetMentions', beforeGetMentions, callbacks.priority.MEDIUM, 'before-get-mentions-get-teams');
});
2 changes: 1 addition & 1 deletion apps/meteor/lib/callbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export type Hook =
| 'afterSaveUser'
| 'afterValidateNewOAuthUser'
| 'beforeActivateUser'
| 'beforeGetMentions'
| 'beforeGetTeamMentions'
| 'beforeReadMessages'
| 'beforeRemoveFromRoom'
| 'beforeValidateLogin'
Expand Down