var RDB = require('./redis.js'), utils = require('./../public/src/utils.js'), user = require('./user.js'), topics = require('./topics.js'), favourites = require('./favourites.js'), threadTools = require('./threadTools.js'), postTools = require('./postTools'), categories = require('./categories'), feed = require('./feed.js'), async = require('async'), plugins = require('./plugins'), reds = require('reds'), postSearch = reds.createSearch('nodebbpostsearch'), nconf = require('nconf'), meta = require('./meta.js'), winston = require('winston'); (function(Posts) { var customUserInfo = {}; Posts.getPostsByTid = function(tid, start, end, callback) { RDB.lrange('tid:' + tid + ':posts', start, end, function(err, pids) { RDB.handle(err); if (pids.length) { plugins.fireHook('filter:post.getTopic', pids, function(err, posts) { if (!err & 0 < posts.length) { Posts.getPostsByPids(pids, function(err, posts) { plugins.fireHook('action:post.gotTopic', posts); callback(posts); }); } else { callback(posts); } }); } else { callback([]); } }); }; Posts.addUserInfoToPost = function(post, callback) { user.getUserFields(post.uid, ['username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned'], function(err, userData) { if (err) { return callback(); } postTools.parse(userData.signature, function(err, signature) { post.username = userData.username || 'anonymous'; post.userslug = userData.userslug || ''; post.user_rep = userData.reputation || 0; post.user_postcount = userData.postcount || 0; post.user_banned = userData.banned || '0'; post.picture = userData.picture || require('gravatar').url('', {}, https = nconf.get('https')); post.signature = signature; for (var info in customUserInfo) { if (customUserInfo.hasOwnProperty(info)) { post[info] = userData[info] || customUserInfo[info]; } } plugins.fireHook('filter:posts.custom_profile_info', {profile: "", uid: post.uid}, function(err, profile_info) { post.additional_profile_info = profile_info.profile; if (post.editor !== '') { user.getUserFields(post.editor, ['username', 'userslug'], function(err, editorData) { if (err) return callback(); post.editorname = editorData.username; post.editorslug = editorData.userslug; callback(); }); } else { callback(); } }); }); }); }; Posts.getPostSummaryByPids = function(pids, callback) { var posts = []; function getPostSummary(pid, callback) { async.waterfall([ function(next) { Posts.getPostFields(pid, ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'], function(postData) { if (postData.deleted === '1') return callback(null); else { postData.relativeTime = new Date(parseInt(postData.timestamp || 0, 10)).toISOString(); next(null, postData); } }); }, function(postData, next) { Posts.addUserInfoToPost(postData, function() { next(null, postData); }); }, function(postData, next) { topics.getTopicFields(postData.tid, ['slug', 'deleted'], function(err, topicData) { if (err) return callback(err); else if (topicData.deleted === '1') return callback(null); postData.topicSlug = topicData.slug; next(null, postData); }); }, function(postData, next) { if (postData.content) { postTools.parse(postData.content, function(err, content) { if (!err) postData.content = utils.strip_tags(content); next(err, postData); }); } else next(null, postData); } ], function(err, postData) { if (!err) posts.push(postData); callback(err); }); } async.eachSeries(pids, getPostSummary, function(err) { if (!err) { callback(null, posts); } else { callback(err, null); } }); }; // TODO: this function is never called except from some debug route. clean up? Posts.getPostData = function(pid, callback) { RDB.hgetall('post:' + pid, function(err, data) { if (err === null) { plugins.fireHook('filter:post.get', data, function(err, newData) { if (!err) callback(newData); else callback(data); }); } else { winston.error(err); } }); } Posts.getPostFields = function(pid, fields, callback) { RDB.hmgetObject('post:' + pid, fields, function(err, data) { if (err === null) { // TODO: I think the plugins system needs an optional 'parameters' paramter so I don't have to do this: data = data || {}; data.pid = pid; data.fields = fields; plugins.fireHook('filter:post.getFields', data, function(err, data) { callback(data); }); } else { console.log(err); } }); } Posts.getPostField = function(pid, field, callback) { RDB.hget('post:' + pid, field, function(err, data) { if (err === null) { // TODO: I think the plugins system needs an optional 'parameters' paramter so I don't have to do this: data = data || {}; data.pid = pid; data.field = field; plugins.fireHook('filter:post.getField', data, function(err, data) { callback(data); }); } else { console.log(err); } }); } Posts.setPostField = function(pid, field, value, done) { RDB.hset('post:' + pid, field, value); plugins.fireHook('action:post.setField', { 'pid': pid, 'field': field, 'value': value }, done); } Posts.getPostsByPids = function(pids, callback) { var posts = [], multi = RDB.multi(); for(var x=0,numPids=pids.length;x 10) { RDB.spop('cid:' + cid + ':active_users'); } categories.addActiveUser(cid, uid); }); }); user.onNewPostMade(uid, tid, pid, timestamp); async.parallel({ content: function(next) { plugins.fireHook('filter:post.get', postData, function(err, newPostData) { if (!err) postData = newPostData; postTools.parse(postData.content, function(err, content) { next(null, content); }); }); } }, function(err, results) { postData.content = results.content; callback(postData); }); plugins.fireHook('action:post.save', postData); postSearch.index(content, pid); }); }); } else { callback(null); } }); } Posts.uploadPostImage = function(image, callback) { var imgur = require('./imgur'); imgur.setClientID(meta.config.imgurClientID); if(!image) return callback('invalid image', null); imgur.upload(image.data, 'base64', function(err, data) { if(err) { callback('Can\'t upload image!', null); } else { if(data.success) { var img= {url:data.data.link, name:image.name}; callback(null, img); } else { winston.error('Can\'t upload image, did you set imgurClientID?'); callback("upload error", null); } } }); } Posts.getPostsByUid = function(uid, start, end, callback) { user.getPostIds(uid, start, end, function(pids) { if (pids && pids.length) { plugins.fireHook('filter:post.getTopic', pids, function(err, posts) { if (!err & 0 < posts.length) { Posts.getPostsByPids(pids, function(err, posts) { plugins.fireHook('action:post.gotTopic', posts); callback(posts); }); } else { callback(posts); } }); } else callback([]); }); } Posts.getTopicPostStats = function() { RDB.mget(['totaltopiccount', 'totalpostcount'], function(err, data) { if (err === null) { var stats = { topics: data[0] ? data[0] : 0, posts: data[1] ? data[1] : 0 }; io.sockets.emit('post.stats', stats); } else console.log(err); }); } Posts.reIndexPids = function(pids, callback) { function reIndex(pid, callback) { Posts.getPostField(pid, 'content', function(content) { postSearch.remove(pid, function() { if (content && content.length) { postSearch.index(content, pid); } callback(null); }); }); } async.each(pids, reIndex, function(err) { if (err) { callback(err, null); } else { callback(null, 'Posts reindexed'); } }); } Posts.getFavourites = function(uid, callback) { RDB.zrevrange('uid:' + uid + ':favourites', 0, -1, function(err, pids) { if (err) return callback(err, null); Posts.getPostSummaryByPids(pids, function(err, posts) { if (err) return callback(err, null); callback(null, posts); }); }); } }(exports));