/*! * nodeclub - controllers/topic.js */ /** * Module dependencies. */ var validator = require('validator'); var at = require('../common/at'); var User = require('../proxy').User; var Topic = require('../proxy').Topic; var TopicCollect = require('../proxy').TopicCollect; var EventProxy = require('eventproxy'); var tools = require('../common/tools'); var store = require('../common/store'); var config = require('../config'); var _ = require('lodash'); var cache = require('../common/cache'); var logger = require('../common/logger') /** * Topic page * * @param {HttpRequest} req * @param {HttpResponse} res * @param {Function} next */ exports.index = function (req, res, next) { function isUped(user, reply) { if (!reply.ups) { return false; } return reply.ups.indexOf(user._id) !== -1; } var topic_id = req.params.tid; var currentUser = req.session.user; if (topic_id.length !== 24) { return res.render404('此话题不存在或已被删除。'); } var events = ['topic', 'other_topics', 'no_reply_topics', 'is_collect']; var ep = EventProxy.create(events, function (topic, other_topics, no_reply_topics, is_collect) { res.render('topic/index', { topic: topic, author_other_topics: other_topics, no_reply_topics: no_reply_topics, is_uped: isUped, is_collect: is_collect, }); }); ep.fail(next); Topic.getFullTopic(topic_id, ep.done(function (message, topic, author, replies) { if (message) { logger.error('getFullTopic error topic_id: ' + topic_id) return res.renderError(message); } topic.visit_count += 1; topic.save(); topic.author = author; topic.replies = replies; // 点赞数排名第三的回答,它的点赞数就是阈值 topic.reply_up_threshold = (function () { var allUpCount = replies.map(function (reply) { return reply.ups && reply.ups.length || 0; }); allUpCount = _.sortBy(allUpCount, Number).reverse(); var threshold = allUpCount[2] || 0; if (threshold < 3) { threshold = 3; } return threshold; })(); ep.emit('topic', topic); // get other_topics var options = { limit: 5, sort: '-last_reply_at'}; var query = { author_id: topic.author_id, _id: { '$nin': [ topic._id ] } }; Topic.getTopicsByQuery(query, options, ep.done('other_topics')); // get no_reply_topics cache.get('no_reply_topics', ep.done(function (no_reply_topics) { if (no_reply_topics) { ep.emit('no_reply_topics', no_reply_topics); } else { Topic.getTopicsByQuery( { reply_count: 0, tab: {$nin: ['job', 'dev']}}, { limit: 5, sort: '-create_at'}, ep.done('no_reply_topics', function (no_reply_topics) { cache.set('no_reply_topics', no_reply_topics, 60 * 1); return no_reply_topics; })); } })); })); if (!currentUser) { ep.emit('is_collect', null); } else { TopicCollect.getTopicCollect(currentUser._id, topic_id, ep.done('is_collect')) } }; exports.create = function (req, res, next) { res.render('topic/edit', { tabs: config.tabs }); }; exports.put = function (req, res, next) { var title = validator.trim(req.body.title); var tab = validator.trim(req.body.tab); var content = validator.trim(req.body.t_content); // 得到所有的 tab, e.g. ['ask', 'share', ..] var allTabs = config.tabs.map(function (tPair) { return tPair[0]; }); // 验证 var editError; if (title === '') { editError = '标题不能是空的。'; } else if (title.length < 5 || title.length > 100) { editError = '标题字数太多或太少。'; } else if (!tab || allTabs.indexOf(tab) === -1) { editError = '必须选择一个版块。'; } else if (content === '') { editError = '内容不可为空'; } // END 验证 if (editError) { res.status(422); return res.render('topic/edit', { edit_error: editError, title: title, content: content, tabs: config.tabs }); } Topic.newAndSave(title, content, tab, req.session.user._id, function (err, topic) { if (err) { return next(err); } var proxy = new EventProxy(); proxy.all('score_saved', function () { res.redirect('/topic/' + topic._id); }); proxy.fail(next); User.getUserById(req.session.user._id, proxy.done(function (user) { user.score += 5; user.topic_count += 1; user.save(); req.session.user = user; proxy.emit('score_saved'); })); //发送at消息 at.sendMessageToMentionUsers(content, topic._id, req.session.user._id); }); }; exports.showEdit = function (req, res, next) { var topic_id = req.params.tid; Topic.getTopicById(topic_id, function (err, topic, tags) { if (!topic) { res.render404('此话题不存在或已被删除。'); return; } if (String(topic.author_id) === String(req.session.user._id) || req.session.user.is_admin) { res.render('topic/edit', { action: 'edit', topic_id: topic._id, title: topic.title, content: topic.content, tab: topic.tab, tabs: config.tabs }); } else { res.renderError('对不起,你不能编辑此话题。', 403); } }); }; exports.update = function (req, res, next) { var topic_id = req.params.tid; var title = req.body.title; var tab = req.body.tab; var content = req.body.t_content; Topic.getTopicById(topic_id, function (err, topic, tags) { if (!topic) { res.render404('此话题不存在或已被删除。'); return; } if (topic.author_id.equals(req.session.user._id) || req.session.user.is_admin) { title = validator.trim(title); tab = validator.trim(tab); content = validator.trim(content); // 验证 var editError; if (title === '') { editError = '标题不能是空的。'; } else if (title.length < 5 || title.length > 100) { editError = '标题字数太多或太少。'; } else if (!tab) { editError = '必须选择一个版块。'; } // END 验证 if (editError) { return res.render('topic/edit', { action: 'edit', edit_error: editError, topic_id: topic._id, content: content, tabs: config.tabs }); } //保存话题 topic.title = title; topic.content = content; topic.tab = tab; topic.update_at = new Date(); topic.save(function (err) { if (err) { return next(err); } //发送at消息 at.sendMessageToMentionUsers(content, topic._id, req.session.user._id); res.redirect('/topic/' + topic._id); }); } else { res.renderError('对不起,你不能编辑此话题。', 403); } }); }; exports.delete = function (req, res, next) { //删除话题, 话题作者topic_count减1 //删除回复,回复作者reply_count减1 //删除topic_collect,用户collect_topic_count减1 var topic_id = req.params.tid; Topic.getFullTopic(topic_id, function (err, err_msg, topic, author, replies) { if (err) { return res.send({ success: false, message: err.message }); } if (!req.session.user.is_admin && !(topic.author_id.equals(req.session.user._id))) { res.status(403); return res.send({success: false, message: '无权限'}); } if (!topic) { res.status(422); return res.send({ success: false, message: '此话题不存在或已被删除。' }); } author.score -= 5; author.topic_count -= 1; author.save(); topic.deleted = true; topic.save(function (err) { if (err) { return res.send({ success: false, message: err.message }); } res.send({ success: true, message: '话题已被删除。' }); }); }); }; // 设为置顶 exports.top = function (req, res, next) { var topic_id = req.params.tid; var referer = req.get('referer'); if (topic_id.length !== 24) { res.render404('此话题不存在或已被删除。'); return; } Topic.getTopic(topic_id, function (err, topic) { if (err) { return next(err); } if (!topic) { res.render404('此话题不存在或已被删除。'); return; } topic.top = !topic.top; topic.save(function (err) { if (err) { return next(err); } var msg = topic.top ? '此话题已置顶。' : '此话题已取消置顶。'; res.render('notify/notify', {success: msg, referer: referer}); }); }); }; // 设为精华 exports.good = function (req, res, next) { var topicId = req.params.tid; var referer = req.get('referer'); Topic.getTopic(topicId, function (err, topic) { if (err) { return next(err); } if (!topic) { res.render404('此话题不存在或已被删除。'); return; } topic.good = !topic.good; topic.save(function (err) { if (err) { return next(err); } var msg = topic.good ? '此话题已加精。' : '此话题已取消加精。'; res.render('notify/notify', {success: msg, referer: referer}); }); }); }; // 锁定主题,不可再回复 exports.lock = function (req, res, next) { var topicId = req.params.tid; var referer = req.get('referer'); Topic.getTopic(topicId, function (err, topic) { if (err) { return next(err); } if (!topic) { res.render404('此话题不存在或已被删除。'); return; } topic.lock = !topic.lock; topic.save(function (err) { if (err) { return next(err); } var msg = topic.lock ? '此话题已锁定。' : '此话题已取消锁定。'; res.render('notify/notify', {success: msg, referer: referer}); }); }); }; // 收藏主题 exports.collect = function (req, res, next) { var topic_id = req.body.topic_id; Topic.getTopic(topic_id, function (err, topic) { if (err) { return next(err); } if (!topic) { res.json({status: 'failed'}); } TopicCollect.getTopicCollect(req.session.user._id, topic._id, function (err, doc) { if (err) { return next(err); } if (doc) { res.json({status: 'failed'}); return; } TopicCollect.newAndSave(req.session.user._id, topic._id, function (err) { if (err) { return next(err); } res.json({status: 'success'}); }); User.getUserById(req.session.user._id, function (err, user) { if (err) { return next(err); } user.collect_topic_count += 1; user.save(); }); req.session.user.collect_topic_count += 1; topic.collect_count += 1; topic.save(); }); }); }; exports.de_collect = function (req, res, next) { var topic_id = req.body.topic_id; Topic.getTopic(topic_id, function (err, topic) { if (err) { return next(err); } if (!topic) { res.json({status: 'failed'}); } TopicCollect.remove(req.session.user._id, topic._id, function (err, removeResult) { if (err) { return next(err); } if (removeResult.n == 0) { return res.json({status: 'failed'}) } User.getUserById(req.session.user._id, function (err, user) { if (err) { return next(err); } user.collect_topic_count -= 1; req.session.user = user; user.save(); }); topic.collect_count -= 1; topic.save(); res.json({status: 'success'}); }); }); }; exports.upload = function (req, res, next) { var isFileLimit = false; req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { file.on('limit', function () { isFileLimit = true; res.json({ success: false, msg: 'File size too large. Max is ' + config.file_limit }) }); store.upload(file, {filename: filename}, function (err, result) { if (err) { return next(err); } if (isFileLimit) { return; } res.json({ success: true, url: result.url, }); }); }); req.pipe(req.busboy); };