Squashed commit of the following:

commit 56582bc9eee5d81a01f42a28808b617b9c96873a
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 05:21:11 2015 -0400

    added missing template

commit 6462a1626e7d8d77210b6e10eace5c9214335f33
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 05:19:07 2015 -0400

    sitemap index

commit 3cfd56f1fbc8e03405dc394375bf5ff6eef21322
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 04:47:52 2015 -0400

    sitemap routes, controllers, and library methods for pages, categories, and topics

commit e58e07c0881bdbe16d503b4679b85f761b02163c
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 04:07:39 2015 -0400

    added groups to sitemap

commit 7ee584b632
Author: Julian Lam <julian@designcreateplay.com>
Date:   Tue Oct 27 01:43:06 2015 -0400

    If notification dropdown is double-clicked, all notifications are marked read

commit 488f147bef
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:39:19 2015 -0400

    closes #3781

commit 5e1bd58a02
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:28:30 2015 -0400

    closes #3782

commit 57d3980267
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 22:16:08 2015 -0400

    closes #3790

commit 555c5b82da
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 21:19:20 2015 -0400

    check user settings

commit 5454862c1c
Author: barisusakli <barisusakli@gmail.com>
Date:   Mon Oct 26 20:26:02 2015 -0400

    wait for all callbacks when creating tags

commit 051c5077eb
Merge: 839fd93 e0e04ef
Author: Barış Soner Uşaklı <barisusakli@gmail.com>
Date:   Mon Oct 26 09:54:12 2015 -0400

    Merge pull request #3792 from drlogout/master

    Fixed wrong method name in socket.io/groups.js from isAdmin to isAdmi…

commit e0e04ef892
Author: Christian Nolte <hello@noltech.net>
Date:   Mon Oct 26 14:50:32 2015 +0100

    Fixed wrong method name in socket.io/groups.js from isAdmin to isAdministrator

commit 839fd935ad
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 21:54:35 2015 -0400

    add back thread tools filter

commit 37060bf1a3
Merge: 5820a19 bf918bd
Author: Barış Soner Uşaklı <barisusakli@gmail.com>
Date:   Sun Oct 25 18:13:06 2015 -0400

    Merge pull request #3787 from cubehouse/patch-1

    Upgrade script fails on some consoles

commit 5820a193f6
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 17:04:46 2015 -0400

    closes #3789

commit 0d88d52557
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 17:03:33 2015 -0400

    up theme

commit 9bc43ba5e1
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 16:57:42 2015 -0400

    closes #3788

commit aafd4b6984
Author: barisusakli <barisusakli@gmail.com>
Date:   Sun Oct 25 15:56:17 2015 -0400

    closes #3786

commit bf918bd016
Author: James Holding <cubehouse@users.noreply.github.com>
Date:   Sun Oct 25 10:14:00 2015 +0000

    Upgrade script fails on some consoles

    The upgrade script errors/fails on some consoles if the stdout.columns isn't set (my console did this when upgrading a Docker instance of NodeBB).
    Checking for stdout.columns before using, falling back to a couple of spaces for slightly prettiness if we can't work out the console width.
v1.18.x
Julian Lam 9 years ago
parent f7f43de644
commit 68c3f9d849

