"use strict"; var async = require('async'), winston = require('winston'), validator = require('validator'), _ = require('underscore'), db = require('./database'), posts = require('./posts'), utils = require('../public/src/utils'), plugins = require('./plugins'), user = require('./user'), categories = require('./categories'), privileges = require('./privileges'); (function(Topics) { require('./topics/create')(Topics); require('./topics/delete')(Topics); require('./topics/unread')(Topics); require('./topics/recent')(Topics); require('./topics/popular')(Topics); require('./topics/fork')(Topics); require('./topics/posts')(Topics); require('./topics/follow')(Topics); require('./topics/tags')(Topics); Topics.getTopicData = function(tid, callback) { Topics.getTopicsData([tid], function(err, topics) { callback(err, Array.isArray(topics) && topics.length ? topics[0] : null); }); }; Topics.getTopicsData = function(tids, callback) { var keys = []; for (var i=0; i 100) { var e = new Error('TOO LARGE'); winston.warn('GET_TOPIC_WITH_POSTS set, start, end, uid, tid', set, start, end, uid, tid, e.stack); } Topics.addPostData(posts, uid, next); }); }); }, category: function(next) { Topics.getCategoryData(tid, next); }, pageCount: function(next) { Topics.getPageCount(tid, uid, next); }, threadTools: function(next) { plugins.fireHook('filter:topic.thread_tools', [], next); }, tags: function(next) { Topics.getTopicTagsObjects(tid, next); } }, function(err, results) { if (err) { return callback(err); } topicData.category = results.category; topicData.posts = results.posts; topicData.tags = results.tags; topicData.thread_tools = results.threadTools; topicData.pageCount = results.pageCount; topicData.unreplied = parseInt(topicData.postcount, 10) === 1; topicData.deleted = parseInt(topicData.deleted, 10) === 1; topicData.locked = parseInt(topicData.locked, 10) === 1; topicData.pinned = parseInt(topicData.pinned, 10) === 1; plugins.fireHook('filter:topic.get', topicData, callback); }); }); }; Topics.getMainPost = function(tid, uid, callback) { Topics.getMainPosts([tid], uid, function(err, mainPosts) { callback(err, Array.isArray(mainPosts) && mainPosts.length ? mainPosts[0] : null); }); }; Topics.getMainPosts = function(tids, uid, callback) { var keys = tids.map(function(tid) { return 'topic:' + tid; }); db.getObjectsFields(keys, ['mainPid'], function(err, topicData) { if (err) { return callback(err); } var mainPids = topicData.map(function(topic) { return topic ? topic.mainPid : null; }); posts.getPostsByPids(mainPids, function(err, postData) { if (err) { return callback(err); } if (!Array.isArray(postData) || !postData.length) { return callback(null, []); } Topics.addPostData(postData, uid, callback); }); }); }; Topics.getTeasers = function(tids, uid, callback) { if(!Array.isArray(tids)) { return callback(null, []); } async.map(tids, function(tid, next) { db.getSortedSetRevRange('tid:' + tid + ':posts', 0, 0, function(err, data) { next(err, Array.isArray(data) && data.length ? data[0] : null); }); }, function(err, pids) { if (err) { return callback(err); } var postKeys = pids.filter(Boolean).map(function(pid) { return 'post:' + pid; }); db.getObjectsFields(postKeys, ['pid', 'uid', 'timestamp', 'tid'], function(err, postData) { if (err) { return callback(err); } var uids = postData.map(function(post) { return post.uid; }).filter(function(uid, index, array) { return array.indexOf(uid) === index; }); async.parallel({ users: function(next) { user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], next); }, indices: function(next) { posts.getPostIndices(postData, uid, next); } }, function(err, results) { if (err) { return callback(err); } var users = {}; results.users.forEach(function(user) { users[user.uid] = user; }); var tidToPost = {}; postData.forEach(function(post, index) { post.user = users[post.uid]; post.index = results.indices[index] + 1; post.timestamp = utils.toISOString(post.timestamp); tidToPost[post.tid] = post; }); var teasers = tids.map(function(tid) { return tidToPost[tid]; }); callback(null, teasers); }); }); }); }; Topics.getTeaser = function(tid, uid, callback) { Topics.getLatestUndeletedPid(tid, function(err, pid) { if (err || !pid) { return callback(err); } async.parallel({ postData: function(next) { posts.getPostFields(pid, ['pid', 'uid', 'timestamp'], function(err, postData) { if (err) { return next(err); } else if(!postData || !utils.isNumber(postData.uid)) { return callback(); } user.getUserFields(postData.uid, ['username', 'userslug', 'picture'], function(err, userData) { if (err) { return next(err); } postData.user = userData; next(null, postData); }); }); }, postIndex: function(next) { posts.getPidIndex(pid, uid, next); } }, function(err, results) { if (err) { return callback(err); } results.postData.timestamp = utils.toISOString(results.postData.timestamp); results.postData.index = results.postIndex; callback(null, results.postData); }); }); }; Topics.getTopicField = function(tid, field, callback) { db.getObjectField('topic:' + tid, field, callback); }; Topics.getTopicFields = function(tid, fields, callback) { db.getObjectFields('topic:' + tid, fields, callback); }; Topics.getTopicsFields = function(tids, fields, callback) { var keys = tids.map(function(tid) { return 'topic:' + tid; }); db.getObjectsFields(keys, fields, callback); }; Topics.setTopicField = function(tid, field, value, callback) { db.setObjectField('topic:' + tid, field, value, callback); }; Topics.isLocked = function(tid, callback) { Topics.getTopicField(tid, 'locked', function(err, locked) { if(err) { return callback(err); } callback(null, parseInt(locked, 10) === 1); }); }; Topics.isOwner = function(tid, uid, callback) { uid = parseInt(uid, 10); if (uid === 0) { return callback(null, false); } Topics.getTopicField(tid, 'uid', function(err, author) { callback(err, parseInt(author, 10) === uid); }); }; Topics.getUids = function(tid, callback) { Topics.getPids(tid, function(err, pids) { if (err) { return callback(err); } var keys = pids.map(function(pid) { return 'post:' + pid; }); db.getObjectsFields(keys, ['uid'], function(err, data) { if (err) { return callback(err); } var uids = data.map(function(data) { return data.uid; }).filter(function(uid, pos, array) { return array.indexOf(uid) === pos; }); callback(null, uids); }); }); }; Topics.search = function(tid, term, callback) { if (plugins.hasListeners('filter:topic.search')) { plugins.fireHook('filter:topic.search', { tid: tid, term: term }, callback); } else { callback(new Error('no-plugins-available'), []); } }; }(exports));