mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	posts.js refactor pt1
This commit is contained in:
		
							
								
								
									
										412
									
								
								src/posts.js
									
									
									
									
									
								
							
							
						
						
									
										412
									
								
								src/posts.js
									
									
									
									
									
								
							| @@ -1,107 +1,25 @@ | |||||||
| 'use strict'; | 'use strict'; | ||||||
|  |  | ||||||
| var async = require('async'), | var async = require('async'), | ||||||
| 	path = require('path'), |  | ||||||
| 	fs = require('fs'), |  | ||||||
| 	nconf = require('nconf'), |  | ||||||
| 	_ = require('underscore'), | 	_ = require('underscore'), | ||||||
| 	validator = require('validator'), |  | ||||||
| 	winston = require('winston'), |  | ||||||
| 	gravatar = require('gravatar'), |  | ||||||
| 	S = require('string'), |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	db = require('./database'), | 	db = require('./database'), | ||||||
| 	utils = require('../public/src/utils'), | 	utils = require('../public/src/utils'), | ||||||
| 	user = require('./user'), | 	user = require('./user'), | ||||||
| 	groups = require('./groups'), |  | ||||||
| 	topics = require('./topics'), | 	topics = require('./topics'), | ||||||
| 	favourites = require('./favourites'), |  | ||||||
| 	postTools = require('./postTools'), | 	postTools = require('./postTools'), | ||||||
| 	privileges = require('./privileges'), | 	plugins = require('./plugins'); | ||||||
| 	categories = require('./categories'), |  | ||||||
| 	plugins = require('./plugins'), |  | ||||||
| 	meta = require('./meta'), |  | ||||||
| 	emitter = require('./emitter'), |  | ||||||
| 	websockets = require('./socket.io'); |  | ||||||
|  |  | ||||||
| (function(Posts) { | (function(Posts) { | ||||||
| 	require('./posts/recent')(Posts); |  | ||||||
|  | 	require('./posts/create')(Posts); | ||||||
| 	require('./posts/delete')(Posts); | 	require('./posts/delete')(Posts); | ||||||
|  | 	require('./posts/user')(Posts); | ||||||
|  | 	require('./posts/category')(Posts); | ||||||
|  | 	require('./posts/summary')(Posts); | ||||||
|  | 	require('./posts/recent')(Posts); | ||||||
| 	require('./posts/flags')(Posts); | 	require('./posts/flags')(Posts); | ||||||
|  |  | ||||||
| 	Posts.create = function(data, callback) { |  | ||||||
| 		var uid = data.uid, |  | ||||||
| 			tid = data.tid, |  | ||||||
| 			content = data.content, |  | ||||||
| 			timestamp = data.timestamp || Date.now(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		if (uid === null) { |  | ||||||
| 			return callback(new Error('[[error:invalid-uid]]')); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		var postData; |  | ||||||
|  |  | ||||||
| 		async.waterfall([ |  | ||||||
| 			function(next) { |  | ||||||
| 				db.incrObjectField('global', 'nextPid', next); |  | ||||||
| 			}, |  | ||||||
| 			function(pid, next) { |  | ||||||
|  |  | ||||||
| 				postData = { |  | ||||||
| 					'pid': pid, |  | ||||||
| 					'uid': uid, |  | ||||||
| 					'tid': tid, |  | ||||||
| 					'content': content, |  | ||||||
| 					'timestamp': timestamp, |  | ||||||
| 					'reputation': 0, |  | ||||||
| 					'votes': 0, |  | ||||||
| 					'editor': '', |  | ||||||
| 					'edited': 0, |  | ||||||
| 					'deleted': 0 |  | ||||||
| 				}; |  | ||||||
|  |  | ||||||
| 				if (data.toPid) { |  | ||||||
| 					postData.toPid = data.toPid; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				plugins.fireHook('filter:post.save', postData, next); |  | ||||||
| 			}, |  | ||||||
| 			function(postData, next) { |  | ||||||
| 				db.setObject('post:' + postData.pid, postData, next); |  | ||||||
| 			}, |  | ||||||
| 			function(next) { |  | ||||||
| 				async.parallel([ |  | ||||||
| 					function(next) { |  | ||||||
| 						user.onNewPostMade(postData, next); |  | ||||||
| 					}, |  | ||||||
| 					function(next) { |  | ||||||
| 						topics.onNewPostMade(postData, next); |  | ||||||
| 					}, |  | ||||||
| 					function(next) { |  | ||||||
| 						categories.onNewPostMade(postData, next); |  | ||||||
| 					}, |  | ||||||
| 					function(next) { |  | ||||||
| 						db.sortedSetAdd('posts:pid', timestamp, postData.pid, next); |  | ||||||
| 					}, |  | ||||||
| 					function(next) { |  | ||||||
| 						db.incrObjectField('global', 'postCount', next); |  | ||||||
| 					} |  | ||||||
| 				], function(err) { |  | ||||||
| 					if (err) { |  | ||||||
| 						return next(err); |  | ||||||
| 					} |  | ||||||
| 					plugins.fireHook('filter:post.get', postData, next); |  | ||||||
| 				}); |  | ||||||
| 			}, |  | ||||||
| 			function(postData, next) { |  | ||||||
| 				plugins.fireHook('action:post.save', postData); |  | ||||||
| 				next(null, postData); |  | ||||||
| 			} |  | ||||||
| 		], callback); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.exists = function(pid, callback) { | 	Posts.exists = function(pid, callback) { | ||||||
| 		db.isSortedSetMember('posts:pid', pid, callback); | 		db.isSortedSetMember('posts:pid', pid, callback); | ||||||
| 	}; | 	}; | ||||||
| @@ -167,184 +85,6 @@ var async = require('async'), | |||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Posts.getUserInfoForPosts = function(uids, uid, callback) { |  | ||||||
| 		async.parallel({ |  | ||||||
| 			groups: function(next) { |  | ||||||
| 				groups.getUserGroups(uids, next); |  | ||||||
| 			}, |  | ||||||
| 			userData: function(next) { |  | ||||||
| 				user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status'], next); |  | ||||||
| 			}, |  | ||||||
| 			online: function(next) { |  | ||||||
| 				websockets.isUsersOnline(uids, next); |  | ||||||
| 			} |  | ||||||
| 		}, function(err, results) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			var userData = results.userData; |  | ||||||
| 			for(var i=0; i<userData.length; ++i) { |  | ||||||
| 				userData[i].groups = results.groups[i]; |  | ||||||
| 				userData[i].status = results.online[i] ? (userData[i].status || 'online') : 'offline'; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			async.map(userData, function(userData, next) { |  | ||||||
| 				userData.uid = userData.uid || 0; |  | ||||||
| 				userData.username = userData.username || '[[global:guest]]'; |  | ||||||
| 				userData.userslug = userData.userslug || ''; |  | ||||||
| 				userData.reputation = userData.reputation || 0; |  | ||||||
| 				userData.postcount = userData.postcount || 0; |  | ||||||
| 				userData.banned = parseInt(userData.banned, 10) === 1; |  | ||||||
| 				userData.picture = userData.picture || user.createGravatarURLFromEmail(''); |  | ||||||
|  |  | ||||||
| 				async.parallel({ |  | ||||||
| 					signature: function(next) { |  | ||||||
| 						if (parseInt(meta.config.disableSignatures, 10) === 1) { |  | ||||||
| 							userData.signature = ''; |  | ||||||
| 							return next(); |  | ||||||
| 						} |  | ||||||
| 						postTools.parseSignature(userData, uid, next); |  | ||||||
| 					}, |  | ||||||
| 					customProfileInfo: function(next) { |  | ||||||
| 						plugins.fireHook('filter:posts.custom_profile_info', {profile: [], uid: userData.uid}, next); |  | ||||||
| 					} |  | ||||||
| 				}, function(err, results) { |  | ||||||
| 					if (err) { |  | ||||||
| 						return next(err); |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					userData.custom_profile_info = results.customProfileInfo.profile; |  | ||||||
|  |  | ||||||
| 					plugins.fireHook('filter:posts.modifyUserInfo', userData, next); |  | ||||||
| 				}); |  | ||||||
| 			}, callback); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.getPostSummaryByPids = function(pids, uid, options, callback) { |  | ||||||
| 		options.stripTags = options.hasOwnProperty('stripTags') ? options.stripTags : false; |  | ||||||
| 		options.parse = options.hasOwnProperty('parse') ? options.parse : true; |  | ||||||
| 		options.extraFields = options.hasOwnProperty('extraFields') ? options.extraFields : []; |  | ||||||
|  |  | ||||||
| 		if (!Array.isArray(pids) || !pids.length) { |  | ||||||
| 			return callback(null, []); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		var keys = pids.map(function(pid) { |  | ||||||
| 			return 'post:' + pid; |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		var fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'].concat(options.extraFields); |  | ||||||
|  |  | ||||||
| 		db.getObjectsFields(keys, fields, function(err, posts) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			posts = posts.filter(function(p) { |  | ||||||
| 				return !!p && parseInt(p.deleted, 10) !== 1; |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			var uids = [], tids = []; |  | ||||||
| 			for(var i=0; i<posts.length; ++i) { |  | ||||||
| 				if (uids.indexOf(posts[i].uid) === -1) { |  | ||||||
| 					uids.push(posts[i].uid); |  | ||||||
| 				} |  | ||||||
| 				if (tids.indexOf('topic:' + posts[i].tid) === -1) { |  | ||||||
| 					tids.push('topic:' + posts[i].tid); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			async.parallel({ |  | ||||||
| 				users: function(next) { |  | ||||||
| 					user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], next); |  | ||||||
| 				}, |  | ||||||
| 				topicsAndCategories: function(next) { |  | ||||||
| 					db.getObjectsFields(tids, ['uid', 'tid', 'title', 'cid', 'slug', 'deleted'], function(err, topics) { |  | ||||||
| 						if (err) { |  | ||||||
| 							return next(err); |  | ||||||
| 						} |  | ||||||
|  |  | ||||||
| 						var cids = topics.map(function(topic) { |  | ||||||
| 							if (topic) { |  | ||||||
| 								topic.title = validator.escape(topic.title); |  | ||||||
| 							} |  | ||||||
| 							return topic && topic.cid; |  | ||||||
| 						}).filter(function(value, index, array) { |  | ||||||
| 							return value && array.indexOf(value) === index; |  | ||||||
| 						}); |  | ||||||
|  |  | ||||||
| 						categories.getMultipleCategoryFields(cids, ['cid', 'name', 'icon', 'slug'], function(err, categories) { |  | ||||||
| 							next(err, {topics: topics, categories: categories}); |  | ||||||
| 						}); |  | ||||||
| 					}); |  | ||||||
| 				}, |  | ||||||
| 				indices: function(next) { |  | ||||||
| 					Posts.getPostIndices(posts, uid, next); |  | ||||||
| 				} |  | ||||||
| 			}, function(err, results) { |  | ||||||
| 				function toObject(key, data) { |  | ||||||
| 					var obj = {}; |  | ||||||
| 					for(var i=0; i<data.length; ++i) { |  | ||||||
| 						obj[data[i][key]] = data[i]; |  | ||||||
| 					} |  | ||||||
| 					return obj; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				function stripTags(content) { |  | ||||||
| 					if (options.stripTags && content) { |  | ||||||
| 						var s = S(content); |  | ||||||
| 						return s.stripTags.apply(s, utils.stripTags).s; |  | ||||||
| 					} |  | ||||||
| 					return content; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if (err) { |  | ||||||
| 					return callback(err); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				results.users = toObject('uid', results.users); |  | ||||||
| 				results.topics = toObject('tid', results.topicsAndCategories.topics); |  | ||||||
| 				results.categories = toObject('cid', results.topicsAndCategories.categories); |  | ||||||
|  |  | ||||||
| 				for (var i=0; i<posts.length; ++i) { |  | ||||||
| 					posts[i].index = utils.isNumber(results.indices[i]) ? parseInt(results.indices[i], 10) + 1 : 1; |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				posts = posts.filter(function(post) { |  | ||||||
| 					return results.topics[post.tid] && parseInt(results.topics[post.tid].deleted, 10) !== 1; |  | ||||||
| 				}); |  | ||||||
|  |  | ||||||
| 				async.map(posts, function(post, next) { |  | ||||||
| 					post.user = results.users[post.uid]; |  | ||||||
| 					post.topic = results.topics[post.tid]; |  | ||||||
| 					post.category = results.categories[post.topic.cid]; |  | ||||||
| 					post.relativeTime = utils.toISOString(post.timestamp); |  | ||||||
|  |  | ||||||
| 					if (!post.content || !options.parse) { |  | ||||||
| 						post.content = stripTags(post.content); |  | ||||||
| 						return next(null, post); |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					postTools.parsePost(post, uid, function(err, post) { |  | ||||||
| 						if (err) { |  | ||||||
| 							return next(err); |  | ||||||
| 						} |  | ||||||
|  |  | ||||||
| 						post.content = stripTags(post.content); |  | ||||||
|  |  | ||||||
| 						next(null, post); |  | ||||||
| 					}); |  | ||||||
| 				}, function(err, posts) { |  | ||||||
| 					plugins.fireHook('filter:post.getPostSummaryByPids', {posts: posts, uid: uid}, function(err, postData) { |  | ||||||
| 						callback(err, postData.posts); |  | ||||||
| 					}); |  | ||||||
| 				}); |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.getPostData = function(pid, callback) { | 	Posts.getPostData = function(pid, callback) { | ||||||
| 		db.getObject('post:' + pid, function(err, data) { | 		db.getObject('post:' + pid, function(err, data) { | ||||||
| 			if(err) { | 			if(err) { | ||||||
| @@ -405,107 +145,6 @@ var async = require('async'), | |||||||
| 		db.setObject('post:' + pid, data, callback); | 		db.setObject('post:' + pid, data, callback); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Posts.getCidByPid = function(pid, callback) { |  | ||||||
| 		Posts.getPostField(pid, 'tid', function(err, tid) { |  | ||||||
| 			if(err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			topics.getTopicField(tid, 'cid', function(err, cid) { |  | ||||||
| 				if(err || !cid) { |  | ||||||
| 					return callback(err || new Error('[[error:invalid-cid]]')); |  | ||||||
| 				} |  | ||||||
| 				callback(null, cid); |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.getCidsByPids = function(pids, callback) { |  | ||||||
| 		Posts.getPostsFields(pids, ['tid'], function(err, posts) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			var tids = posts.map(function(post) { |  | ||||||
| 				return post.tid; |  | ||||||
| 			}).filter(function(tid, index, array) { |  | ||||||
| 				return tid && array.indexOf(tid) === index; |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			topics.getTopicsFields(tids, ['cid'], function(err, topics) { |  | ||||||
| 				if (err) { |  | ||||||
| 					return callback(err); |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				var map = {}; |  | ||||||
| 				topics.forEach(function(topic, index) { |  | ||||||
| 					if (topic) { |  | ||||||
| 						map[tids[index]] = topic.cid; |  | ||||||
| 					} |  | ||||||
| 				}); |  | ||||||
|  |  | ||||||
| 				var cids = posts.map(function(post) { |  | ||||||
| 					return map[post.tid]; |  | ||||||
| 				}); |  | ||||||
|  |  | ||||||
| 				callback(null, cids); |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.getPostsByUid = function(callerUid, uid, start, end, callback) { |  | ||||||
| 		user.getPostIds(uid, start, end, function(err, pids) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			privileges.posts.filter('read', pids, callerUid, function(err, pids) { |  | ||||||
| 				if (err) { |  | ||||||
| 					return callback(err); |  | ||||||
| 				} |  | ||||||
| 				getPosts(pids, callerUid, function(err, posts) { |  | ||||||
| 					if (err) { |  | ||||||
| 						return callback(err); |  | ||||||
| 					} |  | ||||||
| 					callback(null, {posts: posts, nextStart: end + 1}); |  | ||||||
| 				}); |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.getFavourites = function(uid, start, end, callback) { |  | ||||||
| 		db.getSortedSetRevRange('uid:' + uid + ':favourites', start, end, function(err, pids) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			getPosts(pids, uid, function(err, posts) { |  | ||||||
| 				if (err) { |  | ||||||
| 					return callback(err); |  | ||||||
| 				} |  | ||||||
| 				callback(null, {posts: posts, nextStart: end + 1}); |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	function getPosts(pids, uid, callback) { |  | ||||||
| 		if (!Array.isArray(pids) || !pids.length) { |  | ||||||
| 			return callback(null, []); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Posts.getPostSummaryByPids(pids, uid, {stripTags: false}, function(err, posts) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if (!Array.isArray(posts) || !posts.length) { |  | ||||||
| 				return callback(null, []); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			callback(null, posts); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Posts.getPidIndex = function(pid, uid, callback) { | 	Posts.getPidIndex = function(pid, uid, callback) { | ||||||
| 		async.parallel({ | 		async.parallel({ | ||||||
| 			settings: function(next) { | 			settings: function(next) { | ||||||
| @@ -568,43 +207,6 @@ var async = require('async'), | |||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	Posts.isOwner = function(pid, uid, callback) { |  | ||||||
| 		uid = parseInt(uid, 10); |  | ||||||
| 		if (Array.isArray(pid)) { |  | ||||||
| 			if (!uid) { |  | ||||||
| 				return callback(null, pid.map(function() {return false;})); |  | ||||||
| 			} |  | ||||||
| 			Posts.getPostsFields(pid, ['uid'], function(err, posts) { |  | ||||||
| 				if (err) { |  | ||||||
| 					return callback(err); |  | ||||||
| 				} |  | ||||||
| 				posts = posts.map(function(post) { |  | ||||||
| 					return post && parseInt(post.uid, 10) === uid; |  | ||||||
| 				}); |  | ||||||
| 				callback(null, posts); |  | ||||||
| 			}); |  | ||||||
| 		} else { |  | ||||||
| 			if (!uid) { |  | ||||||
| 				return callback(null, false); |  | ||||||
| 			} |  | ||||||
| 			Posts.getPostField(pid, 'uid', function(err, author) { |  | ||||||
| 				callback(err, parseInt(author, 10) === uid); |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	Posts.isModerator = function(pids, uid, callback) { |  | ||||||
| 		if (!parseInt(uid, 10)) { |  | ||||||
| 			return callback(null, pids.map(function() {return false;})); |  | ||||||
| 		} |  | ||||||
| 		Posts.getCidsByPids(pids, function(err, cids) { |  | ||||||
| 			if (err) { |  | ||||||
| 				return callback(err); |  | ||||||
| 			} |  | ||||||
| 			user.isModerator(uid, cids, callback); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Posts.isMain = function(pid, callback) { | 	Posts.isMain = function(pid, callback) { | ||||||
| 		Posts.getPostField(pid, 'tid', function(err, tid) { | 		Posts.getPostField(pid, 'tid', function(err, tid) { | ||||||
| 			if (err) { | 			if (err) { | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								src/posts/category.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/posts/category.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  |  | ||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var topics = require('../topics'); | ||||||
|  |  | ||||||
|  | module.exports = function(Posts) { | ||||||
|  |  | ||||||
|  | 	Posts.getCidByPid = function(pid, callback) { | ||||||
|  | 		Posts.getPostField(pid, 'tid', function(err, tid) { | ||||||
|  | 			if(err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			topics.getTopicField(tid, 'cid', function(err, cid) { | ||||||
|  | 				if(err || !cid) { | ||||||
|  | 					return callback(err || new Error('[[error:invalid-cid]]')); | ||||||
|  | 				} | ||||||
|  | 				callback(null, cid); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.getCidsByPids = function(pids, callback) { | ||||||
|  | 		Posts.getPostsFields(pids, ['tid'], function(err, posts) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var tids = posts.map(function(post) { | ||||||
|  | 				return post.tid; | ||||||
|  | 			}).filter(function(tid, index, array) { | ||||||
|  | 				return tid && array.indexOf(tid) === index; | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			topics.getTopicsFields(tids, ['cid'], function(err, topics) { | ||||||
|  | 				if (err) { | ||||||
|  | 					return callback(err); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				var map = {}; | ||||||
|  | 				topics.forEach(function(topic, index) { | ||||||
|  | 					if (topic) { | ||||||
|  | 						map[tids[index]] = topic.cid; | ||||||
|  | 					} | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				var cids = posts.map(function(post) { | ||||||
|  | 					return map[post.tid]; | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				callback(null, cids); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
							
								
								
									
										86
									
								
								src/posts/create.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/posts/create.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var async = require('async'), | ||||||
|  |  | ||||||
|  | 	db = require('../database'), | ||||||
|  | 	plugins = require('../plugins'), | ||||||
|  | 	user = require('../user'), | ||||||
|  | 	topics = require('../topics'), | ||||||
|  | 	categories = require('../categories'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = function(Posts) { | ||||||
|  | 	Posts.create = function(data, callback) { | ||||||
|  | 		var uid = data.uid, | ||||||
|  | 			tid = data.tid, | ||||||
|  | 			content = data.content, | ||||||
|  | 			timestamp = data.timestamp || Date.now(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		if (!uid && parseInt(uid, 10) !== 0) { | ||||||
|  | 			return callback(new Error('[[error:invalid-uid]]')); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var postData; | ||||||
|  |  | ||||||
|  | 		async.waterfall([ | ||||||
|  | 			function(next) { | ||||||
|  | 				db.incrObjectField('global', 'nextPid', next); | ||||||
|  | 			}, | ||||||
|  | 			function(pid, next) { | ||||||
|  |  | ||||||
|  | 				postData = { | ||||||
|  | 					'pid': pid, | ||||||
|  | 					'uid': uid, | ||||||
|  | 					'tid': tid, | ||||||
|  | 					'content': content, | ||||||
|  | 					'timestamp': timestamp, | ||||||
|  | 					'reputation': 0, | ||||||
|  | 					'votes': 0, | ||||||
|  | 					'editor': '', | ||||||
|  | 					'edited': 0, | ||||||
|  | 					'deleted': 0 | ||||||
|  | 				}; | ||||||
|  |  | ||||||
|  | 				if (data.toPid) { | ||||||
|  | 					postData.toPid = data.toPid; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				plugins.fireHook('filter:post.save', postData, next); | ||||||
|  | 			}, | ||||||
|  | 			function(postData, next) { | ||||||
|  | 				db.setObject('post:' + postData.pid, postData, next); | ||||||
|  | 			}, | ||||||
|  | 			function(next) { | ||||||
|  | 				async.parallel([ | ||||||
|  | 					function(next) { | ||||||
|  | 						user.onNewPostMade(postData, next); | ||||||
|  | 					}, | ||||||
|  | 					function(next) { | ||||||
|  | 						topics.onNewPostMade(postData, next); | ||||||
|  | 					}, | ||||||
|  | 					function(next) { | ||||||
|  | 						categories.onNewPostMade(postData, next); | ||||||
|  | 					}, | ||||||
|  | 					function(next) { | ||||||
|  | 						db.sortedSetAdd('posts:pid', timestamp, postData.pid, next); | ||||||
|  | 					}, | ||||||
|  | 					function(next) { | ||||||
|  | 						db.incrObjectField('global', 'postCount', next); | ||||||
|  | 					} | ||||||
|  | 				], function(err) { | ||||||
|  | 					if (err) { | ||||||
|  | 						return next(err); | ||||||
|  | 					} | ||||||
|  | 					plugins.fireHook('filter:post.get', postData, next); | ||||||
|  | 				}); | ||||||
|  | 			}, | ||||||
|  | 			function(postData, next) { | ||||||
|  | 				plugins.fireHook('action:post.save', postData); | ||||||
|  | 				next(null, postData); | ||||||
|  | 			} | ||||||
|  | 		], callback); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										140
									
								
								src/posts/summary.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/posts/summary.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  |  | ||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var async = require('async'), | ||||||
|  | 	validator = require('validator'), | ||||||
|  | 	S = require('string'), | ||||||
|  |  | ||||||
|  | 	db = require('../database'), | ||||||
|  | 	user = require('../user'), | ||||||
|  | 	plugins = require('../plugins'), | ||||||
|  | 	categories = require('../categories'), | ||||||
|  | 	postTools = require('../postTools'), | ||||||
|  | 	utils = require('../../public/src/utils'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = function(Posts) { | ||||||
|  |  | ||||||
|  | 	Posts.getPostSummaryByPids = function(pids, uid, options, callback) { | ||||||
|  | 		options.stripTags = options.hasOwnProperty('stripTags') ? options.stripTags : false; | ||||||
|  | 		options.parse = options.hasOwnProperty('parse') ? options.parse : true; | ||||||
|  | 		options.extraFields = options.hasOwnProperty('extraFields') ? options.extraFields : []; | ||||||
|  |  | ||||||
|  | 		if (!Array.isArray(pids) || !pids.length) { | ||||||
|  | 			return callback(null, []); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var keys = pids.map(function(pid) { | ||||||
|  | 			return 'post:' + pid; | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		var fields = ['pid', 'tid', 'content', 'uid', 'timestamp', 'deleted'].concat(options.extraFields); | ||||||
|  |  | ||||||
|  | 		db.getObjectsFields(keys, fields, function(err, posts) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			posts = posts.filter(function(p) { | ||||||
|  | 				return !!p && parseInt(p.deleted, 10) !== 1; | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			var uids = [], tids = []; | ||||||
|  | 			for(var i=0; i<posts.length; ++i) { | ||||||
|  | 				if (uids.indexOf(posts[i].uid) === -1) { | ||||||
|  | 					uids.push(posts[i].uid); | ||||||
|  | 				} | ||||||
|  | 				if (tids.indexOf('topic:' + posts[i].tid) === -1) { | ||||||
|  | 					tids.push('topic:' + posts[i].tid); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			async.parallel({ | ||||||
|  | 				users: function(next) { | ||||||
|  | 					user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], next); | ||||||
|  | 				}, | ||||||
|  | 				topicsAndCategories: function(next) { | ||||||
|  | 					db.getObjectsFields(tids, ['uid', 'tid', 'title', 'cid', 'slug', 'deleted'], function(err, topics) { | ||||||
|  | 						if (err) { | ||||||
|  | 							return next(err); | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						var cids = topics.map(function(topic) { | ||||||
|  | 							if (topic) { | ||||||
|  | 								topic.title = validator.escape(topic.title); | ||||||
|  | 							} | ||||||
|  | 							return topic && topic.cid; | ||||||
|  | 						}).filter(function(value, index, array) { | ||||||
|  | 							return value && array.indexOf(value) === index; | ||||||
|  | 						}); | ||||||
|  |  | ||||||
|  | 						categories.getMultipleCategoryFields(cids, ['cid', 'name', 'icon', 'slug'], function(err, categories) { | ||||||
|  | 							next(err, {topics: topics, categories: categories}); | ||||||
|  | 						}); | ||||||
|  | 					}); | ||||||
|  | 				}, | ||||||
|  | 				indices: function(next) { | ||||||
|  | 					Posts.getPostIndices(posts, uid, next); | ||||||
|  | 				} | ||||||
|  | 			}, function(err, results) { | ||||||
|  | 				function toObject(key, data) { | ||||||
|  | 					var obj = {}; | ||||||
|  | 					for(var i=0; i<data.length; ++i) { | ||||||
|  | 						obj[data[i][key]] = data[i]; | ||||||
|  | 					} | ||||||
|  | 					return obj; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				function stripTags(content) { | ||||||
|  | 					if (options.stripTags && content) { | ||||||
|  | 						var s = S(content); | ||||||
|  | 						return s.stripTags.apply(s, utils.stripTags).s; | ||||||
|  | 					} | ||||||
|  | 					return content; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (err) { | ||||||
|  | 					return callback(err); | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				results.users = toObject('uid', results.users); | ||||||
|  | 				results.topics = toObject('tid', results.topicsAndCategories.topics); | ||||||
|  | 				results.categories = toObject('cid', results.topicsAndCategories.categories); | ||||||
|  |  | ||||||
|  | 				for (var i=0; i<posts.length; ++i) { | ||||||
|  | 					posts[i].index = utils.isNumber(results.indices[i]) ? parseInt(results.indices[i], 10) + 1 : 1; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				posts = posts.filter(function(post) { | ||||||
|  | 					return results.topics[post.tid] && parseInt(results.topics[post.tid].deleted, 10) !== 1; | ||||||
|  | 				}); | ||||||
|  |  | ||||||
|  | 				async.map(posts, function(post, next) { | ||||||
|  | 					post.user = results.users[post.uid]; | ||||||
|  | 					post.topic = results.topics[post.tid]; | ||||||
|  | 					post.category = results.categories[post.topic.cid]; | ||||||
|  | 					post.relativeTime = utils.toISOString(post.timestamp); | ||||||
|  |  | ||||||
|  | 					if (!post.content || !options.parse) { | ||||||
|  | 						post.content = stripTags(post.content); | ||||||
|  | 						return next(null, post); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					postTools.parsePost(post, uid, function(err, post) { | ||||||
|  | 						if (err) { | ||||||
|  | 							return next(err); | ||||||
|  | 						} | ||||||
|  |  | ||||||
|  | 						post.content = stripTags(post.content); | ||||||
|  |  | ||||||
|  | 						next(null, post); | ||||||
|  | 					}); | ||||||
|  | 				}, function(err, posts) { | ||||||
|  | 					plugins.fireHook('filter:post.getPostSummaryByPids', {posts: posts, uid: uid}, function(err, postData) { | ||||||
|  | 						callback(err, postData.posts); | ||||||
|  | 					}); | ||||||
|  | 				}); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
							
								
								
									
										163
									
								
								src/posts/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								src/posts/user.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | |||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var async = require('async'), | ||||||
|  |  | ||||||
|  | 	db = require('../database'), | ||||||
|  | 	user = require('../user'), | ||||||
|  | 	groups = require('../groups'), | ||||||
|  | 	meta = require('../meta'), | ||||||
|  | 	websockets = require('../socket.io'), | ||||||
|  | 	postTools = require('../postTools'), | ||||||
|  | 	plugins = require('../plugins'), | ||||||
|  | 	privileges = require('../privileges'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | module.exports = function(Posts) { | ||||||
|  |  | ||||||
|  | 	Posts.getUserInfoForPosts = function(uids, uid, callback) { | ||||||
|  | 		async.parallel({ | ||||||
|  | 			groups: function(next) { | ||||||
|  | 				groups.getUserGroups(uids, next); | ||||||
|  | 			}, | ||||||
|  | 			userData: function(next) { | ||||||
|  | 				user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status'], next); | ||||||
|  | 			}, | ||||||
|  | 			online: function(next) { | ||||||
|  | 				websockets.isUsersOnline(uids, next); | ||||||
|  | 			} | ||||||
|  | 		}, function(err, results) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			var userData = results.userData; | ||||||
|  | 			for(var i=0; i<userData.length; ++i) { | ||||||
|  | 				userData[i].groups = results.groups[i]; | ||||||
|  | 				userData[i].status = results.online[i] ? (userData[i].status || 'online') : 'offline'; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			async.map(userData, function(userData, next) { | ||||||
|  | 				userData.uid = userData.uid || 0; | ||||||
|  | 				userData.username = userData.username || '[[global:guest]]'; | ||||||
|  | 				userData.userslug = userData.userslug || ''; | ||||||
|  | 				userData.reputation = userData.reputation || 0; | ||||||
|  | 				userData.postcount = userData.postcount || 0; | ||||||
|  | 				userData.banned = parseInt(userData.banned, 10) === 1; | ||||||
|  | 				userData.picture = userData.picture || user.createGravatarURLFromEmail(''); | ||||||
|  |  | ||||||
|  | 				async.parallel({ | ||||||
|  | 					signature: function(next) { | ||||||
|  | 						if (parseInt(meta.config.disableSignatures, 10) === 1) { | ||||||
|  | 							userData.signature = ''; | ||||||
|  | 							return next(); | ||||||
|  | 						} | ||||||
|  | 						postTools.parseSignature(userData, uid, next); | ||||||
|  | 					}, | ||||||
|  | 					customProfileInfo: function(next) { | ||||||
|  | 						plugins.fireHook('filter:posts.custom_profile_info', {profile: [], uid: userData.uid}, next); | ||||||
|  | 					} | ||||||
|  | 				}, function(err, results) { | ||||||
|  | 					if (err) { | ||||||
|  | 						return next(err); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					userData.custom_profile_info = results.customProfileInfo.profile; | ||||||
|  |  | ||||||
|  | 					plugins.fireHook('filter:posts.modifyUserInfo', userData, next); | ||||||
|  | 				}); | ||||||
|  | 			}, callback); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.isOwner = function(pid, uid, callback) { | ||||||
|  | 		uid = parseInt(uid, 10); | ||||||
|  | 		if (Array.isArray(pid)) { | ||||||
|  | 			if (!uid) { | ||||||
|  | 				return callback(null, pid.map(function() {return false;})); | ||||||
|  | 			} | ||||||
|  | 			Posts.getPostsFields(pid, ['uid'], function(err, posts) { | ||||||
|  | 				if (err) { | ||||||
|  | 					return callback(err); | ||||||
|  | 				} | ||||||
|  | 				posts = posts.map(function(post) { | ||||||
|  | 					return post && parseInt(post.uid, 10) === uid; | ||||||
|  | 				}); | ||||||
|  | 				callback(null, posts); | ||||||
|  | 			}); | ||||||
|  | 		} else { | ||||||
|  | 			if (!uid) { | ||||||
|  | 				return callback(null, false); | ||||||
|  | 			} | ||||||
|  | 			Posts.getPostField(pid, 'uid', function(err, author) { | ||||||
|  | 				callback(err, parseInt(author, 10) === uid); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.isModerator = function(pids, uid, callback) { | ||||||
|  | 		if (!parseInt(uid, 10)) { | ||||||
|  | 			return callback(null, pids.map(function() {return false;})); | ||||||
|  | 		} | ||||||
|  | 		Posts.getCidsByPids(pids, function(err, cids) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  | 			user.isModerator(uid, cids, callback); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.getPostsByUid = function(callerUid, uid, start, end, callback) { | ||||||
|  | 		user.getPostIds(uid, start, end, function(err, pids) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			privileges.posts.filter('read', pids, callerUid, function(err, pids) { | ||||||
|  | 				if (err) { | ||||||
|  | 					return callback(err); | ||||||
|  | 				} | ||||||
|  | 				getPosts(pids, callerUid, function(err, posts) { | ||||||
|  | 					if (err) { | ||||||
|  | 						return callback(err); | ||||||
|  | 					} | ||||||
|  | 					callback(null, {posts: posts, nextStart: end + 1}); | ||||||
|  | 				}); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	Posts.getFavourites = function(uid, start, end, callback) { | ||||||
|  | 		db.getSortedSetRevRange('uid:' + uid + ':favourites', start, end, function(err, pids) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			getPosts(pids, uid, function(err, posts) { | ||||||
|  | 				if (err) { | ||||||
|  | 					return callback(err); | ||||||
|  | 				} | ||||||
|  | 				callback(null, {posts: posts, nextStart: end + 1}); | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 	}; | ||||||
|  |  | ||||||
|  | 	function getPosts(pids, uid, callback) { | ||||||
|  | 		if (!Array.isArray(pids) || !pids.length) { | ||||||
|  | 			return callback(null, []); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		Posts.getPostSummaryByPids(pids, uid, {stripTags: false}, function(err, posts) { | ||||||
|  | 			if (err) { | ||||||
|  | 				return callback(err); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (!Array.isArray(posts) || !posts.length) { | ||||||
|  | 				return callback(null, []); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			callback(null, posts); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | }; | ||||||
		Reference in New Issue
	
	Block a user