email service

This commit is contained in:
Ivan Socolsky 2015-04-29 00:34:18 -03:00
parent 39b254b163
commit 12232dbe16
4 changed files with 164 additions and 17 deletions

111
lib/emailservice.js Normal file
View File

@ -0,0 +1,111 @@
'use strict';
var _ = require('lodash');
var $ = require('preconditions').singleton();
var async = require('async');
var log = require('npmlog');
log.debug = log.verbose;
var fs = require('fs');
var Model = require('./model');
var EMAIL_TYPES = {
'NewTxProposal': {
filename: 'new_tx_proposal',
notifyCreator: false,
notifyDoer: false,
},
'NewOutgoingTx': {
filename: 'new_outgoing_tx',
notifyCreator: true,
notifyDoer: true,
},
'NewIncomingTx': {
filename: 'new_incoming_tx',
notifyCreator: true,
notifyDoer: true,
},
'TxProposalFinallyRejected': {
filename: 'txp_finally_rejected',
notifyCreator: true,
notifyDoer: false,
},
};
function EmailService(opts) {
this.storage = opts.storage;
this.lock = opts.lock;
};
EmailService.prototype._readTemplate = function(filename, cb) {
fs.readFile(__dirname + '/templates/' + filename + '.plain', 'utf8', function(err, template) {
var lines = template.split('\n');
return cb(null, {
subject: _.template(lines[0]),
body: _.template(_.rest(lines).join('\n')),
});
});
};
EmailService.prototype._applyTemplate = function(template, data, cb) {
var result = _.mapValues(template, function(t) {
// TODO: If this throws exception, log and abort email generation
return t(data);
});
return cb(null, result);
};
EmailService.prototype._generateFromNotification = function(notification, cb) {
var self = this;
var emailType = EMAIL_TYPES[notification.type];
if (!emailType) return cb();
self.storage.fetchPreferences(notification.walletId, null, function(err, preferences) {
if (_.isEmpty(preferences)) return cb();
var addressesByCopayer = _.reduce(preferences, function(memo, p) {
if (p.email) {
memo[p.copayerId] = p.email;
}
return memo;
}, {});
if (_.isEmpty(addressesByCopayer)) return cb();
self._readTemplate(emailType.filename, function(err, template) {
if (err) return cb(err);
self._applyTemplate(template, notification.data, function(err, content) {
if (err) return cb(err);
_.each(addressesByCopayer, function(emailAddress, copayerId) {
var email = Model.Email.create({
walletId: notification.walletId,
copayerId: copayerId,
to: emailAddress,
subject: content.subject,
body: content.body,
});
self.storage.storeEmail(email, function(err) {
return cb(err);
});
});
});
});
});
return cb();
};
EmailService.prototype._send = function(cb) {
var self = this;
this.lock.runLocked('emails', cb, function() {
//self._fetchUnsentEmails();
});
};
module.exports = EmailService;

View File

@ -18,13 +18,19 @@ var Lock = require('./lock');
var Storage = require('./storage');
var MessageBroker = require('./messagebroker');
var BlockchainExplorer = require('./blockchainexplorer');
var EmailService = require('./emailservice');
var Model = require('./model');
var Wallet = Model.Wallet;
var initialized = false;
var lock, storage, blockchainExplorer, blockchainExplorerOpts;
var lock;
var storage;
var blockchainExplorer;
var blockchainExplorerOpts;
var messageBroker;
var emailService;
/**
@ -41,6 +47,7 @@ function WalletService() {
this.blockchainExplorerOpts = blockchainExplorerOpts;
this.messageBroker = messageBroker;
this.notifyTicker = 0;
this.emailService = emailService;
};
/**
@ -58,20 +65,28 @@ WalletService.initialize = function(opts, cb) {
blockchainExplorer = opts.blockchainExplorer;
blockchainExplorerOpts = opts.blockchainExplorerOpts;
if (initialized)
return cb();
if (initialized) return cb();
function initStorage(cb) {
if (opts.storage) {
storage = opts.storage;
return cb();
} else {
var newStorage = new Storage();
newStorage.connect(opts.storageOpts, function(err) {
if (err) return cb(err);
storage = newStorage;
return cb();
});
}
var newStorage = new Storage();
newStorage.connect(opts.storageOpts, function(err) {
if (err) return cb(err);
storage = newStorage;
return cb();
};
function initEmailService(cb) {
emailService = new EmailService({
lock: lock,
storage: storage,
});
return cb();
};
function initMessageBroker(cb) {
@ -91,11 +106,15 @@ WalletService.initialize = function(opts, cb) {
function(next) {
initMessageBroker(next);
},
function(next) {
initEmailService(next);
},
], function(err) {
if (err) {
log.error('Could not initialize', err);
throw err;
}
], function() {
initialized = true;
return cb();
});
@ -331,9 +350,12 @@ WalletService.prototype._notify = function(type, data, opts, cb) {
creatorId: opts.isGlobal ? null : copayerId,
walletId: walletId,
});
this.storage.storeNotification(walletId, n, function() {
self.messageBroker.send(n);
if (cb) return cb();
this.storage.storeNotification(walletId, notification, function() {
self.messageBroker.send(notification);
self.emailService._generateFromNotification(notification, function() {
if (cb) return cb();
});
});
};

View File

@ -356,13 +356,25 @@ Storage.prototype.fetchAddress = function(address, cb) {
};
Storage.prototype.fetchPreferences = function(walletId, copayerId, cb) {
this.db.collection(collections.PREFERENCES).findOne({
this.db.collection(collections.PREFERENCES).find({
walletId: walletId,
copayerId: copayerId,
}, function(err, result) {
}).toArray(function(err, result) {
if (err) return cb(err);
if (copayerId) {
result = _.find(result, {
copayerId: copayerId
});
}
if (!result) return cb();
return cb(null, Model.Preferences.fromObj(result));
var preferences = _.map([].concat(result), function(r) {
return Model.Preferences.fromObj(r);
});
if (copayerId) {
preferences = preferences[0];
}
return cb(null, preferences);
});
};
@ -379,7 +391,7 @@ Storage.prototype.storePreferences = function(preferences, cb) {
Storage.prototype.storeEmail = function(email, cb) {
this.db.collection(collections.EMAIL_QUEUE).update({
id: email.id,
}, txp, {
}, email, {
w: 1,
upsert: true,
}, cb);
@ -388,7 +400,7 @@ Storage.prototype.storeEmail = function(email, cb) {
Storage.prototype.fetchUnsentEmails = function(cb) {
this.db.collection(collections.EMAIL_QUEUE).find({
status: 'pending',
}, function(err, result) {
}).toArray(function(err, result) {
if (err) return cb(err);
if (!result) return cb();
return cb(null, Model.Email.fromObj(result));

View File

@ -0,0 +1,2 @@
New transaction proposal!
A new transaction proposal has been created by another copayer.