Vulcan/collections/posts.js

309 lines
8.7 KiB
JavaScript
Raw Normal View History

postSchemaObject = {
_id: {
type: String,
optional: true
},
createdAt: {
type: Date,
optional: true
},
2014-07-03 13:15:23 +09:00
postedAt: {
type: Date,
optional: true
},
title: {
type: String,
label: "Title",
},
url: {
type: String,
label: "URL",
optional: true
},
body: {
type: String,
optional: true
},
author: {
type: String,
optional: true
},
comments: {
type: Number,
optional: true
},
2014-07-22 10:29:37 +09:00
lastCommentedAt: {
2014-07-19 15:08:28 +09:00
type: Date,
optional: true
},
2014-07-03 17:13:22 +09:00
clicks: {
type: Number,
optional: true
},
baseScore: {
type: Number,
decimal: true,
optional: true
},
upvotes: {
type: Number,
optional: true
},
upvoters: {
type: [String], // XXX
optional: true
},
downvotes: {
type: Number,
optional: true
},
downvoters: {
type: [String], // XXX
optional: true
},
score: {
type: Number,
decimal: true,
optional: true
},
status: {
type: Number,
optional: true
},
sticky: {
type: Boolean,
optional: true
},
inactive: {
type: Boolean,
optional: true
},
userId: {
type: String, // XXX
optional: true
}
};
// add any extra properties to postSchemaObject (provided by packages for example)
_.each(addToPostSchema, function(item){
postSchemaObject[item.propertyName] = item.propertySchema;
});
Posts = new Meteor.Collection("posts", {
schema: new SimpleSchema(postSchemaObject)
});
2014-05-10 16:57:17 +09:00
2012-10-24 11:04:42 +09:00
STATUS_PENDING=1;
STATUS_APPROVED=2;
STATUS_REJECTED=3;
2013-07-04 12:51:26 +09:00
Posts.deny({
update: function(userId, post, fieldNames) {
if(isAdminById(userId))
2013-07-05 07:09:15 +09:00
return false;
2013-11-05 09:32:21 +09:00
// deny the update if it contains something other than the following fields
2014-05-16 09:19:35 +09:00
return (_.without(fieldNames, 'title', 'url', 'body', 'shortUrl', 'shortTitle', 'categories').length > 0);
2013-07-04 12:51:26 +09:00
}
});
2013-11-05 09:32:21 +09:00
Posts.allow({
insert: canPostById
, update: canEditById
, remove: canEditById
});
clickedPosts = [];
Meteor.methods({
post: function(post){
2014-05-16 09:19:35 +09:00
var title = cleanUp(post.title),
2013-04-26 17:28:09 +09:00
body = cleanUp(post.body),
user = Meteor.user(),
userId = user._id,
2013-04-26 17:28:09 +09:00
timeSinceLastPost=timeSinceLast(user, Posts),
numberOfPostsInPast24Hours=numberOfItemsInPast24Hours(user, Posts),
postInterval = Math.abs(parseInt(getSetting('postInterval', 30))),
maxPostsPer24Hours = Math.abs(parseInt(getSetting('maxPostsPerDay', 30))),
postId = '';
2014-07-03 13:15:23 +09:00
// ------------------------------ Checks ------------------------------ //
2013-11-06 09:33:56 +09:00
// check that user can post
2012-10-05 13:59:40 +09:00
if (!user || !canPost(user))
2013-11-11 22:07:19 +01:00
throw new Meteor.Error(601, i18n.t('You need to login or be invited to post new stories.'));
2012-10-10 08:32:49 +09:00
2014-05-16 09:19:35 +09:00
// check that user provided a title
if(!post.title)
throw new Meteor.Error(602, i18n.t('Please fill in a title'));
2012-10-05 13:59:40 +09:00
2014-07-03 14:20:24 +09:00
if(!!post.url){
// check that there are no previous posts with the same link in the past 6 months
var sixMonthsAgo = moment().subtract('months', 6).toDate();
var postWithSameLink = Posts.findOne({url: post.url, postedAt: {$gte: sixMonthsAgo}});
if(typeof postWithSameLink !== 'undefined'){
Meteor.call('upvotePost', postWithSameLink);
throw new Meteor.Error(603, i18n.t('This link has already been posted'), postWithSameLink._id);
}
}
if(!isAdmin(Meteor.user())){
// check that user waits more than X seconds between posts
if(!this.isSimulation && timeSinceLastPost < postInterval)
2013-11-11 22:07:19 +01:00
throw new Meteor.Error(604, i18n.t('Please wait ')+(postInterval-timeSinceLastPost)+i18n.t(' seconds before posting again'));
2012-10-24 11:04:42 +09:00
// check that the user doesn't post more than Y posts per day
if(!this.isSimulation && numberOfPostsInPast24Hours > maxPostsPer24Hours)
2013-11-11 22:07:19 +01:00
throw new Meteor.Error(605, i18n.t('Sorry, you cannot submit more than ')+maxPostsPer24Hours+i18n.t(' posts per day'));
}
2012-10-23 12:24:38 +09:00
2014-07-03 13:15:23 +09:00
// ------------------------------ Properties ------------------------------ //
// Basic Properties
properties = {
2014-05-16 09:19:35 +09:00
title: title,
body: body,
2012-10-23 12:24:38 +09:00
userId: userId,
author: getDisplayNameById(userId),
upvotes: 0,
downvotes: 0,
comments: 0,
baseScore: 0,
2012-10-24 11:04:42 +09:00
score: 0,
inactive: false,
2014-07-03 13:15:23 +09:00
}
// UserId
if(isAdmin(Meteor.user()) && !!post.userId){ // only let admins post as other users
properties.userId = post.userId;
}
// Status
var defaultPostStatus = getSetting('requirePostsApproval') ? STATUS_PENDING : STATUS_APPROVED;
if(isAdmin(Meteor.user()) && !!post.status){ // if user is admin and a custom status has been set
properties.status = post.status;
}else{ // else use default status
properties.status = defaultPostStatus;
}
// CreatedAt
properties.createdAt = new Date();
2014-07-03 13:15:23 +09:00
// PostedAt
if(properties.status == 2){ // only set postedAt if post is approved
if(isAdmin(Meteor.user()) && !!post.postedAt){ // if user is admin and a custom postDate has been set
properties.postedAt = post.postedAt;
}else{ // else use current time
properties.postedAt = new Date();
}
2013-01-13 08:52:35 +09:00
}
2012-10-04 15:26:59 +09:00
2014-07-03 13:15:23 +09:00
post = _.extend(post, properties);
2014-07-05 18:06:28 +09:00
// ------------------------------ Callbacks ------------------------------ //
// run all post submit server callbacks on post object successively
post = postSubmitServerCallbacks.reduce(function(result, currentFunction) {
return currentFunction(result);
}, post);
2014-07-03 13:15:23 +09:00
// ------------------------------ Insert ------------------------------ //
2014-07-03 14:13:47 +09:00
// console.log(post)
2014-07-03 13:15:23 +09:00
post._id = Posts.insert(post);
// ------------------------------ Post-Insert ------------------------------ //
2013-01-15 08:46:00 +09:00
2013-11-08 11:10:23 +09:00
// increment posts count
Meteor.users.update({_id: userId}, {$inc: {postCount: 1}});
var postAuthor = Meteor.users.findOne(post.userId);
2013-10-29 17:54:45 +09:00
Meteor.call('upvotePost', post, postAuthor);
2014-08-03 11:50:10 +09:00
if(!!getSetting('emailNotifications', false)){
2013-10-23 10:21:08 +08:00
// notify users of new posts
2014-08-03 11:50:10 +09:00
emailProperties = {
postAuthorName : getDisplayName(postAuthor),
postAuthorId : post.userId,
postTitle : title,
postId : post._id,
profileUrl: getProfileUrlById(post.userId),
postUrl: getPostUrl(post._id)
};
// call a server method because we do not have access to users' info on the client
2014-08-03 11:50:10 +09:00
Meteor.call('newPostNotify', emailProperties, function(error, result){
//run asynchronously
});
}
2012-10-24 11:04:42 +09:00
return post;
2013-01-13 08:52:35 +09:00
},
2014-07-03 13:15:23 +09:00
setPostedAt: function(post, customPostedAt){
2014-07-03 16:17:36 +09:00
2014-07-03 13:15:23 +09:00
var postedAt = new Date(); // default to current date and time
2014-07-03 16:17:36 +09:00
2014-07-03 13:15:23 +09:00
if(isAdmin(Meteor.user()) && typeof customPostedAt !== 'undefined') // if user is admin and a custom datetime has been set
var postedAt = customPostedAt;
2014-07-03 16:17:36 +09:00
2014-07-03 13:15:23 +09:00
Posts.update(post._id, {$set: {postedAt: postedAt}});
},
2013-01-13 10:21:09 +09:00
post_edit: function(post){
2013-11-06 09:29:10 +09:00
// TODO: make post_edit server-side?
2013-07-04 12:51:26 +09:00
},
2014-05-23 13:08:52 +09:00
approvePost: function(post){
if(isAdmin(Meteor.user())){
var now = new Date();
2014-07-03 14:13:47 +09:00
Posts.update(post._id, {$set: {status: 2, postedAt: now}});
2014-05-23 13:08:52 +09:00
}else{
throwError('You need to be an admin to do that.');
}
},
unapprovePost: function(post){
if(isAdmin(Meteor.user())){
Posts.update(post._id, {$set: {status: 1}});
}else{
throwError('You need to be an admin to do that.');
}
},
clickedPost: function(post, sessionId){
// only let clients increment a post's click counter once per session
var click = {_id: post._id, sessionId: sessionId};
if(_.where(clickedPosts, click).length == 0){
clickedPosts.push(click);
Posts.update(post._id, { $inc: { clicks: 1 }});
}
},
deletePostById: function(postId) {
// remove post comments
2013-11-08 11:10:23 +09:00
// if(!this.isSimulation) {
// Comments.remove({post: postId});
// }
// NOTE: actually, keep comments afer all
// decrement post count
2013-11-11 20:53:02 +02:00
var post = Posts.findOne({_id: postId});
2013-11-11 21:15:04 +02:00
if(!Meteor.userId() || !canEditById(Meteor.userId(), post)) throw new Meteor.Error(606, 'You need permission to edit or delete a post');
2013-11-11 20:53:02 +02:00
2013-11-11 21:15:04 +02:00
Meteor.users.update({_id: post.userId}, {$inc: {postCount: -1}});
Posts.remove(postId);
2014-08-03 11:50:10 +09:00
},
newPostNotify : function(p){
// only run on server since we need to get a list of all users
if(Meteor.isServer){
var currentUser = Meteor.users.findOne(this.userId);
console.log('newPostNotify');
var subject = p.postAuthorName+' has created a new post: '+p.postTitle;
var html = Handlebars.templates[getTemplate('emailNewPost')](p)
// send a notification to every user according to their notifications settings
Meteor.users.find({'profile.notifications.posts': 1}).forEach(function(user) {
// don't send users notifications for their own posts
if(user._id !== currentUser._id && getUserSetting('notifications.posts', false, user))
sendEmail(getEmail(user), subject, html);
});
}
}
});