mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-05 19:08:22 +02:00
@@ -305,4 +305,23 @@ var privileges = require('./privileges');
|
||||
return tree;
|
||||
};
|
||||
|
||||
Categories.getIgnorers = function(cid, start, stop, callback) {
|
||||
db.getSortedSetRevRange('cid:' + cid + ':ignorers', start, stop, callback);
|
||||
};
|
||||
|
||||
Categories.filterIgnoringUids = function(cid, uids, callback) {
|
||||
async.waterfall([
|
||||
function (next){
|
||||
db.sortedSetScores('cid:' + cid + ':ignorers', uids, next);
|
||||
},
|
||||
function (scores, next) {
|
||||
var readingUids = uids.filter(function(uid, index) {
|
||||
return uid && !!scores[index];
|
||||
});
|
||||
next(null, readingUids);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
|
||||
}(exports));
|
||||
|
||||
@@ -38,6 +38,7 @@ module.exports = function(Categories) {
|
||||
'cid:' + cid + ':tids:posts',
|
||||
'cid:' + cid + ':pids',
|
||||
'cid:' + cid + ':read_by_uid',
|
||||
'cid:' + cid + ':ignorers',
|
||||
'cid:' + cid + ':children',
|
||||
'category:' + cid
|
||||
], next);
|
||||
|
||||
@@ -4,6 +4,7 @@ var async = require('async');
|
||||
var winston = require('winston');
|
||||
var S = require('string');
|
||||
|
||||
var db = require('../database');
|
||||
var websockets = require('./index');
|
||||
var user = require('../user');
|
||||
var posts = require('../posts');
|
||||
@@ -27,6 +28,9 @@ SocketHelpers.notifyNew = function(uid, type, result) {
|
||||
function(uids, next) {
|
||||
privileges.topics.filterUids('read', result.posts[0].topic.tid, uids, next);
|
||||
},
|
||||
function(uids, next) {
|
||||
filterTidCidIgnorers(uids, result.posts[0].topic.tid, result.posts[0].topic.cid, next);
|
||||
},
|
||||
function(uids, next) {
|
||||
plugins.fireHook('filter:sockets.sendNewPostToUids', {uidsTo: uids, uidFrom: uid, type: type}, next);
|
||||
}
|
||||
@@ -48,6 +52,31 @@ SocketHelpers.notifyNew = function(uid, type, result) {
|
||||
});
|
||||
};
|
||||
|
||||
function filterTidCidIgnorers(uids, tid, cid, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
topicFollowed: function(next) {
|
||||
db.isSetMembers('tid:' + tid + ':followers', uids, next);
|
||||
},
|
||||
topicIgnored: function(next) {
|
||||
db.isSetMembers('tid:' + tid + ':ignorers', uids, next);
|
||||
},
|
||||
categoryIgnored: function(next) {
|
||||
db.sortedSetScores('cid:' + cid + ':ignorers', uids, next);
|
||||
}
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
uids = uids.filter(function(uid, index) {
|
||||
return results.topicFollowed[index] ||
|
||||
(!results.topicFollowed[index] && !results.topicIgnored[index] && !results.categoryIgnored[index]);
|
||||
});
|
||||
next(null, uids);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
SocketHelpers.sendNotificationToPostOwner = function(pid, fromuid, notification) {
|
||||
if (!pid || !fromuid || !notification) {
|
||||
return;
|
||||
|
||||
@@ -72,8 +72,15 @@ SocketTopics.createTopicFromPosts = function(socket, data, callback) {
|
||||
topics.createTopicFromPosts(socket.uid, data.title, data.pids, data.fromTid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.toggleFollow = function(socket, tid, callback) {
|
||||
followCommand(topics.toggleFollow, socket, tid, callback);
|
||||
SocketTopics.changeWatching = function(socket, data, callback) {
|
||||
if (!data.tid || !data.type) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
var commands = ['follow', 'unfollow', 'ignore'];
|
||||
if (commands.indexOf(data.type) === -1) {
|
||||
return callback(new Error('[[error:invalid-command]]'));
|
||||
}
|
||||
followCommand(topics[data.type], socket, data.tid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.follow = function(socket, tid, callback) {
|
||||
|
||||
@@ -131,6 +131,9 @@ var social = require('./social');
|
||||
hasRead: function(next) {
|
||||
Topics.hasReadTopics(tids, uid, next);
|
||||
},
|
||||
isIgnored: function(next) {
|
||||
Topics.isIgnoring(tids, uid, next);
|
||||
},
|
||||
bookmarks: function(next) {
|
||||
Topics.getUserBookmarks(tids, uid, next);
|
||||
},
|
||||
@@ -157,7 +160,8 @@ var social = require('./social');
|
||||
topics[i].pinned = parseInt(topics[i].pinned, 10) === 1;
|
||||
topics[i].locked = parseInt(topics[i].locked, 10) === 1;
|
||||
topics[i].deleted = parseInt(topics[i].deleted, 10) === 1;
|
||||
topics[i].unread = !results.hasRead[i];
|
||||
topics[i].ignored = results.isIgnored[i];
|
||||
topics[i].unread = !results.hasRead[i] && !results.isIgnored[i];
|
||||
topics[i].bookmark = results.bookmarks[i];
|
||||
topics[i].unreplied = !topics[i].teaser;
|
||||
}
|
||||
@@ -184,6 +188,7 @@ var social = require('./social');
|
||||
threadTools: async.apply(plugins.fireHook, 'filter:topic.thread_tools', {topic: topicData, uid: uid, tools: []}),
|
||||
tags: async.apply(Topics.getTopicTagsObjects, topicData.tid),
|
||||
isFollowing: async.apply(Topics.isFollowing, [topicData.tid], uid),
|
||||
isIgnoring: async.apply(Topics.isIgnoring, [topicData.tid], uid),
|
||||
bookmark: async.apply(Topics.getUserBookmark, topicData.tid, uid),
|
||||
postSharing: async.apply(social.getActivePostSharing)
|
||||
}, next);
|
||||
@@ -194,6 +199,8 @@ var social = require('./social');
|
||||
topicData.thread_tools = results.threadTools.tools;
|
||||
topicData.tags = results.tags;
|
||||
topicData.isFollowing = results.isFollowing[0];
|
||||
topicData.isNotFollowing = !results.isFollowing[0] && !results.isIgnoring[0];
|
||||
topicData.isIgnoring = results.isIgnoring[0];
|
||||
topicData.bookmark = results.bookmark;
|
||||
topicData.postSharing = results.postSharing;
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ module.exports = function(Topics) {
|
||||
function(next) {
|
||||
db.deleteAll([
|
||||
'tid:' + tid + ':followers',
|
||||
'tid:' + tid + ':ignorers',
|
||||
'tid:' + tid + ':posts',
|
||||
'tid:' + tid + ':posts:votes',
|
||||
'tid:' + tid + ':bookmarks',
|
||||
|
||||
@@ -56,12 +56,12 @@ module.exports = function(Topics) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
db.setAdd('tid:' + tid + ':followers', uid, next);
|
||||
follow(tid, uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'action:topic.follow', { uid: uid, tid: tid }),
|
||||
function(next) {
|
||||
db.sortedSetAdd('uid:' + uid + ':followed_tids', Date.now(), tid, next);
|
||||
}
|
||||
function (next) {
|
||||
unignore(tid, uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'action:topic.follow', {uid: uid, tid: tid})
|
||||
], callback);
|
||||
};
|
||||
|
||||
@@ -75,14 +75,77 @@ module.exports = function(Topics) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
unfollow(tid, uid, next);
|
||||
},
|
||||
function (next) {
|
||||
unignore(tid, uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'action:topic.unfollow', {uid: uid, tid: tid}),
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.ignore = function(tid, uid, callback) {
|
||||
callback = callback || function() {};
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
Topics.exists(tid, next);
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-topic]]'));
|
||||
}
|
||||
ignore(tid, uid, next);
|
||||
},
|
||||
function (next) {
|
||||
unfollow(tid, uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'action:topic.ignore', {uid: uid, tid: tid})
|
||||
], callback);
|
||||
};
|
||||
|
||||
function follow(tid, uid, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setAdd('tid:' + tid + ':followers', uid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('uid:' + uid + ':followed_tids', Date.now(), tid, next);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
function unfollow(tid, uid, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setRemove('tid:' + tid + ':followers', uid, next);
|
||||
},
|
||||
async.apply(plugins.fireHook, 'action:topic.unfollow', { uid: uid, tid: tid }),
|
||||
function(next) {
|
||||
function (next) {
|
||||
db.sortedSetRemove('uid:' + uid + ':followed_tids', tid, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
}
|
||||
|
||||
function ignore(tid, uid, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setAdd('tid:' + tid + ':ignorers', uid, next);
|
||||
},
|
||||
function(next) {
|
||||
db.sortedSetAdd('uid:' + uid + ':ignored_tids', Date.now(), tid, next);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
function unignore(tid, uid, callback) {
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
db.setRemove('tid:' + tid + ':ignorers', uid, next);
|
||||
},
|
||||
function(next) {
|
||||
db.sortedSetRemove('uid:' + uid + ':ignored_tids', tid, next);
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
|
||||
Topics.isFollowing = function(tids, uid, callback) {
|
||||
if (!Array.isArray(tids)) {
|
||||
@@ -97,10 +160,41 @@ module.exports = function(Topics) {
|
||||
db.isMemberOfSets(keys, uid, callback);
|
||||
};
|
||||
|
||||
Topics.isIgnoring = function(tids, uid, callback) {
|
||||
if (!Array.isArray(tids)) {
|
||||
return callback();
|
||||
}
|
||||
if (!parseInt(uid, 10)) {
|
||||
return callback(null, tids.map(function() { return false; }));
|
||||
}
|
||||
var keys = tids.map(function(tid) {
|
||||
return 'tid:' + tid + ':ignorers';
|
||||
});
|
||||
db.isMemberOfSets(keys, uid, callback);
|
||||
};
|
||||
|
||||
Topics.getFollowers = function(tid, callback) {
|
||||
db.getSetMembers('tid:' + tid + ':followers', callback);
|
||||
};
|
||||
|
||||
Topics.getIgnorers = function(tid, callback) {
|
||||
db.getSetMembers('tid:' + tid + ':ignorers', callback);
|
||||
};
|
||||
|
||||
Topics.filterIgnoringUids = function(tid, uids, callback) {
|
||||
async.waterfall([
|
||||
function (next){
|
||||
db.isSetMembers('tid:' + tid + ':ignorers', uids, next);
|
||||
},
|
||||
function (isMembers, next){
|
||||
var readingUids = uids.filter(function(uid, index) {
|
||||
return uid && isMembers[index];
|
||||
});
|
||||
next(null, readingUids);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.notifyFollowers = function(postData, exceptUid, callback) {
|
||||
callback = callback || function() {};
|
||||
var followers;
|
||||
|
||||
@@ -87,6 +87,9 @@ module.exports = function(Topics) {
|
||||
}
|
||||
user.getIgnoredCategories(uid, next);
|
||||
},
|
||||
ignoredTids: function(next) {
|
||||
user.getIgnoredTids(uid, 0, -1, next);
|
||||
},
|
||||
recentTids: function(next) {
|
||||
db.getSortedSetRevRangeByScoreWithScores('topics:recent', 0, -1, '+inf', cutoff, next);
|
||||
},
|
||||
@@ -116,6 +119,9 @@ module.exports = function(Topics) {
|
||||
});
|
||||
|
||||
var tids = results.recentTids.filter(function(recentTopic) {
|
||||
if (results.ignoredTids.indexOf(recentTopic.value.toString()) !== -1) {
|
||||
return false;
|
||||
}
|
||||
switch (filter) {
|
||||
case 'new':
|
||||
return !userRead[recentTopic.value];
|
||||
@@ -138,7 +144,7 @@ module.exports = function(Topics) {
|
||||
|
||||
tids = tids.slice(0, 200);
|
||||
|
||||
filterTopics(uid, tids, cid, ignoredCids, next);
|
||||
filterTopics(uid, tids, cid, ignoredCids, filter, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
@@ -155,7 +161,7 @@ module.exports = function(Topics) {
|
||||
});
|
||||
}
|
||||
|
||||
function filterTopics(uid, tids, cid, ignoredCids, callback) {
|
||||
function filterTopics(uid, tids, cid, ignoredCids, filter, callback) {
|
||||
if (!Array.isArray(ignoredCids) || !tids.length) {
|
||||
return callback(null, tids);
|
||||
}
|
||||
@@ -165,11 +171,24 @@ module.exports = function(Topics) {
|
||||
privileges.topics.filterTids('read', tids, uid, next);
|
||||
},
|
||||
function(tids, next) {
|
||||
Topics.getTopicsFields(tids, ['tid', 'cid'], next);
|
||||
async.parallel({
|
||||
topics: function(next) {
|
||||
Topics.getTopicsFields(tids, ['tid', 'cid'], next);
|
||||
},
|
||||
isTopicsFollowed: function(next) {
|
||||
if (filter === 'watched' || filter === 'new') {
|
||||
return next(null, []);
|
||||
}
|
||||
db.sortedSetScores('uid:' + uid + ':followed_tids', tids, next);
|
||||
}
|
||||
}, next);
|
||||
},
|
||||
function(topics, next) {
|
||||
tids = topics.filter(function(topic) {
|
||||
return topic && topic.cid && ignoredCids.indexOf(topic.cid.toString()) === -1 && (!cid || parseInt(cid, 10) === parseInt(topic.cid, 10));
|
||||
function(results, next) {
|
||||
var topics = results.topics;
|
||||
tids = topics.filter(function(topic, index) {
|
||||
return topic && topic.cid &&
|
||||
(!!results.isTopicsFollowed[index] || ignoredCids.indexOf(topic.cid.toString()) === -1) &&
|
||||
(!cid || parseInt(cid, 10) === parseInt(topic.cid, 10));
|
||||
}).map(function(topic) {
|
||||
return topic.tid;
|
||||
});
|
||||
|
||||
13
src/user.js
13
src/user.js
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
var async = require('async');
|
||||
|
||||
plugins = require('./plugins'),
|
||||
db = require('./database'),
|
||||
topics = require('./topics'),
|
||||
privileges = require('./privileges'),
|
||||
utils = require('../public/src/utils');
|
||||
var plugins = require('./plugins');
|
||||
var db = require('./database');
|
||||
var topics = require('./topics');
|
||||
var privileges = require('./privileges');
|
||||
var utils = require('../public/src/utils');
|
||||
|
||||
(function(User) {
|
||||
|
||||
@@ -19,6 +19,7 @@ var async = require('async'),
|
||||
require('./user/auth')(User);
|
||||
require('./user/create')(User);
|
||||
require('./user/posts')(User);
|
||||
require('./user/topics')(User);
|
||||
require('./user/categories')(User);
|
||||
require('./user/follow')(User);
|
||||
require('./user/profile')(User);
|
||||
|
||||
@@ -45,6 +45,9 @@ module.exports = function(User) {
|
||||
return next(new Error('[[error:no-category]]'));
|
||||
}
|
||||
db.sortedSetAdd('uid:' + uid + ':ignored:cids', Date.now(), cid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetAdd('cid:' + cid + ':ignorers', Date.now(), uid, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
@@ -63,6 +66,9 @@ module.exports = function(User) {
|
||||
return next(new Error('[[error:no-category]]'));
|
||||
}
|
||||
db.sortedSetRemove('uid:' + uid + ':ignored:cids', cid, next);
|
||||
},
|
||||
function (next) {
|
||||
db.sortedSetRemove('cid:' + cid + ':ignorers', uid, next);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
@@ -102,8 +102,12 @@ module.exports = function(User) {
|
||||
},
|
||||
function(next) {
|
||||
var keys = [
|
||||
'uid:' + uid + ':notifications:read', 'uid:' + uid + ':notifications:unread',
|
||||
'uid:' + uid + ':favourites', 'uid:' + uid + ':followed_tids', 'user:' + uid + ':settings',
|
||||
'uid:' + uid + ':notifications:read',
|
||||
'uid:' + uid + ':notifications:unread',
|
||||
'uid:' + uid + ':favourites',
|
||||
'uid:' + uid + ':followed_tids',
|
||||
'uid:' + uid + ':ignored_tids',
|
||||
'user:' + uid + ':settings',
|
||||
'uid:' + uid + ':topics', 'uid:' + uid + ':posts',
|
||||
'uid:' + uid + ':chats', 'uid:' + uid + ':chats:unread',
|
||||
'uid:' + uid + ':chat:rooms', 'uid:' + uid + ':chat:rooms:unread',
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
db = require('../database'),
|
||||
meta = require('../meta'),
|
||||
privileges = require('../privileges');
|
||||
var async = require('async');
|
||||
var db = require('../database');
|
||||
var meta = require('../meta');
|
||||
var privileges = require('../privileges');
|
||||
|
||||
module.exports = function(User) {
|
||||
|
||||
@@ -83,13 +83,6 @@ module.exports = function(User) {
|
||||
db.sortedSetAdd('uid:' + uid + ':posts', timestamp, pid, callback);
|
||||
};
|
||||
|
||||
User.addTopicIdToUser = function(uid, tid, timestamp, callback) {
|
||||
async.parallel([
|
||||
async.apply(db.sortedSetAdd, 'uid:' + uid + ':topics', timestamp, tid),
|
||||
async.apply(User.incrementUserFieldBy, uid, 'topiccount', 1)
|
||||
], callback);
|
||||
};
|
||||
|
||||
User.incrementUserPostCountBy = function(uid, value, callback) {
|
||||
callback = callback || function() {};
|
||||
User.incrementUserFieldBy(uid, 'postcount', value, function(err, newpostcount) {
|
||||
|
||||
19
src/user/topics.js
Normal file
19
src/user/topics.js
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async');
|
||||
var db = require('../database');
|
||||
|
||||
module.exports = function(User) {
|
||||
|
||||
User.getIgnoredTids = function(uid, start, stop, callback) {
|
||||
db.getSortedSetRevRange('uid:' + uid + ':ignored_tids', start, stop, callback);
|
||||
};
|
||||
|
||||
User.addTopicIdToUser = function(uid, tid, timestamp, callback) {
|
||||
async.parallel([
|
||||
async.apply(db.sortedSetAdd, 'uid:' + uid + ':topics', timestamp, tid),
|
||||
async.apply(User.incrementUserFieldBy, uid, 'topiccount', 1)
|
||||
], callback);
|
||||
};
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user