mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-01-06 23:52:58 +01:00
Merge branch 'master' of https://github.com/designcreateplay/NodeBB
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
}
|
||||
|
||||
winston.info('test_database flushed');
|
||||
/*
|
||||
|
||||
meta.configs.init(function () {
|
||||
nconf.set('url', nconf.get('base_url') + (nconf.get('use_port') ? ':' + nconf.get('port') : '') + nconf.get('relative_path'));
|
||||
nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-vanilla/templates'));
|
||||
@@ -90,8 +90,7 @@
|
||||
sockets.init(webserver.server);
|
||||
|
||||
done();
|
||||
});*/
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"scripts": {
|
||||
"start": "./nodebb start",
|
||||
"stop": "./nodebb stop",
|
||||
"test": "mocha ./tests/database.js -t 1000"
|
||||
"test": "mocha ./tests -t 10000"
|
||||
},
|
||||
"dependencies": {
|
||||
"express": "3.2.0",
|
||||
|
||||
@@ -69,6 +69,6 @@
|
||||
"invisible": "Invisible",
|
||||
"offline": "Offline",
|
||||
|
||||
"privacy": "Privacy",
|
||||
"email": "Email",
|
||||
"language": "Language"
|
||||
}
|
||||
|
||||
@@ -9,5 +9,13 @@
|
||||
"continue_to": "Continue to",
|
||||
"return_to": "Return to ",
|
||||
"new_notification": "New Notification",
|
||||
"you_have_unread_notifications": "You have unread notifications."
|
||||
"you_have_unread_notifications": "You have unread notifications.",
|
||||
|
||||
"user_made_post": "<strong>%1</strong> made a new post",
|
||||
"new_message_from": "New message from <strong>%1</strong>",
|
||||
"upvoted_your_post": "<strong>%1</strong> has upvoted your post.",
|
||||
"favourited_your_post": "<strong>%1</strong> has favourited your post.",
|
||||
"user_flagged_post": "<strong>%1</strong> flagged a post.",
|
||||
"user_posted_to" : "<strong>%1</strong> has posted a reply to: <strong>%2</strong>"
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,12 @@
|
||||
|
||||
"settings": "Settings",
|
||||
"show_email": "Show My Email",
|
||||
"digest_label": "Subscribe to Digest",
|
||||
"digest_description": "Subscribe to email updates for this forum (new notifications and topics) according to a set schedule",
|
||||
"digest_off": "Off",
|
||||
"digest_daily": "Daily",
|
||||
"digest_weekly": "Weekly",
|
||||
"digest_monthly": "Monthly",
|
||||
|
||||
"has_no_follower": "This user doesn't have any followers :(",
|
||||
"follows_no_one": "This user isn't following anyone :(",
|
||||
|
||||
@@ -16,11 +16,11 @@ define(['forum/accountheader'], function(header) {
|
||||
}
|
||||
|
||||
switch (input.attr('type')) {
|
||||
case 'text' :
|
||||
case 'textarea' :
|
||||
case 'text':
|
||||
case 'textarea':
|
||||
settings[setting] = input.val();
|
||||
break;
|
||||
case 'checkbox' :
|
||||
case 'checkbox':
|
||||
settings[setting] = input.is(':checked') ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
"use strict";
|
||||
/* global define, app, socket */
|
||||
|
||||
define(function() {
|
||||
var Plugins = {
|
||||
init: function() {
|
||||
@@ -19,10 +22,13 @@ define(function() {
|
||||
app.alert({
|
||||
alert_id: 'plugin_toggled',
|
||||
title: 'Plugin ' + (status.active ? 'Enabled' : 'Disabled'),
|
||||
message: 'Restarting your NodeBB <i class="fa fa-refresh fa-spin"></i>',
|
||||
type: 'warning',
|
||||
timeout: 5000
|
||||
})
|
||||
message: 'Please restart your NodeBB to fully ' + (status.active ? 'activate' : 'deactivate') + ' this plugin',
|
||||
type: 'info',
|
||||
timeout: 5000,
|
||||
clickfn: function() {
|
||||
socket.emit('admin.restart');
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
pluginsList.append('<li><p><i>No plugins found.</i></p></li>');
|
||||
|
||||
@@ -39,10 +39,13 @@ define(['forum/admin/settings'], function(Settings) {
|
||||
|
||||
app.alert({
|
||||
alert_id: 'admin:theme',
|
||||
type: 'success',
|
||||
type: 'info',
|
||||
title: 'Theme Changed',
|
||||
message: 'Restarting your NodeBB <i class="fa fa-refresh fa-spin"></i>',
|
||||
timeout: 3500
|
||||
message: 'Please restart your NodeBB to fully activate this theme',
|
||||
timeout: 5000,
|
||||
clickfn: function() {
|
||||
socket.emit('admin.restart');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -251,7 +254,7 @@ define(['forum/admin/settings'], function(Settings) {
|
||||
timeout: 2500
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,11 +225,13 @@ define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer
|
||||
});
|
||||
}
|
||||
|
||||
Category.onTopicsLoaded = function(topics, callback) {
|
||||
if(!topics || !topics.length) {
|
||||
Category.onTopicsLoaded = function(data, callback) {
|
||||
if(!data || !data.topics.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var topics = data.topics;
|
||||
|
||||
function removeAlreadyAddedTopics() {
|
||||
topics = topics.filter(function(topic) {
|
||||
return $('#topics-container li[data-tid="' + topic.tid +'"]').length === 0;
|
||||
@@ -261,7 +263,7 @@ define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer
|
||||
findInsertionPoint();
|
||||
|
||||
ajaxify.loadTemplate('category', function(categoryTemplate) {
|
||||
var html = templates.parse(templates.getBlock(categoryTemplate, 'topics'), {topics: topics});
|
||||
var html = templates.parse(templates.getBlock(categoryTemplate, 'topics'), data);
|
||||
|
||||
translator.translate(html, function(translatedHTML) {
|
||||
var container = $('#topics-container'),
|
||||
@@ -309,6 +311,7 @@ define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer
|
||||
cid: cid,
|
||||
after: after
|
||||
}, function (err, data) {
|
||||
console.log(data);
|
||||
loadingMoreTopics = false;
|
||||
|
||||
if(err) {
|
||||
@@ -316,7 +319,7 @@ define(['composer', 'forum/pagination', 'share', 'navigator'], function(composer
|
||||
}
|
||||
|
||||
if (data && data.topics.length) {
|
||||
Category.onTopicsLoaded(data.topics, callback);
|
||||
Category.onTopicsLoaded(data, callback);
|
||||
$('#topics-container').attr('data-nextstart', data.nextStart);
|
||||
} else {
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
/* globals define, socket, translator, utils, config, app, ajaxify, Tinycon*/
|
||||
|
||||
|
||||
define(['sounds'], function(sound) {
|
||||
var Notifications = {};
|
||||
|
||||
@@ -13,50 +18,44 @@ define(['sounds'], function(sound) {
|
||||
|
||||
socket.emit('notifications.get', null, function(err, data) {
|
||||
|
||||
var numRead = data.read.length,
|
||||
numUnread = data.unread.length,
|
||||
x;
|
||||
function createNotification(notification, callback) {
|
||||
if (notification.image) {
|
||||
image = '<img class="image" src="' + notification.image + '" />';
|
||||
} else {
|
||||
image = '';
|
||||
}
|
||||
|
||||
var html = '';
|
||||
return '<li class="' + (notification.readClass || '') + '"><a href="' + notification.path + '">' + image + '<span class="pull-right relTime">' + utils.relativeTime(notification.datetime, true) + '</span><span class="text">' + notification.text + '</span></a></li>';
|
||||
}
|
||||
|
||||
var x, html = '';
|
||||
|
||||
if (!err && (data.read.length + data.unread.length) > 0) {
|
||||
var image = '';
|
||||
for (x = 0; x < numUnread; x++) {
|
||||
if (data.unread[x].image) {
|
||||
image = '<img class="image" src="' + data.unread[x].image + '" />';
|
||||
} else {
|
||||
image = '';
|
||||
}
|
||||
html += '<li class="' + (data.unread[x].readClass || '') + '"><a href="' + data.unread[x].path + '">' + image + '<span class="pull-right relTime">' + utils.relativeTime(data.unread[x].datetime, true) + '</span><span class="text">' + data.unread[x].text + '</span></a></li>';
|
||||
for (x = 0; x < data.unread.length; x++) {
|
||||
html += createNotification(data.unread[x]);
|
||||
}
|
||||
|
||||
for (x = 0; x < numRead; x++) {
|
||||
if (data.read[x].image) {
|
||||
image = '<img src="' + data.read[x].image + '" />';
|
||||
} else {
|
||||
image = '';
|
||||
}
|
||||
html += '<li class="' + data.read[x].readClass + '"><a href="' + data.read[x].path + '">' + image + '<span class="pull-right relTime">' + utils.relativeTime(data.read[x].datetime, true) + '</span><span class="text">' + data.read[x].text + '</span></a></li>';
|
||||
for (x = 0; x < data.read.length; x++) {
|
||||
html += createNotification(data.read[x]);
|
||||
}
|
||||
addSeeAllLink(replaceHtml);
|
||||
|
||||
addSeeAllLink();
|
||||
|
||||
} else {
|
||||
translator.translate('<li class="no-notifs"><a>[[notifications:no_notifs]]</a></li>', function(translated) {
|
||||
html += translated;
|
||||
addSeeAllLink(replaceHtml);
|
||||
});
|
||||
html += '<li class="no-notifs"><a>[[notifications:no_notifs]]</a></li>';
|
||||
addSeeAllLink();
|
||||
}
|
||||
|
||||
function addSeeAllLink(callback) {
|
||||
translator.translate('<li class="pagelink"><a href="' + RELATIVE_PATH + '/notifications">[[notifications:see_all]]</a></li>', function(translated) {
|
||||
html += translated;
|
||||
callback();
|
||||
});
|
||||
function addSeeAllLink() {
|
||||
html += '<li class="pagelink"><a href="' + config.relative_path + '/notifications">[[notifications:see_all]]</a></li>';
|
||||
}
|
||||
|
||||
function replaceHtml() {
|
||||
notifList.html(html);
|
||||
}
|
||||
|
||||
translator.translate(html, function(translated) {
|
||||
notifList.html(translated);
|
||||
});
|
||||
|
||||
|
||||
updateNotifCount(data.unread.length);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
var Groups = require('./groups'),
|
||||
User = require('./user'),
|
||||
categories = require('./categories'),
|
||||
|
||||
async = require('async'),
|
||||
db = require('./database');
|
||||
@@ -36,6 +37,9 @@ CategoryTools.exists = function(cid, callback) {
|
||||
|
||||
CategoryTools.privileges = function(cid, uid, callback) {
|
||||
async.parallel({
|
||||
"disabled": function(next) {
|
||||
categories.getCategoryField(cid, 'disabled', next);
|
||||
},
|
||||
"+r": function(next) {
|
||||
internals.isMember('cid:' + cid + ':privileges:+r', uid, next);
|
||||
},
|
||||
@@ -62,6 +66,7 @@ CategoryTools.privileges = function(cid, uid, callback) {
|
||||
"g+w": privileges['g+w'],
|
||||
read: (
|
||||
(
|
||||
parseInt(privileges.disabled, 10) !== 1 &&
|
||||
(privileges['+r'] || privileges['+r'] === null) &&
|
||||
(privileges['g+r'] || privileges['g+r'] === null)
|
||||
) ||
|
||||
@@ -70,6 +75,7 @@ CategoryTools.privileges = function(cid, uid, callback) {
|
||||
),
|
||||
write: (
|
||||
(
|
||||
parseInt(privileges.disabled, 10) !== 1 &&
|
||||
(privileges['+w'] || privileges['+w'] === null) &&
|
||||
(privileges['g+w'] || privileges['g+w'] === null)
|
||||
) ||
|
||||
|
||||
@@ -348,9 +348,15 @@ accountsController.accountSettings = function(req, res, next) {
|
||||
return userNotFound();
|
||||
}
|
||||
|
||||
results.user.yourid = req.user.uid;
|
||||
results.user.theirid = uid;
|
||||
results.user.settings = settings;
|
||||
results = {
|
||||
username: results.user.username,
|
||||
userslug: results.user.userslug,
|
||||
uid: uid,
|
||||
yourid: req.user.uid,
|
||||
theirid: uid,
|
||||
settings: settings,
|
||||
languages: results.languages
|
||||
};
|
||||
|
||||
res.render('accountsettings', results);
|
||||
});
|
||||
|
||||
@@ -37,7 +37,8 @@ adminController.home = function(req, res, next) {
|
||||
res.render('admin/index', {
|
||||
version: pkg.version,
|
||||
emailerInstalled: plugins.hasListeners('action:email.send'),
|
||||
searchInstalled: plugins.hasListeners('filter:search.query')
|
||||
searchInstalled: plugins.hasListeners('filter:search.query'),
|
||||
restartRequired: meta.restartRequired
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -68,14 +68,14 @@ categoriesController.get = function(req, res, next) {
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
categoryTools.privileges(cid, uid, function(err, categoryPrivileges) {
|
||||
if (!err) {
|
||||
if (!categoryPrivileges.read) {
|
||||
next(new Error('[[error:no-privileges]]'));
|
||||
} else {
|
||||
next(null, categoryPrivileges);
|
||||
}
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (!categoryPrivileges.read) {
|
||||
next(new Error('[[error:no-privileges]]'));
|
||||
} else {
|
||||
next(err);
|
||||
next(null, categoryPrivileges);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -18,7 +18,9 @@ var fs = require('fs'),
|
||||
User = require('./user');
|
||||
|
||||
(function (Meta) {
|
||||
Meta.restartRequired = false;
|
||||
Meta.config = {};
|
||||
|
||||
Meta.configs = {
|
||||
init: function (callback) {
|
||||
delete Meta.config;
|
||||
@@ -159,6 +161,9 @@ var fs = require('fs'),
|
||||
db.setObjectField('config', 'theme:src', data.src, callback);
|
||||
break;
|
||||
}
|
||||
|
||||
// Restart Required flag
|
||||
meta.restartRequired = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -383,6 +383,8 @@ var fs = require('fs'),
|
||||
return;
|
||||
}
|
||||
|
||||
// Restart Required flag
|
||||
meta.restartRequired = true;
|
||||
|
||||
if(active) {
|
||||
Plugins.fireHook('action:plugin.deactivate', id);
|
||||
|
||||
@@ -54,7 +54,6 @@ module.exports = function(app, middleware, controllers) {
|
||||
});
|
||||
|
||||
app.get('/test', function(req, res) {
|
||||
require('../meta').sounds.init();
|
||||
res.send(200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -79,7 +79,6 @@ SocketAdmin.themes.set = function(socket, data, callback) {
|
||||
widgets.reset(function(err) {
|
||||
meta.themes.set(data, function() {
|
||||
callback();
|
||||
meta.restart();
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -87,7 +86,6 @@ SocketAdmin.themes.set = function(socket, data, callback) {
|
||||
SocketAdmin.plugins.toggle = function(socket, plugin_id) {
|
||||
plugins.toggleActive(plugin_id, function(status) {
|
||||
socket.emit('admin.plugins.toggle', status);
|
||||
meta.restart();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var categories = require('../categories'),
|
||||
var async = require('async'),
|
||||
categories = require('../categories'),
|
||||
categoryTools = require('../categoryTools'),
|
||||
meta = require('./../meta'),
|
||||
user = require('./../user'),
|
||||
@@ -30,12 +31,29 @@ SocketCategories.loadMore = function(socket, data, callback) {
|
||||
return callback(new Error('[[error:invalid-data]]'));
|
||||
}
|
||||
|
||||
user.getSettings(socket.uid, function(err, settings) {
|
||||
async.parallel({
|
||||
privileges: function(next) {
|
||||
categoryTools.privileges(data.cid, socket.uid, next);
|
||||
},
|
||||
settings: function(next) {
|
||||
user.getSettings(socket.uid, next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var start = parseInt(data.after, 10),
|
||||
end = start + settings.topicsPerPage - 1;
|
||||
end = start + results.settings.topicsPerPage - 1;
|
||||
|
||||
categories.getCategoryTopics(data.cid, start, end, socket.uid, callback);
|
||||
categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
data.privileges = results.privileges;
|
||||
callback(null, data);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ SocketModules.chats.send = function(socket, data, callback) {
|
||||
|
||||
function sendChatNotification(fromuid, touid, username) {
|
||||
if (!module.parent.exports.isUserOnline(touid)) {
|
||||
var notifText = 'New message from <strong>' + username + '</strong>';
|
||||
var notifText = '[[notifications:new_message_from,' + username + ']]';
|
||||
notifications.create({
|
||||
text: notifText,
|
||||
path: 'javascript:app.openChat('' + username + '', ' + fromuid + ');',
|
||||
|
||||
@@ -33,15 +33,12 @@ SocketPosts.reply = function(socket, data, callback) {
|
||||
}
|
||||
|
||||
if (postData) {
|
||||
websockets.server.sockets.emit('event:new_post', {
|
||||
posts: [postData]
|
||||
});
|
||||
|
||||
module.parent.exports.emitTopicPostStats();
|
||||
|
||||
var socketData = {
|
||||
posts: [postData]
|
||||
};
|
||||
|
||||
websockets.server.sockets.emit('event:new_post', socketData);
|
||||
|
||||
callback();
|
||||
}
|
||||
});
|
||||
@@ -49,7 +46,7 @@ SocketPosts.reply = function(socket, data, callback) {
|
||||
|
||||
SocketPosts.upvote = function(socket, data, callback) {
|
||||
favouriteCommand('upvote', 'voted', socket, data, callback);
|
||||
sendNotificationToPostOwner(data, socket.uid, 'has upvoted your post');
|
||||
sendNotificationToPostOwner(data, socket.uid, 'notifications:upvoted_your_post');
|
||||
};
|
||||
|
||||
SocketPosts.downvote = function(socket, data, callback) {
|
||||
@@ -62,7 +59,7 @@ SocketPosts.unvote = function(socket, data, callback) {
|
||||
|
||||
SocketPosts.favourite = function(socket, data, callback) {
|
||||
favouriteCommand('favourite', 'favourited', socket, data, callback);
|
||||
sendNotificationToPostOwner(data, socket.uid, 'has favourited your post');
|
||||
sendNotificationToPostOwner(data, socket.uid, 'notifications:favourited_your_post');
|
||||
};
|
||||
|
||||
SocketPosts.unfavourite = function(socket, data, callback) {
|
||||
@@ -87,7 +84,7 @@ function favouriteCommand(command, eventName, socket, data, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
function sendNotificationToPostOwner(data, uid, message) {
|
||||
function sendNotificationToPostOwner(data, uid, notification) {
|
||||
if(data && data.pid && uid) {
|
||||
posts.getPostFields(data.pid, ['tid', 'uid'], function(err, postData) {
|
||||
if (err) {
|
||||
@@ -109,8 +106,9 @@ function sendNotificationToPostOwner(data, uid, message) {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifications.create({
|
||||
text: '<strong>' + results.username + '</strong> ' + message,
|
||||
text: '[[' + notification + ', ' + results.username + ']]',
|
||||
path: nconf.get('relative_path') + '/topic/' + results.slug + '#' + data.pid,
|
||||
uniqueId: 'post:' + data.pid,
|
||||
from: uid
|
||||
@@ -258,7 +256,7 @@ SocketPosts.flag = function(socket, pid, callback) {
|
||||
user.getUserField(socket.uid, 'username', next);
|
||||
},
|
||||
function(username, next) {
|
||||
message = '<strong>' + username + '</strong> flagged a post.';
|
||||
message = '[[notifications:user_flagged_post, ' + username + ']]';
|
||||
posts.getPostField(pid, 'tid', next);
|
||||
},
|
||||
function(tid, next) {
|
||||
|
||||
@@ -229,7 +229,7 @@ var winston = require('winston'),
|
||||
}
|
||||
|
||||
notifications.create({
|
||||
text: '<strong>' + username + '</strong> has posted a reply to: "<strong>' + topicData.title + '</strong>"',
|
||||
text: '[[notifications:user_posted_to, ' + username + ', ' + topicData.title + ']]',
|
||||
path: nconf.get('relative_path') + '/topic/' + topicData.slug + '#' + pid,
|
||||
uniqueId: 'topic:' + tid,
|
||||
from: exceptUid
|
||||
|
||||
@@ -49,7 +49,6 @@ module.exports = function(User) {
|
||||
}
|
||||
if (exists) {
|
||||
async.forever(function(next) {
|
||||
// Append a random number to the username
|
||||
var newUsername = userData.username + (Math.floor(Math.random() * 255) + 1);
|
||||
User.exists(newUsername, function(err, exists) {
|
||||
if (!exists) {
|
||||
@@ -87,10 +86,11 @@ module.exports = function(User) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
userData = results[results.length - 1];
|
||||
|
||||
userData = results[results.length - 1];
|
||||
var userNameChanged = !!results[3];
|
||||
// If a new username was picked...
|
||||
if (results[3]) {
|
||||
if (userNameChanged) {
|
||||
userData.username = results[3];
|
||||
userData.userslug = utils.slugify(results[3]);
|
||||
}
|
||||
@@ -149,16 +149,13 @@ module.exports = function(User) {
|
||||
|
||||
groups.join('registered-users', uid);
|
||||
|
||||
// If their username was automatically changed...
|
||||
if (results[3]) {
|
||||
translator.translate('[[user:username_taken_workaround, ' + userData.username + ']]', function(notifText) {
|
||||
notifications.create({
|
||||
text: notifText,
|
||||
picture: 'brand:logo',
|
||||
datetime: Date.now()
|
||||
}, function(nid) {
|
||||
notifications.push(nid, uid);
|
||||
});
|
||||
if (userNameChanged) {
|
||||
notifications.create({
|
||||
text: '[[user:username_taken_workaround, ' + userData.username + ']]',
|
||||
picture: 'brand:logo',
|
||||
datetime: Date.now()
|
||||
}, function(nid) {
|
||||
notifications.push(nid, uid);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ var db = require('../database'),
|
||||
nconf = require('nconf'),
|
||||
|
||||
user = require('../user'),
|
||||
UserNotifications = require('./notifications'),
|
||||
topics = require('../topics'),
|
||||
emailer = require('../emailer'),
|
||||
meta = require('../meta');
|
||||
@@ -23,6 +22,8 @@ module.exports = function(User) {
|
||||
};
|
||||
|
||||
User.sendDailyDigests = function() {
|
||||
var yesterday = Date.now() - (1000*60*60*24);
|
||||
|
||||
async.parallel({
|
||||
recent: function(next) {
|
||||
topics.getLatestTopics(0, 0, 10, 'day', next);
|
||||
@@ -33,39 +34,61 @@ module.exports = function(User) {
|
||||
}, function(err, data) {
|
||||
var now = new Date();
|
||||
|
||||
async.each(data.uids, function(uid, next) {
|
||||
UserNotifications.getDailyUnread(uid, function(err, notifications) {
|
||||
if (!err && notifications && notifications.length) {
|
||||
async.parallel({
|
||||
recipients: function(next) {
|
||||
User.getMultipleUserFields(data.uids, ['uid', 'username', 'lastonline'], next);
|
||||
},
|
||||
userSettings: function(next) {
|
||||
User.getMultipleUserSettings(data.uids, next);
|
||||
}
|
||||
}, function(err, users) {
|
||||
var recipients = users.recipients,
|
||||
userSettings = users.userSettings,
|
||||
subscribed;
|
||||
|
||||
// Find uids subscribed to daily digest emails
|
||||
subscribed = userSettings.filter(function(setting) {
|
||||
return !setting.dailyDigestFreq || setting.dailyDigestFreq === 'daily';
|
||||
}).map(function(setting) {
|
||||
return setting.uid;
|
||||
});
|
||||
|
||||
// Find only those users who have not been online in the past 24 hours
|
||||
var users = recipients.filter(function(userObj) {
|
||||
return subscribed.indexOf(userObj.uid) !== -1 && yesterday > parseInt(userObj.lastonline, 10);
|
||||
});
|
||||
|
||||
// Consider using eachLimit, but *only* if people complain about email relays choking -- otherwise we're ok.
|
||||
async.each(users, function(userObj, next) {
|
||||
user.notifications.getDailyUnread(userObj.uid, function(err, notifications) {
|
||||
// Turn relative URLs into absolute ones
|
||||
for(var i=0; i<notifications.length; ++i) {
|
||||
if (notifications[i].image.indexOf('http') !== 0) {
|
||||
notifications[i].image = nconf.get('url') + notifications[i].image;
|
||||
}
|
||||
}
|
||||
|
||||
user.getUserField(uid, 'username', function(err, username) {
|
||||
// Send daily digest email
|
||||
// winston.info('[user/notifications] Sending Daily Digest to uid ' + uid);
|
||||
emailer.send('dailydigest', uid, {
|
||||
subject: '[' + meta.config.title + '] Daily Digest for ' + now.getFullYear()+ '/' + (now.getMonth()+1) + '/' + now.getDate(),
|
||||
username: username,
|
||||
url: nconf.get('url'),
|
||||
site_title: meta.config.title,
|
||||
notifications: notifications,
|
||||
recent: data.recent.topics
|
||||
});
|
||||
// Send daily digest email
|
||||
// winston.info('[user/notifications] Sending Daily Digest to uid ' + userObj.uid);
|
||||
emailer.send('dailydigest', userObj.uid, {
|
||||
subject: '[' + meta.config.title + '] Daily Digest for ' + now.getFullYear()+ '/' + (now.getMonth()+1) + '/' + now.getDate(),
|
||||
username: userObj.username,
|
||||
url: nconf.get('url'),
|
||||
site_title: meta.config.title,
|
||||
notifications: notifications,
|
||||
recent: data.recent.topics
|
||||
});
|
||||
}
|
||||
|
||||
next(err);
|
||||
next(err);
|
||||
});
|
||||
}, function(err) {
|
||||
// When finished...
|
||||
if (!err) {
|
||||
winston.info('[user/jobs] Daily Digests sent!');
|
||||
} else {
|
||||
winston.error('[user/jobs] Could not send daily digests: ' + err.message);
|
||||
}
|
||||
});
|
||||
}, function(err) {
|
||||
// When finished...
|
||||
if (!err) {
|
||||
winston.info('[user/jobs] Daily Digests sent!');
|
||||
} else {
|
||||
winston.error('[user/jobs] Could not send daily digests: ' + err.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ var async = require('async'),
|
||||
db.getSetMembers('followers:' + uid, function(err, followers) {
|
||||
if (followers && followers.length) {
|
||||
topics.getTopicField(tid, 'slug', function(err, slug) {
|
||||
var message = '<strong>' + username + '</strong> made a new post';
|
||||
var message = '[[notifications:user_made_post, ' + username + ']]';
|
||||
|
||||
notifications.create({
|
||||
text: message,
|
||||
|
||||
@@ -25,6 +25,7 @@ module.exports = function(User) {
|
||||
settings = data.settings;
|
||||
|
||||
settings.showemail = settings.showemail ? parseInt(settings.showemail, 10) !== 0 : false;
|
||||
settings.dailyDigestFreq = settings.dailyDigestFreq || 'daily';
|
||||
settings.usePagination = settings.usePagination ? parseInt(settings.usePagination, 10) === 1 : parseInt(meta.config.usePagination, 10) === 1;
|
||||
settings.topicsPerPage = settings.topicsPerPage ? parseInt(settings.topicsPerPage, 10) : parseInt(meta.config.topicsPerPage, 10) || 20;
|
||||
settings.postsPerPage = settings.postsPerPage ? parseInt(settings.postsPerPage, 10) : parseInt(meta.config.postsPerPage, 10) || 10;
|
||||
@@ -35,16 +36,43 @@ module.exports = function(User) {
|
||||
});
|
||||
};
|
||||
|
||||
User.getMultipleUserSettings = function(uids, callback) {
|
||||
if (!Array.isArray(uids) || !uids.length) {
|
||||
return callback(null, []);
|
||||
}
|
||||
|
||||
var keys = uids.map(function(uid) {
|
||||
return 'user:' + uid + ':settings';
|
||||
});
|
||||
|
||||
db.getObjects(keys, function(err, settings) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// Associate uid
|
||||
settings = settings.map(function(setting, idx) {
|
||||
setting = setting || {};
|
||||
setting.uid = uids[idx];
|
||||
return setting;
|
||||
});
|
||||
|
||||
callback(null, settings);
|
||||
});
|
||||
};
|
||||
|
||||
User.saveSettings = function(uid, data, callback) {
|
||||
|
||||
if(!data.topicsPerPage || !data.postsPerPage || parseInt(data.topicsPerPage, 10) <= 0 || parseInt(data.postsPerPage, 10) <= 0) {
|
||||
return callback(new Error('[[error:invalid-pagination-value]]'));
|
||||
}
|
||||
|
||||
plugins.fireHook('action:user.saveSettings', {uid: uid, settings: data});
|
||||
data.language = data.language || meta.config.defaultLang;
|
||||
|
||||
plugins.fireHook('action:user.saveSettings', {uid: uid, settings: data});
|
||||
db.setObject('user:' + uid + ':settings', {
|
||||
showemail: data.showemail,
|
||||
dailyDigestFreq: data.dailyDigestFreq || 'daily',
|
||||
usePagination: data.usePagination,
|
||||
topicsPerPage: data.topicsPerPage,
|
||||
postsPerPage: data.postsPerPage,
|
||||
|
||||
Reference in New Issue
Block a user