Loading comments/lib/mailer.js +54 −11 Original line number Diff line number Diff line var nodemailer = require("nodemailer"); var ReplyDetector = require("./reply_detector"); var config = require("../config"); /** Loading @@ -19,26 +20,68 @@ function Mailer(cfg) { Mailer.prototype = { /** * Sends e-mail updates about the comment to all subscribers who * have subscribed to that thread. * Sends e-mail updates about the comment to everybody who need to * be updated about it. This includes: * * - users who have explicitly subscribed to the thread. * - users who are mentioned in the comment using @username syntax. */ sendEmailUpdates: function() { this.db.subscriptions().findUsersByTarget(this.comment.target_id, function(err, users) { // don't send e-mail to the user who posted the comment var otherUsers = users.filter(function(u){ return u.id !== this.comment.user_id; }, this); if (otherUsers.length === 0) { this.getUsersToBeNotified(function(users) { if (users.length === 0) { return; } var emails = otherUsers.map(this.createMessage, this); this.batchSend(users.map(this.createMessage, this)); }.bind(this)); }, getUsersToBeNotified: function(callback) { this.getSubscribers(function(subscribers) { this.getReplyReceivers(function(replyReceivers) { callback(this.merge(subscribers, replyReceivers)); }.bind(this)); }.bind(this)); }, // gives all users who have explicitly subscribed to a thread getSubscribers: function(callback) { this.db.subscriptions().findUsersByTarget(this.comment.target_id, function(err, users) { callback(this.excludeUserWithId(users, this.comment.user_id)); }.bind(this)); }, this.batchSend(emails); // gives users who were referred to in this comment using "@username" syntax. getReplyReceivers: function(callback) { this.db.subscriptions().findImplicitSubscribersByTarget(this.comment.target_id, function(err, users) { var otherUsers = this.excludeUserWithId(users, this.comment.user_id); callback(ReplyDetector.detect(this.comment.content, otherUsers)); }.bind(this)); }, merge: function(target, source) { var userMap = {}; target.forEach(function(user) { if (!userMap[user.id]) { userMap[user.id] = user; } }); source.forEach(function(user) { if (!userMap[user.id]) { userMap[user.id] = user; target.push(user); } }); return target; }, excludeUserWithId: function(users, user_id) { return users.filter(function(u){ return u.id !== user_id; }); }, createMessage: function(user) { var title = this.createTitle(); Loading comments/lib/subscriptions.js +17 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,23 @@ Subscriptions.prototype = { this.db.query(sql, [target_id], callback); }, /** * Gets all users who have posted to the given target. * * @param {Number} target_id ID of the target. * @param {Function} callback Called with the result. * @param {Error} callback.err The error object. * @param {Object[]} callback.users An array of users. */ findImplicitSubscribersByTarget: function(target_id, callback) { var sql = [ "SELECT DISTINCT users.*", "FROM visible_comments JOIN users on visible_comments.user_id = users.id", "WHERE target_id = ?" ]; this.db.query(sql, [target_id], callback); }, /** * Adds new subscription. * @param {Object} subscription Loading comments/spec/subscriptions.spec.js +7 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,13 @@ describe("Subscriptions", function() { }); }); it("#findImplicitSubscribersByTarget returns username and email fields", function(done) { subscriptions.findImplicitSubscribersByTarget(1, function(err, users) { expect(users.map(function(u){return u.username;})).toEqual(["renku", "john", "mary"]); done(); }); }); it("#add adds new subscription", function(done) { subscriptions.add({user_id: 1, target: {type: "guide", cls: "testing", member: ""}}, function(err, id) { subscriptions.findTargetsByUser(1, function(err, subs) { Loading Loading
comments/lib/mailer.js +54 −11 Original line number Diff line number Diff line var nodemailer = require("nodemailer"); var ReplyDetector = require("./reply_detector"); var config = require("../config"); /** Loading @@ -19,26 +20,68 @@ function Mailer(cfg) { Mailer.prototype = { /** * Sends e-mail updates about the comment to all subscribers who * have subscribed to that thread. * Sends e-mail updates about the comment to everybody who need to * be updated about it. This includes: * * - users who have explicitly subscribed to the thread. * - users who are mentioned in the comment using @username syntax. */ sendEmailUpdates: function() { this.db.subscriptions().findUsersByTarget(this.comment.target_id, function(err, users) { // don't send e-mail to the user who posted the comment var otherUsers = users.filter(function(u){ return u.id !== this.comment.user_id; }, this); if (otherUsers.length === 0) { this.getUsersToBeNotified(function(users) { if (users.length === 0) { return; } var emails = otherUsers.map(this.createMessage, this); this.batchSend(users.map(this.createMessage, this)); }.bind(this)); }, getUsersToBeNotified: function(callback) { this.getSubscribers(function(subscribers) { this.getReplyReceivers(function(replyReceivers) { callback(this.merge(subscribers, replyReceivers)); }.bind(this)); }.bind(this)); }, // gives all users who have explicitly subscribed to a thread getSubscribers: function(callback) { this.db.subscriptions().findUsersByTarget(this.comment.target_id, function(err, users) { callback(this.excludeUserWithId(users, this.comment.user_id)); }.bind(this)); }, this.batchSend(emails); // gives users who were referred to in this comment using "@username" syntax. getReplyReceivers: function(callback) { this.db.subscriptions().findImplicitSubscribersByTarget(this.comment.target_id, function(err, users) { var otherUsers = this.excludeUserWithId(users, this.comment.user_id); callback(ReplyDetector.detect(this.comment.content, otherUsers)); }.bind(this)); }, merge: function(target, source) { var userMap = {}; target.forEach(function(user) { if (!userMap[user.id]) { userMap[user.id] = user; } }); source.forEach(function(user) { if (!userMap[user.id]) { userMap[user.id] = user; target.push(user); } }); return target; }, excludeUserWithId: function(users, user_id) { return users.filter(function(u){ return u.id !== user_id; }); }, createMessage: function(user) { var title = this.createTitle(); Loading
comments/lib/subscriptions.js +17 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,23 @@ Subscriptions.prototype = { this.db.query(sql, [target_id], callback); }, /** * Gets all users who have posted to the given target. * * @param {Number} target_id ID of the target. * @param {Function} callback Called with the result. * @param {Error} callback.err The error object. * @param {Object[]} callback.users An array of users. */ findImplicitSubscribersByTarget: function(target_id, callback) { var sql = [ "SELECT DISTINCT users.*", "FROM visible_comments JOIN users on visible_comments.user_id = users.id", "WHERE target_id = ?" ]; this.db.query(sql, [target_id], callback); }, /** * Adds new subscription. * @param {Object} subscription Loading
comments/spec/subscriptions.spec.js +7 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,13 @@ describe("Subscriptions", function() { }); }); it("#findImplicitSubscribersByTarget returns username and email fields", function(done) { subscriptions.findImplicitSubscribersByTarget(1, function(err, users) { expect(users.map(function(u){return u.username;})).toEqual(["renku", "john", "mary"]); done(); }); }); it("#add adds new subscription", function(done) { subscriptions.add({user_id: 1, target: {type: "guide", cls: "testing", member: ""}}, function(err, id) { subscriptions.findTargetsByUser(1, function(err, subs) { Loading