mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-29 18:16:17 +01:00
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 commit7ee584b632Author: 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 commit488f147befAuthor: barisusakli <barisusakli@gmail.com> Date: Mon Oct 26 22:39:19 2015 -0400 closes #3781 commit5e1bd58a02Author: barisusakli <barisusakli@gmail.com> Date: Mon Oct 26 22:28:30 2015 -0400 closes #3782 commit57d3980267Author: barisusakli <barisusakli@gmail.com> Date: Mon Oct 26 22:16:08 2015 -0400 closes #3790 commit555c5b82daAuthor: barisusakli <barisusakli@gmail.com> Date: Mon Oct 26 21:19:20 2015 -0400 check user settings commit5454862c1cAuthor: barisusakli <barisusakli@gmail.com> Date: Mon Oct 26 20:26:02 2015 -0400 wait for all callbacks when creating tags commit051c5077ebMerge:839fd93e0e04efAuthor: 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… commite0e04ef892Author: 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 commit839fd935adAuthor: barisusakli <barisusakli@gmail.com> Date: Sun Oct 25 21:54:35 2015 -0400 add back thread tools filter commit37060bf1a3Merge:5820a19bf918bdAuthor: 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 commit5820a193f6Author: barisusakli <barisusakli@gmail.com> Date: Sun Oct 25 17:04:46 2015 -0400 closes #3789 commit0d88d52557Author: barisusakli <barisusakli@gmail.com> Date: Sun Oct 25 17:03:33 2015 -0400 up theme commit9bc43ba5e1Author: barisusakli <barisusakli@gmail.com> Date: Sun Oct 25 16:57:42 2015 -0400 closes #3788 commitaafd4b6984Author: barisusakli <barisusakli@gmail.com> Date: Sun Oct 25 15:56:17 2015 -0400 closes #3786 commitbf918bd016Author: 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.
This commit is contained in:
6
nodebb
6
nodebb
@@ -144,8 +144,10 @@ switch(process.argv[2]) {
|
||||
if (err) {
|
||||
process.stdout.write('\nError'.red + ': ' + err.message + '\n');
|
||||
} else {
|
||||
var message = 'NodeBB Upgrade Complete!',
|
||||
spaces = new Array(Math.floor(process.stdout.columns / 2) - (message.length / 2) + 1).join(' ');
|
||||
var message = 'NodeBB Upgrade Complete!';
|
||||
// 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('\n' + spaces + message.green.bold + '\n\n'.reset);
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
"nodebb-plugin-spam-be-gone": "0.4.2",
|
||||
"nodebb-rewards-essentials": "0.0.5",
|
||||
"nodebb-theme-lavender": "2.0.10",
|
||||
"nodebb-theme-persona": "3.0.61",
|
||||
"nodebb-theme-vanilla": "4.0.28",
|
||||
"nodebb-theme-persona": "3.0.62",
|
||||
"nodebb-theme-vanilla": "4.0.29",
|
||||
"nodebb-widget-essentials": "2.0.3",
|
||||
"npm": "^2.1.4",
|
||||
"passport": "^0.3.0",
|
||||
@@ -61,7 +61,7 @@
|
||||
"rss": "^1.0.0",
|
||||
"semver": "^5.0.1",
|
||||
"serve-favicon": "^2.1.5",
|
||||
"sitemap": "^1.0.0",
|
||||
"sitemap": "^1.4.0",
|
||||
"socket.io": "^1.2.1",
|
||||
"socket.io-client": "^1.2.1",
|
||||
"socket.io-redis": "^0.1.3",
|
||||
|
||||
@@ -10,7 +10,7 @@ define('forum/topic/fork', ['components'], function(components) {
|
||||
pids = [];
|
||||
|
||||
Fork.init = function() {
|
||||
components.get('topic/fork').on('click', onForkThreadClicked);
|
||||
$('.topic').on('click', '[component="topic/fork"]', onForkThreadClicked);
|
||||
};
|
||||
|
||||
function disableClicks() {
|
||||
|
||||
@@ -11,14 +11,21 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
|
||||
notifList = components.get('notifications/list'),
|
||||
notifIcon = components.get('notifications/icon');
|
||||
|
||||
notifTrigger.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
if (notifContainer.hasClass('open')) {
|
||||
return;
|
||||
}
|
||||
notifTrigger
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
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() {
|
||||
var unread = $(this).hasClass('unread');
|
||||
@@ -33,14 +40,7 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
|
||||
});
|
||||
});
|
||||
|
||||
notifContainer.on('click', '.mark-all-read', function() {
|
||||
socket.emit('notifications.markAllRead', function(err) {
|
||||
if (err) {
|
||||
app.alertError(err.message);
|
||||
}
|
||||
Notifications.updateNotifCount(0);
|
||||
});
|
||||
});
|
||||
notifContainer.on('click', '.mark-all-read', Notifications.markAllRead);
|
||||
|
||||
notifList.on('click', '.mark-read', function(e) {
|
||||
var liEl = $(this).parent(),
|
||||
@@ -125,5 +125,14 @@ define('notifications', ['sounds', 'translator', 'components'], function(sound,
|
||||
Tinycon.setBubble(count);
|
||||
};
|
||||
|
||||
Notifications.markAllRead = function() {
|
||||
socket.emit('notifications.markAllRead', function(err) {
|
||||
if (err) {
|
||||
app.alertError(err.message);
|
||||
}
|
||||
Notifications.updateNotifCount(0);
|
||||
});
|
||||
};
|
||||
|
||||
return Notifications;
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ var async = require('async'),
|
||||
posts = require('../posts'),
|
||||
topics = require('../topics'),
|
||||
plugins = require('../plugins'),
|
||||
sitemap = require('../sitemap'),
|
||||
categories = require('../categories'),
|
||||
privileges = require('../privileges'),
|
||||
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();
|
||||
}
|
||||
|
||||
var sitemap = require('../sitemap.js');
|
||||
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) {
|
||||
return next();
|
||||
}
|
||||
|
||||
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.send(xml);
|
||||
});
|
||||
|
||||
@@ -374,12 +374,8 @@ var db = require('./database'),
|
||||
};
|
||||
|
||||
Messaging.canMessage = function(fromUid, toUid, callback) {
|
||||
if (parseInt(meta.config.disableChat) === 1) {
|
||||
return callback(new Error('[[error:chat-disabled]]'));
|
||||
} else if (toUid === fromUid) {
|
||||
return callback(new Error('[[error:cant-chat-with-yourself]]'));
|
||||
} else if (!fromUid) {
|
||||
return callback(new Error('[[error:not-logged-in]]'));
|
||||
if (parseInt(meta.config.disableChat) === 1 || !fromUid || toUid === fromUid) {
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
@@ -388,17 +384,17 @@ var db = require('./database'),
|
||||
},
|
||||
function (exists, next) {
|
||||
if (!exists) {
|
||||
return next(new Error('[[error:no-user]]'));
|
||||
return callback(null, false);
|
||||
}
|
||||
user.getUserFields(fromUid, ['banned', 'email:confirmed'], next);
|
||||
},
|
||||
function (userData, next) {
|
||||
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) {
|
||||
return next(new Error('[[error:email-not-confirmed-chat]]'));
|
||||
return callback(null, false);
|
||||
}
|
||||
|
||||
user.getSettings(toUid, next);
|
||||
|
||||
@@ -7,7 +7,7 @@ var admin = {},
|
||||
db = require('../database'),
|
||||
translator = require('../../public/src/modules/translator');
|
||||
|
||||
var navigationCache = null;
|
||||
admin.cache = null;
|
||||
|
||||
admin.save = function(data, callback) {
|
||||
var order = Object.keys(data),
|
||||
@@ -24,7 +24,7 @@ admin.save = function(data, callback) {
|
||||
return JSON.stringify(data);
|
||||
});
|
||||
|
||||
navigationCache = null;
|
||||
admin.cache = null;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
db.delete('navigation:enabled', next);
|
||||
@@ -43,19 +43,16 @@ admin.getAdmin = function(callback) {
|
||||
};
|
||||
|
||||
admin.get = function(callback) {
|
||||
if (navigationCache) {
|
||||
return callback(null, navigationCache);
|
||||
}
|
||||
|
||||
db.getSortedSetRange('navigation:enabled', 0, -1, function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
navigationCache = data.map(function(item, idx) {
|
||||
|
||||
data = data.map(function(item, idx) {
|
||||
return JSON.parse(item)[idx];
|
||||
});
|
||||
|
||||
callback(null, navigationCache);
|
||||
callback(null, data);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
|
||||
var navigation = {},
|
||||
admin = require('./admin'),
|
||||
translator = require('../../public/src/modules/translator');
|
||||
|
||||
var navigation = {};
|
||||
var admin = require('./admin');
|
||||
var translator = require('../../public/src/modules/translator');
|
||||
|
||||
navigation.get = function(callback) {
|
||||
if (admin.cache) {
|
||||
return callback(null, admin.cache);
|
||||
}
|
||||
|
||||
admin.get(function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
@@ -23,6 +26,8 @@ navigation.get = function(callback) {
|
||||
return item;
|
||||
});
|
||||
|
||||
admin.cache = data;
|
||||
|
||||
callback(null, data);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ module.exports = function(Posts) {
|
||||
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];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,7 +101,12 @@ module.exports = function(privileges) {
|
||||
});
|
||||
|
||||
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');
|
||||
if (adminIndex !== -1) {
|
||||
|
||||
@@ -84,6 +84,9 @@ module.exports = function(app, middleware) {
|
||||
pluginRouter.render = function() {
|
||||
app.render.apply(app, arguments);
|
||||
};
|
||||
controllers.render = function() {
|
||||
app.render.apply(app, arguments);
|
||||
};
|
||||
|
||||
// Set-up for hotswapping (when NodeBB reloads)
|
||||
pluginRouter.hotswapId = 'plugins';
|
||||
@@ -175,7 +178,7 @@ function handle404(app, middleware) {
|
||||
}
|
||||
|
||||
function handleErrors(app, middleware) {
|
||||
app.use(function(err, req, res) {
|
||||
app.use(function(err, req, res, next) {
|
||||
if (err.code === 'EBADCSRFTOKEN') {
|
||||
winston.error(req.path + '\n', err.message);
|
||||
return res.sendStatus(403);
|
||||
@@ -190,7 +193,7 @@ function handleErrors(app, middleware) {
|
||||
res.status(err.status || 500);
|
||||
|
||||
if (res.locals.isAPI) {
|
||||
return res.json({path: req.path, error: err.message});
|
||||
res.json({path: req.path, error: err.message});
|
||||
} else {
|
||||
middleware.buildHeader(req, res, function() {
|
||||
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('/nodebb.min.js', middleware.addExpiresHeaders, sendMinifiedJS);
|
||||
// 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('/manifest.json', controllers.manifest);
|
||||
app.get('/css/previews/:theme', controllers.admin.themes.get);
|
||||
|
||||
205
src/sitemap.js
205
src/sitemap.js
@@ -12,30 +12,37 @@ var path = require('path'),
|
||||
meta = require('./meta'),
|
||||
utils = require('../public/src/utils');
|
||||
|
||||
var sitemap = {};
|
||||
var sitemap = {
|
||||
maps: {
|
||||
topics: []
|
||||
}
|
||||
};
|
||||
|
||||
sitemap.render = function(callback) {
|
||||
if (sitemap.obj && sitemap.obj.cache.length) {
|
||||
return sitemap.obj.toXML(callback);
|
||||
}
|
||||
var numTopics = parseInt(meta.config.sitemapTopics, 10) || 500;
|
||||
var returnData = {
|
||||
url: nconf.get('url'),
|
||||
topics: []
|
||||
};
|
||||
var numPages;
|
||||
|
||||
async.parallel([
|
||||
sitemap.getStaticUrls,
|
||||
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) {
|
||||
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,74 +59,126 @@ sitemap.getStaticUrls = function(callback) {
|
||||
url: '/users',
|
||||
changefreq: 'daily',
|
||||
priority: '0.4'
|
||||
}, {
|
||||
url: '/groups',
|
||||
changefreq: 'daily',
|
||||
priority: '0.4'
|
||||
}]);
|
||||
};
|
||||
|
||||
sitemap.getDynamicUrls = function(callback) {
|
||||
var returnUrls = [];
|
||||
sitemap.getPages = function(callback) {
|
||||
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);
|
||||
}
|
||||
var urls = [{
|
||||
url: '',
|
||||
changefreq: 'weekly',
|
||||
priority: '0.6'
|
||||
}, {
|
||||
url: '/recent',
|
||||
changefreq: 'daily',
|
||||
priority: '0.4'
|
||||
}, {
|
||||
url: '/users',
|
||||
changefreq: 'daily',
|
||||
priority: '0.4'
|
||||
}, {
|
||||
url: '/groups',
|
||||
changefreq: 'daily',
|
||||
priority: '0.4'
|
||||
}];
|
||||
|
||||
sitemap.maps.pages = sm.createSitemap({
|
||||
hostname: nconf.get('url'),
|
||||
cacheTime: 1000 * 60 * 60 * 24, // Cached for 24 hours
|
||||
urls: urls
|
||||
});
|
||||
|
||||
categoriesData.forEach(function(category) {
|
||||
if (category) {
|
||||
categoryUrls.push({
|
||||
url: '/category/' + category.slug,
|
||||
changefreq: 'weekly',
|
||||
priority: '0.4'
|
||||
});
|
||||
}
|
||||
});
|
||||
sitemap.maps.pages.toXML(callback);
|
||||
};
|
||||
|
||||
next(null, categoryUrls);
|
||||
});
|
||||
},
|
||||
topicUrls: function(next) {
|
||||
var topicUrls = [];
|
||||
sitemap.getCategories = function(callback) {
|
||||
if (sitemap.maps.categories && sitemap.maps.categories.cache.length) {
|
||||
return sitemap.maps.categories.toXML(callback);
|
||||
}
|
||||
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
db.getSortedSetRevRange('topics:recent', 0, parseInt(meta.config.sitemapTopics, 10) || -1, next);
|
||||
},
|
||||
function(tids, next) {
|
||||
privileges.topics.filterTids('read', tids, 0, next);
|
||||
},
|
||||
function(tids, next) {
|
||||
topics.getTopicsFields(tids, ['tid', 'title', 'slug', 'lastposttime'], next);
|
||||
}
|
||||
], function(err, topics) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
topics.forEach(function(topic) {
|
||||
if (topic) {
|
||||
topicUrls.push({
|
||||
url: '/topic/' + topic.slug,
|
||||
lastmodISO: utils.toISOString(topic.lastposttime),
|
||||
changefreq: 'daily',
|
||||
priority: '0.6'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
next(null, topicUrls);
|
||||
});
|
||||
}
|
||||
}, function(err, data) {
|
||||
if (!err) {
|
||||
returnUrls = data.categoryUrls.concat(data.topicUrls);
|
||||
var categoryUrls = [];
|
||||
categories.getCategoriesByPrivilege('categories:cid', 0, 'find', function(err, categoriesData) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
callback(err, returnUrls);
|
||||
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 = [];
|
||||
|
||||
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, topics) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
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() {
|
||||
if (sitemap.obj) {
|
||||
|
||||
@@ -63,7 +63,7 @@ SocketGroups.leave = function(socket, data, callback) {
|
||||
function isOwner(next) {
|
||||
return function (socket, data, callback) {
|
||||
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)
|
||||
}, function(err, results) {
|
||||
if (err || (!isOwner && !results.isAdmin)) {
|
||||
|
||||
@@ -4,6 +4,7 @@ var async = require('async');
|
||||
var topics = require('../../topics');
|
||||
var events = require('../../events');
|
||||
var privileges = require('../../privileges');
|
||||
var plugins = require('../../plugins');
|
||||
var socketHelpers = require('../helpers');
|
||||
|
||||
module.exports = function(SocketTopics) {
|
||||
@@ -13,28 +14,33 @@ module.exports = function(SocketTopics) {
|
||||
return;
|
||||
}
|
||||
if (!data) {
|
||||
return callback(new Error('[[error:invalid-data]]'))
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
topic: function(next) {
|
||||
topics.getTopicFields(data.tid, ['deleted', 'locked', 'pinned'], next);
|
||||
var topic;
|
||||
async.waterfall([
|
||||
function (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) {
|
||||
privileges.topics.get(data.tid, socket.uid, next);
|
||||
function (results, next) {
|
||||
topic = results.topic;
|
||||
topic.privileges = results.privileges;
|
||||
plugins.fireHook('filter:topic.thread_tools', {topic: results.topic, uid: socket.uid, tools: []}, next);
|
||||
},
|
||||
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);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
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);
|
||||
});
|
||||
], callback);
|
||||
};
|
||||
|
||||
SocketTopics.delete = function(socket, data, callback) {
|
||||
|
||||
@@ -18,29 +18,31 @@ module.exports = function(Topics) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
plugins.fireHook('filter:tags.filter', {tags: tags, tid: tid}, function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
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) {
|
||||
if (!err) {
|
||||
updateTagCount(tag);
|
||||
async.each(tags, function(tag, next) {
|
||||
tag = Topics.cleanUpTag(tag);
|
||||
if (tag.length < (meta.config.minimumTagLength || 3)) {
|
||||
return next();
|
||||
}
|
||||
next(err);
|
||||
});
|
||||
}, callback);
|
||||
});
|
||||
|
||||
async.parallel([
|
||||
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) {
|
||||
|
||||
@@ -98,7 +98,7 @@ var async = require('async'),
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
9
src/views/500-embed.tpl
Normal file
9
src/views/500-embed.tpl
Normal file
@@ -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">
|
||||
<strong>[[global:500.title]]</strong>
|
||||
<p>[[global:500.message]]</p>
|
||||
<p>{path}</p>
|
||||
<!-- IF error --><p>{error}</p><!-- ENDIF error -->
|
||||
|
||||
</div>
|
||||
</script>
|
||||
14
src/views/sitemap.tpl
Normal file
14
src/views/sitemap.tpl
Normal file
@@ -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>
|
||||
Reference in New Issue
Block a user