notification changes

-only send a notification when the person you follow creates a topic
-you still get a notification per post if you are following a topic
-changed notifications.push so that it sends the notifications over a
period of time, currently to 50 users per second
-optimized topics.notifyFollowers and
user.notifications.sendTopicNotification, they no longer query the
database for the topic and post data instead they get it as params
-you can no longer follow yourself :)
-changed mongo sortedSetRemove so that it doesn't use $in if there is
only a single value to remove
v1.18.x
barisusakli 11 years ago
parent eb546dfaab
commit 9e8be432b3

@ -18,6 +18,7 @@
"favourited_your_post_in": "<strong>%1</strong> has favourited your post in <strong>%2</strong>.",
"user_flagged_post_in": "<strong>%1</strong> flagged a post in <strong>%2</strong>",
"user_posted_to" : "<strong>%1</strong> has posted a reply to: <strong>%2</strong>",
"user_posted_topic": "<strong>%1</strong> has posted a new topic: <strong>%2</strong>",
"user_mentioned_you_in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
"user_started_following_you": "<strong>%1</strong> started following you.",

@ -61,18 +61,21 @@ module.exports = function(db, module) {
};
module.sortedSetRemove = function(key, value, callback) {
function done(err) {
callback(err);
}
callback = callback || helpers.noop;
if (!key) {
return callback();
}
if (!Array.isArray(value)) {
value = [value];
}
value = value.map(helpers.valueToString);
db.collection('objects').remove({_key: key, value: {$in: value}}, function(err) {
callback(err);
});
if (Array.isArray(value)) {
value = value.map(helpers.valueToString);
db.collection('objects').remove({_key: key, value: {$in: value}}, done);
} else {
value = helpers.valueToString(value);
db.collection('objects').remove({_key: key, value: value}, done);
}
};
module.sortedSetsRemove = function(keys, value, callback) {

@ -128,17 +128,58 @@ var async = require('async'),
return callback();
}
var websockets = require('./socket.io');
if (!Array.isArray(uids)) {
uids = [uids];
}
uids = uids.filter(function(uid) {
return parseInt(uid, 10);
});
if (!uids.length) {
return callback();
}
var done = false;
var start = 0;
var batchSize = 50;
setTimeout(function() {
async.whilst(
function() {
return !done;
},
function(next) {
var currentUids = uids.slice(start, start + batchSize);
if (!currentUids.length) {
done = true;
return next();
}
pushToUids(currentUids, notification, function(err) {
if (err) {
return next(err);
}
start = start + batchSize;
setTimeout(next, 1000);
});
},
function(err) {
if (err) {
winston.error(err.stack);
}
}
);
}, 1000);
callback();
};
function pushToUids(uids, notification, callback) {
var unreadKeys = [];
var readKeys = [];
uids.filter(function(uid) {
return parseInt(uid, 10);
}).forEach(function(uid) {
uids.forEach(function(uid) {
unreadKeys.push('uid:' + uid + ':notifications:unread');
readKeys.push('uid:' + uid + ':notifications:read');
});
@ -163,13 +204,15 @@ var async = require('async'),
}
plugins.fireHook('action:notification.pushed', {notification: notification, uids: uids});
callback();
var websockets = require('./socket.io');
for(var i=0; i<uids.length; ++i) {
websockets.in('uid_' + uids[i]).emit('event:new_notification', notification);
}
callback();
});
};
}
Notifications.pushGroup = function(notification, groupName, callback) {
callback = callback || function() {};

@ -161,6 +161,10 @@ module.exports = function(Topics) {
plugins.fireHook('action:topic.post', data.topicData);
if (parseInt(uid, 10)) {
user.notifications.sendTopicNotificationToFollowers(uid, data.topicData, data.postData);
}
next(null, {
topicData: data.topicData,
postData: data.postData
@ -262,9 +266,7 @@ module.exports = function(Topics) {
postData.relativeTime = utils.toISOString(postData.timestamp);
if (parseInt(uid, 10)) {
Topics.notifyFollowers(tid, postData.pid, uid);
user.notifications.sendPostNotificationToFollowers(uid, tid, postData.pid);
Topics.notifyFollowers(postData.topic, postData, uid);
}
next(null, postData);

@ -21,8 +21,8 @@ module.exports = function(Topics) {
db.getSetMembers('tid:' + tid + ':followers', callback);
};
Topics.notifyFollowers = function(tid, pid, exceptUid) {
Topics.getFollowers(tid, function(err, followers) {
Topics.notifyFollowers = function(topicData, postData, exceptUid) {
Topics.getFollowers(topicData.tid, function(err, followers) {
if (err || !Array.isArray(followers) || !followers.length) {
return;
}
@ -36,34 +36,17 @@ module.exports = function(Topics) {
return;
}
async.parallel({
title: async.apply(Topics.getTopicField, tid, 'title'),
username: async.apply(user.getUserField, exceptUid, 'username'),
postContent: function(next) {
async.waterfall([
async.apply(posts.getPostField, pid, 'content'),
function(content, next) {
postTools.parse(content, next);
}
], next);
notifications.create({
bodyShort: '[[notifications:user_posted_to, ' + postData.user.username + ', ' + topicData.title + ']]',
bodyLong: postData.content,
pid: postData.pid,
nid: 'tid:' + topicData.tid + ':pid:' + postData.pid + ':uid:' + exceptUid,
tid: topicData.tid,
from: exceptUid
}, function(err, notification) {
if (!err && notification) {
notifications.push(notification, followers);
}
}, function(err, results) {
if (err) {
return;
}
notifications.create({
bodyShort: '[[notifications:user_posted_to, ' + results.username + ', ' + results.title + ']]',
bodyLong: results.postContent,
pid: pid,
nid: 'tid:' + tid + ':pid:' + pid + ':uid:' + exceptUid,
tid: tid,
from: exceptUid
}, function(err, notification) {
if (!err && notification) {
notifications.push(notification, followers);
}
});
});
});
};

@ -15,6 +15,14 @@ module.exports = function(User) {
};
function toggleFollow(type, uid, theiruid, callback) {
if (!parseInt(uid, 10) || !parseInt(theiruid, 10)) {
return callback(new Error('[[error:invalid-uid]]'));
}
if (parseInt(uid, 10) === parseInt(theiruid, 10)) {
return callback(new Error('[[error:you-cant-follow-yourself]]'));
}
var command = type === 'follow' ? 'setAdd' : 'setRemove';
db[command]('following:' + uid, theiruid, function(err) {
if(err) {

@ -247,56 +247,28 @@ var async = require('async'),
};
UserNotifications.sendPostNotificationToFollowers = function(uid, tid, pid) {
UserNotifications.sendTopicNotificationToFollowers = function(uid, topicData, postData) {
db.getSetMembers('followers:' + uid, function(err, followers) {
if (err || !Array.isArray(followers) || !followers.length) {
return;
}
async.parallel({
username: async.apply(user.getUserField, uid, 'username'),
topic: async.apply(topics.getTopicFields, tid, ['cid', 'title']),
postContent: function(next) {
async.waterfall([
async.apply(posts.getPostField, pid, 'content'),
function(content, next) {
postTools.parse(content, next);
}
], next);
},
topicFollowers: function(next) {
db.isSetMembers('tid:' + tid + ':followers', followers, next);
}
}, function(err, results) {
if (err) {
return;
}
followers = followers.filter(function(value, index) {
return !results.topicFollowers[index];
});
if (!followers.length) {
privileges.categories.filterUids('read', topicData.cid, followers, function(err, followers) {
if (err || !followers.length) {
return;
}
privileges.categories.filterUids('read', results.topic.cid, followers, function(err, followers) {
if (err || !followers.length) {
return;
notifications.create({
bodyShort: '[[notifications:user_posted_topic, ' + postData.user.username + ', ' + topicData.title + ']]',
bodyLong: postData.content,
pid: postData.pid,
nid: 'tid:' + postData.tid + ':pid:' + postData.pid + ':uid:' + uid,
tid: postData.tid,
from: uid
}, function(err, notification) {
if (!err && notification) {
notifications.push(notification, followers);
}
notifications.create({
bodyShort: '[[notifications:user_posted_to, ' + results.username + ', ' + results.topic.title + ']]',
bodyLong: results.postContent,
pid: pid,
nid: 'tid:' + tid + ':pid:' + pid + ':uid:' + uid,
tid: tid,
from: uid
}, function(err, notification) {
if (!err && notification) {
notifications.push(notification, followers);
}
});
});
});
});

Loading…
Cancel
Save