mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-02-09 08:07:37 +01:00
feat: wip, better digest handling (+ eventual digest resend logic) (#7995)
* feat: wip, better digest handling (+ eventual digest resend logic)
- await emailer.send call in digest.send method
- save send success to a new sorted set digest:{interval}:byUid
* feat: continuing work on digest tools
- Added ACP page to view digest settings and delivery times per user
* feat: added paginator and stub buttons for resending digest
* feat: wrapping up digest revamp
- New language strings in ACP digest page
- Client-side ACP script for digest ACP page
- Websocket call for ACP page to execute digests
- Broke out logic to retrieve user digest settings to getUsersInterval
* fix: minor cleanup
* fix: #8010 and some style suggestions from baris
* fix: resolve confusing comment
This commit is contained in:
@@ -4,6 +4,7 @@ const async = require('async');
|
||||
const winston = require('winston');
|
||||
const nconf = require('nconf');
|
||||
|
||||
const db = require('../database');
|
||||
const batch = require('../batch');
|
||||
const meta = require('../meta');
|
||||
const user = require('../user');
|
||||
@@ -28,17 +29,49 @@ Digest.execute = async function (payload) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const count = await Digest.send({
|
||||
await Digest.send({
|
||||
interval: payload.interval,
|
||||
subscribers: subscribers,
|
||||
});
|
||||
winston.info('[user/jobs] Digest (' + payload.interval + ') scheduling completed. ' + count + ' email(s) sent.');
|
||||
winston.info('[user/jobs] Digest (' + payload.interval + ') scheduling completed. Sending emails; this may take some time...');
|
||||
} catch (err) {
|
||||
winston.error('[user/jobs] Could not send digests (' + payload.interval + ')', err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
Digest.getUsersInterval = async (uids) => {
|
||||
// Checks whether user specifies digest setting, or null/false for system default setting
|
||||
let single = false;
|
||||
if (!Array.isArray(uids) && !isNaN(parseInt(uids, 10))) {
|
||||
uids = [uids];
|
||||
single = true;
|
||||
}
|
||||
|
||||
let settings = await Promise.all([
|
||||
db.isSortedSetMembers('digest:day:uids', uids),
|
||||
db.isSortedSetMembers('digest:week:uids', uids),
|
||||
db.isSortedSetMembers('digest:month:uids', uids),
|
||||
]);
|
||||
settings = settings.reduce((memo, cur, idx) => {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
memo = cur.map(bool => (bool === true ? 'day' : bool));
|
||||
break;
|
||||
case 1:
|
||||
memo = cur.map(bool => (bool === true ? 'week' : bool));
|
||||
break;
|
||||
case 2:
|
||||
memo = cur.map(bool => (bool === true ? 'month' : bool));
|
||||
break;
|
||||
}
|
||||
|
||||
return memo;
|
||||
});
|
||||
|
||||
return single ? settings[0] : settings;
|
||||
};
|
||||
|
||||
Digest.getSubscribers = async function (interval) {
|
||||
var subscribers = [];
|
||||
|
||||
@@ -99,21 +132,53 @@ Digest.send = async function (data) {
|
||||
return topicObj;
|
||||
});
|
||||
emailsSent += 1;
|
||||
emailer.send('digest', userObj.uid, {
|
||||
subject: '[[email:digest.subject, ' + (now.getFullYear() + '/' + (now.getMonth() + 1) + '/' + now.getDate()) + ']]',
|
||||
username: userObj.username,
|
||||
userslug: userObj.userslug,
|
||||
notifications: notifications,
|
||||
recent: topicsData,
|
||||
interval: data.interval,
|
||||
showUnsubscribe: true,
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
winston.error('[user/jobs] Could not send digest email', err);
|
||||
}
|
||||
});
|
||||
try {
|
||||
await emailer.send('digest', userObj.uid, {
|
||||
subject: '[[email:digest.subject, ' + (now.getFullYear() + '/' + (now.getMonth() + 1) + '/' + now.getDate()) + ']]',
|
||||
username: userObj.username,
|
||||
userslug: userObj.userslug,
|
||||
notifications: notifications,
|
||||
recent: topicsData,
|
||||
interval: data.interval,
|
||||
showUnsubscribe: true,
|
||||
});
|
||||
} catch (err) {
|
||||
winston.error('[user/jobs] Could not send digest email', err);
|
||||
}
|
||||
|
||||
if (data.interval !== 'alltime') {
|
||||
await db.sortedSetAdd('digest:delivery', now.getTime(), userObj.uid);
|
||||
}
|
||||
}, function () {
|
||||
winston.info('[user/jobs] Digest (' + data.interval + ') sending completed. ' + emailsSent + ' emails sent.');
|
||||
});
|
||||
return emailsSent;
|
||||
};
|
||||
|
||||
Digest.getDeliveryTimes = async (start, stop) => {
|
||||
const count = await db.sortedSetCard('users:joindate');
|
||||
const uids = await user.getUidsFromSet('users:joindate', start, stop);
|
||||
if (!uids) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Grab the last time a digest was successfully delivered to these uids
|
||||
const scores = await db.sortedSetScores('digest:delivery', uids);
|
||||
|
||||
// Get users' digest settings
|
||||
const settings = await Digest.getUsersInterval(uids);
|
||||
|
||||
// Populate user data
|
||||
let userData = await user.getUsersFields(uids, ['username', 'picture']);
|
||||
userData = userData.map((user, idx) => {
|
||||
user.lastDelivery = scores[idx] ? new Date(scores[idx]).toISOString() : '[[admin/manage/digest:null]]';
|
||||
user.setting = settings[idx];
|
||||
return user;
|
||||
});
|
||||
|
||||
return {
|
||||
users: userData,
|
||||
count: count,
|
||||
};
|
||||
};
|
||||
|
||||
async function getTermTopics(term, uid, start, stop) {
|
||||
|
||||
Reference in New Issue
Block a user