mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-29 10:06:13 +01:00
socketio/posts socketio/topics refactor
This commit is contained in:
@@ -6,23 +6,22 @@ var nconf = require('nconf'),
|
||||
winston = require('winston'),
|
||||
|
||||
topics = require('../topics'),
|
||||
categories = require('../categories'),
|
||||
privileges = require('../privileges'),
|
||||
plugins = require('../plugins'),
|
||||
notifications = require('../notifications'),
|
||||
websockets = require('./index'),
|
||||
user = require('../user'),
|
||||
db = require('../database'),
|
||||
meta = require('../meta'),
|
||||
events = require('../events'),
|
||||
utils = require('../../public/src/utils'),
|
||||
|
||||
|
||||
SocketTopics = {};
|
||||
|
||||
require('./topics/unread')(SocketTopics);
|
||||
require('./topics/move')(SocketTopics);
|
||||
require('./topics/tools')(SocketTopics);
|
||||
require('./topics/infinitescroll')(SocketTopics);
|
||||
require('./topics/tags')(SocketTopics);
|
||||
|
||||
SocketTopics.post = function(socket, data, callback) {
|
||||
if(!data) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
@@ -102,175 +101,11 @@ SocketTopics.bookmark = function(socket, data, callback) {
|
||||
topics.setUserBookmark(data.tid, socket.uid, data.index, callback);
|
||||
};
|
||||
|
||||
SocketTopics.markAsRead = function(socket, tids, callback) {
|
||||
if (!Array.isArray(tids) || !socket.uid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
if (!tids.length) {
|
||||
return callback();
|
||||
}
|
||||
tids = tids.filter(function(tid) {
|
||||
return tid && utils.isNumber(tid);
|
||||
});
|
||||
|
||||
topics.markAsRead(tids, socket.uid, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
|
||||
for (var i=0; i<tids.length; ++i) {
|
||||
topics.markTopicNotificationsRead(tids[i], socket.uid);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.markTopicNotificationsRead = function(socket, tid, callback) {
|
||||
if (!tid || !socket.uid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
topics.markTopicNotificationsRead(tid, socket.uid);
|
||||
};
|
||||
|
||||
SocketTopics.markAllRead = function(socket, data, callback) {
|
||||
db.getSortedSetRevRangeByScore('topics:recent', 0, -1, '+inf', Date.now() - topics.unreadCutoff, function(err, tids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
SocketTopics.markAsRead(socket, tids, callback);
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.markCategoryTopicsRead = function(socket, cid, callback) {
|
||||
topics.getUnreadTids(cid, socket.uid, 0, -1, function(err, tids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
SocketTopics.markAsRead(socket, tids, callback);
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.markAsUnreadForAll = function(socket, tids, callback) {
|
||||
if (!Array.isArray(tids)) {
|
||||
return callback(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
user.isAdministrator(socket.uid, function(err, isAdmin) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.each(tids, function(tid, next) {
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
topics.exists(tid, next);
|
||||
},
|
||||
function(exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
topics.getTopicField(tid, 'cid', next);
|
||||
},
|
||||
function(cid, next) {
|
||||
user.isModerator(socket.uid, cid, next);
|
||||
},
|
||||
function(isMod, next) {
|
||||
if (!isAdmin && !isMod) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
topics.markAsUnreadForAll(tid, next);
|
||||
},
|
||||
function(next) {
|
||||
topics.updateRecent(tid, Date.now(), next);
|
||||
}
|
||||
], next);
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
topics.pushUnreadCount(socket.uid);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.delete = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('delete', 'event:topic_deleted', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.restore = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('restore', 'event:topic_restored', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.purge = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('purge', 'event:topic_purged', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.lock = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('lock', 'event:topic_locked', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unlock = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('unlock', 'event:topic_unlocked', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.pin = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('pin', 'event:topic_pinned', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.unpin = function(socket, data, callback) {
|
||||
SocketTopics.doTopicAction('unpin', 'event:topic_unpinned', socket, data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.doTopicAction = function(action, event, socket, data, callback) {
|
||||
callback = callback || function() {};
|
||||
if (!socket.uid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data || !Array.isArray(data.tids) || !data.cid) {
|
||||
return callback(new Error('[[error:invalid-tid]]'));
|
||||
}
|
||||
|
||||
if (typeof topics.tools[action] !== 'function') {
|
||||
return callback();
|
||||
}
|
||||
|
||||
async.each(data.tids, function(tid, next) {
|
||||
topics.tools[action](tid, socket.uid, function(err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
emitToTopicAndCategory(event, data);
|
||||
|
||||
if (action === 'delete' || action === 'restore' || action === 'purge') {
|
||||
events.log({
|
||||
type: 'topic-' + action,
|
||||
uid: socket.uid,
|
||||
ip: socket.ip,
|
||||
tid: tid
|
||||
});
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
function emitToTopicAndCategory(event, data) {
|
||||
SocketTopics.emitToTopicAndCategory = function(event, data) {
|
||||
websockets.in('topic_' + data.tid).emit(event, data);
|
||||
websockets.in('category_' + data.cid).emit(event, data);
|
||||
}
|
||||
};
|
||||
|
||||
SocketTopics.createTopicFromPosts = function(socket, data, callback) {
|
||||
if (!socket.uid) {
|
||||
@@ -284,75 +119,8 @@ SocketTopics.createTopicFromPosts = function(socket, data, callback) {
|
||||
topics.createTopicFromPosts(socket.uid, data.title, data.pids, callback);
|
||||
};
|
||||
|
||||
SocketTopics.movePost = function(socket, data, callback) {
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
}
|
||||
|
||||
if (!data || !data.pid || !data.tid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
privileges.posts.canMove(data.pid, socket.uid, function(err, canMove) {
|
||||
if (err || !canMove) {
|
||||
return callback(err || new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
topics.movePostToTopic(data.pid, data.tid, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
require('./posts').sendNotificationToPostOwner(data.pid, socket.uid, 'notifications:moved_your_post');
|
||||
callback();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.move = function(socket, data, callback) {
|
||||
if(!data || !Array.isArray(data.tids) || !data.cid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
async.eachLimit(data.tids, 10, function(tid, next) {
|
||||
var topicData;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
privileges.topics.isAdminOrMod(tid, socket.uid, next);
|
||||
},
|
||||
function(canMove, next) {
|
||||
if (!canMove) {
|
||||
return next(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
next();
|
||||
},
|
||||
function(next) {
|
||||
topics.getTopicFields(tid, ['cid', 'slug'], next);
|
||||
},
|
||||
function(_topicData, next) {
|
||||
topicData = _topicData;
|
||||
topicData.tid = tid;
|
||||
topics.tools.move(tid, data.cid, socket.uid, next);
|
||||
}
|
||||
], function(err) {
|
||||
if(err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
websockets.in('topic_' + tid).emit('event:topic_moved', topicData);
|
||||
|
||||
websockets.in('category_' + topicData.cid).emit('event:topic_moved', topicData);
|
||||
|
||||
SocketTopics.sendNotificationToTopicOwner(tid, socket.uid, 'notifications:moved_your_topic');
|
||||
|
||||
next();
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
|
||||
SocketTopics.sendNotificationToTopicOwner = function(tid, fromuid, notification) {
|
||||
if(!tid || !fromuid) {
|
||||
if (!tid || !fromuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -378,30 +146,8 @@ SocketTopics.sendNotificationToTopicOwner = function(tid, fromuid, notification)
|
||||
};
|
||||
|
||||
|
||||
SocketTopics.moveAll = function(socket, data, callback) {
|
||||
if(!data || !data.cid || !data.currentCid) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
privileges.categories.canMoveAllTopics(data.currentCid, data.cid, data.uid, function(err, canMove) {
|
||||
if (err || canMove) {
|
||||
return callback(err || new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
categories.getTopicIds('cid:' + data.currentCid + ':tids', true, 0, -1, function(err, tids) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
async.eachLimit(tids, 10, function(tid, next) {
|
||||
topics.tools.move(tid, data.cid, socket.uid, next);
|
||||
}, callback);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.toggleFollow = function(socket, tid, callback) {
|
||||
if(!socket.uid) {
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
}
|
||||
|
||||
@@ -409,154 +155,17 @@ SocketTopics.toggleFollow = function(socket, tid, callback) {
|
||||
};
|
||||
|
||||
SocketTopics.follow = function(socket, tid, callback) {
|
||||
if(!socket.uid) {
|
||||
if (!socket.uid) {
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
}
|
||||
|
||||
topics.follow(tid, socket.uid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.loadMore = function(socket, data, callback) {
|
||||
if (!data || !data.tid || !utils.isNumber(data.after) || parseInt(data.after, 10) < 0) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
settings: function(next) {
|
||||
user.getSettings(socket.uid, next);
|
||||
},
|
||||
privileges: function(next) {
|
||||
privileges.topics.get(data.tid, socket.uid, next);
|
||||
},
|
||||
topic: function(next) {
|
||||
topics.getTopicFields(data.tid, ['postcount', 'deleted'], next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (!results.privileges.read || (parseInt(results.topic.deleted, 10) && !results.privileges.view_deleted)) {
|
||||
return callback(new Error('[[error:no-privileges]]'));
|
||||
}
|
||||
|
||||
var set = 'tid:' + data.tid + ':posts';
|
||||
var reverse = results.settings.topicPostSort === 'newest_to_oldest' || results.settings.topicPostSort === 'most_votes';
|
||||
var start = Math.max(0, parseInt(data.after, 10));
|
||||
|
||||
var infScrollPostsPerPage = 10;
|
||||
|
||||
if (data.direction === -1) {
|
||||
start = start - (reverse ? -infScrollPostsPerPage : infScrollPostsPerPage);
|
||||
}
|
||||
|
||||
if (reverse) {
|
||||
start = results.topic.postcount - 1 - start;
|
||||
if (results.settings.topicPostSort === 'most_votes') {
|
||||
set = 'tid:' + data.tid + ':posts:votes';
|
||||
}
|
||||
}
|
||||
|
||||
var stop = start + (infScrollPostsPerPage - 1);
|
||||
|
||||
start = Math.max(0, start);
|
||||
stop = Math.max(0, stop);
|
||||
|
||||
async.parallel({
|
||||
mainPost: function(next) {
|
||||
if (start > 0) {
|
||||
return next();
|
||||
}
|
||||
topics.getMainPost(data.tid, socket.uid, next);
|
||||
},
|
||||
posts: function(next) {
|
||||
topics.getTopicPosts(data.tid, set, start, stop, socket.uid, reverse, next);
|
||||
},
|
||||
privileges: function(next) {
|
||||
next(null, results.privileges);
|
||||
},
|
||||
'reputation:disabled': function(next) {
|
||||
next(null, parseInt(meta.config['reputation:disabled'], 10) === 1);
|
||||
},
|
||||
'downvote:disabled': function(next) {
|
||||
next(null, parseInt(meta.config['downvote:disabled'], 10) === 1);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (results.mainPost) {
|
||||
results.posts = [results.mainPost].concat(results.posts);
|
||||
}
|
||||
|
||||
callback(err, results);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.loadMoreUnreadTopics = function(socket, data, callback) {
|
||||
if (!data || !data.after) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
var start = parseInt(data.after, 10),
|
||||
stop = start + 9;
|
||||
|
||||
topics.getUnreadTopics(data.cid, socket.uid, start, stop, callback);
|
||||
};
|
||||
|
||||
SocketTopics.loadMoreFromSet = function(socket, data, callback) {
|
||||
if (!data || !data.after || !data.set) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
var start = parseInt(data.after, 10),
|
||||
stop = start + 9;
|
||||
|
||||
topics.getTopicsFromSet(data.set, socket.uid, start, stop, callback);
|
||||
};
|
||||
|
||||
SocketTopics.loadTopics = function(socket, data, callback) {
|
||||
if (!data || !data.set || !utils.isNumber(data.start) || !utils.isNumber(data.stop)) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
topics.getTopicsFromSet(data.set, socket.uid, data.start, data.stop, callback);
|
||||
};
|
||||
|
||||
SocketTopics.getPageCount = function(socket, tid, callback) {
|
||||
topics.getPageCount(tid, socket.uid, callback);
|
||||
};
|
||||
|
||||
SocketTopics.searchTags = function(socket, data, callback) {
|
||||
topics.searchTags(data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.search = function(socket, data, callback) {
|
||||
topics.search(data.tid, data.term, callback);
|
||||
};
|
||||
|
||||
SocketTopics.searchAndLoadTags = function(socket, data, callback) {
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
topics.searchAndLoadTags(data, callback);
|
||||
};
|
||||
|
||||
SocketTopics.loadMoreTags = function(socket, data, callback) {
|
||||
if(!data || !utils.isNumber(data.after)) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
var start = parseInt(data.after, 10),
|
||||
stop = start + 99;
|
||||
|
||||
topics.getTags(start, stop, function(err, tags) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback(null, {tags: tags, nextStart: stop + 1});
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.isModerator = function(socket, tid, callback) {
|
||||
topics.getTopicField(tid, 'cid', function(err, cid) {
|
||||
if (err) {
|
||||
|
||||
Reference in New Issue
Block a user