diff --git a/public/src/client/unread.js b/public/src/client/unread.js index 9df088a16f..d5a8966576 100644 --- a/public/src/client/unread.js +++ b/public/src/client/unread.js @@ -4,6 +4,12 @@ define('forum/unread', ['topicSelect', 'components', 'topicList'], function (topicSelect, components, topicList) { var Unread = {}; + var watchStates = { + ignoring: 1, + notwatching: 2, + watching: 3, + }; + Unread.init = function () { app.enterRoom('unread_topics'); @@ -95,8 +101,11 @@ define('forum/unread', ['topicSelect', 'components', 'topicList'], function (top function onNewPost(data) { if (data && data.posts && data.posts.length) { var post = data.posts[0]; - - if (parseInt(post.uid, 10) !== parseInt(app.user.uid, 10) && !unreadTopics[post.topic.tid]) { + if ( + parseInt(post.uid, 10) !== parseInt(app.user.uid, 10) && + !unreadTopics[post.topic.tid] && + (post.topic.isFollowing || post.categoryWatchState === watchStates.watching) + ) { increaseUnreadCount(post); markTopicsUnread(post.topic.tid); unreadTopics[post.topic.tid] = true; @@ -119,16 +128,10 @@ define('forum/unread', ['topicSelect', 'components', 'topicList'], function (top var unreadUnrepliedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=unreplied"].navigation-link i').attr('data-content'), 10) + 1; updateUnreadTopicCount('/unread?filter=unreplied', unreadUnrepliedTopicCount); } - if ($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').length) { - socket.emit('topics.isFollowed', post.topic.tid, function (err, isFollowed) { - if (err) { - return app.alertError(err.message); - } - if (isFollowed) { - var unreadWatchedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').attr('data-content'), 10) + 1; - updateUnreadTopicCount('/unread?filter=watched', unreadWatchedTopicCount); - } - }); + + if (post.topic.isFollowing) { + var unreadWatchedTopicCount = parseInt($('a[href="' + config.relative_path + '/unread?filter=watched"].navigation-link i').attr('data-content'), 10) + 1; + updateUnreadTopicCount('/unread?filter=watched', unreadWatchedTopicCount); } } diff --git a/public/src/modules/topicList.js b/public/src/modules/topicList.js index 56219fec14..ab4d0aa08c 100644 --- a/public/src/modules/topicList.js +++ b/public/src/modules/topicList.js @@ -82,10 +82,19 @@ define('topicList', [ socket.removeListener('event:new_post', onNewPost); }; + function isCategoryVisible(cid) { + return ajaxify.data.categories && ajaxify.data.categories.length && ajaxify.data.categories.some(function (c) { + return parseInt(c.cid, 10) === parseInt(cid, 10); + }); + } + function onNewTopic(data) { - if ((ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(data.cid, 10)) === -1) || + if ( + (ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(data.cid, 10)) === -1) || (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched') || - (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(data.cid, 10))) { + (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(data.cid, 10)) || + (!isCategoryVisible(data.cid)) + ) { return; } @@ -94,35 +103,23 @@ define('topicList', [ } function onNewPost(data) { - function showAlert() { - newPostCount += 1; - updateAlertText(); - } - var post = data.posts[0]; - if ( - (!post || !post.topic) || + if (!post || !post.topic) { + return; + } + if (!post.topic.isFollowing && ( (parseInt(post.topic.mainPid, 10) === parseInt(post.pid, 10)) || (ajaxify.data.selectedCids && ajaxify.data.selectedCids.length && ajaxify.data.selectedCids.indexOf(parseInt(post.topic.cid, 10)) === -1) || (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'new') || - (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(post.topic.cid, 10)) - ) { + (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched' && !post.topic.isFollowing) || + (ajaxify.data.template.category && parseInt(ajaxify.data.cid, 10) !== parseInt(post.topic.cid, 10)) || + (!isCategoryVisible(post.topic.cid)) + )) { return; } - if (ajaxify.data.selectedFilter && ajaxify.data.selectedFilter.filter === 'watched') { - socket.emit('topics.isFollowed', post.tid, function (err, isFollowed) { - if (err) { - app.alertError(err.message); - } - if (isFollowed) { - showAlert(); - } - }); - return; - } - - showAlert(); + newPostCount += 1; + updateAlertText(); } function updateAlertText() { diff --git a/src/controllers/accounts/profile.js b/src/controllers/accounts/profile.js index 18d453f2ec..62ce87065d 100644 --- a/src/controllers/accounts/profile.js +++ b/src/controllers/accounts/profile.js @@ -41,7 +41,7 @@ profileController.get = function (req, res, callback) { } userData = _userData; - if (!req.isSpider()) { + if (req.uid >= 0) { req.session.uids_viewed = req.session.uids_viewed || {}; if (req.uid !== userData.uid && (!req.session.uids_viewed[userData.uid] || req.session.uids_viewed[userData.uid] < Date.now() - 3600000)) { diff --git a/src/controllers/api.js b/src/controllers/api.js index 522e4676e3..f90b2453f9 100644 --- a/src/controllers/api.js +++ b/src/controllers/api.js @@ -57,7 +57,7 @@ apiController.loadConfig = function (req, callback) { config.requireEmailConfirmation = meta.config.requireEmailConfirmation === 1; config.topicPostSort = meta.config.topicPostSort || 'oldest_to_newest'; config.categoryTopicSort = meta.config.categoryTopicSort || 'newest_to_oldest'; - config.csrf_token = !req.isSpider() && req.csrfToken && req.csrfToken(); + config.csrf_token = req.uid >= 0 && req.csrfToken && req.csrfToken(); config.searchEnabled = plugins.hasListeners('filter:search.query'); config.bootswatchSkin = meta.config.bootswatchSkin || ''; config.enablePostHistory = (meta.config.enablePostHistory || 1) === 1; diff --git a/src/controllers/topics.js b/src/controllers/topics.js index e6f38244a3..97b2c78795 100644 --- a/src/controllers/topics.js +++ b/src/controllers/topics.js @@ -161,7 +161,7 @@ topicsController.get = function (req, res, callback) { res.locals.linkTags.push(rel); }); - if (!req.isSpider()) { + if (req.uid >= 0) { req.session.tids_viewed = req.session.tids_viewed || {}; if (!req.session.tids_viewed[tid] || req.session.tids_viewed[tid] < Date.now() - 3600000) { topics.increaseViewCount(tid); diff --git a/src/middleware/header.js b/src/middleware/header.js index 052a69ff4a..e2d6633722 100644 --- a/src/middleware/header.js +++ b/src/middleware/header.js @@ -26,7 +26,7 @@ module.exports = function (middleware) { res.locals.isAPI = false; async.waterfall([ function (next) { - if (!req.isSpider()) { + if (req.uid >= 0) { middleware.applyCSRF(req, res, next); } else { setImmediate(next); @@ -241,7 +241,7 @@ module.exports = function (middleware) { data.templateValues.useCustomJS = meta.config.useCustomJS; data.templateValues.customJS = data.templateValues.useCustomJS ? meta.config.customJS : ''; - data.templateValues.isSpider = req.isSpider(); + data.templateValues.isSpider = req.uid === -1; req.app.render('footer', data.templateValues, next); }, ], callback); diff --git a/src/routes/api.js b/src/routes/api.js index d2143f30da..1fc95c6764 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -9,7 +9,7 @@ module.exports = function (app, middleware, controllers) { app.use('/api', router); router.get('/config', function (req, res, next) { - if (!req.isSpider()) { + if (req.uid >= 0) { middleware.applyCSRF(req, res, next); } else { setImmediate(next); diff --git a/src/socket.io/helpers.js b/src/socket.io/helpers.js index bc18e4b69a..5e1f85cd66 100644 --- a/src/socket.io/helpers.js +++ b/src/socket.io/helpers.js @@ -2,6 +2,7 @@ var async = require('async'); var winston = require('winston'); +var _ = require('lodash'); var db = require('../database'); var websockets = require('./index'); @@ -17,21 +18,32 @@ var utils = require('../utils'); var SocketHelpers = module.exports; SocketHelpers.notifyNew = function (uid, type, result) { + let watchStateUids; + let categoryWatchStates; + let topicFollowState; + const post = result.posts[0]; + const tid = post.topic.tid; + const cid = post.topic.cid; async.waterfall([ function (next) { user.getUidsFromSet('users:online', 0, -1, next); }, function (uids, next) { - privileges.topics.filterUids('read', result.posts[0].topic.tid, uids, next); + uids = uids.filter(uid => parseInt(uid, 10) !== uid); + privileges.topics.filterUids('read', tid, uids, next); }, function (uids, next) { - filterTidCidIgnorers(uids, result.posts[0].topic.tid, result.posts[0].topic.cid, next); + watchStateUids = uids; + getWatchStates(watchStateUids, tid, cid, next); }, - function (uids, next) { + function (watchStates, next) { + categoryWatchStates = _.zipObject(watchStateUids, watchStates.categoryWatchStates); + topicFollowState = _.zipObject(watchStateUids, watchStates.topicFollowed); + const uids = filterTidCidIgnorers(watchStateUids, watchStates); user.blocks.filterUids(uid, uids, next); }, function (uids, next) { - user.blocks.filterUids(result.posts[0].topic.uid, uids, next); + user.blocks.filterUids(post.topic.uid, uids, next); }, function (uids, next) { plugins.fireHook('filter:sockets.sendNewPostToUids', { uidsTo: uids, uidFrom: uid, type: type }, next); @@ -41,42 +53,38 @@ SocketHelpers.notifyNew = function (uid, type, result) { return winston.error(err.stack); } - result.posts[0].ip = undefined; + post.ip = undefined; data.uidsTo.forEach(function (toUid) { - if (parseInt(toUid, 10) !== uid) { - websockets.in('uid_' + toUid).emit('event:new_post', result); - if (result.topic && type === 'newTopic') { - websockets.in('uid_' + toUid).emit('event:new_topic', result.topic); - } + post.categoryWatchState = categoryWatchStates[toUid]; + post.topic.isFollowing = topicFollowState[toUid]; + websockets.in('uid_' + toUid).emit('event:new_post', result); + if (result.topic && type === 'newTopic') { + websockets.in('uid_' + toUid).emit('event:new_topic', result.topic); } }); }); }; -function filterTidCidIgnorers(uids, tid, cid, callback) { - async.waterfall([ - function (next) { - async.parallel({ - topicFollowed: function (next) { - db.isSetMembers('tid:' + tid + ':followers', uids, next); - }, - topicIgnored: function (next) { - db.isSetMembers('tid:' + tid + ':ignorers', uids, next); - }, - categoryWatchStates: function (next) { - categories.getUidsWatchStates(cid, uids, next); - }, - }, next); +function getWatchStates(uids, tid, cid, callback) { + async.parallel({ + topicFollowed: function (next) { + db.isSetMembers('tid:' + tid + ':followers', uids, next); }, - function (results, next) { - uids = uids.filter(function (uid, index) { - return results.topicFollowed[index] || - (!results.topicIgnored[index] && results.categoryWatchStates[index] !== categories.watchStates.ignoring); - }); - next(null, uids); + topicIgnored: function (next) { + db.isSetMembers('tid:' + tid + ':ignorers', uids, next); + }, + categoryWatchStates: function (next) { + categories.getUidsWatchStates(cid, uids, next); }, - ], callback); + }, callback); +} + +function filterTidCidIgnorers(uids, watchStates) { + return uids.filter(function (uid, index) { + return watchStates.topicFollowed[index] || + (!watchStates.topicIgnored[index] && watchStates.categoryWatchStates[index] !== categories.watchStates.ignoring); + }); } SocketHelpers.sendNotificationToPostOwner = function (pid, fromuid, command, notification) {