242 lines
5.6 KiB
JavaScript
242 lines
5.6 KiB
JavaScript
const async = require('async');
|
|
const nodemailer = require('nodemailer');
|
|
const Email = require('email-templates');
|
|
const fs = require('mz/fs');
|
|
const path = require('path');
|
|
const getPaths = require('get-paths');
|
|
const AbstractIntervalWorker = require('./abstractintervalworker');
|
|
const NotificationType = require('../repository/notification').NotificationType;
|
|
const _ = require('lodash');
|
|
|
|
|
|
function humanFileSize(bytes, si)
|
|
{
|
|
var thresh = si ? 1000 : 1024;
|
|
if(Math.abs(bytes) < thresh)
|
|
{
|
|
return bytes + ' B';
|
|
}
|
|
|
|
var units = si
|
|
? ['kB','MB','GB','TB','PB','EB','ZB','YB']
|
|
: ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
|
|
var u = -1;
|
|
|
|
do
|
|
{
|
|
bytes /= thresh;
|
|
++u;
|
|
}
|
|
while(Math.abs(bytes) >= thresh && u < units.length - 1);
|
|
|
|
return bytes.toFixed(1) + ' ' + units[u];
|
|
}
|
|
|
|
|
|
class NotificationWorker extends AbstractIntervalWorker
|
|
{
|
|
constructor(repository)
|
|
{
|
|
super();
|
|
this.repository = repository;
|
|
}
|
|
|
|
|
|
async tick()
|
|
{
|
|
var self = this;
|
|
|
|
var notifications = await self.repository.notifications.list();
|
|
return new Promise((resolve, reject) =>
|
|
{
|
|
async.eachOfSeries(notifications,
|
|
async (item) => { await self.handleNotification(item) },
|
|
(err) =>
|
|
{
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve();
|
|
});
|
|
})
|
|
}
|
|
|
|
|
|
async handleNotification(notification)
|
|
{
|
|
let self = this;
|
|
|
|
let user = await self.repository.users.get(notification.userId);
|
|
if (user === null || !user.email)
|
|
return;
|
|
|
|
switch (notification.type)
|
|
{
|
|
case NotificationType.UploadComplete:
|
|
await self.sendUploadNotification(notification, user);
|
|
break;
|
|
|
|
case NotificationType.CodeMoved:
|
|
await self.sendCodeMovedNotification(notification, user);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
getDefaultLocals(user)
|
|
{
|
|
return {
|
|
// Data
|
|
user: user,
|
|
|
|
// Configuration
|
|
adminUrl: config.notifications.adminUrl,
|
|
|
|
// Helper functions
|
|
humanFileSize: humanFileSize
|
|
}
|
|
}
|
|
|
|
|
|
async sendUploadNotification(notification, user)
|
|
{
|
|
let self = this;
|
|
let locals = self.getDefaultLocals(user);
|
|
|
|
locals.upload = await self.repository.uploads.get(notification.uploadId);
|
|
if (locals.upload === null)
|
|
return;
|
|
|
|
await self.sendNotification(notification, user, locals, 'uploadnotification');
|
|
}
|
|
|
|
|
|
async sendCodeMovedNotification(notification, user)
|
|
{
|
|
let self = this;
|
|
let locals = self.getDefaultLocals(user);
|
|
|
|
locals.uploads = await self.repository.uploads.listForCode(notification.codeId);
|
|
if (locals.uploads === null || locals.uploads.length == 0)
|
|
return;
|
|
|
|
locals.fileCount = 0;
|
|
_.forEach(locals.uploads, (upload) =>
|
|
{
|
|
locals.fileCount += upload.files.length;
|
|
});
|
|
|
|
locals.prevUser = {
|
|
userId: null,
|
|
name: ''
|
|
};
|
|
|
|
if (notification.metadata !== null)
|
|
{
|
|
let resolveUser = async (userId) =>
|
|
{
|
|
if (!userId)
|
|
return null;
|
|
|
|
let user = await self.repository.users.get(userId);
|
|
if (user !== null)
|
|
{
|
|
return {
|
|
userId: userId,
|
|
name: user.name
|
|
}
|
|
}
|
|
};
|
|
|
|
locals.prevUser = await resolveUser(notification.metadata.prevUserId);
|
|
locals.assignUser = await resolveUser(notification.metadata.assignUserId);
|
|
}
|
|
|
|
await self.sendNotification(notification, user, locals, 'movednotification');
|
|
}
|
|
|
|
|
|
async sendNotification(notification, user, locals, template)
|
|
{
|
|
let self = this;
|
|
|
|
return new Promise((resolve, reject) =>
|
|
{
|
|
const email = new Email({
|
|
message: {
|
|
from: config.notifications.mail.from
|
|
},
|
|
|
|
send: true,
|
|
preview: false,
|
|
transport: nodemailer.createTransport(config.notifications.mail.transport),
|
|
views: {
|
|
options: {
|
|
extension: 'ejs'
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
// Override the default template locator with one that checks
|
|
// the custom folder first, then falls back to the configured folder
|
|
let getTemplatePathFromRoot = function(root, view, ext)
|
|
{
|
|
return new Promise(async (resolve, reject) => {
|
|
try {
|
|
const paths = await getPaths(
|
|
root,
|
|
view,
|
|
ext
|
|
);
|
|
const filePath = path.resolve(root, paths.rel);
|
|
resolve({ filePath, paths });
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
});
|
|
};
|
|
|
|
email.getTemplatePath = async function(view)
|
|
{
|
|
try
|
|
{
|
|
return await getTemplatePathFromRoot(path.resolve('custom/emails'), view, this.config.views.options.extension);
|
|
}
|
|
catch (err)
|
|
{
|
|
return await getTemplatePathFromRoot(this.config.views.root, view, this.config.views.options.extension);
|
|
}
|
|
};
|
|
|
|
|
|
email
|
|
.send({
|
|
template: template,
|
|
message: {
|
|
to: user.email
|
|
},
|
|
locals: locals
|
|
})
|
|
.then(async () =>
|
|
{
|
|
await self.repository.notifications.delete(notification.id);
|
|
console.log('Notification sent to: ' + user.email);
|
|
resolve();
|
|
})
|
|
.catch(async (error) =>
|
|
{
|
|
console.log(error);
|
|
notification.attempt++;
|
|
if (notification.attempt > config.notifications.maxAttempts)
|
|
await self.repository.notifications.delete(notification.id);
|
|
else
|
|
await self.repository.notifications.update(notification);
|
|
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = NotificationWorker; |