Commit 1c186adf authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Sending of e-mail updates when @username replies found.

parent 8c05ca54
Loading
Loading
Loading
Loading
+54 −11
Original line number Diff line number Diff line
var nodemailer = require("nodemailer");
var ReplyDetector = require("./reply_detector");
var config = require("../config");

/**
@@ -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();

+17 −0
Original line number Diff line number Diff line
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -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) {