diff --git a/src/database/redis/sorted/add.js b/src/database/redis/sorted/add.js index e60d079eac..5a21639be4 100644 --- a/src/database/redis/sorted/add.js +++ b/src/database/redis/sorted/add.js @@ -33,6 +33,9 @@ module.exports = function (redisClient, module) { module.sortedSetsAdd = function (keys, score, value, callback) { callback = callback || function () {}; + if (!Array.isArray(keys) || !keys.length) { + return callback(); + } var multi = redisClient.multi(); for (var i = 0; i < keys.length; i += 1) { diff --git a/src/groups/delete.js b/src/groups/delete.js index 3ee69722c7..6494eeb0ba 100644 --- a/src/groups/delete.js +++ b/src/groups/delete.js @@ -26,6 +26,7 @@ module.exports = function (Groups) { async.apply(db.delete, 'group:' + groupName + ':pending'), async.apply(db.delete, 'group:' + groupName + ':invited'), async.apply(db.delete, 'group:' + groupName + ':owners'), + async.apply(db.delete, 'group:' + groupName + ':member:pids'), async.apply(db.deleteObjectField, 'groupslug:groupname', utils.slugify(groupName)), function (next) { db.getSortedSetRange('groups:createtime', 0, -1, function (err, groups) { diff --git a/src/groups/posts.js b/src/groups/posts.js index 2fc40cac37..d8d4b8ab4c 100644 --- a/src/groups/posts.js +++ b/src/groups/posts.js @@ -7,21 +7,62 @@ var privileges = require('../privileges'); var posts = require('../posts'); module.exports = function (Groups) { - Groups.getLatestMemberPosts = function (groupName, max, uid, callback) { + + Groups.onNewPostMade = function (postData, callback) { + if (!parseInt(postData.uid, 10)) { + return setImmediate(callback); + } + + var groupNames; async.waterfall([ function (next) { - Groups.getMembers(groupName, 0, 100, next); + Groups.getUserGroupMembership('groups:visible:createtime', [postData.uid], next); }, - function (uids, next) { - if (!Array.isArray(uids) || !uids.length) { - return callback(null, []); - } - var keys = uids.map(function (uid) { - return 'uid:' + uid + ':posts'; + function (_groupNames, next) { + groupNames = _groupNames[0]; + + var keys = groupNames.map(function (groupName) { + return 'group:' + groupName + ':member:pids'; }); - db.getSortedSetRevRange(keys, 0, max - 1, next); + + db.sortedSetsAdd(keys, postData.timestamp, postData.pid, next); + }, + function (next) { + async.each(groupNames, function (groupName, next) { + truncateMemberPosts(groupName, next); + }, next); + }, + ], callback); + }; + + function truncateMemberPosts(groupName, callback) { + async.waterfall([ + function (next) { + db.getSortedSetRevRange('group:' + groupName + ':member:pids', 10, 10, next); + }, + function (lastPid, next) { + lastPid = lastPid[0]; + if (!parseInt(lastPid, 10)) { + return callback(); + } + db.sortedSetScore('group:' + groupName + ':member:pids', lastPid, next); + }, + function (score, next) { + db.sortedSetsRemoveRangeByScore(['group:' + groupName + ':member:pids'], '-inf', score, next); + }, + ], callback); + } + + Groups.getLatestMemberPosts = function (groupName, max, uid, callback) { + async.waterfall([ + function (next) { + db.getSortedSetRevRange('group:' + groupName + ':member:pids', 0, max - 1, next); }, function (pids, next) { + if (!Array.isArray(pids) || !pids.length) { + return callback(null, []); + } + privileges.posts.filter('read', pids, uid, next); }, function (pids, next) { diff --git a/src/groups/user.js b/src/groups/user.js index 9a68478ade..1f580f57cc 100644 --- a/src/groups/user.js +++ b/src/groups/user.js @@ -22,6 +22,19 @@ module.exports = function (Groups) { }; Groups.getUserGroupsFromSet = function (set, uids, callback) { + async.waterfall([ + function (next) { + Groups.getUserGroupMembership(set, uids, next); + }, + function (memberOf, next) { + async.map(memberOf, function(memberOf, next) { + Groups.getGroupsData(memberOf, next); + }, next); + }, + ], callback); + }; + + Groups.getUserGroupMembership = function(set, uids, callback) { async.waterfall([ function (next) { db.getSortedSetRevRange(set, 0, -1, next); @@ -40,7 +53,7 @@ module.exports = function (Groups) { } }); - Groups.getGroupsData(memberOf, next); + next(null, memberOf); }, ], next); }, next); diff --git a/src/posts/create.js b/src/posts/create.js index 09c4e9c9b7..75b0f8321e 100644 --- a/src/posts/create.js +++ b/src/posts/create.js @@ -9,6 +9,7 @@ var plugins = require('../plugins'); var user = require('../user'); var topics = require('../topics'); var categories = require('../categories'); +var groups = require('../groups'); var utils = require('../utils'); module.exports = function (Posts) { @@ -82,6 +83,9 @@ module.exports = function (Posts) { categories.onNewPostMade(topicData.cid, topicData.pinned, postData, next); }); }, + function (next) { + groups.onNewPostMade(postData, next); + }, function (next) { db.sortedSetAdd('posts:pid', timestamp, postData.pid, next); }, diff --git a/src/posts/delete.js b/src/posts/delete.js index a2874770af..eb5730bcd0 100644 --- a/src/posts/delete.js +++ b/src/posts/delete.js @@ -6,6 +6,7 @@ var _ = require('underscore'); var db = require('../database'); var topics = require('../topics'); var user = require('../user'); +var groups = require('../groups'); var notifications = require('../notifications'); var plugins = require('../plugins'); @@ -141,6 +142,9 @@ module.exports = function (Posts) { function (next) { deletePostFromReplies(pid, next); }, + function (next) { + deletePostFromGroups(pid, next); + }, function (next) { db.sortedSetsRemove(['posts:pid', 'posts:flagged'], pid, next); }, @@ -294,4 +298,27 @@ module.exports = function (Posts) { ], callback); }); } + + function deletePostFromGroups(pid, callback) { + async.waterfall([ + function (next) { + Posts.getPostField(pid, 'uid', next); + }, + function (uid, next) { + if (!parseInt(uid, 10)) { + return callback(); + } + groups.getUserGroupMembership('groups:visible:createtime', [uid], next); + }, + function (groupNames, next) { + groupNames = groupNames[0]; + var keys = groupNames.map(function (groupName) { + return 'group:' + groupName + ':member:pids'; + }); + + db.sortedSetsRemove(keys, pid, next); + }, + ], callback); + + } };