refactor: add email notification delay to chat message notifications

This commit is contained in:
Julian Lam
2023-10-02 10:54:17 -04:00
parent 5fe1ad9580
commit a47b4805f3

View File

@@ -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;