From cda38d6ed63cdcd963afc300807ed68054ba850d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 9 Mar 2015 13:16:14 -0400 Subject: [PATCH 1/5] closes #2515 --- src/posts.js | 26 +----------------- src/posts/topics.js | 44 ++++++++++++++++++++++++++++++ src/socket.io/posts.js | 60 +++++++++++++++++++++++++++++++++-------- src/socket.io/topics.js | 18 ++++++------- 4 files changed, 103 insertions(+), 45 deletions(-) create mode 100644 src/posts/topics.js diff --git a/src/posts.js b/src/posts.js index c8cfb8f085..2c7ca82737 100644 --- a/src/posts.js +++ b/src/posts.js @@ -16,6 +16,7 @@ var async = require('async'), require('./posts/create')(Posts); require('./posts/delete')(Posts); require('./posts/user')(Posts); + require('./posts/topics')(Posts); require('./posts/category')(Posts); require('./posts/summary')(Posts); require('./posts/recent')(Posts); @@ -25,20 +26,6 @@ var async = require('async'), db.isSortedSetMember('posts:pid', pid, callback); }; - Posts.getPostsByTid = function(tid, set, start, end, uid, reverse, callback) { - Posts.getPidsFromSet(set, start, end, reverse, function(err, pids) { - if(err) { - return callback(err); - } - - if(!Array.isArray(pids) || !pids.length) { - return callback(null, []); - } - - Posts.getPostsByPids(pids, uid, callback); - }); - }; - Posts.getPidsFromSet = function(set, start, end, reverse, callback) { if (isNaN(start) || isNaN(end)) { return callback(null, []); @@ -243,17 +230,6 @@ var async = require('async'), }); }; - Posts.isMain = function(pid, callback) { - Posts.getPostField(pid, 'tid', function(err, tid) { - if (err) { - return callback(err); - } - topics.getTopicField(tid, 'mainPid', function(err, mainPid) { - callback(err, parseInt(pid, 10) === parseInt(mainPid, 10)); - }); - }); - }; - Posts.updatePostVoteCount = function(pid, voteCount, callback) { async.parallel([ function(next) { diff --git a/src/posts/topics.js b/src/posts/topics.js new file mode 100644 index 0000000000..75577d2925 --- /dev/null +++ b/src/posts/topics.js @@ -0,0 +1,44 @@ + +'use strict'; + +var async = require('async'), + topics = require('../topics'); + +module.exports = function(Posts) { + + Posts.getPostsByTid = function(tid, set, start, end, uid, reverse, callback) { + Posts.getPidsFromSet(set, start, end, reverse, function(err, pids) { + if (err) { + return callback(err); + } + + if (!Array.isArray(pids) || !pids.length) { + return callback(null, []); + } + + Posts.getPostsByPids(pids, uid, callback); + }); + }; + + Posts.isMain = function(pid, callback) { + Posts.getPostField(pid, 'tid', function(err, tid) { + if (err) { + return callback(err); + } + topics.getTopicField(tid, 'mainPid', function(err, mainPid) { + callback(err, parseInt(pid, 10) === parseInt(mainPid, 10)); + }); + }); + }; + + Posts.getTopicFields = function(pid, fields, callback) { + Posts.getPostField(pid, 'tid', function(err, tid) { + if (err) { + return callback(err); + } + + topics.getTopicFields(tid, fields, callback); + }); + }; + +}; \ No newline at end of file diff --git a/src/socket.io/posts.js b/src/socket.io/posts.js index 0b5ab9b418..e8f5ef9a63 100644 --- a/src/socket.io/posts.js +++ b/src/socket.io/posts.js @@ -16,6 +16,7 @@ var async = require('async'), groups = require('../groups'), user = require('../user'), websockets = require('./index'), + socketTopics = require('./topics'), events = require('../events'), utils = require('../../public/src/utils'), @@ -345,27 +346,64 @@ function deleteOrRestore(command, socket, data, callback) { } SocketPosts.purge = function(socket, data, callback) { - if(!data || !parseInt(data.pid, 10)) { + function purgePost() { + postTools.purge(socket.uid, data.pid, function(err) { + if (err) { + return callback(err); + } + + websockets.in('topic_' + data.tid).emit('event:post_purged', data.pid); + + events.log({ + type: 'post-purge', + uid: socket.uid, + pid: data.pid, + ip: socket.ip + }); + + callback(); + }); + } + + if (!data || !parseInt(data.pid, 10)) { return callback(new Error('[[error:invalid-data]]')); } - postTools.purge(socket.uid, data.pid, function(err) { - if(err) { + + isMainAndLastPost(data.pid, function(err, results) { + if (err) { return callback(err); } - websockets.in('topic_' + data.tid).emit('event:post_purged', data.pid); + if (!results.isMain) { + return purgePost(); + } - events.log({ - type: 'post-purge', - uid: socket.uid, - pid: data.pid, - ip: socket.ip + if (!results.isLast) { + return callback(new Error('[[error:cant-purge-main-post]]')); + } + + posts.getTopicFields(data.pid, ['tid', 'cid'], function(err, topic) { + if (err) { + return callback(err); + } + socketTopics.doTopicAction('delete', 'event:topic_deleted', socket, {tids: [topic.tid], cid: topic.cid}, callback); }); - - callback(); }); }; +function isMainAndLastPost(pid, callback) { + async.parallel({ + isMain: function(next) { + posts.isMain(pid, next); + }, + isLast: function(next) { + posts.getTopicFields(pid, ['postcount'], function(err, topic) { + next(err, topic ? parseInt(topic.postcount, 10) === 1 : false); + }); + } + }, callback); +} + SocketPosts.getPrivileges = function(socket, pids, callback) { privileges.posts.get(pids, socket.uid, function(err, privileges) { if (err) { diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js index a4ee937429..cd42d1fde4 100644 --- a/src/socket.io/topics.js +++ b/src/socket.io/topics.js @@ -205,34 +205,34 @@ SocketTopics.markAsUnreadForAll = function(socket, tids, callback) { }; SocketTopics.delete = function(socket, data, callback) { - doTopicAction('delete', 'event:topic_deleted', socket, data, callback); + SocketTopics.doTopicAction('delete', 'event:topic_deleted', socket, data, callback); }; SocketTopics.restore = function(socket, data, callback) { - doTopicAction('restore', 'event:topic_restored', socket, data, callback); + SocketTopics.doTopicAction('restore', 'event:topic_restored', socket, data, callback); }; SocketTopics.purge = function(socket, data, callback) { - doTopicAction('purge', 'event:topic_purged', socket, data, callback); + SocketTopics.doTopicAction('purge', 'event:topic_purged', socket, data, callback); }; SocketTopics.lock = function(socket, data, callback) { - doTopicAction('lock', 'event:topic_locked', socket, data, callback); + SocketTopics.doTopicAction('lock', 'event:topic_locked', socket, data, callback); }; SocketTopics.unlock = function(socket, data, callback) { - doTopicAction('unlock', 'event:topic_unlocked', socket, data, callback); + SocketTopics.doTopicAction('unlock', 'event:topic_unlocked', socket, data, callback); }; SocketTopics.pin = function(socket, data, callback) { - doTopicAction('pin', 'event:topic_pinned', socket, data, callback); + SocketTopics.doTopicAction('pin', 'event:topic_pinned', socket, data, callback); }; SocketTopics.unpin = function(socket, data, callback) { - doTopicAction('unpin', 'event:topic_unpinned', socket, data, callback); + SocketTopics.doTopicAction('unpin', 'event:topic_unpinned', socket, data, callback); }; -function doTopicAction(action, event, socket, data, callback) { +SocketTopics.doTopicAction = function(action, event, socket, data, callback) { if (!socket.uid) { return; } @@ -274,7 +274,7 @@ function doTopicAction(action, event, socket, data, callback) { }); }); }, callback); -} +}; function emitToTopicAndCategory(event, data) { websockets.in('topic_' + data.tid).emit(event, data); From 33723f8b1be5591c6ef6c6a31590e388cfe42591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 9 Mar 2015 13:54:35 -0400 Subject: [PATCH 2/5] closes #2835 --- src/controllers/categories.js | 2 +- src/routes/feeds.js | 115 ++++++++++++++++++++++++---------- src/topics.js | 10 ++- 3 files changed, 91 insertions(+), 36 deletions(-) diff --git a/src/controllers/categories.js b/src/controllers/categories.js index 1ec014240b..5264e0e5f4 100644 --- a/src/controllers/categories.js +++ b/src/controllers/categories.js @@ -55,7 +55,7 @@ categoriesController.popular = function(req, res, next) { var data = { topics: topics, 'feeds:disableRSS': parseInt(meta.config['feeds:disableRSS'], 10) === 1, - rssFeedUrl: nconf.get('relative_path') + '/popular.rss', + rssFeedUrl: nconf.get('relative_path') + '/popular/' + (req.params.term || 'daily') + '.rss', breadcrumbs: helpers.buildBreadcrumbs([{text: '[[global:header.popular]]'}]) }; diff --git a/src/routes/feeds.js b/src/routes/feeds.js index 12b0f6a0e1..0f2f6082b6 100644 --- a/src/routes/feeds.js +++ b/src/routes/feeds.js @@ -135,14 +135,17 @@ function generateForCategory(req, res, next) { return next(err); } - var feed = generateTopicsFeed({ + generateTopicsFeed({ title: categoryData.name, description: categoryData.description, feed_url: '/category/' + cid + '.rss', site_url: '/category/' + categoryData.cid, - }, categoryData.topics); - - sendFeed(feed, res); + }, categoryData.topics, function(err, feed) { + if (err) { + return next(err); + } + sendFeed(feed, res); + }); }); } @@ -156,12 +159,32 @@ function generateForRecent(req, res, next) { } function generateForPopular(req, res, next) { - generateForTopics({ - title: 'Popular Topics', - description: 'A list of topics that are sorted by post count', - feed_url: '/popular.rss', - site_url: '/popular' - }, 'topics:posts', req, res, next); + var uid = req.user ? req.user.uid : 0; + var terms = { + daily: 'day', + weekly: 'week', + monthly: 'month', + alltime: 'alltime' + }; + var term = terms[req.params.term] || 'day'; + + topics.getPopular(term, uid, 19, function(err, topics) { + if (err) { + return next(err); + } + + generateTopicsFeed({ + title: 'Popular Topics', + description: 'A list of topics that are sorted by post count', + feed_url: '/popular/' + (req.params.term || 'daily') + '.rss', + site_url: '/popular/' + (req.params.term || 'daily') + }, topics, function(err, feed) { + if (err) { + return next(err); + } + sendFeed(feed, res); + }); + }); } function disabledRSS(req, res, next) { @@ -178,35 +201,58 @@ function generateForTopics(options, set, req, res, next) { if (err) { return next(err); } - - var feed = generateTopicsFeed(options, data.topics); - - sendFeed(feed, res); + + generateTopicsFeed(options, data.topics, function(err, feed) { + if (err) { + return next(err); + } + sendFeed(feed, res); + }); }); } -function generateTopicsFeed(feedOptions, topics) { - - feedOptions.ttl = 60; - feedOptions.feed_url = nconf.get('url') + feedOptions.feed_url; - feedOptions.site_url = nconf.get('url') + feedOptions.site_url; - - var feed = new rss(feedOptions); - - if (topics.length > 0) { - feed.pubDate = new Date(parseInt(topics[0].lastposttime, 10)).toUTCString(); - } - - topics.forEach(function(topicData) { - feed.item({ - title: topicData.title, - url: nconf.get('url') + '/topic/' + topicData.slug, - author: topicData.username, - date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString() - }); +function generateTopicsFeed(feedOptions, feedTopics, callback) { + var tids = feedTopics.map(function(topic) { + return topic ? topic.tid : null; }); + + topics.getMainPids(tids, function(err, pids) { + if (err) { + return callback(err); + } + posts.getPostsFields(pids, ['content'], function(err, posts) { + if (err) { + return callback(err); + } - return feed; + feedTopics.forEach(function(topic, index) { + if (topic && posts[index]) { + topic.mainPost = posts[index].content; + } + }); + + feedOptions.ttl = 60; + feedOptions.feed_url = nconf.get('url') + feedOptions.feed_url; + feedOptions.site_url = nconf.get('url') + feedOptions.site_url; + + var feed = new rss(feedOptions); + + if (feedTopics.length > 0) { + feed.pubDate = new Date(parseInt(feedTopics[0].lastposttime, 10)).toUTCString(); + } + + feedTopics.forEach(function(topicData) { + feed.item({ + title: topicData.title, + description: topicData.mainPost, + url: nconf.get('url') + '/topic/' + topicData.slug, + author: topicData.username, + date: new Date(parseInt(topicData.lastposttime, 10)).toUTCString() + }); + }); + callback(null, feed); + }); + }); } function generateForRecentPosts(req, res, next) { @@ -291,6 +337,7 @@ module.exports = function(app, middleware, controllers){ app.get('/category/:category_id.rss', hasCategoryPrivileges, disabledRSS, generateForCategory); app.get('/recent.rss', disabledRSS, generateForRecent); app.get('/popular.rss', disabledRSS, generateForPopular); + app.get('/popular/:term.rss', disabledRSS, generateForPopular); app.get('/recentposts.rss', disabledRSS, generateForRecentPosts); app.get('/category/:category_id/recentposts.rss', hasCategoryPrivileges, disabledRSS, generateForCategoryRecentPosts); app.get('/user/:userslug/topics.rss', disabledRSS, generateForUserTopics); diff --git a/src/topics.js b/src/topics.js index 274ffbcf70..3c22bcf30c 100644 --- a/src/topics.js +++ b/src/topics.js @@ -255,7 +255,7 @@ var async = require('async'), }); }; - Topics.getMainPosts = function(tids, uid, callback) { + Topics.getMainPids = function(tids, callback) { Topics.getTopicsFields(tids, ['mainPid'], function(err, topicData) { if (err) { return callback(err); @@ -264,7 +264,15 @@ var async = require('async'), var mainPids = topicData.map(function(topic) { return topic ? topic.mainPid : null; }); + callback(null, mainPids); + }); + }; + Topics.getMainPosts = function(tids, uid, callback) { + Topics.getMainPids(tids, function(err, mainPids) { + if (err) { + return callback(err); + } getMainPosts(mainPids, uid, callback); }); }; From 4d45a81fdb0686bfcb21c9849b2da4bf2248a5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 9 Mar 2015 15:30:52 -0400 Subject: [PATCH 3/5] closes #2383 --- public/src/ajaxify.js | 12 +++++++----- src/views/500.tpl | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 865626635c..5e26619253 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -89,11 +89,9 @@ $(document).ready(function() { app.previousUrl = url; return ajaxify.go('login'); } else if (status === 302) { - if (data.responseJSON.path) { - if (!ajaxify.go(data.responseJSON.path, callback, quiet)) { - window.location.href = data.responseJSON.path; - } - } else if (data.responseJSON) { + if (data.responseJSON.external && data.responseJSON.path) { + window.location.href = data.responseJSON.path; + } else if (typeof data.responseJSON === 'string') { ajaxify.go(data.responseJSON.slice(1), callback, quiet); } } @@ -184,6 +182,9 @@ $(document).ready(function() { } }, error: function(data, textStatus) { + if (data.status === 0 && textStatus === 'error') { + data.status = 500; + } callback({ data: data, textStatus: textStatus @@ -264,5 +265,6 @@ $(document).ready(function() { ajaxifyAnchors(); app.load(); + templates.cache['500'] = $('.tpl-500').html(); }); \ No newline at end of file diff --git a/src/views/500.tpl b/src/views/500.tpl index 13b0e9de89..6408fbb79d 100644 --- a/src/views/500.tpl +++ b/src/views/500.tpl @@ -1,7 +1,7 @@
[[global:500.title]]

