diff --git a/.changeset/clean-flies-collect.md b/.changeset/clean-flies-collect.md new file mode 100644 index 000000000000..4921355b51e8 --- /dev/null +++ b/.changeset/clean-flies-collect.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fix user highlights not matching only whole words diff --git a/apps/meteor/app/lib/server/functions/notifications/index.ts b/apps/meteor/app/lib/server/functions/notifications/index.ts index 54b18f502ae7..538ff2ad5ed9 100644 --- a/apps/meteor/app/lib/server/functions/notifications/index.ts +++ b/apps/meteor/app/lib/server/functions/notifications/index.ts @@ -47,22 +47,3 @@ export function replaceMentionedUsernamesWithFullNames(message: string, mentions }); return message; } - -/** - * Checks if a message contains a user highlight - * - * @param {string} message - * @param {array|undefined} highlights - * - * @returns {boolean} - */ -export function messageContainsHighlight(message: Pick, highlights: string[] | undefined): boolean { - if (!highlights || highlights.length === 0) { - return false; - } - - return highlights.some((highlight: string) => { - const regexp = new RegExp(escapeRegExp(highlight), 'i'); - return regexp.test(message.msg); - }); -} diff --git a/apps/meteor/app/lib/server/functions/notifications/messageContainsHighlight.ts b/apps/meteor/app/lib/server/functions/notifications/messageContainsHighlight.ts new file mode 100644 index 000000000000..d749441ba0b4 --- /dev/null +++ b/apps/meteor/app/lib/server/functions/notifications/messageContainsHighlight.ts @@ -0,0 +1,22 @@ +import type { IMessage } from '@rocket.chat/core-typings'; +import { escapeRegExp } from '@rocket.chat/string-helpers'; + +/** + * Checks if a message contains a user highlight + * + * @param {string} message + * @param {array|undefined} highlights + * + * @returns {boolean} + */ +export function messageContainsHighlight(message: Pick, highlights: string[] | undefined): boolean { + if (!highlights || highlights.length === 0) { + return false; + } + + return highlights.some((highlight: string) => { + const hl = escapeRegExp(highlight); + const regexp = new RegExp(`(? { - const regexp = new RegExp(escapeRegExp(highlight), 'i'); - return regexp.test(message.msg); - }); -} - export async function getMentions(message: IMessage): Promise<{ toAll: boolean; toHere: boolean; mentionIds: string[] }> { const { mentions, diff --git a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts index 94c25f476222..fe65ebe5a5d2 100644 --- a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts +++ b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts @@ -17,9 +17,10 @@ import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { Notification } from '../../../notification-queue/server/NotificationQueue'; import { settings } from '../../../settings/server'; -import { messageContainsHighlight, parseMessageTextPerUser, replaceMentionedUsernamesWithFullNames } from '../functions/notifications'; +import { parseMessageTextPerUser, replaceMentionedUsernamesWithFullNames } from '../functions/notifications'; import { notifyDesktopUser, shouldNotifyDesktop } from '../functions/notifications/desktop'; import { getEmailData, shouldNotifyEmail } from '../functions/notifications/email'; +import { messageContainsHighlight } from '../functions/notifications/messageContainsHighlight'; import { getPushData, shouldNotifyMobile } from '../functions/notifications/mobile'; import { getMentions } from './notifyUsersOnMessage'; diff --git a/apps/meteor/tests/unit/app/lib/server/functions/notifications/messageContainsHighlight.tests.ts b/apps/meteor/tests/unit/app/lib/server/functions/notifications/messageContainsHighlight.tests.ts new file mode 100644 index 000000000000..2cc8a9248c34 --- /dev/null +++ b/apps/meteor/tests/unit/app/lib/server/functions/notifications/messageContainsHighlight.tests.ts @@ -0,0 +1,69 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { messageContainsHighlight } from '../../../../../../../app/lib/server/functions/notifications/messageContainsHighlight'; + +describe('messageContainsHighlight', () => { + it('should return false for no highlights', async () => { + const message = { + msg: 'regular message', + }; + expect(messageContainsHighlight(message, [])).to.be.false; + }); + + it('should return true when find a highlight in the beggining of the message', async () => { + const message = { + msg: 'highlighted regular message', + }; + expect(messageContainsHighlight(message, ['highlighted'])).to.be.true; + }); + + it('should return true when find a highlight in the end of the message', async () => { + const message = { + msg: 'highlighted regular message', + }; + expect(messageContainsHighlight(message, ['message'])).to.be.true; + }); + + it('should return false if the highlight is just part of the word', async () => { + const message = { + msg: 'highlighted regular message', + }; + expect(messageContainsHighlight(message, ['light'])).to.be.false; + }); + + it('should return true if find one of the multiple highlights', async () => { + const message = { + msg: 'highlighted regular message', + }; + expect(messageContainsHighlight(message, ['high', 'ssage', 'regular', 'light'])).to.be.true; + }); + + it('should return true if highlight case not match', async () => { + const message = { + msg: 'highlighted regular message', + }; + expect(messageContainsHighlight(message, ['ReGuLaR'])).to.be.true; + }); + + it('should return false if the highlight word is an emoji', async () => { + const message = { + msg: 'highlighted :thumbsup: message', + }; + expect(messageContainsHighlight(message, ['thumbsup'])).to.be.false; + }); + + it('should return true for a highlight word beggining with :', async () => { + const message = { + msg: 'highlighted :thumbsup message', + }; + expect(messageContainsHighlight(message, ['thumbsup'])).to.be.true; + }); + + it('should return true for a highlight word ending with :', async () => { + const message = { + msg: 'highlighted thumbsup: message', + }; + expect(messageContainsHighlight(message, ['thumbsup'])).to.be.true; + }); +});