@ -144,8 +144,10 @@ switch(process.argv[2]) {
if (err) { if (err) {
process.stdout.write('\nError'.red + ': ' + err.message + '\n'); process.stdout.write('\nError'.red + ': ' + err.message + '\n');
} else { } else {
var message = 'NodeBB Upgrade Complete!', var message = 'NodeBB Upgrade Complete!';
spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' '); // some consoles will return undefined/zero columns, so just use 2 spaces in upgrade script if we can't get our column count
var columns = process.stdout.columns;
var spaces = columns ? new Array(Math.floor(columns / 2) - (message.length / 2) + 1).join(' ') : " ";
process.stdout.write('OK\n'.green); process.stdout.write('OK\n'.green);
process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset); process.stdout.write('\n' + spaces + message.green.bold + '\n\n'.reset);

@ -49,8 +49,8 @@
"nodebb-plugin-spam-be-gone": "0.4.2", "nodebb-plugin-spam-be-gone": "0.4.2",
"nodebb-rewards-essentials": "0.0.5", "nodebb-rewards-essentials": "0.0.5",
"nodebb-theme-lavender": "2.0.10", "nodebb-theme-lavender": "2.0.10",
"nodebb-theme-persona": "3.0.61", "nodebb-theme-persona": "3.0.62",
"nodebb-theme-vanilla": "4.0.28", "nodebb-theme-vanilla": "4.0.29",
"nodebb-widget-essentials": "2.0.3", "nodebb-widget-essentials": "2.0.3",
"npm": "^2.1.4", "npm": "^2.1.4",
"passport": "^0.3.0", "passport": "^0.3.0",
@ -61,7 +61,7 @@
"rss": "^1.0.0", "rss": "^1.0.0",
"semver": "^5.0.1", "semver": "^5.0.1",
"serve-favicon": "^2.1.5", "serve-favicon": "^2.1.5",
"sitemap": "^1.0.0", "sitemap": "^1.4.0",
"socket.io": "^1.2.1", "socket.io": "^1.2.1",
"socket.io-client": "^1.2.1", "socket.io-client": "^1.2.1",
"socket.io-redis": "^0.1.3", "socket.io-redis": "^0.1.3",

@ -10,7 +10,7 @@ define('forum/topic/fork', ['components'], function(components) {
pids = []; pids = [];
Fork.init = function() { Fork.init = function() {
components.get('topic/fork').on('click', onForkThreadClicked); $('.topic').on('click', '[component="topic/fork"]', onForkThreadClicked);
}; };
function disableClicks() { function disableClicks() {

@ -11,14 +11,21 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
notifList = components.get('notifications/list'), notifList = components.get('notifications/list'),
notifIcon = components.get('notifications/icon'); notifIcon = components.get('notifications/icon');
notifTrigger.on('click', function(e) { notifTrigger
e.preventDefault(); .on('click', function(e) {
if (notifContainer.hasClass('open')) { e.preventDefault();
return; if (notifContainer.hasClass('open')) {
} return;
}
Notifications.loadNotifications(notifList); Notifications.loadNotifications(notifList);
}); })
.on('dblclick', function(e) {
e.preventDefault();
if (parseInt(notifIcon.attr('data-content'), 10) > 0) {
Notifications.markAllRead();
}
});
notifList.on('click', '[data-nid]', function() { notifList.on('click', '[data-nid]', function() {
var unread = $(this).hasClass('unread'); var unread = $(this).hasClass('unread');
@ -33,14 +40,7 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
}); });
}); });
notifContainer.on('click', '.mark-all-read', function() { notifContainer.on('click', '.mark-all-read', Notifications.markAllRead);
socket.emit('notifications.markAllRead', function(err) {
if (err) {
app.alertError(err.message);
}
Notifications.updateNotifCount(0);
});
});
notifList.on('click', '.mark-read', function(e) { notifList.on('click', '.mark-read', function(e) {
var liEl = $(this).parent(), var liEl = $(this).parent(),
@ -125,5 +125,14 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
Tinycon.setBubble(count); Tinycon.setBubble(count);
}; };
Notifications.markAllRead = function() {
socket.emit('notifications.markAllRead', function(err) {
if (err) {
app.alertError(err.message);
}
Notifications.updateNotifCount(0);
});
};
return Notifications; return Notifications;
}); });

