mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-29 18:16:17 +01:00
refactor: add email notification delay to chat message notifications
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
const cron = require('cron').CronJob;
|
const cron = require('cron').CronJob;
|
||||||
@@ -15,9 +16,17 @@ const batch = require('./batch');
|
|||||||
const plugins = require('./plugins');
|
const plugins = require('./plugins');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const emailer = require('./emailer');
|
const emailer = require('./emailer');
|
||||||
|
const ttlCache = require('./cache/ttl');
|
||||||
|
|
||||||
const Notifications = module.exports;
|
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 = [
|
Notifications.baseTypes = [
|
||||||
'notificationType_upvote',
|
'notificationType_upvote',
|
||||||
'notificationType_new-topic',
|
'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) {
|
async function getUidsBySettings(uids) {
|
||||||
const uidsToNotify = [];
|
const uidsToNotify = [];
|
||||||
const uidsToEmail = [];
|
const uidsToEmail = [];
|
||||||
@@ -252,18 +231,62 @@ async function pushToUids(uids, notification) {
|
|||||||
if (notification.type) {
|
if (notification.type) {
|
||||||
results = await getUidsBySettings(data.uids);
|
results = await getUidsBySettings(data.uids);
|
||||||
}
|
}
|
||||||
await Promise.all([
|
await sendNotification(results.uidsToNotify);
|
||||||
sendNotification(results.uidsToNotify),
|
const delayNotificationTypes = ['new-chat', 'new-group-chat', 'new-public-chat'];
|
||||||
sendEmail(results.uidsToEmail),
|
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', {
|
plugins.hooks.fire('action:notification.pushed', {
|
||||||
notification: notification,
|
notification,
|
||||||
uids: results.uidsToNotify,
|
uids: results.uidsToNotify,
|
||||||
uidsNotified: results.uidsToNotify,
|
uidsNotified: results.uidsToNotify,
|
||||||
uidsEmailed: results.uidsToEmail,
|
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) {
|
Notifications.pushGroup = async function (notification, groupName) {
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user