You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nodebb/src/topics/create.js

297 lines
7.5 KiB
JavaScript

'use strict';
var async = require('async'),
validator = require('validator'),
11 years ago
db = require('../database'),
utils = require('../../public/src/utils'),
plugins = require('../plugins'),
user = require('../user'),
meta = require('../meta'),
posts = require('../posts'),
threadTools = require('../threadTools'),
postTools = require('../postTools'),
privileges = require('../privileges'),
11 years ago
categories = require('../categories');
module.exports = function(Topics) {
Topics.create = function(data, callback) {
var uid = data.uid,
title = data.title,
cid = data.cid;
db.incrObjectField('global', 'nextTid', function(err, tid) {
if (err) {
return callback(err);
}
var slug = utils.slugify(title),
timestamp = Date.now();
if (!slug.length) {
return callback(new Error('[[error:invalid-title]]'));
}
slug = tid + '/' + slug;
var topicData = {
'tid': tid,
'uid': uid,
'cid': cid,
'mainPid': 0,
'title': title,
'slug': slug,
'timestamp': timestamp,
'lastposttime': 0,
'postcount': 0,
'viewcount': 0,
'locked': 0,
'deleted': 0,
'pinned': 0
};
if (data.thumb) {
topicData.thumb = data.thumb;
}
db.setObject('topic:' + tid, topicData, function(err) {
if (err) {
return callback(err);
}
async.parallel([
function(next) {
10 years ago
db.sortedSetsAdd([
'topics:tid',
'cid:' + cid + ':tids',
'cid:' + cid + ':uid:' + uid + ':tids'
], timestamp, tid, next);
},
function(next) {
user.addTopicIdToUser(uid, tid, timestamp, next);
},
function(next) {
db.incrObjectField('category:' + cid, 'topic_count', next);
},
function(next) {
db.incrObjectField('global', 'topicCount', next);
},
function(next) {
Topics.createTags(data.tags, tid, timestamp, next);
}
], function(err) {
if (err) {
return callback(err);
}
10 years ago
plugins.fireHook('action:topic.save', topicData);
callback(null, tid);
});
});
});
};
Topics.post = function(data, callback) {
var uid = data.uid,
handle = data.handle,
title = data.title,
content = data.content,
cid = data.cid;
if (title) {
title = title.trim();
}
if (!title || title.length < parseInt(meta.config.minimumTitleLength, 10)) {
return callback(new Error('[[error:title-too-short, ' + meta.config.minimumTitleLength + ']]'));
10 years ago
} else if (title.length > parseInt(meta.config.maximumTitleLength, 10)) {
return callback(new Error('[[error:title-too-long, ' + meta.config.maximumTitleLength + ']]'));
}
async.waterfall([
10 years ago
function(next) {
checkContentLength(content, next);
},
function(next) {
11 years ago
categories.exists(cid, next);
},
function(categoryExists, next) {
if (!categoryExists) {
return next(new Error('[[error:no-category]]'));
}
11 years ago
privileges.categories.can('topics:create', cid, uid, next);
},
11 years ago
function(canCreate, next) {
if(!canCreate) {
return next(new Error('[[error:no-privileges]]'));
}
user.isReadyToPost(uid, next);
},
function(next) {
plugins.fireHook('filter:topic.post', data, next);
},
function(filteredData, next) {
content = filteredData.content || data.content;
Topics.create({uid: uid, title: title, cid: cid, thumb: data.thumb, tags: data.tags}, next);
},
function(tid, next) {
Topics.reply({uid:uid, tid:tid, handle: handle, content:content, req: data.req}, next);
},
function(postData, next) {
11 years ago
async.parallel({
postData: function(next) {
next(null, postData);
},
settings: function(next) {
user.getSettings(uid, function(err, settings) {
if (err) {
return next(err);
}
if (settings.followTopicsOnCreate) {
threadTools.follow(postData.tid, uid, next);
} else {
next();
}
});
},
topicData: function(next) {
Topics.getTopicsByTids([postData.tid], 0, next);
}
11 years ago
}, next);
},
function(data, next) {
if(!Array.isArray(data.topicData) || !data.topicData.length) {
return next(new Error('[[error:no-topic]]'));
}
data.topicData = data.topicData[0];
data.topicData.unreplied = 1;
11 years ago
plugins.fireHook('action:topic.post', data.topicData);
11 years ago
if (parseInt(uid, 10)) {
user.notifications.sendTopicNotificationToFollowers(uid, data.topicData, data.postData);
}
11 years ago
next(null, {
topicData: data.topicData,
postData: data.postData
});
}
], callback);
};
Topics.reply = function(data, callback) {
var tid = data.tid,
uid = data.uid,
toPid = data.toPid,
handle = data.handle,
content = data.content,
postData;
async.waterfall([
function(next) {
async.parallel({
exists: function(next) {
threadTools.exists(tid, next);
},
locked: function(next) {
Topics.isLocked(tid, next);
},
canReply: function(next) {
privileges.topics.can('topics:reply', tid, uid, next);
}
}, next);
},
function(results, next) {
if (!results.exists) {
return next(new Error('[[error:no-topic]]'));
}
if (results.locked) {
return next(new Error('[[error:topic-locked]]'));
}
if (!results.canReply) {
return next(new Error('[[error:no-privileges]]'));
}
user.isReadyToPost(uid, next);
},
function(next) {
plugins.fireHook('filter:topic.reply', data, next);
},
function(filteredData, next) {
content = filteredData.content || data.content;
if (content) {
content = content.trim();
}
10 years ago
checkContentLength(content, next);
},
function(next) {
posts.create({uid: uid, tid: tid, handle: handle, content: content, toPid: toPid, ip: data.req ? data.req.ip : null}, next);
},
function(data, next) {
postData = data;
Topics.markAsUnreadForAll(tid, next);
},
function(next) {
Topics.markAsRead([tid], uid, next);
},
11 years ago
function(next) {
async.parallel({
userInfo: function(next) {
posts.getUserInfoForPosts([postData.uid], uid, next);
},
topicInfo: function(next) {
Topics.getTopicFields(tid, ['tid', 'title', 'slug', 'cid'], next);
},
settings: function(next) {
user.getSettings(uid, next);
},
postIndex: function(next) {
posts.getPidIndex(postData.pid, uid, next);
},
content: function(next) {
postTools.parsePost(postData, uid, next);
}
}, next);
11 years ago
},
function(results, next) {
postData.user = results.userInfo[0];
postData.topic = results.topicInfo;
// Username override for guests, if enabled
if (parseInt(meta.config.allowGuestHandles, 10) === 1 && parseInt(postData.uid, 10) === 0 && data.handle) {
postData.user.username = data.handle;
}
if (results.settings.followTopicsOnReply) {
11 years ago
threadTools.follow(postData.tid, uid);
}
postData.index = results.postIndex - 1;
postData.favourited = false;
postData.votes = 0;
postData.display_moderator_tools = true;
postData.display_move_tools = true;
postData.selfPost = false;
postData.relativeTime = utils.toISOString(postData.timestamp);
if (parseInt(uid, 10)) {
10 years ago
Topics.notifyFollowers(postData, uid);
}
10 years ago
postData.topic.title = validator.escape(postData.topic.title);
next(null, postData);
}
], callback);
};
10 years ago
function checkContentLength(content, callback) {
if (!content || content.length < parseInt(meta.config.miminumPostLength, 10)) {
return callback(new Error('[[error:content-too-short, ' + meta.config.minimumPostLength + ']]'));
}
callback();
}
};