@ -10,6 +10,7 @@ var async = require('async'),
posts = require('../posts'), posts = require('../posts'),
topics = require('../topics'), topics = require('../topics'),
plugins = require('../plugins'), plugins = require('../plugins'),
sitemap = require('../sitemap'),
categories = require('../categories'), categories = require('../categories'),
privileges = require('../privileges'), privileges = require('../privileges'),
helpers = require('./helpers'); helpers = require('./helpers');
@ -161,14 +162,56 @@ Controllers.confirmEmail = function(req, res, next) {
}); });
}; };
Controllers.sitemap = function(req, res, next) { Controllers.sitemap = {};
Controllers.sitemap.render = function(req, res, next) {
sitemap.render(function(err, tplData) {
Controllers.render('sitemap', tplData, function(err, xml) {
res.header('Content-Type', 'application/xml');
res.send(xml);
});
})
};
Controllers.sitemap.getPages = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next();
}
sitemap.getPages(function(err, xml) {
if (err) {
return next(err);
}
res.header('Content-Type', 'application/xml');
res.send(xml);
});
};
Controllers.sitemap.getCategories = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) { if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next(); return next();
} }
var sitemap = require('../sitemap.js'); sitemap.getCategories(function(err, xml) {
if (err) {
return next(err);
}
res.header('Content-Type', 'application/xml');
res.send(xml);
});
};
Controllers.sitemap.getTopicPage = function(req, res, next) {
if (parseInt(meta.config['feeds:disableSitemap'], 10) === 1) {
return next();
}
sitemap.getTopicPage(parseInt(req.params[0], 10), function(err, xml) {
if (err) {
return next(err);
} else if (!xml) {
return next();
}
sitemap.render(function(xml) {
res.header('Content-Type', 'application/xml'); res.header('Content-Type', 'application/xml');
res.send(xml); res.send(xml);
}); });

@ -374,12 +374,8 @@ var db = require('./database'),
}; };
Messaging.canMessage = function(fromUid, toUid, callback) { Messaging.canMessage = function(fromUid, toUid, callback) {
if (parseInt(meta.config.disableChat) === 1) { if (parseInt(meta.config.disableChat) === 1 || !fromUid || toUid === fromUid) {
return callback(new Error('[[error:chat-disabled]]')); return callback(null, false);
} else if (toUid === fromUid) {
return callback(new Error('[[error:cant-chat-with-yourself]]'));
} else if (!fromUid) {
return callback(new Error('[[error:not-logged-in]]'));
} }
async.waterfall([ async.waterfall([
@ -388,17 +384,17 @@ var db = require('./database'),
}, },
function (exists, next) { function (exists, next) {
if (!exists) { if (!exists) {
return next(new Error('[[error:no-user]]')); return callback(null, false);
} }
user.getUserFields(fromUid, ['banned', 'email:confirmed'], next); user.getUserFields(fromUid, ['banned', 'email:confirmed'], next);
}, },
function (userData, next) { function (userData, next) {
if (parseInt(userData.banned, 10) === 1) { if (parseInt(userData.banned, 10) === 1) {
return next(new Error('[[error:user-banned]]')); return callback(null, false);
} }
if (parseInt(meta.config.requireEmailConfirmation, 10) === 1 && parseInt(userData['email:confirmed'], 10) !== 1) { if (parseInt(meta.config.requireEmailConfirmation, 10) === 1 && parseInt(userData['email:confirmed'], 10) !== 1) {
return next(new Error('[[error:email-not-confirmed-chat]]')); return callback(null, false);
} }
user.getSettings(toUid, next); user.getSettings(toUid, next);

@ -7,7 +7,7 @@ var admin = {},
db = require('../database'), db = require('../database'),
translator = require('../../public/src/modules/translator'); translator = require('../../public/src/modules/translator');
var navigationCache = null; admin.cache = null;
admin.save = function(data, callback) { admin.save = function(data, callback) {
var order = Object.keys(data), var order = Object.keys(data),
@ -24,7 +24,7 @@ admin.save = function(data, callback) {
return JSON.stringify(data); return JSON.stringify(data);
}); });
navigationCache = null; admin.cache = null;
async.waterfall([ async.waterfall([
function(next) { function(next) {
db.delete('navigation:enabled', next); db.delete('navigation:enabled', next);
@ -43,19 +43,16 @@ admin.getAdmin = function(callback) {
}; };
admin.get = function(callback) { admin.get = function(callback) {
if (navigationCache) {
return callback(null, navigationCache);
}
db.getSortedSetRange('navigation:enabled', 0, -1, function(err, data) { db.getSortedSetRange('navigation:enabled', 0, -1, function(err, data) {
if (err) { if (err) {
return callback(err); return callback(err);
} }
navigationCache = data.map(function(item, idx) {
data = data.map(function(item, idx) {
return JSON.parse(item)[idx]; return JSON.parse(item)[idx];
}); });
callback(null, navigationCache); callback(null, data);
}); });
}; };

@ -1,12 +1,15 @@
"use strict"; "use strict";
var navigation = {}, var navigation = {};
admin = require('./admin'), var admin = require('./admin');
translator = require('../../public/src/modules/translator'); var translator = require('../../public/src/modules/translator');
navigation.get = function(callback) { navigation.get = function(callback) {
if (admin.cache) {
return callback(null, admin.cache);
}
admin.get(function(err, data) { admin.get(function(err, data) {
if (err) { if (err) {
return callback(err); return callback(err);
@ -23,6 +26,8 @@ navigation.get = function(callback) {
return item; return item;
}); });
admin.cache = data;
callback(null, data); callback(null, data);
}); });
}; };

@ -43,7 +43,7 @@ module.exports = function(Posts) {
userTitle: group.userTitle userTitle: group.userTitle
}; };
if (group.name === results.userSettings[i].groupTitle && group.userTitleEnabled) { if (results.userSettings[i] && group.name === results.userSettings[i].groupTitle && group.userTitleEnabled) {
userData.selectedGroup = userData.groups[index]; userData.selectedGroup = userData.groups[index];
} }
}); });

@ -101,7 +101,12 @@ module.exports = function(privileges) {
}); });
groupNames = groups.getEphemeralGroups().concat(groupNames); groupNames = groups.getEphemeralGroups().concat(groupNames);
groupNames.splice(0, 0, groupNames.splice(groupNames.indexOf('registered-users'), 1)[0]); var registeredUsersIndex = groupNames.indexOf('registered-users');
if (registeredUsersIndex !== -1) {
groupNames.splice(0, 0, groupNames.splice(registeredUsersIndex, 1)[0]);
} else {
groupNames = ['registered-users'].concat(groupNames);
}
var adminIndex = groupNames.indexOf('administrators'); var adminIndex = groupNames.indexOf('administrators');
if (adminIndex !== -1) { if (adminIndex !== -1) {

@ -84,6 +84,9 @@ module.exports = function(app, middleware) {
pluginRouter.render = function() { pluginRouter.render = function() {
app.render.apply(app, arguments); app.render.apply(app, arguments);
}; };
controllers.render = function() {
app.render.apply(app, arguments);
};
// Set-up for hotswapping (when NodeBB reloads) // Set-up for hotswapping (when NodeBB reloads)
pluginRouter.hotswapId = 'plugins'; pluginRouter.hotswapId = 'plugins';
@ -175,7 +178,7 @@ function handle404(app, middleware) {
} }
function handleErrors(app, middleware) { function handleErrors(app, middleware) {
app.use(function(err, req, res) { app.use(function(err, req, res, next) {
if (err.code === 'EBADCSRFTOKEN') { if (err.code === 'EBADCSRFTOKEN') {
winston.error(req.path + '\n', err.message); winston.error(req.path + '\n', err.message);
return res.sendStatus(403); return res.sendStatus(403);
@ -190,7 +193,7 @@ function handleErrors(app, middleware) {
res.status(err.status || 500); res.status(err.status || 500);
if (res.locals.isAPI) { if (res.locals.isAPI) {
return res.json({path: req.path, error: err.message}); res.json({path: req.path, error: err.message});
} else { } else {
middleware.buildHeader(req, res, function() { middleware.buildHeader(req, res, function() {
res.render('500', {path: req.path, error: err.message}); res.render('500', {path: req.path, error: err.message});

@ -31,7 +31,10 @@ module.exports = function(app, middleware, controllers) {
app.get('/admin.css', middleware.addExpiresHeaders, sendACPStylesheet); app.get('/admin.css', middleware.addExpiresHeaders, sendACPStylesheet);
app.get('/nodebb.min.js', middleware.addExpiresHeaders, sendMinifiedJS); app.get('/nodebb.min.js', middleware.addExpiresHeaders, sendMinifiedJS);
// app.get('/nodebb.min.js.map', middleware.addExpiresHeaders, sendJSSourceMap); // app.get('/nodebb.min.js.map', middleware.addExpiresHeaders, sendJSSourceMap);
app.get('/sitemap.xml', controllers.sitemap); app.get('/sitemap.xml', controllers.sitemap.render);
app.get('/sitemap/pages.xml', controllers.sitemap.getPages);
app.get('/sitemap/categories.xml', controllers.sitemap.getCategories);
app.get(/\/sitemap\/topics\.(\d+)\.xml/, controllers.sitemap.getTopicPage);
app.get('/robots.txt', controllers.robots); app.get('/robots.txt', controllers.robots);
app.get('/manifest.json', controllers.manifest); app.get('/manifest.json', controllers.manifest);
app.get('/css/previews/:theme', controllers.admin.themes.get); app.get('/css/previews/:theme', controllers.admin.themes.get);

@ -12,30 +12,37 @@ var path = require('path'),
meta = require('./meta'), meta = require('./meta'),
utils = require('../public/src/utils'); utils = require('../public/src/utils');
var sitemap = {}; var sitemap = {
maps: {
topics: []
}
};
sitemap.render = function(callback) { sitemap.render = function(callback) {
if (sitemap.obj && sitemap.obj.cache.length) { var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
return sitemap.obj.toXML(callback); var returnData = {
} url: nconf.get('url'),
topics: []
async.parallel([ };
sitemap.getStaticUrls, var numPages;
sitemap.getDynamicUrls
], function(err, urls) { async.waterfall([
async.apply(db.getSortedSetRange, 'topics:recent', 0, -1),
function(tids, next) {
privileges.topics.filterTids('read', tids, 0, next);
}
], function(err, tids) {
if (err) { if (err) {
return callback(err); numPages = 1;
} else {
numPages = Math.ceil(tids.length / numTopics);
} }
urls = urls[0].concat(urls[1]); for(var x=1;x<=numPages;x++) {
returnData.topics.push(x);
sitemap.obj = sm.createSitemap({ }
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60, // Cached for 1 hour
urls: urls
});
sitemap.obj.toXML(callback); callback(null, returnData);
}); });
}; };
@ -52,75 +59,127 @@ sitemap.getStaticUrls = function(callback) {
url: '/users', url: '/users',
changefreq: 'daily', changefreq: 'daily',
priority: '0.4' priority: '0.4'
}, {
url: '/groups',
changefreq: 'daily',
priority: '0.4'
}]); }]);
}; };
sitemap.getDynamicUrls = function(callback) { sitemap.getPages = function(callback) {
var returnUrls = []; if (sitemap.maps.pages && sitemap.maps.pages.cache.length) {
return sitemap.maps.pages.toXML(callback);
async.parallel({ }
categoryUrls: function(next) {
var categoryUrls = [];
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
if (err) {
return next(err);
}
categoriesData.forEach(function(category) {
if (category) {
categoryUrls.push({
url: '/category/' + category.slug,
changefreq: 'weekly',
priority: '0.4'
});
}
});
next(null, categoryUrls); var urls = [{
}); url: '',
}, changefreq: 'weekly',
topicUrls: function(next) { priority: '0.6'
var topicUrls = []; }, {
url: '/recent',
async.waterfall([ changefreq: 'daily',
function(next) { priority: '0.4'
db.getSortedSetRevRange('topics:recent', 0, parseInt(meta.config.sitemapTopics, 10) || -1, next); }, {
}, url: '/users',
function(tids, next) { changefreq: 'daily',
privileges.topics.filterTids('read', tids, 0, next); priority: '0.4'
}, }, {
function(tids, next) { url: '/groups',
topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime'], next); changefreq: 'daily',
} priority: '0.4'
], function(err, topics) { }];
if (err) {
return next(err); sitemap.maps.pages = sm.createSitemap({
} hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
topics.forEach(function(topic) { urls: urls
if (topic) { });
topicUrls.push({
url: '/topic/' + topic.slug, sitemap.maps.pages.toXML(callback);
lastmodISO: utils.toISOString(topic.lastposttime), };
changefreq: 'daily',
priority: '0.6' sitemap.getCategories = function(callback) {
}); if (sitemap.maps.categories && sitemap.maps.categories.cache.length) {
} return sitemap.maps.categories.toXML(callback);
}
var categoryUrls = [];
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
if (err) {
return callback(err);
}
categoriesData.forEach(function(category) {
if (category) {
categoryUrls.push({
url: '/category/' + category.slug,
changefreq: 'weekly',
priority: '0.4'
}); });
}
});
sitemap.maps.categories = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
urls: categoryUrls
});
sitemap.maps.categories.toXML(callback);
});
};
sitemap.getTopicPage = function(page, callback) {
if (parseInt(page, 10) <= 0) {
return callback();
}
var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
var min = (parseInt(page, 10) - 1) * numTopics;
var max = min + numTopics;
if (sitemap.maps.topics[page-1] && sitemap.maps.topics[page-1].cache.length) {
return sitemap.maps.topics[page-1].toXML(callback);
}
var topicUrls = [];
next(null, topicUrls); async.waterfall([
}); function(next) {
db.getSortedSetRevRange('topics:recent', min, max, next);
},
function(tids, next) {
privileges.topics.filterTids('read', tids, 0, next);
},
function(tids, next) {
topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime'], next);
} }
}, function(err, data) { ], function(err, topics) {
if (!err) { if (err) {
returnUrls = data.categoryUrls.concat(data.topicUrls); return callback(err);
} }
callback(err, returnUrls); topics.forEach(function(topic) {
if (topic) {
topicUrls.push({
url: '/topic/' + topic.slug,
lastmodISO: utils.toISOString(topic.lastposttime),
changefreq: 'daily',
priority: '0.6'
});
}
});
sitemap.maps.topics[page-1] = sm.createSitemap({
hostname: nconf.get('url'),
cacheTime: 1000 * 60 * 60, // Cached for 1 hour
urls: topicUrls
});
sitemap.maps.topics[page-1].toXML(callback);
}); });
}; };
sitemap.clearCache = function() { sitemap.clearCache = function() {
if (sitemap.obj) { if (sitemap.obj) {
sitemap.obj.clearCache(); sitemap.obj.clearCache();

@ -63,7 +63,7 @@ SocketGroups.leave = function(socket, data, callback) {
function isOwner(next) { function isOwner(next) {
return function (socket, data, callback) { return function (socket, data, callback) {
async.parallel({ async.parallel({
isAdmin: async.apply(user.isAdmin, socket.uid), isAdmin: async.apply(user.isAdministrator, socket.uid),
isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName) isOwner: async.apply(groups.ownership.isOwner, socket.uid, data.groupName)
}, function(err, results) { }, function(err, results) {
if (err || (!isOwner && !results.isAdmin)) { if (err || (!isOwner && !results.isAdmin)) {

@ -4,6 +4,7 @@ var async = require('async');
var topics = require('../../topics'); var topics = require('../../topics');
var events = require('../../events'); var events = require('../../events');
var privileges = require('../../privileges'); var privileges = require('../../privileges');
var plugins = require('../../plugins');
var socketHelpers = require('../helpers'); var socketHelpers = require('../helpers');
module.exports = function(SocketTopics) { module.exports = function(SocketTopics) {
@ -13,28 +14,33 @@ module.exports = function(SocketTopics) {
return; return;
} }
if (!data) { if (!data) {
return callback(new Error('[[error:invalid-data]]')) return callback(new Error('[[error:invalid-data]]'));
} }
var topic;
async.parallel({ async.waterfall([
topic: function(next) { function (next) {
topics.getTopicFields(data.tid, ['deleted', 'locked', 'pinned'], next); async.parallel({
topic: function(next) {
topics.getTopicData(data.tid, next);
},
privileges: function(next) {
privileges.topics.get(data.tid, socket.uid, next);
}
}, next);
}, },
privileges: function(next) { function (results, next) {
privileges.topics.get(data.tid, socket.uid, next); topic = results.topic;
} topic.privileges = results.privileges;
}, function(err, results) { plugins.fireHook('filter:topic.thread_tools', {topic: results.topic, uid: socket.uid, tools: []}, next);
if (err) { },
return callback(err); function (data, next) {
topic.deleted = parseInt(topic.deleted, 10) === 1;
topic.locked = parseInt(topic.locked, 10) === 1;
topic.pinned = parseInt(topic.pinned, 10) === 1;
topic.thread_tools = data.tools;
next(null, topic);
} }
], callback);
results.topic.deleted = parseInt(results.topic.deleted, 10) === 1;
results.topic.locked = parseInt(results.topic.locked, 10) === 1;
results.topic.pinned = parseInt(results.topic.pinned, 10) === 1;
results.topic.privileges = results.privileges;
callback(null, results.topic);
});
}; };
SocketTopics.delete = function(socket, data, callback) { SocketTopics.delete = function(socket, data, callback) {

@ -18,29 +18,31 @@ module.exports = function(Topics) {
return callback(); return callback();
} }
plugins.fireHook('filter:tags.filter', {tags: tags, tid: tid}, function(err, data) { async.waterfall([
if (err) { function (next) {
return callback(err); plugins.fireHook('filter:tags.filter', {tags: tags, tid: tid}, next);
} },
function (data, next) {
tags = data.tags.slice(0, meta.config.maximumTagsPerTopic || 5); tags = data.tags.slice(0, meta.config.maximumTagsPerTopic || 5);
async.each(tags, function(tag, next) {
tag = Topics.cleanUpTag(tag);
if (tag.length < (meta.config.minimumTagLength || 3)) {
return next();
}
db.setAdd('topic:' + tid + ':tags', tag);
db.sortedSetAdd('tag:' + tag + ':topics', timestamp, tid, function(err) { async.each(tags, function(tag, next) {
if (!err) { tag = Topics.cleanUpTag(tag);
updateTagCount(tag); if (tag.length < (meta.config.minimumTagLength || 3)) {
return next();
} }
next(err);
}); async.parallel([
}, callback); async.apply(db.setAdd, 'topic:' + tid + ':tags', tag),
}); async.apply(db.sortedSetAdd, 'tag:' + tag + ':topics', timestamp, tid)
], function(err) {
if (err) {
return next(err);
}
updateTagCount(tag, next);
});
}, next);
}
], callback);
}; };
Topics.cleanUpTag = function(tag) { Topics.cleanUpTag = function(tag) {

@ -98,7 +98,7 @@ var async = require('async'),
} }
for(var i=0; i<notifications.length; ++i) { for(var i=0; i<notifications.length; ++i) {
if (notifications[i].image.indexOf('http') !== 0) { if (notifications[i].image && notifications[i].image.indexOf('http') !== 0) {
notifications[i].image = nconf.get('url') + notifications[i].image; notifications[i].image = nconf.get('url') + notifications[i].image;
} }
} }

@ -0,0 +1,9 @@
<script type="text/tpl" data-template="500">
<div class="alert alert-danger">
<strong>[[global:500.title]]</strong>
<p>[[global:500.message]]</p>
<p>{path}</p>
<!-- IF error --><p>{error}</p><!-- ENDIF error -->
</div>
</script>

@ -1,9 +1,6 @@
<script type="text/tpl" data-template="500">
<div class="alert alert-danger"> <div class="alert alert-danger">
<strong>[[global:500.title]]</strong> <strong>[[global:500.title]]</strong>
<p>[[global:500.message]]</p> <p>[[global:500.message]]</p>
<p>{path}</p> <p>{path}</p>
<!-- IF error --><p>{error}</p><!-- ENDIF error --> <!-- IF error --><p>{error}</p><!-- ENDIF error -->
</div> </div>
</script>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>{url}/sitemap/pages.xml</loc>
</sitemap>
<sitemap>
<loc>{url}/sitemap/categories.xml</loc>
</sitemap>
<!-- BEGIN topics -->
<sitemap>
<loc>{url}/sitemap/topics.@value.xml</loc>
</sitemap>
<!-- END topics -->
</sitemapindex>
Loading…
Cancel
Save