mirror of
https://github.com/NodeBB/NodeBB.git
synced 2026-07-05 07:47:26 +02:00
@@ -22,7 +22,7 @@ define('admin/general/dashboard', ['semver'], function(semver) {
|
||||
|
||||
Admin.init = function() {
|
||||
app.enterRoom('admin');
|
||||
socket.emit('meta.rooms.getAll', Admin.updateRoomUsage);
|
||||
socket.emit('admin.rooms.getAll', Admin.updateRoomUsage);
|
||||
|
||||
isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||
|
||||
@@ -439,7 +439,7 @@ define('admin/general/dashboard', ['semver'], function(semver) {
|
||||
|
||||
intervals.rooms = setInterval(function() {
|
||||
if (app.isFocused && app.isConnected) {
|
||||
socket.emit('meta.rooms.getAll', Admin.updateRoomUsage);
|
||||
socket.emit('admin.rooms.getAll', Admin.updateRoomUsage);
|
||||
}
|
||||
}, realtime ? DEFAULTS.realtimeInterval : DEFAULTS.roomInterval);
|
||||
|
||||
|
||||
@@ -130,11 +130,7 @@ app.cacheBuster = null;
|
||||
|
||||
app.enterRoom = function (room, callback) {
|
||||
callback = callback || function() {};
|
||||
if (socket) {
|
||||
if (app.currentRoom === room) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (socket && app.user.uid && app.currentRoom !== room) {
|
||||
socket.emit('meta.rooms.enter', {
|
||||
enter: room,
|
||||
username: app.user.username,
|
||||
@@ -148,6 +144,7 @@ app.cacheBuster = null;
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
app.currentRoom = room;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -8,12 +8,11 @@ define('forum/topic', [
|
||||
'forum/topic/threadTools',
|
||||
'forum/topic/postTools',
|
||||
'forum/topic/events',
|
||||
'forum/topic/browsing',
|
||||
'forum/topic/posts',
|
||||
'navigator',
|
||||
'sort',
|
||||
'components'
|
||||
], function(infinitescroll, threadTools, postTools, events, browsing, posts, navigator, sort, components) {
|
||||
], function(infinitescroll, threadTools, postTools, events, posts, navigator, sort, components) {
|
||||
var Topic = {},
|
||||
currentUrl = '';
|
||||
|
||||
@@ -70,16 +69,6 @@ define('forum/topic', [
|
||||
|
||||
$(window).on('scroll', updateTopicTitle);
|
||||
|
||||
|
||||
if (app.user.uid) {
|
||||
socket.emit('topics.enter', tid, function(err, data) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
browsing.onUpdateUsersInRoom(data);
|
||||
});
|
||||
}
|
||||
|
||||
handleTopicSearch();
|
||||
|
||||
$(window).trigger('action:topic.loaded');
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
/* globals define, app, config, socket, ajaxify */
|
||||
|
||||
define('forum/topic/browsing', function() {
|
||||
|
||||
var Browsing = {};
|
||||
|
||||
Browsing.onUpdateUsersInRoom = function(data) {
|
||||
if (data && data.room.indexOf('topic_' + ajaxify.data.tid) !== -1) {
|
||||
$('[component="topic/browsing/list"]').parent().toggleClass('hidden', !data.users.length);
|
||||
for (var i=0; i<data.users.length; ++i) {
|
||||
addUserIcon(data.users[i]);
|
||||
}
|
||||
|
||||
updateUserCount(data.hidden);
|
||||
}
|
||||
};
|
||||
|
||||
Browsing.onUserEnter = function(data) {
|
||||
var browsingList = $('[component="topic/browsing/list"]');
|
||||
var user = browsingList.find('a[data-uid="' + data.uid + '"]');
|
||||
if (!user.length && browsingList.first().children().length < 10) {
|
||||
addUserIcon(data);
|
||||
} else if (user.length) {
|
||||
user.attr('data-count', parseInt(user.attr('data-count'), 10) + 1);
|
||||
} else {
|
||||
increaseUserCount(1);
|
||||
}
|
||||
Browsing.onUserStatusChange(data);
|
||||
};
|
||||
|
||||
Browsing.onUserLeave = function(uid) {
|
||||
if (app.user.uid === parseInt(uid, 10)) {
|
||||
return;
|
||||
}
|
||||
var browsingList = $('[component="topic/browsing/list"]');
|
||||
var user = browsingList.find('a[data-uid="' + uid + '"]');
|
||||
if (user.length) {
|
||||
var count = Math.max(0, parseInt(user.attr('data-count'), 10) - 1);
|
||||
user.attr('data-count', count);
|
||||
if (count <= 0) {
|
||||
user.parent().remove();
|
||||
if (!browsingList.children(':not(.hidden)').length) {
|
||||
browsingList.parent().addClass('hidden');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
increaseUserCount(-1);
|
||||
}
|
||||
};
|
||||
|
||||
Browsing.onUserStatusChange = function(data) {
|
||||
app.updateUserStatus($('[data-uid="' + data.uid + '"] [component="user/status"]'), data.status);
|
||||
|
||||
updateBrowsingUsers(data);
|
||||
};
|
||||
|
||||
function updateBrowsingUsers(data) {
|
||||
var browsingList = $('[component="topic/browsing/list"]');
|
||||
var user = browsingList.find('a[data-uid="'+ data.uid + '"]');
|
||||
if (user.length) {
|
||||
user.parent().toggleClass('hidden', data.status === 'offline');
|
||||
browsingList.parent().toggleClass('hidden', !browsingList.children(':not(.hidden)').length);
|
||||
}
|
||||
}
|
||||
|
||||
function addUserIcon(user) {
|
||||
if (!user.userslug) {
|
||||
return;
|
||||
}
|
||||
var browsingList = $('[component="topic/browsing/list"]');
|
||||
var userEl = createUserIcon(user.uid, user.picture, user.userslug, user.username, user['icon:bgColor'], user['icon:text']);
|
||||
var isSelf = parseInt(user.uid, 10) === parseInt(app.user.uid, 10);
|
||||
if (isSelf) {
|
||||
browsingList.prepend(userEl);
|
||||
} else {
|
||||
browsingList.append(userEl);
|
||||
}
|
||||
|
||||
browsingList.find('a[data-uid]').tooltip({
|
||||
placement: 'top'
|
||||
});
|
||||
}
|
||||
|
||||
function createUserIcon(uid, picture, userslug, username, iconBg, iconText) {
|
||||
if (!$('[component="topic/browsing/list"]').find('[data-uid="' + uid + '"]').length) {
|
||||
var imgOrIcon = picture ?
|
||||
'<img src="'+ picture +'" />' :
|
||||
'<div class="user-icon" style="background-color: ' + iconBg + ';">' + iconText + '</div>';
|
||||
|
||||
return $('<div class="inline-block"><a title="' + username + '" data-uid="' + uid + '" data-count="1" href="' + config.relative_path + '/user/' + userslug + '">' + imgOrIcon + '</a></div>');
|
||||
}
|
||||
}
|
||||
|
||||
function updateUserCount(count) {
|
||||
count = parseInt(count, 10);
|
||||
if (!count || count < 0) {
|
||||
count = 0;
|
||||
}
|
||||
$('[component="topic/browsing/count"]').text(count).parent().toggleClass('hidden', count === 0);
|
||||
}
|
||||
|
||||
function increaseUserCount(incr) {
|
||||
updateUserCount(parseInt($('[component="topic/browsing/count"]').first().text(), 10) + incr);
|
||||
}
|
||||
|
||||
return Browsing;
|
||||
});
|
||||
@@ -4,19 +4,16 @@
|
||||
/* globals config, app, ajaxify, define, socket, templates, translator, utils */
|
||||
|
||||
define('forum/topic/events', [
|
||||
'forum/topic/browsing',
|
||||
'forum/topic/postTools',
|
||||
'forum/topic/threadTools',
|
||||
'forum/topic/posts',
|
||||
'components'
|
||||
], function(browsing, postTools, threadTools, posts, components) {
|
||||
], function(postTools, threadTools, posts, components) {
|
||||
|
||||
var Events = {};
|
||||
|
||||
var events = {
|
||||
'event:user_enter': browsing.onUserEnter,
|
||||
'event:user_leave': browsing.onUserLeave,
|
||||
'event:user_status_change': browsing.onUserStatusChange,
|
||||
'event:user_status_change': onUserStatusChange,
|
||||
'event:voted': updatePostVotesAndUserReputation,
|
||||
'event:favourited': updateFavouriteCount,
|
||||
|
||||
@@ -69,6 +66,10 @@ define('forum/topic/events', [
|
||||
}
|
||||
};
|
||||
|
||||
function onUserStatusChange(data) {
|
||||
app.updateUserStatus($('[data-uid="' + data.uid + '"] [component="user/status"]'), data.status);
|
||||
}
|
||||
|
||||
function updatePostVotesAndUserReputation(data) {
|
||||
var votes = components.get('post/vote-count', data.post.pid),
|
||||
reputationElements = $('.reputation[data-uid="' + data.post.uid + '"]');
|
||||
|
||||
@@ -10,9 +10,6 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
|
||||
var chatsToggleEl = components.get('chat/dropdown'),
|
||||
chatsListEl = components.get('chat/list');
|
||||
|
||||
// Sync open chats between all user socket sessions
|
||||
module.sync();
|
||||
|
||||
chatsToggleEl.on('click', function() {
|
||||
if (chatsToggleEl.parent().hasClass('open')) {
|
||||
return;
|
||||
@@ -93,42 +90,6 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
|
||||
var modal = module.getModal(data.uid);
|
||||
app.updateUserStatus(modal.find('[component="user/status"]'), data.status);
|
||||
});
|
||||
|
||||
socket.on('query:chats.sync', function(data, callback) {
|
||||
var chats = Array.prototype.map.call(taskbar.get('chat'), function(chatObj) {
|
||||
return {
|
||||
username: chatObj.options.title,
|
||||
uid: chatObj.options.touid,
|
||||
new: chatObj.element.hasClass('new')
|
||||
};
|
||||
});
|
||||
|
||||
callback(null, chats);
|
||||
});
|
||||
|
||||
socket.on('event:chats.open', function(data) {
|
||||
data.silent = true;
|
||||
module.createModal(data);
|
||||
});
|
||||
|
||||
socket.on('event:chats.close', function(uid) {
|
||||
module.close(module.getModal(uid), true);
|
||||
});
|
||||
|
||||
socket.on('event:chats.toggleNew', function(data) {
|
||||
var uuid = module.getModal(data.uid).attr('UUID');
|
||||
module.toggleNew(uuid, data.state, true);
|
||||
});
|
||||
|
||||
$(window).on('action:taskbar.toggleNew', function(ev, uuid) {
|
||||
var modal = $('.chat-modal[uuid="' + uuid + '"]'),
|
||||
touid = modal.attr('touid');
|
||||
|
||||
socket.emit('modules.chats.toggleNew', {
|
||||
uid: touid,
|
||||
state: false
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.loadChatsDropdown = function(chatsListEl) {
|
||||
@@ -318,10 +279,6 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
|
||||
state: ''
|
||||
});
|
||||
|
||||
if (!data.silent) {
|
||||
socket.emit('modules.chats.open', data);
|
||||
}
|
||||
|
||||
$(window).trigger('action:chat.loaded', chatModal);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
@@ -343,10 +300,6 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
|
||||
taskbar.discard('chat', chatModal.attr('UUID'));
|
||||
Chats.notifyTyping(chatModal.attr('touid'), false);
|
||||
|
||||
if (!silent) {
|
||||
socket.emit('modules.chats.close', chatModal.attr('touid'));
|
||||
}
|
||||
|
||||
if (chatModal.attr('data-mobile')) {
|
||||
module.disableMobileBehaviour(chatModal);
|
||||
}
|
||||
@@ -423,27 +376,7 @@ define('chat', ['components', 'taskbar', 'string', 'sounds', 'forum/chats', 'tra
|
||||
socket.emit('modules.chats.canMessage', toUid, callback);
|
||||
};
|
||||
|
||||
module.sync = function() {
|
||||
socket.emit('modules.chats.sync', function(err, users) {
|
||||
if (err) {
|
||||
return app.alertError(err.message);
|
||||
}
|
||||
|
||||
users.forEach(function(user) {
|
||||
if (!module.modalExists(user.uid)) {
|
||||
module.createModal({
|
||||
username: user.username,
|
||||
touid: user.uid,
|
||||
silent: true
|
||||
}, function(modal) {
|
||||
if (user.new) {
|
||||
module.toggleNew(modal.attr('UUID'), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return module;
|
||||
});
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var cronJob = require('cron').CronJob,
|
||||
db = require('./database');
|
||||
|
||||
var cronJob = require('cron').CronJob;
|
||||
var db = require('./database');
|
||||
|
||||
(function(Analytics) {
|
||||
|
||||
@@ -61,6 +60,8 @@ var cronJob = require('cron').CronJob,
|
||||
db.incrObjectFieldBy('global', 'uniqueIPCount', uniqueIPCount);
|
||||
uniqueIPCount = 0;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
Analytics.getUnwrittenPageviews = function() {
|
||||
|
||||
@@ -58,7 +58,7 @@ helpers.getUserDataByUserSlug = function(userslug, callerUID, callback) {
|
||||
var self = parseInt(callerUID, 10) === parseInt(userData.uid, 10);
|
||||
|
||||
userData.joindate = utils.toISOString(userData.joindate);
|
||||
userData.lastonline = userData.lastonline ? utils.toISOString(userData.lastonline) : userData.joindate;
|
||||
userData.lastonlineISO = utils.toISOString(userData.lastonline || userData.joindate);
|
||||
userData.age = userData.birthday ? Math.floor((new Date().getTime() - new Date(userData.birthday).getTime()) / 31536000000) : '';
|
||||
|
||||
if (!(isAdmin || self || (userData.email && userSettings.showemail))) {
|
||||
@@ -86,7 +86,7 @@ helpers.getUserDataByUserSlug = function(userslug, callerUID, callback) {
|
||||
userData['email:confirmed'] = !!parseInt(userData['email:confirmed'], 10);
|
||||
userData.profile_links = results.profile_links;
|
||||
userData.sso = results.sso.associations;
|
||||
userData.status = require('../../socket.io').isUserOnline(userData.uid) ? (userData.status || 'online') : 'offline';
|
||||
userData.status = user.getStatus(userData);
|
||||
userData.banned = parseInt(userData.banned, 10) === 1;
|
||||
userData.website = validator.escape(userData.website);
|
||||
userData.websiteLink = !userData.website.startsWith('http') ? 'http://' + userData.website : userData.website;
|
||||
|
||||
@@ -125,6 +125,7 @@ topicsController.get = function(req, res, callback) {
|
||||
});
|
||||
},
|
||||
function (topicData, next) {
|
||||
|
||||
var breadcrumbs = [
|
||||
{
|
||||
text: topicData.category.name,
|
||||
@@ -265,6 +266,18 @@ topicsController.get = function(req, res, callback) {
|
||||
|
||||
topics.increaseViewCount(tid);
|
||||
|
||||
if (req.uid) {
|
||||
topics.markAsRead([tid], req.uid, function(err, markedRead) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
if (markedRead) {
|
||||
topics.pushUnreadCount(req.uid);
|
||||
topics.markTopicNotificationsRead(tid, req.uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
plugins.fireHook('filter:topic.build', {req: req, res: res, templateData: data}, function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
||||
@@ -149,84 +149,6 @@ usersController.getUsersForSearch = function(req, res, next) {
|
||||
});
|
||||
};
|
||||
|
||||
usersController.getMap = function(req, res, next) {
|
||||
var socketIO = require('../socket.io');
|
||||
var rooms = require('../socket.io/rooms');
|
||||
|
||||
var roomNames = ['user_list', 'categories', 'unread_topics', 'recent_topics', 'popular_topics', 'tags'];
|
||||
var links = {
|
||||
user_list: '/users',
|
||||
categories: '/categories',
|
||||
unread_topics: '/unread',
|
||||
recent_topics: '/recent',
|
||||
popular_topics: '/popular',
|
||||
tags: '/tags'
|
||||
};
|
||||
|
||||
var keys = Object.keys(rooms.roomClients());
|
||||
|
||||
keys = keys.filter(function(key) {
|
||||
return key.startsWith('topic_') || key.startsWith('category_');
|
||||
});
|
||||
|
||||
roomNames = roomNames.concat(keys);
|
||||
|
||||
async.map(roomNames, function(roomName, next) {
|
||||
socketIO.getUsersInRoom(0, roomName, 0, 39, function(err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (roomName.startsWith('category_')) {
|
||||
var cid = roomName.split('_')[1];
|
||||
categories.getCategoryFields(cid, ['slug', 'name'], function(err, categoryData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
data.room = validator.escape(categoryData.name);
|
||||
data.link = '/category/' + categoryData.slug;
|
||||
data.core = false;
|
||||
next(null, data);
|
||||
});
|
||||
} else if (roomName.startsWith('topic_')) {
|
||||
var tid = roomName.split('_')[1];
|
||||
topics.getTopicFields(tid, ['slug', 'title'], function(err, topicData) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
data.room = validator.escape(topicData.title);
|
||||
data.link = '/topic/' + topicData.slug;
|
||||
data.core = false;
|
||||
next(null, data);
|
||||
});
|
||||
} else {
|
||||
data.core = true;
|
||||
next(null, data);
|
||||
}
|
||||
});
|
||||
}, function(err, data) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
data.sort(function(a, b) {
|
||||
return b.users.length - a.users.length;
|
||||
});
|
||||
|
||||
data.forEach(function(room) {
|
||||
if (!room.link) {
|
||||
room.link = links[room.room];
|
||||
}
|
||||
});
|
||||
|
||||
res.render('usersMap', {
|
||||
rooms: data,
|
||||
'reputation:disabled': parseInt(meta.config['reputation:disabled'], 10) === 1,
|
||||
title: '[[pages:users/map]]',
|
||||
breadcrumbs: helpers.buildBreadcrumbs([{text: '[[global:users]]', url: '/users'}, {text: '[[global:map]]'}])
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function render(req, res, data, next) {
|
||||
plugins.fireHook('filter:users.build', {req: req, res: res, templateData: data}, function(err, data) {
|
||||
if (err) {
|
||||
|
||||
@@ -321,7 +321,7 @@ module.exports = function(db, module) {
|
||||
return callback();
|
||||
}
|
||||
value = helpers.valueToString(value);
|
||||
db.collection('objects').findOne({_key:key, value: value}, {fields:{_id: 0, score: 1}}, function(err, result) {
|
||||
db.collection('objects').findOne({_key: key, value: value}, {fields:{_id: 0, score: 1}}, function(err, result) {
|
||||
callback(err, result ? result.score : null);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -266,7 +266,7 @@ var db = require('./database'),
|
||||
db.isSortedSetMembers('uid:' + uid + ':chats:unread', uids, next);
|
||||
},
|
||||
users: function(next) {
|
||||
user.getUsersFields(uids, ['uid', 'username', 'picture', 'status'] , next);
|
||||
user.getUsersFields(uids, ['uid', 'username', 'picture', 'status', 'lastonline'] , next);
|
||||
},
|
||||
teasers: function(next) {
|
||||
async.map(uids, function(fromuid, next) {
|
||||
@@ -288,11 +288,11 @@ var db = require('./database'),
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
results.users.forEach(function(user, index) {
|
||||
if (user && parseInt(user.uid, 10)) {
|
||||
user.unread = results.unread[index];
|
||||
user.status = sockets.isUserOnline(user.uid) ? user.status : 'offline';
|
||||
user.teaser = results.teasers[index];
|
||||
results.users.forEach(function(userData, index) {
|
||||
if (userData && parseInt(userData.uid, 10)) {
|
||||
userData.unread = results.unread[index];
|
||||
userData.status = user.getStatus(userData);
|
||||
userData.teaser = results.teasers[index];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -416,35 +416,37 @@ var db = require('./database'),
|
||||
};
|
||||
|
||||
function sendNotifications(fromuid, touid, messageObj, callback) {
|
||||
if (sockets.isUserOnline(touid)) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
notifications.create({
|
||||
bodyShort: '[[notifications:new_message_from, ' + messageObj.fromUser.username + ']]',
|
||||
bodyLong: messageObj.content,
|
||||
nid: 'chat_' + fromuid + '_' + touid,
|
||||
from: fromuid,
|
||||
path: '/chats/' + messageObj.fromUser.username
|
||||
}, function(err, notification) {
|
||||
if (!err && notification) {
|
||||
notifications.push(notification, [touid], callback);
|
||||
user.isOnline(touid, function(err, isOnline) {
|
||||
if (err || isOnline) {
|
||||
return callback(err);
|
||||
}
|
||||
});
|
||||
|
||||
user.getSettings(messageObj.toUser.uid, function(err, settings) {
|
||||
if (settings.sendChatNotifications && !parseInt(meta.config.disableEmailSubscriptions, 10)) {
|
||||
emailer.send('notif_chat', touid, {
|
||||
subject: '[[email:notif.chat.subject, ' + messageObj.fromUser.username + ']]',
|
||||
username: messageObj.toUser.username,
|
||||
userslug: utils.slugify(messageObj.toUser.username),
|
||||
summary: '[[notifications:new_message_from, ' + messageObj.fromUser.username + ']]',
|
||||
message: messageObj,
|
||||
site_title: meta.config.title || 'NodeBB',
|
||||
url: nconf.get('url'),
|
||||
fromUserslug: utils.slugify(messageObj.fromUser.username)
|
||||
});
|
||||
}
|
||||
notifications.create({
|
||||
bodyShort: '[[notifications:new_message_from, ' + messageObj.fromUser.username + ']]',
|
||||
bodyLong: messageObj.content,
|
||||
nid: 'chat_' + fromuid + '_' + touid,
|
||||
from: fromuid,
|
||||
path: '/chats/' + messageObj.fromUser.username
|
||||
}, function(err, notification) {
|
||||
if (!err && notification) {
|
||||
notifications.push(notification, [touid], callback);
|
||||
}
|
||||
});
|
||||
|
||||
user.getSettings(messageObj.toUser.uid, function(err, settings) {
|
||||
if (settings.sendChatNotifications && !parseInt(meta.config.disableEmailSubscriptions, 10)) {
|
||||
emailer.send('notif_chat', touid, {
|
||||
subject: '[[email:notif.chat.subject, ' + messageObj.fromUser.username + ']]',
|
||||
username: messageObj.toUser.username,
|
||||
userslug: utils.slugify(messageObj.toUser.username),
|
||||
summary: '[[notifications:new_message_from, ' + messageObj.fromUser.username + ']]',
|
||||
message: messageObj,
|
||||
site_title: meta.config.title || 'NodeBB',
|
||||
url: nconf.get('url'),
|
||||
fromUserslug: utils.slugify(messageObj.fromUser.username)
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ module.exports = function(Meta) {
|
||||
'public/src/client/recent.js',
|
||||
'public/src/client/unread.js',
|
||||
'public/src/client/topic.js',
|
||||
'public/src/client/topic/browsing.js',
|
||||
'public/src/client/topic/events.js',
|
||||
'public/src/client/topic/flag.js',
|
||||
'public/src/client/topic/fork.js',
|
||||
|
||||
@@ -20,10 +20,7 @@ module.exports = function(Posts) {
|
||||
user.getMultipleUserSettings(uids, next);
|
||||
},
|
||||
userData: function(next) {
|
||||
user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status'], next);
|
||||
},
|
||||
online: function(next) {
|
||||
require('../socket.io').isUsersOnline(uids, next);
|
||||
user.getUsersFields(uids, ['uid', 'username', 'fullname', 'userslug', 'reputation', 'postcount', 'picture', 'signature', 'banned', 'status', 'lastonline'], next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
@@ -47,7 +44,7 @@ module.exports = function(Posts) {
|
||||
userData.selectedGroup = userData.groups[index];
|
||||
}
|
||||
});
|
||||
userData.status = user.getStatus(userData.status, results.online[i]);
|
||||
userData.status = user.getStatus(userData);
|
||||
});
|
||||
|
||||
async.map(userData, function(userData, next) {
|
||||
|
||||
@@ -62,7 +62,6 @@ function userRoutes(app, middleware, controllers) {
|
||||
setupPageRoute(app, '/users/sort-posts', middleware, middlewares, controllers.users.getUsersSortedByPosts);
|
||||
setupPageRoute(app, '/users/sort-reputation', middleware, middlewares, controllers.users.getUsersSortedByReputation);
|
||||
setupPageRoute(app, '/users/search', middleware, middlewares, controllers.users.getUsersForSearch);
|
||||
setupPageRoute(app, '/users/map', middleware, middlewares, controllers.users.getMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ var async = require('async'),
|
||||
tags: require('./admin/tags'),
|
||||
rewards: require('./admin/rewards'),
|
||||
navigation: require('./admin/navigation'),
|
||||
rooms: require('./admin/rooms'),
|
||||
themes: {},
|
||||
plugins: {},
|
||||
widgets: {},
|
||||
|
||||
73
src/socket.io/admin/rooms.js
Normal file
73
src/socket.io/admin/rooms.js
Normal file
@@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
var validator = require('validator');
|
||||
var topics = require('../../topics');
|
||||
|
||||
var SocketRooms = {};
|
||||
|
||||
SocketRooms.getAll = function(socket, data, callback) {
|
||||
|
||||
var websockets = require('../index');
|
||||
var io = websockets.server;
|
||||
if (!io) {
|
||||
return;
|
||||
}
|
||||
|
||||
var roomClients = io.sockets.adapter.rooms;
|
||||
var socketData = {
|
||||
onlineGuestCount: websockets.getOnlineAnonCount(),
|
||||
onlineRegisteredCount: websockets.getOnlineUserCount(),
|
||||
socketCount: websockets.getSocketCount(),
|
||||
users: {
|
||||
categories: roomClients.categories ? Object.keys(roomClients.categories).length : 0,
|
||||
recent: roomClients.recent_topics ? Object.keys(roomClients.recent_topics).length : 0,
|
||||
unread: roomClients.unread_topics ? Object.keys(roomClients.unread_topics).length: 0,
|
||||
popular: roomClients.popular_topics ? Object.keys(roomClients.popular_topics).length: 0,
|
||||
topics: 0,
|
||||
category: 0
|
||||
},
|
||||
topics: {}
|
||||
};
|
||||
|
||||
var topTenTopics = [],
|
||||
tid;
|
||||
|
||||
for (var room in roomClients) {
|
||||
if (roomClients.hasOwnProperty(room)) {
|
||||
tid = room.match(/^topic_(\d+)/);
|
||||
if (tid) {
|
||||
var length = Object.keys(roomClients[room]).length;
|
||||
socketData.users.topics += length;
|
||||
|
||||
topTenTopics.push({tid: tid[1], count: length});
|
||||
} else if (room.match(/^category/)) {
|
||||
socketData.users.category += Object.keys(roomClients[room]).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
topTenTopics = topTenTopics.sort(function(a, b) {
|
||||
return b.count - a.count;
|
||||
}).slice(0, 10);
|
||||
|
||||
var topTenTids = topTenTopics.map(function(topic) {
|
||||
return topic.tid;
|
||||
});
|
||||
|
||||
topics.getTopicsFields(topTenTids, ['title'], function(err, titles) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
topTenTopics.forEach(function(topic, index) {
|
||||
socketData.topics[topic.tid] = {
|
||||
value: topic.count || 0,
|
||||
title: validator.escape(titles[index].title)
|
||||
};
|
||||
});
|
||||
|
||||
callback(null, socketData);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = SocketRooms;
|
||||
@@ -137,11 +137,6 @@ SocketCategories.getTopicCount = function(socket, cid, callback) {
|
||||
categories.getCategoryField(cid, 'topic_count', callback);
|
||||
};
|
||||
|
||||
SocketCategories.getUsersInCategory = function(socket, cid, callback) {
|
||||
var uids = websockets.getUidsInRoom('category_' + cid);
|
||||
user.getUsersFields(uids, ['uid', 'userslug', 'username', 'picture'], callback);
|
||||
};
|
||||
|
||||
SocketCategories.getCategoriesByPrivilege = function(socket, privilege, callback) {
|
||||
categories.getCategoriesByPrivilege('categories:cid', socket.uid, privilege, callback);
|
||||
};
|
||||
|
||||
@@ -11,7 +11,6 @@ var SocketIO = require('socket.io'),
|
||||
user = require('../user'),
|
||||
logger = require('../logger'),
|
||||
ratelimit = require('../middleware/ratelimit'),
|
||||
rooms = require('./rooms'),
|
||||
|
||||
Sockets = {},
|
||||
Namespaces = {};
|
||||
@@ -46,12 +45,6 @@ function onConnection(socket) {
|
||||
|
||||
onConnect(socket);
|
||||
|
||||
// see https://github.com/Automattic/socket.io/issues/1814 and
|
||||
// http://stackoverflow.com/questions/25830415/get-the-list-of-rooms-the-client-is-currently-in-on-disconnect-event
|
||||
socket.onclose = function(reason) {
|
||||
Object.getPrototypeOf(this).onclose.call(this, {reason: reason, rooms: socket.rooms.slice()});
|
||||
};
|
||||
|
||||
socket.on('disconnect', function(data) {
|
||||
onDisconnect(socket, data);
|
||||
});
|
||||
@@ -63,8 +56,8 @@ function onConnection(socket) {
|
||||
|
||||
function onConnect(socket) {
|
||||
if (socket.uid) {
|
||||
rooms.enter(socket, 'uid_' + socket.uid);
|
||||
rooms.enter(socket, 'online_users');
|
||||
socket.join('uid_' + socket.uid);
|
||||
socket.join('online_users');
|
||||
|
||||
user.getUserFields(socket.uid, ['status'], function(err, userData) {
|
||||
if (err || !userData) {
|
||||
@@ -76,25 +69,17 @@ function onConnect(socket) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
rooms.enter(socket, 'online_guests');
|
||||
socket.join('online_guests');
|
||||
}
|
||||
}
|
||||
|
||||
function onDisconnect(socket, data) {
|
||||
function onDisconnect(socket) {
|
||||
if (socket.uid) {
|
||||
var socketCount = Sockets.getUserSocketCount(socket.uid);
|
||||
if (socketCount <= 1) {
|
||||
socket.broadcast.emit('event:user_status_change', {uid: socket.uid, status: 'offline'});
|
||||
}
|
||||
|
||||
// see https://github.com/Automattic/socket.io/issues/1814
|
||||
data.rooms.forEach(function(roomName) {
|
||||
if (roomName.startsWith('topic')) {
|
||||
io.in(roomName).emit('event:user_leave', socket.uid);
|
||||
}
|
||||
});
|
||||
}
|
||||
rooms.leaveAll(socket, data.rooms);
|
||||
}
|
||||
|
||||
function onMessage(socket, payload) {
|
||||
@@ -211,25 +196,32 @@ Sockets.in = function(room) {
|
||||
};
|
||||
|
||||
Sockets.getSocketCount = function() {
|
||||
return rooms.socketCount();
|
||||
if (!io) {
|
||||
return 0;
|
||||
}
|
||||
return io.sockets.sockets.length;
|
||||
};
|
||||
|
||||
Sockets.getUserSocketCount = function(uid) {
|
||||
return rooms.clients('uid_' + uid).length;
|
||||
if (!io) {
|
||||
return 0;
|
||||
}
|
||||
return io.sockets.adapter.rooms['uid_' + uid] ? Object.keys(io.sockets.adapter.rooms['uid_' + uid]).length : 0;
|
||||
};
|
||||
|
||||
Sockets.getOnlineUserCount = function() {
|
||||
var count = 0;
|
||||
Object.keys(rooms.roomClients()).forEach(function(roomName) {
|
||||
if (roomName.startsWith('uid_')) {
|
||||
++ count;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
if (!io) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return io.sockets.adapter.rooms.online_users ? Object.keys(io.sockets.adapter.rooms.online_users).length : 0;
|
||||
};
|
||||
|
||||
Sockets.getOnlineAnonCount = function () {
|
||||
return rooms.clients('online_guests').length;
|
||||
if (!io) {
|
||||
return 0;
|
||||
}
|
||||
return io.sockets.adapter.rooms.online_guests ? Object.keys(io.sockets.adapter.rooms.online_guests).length : 0;
|
||||
};
|
||||
|
||||
Sockets.reqFromSocket = function(socket) {
|
||||
@@ -249,76 +241,30 @@ Sockets.reqFromSocket = function(socket) {
|
||||
};
|
||||
|
||||
Sockets.isUserOnline = function(uid) {
|
||||
return !!rooms.clients('uid_' + uid).length;
|
||||
winston.warn('[deprecated] Sockets.isUserOnline')
|
||||
return false;
|
||||
};
|
||||
|
||||
Sockets.isUsersOnline = function(uids, callback) {
|
||||
callback(null, uids.map(Sockets.isUserOnline));
|
||||
winston.warn('[deprecated] Sockets.isUsersOnline')
|
||||
callback(null, uids.map(function() { return false; }));
|
||||
};
|
||||
|
||||
Sockets.getUsersInRoom = function (uid, roomName, start, stop, callback) {
|
||||
if (!roomName) {
|
||||
return;
|
||||
}
|
||||
|
||||
var uids = Sockets.getUidsInRoom(roomName);
|
||||
var total = uids.length;
|
||||
if (stop !== -1) {
|
||||
uids = uids.slice(start, stop);
|
||||
}
|
||||
|
||||
if (uid && uids.indexOf(uid.toString()) === -1) {
|
||||
uids = [uid].concat(uids);
|
||||
}
|
||||
|
||||
if (!uids.length) {
|
||||
return callback(null, {users: [], total: 0 , room: roomName});
|
||||
}
|
||||
user.getUsersFields(uids, ['uid', 'username', 'userslug', 'picture', 'status'], function(err, users) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
users = users.filter(function(user) {
|
||||
return user && user.status !== 'offline';
|
||||
});
|
||||
|
||||
callback(null, {
|
||||
users: users,
|
||||
room: roomName,
|
||||
total: users.length ? total : 0,
|
||||
hidden: Math.max(0, total - uids.length)
|
||||
});
|
||||
winston.warn('[deprecated] Sockets.getUsersInRoom')
|
||||
callback(null, {
|
||||
users: [],
|
||||
room: roomName,
|
||||
total: 0,
|
||||
hidden: 0
|
||||
});
|
||||
return;
|
||||
};
|
||||
|
||||
Sockets.getUidsInRoom = function(roomName, callback) {
|
||||
winston.warn('[deprecated] Sockets.getUidsInRoom')
|
||||
callback = callback || function() {};
|
||||
|
||||
var uids = [];
|
||||
|
||||
var socketids = rooms.clients(roomName);
|
||||
if (!Array.isArray(socketids) || !socketids.length) {
|
||||
callback(null, []);
|
||||
return [];
|
||||
}
|
||||
|
||||
for(var i=0; i<socketids.length; ++i) {
|
||||
var socketRooms = rooms.clientRooms(socketids[i]);
|
||||
if (Array.isArray(socketRooms)) {
|
||||
socketRooms.forEach(function(roomName) {
|
||||
if (roomName.startsWith('uid_')) {
|
||||
var uid = roomName.split('_')[1];
|
||||
if (uids.indexOf(uid) === -1) {
|
||||
uids.push(uid);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, uids);
|
||||
return uids;
|
||||
callback(null, []);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var validator = require('validator'),
|
||||
|
||||
meta = require('../meta'),
|
||||
var meta = require('../meta'),
|
||||
user = require('../user'),
|
||||
topics = require('../topics'),
|
||||
emitter = require('../emitter'),
|
||||
rooms = require('./rooms'),
|
||||
|
||||
websockets = require('./'),
|
||||
|
||||
@@ -50,16 +47,8 @@ SocketMeta.rooms.enter = function(socket, data, callback) {
|
||||
leaveCurrentRoom(socket);
|
||||
|
||||
if (data.enter) {
|
||||
rooms.enter(socket, data.enter);
|
||||
socket.join(data.enter);
|
||||
socket.currentRoom = data.enter;
|
||||
if (data.enter.indexOf('topic') !== -1) {
|
||||
data.uid = socket.uid;
|
||||
data.picture = validator.escape(data.picture);
|
||||
data.username = validator.escape(data.username);
|
||||
data.userslug = validator.escape(data.userslug);
|
||||
|
||||
websockets.in(data.enter).emit('event:user_enter', data);
|
||||
}
|
||||
}
|
||||
callback();
|
||||
};
|
||||
@@ -74,70 +63,11 @@ SocketMeta.rooms.leaveCurrent = function(socket, data, callback) {
|
||||
|
||||
function leaveCurrentRoom(socket) {
|
||||
if (socket.currentRoom) {
|
||||
rooms.leave(socket, socket.currentRoom);
|
||||
if (socket.currentRoom.indexOf('topic') !== -1) {
|
||||
websockets.in(socket.currentRoom).emit('event:user_leave', socket.uid);
|
||||
}
|
||||
socket.leave(socket.currentRoom);
|
||||
socket.currentRoom = '';
|
||||
}
|
||||
}
|
||||
|
||||
SocketMeta.rooms.getAll = function(socket, data, callback) {
|
||||
var roomClients = rooms.roomClients();
|
||||
var socketData = {
|
||||
onlineGuestCount: websockets.getOnlineAnonCount(),
|
||||
onlineRegisteredCount: websockets.getOnlineUserCount(),
|
||||
socketCount: websockets.getSocketCount(),
|
||||
users: {
|
||||
categories: roomClients.categories ? roomClients.categories.length : 0,
|
||||
recent: roomClients.recent_topics ? roomClients.recent_topics.length : 0,
|
||||
unread: roomClients.unread_topics ? roomClients.unread_topics.length: 0,
|
||||
popular: roomClients.popular_topics ? roomClients.popular_topics.length: 0,
|
||||
topics: 0,
|
||||
category: 0
|
||||
},
|
||||
topics: {}
|
||||
};
|
||||
|
||||
var topTenTopics = [],
|
||||
tid;
|
||||
|
||||
for (var room in roomClients) {
|
||||
if (roomClients.hasOwnProperty(room)) {
|
||||
tid = room.match(/^topic_(\d+)/);
|
||||
if (tid) {
|
||||
var length = roomClients[room].length;
|
||||
socketData.users.topics += length;
|
||||
|
||||
topTenTopics.push({tid: tid[1], count: length});
|
||||
} else if (room.match(/^category/)) {
|
||||
socketData.users.category += roomClients[room].length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
topTenTopics = topTenTopics.sort(function(a, b) {
|
||||
return b.count - a.count;
|
||||
}).slice(0, 10);
|
||||
|
||||
var topTenTids = topTenTopics.map(function(topic) {
|
||||
return topic.tid;
|
||||
});
|
||||
|
||||
topics.getTopicsFields(topTenTids, ['title'], function(err, titles) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
topTenTopics.forEach(function(topic, index) {
|
||||
socketData.topics[topic.tid] = {
|
||||
value: topic.count || 0,
|
||||
title: validator.escape(titles[index].title)
|
||||
};
|
||||
});
|
||||
|
||||
callback(null, socketData);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
module.exports = SocketMeta;
|
||||
|
||||
@@ -7,7 +7,6 @@ var meta = require('../meta'),
|
||||
async = require('async'),
|
||||
|
||||
server = require('./'),
|
||||
rooms = require('./rooms'),
|
||||
|
||||
SocketModules = {
|
||||
chats: {},
|
||||
@@ -105,37 +104,6 @@ SocketModules.chats.getRecentChats = function(socket, data, callback) {
|
||||
Messaging.getRecentChats(socket.uid, start, stop, callback);
|
||||
};
|
||||
|
||||
SocketModules.chats.sync = function(socket, data, callback) {
|
||||
var chats = [],
|
||||
uids = [],
|
||||
socketIds = rooms.clients('uid_' + socket.uid);
|
||||
|
||||
rooms.broadcast(socket, 'uid_' + socket.uid, 'query:chats.sync', {}, function(err, sessionData) {
|
||||
sessionData.forEach(function(data) {
|
||||
data.forEach(function(chat) {
|
||||
if (uids.indexOf(chat.uid) === -1) {
|
||||
chats.push(chat);
|
||||
uids.push(chat.uid);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
callback(err, chats);
|
||||
});
|
||||
};
|
||||
|
||||
SocketModules.chats.open = function(socket, data, callback) {
|
||||
rooms.broadcast(socket, 'uid_' + socket.uid, 'event:chats.open', data);
|
||||
};
|
||||
|
||||
SocketModules.chats.close = function(socket, data, callback) {
|
||||
rooms.broadcast(socket, 'uid_' + socket.uid, 'event:chats.close', data);
|
||||
};
|
||||
|
||||
SocketModules.chats.toggleNew = function(socket, data, callback) {
|
||||
rooms.broadcast(socket, 'uid_' + socket.uid, 'event:chats.toggleNew', data);
|
||||
};
|
||||
|
||||
|
||||
/* Sounds */
|
||||
SocketModules.sounds.getSounds = function(socket, data, callback) {
|
||||
|
||||
@@ -63,15 +63,14 @@ module.exports = function(SocketPosts) {
|
||||
|
||||
async.parallel({
|
||||
admins: async.apply(groups.getMembers, 'administrators', 0, -1),
|
||||
moderators: async.apply(groups.getMembers, 'cid:' + result.topic.cid + ':privileges:mods', 0, -1),
|
||||
uidsInTopic: async.apply(websockets.getUidsInRoom, 'topic_' + result.topic.tid)
|
||||
moderators: async.apply(groups.getMembers, 'cid:' + result.topic.cid + ':privileges:mods', 0, -1)
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return winston.error(err);
|
||||
}
|
||||
|
||||
var uids = results.uidsInTopic.filter(function(uid) {
|
||||
return (results.admins.indexOf(uid) !== -1 || results.moderators.indexOf(uid) !== -1) && parseInt(uid, 10) !== socket.uid;
|
||||
var uids = results.admins.concat(results.moderators).filter(function(uid, index, array) {
|
||||
return uid && array.indexOf(uid) === index;
|
||||
});
|
||||
|
||||
uids.forEach(function(uid) {
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
// Temp solution until
|
||||
// https://github.com/NodeBB/NodeBB/issues/2486
|
||||
// and
|
||||
// https://github.com/Automattic/socket.io/issues/1945
|
||||
// are closed.
|
||||
// Once they are closed switch to .clients() and async calls
|
||||
|
||||
|
||||
var pubsub = require('../pubsub'),
|
||||
async = require('async');
|
||||
|
||||
var rooms = {};
|
||||
|
||||
var clientRooms = {};
|
||||
var roomClients = {};
|
||||
|
||||
rooms.enter = function(socket, room) {
|
||||
socket.join(room);
|
||||
pubsub.publish('socket:join', {id: socket.id, room: room});
|
||||
};
|
||||
|
||||
rooms.leave = function(socket, room) {
|
||||
socket.leave(room);
|
||||
pubsub.publish('socket:leave', {id: socket.id, room: room});
|
||||
};
|
||||
|
||||
rooms.leaveAll = function(socket, roomsToLeave) {
|
||||
roomsToLeave.forEach(function(room) {
|
||||
rooms.leave(socket, room);
|
||||
});
|
||||
};
|
||||
|
||||
rooms.broadcast = function(socket, room, msg, data, callback) {
|
||||
var io = require('./'),
|
||||
socketIds = rooms.clients(room);
|
||||
|
||||
callback = callback || function() {};
|
||||
|
||||
// Filter out socketIds that aren't actually connected
|
||||
socketIds = socketIds.filter(function(id) {
|
||||
return io.server.sockets.connected.hasOwnProperty(id);
|
||||
});
|
||||
|
||||
async.map(socketIds, function(id, next) {
|
||||
var timeout,
|
||||
timeoutPassed = false;
|
||||
|
||||
if (socket.id === id) {
|
||||
return setImmediate(next, null, []);
|
||||
}
|
||||
|
||||
timeout = setTimeout(function() {
|
||||
timeoutPassed = true;
|
||||
next(null, []);
|
||||
}, 500);
|
||||
|
||||
io.server.sockets.connected[id].emit(msg, data || {}, function(err, returnData) {
|
||||
clearTimeout(timeout);
|
||||
if (!timeoutPassed) {
|
||||
next(null, returnData);
|
||||
}
|
||||
});
|
||||
}, callback);
|
||||
};
|
||||
|
||||
pubsub.on('socket:join', onSocketJoin);
|
||||
pubsub.on('socket:leave', onSocketLeave);
|
||||
|
||||
function onSocketJoin(data) {
|
||||
clientRooms[data.id] = clientRooms[data.id] || [];
|
||||
if (clientRooms[data.id].indexOf(data.room) === -1) {
|
||||
clientRooms[data.id].push(data.room);
|
||||
}
|
||||
|
||||
roomClients[data.room] = roomClients[data.room] || [];
|
||||
if (roomClients[data.room].indexOf(data.id) === -1) {
|
||||
roomClients[data.room].push(data.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function onSocketLeave(data) {
|
||||
var index;
|
||||
if (Array.isArray(clientRooms[data.id])) {
|
||||
index = clientRooms[data.id].indexOf(data.room);
|
||||
if (index !== -1) {
|
||||
clientRooms[data.id].splice(index, 1);
|
||||
if (!clientRooms[data.id].length) {
|
||||
delete clientRooms[data.id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(roomClients[data.room])) {
|
||||
index = roomClients[data.room].indexOf(data.id);
|
||||
if (index !== -1) {
|
||||
roomClients[data.room].splice(index, 1);
|
||||
if (!roomClients[data.room].length) {
|
||||
delete roomClients[data.room];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rooms.clients = function(room) {
|
||||
return Array.isArray(roomClients[room]) ? roomClients[room] : [];
|
||||
};
|
||||
|
||||
rooms.clientRooms = function(id) {
|
||||
return Array.isArray(clientRooms[id]) ? clientRooms[id] : [];
|
||||
};
|
||||
|
||||
rooms.socketCount = function() {
|
||||
return Object.keys(clientRooms || {}).length;
|
||||
};
|
||||
|
||||
rooms.roomClients = function() {
|
||||
return roomClients;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = rooms;
|
||||
|
||||
@@ -74,22 +74,6 @@ SocketTopics.post = function(socket, data, callback) {
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.enter = function(socket, tid, callback) {
|
||||
if (!parseInt(tid, 10) || !socket.uid) {
|
||||
return;
|
||||
}
|
||||
async.parallel({
|
||||
markAsRead: function(next) {
|
||||
SocketTopics.markAsRead(socket, [tid], next);
|
||||
},
|
||||
users: function(next) {
|
||||
websockets.getUsersInRoom(socket.uid, 'topic_' + tid, 0, 9, next);
|
||||
}
|
||||
}, function(err, result) {
|
||||
callback(err, result ? result.users : null);
|
||||
});
|
||||
};
|
||||
|
||||
SocketTopics.postcount = function(socket, tid, callback) {
|
||||
topics.getTopicField(tid, 'postcount', callback);
|
||||
};
|
||||
|
||||
@@ -8,15 +8,12 @@ module.exports = function(SocketUser) {
|
||||
if (!socket.uid) {
|
||||
return callback('[[error:invalid-uid]]');
|
||||
}
|
||||
var online = websockets.isUserOnline(uid);
|
||||
if (!online) {
|
||||
return callback(null, 'offline');
|
||||
}
|
||||
user.getUserField(uid, 'status', function(err, status) {
|
||||
|
||||
user.getUserFields(uid, ['lastonline', 'status'], function(err, userData) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
status = status || 'online';
|
||||
var status = user.getStatus(userData);
|
||||
callback(null, status);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -272,13 +272,13 @@ module.exports = function(Topics) {
|
||||
var tid = postData.tid;
|
||||
var uid = postData.uid;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
function (next) {
|
||||
Topics.markAsUnreadForAll(tid, next);
|
||||
},
|
||||
function(next) {
|
||||
function (next) {
|
||||
Topics.markAsRead([tid], uid, next);
|
||||
},
|
||||
function(next) {
|
||||
function (markedRead, next) {
|
||||
async.parallel({
|
||||
userInfo: function(next) {
|
||||
posts.getUserInfoForPosts([postData.uid], uid, next);
|
||||
@@ -294,7 +294,7 @@ module.exports = function(Topics) {
|
||||
}
|
||||
}, next);
|
||||
},
|
||||
function(results, next) {
|
||||
function (results, next) {
|
||||
postData.user = results.userInfo[0];
|
||||
postData.topic = results.topicInfo;
|
||||
|
||||
|
||||
@@ -161,52 +161,45 @@ module.exports = function(Topics) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
async.parallel({
|
||||
topicScores: function(next) {
|
||||
db.sortedSetScores('topics:recent', tids, next);
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
async.parallel({
|
||||
topicScores: async.apply(db.sortedSetScores, 'topics:recent', tids),
|
||||
userScores: async.apply(db.sortedSetScores, 'uid:' + uid + ':tids_read', tids)
|
||||
}, next);
|
||||
},
|
||||
userScores: function(next) {
|
||||
db.sortedSetScores('uid:' + uid + ':tids_read', tids, next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
function (results, next) {
|
||||
tids = tids.filter(function(tid, index) {
|
||||
return results.topicScores[index] && (!results.userScores[index] || results.userScores[index] < results.topicScores[index]);
|
||||
});
|
||||
|
||||
tids = tids.filter(function(tid, index) {
|
||||
return results.topicScores[index] && (!results.userScores[index] || results.userScores[index] < results.topicScores[index]);
|
||||
});
|
||||
|
||||
if (!tids.length) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
var scores = tids.map(function() {
|
||||
return now;
|
||||
});
|
||||
|
||||
async.parallel({
|
||||
markRead: function(next) {
|
||||
db.sortedSetAdd('uid:' + uid + ':tids_read', scores, tids, next);
|
||||
},
|
||||
topicData: function(next) {
|
||||
Topics.getTopicsFields(tids, ['cid'], next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
if (!tids.length) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var now = Date.now();
|
||||
var scores = tids.map(function() {
|
||||
return now;
|
||||
});
|
||||
|
||||
async.parallel({
|
||||
markRead: async.apply(db.sortedSetAdd, 'uid:' + uid + ':tids_read', scores, tids),
|
||||
topicData: async.apply( Topics.getTopicsFields, tids, ['cid'])
|
||||
}, next);
|
||||
},
|
||||
function (results, next) {
|
||||
var cids = results.topicData.map(function(topic) {
|
||||
return topic && topic.cid;
|
||||
}).filter(function(topic, index, array) {
|
||||
return topic && array.indexOf(topic) === index;
|
||||
});
|
||||
|
||||
categories.markAsRead(cids, uid, callback);
|
||||
});
|
||||
});
|
||||
categories.markAsRead(cids, uid, next);
|
||||
},
|
||||
function (next) {
|
||||
next(null, true);
|
||||
}
|
||||
], callback);
|
||||
};
|
||||
|
||||
Topics.markTopicNotificationsRead = function(tid, uid) {
|
||||
|
||||
25
src/user.js
25
src/user.js
@@ -1,12 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
var async = require('async'),
|
||||
nconf = require('nconf'),
|
||||
gravatar = require('gravatar'),
|
||||
|
||||
plugins = require('./plugins'),
|
||||
db = require('./database'),
|
||||
meta = require('./meta'),
|
||||
topics = require('./topics'),
|
||||
privileges = require('./privileges'),
|
||||
utils = require('../public/src/utils');
|
||||
@@ -91,7 +88,7 @@ var async = require('async'),
|
||||
};
|
||||
|
||||
User.getUsers = function(uids, uid, callback) {
|
||||
var fields = ['uid', 'username', 'userslug', 'picture', 'status', 'banned', 'joindate', 'postcount', 'reputation', 'email:confirmed'];
|
||||
var fields = ['uid', 'username', 'userslug', 'picture', 'status', 'banned', 'joindate', 'postcount', 'reputation', 'email:confirmed', 'lastonline'];
|
||||
plugins.fireHook('filter:users.addFields', {fields: fields}, function(err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
@@ -105,9 +102,6 @@ var async = require('async'),
|
||||
},
|
||||
isAdmin: function(next) {
|
||||
User.isAdministrator(uids, next);
|
||||
},
|
||||
isOnline: function(next) {
|
||||
require('./socket.io').isUsersOnline(uids, next);
|
||||
}
|
||||
}, function(err, results) {
|
||||
if (err) {
|
||||
@@ -118,7 +112,7 @@ var async = require('async'),
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
user.status = User.getStatus(user.status, results.isOnline[index]);
|
||||
user.status = User.getStatus(user);
|
||||
user.joindateISO = utils.toISOString(user.joindate);
|
||||
user.administrator = results.isAdmin[index];
|
||||
user.banned = parseInt(user.banned, 10) === 1;
|
||||
@@ -135,8 +129,19 @@ var async = require('async'),
|
||||
});
|
||||
};
|
||||
|
||||
User.getStatus = function(status, isOnline) {
|
||||
return isOnline ? (status || 'online') : 'offline';
|
||||
User.getStatus = function(userData) {
|
||||
var isOnline = Date.now() - parseInt(userData.lastonline, 10) < 300000;
|
||||
return isOnline ? (userData.status || 'online') : 'offline';
|
||||
};
|
||||
|
||||
User.isOnline = function(uid, callback) {
|
||||
db.sortedSetScore('users:online', uid, function(err, lastonline) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
var isOnline = Date.now() - parseInt(lastonline, 10) < 300000;
|
||||
callback(null, isOnline);
|
||||
});
|
||||
};
|
||||
|
||||
User.exists = function(uid, callback) {
|
||||
|
||||
@@ -98,29 +98,16 @@ module.exports = function(User) {
|
||||
function filterAndSortUids(uids, data, callback) {
|
||||
var sortBy = data.sortBy || 'joindate';
|
||||
|
||||
var fields = ['uid', 'status', sortBy];
|
||||
var fields = ['uid', 'status', 'lastonline', sortBy];
|
||||
|
||||
async.parallel({
|
||||
userData: function(next) {
|
||||
User.getUsersFields(uids, fields, next);
|
||||
},
|
||||
isOnline: function(next) {
|
||||
if (data.onlineOnly) {
|
||||
require('../socket.io').isUsersOnline(uids, next);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
}, function(err, results) {
|
||||
User.getUsersFields(uids, fields, function(err, userData) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
var userData = results.userData;
|
||||
|
||||
if (data.onlineOnly) {
|
||||
userData = userData.filter(function(user, index) {
|
||||
return user && user.status !== 'offline' && results.isOnline[index];
|
||||
userData = userData.filter(function(user) {
|
||||
return user && user.status !== 'offline' && (Date.now() - parseInt(user.lastonline, 10) < 300000);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user