You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/topics/follow.js

244 lines
6.3 KiB
JavaScript

'use strict';
var async = require('async');
var db = require('../database');
var posts = require('../posts');
var notifications = require('../notifications');
var privileges = require('../privileges');
var plugins = require('../plugins');
var utils = require('../utils');
module.exports = function (Topics) {
Topics.toggleFollow = function (tid, uid, callback) {
callback = callback || function () {};
10 years ago
var isFollowing;
async.waterfall([
function (next) {
Topics.exists(tid, next);
},
function (exists, next) {
if (!exists) {
return next(new Error('[[error:no-topic]]'));
}
Topics.isFollowing([tid], uid, next);
},
function (_isFollowing, next) {
isFollowing = _isFollowing[0];
if (isFollowing) {
Topics.unfollow(tid, uid, next);
} else {
Topics.follow(tid, uid, next);
}
},
function (next) {
10 years ago
next(null, !isFollowing);
},
10 years ago
], callback);
};
Topics.follow = function (tid, uid, callback) {
setWatching(follow, unignore, 'action:topic.follow', tid, uid, callback);
10 years ago
};
Topics.unfollow = function (tid, uid, callback) {
setWatching(unfollow, unignore, 'action:topic.unfollow', tid, uid, callback);
9 years ago
};
Topics.ignore = function (tid, uid, callback) {
setWatching(ignore, unfollow, 'action:topic.ignore', tid, uid, callback);
};
function setWatching(method1, method2, hook, tid, uid, callback) {
callback = callback || function () {};
if (!parseInt(uid, 10)) {
return callback();
}
9 years ago
async.waterfall([
function (next) {
Topics.exists(tid, next);
},
function (exists, next) {
if (!exists) {
return next(new Error('[[error:no-topic]]'));
}
method1(tid, uid, next);
9 years ago
},
function (next) {
method2(tid, uid, next);
9 years ago
},
function (next) {
plugins.fireHook(hook, { uid: uid, tid: tid });
next();
},
9 years ago
], callback);
}
9 years ago
function follow(tid, uid, callback) {
addToSets('tid:' + tid + ':followers', 'uid:' + uid + ':followed_tids', tid, uid, callback);
9 years ago
}
function unfollow(tid, uid, callback) {
removeFromSets('tid:' + tid + ':followers', 'uid:' + uid + ':followed_tids', tid, uid, callback);
9 years ago
}
function ignore(tid, uid, callback) {
addToSets('tid:' + tid + ':ignorers', 'uid:' + uid + ':ignored_tids', tid, uid, callback);
}
function unignore(tid, uid, callback) {
removeFromSets('tid:' + tid + ':ignorers', 'uid:' + uid + ':ignored_tids', tid, uid, callback);
}
function addToSets(set1, set2, tid, uid, callback) {
9 years ago
async.waterfall([
function (next) {
db.setAdd(set1, uid, next);
9 years ago
},
function (next) {
db.sortedSetAdd(set2, Date.now(), tid, next);
},
9 years ago
], callback);
}
function removeFromSets(set1, set2, tid, uid, callback) {
9 years ago
async.waterfall([
function (next) {
db.setRemove(set1, uid, next);
9 years ago
},
function (next) {
db.sortedSetRemove(set2, tid, next);
},
9 years ago
], callback);
}
Topics.isFollowing = function (tids, uid, callback) {
isIgnoringOrFollowing('followers', tids, uid, callback);
};
Topics.isIgnoring = function (tids, uid, callback) {
isIgnoringOrFollowing('ignorers', tids, uid, callback);
};
function isIgnoringOrFollowing(set, tids, uid, callback) {
9 years ago
if (!Array.isArray(tids)) {
return callback();
}
if (!parseInt(uid, 10)) {
return callback(null, tids.map(function () { return false; }));
9 years ago
}
var keys = tids.map(function (tid) {
return 'tid:' + tid + ':' + set;
9 years ago
});
db.isMemberOfSets(keys, uid, callback);
}
9 years ago
Topics.getFollowers = function (tid, callback) {
db.getSetMembers('tid:' + tid + ':followers', callback);
};
Topics.getIgnorers = function (tid, callback) {
9 years ago
db.getSetMembers('tid:' + tid + ':ignorers', callback);
};
Topics.filterIgnoringUids = function (tid, uids, callback) {
9 years ago
async.waterfall([
function (next) {
db.isSetMembers('tid:' + tid + ':ignorers', uids, next);
9 years ago
},
function (isIgnoring, next) {
var readingUids = uids.filter(function (uid, index) {
return uid && !isIgnoring[index];
9 years ago
});
next(null, readingUids);
},
9 years ago
], callback);
};
Topics.filterWatchedTids = function (tids, uid, callback) {
8 years ago
async.waterfall([
function (next) {
db.sortedSetScores('uid:' + uid + ':followed_tids', tids, next);
},
function (scores, next) {
tids = tids.filter(function (tid, index) {
return tid && !!scores[index];
});
next(null, tids);
},
], callback);
};
Topics.filterNotIgnoredTids = function (tids, uid, callback) {
8 years ago
async.waterfall([
function (next) {
db.sortedSetScores('uid:' + uid + ':ignored_tids', tids, next);
},
function (scores, next) {
tids = tids.filter(function (tid, index) {
return tid && !scores[index];
});
next(null, tids);
},
], callback);
};
Topics.notifyFollowers = function (postData, exceptUid, callback) {
callback = callback || function () {};
var followers;
var title;
var titleEscaped;
10 years ago
async.waterfall([
function (next) {
10 years ago
Topics.getFollowers(postData.topic.tid, next);
},
function (followers, next) {
10 years ago
var index = followers.indexOf(exceptUid.toString());
if (index !== -1) {
followers.splice(index, 1);
}
10 years ago
privileges.topics.filterUids('read', postData.topic.tid, followers, next);
10 years ago
},
function (_followers, next) {
10 years ago
followers = _followers;
if (!followers.length) {
return callback();
}
title = postData.topic.title;
10 years ago
if (title) {
title = utils.decodeHTMLEntities(title);
titleEscaped = title.replace(/%/g, '%').replace(/,/g, ',');
11 years ago
}
8 years ago
postData.content = posts.relativeToAbsolute(postData.content, posts.urlRegex);
postData.content = posts.relativeToAbsolute(postData.content, posts.imgRegex);
10 years ago
notifications.create({
8 years ago
type: 'new-reply',
7 years ago
subject: title,
bodyShort: '[[notifications:user_posted_to, ' + postData.user.username + ', ' + titleEscaped + ']]',
10 years ago
bodyLong: postData.content,
pid: postData.pid,
path: '/post/' + postData.pid,
nid: 'new_post:tid:' + postData.topic.tid + ':pid:' + postData.pid + ':uid:' + exceptUid,
10 years ago
tid: postData.topic.tid,
9 years ago
from: exceptUid,
mergeId: 'notifications:user_posted_to|' + postData.topic.tid,
topicTitle: title,
}, next);
10 years ago
},
function (notification, next) {
if (notification) {
notifications.push(notification, followers);
}
10 years ago
next();
},
10 years ago
], callback);
};
};