snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
432
apps/meteor/server/hooks/messages/sendNotificationsOnMessage.ts
Normal file
432
apps/meteor/server/hooks/messages/sendNotificationsOnMessage.ts
Normal file
@@ -0,0 +1,432 @@
|
||||
import {
|
||||
type IMessage,
|
||||
type ISubscription,
|
||||
type IUser,
|
||||
type IRoom,
|
||||
type NotificationItem,
|
||||
isEditedMessage,
|
||||
type AtLeast,
|
||||
} from '@rocket.chat/core-typings';
|
||||
import { Subscriptions, Users } from '@rocket.chat/models';
|
||||
import moment from 'moment';
|
||||
import type { RootFilterOperators } from 'mongodb';
|
||||
|
||||
import { getMentions } from './notifyUsersOnMessage';
|
||||
import { shortnameToUnicode } from '../../../app/emoji-native/lib/shortnameToUnicode';
|
||||
import { hasPermissionAsync } from '../../lib/authorization/hasPermission';
|
||||
import { callbacks } from '../../lib/callbacks';
|
||||
import { parseMessageTextPerUser, replaceMentionedUsernamesWithFullNames } from '../../lib/notifications/message';
|
||||
import { notifyDesktopUser, shouldNotifyDesktop } from '../../lib/notifications/message/desktop';
|
||||
import { getEmailData, shouldNotifyEmail } from '../../lib/notifications/message/email';
|
||||
import { messageContainsHighlight } from '../../lib/notifications/message/messageContainsHighlight';
|
||||
import { getPushData, shouldNotifyMobile } from '../../lib/notifications/message/mobile';
|
||||
import { Notification } from '../../lib/notifications/queue/NotificationQueue';
|
||||
import { roomCoordinator } from '../../lib/rooms/roomCoordinator';
|
||||
import { settings } from '../../settings';
|
||||
|
||||
type SubscriptionAggregation = {
|
||||
receiver: [Pick<IUser, 'active' | 'emails' | 'language' | 'status' | 'statusConnection' | 'username' | 'settings'> | null];
|
||||
} & Pick<
|
||||
ISubscription,
|
||||
| 'desktopNotifications'
|
||||
| 'emailNotifications'
|
||||
| 'mobilePushNotifications'
|
||||
| 'muteGroupMentions'
|
||||
| 'name'
|
||||
| 'rid'
|
||||
| 'userHighlights'
|
||||
| 'u'
|
||||
| 'audioNotificationValue'
|
||||
>;
|
||||
|
||||
type WithRequiredProperty<Type, Key extends keyof Type> = Type & {
|
||||
[Property in Key]-?: Type[Property];
|
||||
};
|
||||
|
||||
export const sendNotification = async ({
|
||||
subscription,
|
||||
sender,
|
||||
hasReplyToThread,
|
||||
hasMentionToAll,
|
||||
hasMentionToHere,
|
||||
message,
|
||||
notificationMessage,
|
||||
room,
|
||||
mentionIds,
|
||||
disableAllMessageNotifications,
|
||||
}: {
|
||||
subscription: SubscriptionAggregation;
|
||||
sender: Pick<IUser, '_id' | 'name' | 'username'>;
|
||||
|
||||
hasReplyToThread: boolean;
|
||||
hasMentionToAll: boolean;
|
||||
hasMentionToHere: boolean;
|
||||
message: AtLeast<IMessage, '_id' | 'u' | 'msg' | 't' | 'attachments'>;
|
||||
notificationMessage: string;
|
||||
room: IRoom;
|
||||
mentionIds: string[];
|
||||
disableAllMessageNotifications: boolean;
|
||||
}) => {
|
||||
if (settings.get<boolean>('Troubleshoot_Disable_Notifications') === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't notify the sender
|
||||
if (subscription.u._id === sender._id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasMentionToUser = mentionIds.includes(subscription.u._id);
|
||||
|
||||
// mute group notifications (@here and @all) if not directly mentioned as well
|
||||
if (!hasMentionToUser && !hasReplyToThread && subscription.muteGroupMentions && (hasMentionToAll || hasMentionToHere)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!subscription.receiver) {
|
||||
subscription.receiver = [
|
||||
await Users.findOneById(subscription.u._id, {
|
||||
projection: {
|
||||
'active': 1,
|
||||
'emails': 1,
|
||||
'language': 1,
|
||||
'status': 1,
|
||||
'statusConnection': 1,
|
||||
'username': 1,
|
||||
'settings.preferences.enableMobileRinging': 1,
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
const [receiver] = subscription.receiver;
|
||||
|
||||
if (!receiver) {
|
||||
throw new Error('receiver not found');
|
||||
}
|
||||
|
||||
const roomType = room.t;
|
||||
// If the user doesn't have permission to view direct messages, don't send notification of direct messages.
|
||||
if (roomType === 'd' && !(await hasPermissionAsync(subscription.u._id, 'view-d-room'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isThread = !!message.tmid && !message.tshow;
|
||||
const isVideoConf = message.t === 'videoconf';
|
||||
|
||||
notificationMessage = await parseMessageTextPerUser(notificationMessage, message, receiver);
|
||||
|
||||
const isHighlighted = messageContainsHighlight(message, subscription.userHighlights);
|
||||
|
||||
const { desktopNotifications, mobilePushNotifications, emailNotifications } = subscription;
|
||||
|
||||
// busy users don't receive desktop notification
|
||||
if (
|
||||
shouldNotifyDesktop({
|
||||
disableAllMessageNotifications,
|
||||
status: receiver.status ?? 'offline',
|
||||
statusConnection: receiver.statusConnection ?? 'offline',
|
||||
desktopNotifications,
|
||||
hasMentionToAll,
|
||||
hasMentionToHere,
|
||||
isHighlighted,
|
||||
hasMentionToUser,
|
||||
hasReplyToThread,
|
||||
roomType,
|
||||
isThread,
|
||||
})
|
||||
) {
|
||||
await notifyDesktopUser({
|
||||
notificationMessage,
|
||||
userId: subscription.u._id,
|
||||
user: sender,
|
||||
message,
|
||||
room,
|
||||
audioNotificationValue: subscription.audioNotificationValue,
|
||||
});
|
||||
}
|
||||
|
||||
const queueItems: NotificationItem[] = [];
|
||||
|
||||
if (
|
||||
shouldNotifyMobile({
|
||||
disableAllMessageNotifications,
|
||||
mobilePushNotifications,
|
||||
hasMentionToAll,
|
||||
isHighlighted,
|
||||
hasMentionToUser,
|
||||
hasReplyToThread,
|
||||
roomType,
|
||||
isThread,
|
||||
isVideoConf,
|
||||
userPreferences: receiver.settings?.preferences,
|
||||
roomUids: room.uids,
|
||||
})
|
||||
) {
|
||||
queueItems.push({
|
||||
type: 'push',
|
||||
data: await getPushData({
|
||||
notificationMessage,
|
||||
room,
|
||||
message,
|
||||
userId: subscription.u._id,
|
||||
senderUsername: sender.username,
|
||||
senderName: sender.name,
|
||||
receiver,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
receiver.emails &&
|
||||
shouldNotifyEmail({
|
||||
disableAllMessageNotifications,
|
||||
statusConnection: receiver.statusConnection,
|
||||
emailNotifications,
|
||||
isHighlighted,
|
||||
hasMentionToUser,
|
||||
hasMentionToAll,
|
||||
hasReplyToThread,
|
||||
roomType,
|
||||
isThread,
|
||||
})
|
||||
) {
|
||||
const messageWithUnicode = message.msg ? shortnameToUnicode(message.msg) : message.msg;
|
||||
const firstAttachment = message.attachments?.[0];
|
||||
|
||||
const convertedFirstAttachment = firstAttachment
|
||||
? {
|
||||
...firstAttachment,
|
||||
description: typeof firstAttachment.description === 'string' ? shortnameToUnicode(firstAttachment.description) : undefined,
|
||||
text: typeof firstAttachment.text === 'string' ? shortnameToUnicode(firstAttachment.text) : undefined,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const attachments = convertedFirstAttachment ? [convertedFirstAttachment, ...(message.attachments?.slice(1) ?? [])] : [];
|
||||
for (const email of receiver.emails) {
|
||||
if (email.verified) {
|
||||
queueItems.push({
|
||||
type: 'email',
|
||||
data: await getEmailData({
|
||||
message: {
|
||||
...message,
|
||||
msg: messageWithUnicode,
|
||||
...(attachments.length > 0 ? { attachments } : {}),
|
||||
},
|
||||
receiver,
|
||||
sender,
|
||||
subscription,
|
||||
room,
|
||||
emailAddress: email.address,
|
||||
hasMentionToUser,
|
||||
}),
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (queueItems.length) {
|
||||
void Notification.scheduleItem({
|
||||
user: receiver,
|
||||
uid: subscription.u._id,
|
||||
rid: room._id,
|
||||
mid: message._id,
|
||||
items: queueItems,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const project = {
|
||||
$project: {
|
||||
'desktopNotifications': 1,
|
||||
'emailNotifications': 1,
|
||||
'mobilePushNotifications': 1,
|
||||
'muteGroupMentions': 1,
|
||||
'name': 1,
|
||||
'rid': 1,
|
||||
'userHighlights': 1,
|
||||
'u._id': 1,
|
||||
'receiver.active': 1,
|
||||
'receiver.emails': 1,
|
||||
'receiver.language': 1,
|
||||
'receiver.status': 1,
|
||||
'receiver.statusConnection': 1,
|
||||
'receiver.username': 1,
|
||||
'receiver.settings.preferences.enableMobileRinging': 1,
|
||||
'audioNotificationValue': 1,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const filter = {
|
||||
$match: {
|
||||
'receiver.active': true,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const lookup = {
|
||||
$lookup: {
|
||||
from: 'users',
|
||||
localField: 'u._id',
|
||||
foreignField: '_id',
|
||||
as: 'receiver',
|
||||
},
|
||||
} as const;
|
||||
|
||||
export async function sendMessageNotifications(message: IMessage, room: IRoom, usersInThread: string[] = []) {
|
||||
if (settings.get<boolean>('Troubleshoot_Disable_Notifications') === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sender = await roomCoordinator.getRoomDirectives(room.t).getMsgSender(message);
|
||||
if (!sender) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const { toAll: hasMentionToAll, toHere: hasMentionToHere, mentionIds } = await getMentions(message);
|
||||
|
||||
const mentionIdsWithoutGroups = [...mentionIds];
|
||||
|
||||
// getMentions removes `all` and `here` from mentionIds so we need to add them back for compatibility
|
||||
if (hasMentionToAll) {
|
||||
mentionIds.push('all');
|
||||
}
|
||||
if (hasMentionToHere) {
|
||||
mentionIds.push('here');
|
||||
}
|
||||
|
||||
// add users in thread to mentions array because they follow the same rules
|
||||
mentionIds.push(...usersInThread);
|
||||
|
||||
let notificationMessage = await callbacks.run('beforeSendMessageNotifications', message.msg);
|
||||
if (mentionIds.length > 0 && settings.get('UI_Use_Real_Name')) {
|
||||
notificationMessage = replaceMentionedUsernamesWithFullNames(message.msg, message.mentions ?? []);
|
||||
}
|
||||
|
||||
// Don't fetch all users if room exceeds max members
|
||||
const maxMembersForNotification = settings.get<number>('Notifications_Max_Room_Members');
|
||||
const roomMembersCount = await Users.countRoomMembers(room._id);
|
||||
const disableAllMessageNotifications = roomMembersCount > maxMembersForNotification && maxMembersForNotification !== 0;
|
||||
|
||||
const query: WithRequiredProperty<RootFilterOperators<ISubscription>, '$or'> = {
|
||||
rid: room._id,
|
||||
ignored: { $ne: sender._id },
|
||||
disableNotifications: { $ne: true },
|
||||
$or: [{ 'userHighlights.0': { $exists: 1 } }, ...(usersInThread.length > 0 ? [{ 'u._id': { $in: usersInThread } }] : [])],
|
||||
} as const;
|
||||
|
||||
(['desktop', 'mobile', 'email'] as const).forEach((kind) => {
|
||||
const notificationField = kind === 'mobile' ? 'mobilePush' : `${kind}Notifications`;
|
||||
|
||||
query.$or.push({
|
||||
[notificationField]: 'all',
|
||||
...(disableAllMessageNotifications ? { [`${kind}PrefOrigin`]: { $ne: 'user' } } : {}),
|
||||
});
|
||||
|
||||
if (disableAllMessageNotifications) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (room.t === 'd') {
|
||||
query.$or.push({
|
||||
[notificationField]: 'mentions',
|
||||
});
|
||||
} else if (mentionIdsWithoutGroups.length > 0) {
|
||||
query.$or.push({
|
||||
[notificationField]: 'mentions',
|
||||
'u._id': { $in: mentionIdsWithoutGroups },
|
||||
});
|
||||
}
|
||||
|
||||
const serverField = kind === 'email' ? 'emailNotificationMode' : `${kind}Notifications`;
|
||||
const serverPreference = settings.get(`Accounts_Default_User_Preferences_${serverField}`);
|
||||
|
||||
if (serverPreference === 'all' || hasMentionToAll || hasMentionToHere || room.t === 'd') {
|
||||
query.$or.push({
|
||||
[notificationField]: { $exists: false },
|
||||
});
|
||||
} else if (serverPreference === 'mentions' && mentionIdsWithoutGroups.length > 0) {
|
||||
query.$or.push({
|
||||
[notificationField]: { $exists: false },
|
||||
'u._id': { $in: mentionIdsWithoutGroups },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// the find below is crucial. All subscription records returned will receive at least one kind of notification.
|
||||
// the query is defined by the server's default values and Notifications_Max_Room_Members setting.
|
||||
|
||||
const subscriptions = await Subscriptions.col.aggregate<SubscriptionAggregation>([{ $match: query }, lookup, filter, project]).toArray();
|
||||
|
||||
subscriptions.forEach(
|
||||
(subscription) =>
|
||||
void sendNotification({
|
||||
subscription,
|
||||
sender,
|
||||
hasMentionToAll,
|
||||
hasMentionToHere,
|
||||
message,
|
||||
notificationMessage,
|
||||
room,
|
||||
mentionIds,
|
||||
disableAllMessageNotifications,
|
||||
hasReplyToThread: usersInThread?.includes(subscription.u._id),
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
sender,
|
||||
hasMentionToAll,
|
||||
hasMentionToHere,
|
||||
notificationMessage,
|
||||
mentionIds,
|
||||
mentionIdsWithoutGroups,
|
||||
};
|
||||
}
|
||||
|
||||
export async function sendAllNotifications(message: IMessage, room: IRoom) {
|
||||
if (settings.get<boolean>('Troubleshoot_Disable_Notifications') === true) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// threads
|
||||
if (message.tmid) {
|
||||
return message;
|
||||
}
|
||||
// skips this callback if the message was edited
|
||||
if (isEditedMessage(message)) {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (message.ts && Math.abs(moment(message.ts).diff(new Date())) > 60000) {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (room?.t == null) {
|
||||
return message;
|
||||
}
|
||||
|
||||
await sendMessageNotifications(message, room);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
settings.watch('Troubleshoot_Disable_Notifications', (value) => {
|
||||
if (value) {
|
||||
return callbacks.remove('afterSaveMessage', 'sendNotificationsOnMessage');
|
||||
}
|
||||
|
||||
callbacks.add(
|
||||
'afterSaveMessage',
|
||||
(message, { room, options }) => {
|
||||
if (options?.skipNotifications) {
|
||||
return message;
|
||||
}
|
||||
|
||||
return sendAllNotifications(message, room);
|
||||
},
|
||||
callbacks.priority.LOW,
|
||||
'sendNotificationsOnMessage',
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user