mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-27 00:56:13 +01:00
refactor: add email notification delay to chat message notifications
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
const async = require('async');
|
||||
const winston = require('winston');
|
||||
const cron = require('cron').CronJob;
|
||||
@@ -15,9 +16,17 @@ const batch = require('./batch');
|
||||
const plugins = require('./plugins');
|
||||
const utils = require('./utils');
|
||||
const emailer = require('./emailer');
|
||||
const ttlCache = require('./cache/ttl');
|
||||
|
||||
const Notifications = module.exports;
|
||||
|
||||
// ttlcache for email-only chat notifications
|
||||
const notificationCache = ttlCache({
|
||||
ttl: (meta.config.notificationSendDelay || 60) * 1000,
|
||||
noDisposeOnSet: true,
|
||||
dispose: sendEmail,
|
||||
});
|
||||
|
||||
Notifications.baseTypes = [
|
||||
'notificationType_upvote',
|
||||
'notificationType_new-topic',
|
||||
@@ -192,36 +201,6 @@ async function pushToUids(uids, notification) {
|
||||
}
|
||||
}
|
||||
|
||||
async function sendEmail(uids) {
|
||||
// Update CTA messaging (as not all notification types need custom text)
|
||||
if (['new-reply', 'new-chat'].includes(notification.type)) {
|
||||
notification['cta-type'] = notification.type;
|
||||
}
|
||||
let body = notification.bodyLong || '';
|
||||
if (meta.config.removeEmailNotificationImages) {
|
||||
body = body.replace(/<img[^>]*>/, '');
|
||||
}
|
||||
body = posts.relativeToAbsolute(body, posts.urlRegex);
|
||||
body = posts.relativeToAbsolute(body, posts.imgRegex);
|
||||
let errorLogged = false;
|
||||
await async.eachLimit(uids, 3, async (uid) => {
|
||||
await emailer.send('notification', uid, {
|
||||
path: notification.path,
|
||||
notification_url: notification.path.startsWith('http') ? notification.path : nconf.get('url') + notification.path,
|
||||
subject: utils.stripHTMLTags(notification.subject || '[[notifications:new_notification]]'),
|
||||
intro: utils.stripHTMLTags(notification.bodyShort),
|
||||
body: body,
|
||||
notification: notification,
|
||||
showUnsubscribe: true,
|
||||
}).catch((err) => {
|
||||
if (!errorLogged) {
|
||||
winston.error(`[emailer.send] ${err.stack}`);
|
||||
errorLogged = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function getUidsBySettings(uids) {
|
||||
const uidsToNotify = [];
|
||||
const uidsToEmail = [];
|
||||
@@ -252,18 +231,62 @@ async function pushToUids(uids, notification) {
|
||||
if (notification.type) {
|
||||
results = await getUidsBySettings(data.uids);
|
||||
}
|
||||
await Promise.all([
|
||||
sendNotification(results.uidsToNotify),
|
||||
sendEmail(results.uidsToEmail),
|
||||
]);
|
||||
await sendNotification(results.uidsToNotify);
|
||||
const delayNotificationTypes = ['new-chat', 'new-group-chat', 'new-public-chat'];
|
||||
if (delayNotificationTypes.includes(notification.type)) {
|
||||
const cacheKey = `${notification.mergeId}|${results.uidsToEmail.join(',')}`;
|
||||
if (notificationCache.has(cacheKey)) {
|
||||
const payload = notificationCache.get(cacheKey);
|
||||
notification.bodyLong = [payload.notification.bodyLong, notification.bodyLong].join('\n');
|
||||
}
|
||||
notificationCache.set(cacheKey, { uids: results.uidsToEmail, notification });
|
||||
} else {
|
||||
await sendEmail({ uids: results.uidsToEmail, notification });
|
||||
}
|
||||
|
||||
plugins.hooks.fire('action:notification.pushed', {
|
||||
notification: notification,
|
||||
notification,
|
||||
uids: results.uidsToNotify,
|
||||
uidsNotified: results.uidsToNotify,
|
||||
uidsEmailed: results.uidsToEmail,
|
||||
});
|
||||
}
|
||||
|
||||
async function sendEmail({ uids, notification }, mergeId, reason) {
|
||||
// Only act on cache item expiry
|
||||
if (reason && reason !== 'stale') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update CTA messaging (as not all notification types need custom text)
|
||||
if (['new-reply', 'new-chat'].includes(notification.type)) {
|
||||
notification['cta-type'] = notification.type;
|
||||
}
|
||||
let body = notification.bodyLong || '';
|
||||
if (meta.config.removeEmailNotificationImages) {
|
||||
body = body.replace(/<img[^>]*>/, '');
|
||||
}
|
||||
body = posts.relativeToAbsolute(body, posts.urlRegex);
|
||||
body = posts.relativeToAbsolute(body, posts.imgRegex);
|
||||
let errorLogged = false;
|
||||
await async.eachLimit(uids, 3, async (uid) => {
|
||||
await emailer.send('notification', uid, {
|
||||
path: notification.path,
|
||||
notification_url: notification.path.startsWith('http') ? notification.path : nconf.get('url') + notification.path,
|
||||
subject: utils.stripHTMLTags(notification.subject || '[[notifications:new_notification]]'),
|
||||
intro: utils.stripHTMLTags(notification.bodyShort),
|
||||
body: body,
|
||||
notification: notification,
|
||||
showUnsubscribe: true,
|
||||
}).catch((err) => {
|
||||
if (!errorLogged) {
|
||||
winston.error(`[emailer.send] ${err.stack}`);
|
||||
errorLogged = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Notifications.pushGroup = async function (notification, groupName) {
|
||||
if (!notification) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user