[[global:500.message]]

-

{path}

+

{path}

{error}

-
\ No newline at end of file + From 53e0615df79afb951107b23a08eb24261312c9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Mon, 9 Mar 2015 15:33:20 -0400 Subject: [PATCH 4/5] removed path use external --- public/src/ajaxify.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 5e26619253..2392511386 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -89,8 +89,8 @@ $(document).ready(function() { app.previousUrl = url; return ajaxify.go('login'); } else if (status === 302) { - if (data.responseJSON.external && data.responseJSON.path) { - window.location.href = data.responseJSON.path; + if (data.responseJSON.external) { + window.location.href = data.responseJSON.external; } else if (typeof data.responseJSON === 'string') { ajaxify.go(data.responseJSON.slice(1), callback, quiet); } From 4f2ac340b2cfb9e0db7f8b2a0a12d19eb1ecbd4f Mon Sep 17 00:00:00 2001 From: psychobunny Date: Mon, 9 Mar 2015 15:52:01 -0400 Subject: [PATCH 5/5] latest tjs --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f38b87f0d..bab3c6bcb4 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "socket.io-redis": "^0.1.3", "socketio-wildcard": "~0.1.1", "string": "^3.0.0", - "templates.js": "^0.1.23", + "templates.js": "^0.1.28", "uglify-js": "git+https://github.com/julianlam/UglifyJS2.git", "underscore": "~1.7.0", "validator": "^3.30.0",