|
|
|
var RDB = require('./redis.js'),
|
|
|
|
topics = require('./topics.js'),
|
|
|
|
categories = require('./categories.js'),
|
|
|
|
user = require('./user.js'),
|
|
|
|
async = require('async'),
|
|
|
|
notifications = require('./notifications.js');
|
|
|
|
|
|
|
|
(function(ThreadTools) {
|
|
|
|
|
|
|
|
ThreadTools.exists = function(tid, callback) {
|
|
|
|
RDB.sismember('topics:tid', tid, function(err, ismember) {
|
|
|
|
if (err) RDB.handle(err);
|
|
|
|
callback(!!ismember || false);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.privileges = function(tid, uid, callback) {
|
|
|
|
//todo: break early if one condition is true
|
|
|
|
|
|
|
|
function getCategoryPrivileges(next) {
|
|
|
|
topics.getTopicField(tid, 'cid', function(cid) {
|
|
|
|
categories.privileges(cid, uid, function(privileges) {
|
|
|
|
next(null, privileges);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasEnoughRep(next) {
|
|
|
|
user.getUserField(uid, 'reputation', function(reputation) {
|
|
|
|
next(null, reputation >= global.config['privileges:manage_topic']);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async.parallel([getCategoryPrivileges, hasEnoughRep], function(err, results) {
|
|
|
|
callback({
|
|
|
|
editable: results[0].editable || (results.slice(1).indexOf(true) !== -1 ? true : false),
|
|
|
|
view_deleted: results[0].view_deleted || (results.slice(1).indexOf(true) !== -1 ? true : false)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.lock = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
topics.setTopicField(tid, 'locked', 1);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_locked', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.lock', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.unlock = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
topics.setTopicField(tid, 'locked', 0);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_unlocked', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.unlock', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.delete = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
|
|
|
|
topics.setTopicField(tid, 'deleted', 1);
|
|
|
|
ThreadTools.lock(tid, uid);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_deleted', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.delete', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.restore = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
|
|
|
|
topics.setTopicField(tid, 'deleted', 0);
|
|
|
|
ThreadTools.unlock(tid, uid);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_restored', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.restore', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.pin = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
|
|
|
|
topics.setTopicField(tid, 'pinned', 1);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_pinned', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.pin', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.unpin = function(tid, uid, socket) {
|
|
|
|
ThreadTools.privileges(tid, uid, function(privileges) {
|
|
|
|
if (privileges.editable) {
|
|
|
|
|
|
|
|
topics.setTopicField(tid, 'pinned', 0);
|
|
|
|
|
|
|
|
if (socket) {
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_unpinned', {
|
|
|
|
tid: tid,
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.unpin', {
|
|
|
|
status: 'ok',
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.move = function(tid, cid, socket) {
|
|
|
|
|
|
|
|
topics.getTopicField(tid, 'cid', function(oldCid) {
|
|
|
|
|
|
|
|
RDB.smove('categories:' + oldCid + ':tid', 'categories:' + cid + ':tid', tid, function(err, result) {
|
|
|
|
if (!err && result === 1) {
|
|
|
|
|
|
|
|
topics.setTopicField(tid, 'cid', cid);
|
|
|
|
|
|
|
|
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1);
|
|
|
|
categories.incrementCategoryFieldBy(cid, 'topic_count', 1);
|
|
|
|
|
|
|
|
categories.getCategories([cid], function(data) {
|
|
|
|
topics.setTopicField(tid, 'category_name', data.categories[0].name);
|
|
|
|
topics.setTopicField(tid, 'category_slug', data.categories[0].slug);
|
|
|
|
});
|
|
|
|
|
|
|
|
socket.emit('api:topic.move', {
|
|
|
|
status: 'ok'
|
|
|
|
});
|
|
|
|
io.sockets.in('topic_' + tid).emit('event:topic_moved', {
|
|
|
|
tid: tid
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
socket.emit('api:topic.move', {
|
|
|
|
status: 'error'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.isFollowing = function(tid, current_user, callback) {
|
|
|
|
RDB.sismember('tid:' + tid + ':followers', current_user, function(err, following) {
|
|
|
|
callback(following);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.toggleFollow = function(tid, current_user, callback) {
|
|
|
|
ThreadTools.isFollowing(tid, current_user, function(following) {
|
|
|
|
if (!following) {
|
|
|
|
RDB.sadd('tid:' + tid + ':followers', current_user, function(err, success) {
|
|
|
|
if (callback) {
|
|
|
|
if (!err) {
|
|
|
|
callback({
|
|
|
|
status: 'ok',
|
|
|
|
follow: true
|
|
|
|
});
|
|
|
|
} else callback({ status: 'error' });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
RDB.srem('tid:' + tid + ':followers', current_user, function(err, success) {
|
|
|
|
if (callback) {
|
|
|
|
if (!err) {
|
|
|
|
callback({
|
|
|
|
status: 'ok',
|
|
|
|
follow: false
|
|
|
|
});
|
|
|
|
} else callback({ status: 'error' });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.get_followers = function(tid, callback) {
|
|
|
|
RDB.smembers('tid:' + tid + ':followers', function(err, followers) {
|
|
|
|
callback(err, followers);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
ThreadTools.notify_followers = function(tid, exceptUid) {
|
|
|
|
async.parallel([
|
|
|
|
function(next) {
|
|
|
|
|
|
|
|
topics.getTopicField(tid, 'title', function(title) {
|
|
|
|
topics.getTeaser(tid, function(err, teaser) {
|
|
|
|
if (!err) {
|
|
|
|
notifications.create(teaser.username + ' has posted a reply to: "' + title + '"', null, '/topic/' + tid, 'topic:' + tid, function(nid) {
|
|
|
|
next(null, nid);
|
|
|
|
});
|
|
|
|
} else next(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
function(next) {
|
|
|
|
ThreadTools.get_followers(tid, function(err, followers) {
|
|
|
|
if (followers.indexOf(exceptUid) !== -1) followers.splice(followers.indexOf(exceptUid), 1);
|
|
|
|
next(null, followers);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
], function(err, results) {
|
|
|
|
if (!err) notifications.push(results[0], results[1]);
|
|
|
|
// Otherwise, do nothing
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
}(exports));
|