Merge branch 'socketAL-fix'

v1.18.x
Julian Lam 11 years ago
commit 51abf60b3a

@ -36,7 +36,7 @@ var socket,
app.uid = data.uid;
app.showLoginMessage();
socket.emit('api:meta.updateHeader', {
socket.emit('meta.updateHeader', {
fields: ['username', 'picture', 'userslug']
}, app.updateHeader);
});
@ -77,14 +77,14 @@ var socket,
}
app.enterRoom(room, true);
socket.emit('api:meta.reconnected');
socket.emit('meta.reconnected');
setTimeout(function() {
reconnectEl.removeClass('active').addClass("hide");
}, 3000);
}
socket.emit('api:meta.updateHeader', {
socket.emit('meta.updateHeader', {
fields: ['username', 'picture', 'userslug']
}, app.updateHeader);
});
@ -122,6 +122,8 @@ var socket,
setTimeout(app.logout, 1000);
});
socket.on('meta.updateHeader', app.updateHeader);
app.enterRoom('global');
}
},
@ -235,7 +237,7 @@ var socket,
return;
}
socket.emit('api:meta.rooms.enter', {
socket.emit('meta.rooms.enter', {
'enter': room,
'leave': app.currentRoom
});
@ -248,42 +250,22 @@ var socket,
var uids = [];
jQuery('.post-row').each(function () {
uids.push(this.getAttribute('data-uid'));
var uid = $(this).attr('data-uid');
if(uids.indexOf(uid) === -1) {
uids.push(uid);
}
});
socket.emit('api:user.get_online_users', uids, function (users) {
jQuery('a.username-field').each(function () {
if (this.processed === true)
return;
var el = jQuery(this),
uid = el.parents('li').attr('data-uid');
if (uid && jQuery.inArray(uid, users) !== -1) {
el.find('i').remove();
el.prepend('<i class="fa fa-circle"></i>');
} else {
el.find('i').remove();
el.prepend('<i class="fa fa-circle-o"></i>');
}
el.processed = true;
});
jQuery('button .username-field').each(function () {
//DRY FAIL
if (this.processed === true)
return;
socket.emit('user.getOnlineUsers', uids, function (err, users) {
jQuery('button .username-field').each(function (index, element) {
var el = jQuery(this),
uid = el.parents('li').attr('data-uid');
if (uid && jQuery.inArray(uid, users) !== -1) {
el.parent().addClass('btn-success');
el.parent().addClass('btn-success').removeClass('btn-danger');
} else {
el.parent().addClass('btn-danger');
el.parent().addClass('btn-danger').removeClass('btn-success');
}
el.processed = true;
});
});
};
@ -419,6 +401,7 @@ var socket,
interval: undefined,
titles: []
};
app.alternatingTitle = function (title) {
if (typeof title !== 'string') {
return;
@ -449,13 +432,13 @@ var socket,
url = a.pathname.slice(1);
}
socket.emit('api:meta.buildTitle', url, function(title, numNotifications) {
socket.emit('meta.buildTitle', url, function(err, title, numNotifications) {
titleObj.titles[0] = (numNotifications > 0 ? '(' + numNotifications + ') ' : '') + title;
app.alternatingTitle('');
});
};
app.updateHeader = function(data) {
app.updateHeader = function(err, data) {
$('#search-button').off().on('click', function(e) {
e.stopPropagation();
$('#search-fields').removeClass('hide').show();

@ -35,31 +35,31 @@ define(['forum/accountheader'], function(header) {
}
followBtn.on('click', function() {
socket.emit('api:user.follow', {
socket.emit('user.follow', {
uid: theirid
}, function(success) {
if (success) {
followBtn.addClass('hide');
unfollowBtn.removeClass('hide');
app.alertSuccess('You are now following ' + username + '!');
} else {
app.alertError('There was an error following' + username + '!');
}, function(err) {
if(err) {
return app.alertError('There was an error following' + username + '!');
}
followBtn.addClass('hide');
unfollowBtn.removeClass('hide');
app.alertSuccess('You are now following ' + username + '!');
});
return false;
});
unfollowBtn.on('click', function() {
socket.emit('api:user.unfollow', {
socket.emit('user.unfollow', {
uid: theirid
}, function(success) {
if (success) {
followBtn.removeClass('hide');
unfollowBtn.addClass('hide');
app.alertSuccess('You are no longer following ' + username + '!');
} else {
app.alertError('There was an error unfollowing ' + username + '!');
}, function(err) {
if(err) {
return app.alertError('There was an error unfollowing ' + username + '!');
}
followBtn.removeClass('hide');
unfollowBtn.addClass('hide');
app.alertSuccess('You are no longer following ' + username + '!');
});
return false;
});
@ -72,9 +72,9 @@ define(['forum/accountheader'], function(header) {
ajaxify.go($(this).attr('topic-url'));
});
socket.on('api:user.isOnline', Account.handleUserOnline);
socket.on('user.isOnline', Account.handleUserOnline);
socket.emit('api:user.isOnline', theirid, Account.handleUserOnline);
socket.emit('user.isOnline', theirid, Account.handleUserOnline);
socket.on('event:new_post', function(data) {
var html = templates.prepare(templates['account'].blocks['posts']).parse(data);
@ -85,7 +85,7 @@ define(['forum/accountheader'], function(header) {
});
};
Account.handleUserOnline = function(data) {
Account.handleUserOnline = function(err, data) {
var onlineStatus = $('.account-online-status');
if (data.online) {

@ -24,7 +24,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
signature: $('#inputSignature').val()
};
socket.emit('api:user.updateProfile', userData, function(err, data) {
socket.emit('user.updateProfile', userData, function(err, data) {
if (data.success) {
app.alertSuccess('Your profile has been updated successfully!');
if (data.picture) {
@ -36,7 +36,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
gravatarPicture = data.gravatarpicture;
}
} else {
app.alertError('There was an error updating your profile! ' + err.error);
app.alertError('There was an error updating your profile! ' + err.message);
}
});
return false;
@ -108,7 +108,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
uploadedPicture = imageUrlOnServer;
socket.emit('api:meta.updateHeader', {
socket.emit('meta.updateHeader', {
fields: ['username', 'picture', 'userslug']
}, app.updateHeader);
});
@ -174,7 +174,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
$('#changePasswordBtn').on('click', function() {
if (passwordvalid && passwordsmatch && currentPassword.val()) {
socket.emit('api:user.changePassword', {
socket.emit('user.changePassword', {
'currentPassword': currentPassword.val(),
'newPassword': password.val()
}, function(err) {
@ -186,7 +186,7 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
passwordvalid = false;
if (err) {
app.alertError(err.error);
app.alertError(err.message);
return;
}
@ -206,9 +206,9 @@ define(['forum/accountheader', 'uploader'], function(header, uploader) {
type: type
};
socket.emit('api:user.changePicture', userData, function(success) {
if (!success) {
app.alertError('There was an error changing picture!');
socket.emit('user.changePicture', userData, function(err) {
if(err) {
app.alertError(err.message);
}
});
}

@ -10,12 +10,11 @@ define(['forum/accountheader'], function(header) {
showemail: $('#showemailCheckBox').is(':checked') ? 1 : 0
};
socket.emit('api:user.saveSettings', settings, function(err) {
if (!err) {
app.alertSuccess('Settings saved!');
} else {
app.alertError('There was an error saving settings!');
socket.emit('user.saveSettings', settings, function(err) {
if (err) {
return app.alertError('There was an error saving settings!');
}
app.alertSuccess('Settings saved!');
});
return false;
});

@ -13,7 +13,7 @@ define(['uploader'], function(uploader) {
}
function save() {
socket.emit('api:admin.categories.update', modified_categories);
socket.emit('admin.categories.update', modified_categories);
modified_categories = {};
}
@ -86,23 +86,26 @@ define(['uploader'], function(uploader) {
order: $('.admin-categories #entry-container').children().length + 1
};
socket.emit('api:admin.categories.create', category, function(err, data) {
if (!err) {
app.alert({
alert_id: 'category_created',
title: 'Created',
message: 'Category successfully created!',
type: 'success',
timeout: 2000
});
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
categories: [data]
});
$('#entry-container').append(html);
$('#new-category-modal').modal('hide');
socket.emit('admin.categories.create', category, function(err, data) {
if(err) {
return app.alertError(err.message);
}
app.alert({
alert_id: 'category_created',
title: 'Created',
message: 'Category successfully created!',
type: 'success',
timeout: 2000
});
var html = templates.prepare(templates['admin/categories'].blocks['categories']).parse({
categories: [data]
});
$('#entry-container').append(html);
$('#new-category-modal').modal('hide');
});
}
@ -223,7 +226,14 @@ define(['uploader'], function(uploader) {
clearTimeout(searchDelay);
searchDelay = setTimeout(function() {
socket.emit('api:admin.categories.search', searchEl.value, cid, function(err, results) {
socket.emit('admin.categories.search', {
username: searchEl.value,
cid: cid
}, function(err, results) {
if(err) {
return app.alertError(err.message);
}
var numResults = results.length,
resultObj;
for(var x=0;x<numResults;x++) {
@ -254,7 +264,12 @@ define(['uploader'], function(uploader) {
privilege = this.getAttribute('data-priv');
e.preventDefault();
socket.emit('api:admin.categories.setPrivilege', cid, uid, privilege, !btnEl.hasClass('active'), function(err, privileges) {
socket.emit('admin.categories.setPrivilege', {
cid: cid,
uid: uid,
privilege: privilege,
set: !btnEl.hasClass('active')
}, function(err, privileges) {
btnEl.toggleClass('active', privileges[privilege]);
Categories.refreshPrivilegeList(cid);
@ -267,7 +282,10 @@ define(['uploader'], function(uploader) {
});
// User Groups and privileges
socket.emit('api:admin.categories.groupsList', cid, function(err, results) {
socket.emit('admin.categories.groupsList', cid, function(err, results) {
if(err) {
return app.alertError(err.message);
}
var groupsFrag = document.createDocumentFragment(),
numResults = results.length,
trEl = document.createElement('tr'),
@ -295,7 +313,12 @@ define(['uploader'], function(uploader) {
gid = btnEl.parents('tr[data-gid]').attr('data-gid'),
privilege = this.getAttribute('data-gpriv');
e.preventDefault();
socket.emit('api:admin.categories.setGroupPrivilege', cid, gid, privilege, !btnEl.hasClass('active'), function(err) {
socket.emit('admin.categories.setGroupPrivilege', {
cid: cid,
gid: gid,
privilege: privilege,
set: !btnEl.hasClass('active')
}, function(err) {
if (!err) {
btnEl.toggleClass('active');
}
@ -309,7 +332,7 @@ define(['uploader'], function(uploader) {
var modalEl = $('#category-permissions-modal'),
readMembers = modalEl.find('#category-permissions-read'),
writeMembers = modalEl.find('#category-permissions-write');
socket.emit('api:admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
socket.emit('admin.categories.getPrivilegeSettings', cid, function(err, privilegeList) {
var readLength = privilegeList['+r'].length,
writeLength = privilegeList['+w'].length,
readFrag = document.createDocumentFragment(),

@ -15,6 +15,15 @@ jQuery('document').ready(function() {
}, false);
});
socket.emit('api:admin.config.get', function(config) {
socket.emit('admin.config.get', function(err, config) {
if(err) {
return app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Error',
message: 'NodeBB encountered a problem getting config',
type: 'danger'
});
}
app.config = config;
});

@ -29,7 +29,7 @@ define(function() {
errorEl = $('#create-modal-error'),
errorText;
socket.emit('api:admin.groups.create', submitObj, function(err, data) {
socket.emit('admin.groups.create', submitObj, function(err, data) {
if (err) {
switch (err) {
case 'group-exists':
@ -63,14 +63,19 @@ define(function() {
case 'delete':
bootbox.confirm('Are you sure you wish to delete this group?', function(confirm) {
if (confirm) {
socket.emit('api:admin.groups.delete', gid, function(err, data) {
if (data === 'OK') ajaxify.go('admin/groups');
socket.emit('admin.groups.delete', gid, function(err, data) {
console.log(err, data);
if(err) {
return app.alertError(err.message);
}
ajaxify.go('admin/groups');
});
}
});
break;
case 'members':
socket.emit('api:admin.groups.get', gid, function(err, groupObj) {
socket.emit('admin.groups.get', gid, function(err, groupObj) {
var formEl = detailsModal.find('form'),
nameEl = formEl.find('#change-group-name'),
descEl = formEl.find('#change-group-desc'),
@ -120,7 +125,7 @@ define(function() {
foundUserImg = foundUser.getElementsByTagName('img')[0];
foundUserLabel = foundUser.getElementsByTagName('span')[0];
socket.emit('api:admin.user.search', searchText, function(err, results) {
socket.emit('admin.user.search', searchText, function(err, results) {
if (!err && results && results.length > 0) {
var numResults = results.length,
resultsSlug = document.createDocumentFragment(),
@ -152,7 +157,7 @@ define(function() {
});
if (members.indexOf(uid) === -1) {
socket.emit('api:admin.groups.join', {
socket.emit('admin.groups.join', {
gid: gid,
uid: uid
}, function(err, data) {
@ -167,7 +172,7 @@ define(function() {
var uid = this.getAttribute('data-uid'),
gid = detailsModal.attr('data-gid');
socket.emit('api:admin.groups.leave', {
socket.emit('admin.groups.leave', {
gid: gid,
uid: uid
}, function(err, data) {
@ -183,7 +188,7 @@ define(function() {
descEl = formEl.find('#change-group-desc'),
gid = detailsModal.attr('data-gid');
socket.emit('api:admin.groups.update', {
socket.emit('admin.groups.update', {
gid: gid,
values: {
name: nameEl.val(),

@ -2,10 +2,10 @@ define(function() {
var Admin = {};
Admin.init = function() {
ajaxify.register_events(['api:meta.rooms.getAll']);
ajaxify.register_events(['meta.rooms.getAll']);
app.enterRoom('admin');
socket.emit('api:meta.rooms.getAll', Admin.updateRoomUsage);
socket.emit('meta.rooms.getAll', Admin.updateRoomUsage);
socket.on('event:meta.rooms.update', Admin.updateRoomUsage);
$('#logout-link').on('click', function() {
@ -17,15 +17,15 @@ define(function() {
})
};
Admin.updateRoomUsage = function(data) {
console.log('room usage updating', data);
Admin.updateRoomUsage = function(err, data) {
console.log(arguments);
var active_users = document.getElementById('active_users'),
total = 0;
active_users.innerHTML = '';
for (var room in data) {
if (room !== '') {
var count = data[room].length;
var count = $(data[room]).length;
total += count;
active_users.innerHTML = active_users.innerHTML + "<div class='alert alert-success'><strong>" + room + "</strong> " + count + " active user" + (count > 1 ? "s" : "") + "</div>";
}

@ -8,10 +8,10 @@ define(function() {
if (numPlugins > 0) {
pluginsList.on('click', 'button[data-action="toggleActive"]', function() {
pluginID = $(this).parents('li').attr('data-plugin-id');
socket.emit('api:admin.plugins.toggle', pluginID);
socket.emit('admin.plugins.toggle', pluginID);
});
socket.on('api:admin.plugins.toggle', function(status) {
socket.on('admin.plugins.toggle', function(status) {
pluginTgl = document.querySelector('.plugins li[data-plugin-id="' + status.id + '"] button');
pluginTgl.innerHTML = '<i class="fa fa-power-off"></i> ' + (status.active ? 'Dea' : 'A') + 'ctivate';

@ -70,20 +70,12 @@ define(['uploader'], function(uploader) {
value = fields[x].value;
}
socket.emit('api:admin.config.set', {
socket.emit('admin.config.set', {
key: key,
value: value
}, function(data) {
if (data.status === 'ok') {
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Saved',
message: 'Your changes to the NodeBB configuration have been saved.',
type: 'success'
});
} else {
app.alert({
}, function(err) {
if(err) {
return app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Not Saved',
@ -91,6 +83,15 @@ define(['uploader'], function(uploader) {
type: 'danger'
});
}
app.alert({
alert_id: 'config_status',
timeout: 2500,
title: 'Changes Saved',
message: 'Your changes to the NodeBB configuration have been saved.',
type: 'success'
});
});
}
});
@ -119,7 +120,7 @@ define(['uploader'], function(uploader) {
};
Settings.remove = function(key) {
socket.emit('api:admin.config.remove', key);
socket.emit('admin.config.remove', key);
};
return Settings;

@ -23,7 +23,7 @@ define(function() {
cssSrc = parentEl.attr('data-css'),
themeId = parentEl.attr('data-theme');
socket.emit('api:admin.themes.set', {
socket.emit('admin.themes.set', {
type: themeType,
id: themeId,
src: cssSrc
@ -47,7 +47,7 @@ define(function() {
revertEl.addEventListener('click', function() {
bootbox.confirm('Are you sure you wish to remove the custom theme and restore the NodeBB default theme?', function(confirm) {
if (confirm) {
socket.emit('api:admin.themes.set', {
socket.emit('admin.themes.set', {
type: 'local',
id: 'nodebb-theme-cerulean'
}, function(err) {
@ -64,7 +64,11 @@ define(function() {
}, false);
// Installed Themes
socket.emit('api:admin.themes.getInstalled', function(themes) {
socket.emit('admin.themes.getInstalled', function(err, themes) {
if(err) {
return app.alertError(err.message);
}
var instListEl = document.getElementById('installed_themes'),
themeFrag = document.createDocumentFragment(),
liEl = document.createElement('li');

@ -15,37 +15,25 @@ define(function() {
switch (action) {
case 'pin':
if (!$this.hasClass('active')) {
socket.emit('api:topics.pin', {
tid: tid
}, Topics.pin);
socket.emit('topics.pin', tid, Topics.pin);
} else {
socket.emit('api:topics.unpin', {
tid: tid
}, Topics.unpin);
socket.emit('topics.unpin', tid, Topics.unpin);
}
break;
case 'lock':
if (!$this.hasClass('active')) {
socket.emit('api:topics.lock', {
tid: tid
}, Topics.lock);
socket.emit('topics.lock', tid, Topics.lock);
} else {
socket.emit('api:topics.unlock', {
tid: tid
}, Topics.unlock);
socket.emit('topics.unlock', tid, Topics.unlock);
}
break;
case 'delete':
if (!$this.hasClass('active')) {
socket.emit('api:topics.delete', {
tid: tid
}, Topics.setDeleted);
socket.emit('topics.delete', tid, Topics.setDeleted);
} else {
socket.emit('api:topics.restore', {
tid: tid
}, Topics.restore);
socket.emit('topics.restore', tid, Topics.restore);
}
break;
@ -63,13 +51,16 @@ define(function() {
var lastTid = parseInt(topics[topics.length - 1].getAttribute('data-tid'));
this.innerHTML = '<i class="fa fa-refresh fa-spin"></i> Retrieving topics';
socket.emit('api:admin.topics.getMore', {
socket.emit('admin.topics.getMore', {
limit: 10,
after: lastTid
}, function(topics) {
}, function(err, topics) {
if(err) {
return app.alertError(err.message);
}
var btnEl = document.getElementById('topics_loadmore');
topics = JSON.parse(topics);
if (topics.length > 0) {
var html = templates.prepare(templates['admin/topics'].blocks['topics']).parse({
topics: topics
@ -116,8 +107,12 @@ define(function() {
}
}
Topics.setDeleted = function(response) {
if (response.status === 'ok') {
Topics.setDeleted = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).addClass('active');
@ -125,8 +120,12 @@ define(function() {
}
};
Topics.restore = function(response) {
if (response.status === 'ok') {
Topics.restore = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="delete"]');
$(btnEl).removeClass('active');
@ -134,16 +133,24 @@ define(function() {
}
};
Topics.lock = function(response) {
if (response.status === 'ok') {
Topics.lock = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).addClass('active');
}
};
Topics.unlock = function(response) {
if (response.status === 'ok') {
Topics.unlock = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="lock"]');
$(btnEl).removeClass('active');
@ -151,16 +158,24 @@ define(function() {
};
Topics.unpin = function(response) {
if (response.status === 'ok') {
Topics.unpin = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).removeClass('active');
}
};
Topics.pin = function(response) {
if (response.status === 'ok') {
Topics.pin = function(err, response) {
if(err) {
return app.alert(err.message);
}
if (response && response.tid) {
var btnEl = document.querySelector('li[data-tid="' + response.tid + '"] button[data-action="pin"]');
$(btnEl).addClass('active');

@ -68,14 +68,14 @@ define(function() {
if (!isAdmin) {
if (isBanned) {
socket.emit('api:admin.user.unbanUser', uid);
socket.emit('admin.user.unbanUser', uid);
banBtn.removeClass('btn-warning');
parent.attr('data-banned', 0);
updateUserAdminButtons();
} else {
bootbox.confirm('Do you really want to ban "' + parent.attr('data-username') + '"?', function(confirm) {
if (confirm) {
socket.emit('api:admin.user.banUser', uid);
socket.emit('admin.user.banUser', uid);
banBtn.addClass('btn-warning');
parent.attr('data-banned', 1);
updateUserAdminButtons();
@ -103,7 +103,7 @@ define(function() {
});
}
else if (!isAdmin) {
socket.emit('api:admin.user.makeAdmin', uid);
socket.emit('admin.user.makeAdmin', uid);
adminBtn.attr('value', 'UnMake Admin').html('Remove Admin');
parent.attr('data-admin', 1);
updateUserBanButtons();
@ -111,7 +111,7 @@ define(function() {
} else if(uid !== yourid) {
bootbox.confirm('Do you really want to remove this user as admin "' + parent.attr('data-username') + '"?', function(confirm) {
if (confirm) {
socket.emit('api:admin.user.removeAdmin', uid);
socket.emit('admin.user.removeAdmin', uid);
adminBtn.attr('value', 'Make Admin').html('Make Admin');
parent.attr('data-admin', 0);
updateUserBanButtons();
@ -126,16 +126,19 @@ define(function() {
}
function handleUserCreate() {
var errorEl = $('#create-modal-error');
$('#createUser').on('click', function() {
$('#create-modal').modal('show');
$('#create-modal form')[0].reset();
errorEl.addClass('hide');
});
$('#create-modal-go').on('click', function() {
var username = $('#create-user-name').val(),
email = $('#create-user-email').val(),
password = $('#create-user-password').val(),
passwordAgain = $('#create-user-password-again').val(),
errorEl = $('#create-modal-error');
passwordAgain = $('#create-user-password-again').val();
if(password !== passwordAgain) {
return errorEl.html('<strong>Error</strong><p>Passwords must match!</p>').removeClass('hide');
@ -147,13 +150,15 @@ define(function() {
password: password
};
socket.emit('api:admin.user.createUser', user, function(err, data) {
socket.emit('admin.user.createUser', user, function(err) {
if(err) {
return errorEl.html('<strong>Error</strong><p>' + err + '</p>').removeClass('hide');
return errorEl.html('<strong>Error</strong><p>' + err.message + '</p>').removeClass('hide');
}
$('#create-modal').modal('hide');
$('#create-modal').on('hidden.bs.modal', function() {
ajaxify.go('admin/users');
});
app.alertSuccess('User created!');
ajaxify.go('admin/users');
});
});
@ -188,10 +193,10 @@ define(function() {
jQuery('.fa-spinner').removeClass('none');
socket.emit('api:admin.user.search', username, function(err, data) {
socket.emit('admin.user.search', username, function(err, data) {
if(err) {
return app.alertError(err.message);
}
}console.log(data)
var html = templates.prepare(templates['admin/users'].blocks['users']).parse({
users: data
@ -242,11 +247,11 @@ define(function() {
if (set) {
loadingMoreUsers = true;
socket.emit('api:user.loadMore', {
socket.emit('user.loadMore', {
set: set,
after: $('#users-container').children().length
}, function(data) {
if (data.users.length) {
}, function(err, data) {
if (data && data.users.length) {
onUsersLoaded(data.users);
}
loadingMoreUsers = false;

@ -40,7 +40,7 @@ define(['composer'], function(composer) {
socket.on('event:new_topic', Category.onNewTopic);
socket.emit('api:categories.getRecentReplies', cid, renderRecentReplies);
socket.emit('categories.getRecentReplies', cid, renderRecentReplies);
$(window).off('scroll').on('scroll', function (ev) {
var bottom = ($(document).height() - $(window).height()) * 0.9;
@ -81,7 +81,7 @@ define(['composer'], function(composer) {
}
topic.hide().fadeIn('slow');
socket.emit('api:categories.getRecentReplies', templates.get('category_id'), renderRecentReplies);
socket.emit('categories.getRecentReplies', templates.get('category_id'), renderRecentReplies);
addActiveUser(data);
@ -129,19 +129,23 @@ define(['composer'], function(composer) {
}
loadingMoreTopics = true;
socket.emit('api:categories.loadMore', {
socket.emit('categories.loadMore', {
cid: cid,
after: $('#topics-container').children('.category-item').length
}, function (data) {
if (data.topics.length) {
}, function (err, data) {
if(err) {
return app.alertError(err.message);
}
if (data && data.topics.length) {
Category.onTopicsLoaded(data.topics);
}
loadingMoreTopics = false;
});
}
function renderRecentReplies(posts) {
if (!posts || posts.length === 0) {
function renderRecentReplies(err, posts) {
if (err || !posts || posts.length === 0) {
return;
}

@ -1,6 +1,6 @@
define(['notifications', 'chat'], function(Notifications, Chat) {
socket.emit('api:meta.updateHeader', {
socket.emit('meta.updateHeader', {
fields: ['username', 'picture', 'userslug']
}, app.updateHeader);
@ -8,11 +8,11 @@ define(['notifications', 'chat'], function(Notifications, Chat) {
Chat.prepareDOM();
translator.prepareDOM();
function updateUnreadCount(count) {
function updateUnreadCount(err, count) {
$('#unread-count').toggleClass('unread-count', count > 0);
$('#unread-count').attr('data-content', count > 20 ? '20+' : count);
}
socket.on('event:unread.updateCount', updateUnreadCount);
socket.emit('api:user.getUnreadCount', updateUnreadCount);
socket.emit('user.getUnreadCount', updateUnreadCount);
});

@ -4,23 +4,32 @@ define(function() {
home.init = function() {
ajaxify.register_events([
'api:user.count',
'post.stats',
'api:user.getActiveUsers'
'user.count',
'meta.getUsageStats',
'user.getActiveUsers'
]);
socket.emit('api:user.count', function(data) {
socket.emit('user.count', updateUserCount);
socket.on('user.count', updateUserCount);
function updateUserCount(err, data) {
$('#stats_users').html(utils.makeNumberHumanReadable(data.count)).attr('title', data.count);
});
}
socket.emit('meta.getUsageStats', updateUsageStats);
socket.on('meta.getUsageStats', updateUsageStats);
socket.emit('api:meta.getUsageStats', function(data) {
function updateUsageStats(err, data) {
$('#stats_topics').html(utils.makeNumberHumanReadable(data.topics)).attr('title', data.topics);
$('#stats_posts').html(utils.makeNumberHumanReadable(data.posts)).attr('title', data.posts);
});
}
socket.emit('user.getActiveUsers', updateActiveUsers);
socket.on('user.getActiveUsers', updateActiveUsers);
socket.emit('api:user.getActiveUsers', function(data) {
function updateActiveUsers(err, data) {
$('#stats_online').html(data.users);
});
}
}
return home;

@ -84,7 +84,7 @@ define(function() {
var html = templates.prepare(templates['recent'].blocks['topics']).parse({
topics: topics
});
translator.translate(html, function(translatedHTML) {
var container = $('#topics-container');
@ -99,10 +99,13 @@ define(function() {
Recent.loadMoreTopics = function() {
Recent.loadingMoreTopics = true;
socket.emit('api:topics.loadMoreRecentTopics', {
socket.emit('topics.loadMoreRecentTopics', {
after: $('#topics-container').children('li').length,
term: active
}, function(data) {
}, function(err, data) {
if(err) {
return app.alertError(err.message);
}
if (data.topics && data.topics.length) {
Recent.onTopicsLoaded(data.topics);
}

@ -42,10 +42,14 @@ define(function() {
if (!utils.isEmailValid(emailEl.val())) {
showError(email_notify, 'Invalid email address.');
} else {
socket.emit('api:user.emailExists', {
socket.emit('user.emailExists', {
email: emailEl.val()
}, function(exists) {
if (exists === true) {
}, function(err, exists) {
if(err) {
return app.alertError(err.message);
}
if (exists) {
showError(email_notify, 'Email address already taken!');
} else {
showSuccess(email_notify, successIcon);
@ -71,8 +75,18 @@ define(function() {
} else if (!utils.isUserNameValid(username.val()) || !utils.slugify(username.val())) {
showError(username_notify, 'Invalid username!');
} else {
socket.emit('api:user.exists', {
socket.emit('user.exists', {
username: username.val()
}, function(err, exists) {
if(err) {
return app.alertError(err.message);
}
if (exists) {
showError(username_notify, 'Username already taken!');
} else {
showSuccess(username_notify, successIcon);
}
});
}
}
@ -80,6 +94,7 @@ define(function() {
username.on('keyup', function() {
jQuery('#yourUsername').html(this.value.length > 0 ? this.value : 'username');
});
username.on('blur', function() {
validateUsername();
});
@ -123,16 +138,6 @@ define(function() {
validatePasswordConfirm();
});
ajaxify.register_events(['api:user.exists', 'api:user.emailExists']);
socket.on('api:user.exists', function(data) {
if (data.exists === true) {
showError(username_notify, 'Username already taken!');
} else {
showSuccess(username_notify, successIcon);
}
});
function validateForm() {
validationError = false;

@ -8,8 +8,19 @@ define(function() {
document.getElementById('reset').onclick = function() {
if (inputEl.value.length > 0 && inputEl.value.indexOf('@') !== -1) {
socket.emit('api:user.reset.send', {
socket.emit('user.reset.send', {
email: inputEl.value
}, function(err, data) {
if(err) {
return app.alertError(err.message);
}
var submitEl = document.getElementById('reset');
jQuery('#error').hide();
jQuery('#success').show();
jQuery('#success p').html('An email has been dispatched to "' + inputEl.value + '" with instructions on setting a new password.');
inputEl.value = '';
});
} else {
jQuery('#success').hide();
@ -17,30 +28,6 @@ define(function() {
errorTextEl.innerHTML = 'Please enter a valid email';
}
};
ajaxify.register_events(['user.send_reset']);
socket.on('user.send_reset', function(data) {
var submitEl = document.getElementById('reset');
if (data.status === 'ok') {
jQuery('#error').hide();
jQuery('#success').show();
jQuery('#success p').html('An email has been dispatched to "' + data.email + '" with instructions on setting a new password.');
inputEl.value = '';
} else {
jQuery('#success').hide();
jQuery(errorEl).show();
switch (data.message) {
case 'invalid-email':
errorTextEl.innerHTML = 'The email you put in (<span>' + data.email + '</span>) is not registered with us. Please try again.';
break;
case 'send-failed':
errorTextEl.innerHTML = 'There was a problem sending the reset code. Please try again later.';
break;
}
}
});
};
return ResetPassword;

@ -21,36 +21,37 @@ define(function() {
noticeEl.querySelector('p').innerHTML = 'The two passwords you\'ve entered do not match.';
noticeEl.style.display = 'block';
} else {
socket.emit('api:user.reset.commit', {
socket.emit('user.reset.commit', {
code: reset_code,
password: password.value
}, function(err) {
if(err) {
return app.alert(err.message);
}
$('#error').hide();
$('#notice').hide();
$('#success').show();
});
}
}, false);
// Enable the form if the code is valid
socket.emit('api:user.reset.valid', {
socket.emit('user.reset.valid', {
code: reset_code
});
}, function(err, valid) {
if(err) {
return app.alertError(err.message);
}
ajaxify.register_events(['api:user.reset.valid', 'api:user.reset.commit']);
socket.on('api:user.reset.valid', function(data) {
if ( !! data.valid) resetEl.disabled = false;
else {
if (valid) {
resetEl.disabled = false;
} else {
var formEl = document.getElementById('reset-form');
// Show error message
$('#error').show();
formEl.parentNode.removeChild(formEl);
}
})
socket.on('api:user.reset.commit', function(data) {
if (data.status === 'ok') {
$('#error').hide();
$('#notice').hide();
$('#success').show();
}
});
};

@ -52,16 +52,14 @@ define(['composer'], function(composer) {
if (thread_state.deleted !== '1') {
bootbox.confirm('Are you sure you want to delete this thread?', function(confirm) {
if (confirm) {
socket.emit('api:topics.delete', {
tid: tid
}, null);
socket.emit('topics.delete', tid);
}
});
} else {
bootbox.confirm('Are you sure you want to restore this thread?', function(confirm) {
if (confirm) socket.emit('api:topics.restore', {
tid: tid
}, null);
if (confirm) {
socket.emit('topics.restore', tid);
}
});
}
return false;
@ -69,26 +67,18 @@ define(['composer'], function(composer) {
$('.lock_thread').on('click', function(e) {
if (thread_state.locked !== '1') {
socket.emit('api:topics.lock', {
tid: tid
}, null);
socket.emit('topics.lock', tid);
} else {
socket.emit('api:topics.unlock', {
tid: tid
}, null);
socket.emit('topics.unlock', tid);
}
return false;
});
$('.pin_thread').on('click', function(e) {
if (thread_state.pinned !== '1') {
socket.emit('api:topics.pin', {
tid: tid
}, null);
socket.emit('topics.pin', tid);
} else {
socket.emit('api:topics.unpin', {
tid: tid
}, null);
socket.emit('topics.unpin', tid);
}
return false;
});
@ -102,7 +92,7 @@ define(['composer'], function(composer) {
var loadingEl = document.getElementById('categories-loading');
if (loadingEl) {
socket.emit('api:categories.get', function(data) {
socket.emit('categories.get', function(err, data) {
// Render categories
var categoriesFrag = document.createDocumentFragment(),
categoryEl = document.createElement('li'),
@ -145,21 +135,13 @@ define(['composer'], function(composer) {
$(moveThreadModal).find('.modal-header button').fadeOut(250);
commitEl.innerHTML = 'Moving <i class="fa-spin fa-refresh"></i>';
socket.emit('api:topics.move', {
socket.emit('topics.move', {
tid: tid,
cid: targetCid
}, function(data) {
}, function(err) {
moveThreadModal.modal('hide');
if (data.status === 'ok') {
app.alert({
'alert_id': 'thread_move',
type: 'success',
title: 'Topic Successfully Moved',
message: 'This topic has been successfully moved to ' + targetCatLabel,
timeout: 5000
});
} else {
app.alert({
if(err) {
return app.alert({
'alert_id': 'thread_move',
type: 'danger',
title: 'Unable to Move Topic',
@ -167,6 +149,14 @@ define(['composer'], function(composer) {
timeout: 5000
});
}
app.alert({
'alert_id': 'thread_move',
type: 'success',
title: 'Topic Successfully Moved',
message: 'This topic has been successfully moved to ' + targetCatLabel,
timeout: 5000
});
});
}
});
@ -192,7 +182,7 @@ define(['composer'], function(composer) {
forkCommit.on('click', createTopicFromPosts);
function createTopicFromPosts() {
socket.emit('api:topics.createTopicFromPosts', {
socket.emit('topics.createTopicFromPosts', {
title: forkModal.find('#fork-title').val(),
pids: pids
}, function(err) {
@ -298,15 +288,15 @@ define(['composer'], function(composer) {
}
};
socket.emit('api:topics.followCheck', tid, function(state) {
socket.emit('topics.followCheck', tid, function(err, state) {
set_follow_state(state, true);
});
if (followEl[0]) {
followEl[0].addEventListener('click', function() {
socket.emit('api:topics.follow', tid, function(data) {
if (data.status && data.status === 'ok') set_follow_state(data.follow);
else {
app.alert({
socket.emit('topics.follow', tid, function(err, state) {
if(err) {
return app.alert({
type: 'danger',
alert_id: 'topic_follow',
title: 'Please Log In',
@ -314,6 +304,8 @@ define(['composer'], function(composer) {
timeout: 5000
});
}
set_follow_state(state);
});
}, false);
}
@ -375,9 +367,14 @@ define(['composer'], function(composer) {
username = '@' + post.attr('data-username');
}
socket.emit('api:posts.getRawPost', {pid: pid}, function(data) {
quoted = '> ' + data.post.replace(/\n/g, '\n> ') + '\n\n';
socket.emit('posts.getRawPost', pid, function(err, post) {
if(err) {
return app.alert(err.message);
}
var quoted = '';
if(post) {
quoted = '> ' + post.replace(/\n/g, '\n> ') + '\n\n';
}
composer.newReply(tid, topic_name, username + ' said:\n' + quoted);
});
@ -389,12 +386,12 @@ define(['composer'], function(composer) {
var uid = $(this).parents('li').attr('data-uid');
if ($(this).attr('data-favourited') == 'false') {
socket.emit('api:posts.favourite', {
socket.emit('posts.favourite', {
pid: pid,
room_id: app.currentRoom
});
} else {
socket.emit('api:posts.unfavourite', {
socket.emit('posts.unfavourite', {
pid: pid,
room_id: app.currentRoom
});
@ -436,30 +433,20 @@ define(['composer'], function(composer) {
$('#post-container').on('click', '.delete', function(e) {
var pid = $(this).parents('li').attr('data-pid'),
postEl = $(document.querySelector('#post-container li[data-pid="' + pid + '"]')),
deleteAction = !postEl.hasClass('deleted') ? true : false,
confirmDel = confirm((deleteAction ? 'Delete' : 'Restore') + ' this post?');
action = !postEl.hasClass('deleted') ? 'delete' : 'restore';
if (confirmDel) {
if(deleteAction) {
socket.emit('api:posts.delete', {
pid: pid,
tid: tid
}, function(err) {
if(err) {
return app.alertError('Can\'t delete post!');
}
});
} else {
socket.emit('api:posts.restore', {
bootbox.confirm('Are you sure you want to ' + action + ' this post?', function(confirm) {
if (confirm) {
socket.emit('posts.' + action, {
pid: pid,
tid: tid
}, function(err) {
if(err) {
return app.alertError('Can\'t restore post!');
return app.alertError('Can\'t ' + action + ' post!');
}
});
}
}
});
});
$('#post-container').on('click', '.move', function(e) {
@ -488,7 +475,7 @@ define(['composer'], function(composer) {
});
moveBtn.on('click', function() {
socket.emit('api:topics.movePost', {pid: pid, tid: topicId.val()}, function(err) {
socket.emit('topics.movePost', {pid: pid, tid: topicId.val()}, function(err) {
if(err) {
return app.alertError(err.message);
}
@ -515,15 +502,15 @@ define(['composer'], function(composer) {
});
ajaxify.register_events([
'event:rep_up', 'event:rep_down', 'event:new_post', 'api:get_users_in_room',
'event:rep_up', 'event:rep_down', 'event:new_post', 'get_users_in_room',
'event:topic_deleted', 'event:topic_restored', 'event:topic:locked',
'event:topic_unlocked', 'event:topic_pinned', 'event:topic_unpinned',
'event:topic_moved', 'event:post_edited', 'event:post_deleted', 'event:post_restored',
'api:posts.favourite'
'posts.favourite'
]);
socket.on('api:get_users_in_room', function(data) {
socket.on('get_users_in_room', function(data) {
if(data) {
var activeEl = $('.thread_active_users');
@ -629,45 +616,47 @@ define(['composer'], function(composer) {
});
socket.on('event:topic_deleted', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_locked_state(true);
set_delete_state(true);
}
});
socket.on('event:topic_restored', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_locked_state(false);
set_delete_state(false);
}
});
socket.on('event:topic_locked', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_locked_state(true, 1);
}
});
socket.on('event:topic_unlocked', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_locked_state(false, 1);
}
});
socket.on('event:topic_pinned', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_pinned_state(true, 1);
}
});
socket.on('event:topic_unpinned', function(data) {
if (data.tid === tid && data.status === 'ok') {
if (data && data.tid === tid) {
set_pinned_state(false, 1);
}
});
socket.on('event:topic_moved', function(data) {
if (data && data.tid > 0) ajaxify.go('topic/' + data.tid);
if (data && data.tid > 0) {
ajaxify.go('topic/' + data.tid);
}
});
socket.on('event:post_edited', function(data) {
@ -689,8 +678,8 @@ define(['composer'], function(composer) {
});
socket.on('api:posts.favourite', function(data) {
if (data.status === 'ok' && data.pid) {
socket.on('posts.favourite', function(data) {
if (data && data.pid) {
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
if(favBtn.length) {
favBtn.addClass('btn-warning')
@ -700,8 +689,8 @@ define(['composer'], function(composer) {
}
});
socket.on('api:posts.unfavourite', function(data) {
if (data.status === 'ok' && data.pid) {
socket.on('posts.unfavourite', function(data) {
if (data && data.pid) {
var favBtn = $('li[data-pid="' + data.pid + '"] .favourite');
if(favBtn.length) {
favBtn.removeClass('btn-warning')
@ -861,7 +850,11 @@ define(['composer'], function(composer) {
favEl = postEl.find('.favourite'),
replyEl = postEl.find('.post_reply');
socket.emit('api:posts.getPrivileges', pid, function(privileges) {
socket.emit('posts.getPrivileges', pid, function(err, privileges) {
if(err) {
return app.alert(err.message);
}
if (privileges.editable) {
if (!postEl.hasClass('deleted')) {
toggle_post_tools(pid, false);
@ -1056,7 +1049,10 @@ define(['composer'], function(composer) {
.fadeIn('slow');
for (var x = 0, numPosts = data.posts.length; x < numPosts; x++) {
socket.emit('api:posts.getPrivileges', data.posts[x].pid, function(privileges) {
socket.emit('posts.getPrivileges', data.posts[x].pid, function(err, privileges) {
if(err) {
return app.alertError(err.message);
}
toggle_mod_tools(privileges.pid, privileges.editable);
});
}
@ -1087,7 +1083,7 @@ define(['composer'], function(composer) {
}
function updatePostCount() {
socket.emit('api:topics.postcount', templates.get('topic_id'), function(err, postcount) {
socket.emit('topics.postcount', templates.get('topic_id'), function(err, postcount) {
if(!err) {
Topic.postCount = postcount;
$('#topic-post-count').html(Topic.postCount);
@ -1109,12 +1105,16 @@ define(['composer'], function(composer) {
indicatorEl.fadeIn();
}
socket.emit('api:topics.loadMore', {
socket.emit('topics.loadMore', {
tid: tid,
after: parseInt($('#post-container .post-row.infiniteloaded').last().attr('data-index'), 10) + 1
}, function (data) {
}, function (err, data) {
if(err) {
return app.alertError(err.message);
}
infiniteLoaderActive = false;
if (data.posts.length) {
if (data && data.posts && data.posts.length) {
indicatorEl.attr('done', '0');
createNewPosts(data, true);
} else {

@ -8,7 +8,7 @@ define(function() {
ajaxify.register_events([
'event:new_topic',
'event:new_post',
'api:topics.markAllRead'
'topics.markAllRead'
]);
var newTopicCount = 0,
@ -55,19 +55,19 @@ define(function() {
$('#mark-allread-btn').on('click', function() {
var btn = $(this);
socket.emit('api:topics.markAllRead', {}, function(success) {
if (success) {
btn.remove();
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
app.alertSuccess('All topics marked as read!');
$('#numUnreadBadge')
.removeClass('badge-important')
.addClass('badge-inverse')
.html('0');
} else {
app.alertError('There was an error marking topics read!');
socket.emit('topics.markAllRead', function(err) {
if(err) {
return app.alertError('There was an error marking topics read!');
}
btn.remove();
$('#topics-container').empty();
$('#category-no-topics').removeClass('hidden');
app.alertSuccess('All topics marked as read!');
$('#numUnreadBadge')
.removeClass('badge-important')
.addClass('badge-inverse')
.html('0');
});
});
@ -91,9 +91,13 @@ define(function() {
function loadMoreTopics() {
loadingMoreTopics = true;
socket.emit('api:topics.loadMoreUnreadTopics', {
socket.emit('topics.loadMoreUnreadTopics', {
after: parseInt($('#topics-container').attr('data-next-start'), 10)
}, function(data) {
}, function(err, data) {
if(err) {
return app.alertError(err.message);
}
if (data.topics && data.topics.length) {
onTopicsLoaded(data.topics);
$('#topics-container').attr('data-next-start', data.nextStart);

@ -47,7 +47,7 @@ define(function() {
jQuery('#user-notfound-notify').html('<i class="fa fa-spinner fa-spin"></i>');
setTimeout(function() {
socket.emit('api:admin.user.search', username, function(err, data) {
socket.emit('admin.user.search', username, function(err, data) {
if(err) {
return app.alert(err.message);
}
@ -80,10 +80,10 @@ define(function() {
}, 250);
});
socket.on('api:user.isOnline', function(data) {
socket.on('user.isOnline', function(err, data) {
if(getActiveSection() == 'online' && !loadingMoreUsers) {
startLoading('users:online', 0, true);
socket.emit('api:user.getOnlineAnonCount', {} , function(anonCount) {
socket.emit('user.getOnlineAnonCount', {} , function(err, anonCount) {
if(parseInt(anonCount, 10) > 0) {
$('#users-container .anon-user').removeClass('hide');
$('#online_anon_count').html(anonCount);
@ -123,11 +123,11 @@ define(function() {
function startLoading(set, after, emptyContainer) {
loadingMoreUsers = true;
socket.emit('api:user.loadMore', {
socket.emit('user.loadMore', {
set: set,
after: after
}, function(data) {
if (data.users.length) {
}, function(err, data) {
if (data && data.users.length) {
onUsersLoaded(data.users, emptyContainer);
$('#load-more-users-btn').removeClass('disabled');
} else {

@ -13,13 +13,13 @@ define(['taskbar', 'string'], function(taskbar, S) {
return;
}
socket.emit('api:modules.chats.list', function(chats) {
socket.emit('modules.chats.list', function(err, chats) {
var chatsFrag = document.createDocumentFragment(),
chatEl = document.createElement('li'),
numChats = chats.length,
x, userObj;
if (numChats > 0) {
if (!err && numChats > 0) {
for(x=0;x<numChats;x++) {
userObj = chats[x];
chatEl.setAttribute('data-uid', userObj.uid);
@ -90,7 +90,7 @@ define(['taskbar', 'string'], function(taskbar, S) {
}
function checkStatus(chatModal, callback) {
socket.emit('api:user.isOnline', chatModal.touid, function(data) {
socket.emit('user.isOnline', chatModal.touid, function(err, data) {
if(data.online !== chatModal.online) {
if(data.online) {
module.appendChatMessage(chatModal, chatModal.username + ' is currently online.\n', data.timestamp);
@ -191,7 +191,7 @@ define(['taskbar', 'string'], function(taskbar, S) {
}
function getChatMessages(chatModal, callback) {
socket.emit('api:modules.chats.get', {touid:chatModal.touid}, function(messages) {
socket.emit('modules.chats.get', {touid:chatModal.touid}, function(err, messages) {
for(var i = 0; i<messages.length; ++i) {
module.appendChatMessage(chatModal, messages[i].content, messages[i].timestamp);
}
@ -218,7 +218,7 @@ define(['taskbar', 'string'], function(taskbar, S) {
var msg = S(chatModal.find('#chat-message-input').val()).stripTags().s;
if(msg.length) {
msg = msg +'\n';
socket.emit('api:modules.chats.send', { touid:chatModal.touid, message:msg});
socket.emit('modules.chats.send', { touid:chatModal.touid, message:msg});
chatModal.find('#chat-message-input').val('');
}
}

@ -45,9 +45,10 @@ define(['taskbar'], function(taskbar) {
composer.editPost = function(pid) {
if(allowed()) {
socket.emit('api:modules.composer.push', {
pid: pid
}, function(threadData) {
socket.emit('modules.composer.push', pid, function(err, threadData) {
if(err) {
return app.alertError(err.message);
}
push({
pid: pid,
title: threadData.title,
@ -108,8 +109,8 @@ define(['taskbar'], function(taskbar) {
} else if (parseInt(postData.pid) > 0) {
titleEl.val(postData.title);
titleEl.prop('readOnly', true);
socket.emit('api:modules.composer.editCheck', postData.pid, function(editCheck) {
if (editCheck.titleEditable) {
socket.emit('modules.composer.editCheck', postData.pid, function(err, editCheck) {
if (!err && editCheck.titleEditable) {
postContainer.find('input').prop('readonly', false);
}
});
@ -434,7 +435,7 @@ define(['taskbar'], function(taskbar) {
// Still here? Let's post.
if (parseInt(postData.cid) > 0) {
socket.emit('api:topics.post', {
socket.emit('topics.post', {
'title' : titleEl.val(),
'content' : bodyEl.val(),
'category_id' : postData.cid
@ -442,14 +443,14 @@ define(['taskbar'], function(taskbar) {
composer.discard(post_uuid);
});
} else if (parseInt(postData.tid) > 0) {
socket.emit('api:posts.reply', {
socket.emit('posts.reply', {
'topic_id' : postData.tid,
'content' : bodyEl.val()
}, function() {
composer.discard(post_uuid);
});
} else if (parseInt(postData.pid) > 0) {
socket.emit('api:posts.edit', {
socket.emit('posts.edit', {
pid: postData.pid,
content: bodyEl.val(),
title: titleEl.val()
@ -568,12 +569,12 @@ define(['taskbar'], function(taskbar) {
dropDiv.hide();
if(file.type.match('image.*')) {
uploadFile('api:posts.uploadImage', post_uuid, fileData);
uploadFile('posts.uploadImage', post_uuid, fileData);
} else {
if(file.size > parseInt(config.maximumFileSize, 10) * 1024) {
return composerAlert('File too big', 'Maximum allowed file size is ' + config.maximumFileSize + 'kbs');
}
uploadFile('api:posts.uploadFile', post_uuid, fileData);
uploadFile('posts.uploadFile', post_uuid, fileData);
}
});
@ -582,7 +583,7 @@ define(['taskbar'], function(taskbar) {
function uploadFile(method, post_uuid, img) {
var linkStart = method === 'api:posts.uploadImage' ? '!' : '',
var linkStart = method === 'posts.uploadImage' ? '!' : '',
postContainer = $('#cmp-uuid-' + post_uuid),
textarea = postContainer.find('textarea'),
text = textarea.val(),

@ -11,14 +11,14 @@ define(function() {
notifTrigger.addEventListener('click', function(e) {
e.preventDefault();
if (notifContainer.className.indexOf('open') === -1) {
socket.emit('api:notifications.get', null, function(data) {
socket.emit('notifications.get', null, function(err, data) {
var notifFrag = document.createDocumentFragment(),
notifEl = document.createElement('li'),
numRead = data.read.length,
numUnread = data.unread.length,
x;
notifList.innerHTML = '';
if ((data.read.length + data.unread.length) > 0) {
if (!err && (data.read.length + data.unread.length) > 0) {
for (x = 0; x < numUnread; x++) {
notifEl.setAttribute('data-nid', data.unread[x].nid);
notifEl.className = 'unread';
@ -51,13 +51,15 @@ define(function() {
notifIcon.toggleClass('active', false);
}
socket.emit('api:modules.notifications.mark_all_read', null, function() {
notifIcon.toggleClass('active', false);
app.refreshTitle();
socket.emit('modules.notifications.mark_all_read', null, function(err) {
if (!err) {
notifIcon.toggleClass('active', false);
app.refreshTitle();
// Update favicon + local count
Tinycon.setBubble(0);
localStorage.setItem('notifications:count', 0);
// Update favicon + local count
Tinycon.setBubble(0);
localStorage.setItem('notifications:count', 0);
}
});
});
}
@ -78,7 +80,7 @@ define(function() {
}
if (target) {
var nid = parseInt(target.getAttribute('data-nid'));
if (nid > 0) socket.emit('api:modules.notifications.mark_read', nid);
if (nid > 0) socket.emit('modules.notifications.mark_read', nid);
}
});
@ -95,7 +97,7 @@ define(function() {
localStorage.setItem('notifications:count', count);
};
socket.emit('api:notifications.getCount', function(err, count) {
socket.emit('notifications.getCount', function(err, count) {
if (!err) {
updateNotifCount(count);
} else {

@ -15,7 +15,7 @@
</a>
<div class="category row">
<div class="{topic_row_size}">
<div class="col-md-12">
<ul id="topics-container" data-next-start="{nextStart}">
<!-- BEGIN topics -->
<li class="category-item {topics.deleted-class}">

@ -6,11 +6,16 @@ var utils = require('../../public/src/utils'),
UserAdmin.createUser = function(uid, userData, callback) {
user.isAdministrator(uid, function(err, isAdmin) {
if(err) {
return callback(err);
}
if (isAdmin) {
user.create(userData.username, userData.password, userData.email, function(err) {
if(err) {
return callback(err.message);
return callback(err);
}
callback(null);
});
} else {

@ -86,9 +86,7 @@ var db = require('./database.js'),
};
function getTopics(next) {
topics.getTopicsByTids(tids, current_user, function(topicsData) {
next(null, topicsData);
}, category_id);
topics.getTopicsByTids(tids, category_id, current_user, next);
}
function getModerators(next) {
@ -126,9 +124,11 @@ var db = require('./database.js'),
Categories.getCategoryTopics = function(cid, start, stop, uid, callback) {
Categories.getTopicIds(cid, start, stop, function(err, tids) {
topics.getTopicsByTids(tids, uid, function(topicsData) {
callback(topicsData);
}, cid);
if(err) {
return callback(err);
}
topics.getTopicsByTids(tids, cid, uid, callback);
});
};
@ -137,7 +137,6 @@ var db = require('./database.js'),
};
Categories.getAllCategories = function(current_user, callback) {
db.getListRange('categories:cid', 0, -1, function(err, cids) {
if(err) {

@ -46,8 +46,7 @@ var db = require('./database'),
});
}
socket.emit('api:posts.favourite', {
status: 'ok',
socket.emit('posts.favourite', {
pid: pid
});
}
@ -83,8 +82,7 @@ var db = require('./database'),
});
}
socket.emit('api:posts.unfavourite', {
status: 'ok',
socket.emit('posts.unfavourite', {
pid: pid
});
}

@ -122,7 +122,7 @@ var fs = require('fs'),
'theme:templates': '',
'theme:src': ''
};
console.log(themeData);
switch(data.type) {
case 'local':
async.waterfall([

@ -51,7 +51,11 @@ var winston = require('winston'),
}
// [getThreadPrivileges, isOwnPost, hasEnoughRep]
}, function(err, results) {
callback({
if(err) {
return callback(err);
}
callback(null, {
read: results.topicPrivs.read,
editable: results.topicPrivs.editable || results.isOwner || results.hasEnoughRep,
view_deleted: results.topicPrivs.view_deleted || results.isOwner || results.hasEnoughRep
@ -111,7 +115,7 @@ var winston = require('winston'),
});
};
PostTools.privileges(pid, uid, function(privileges) {
PostTools.privileges(pid, uid, function(err, privileges) {
if (privileges.editable) {
plugins.fireHook('filter:post.save', content, function(err, parsedContent) {
if (!err) content = parsedContent;
@ -169,7 +173,7 @@ var winston = require('winston'),
return callback(new Error('Post already deleted!'));
}
PostTools.privileges(pid, uid, function(privileges) {
PostTools.privileges(pid, uid, function(err, privileges) {
if (privileges.editable) {
success();
}
@ -223,7 +227,7 @@ var winston = require('winston'),
return callback(new Error('Post already restored'));
}
PostTools.privileges(pid, uid, function(privileges) {
PostTools.privileges(pid, uid, function(err, privileges) {
if (privileges.editable) {
success();
}

@ -368,41 +368,41 @@ var db = require('./database'),
Posts.uploadPostImage = function(image, callback) {
if(meta.config.imgurClientID) {
if(!image) {
if(!image || !image.data) {
return callback('invalid image', null);
}
require('./imgur').upload(meta.config.imgurClientID, image.data, 'base64', function(err, data) {
if(err) {
callback(err.message, null);
} else {
callback(null, {
url: data.link,
name: image.name
});
return callback(err);
}
callback(null, {
url: data.link,
name: image.name
});
});
} else if (meta.config.allowFileUploads) {
Posts.uploadPostFile(image, callback);
} else {
callback('Uploads are disabled!');
callback(new Error('Uploads are disabled!'));
}
}
Posts.uploadPostFile = function(file, callback) {
if(!meta.config.allowFileUploads) {
return callback('File uploads are not allowed');
return callback(new Error('File uploads are not allowed'));
}
if(!file) {
return callback('invalid file');
if(!file || !file.data) {
return callback(new Error('invalid file'));
}
var buffer = new Buffer(file.data, 'base64');
if(buffer.length > parseInt(meta.config.maximumFileSize, 10) * 1024) {
return callback('File too big');
return callback(new Error('File too big'));
}
var filename = 'upload-' + utils.generateUUID() + path.extname(file.name);
@ -410,13 +410,13 @@ var db = require('./database'),
fs.writeFile(uploadPath, buffer, function (err) {
if(err) {
callback(err.message, null);
} else {
callback(null, {
url: nconf.get('upload_url') + filename,
name: file.name
});
return callback(err);
}
callback(null, {
url: nconf.get('upload_url') + filename,
name: file.name
});
});
}
@ -427,7 +427,7 @@ var db = require('./database'),
}
async.filter(pids, function(pid, next) {
postTools.privileges(pid, 0, function(privileges) {
postTools.privileges(pid, 0, function(err, privileges) {
next(privileges.read);
});
}, function(pids) {

@ -189,16 +189,24 @@ var path = require('path'),
});
});
app.get('/unread', function (req, res) {
app.get('/unread', function (req, res, next) {
var uid = (req.user) ? req.user.uid : 0;
topics.getUnreadTopics(uid, 0, 19, function (data) {
topics.getUnreadTopics(uid, 0, 19, function (err, data) {
if(err) {
return next(err);
}
res.json(data);
});
});
app.get('/unread/total', function (req, res) {
app.get('/unread/total', function (req, res, next) {
var uid = (req.user) ? req.user.uid : 0;
topics.getTotalUnread(uid, function (data) {
topics.getTotalUnread(uid, function (err, data) {
if(err) {
return next(err);
}
res.json(data);
});
});
@ -286,9 +294,9 @@ var path = require('path'),
return callback(err, null);
}
topics.getTopicsByTids(tids, 0, function (topics) {
topics.getTopicsByTids(tids, 0, 0, function (topics) {
callback(null, topics);
}, 0);
});
});
}

@ -15,16 +15,17 @@ var groups = require('../groups'),
async = require('async'),
winston = require('winston'),
index = require('./index'),
SocketAdmin = {};
SocketAdmin.before = function(sessionData, next) {
SocketAdmin.before = function(socket, next) {
// Verify administrative privileges
user.isAdministrator(sessionData.uid, function(err, isAdmin) {
user.isAdministrator(socket.uid, function(err, isAdmin) {
if (isAdmin) {
next();
} else {
winston.warn('[socket.io] Call to admin method blocked (accessed by uid ' + sessionData.uid + ')');
winston.warn('[socket.io] Call to admin method blocked (accessed by uid ' + socket.uid + ')');
}
});
};
@ -33,54 +34,51 @@ SocketAdmin.before = function(sessionData, next) {
SocketAdmin.topics = {};
SocketAdmin.topics.getMore = function(data, callback) {
topics.getAllTopics(data.limit, data.after, function(err, topics) {
callback(JSON.stringify(topics));
});
SocketAdmin.topics.getMore = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
topics.getAllTopics(data.limit, data.after, callback);
};
/* User */
SocketAdmin.user = {};
SocketAdmin.user.makeAdmin = function(theirid, sessionData) {
if (sessionData.uid && sessionData.uid > 0) {
admin.user.makeAdmin(sessionData.uid, theirid, sessionData.socket);
}
SocketAdmin.user.makeAdmin = function(socket, theirid) {
admin.user.makeAdmin(socket.uid, theirid, socket);
};
SocketAdmin.user.removeAdmin = function(theirid, sessionData) {
if (sessionData.uid && sessionData.uid > 0) {
admin.user.removeAdmin(sessionData.uid, theirid, sessionData.socket);
}
SocketAdmin.user.removeAdmin = function(socket, theirid) {
admin.user.removeAdmin(socket.uid, theirid, socket);
};
SocketAdmin.user.createUser = function(user, callback, sessionData) {
if (sessionData.uid && sessionData.uid > 0) {
admin.user.createUser(sessionData.uid, user, callback);
SocketAdmin.user.createUser = function(socket, user, callback) {
if(!user) {
return callback(new Error('invalid data'));
}
admin.user.createUser(socket.uid, user, callback);
};
SocketAdmin.user.banUser = function(theirid, sessionData) {
if (sessionData.uid && sessionData.uid > 0) {
admin.user.banUser(sessionData.uid, theirid, sessionData.socket, function(isBanned) {
if(isBanned) {
if(sessionData.userSockets[theirid]) {
for(var i=0; i<sessionData.userSockets[theirid].length; ++i) {
sessionData.userSockets[theirid][i].emit('event:banned');
}
SocketAdmin.user.banUser = function(socket, theirid) {
admin.user.banUser(socket.uid, theirid, socket, function(isBanned) {
if(isBanned) {
if(index.userSockets[theirid]) {
for(var i=0; i<index.userSockets[theirid].length; ++i) {
index.userSockets[theirid][i].emit('event:banned');
}
module.parent.exports.logoutUser(theirid);
}
});
}
module.parent.exports.logoutUser(theirid);
}
});
};
SocketAdmin.user.unbanUser = function(theirid, sessionData) {
admin.user.unbanUser(sessionData.uid, theirid, sessionData.socket);
SocketAdmin.user.unbanUser = function(socket, theirid) {
admin.user.unbanUser(socket.uid, theirid, socket);
};
SocketAdmin.user.search = function(username, callback, sessionData) {
SocketAdmin.user.search = function(socket, username, callback) {
user.search(username, function(data) {
function isAdmin(userData, next) {
user.isAdministrator(userData.uid, function(err, isAdmin) {
@ -94,11 +92,7 @@ SocketAdmin.user.search = function(username, callback, sessionData) {
}
async.each(data, isAdmin, function(err) {
if(err) {
return callback({message: err.message});
}
callback(null, data);
callback(err, data);
});
});
};
@ -107,42 +101,59 @@ SocketAdmin.user.search = function(username, callback, sessionData) {
SocketAdmin.categories = {};
SocketAdmin.categories.create = function(data, callback) {
categories.create(data, function(err, data) {
callback(err, data);
});
SocketAdmin.categories.create = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
categories.create(data, callback);
};
SocketAdmin.categories.update = function(data, sessionData) {
admin.categories.update(data, sessionData.socket);
SocketAdmin.categories.update = function(socket, data) {
if(!data) {
return callback(new Error('invalid data'));
}
admin.categories.update(data, socket);
};
SocketAdmin.categories.search = function(username, cid, callback, sessionData) {
SocketAdmin.categories.search = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
var username = data.username,
cid = data.cid;
user.search(username, function(data) {
async.map(data, function(userObj, next) {
CategoryTools.privileges(cid, userObj.uid, function(err, privileges) {
if (!err) {
userObj.privileges = privileges;
} else {
winston.error('[socket api:admin.categories.search] Could not retrieve permissions');
if(err) {
return next(err);
}
userObj.privileges = privileges;
next(null, userObj);
});
}, function(err, data) {
if (!callback) {
sessionData.socket.emit('api:admin.categories.search', data);
} else {
callback(null, data);
}
});
}, callback);
});
};
SocketAdmin.categories.setPrivilege = function(cid, uid, privilege, set, callback) {
var cb = function(err) {
CategoryTools.privileges(cid, uid, callback);
};
SocketAdmin.categories.setPrivilege = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
var cid = data.cid,
uid = data.uid,
privilege = data.privilege,
set = data.set,
cb = function(err) {
if(err) {
return callback(err);
}
CategoryTools.privileges(cid, uid, callback);
};
if (set) {
groups.joinByGroupName('cid:' + cid + ':privileges:' + privilege, uid, cb);
@ -151,7 +162,7 @@ SocketAdmin.categories.setPrivilege = function(cid, uid, privilege, set, callbac
}
};
SocketAdmin.categories.getPrivilegeSettings = function(cid, callback) {
SocketAdmin.categories.getPrivilegeSettings = function(socket, cid, callback) {
async.parallel({
"+r": function(next) {
groups.getByGroupName('cid:' + cid + ':privileges:+r', { expand: true }, function(err, groupObj) {
@ -176,6 +187,10 @@ SocketAdmin.categories.getPrivilegeSettings = function(cid, callback) {
});
}
}, function(err, data) {
if(err) {
return callback(err);
}
callback(null, {
"+r": data['+r'].members,
"+w": data['+w'].members
@ -183,29 +198,34 @@ SocketAdmin.categories.getPrivilegeSettings = function(cid, callback) {
});
};
SocketAdmin.categories.setGroupPrivilege = function(cid, gid, privilege, set, callback) {
if (set) {
groups.joinByGroupName('cid:' + cid + ':privileges:' + privilege, gid, callback);
SocketAdmin.categories.setGroupPrivilege = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
if (data.set) {
groups.joinByGroupName('cid:' + data.cid + ':privileges:' + data.privilege, data.gid, callback);
} else {
groups.leaveByGroupName('cid:' + cid + ':privileges:' + privilege, gid, callback);
groups.leaveByGroupName('cid:' + data.cid + ':privileges:' + data.privilege, data.gid, callback);
}
};
SocketAdmin.categories.groupsList = function(cid, callback) {
SocketAdmin.categories.groupsList = function(socket, cid, callback) {
groups.list({expand:false}, function(err, data){
if(err) {
return callback(err);
}
async.map(data, function(groupObj, next) {
CategoryTools.groupPrivileges(cid, groupObj.gid, function(err, privileges) {
if (!err) {
groupObj.privileges = privileges;
} else {
winston.error('[socket api:admin.categories.groupsList] Could not retrieve permissions');
if(err) {
return next(err);
}
groupObj.privileges = privileges;
next(null, groupObj);
});
}, function(err, data) {
callback(null, data);
});
}, callback);
});
};
@ -214,17 +234,20 @@ SocketAdmin.categories.groupsList = function(cid, callback) {
SocketAdmin.themes = {};
SocketAdmin.plugins = {};
SocketAdmin.themes.getInstalled = function(callback) {
meta.themes.get(function(err, themeArr) {
callback(themeArr);
});
SocketAdmin.themes.getInstalled = function(socket, data, callback) {
meta.themes.get(callback);
};
SocketAdmin.themes.set = meta.themes.set;
SocketAdmin.themes.set = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
meta.themes.set(data, callback);
}
SocketAdmin.plugins.toggle = function(plugin_id, sessionData) {
SocketAdmin.plugins.toggle = function(socket, plugin_id) {
plugins.toggleActive(plugin_id, function(status) {
sessionData.socket.emit('api:admin.plugins.toggle', status);
socket.emit('admin.plugins.toggle', status);
});
};
@ -232,32 +255,32 @@ SocketAdmin.plugins.toggle = function(plugin_id, sessionData) {
SocketAdmin.config = {};
SocketAdmin.config.get = function(callback, sessionData) {
meta.configs.list(function(err, config) {
if (!err) {
callback(config);
}
});
SocketAdmin.config.get = function(socket, data, callback) {
meta.configs.list(callback);
};
SocketAdmin.config.set = function(data, callback, sessionData) {
meta.configs.set(data.key, data.value, function(err) {
if (!err) {
callback({
status: 'ok'
});
SocketAdmin.config.set = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
plugins.fireHook('action:config.set', {
key: data.key,
value: data.value
});
meta.configs.set(data.key, data.value, function(err) {
if(err) {
return callback(err);
}
logger.monitorConfig({io: sessionData.server}, data);
callback(null);
plugins.fireHook('action:config.set', {
key: data.key,
value: data.value
});
logger.monitorConfig({io: index.server}, data);
});
};
SocketAdmin.config.remove = function(key) {
SocketAdmin.config.remove = function(socket, key) {
meta.configs.remove(key);
};
@ -265,35 +288,49 @@ SocketAdmin.config.remove = function(key) {
SocketAdmin.groups = {};
SocketAdmin.groups.create = function(data, callback) {
SocketAdmin.groups.create = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
groups.create(data.name, data.description, function(err, groupObj) {
callback(err ? err.message : null, groupObj || undefined);
callback(err, groupObj || undefined);
});
};
SocketAdmin.groups.delete = function(gid, callback) {
groups.destroy(gid, function(err) {
callback(err ? err.message : null, err ? null : 'OK');
});
SocketAdmin.groups.delete = function(socket, gid, callback) {
groups.destroy(gid, callback);
};
SocketAdmin.groups.get = function(gid, callback) {
SocketAdmin.groups.get = function(socket, gid, callback) {
groups.get(gid, {
expand: true
}, function(err, groupObj) {
callback(err ? err.message : null, groupObj || undefined);
callback(err, groupObj || undefined);
});
};
SocketAdmin.groups.join = function(data, callback) {
SocketAdmin.groups.join = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
groups.join(data.gid, data.uid, callback);
};
SocketAdmin.groups.leave = function(data, callback) {
SocketAdmin.groups.leave = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
groups.leave(data.gid, data.uid, callback);
};
SocketAdmin.groups.update = function(data, callback) {
SocketAdmin.groups.update = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
groups.update(data.gid, data.values, function(err) {
callback(err ? err.message : null);
});

@ -2,26 +2,24 @@ var categories = require('../categories'),
SocketCategories = {};
SocketCategories.getRecentReplies = function(tid, callback, sessionData) {
categories.getRecentReplies(tid, sessionData.uid, 4, function(err, replies) {
callback(replies);
});
SocketCategories.getRecentReplies = function(socket, tid, callback) {
categories.getRecentReplies(tid, socket.uid, 4, callback);
};
SocketCategories.get = function(callback) {
categories.getAllCategories(0, function(err, categories) {
if(callback) {
callback(categories);
}
});
SocketCategories.get = function(socket, data, callback) {
categories.getAllCategories(0, callback);
};
SocketCategories.loadMore = function(data, callback, sessionData) {
SocketCategories.loadMore = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
var start = data.after,
end = start + 9;
categories.getCategoryTopics(data.cid, start, end, sessionData.uid, function(topics) {
callback({
categories.getCategoryTopics(data.cid, start, end, socket.uid, function(err, topics) {
callback(err, {
topics: topics
});
});

@ -23,10 +23,13 @@ var SocketIO = require('socket.io'),
/* === */
var users = {},
userSockets = {},
rooms = {},
io;
Sockets.userSockets = {};
Sockets.rooms = {};
Sockets.init = function() {
io = socketioWildcard(SocketIO).listen(global.server, {
@ -35,6 +38,8 @@ Sockets.init = function() {
'browser client minification': true
});
Sockets.server = io;
fs.readdir(__dirname, function(err, files) {
files.splice(files.indexOf('index.js'), 1);
@ -59,8 +64,10 @@ Sockets.init = function() {
uid = users[sessionID] = 0;
}
userSockets[uid] = userSockets[uid] || [];
userSockets[uid].push(socket);
socket.uid = parseInt(uid, 10);
Sockets.userSockets[uid] = Sockets.userSockets[uid] || [];
Sockets.userSockets[uid].push(socket);
/* Need to save some state for the logger & maybe some other modules later on */
socket.state = {
@ -87,36 +94,36 @@ Sockets.init = function() {
});
}
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
io.sockets.in('global').emit('user.isOnline', isUserOnline(uid));
});
});
socket.on('disconnect', function() {
var index = (userSockets[uid] || []).indexOf(socket);
var index = (Sockets.userSockets[uid] || []).indexOf(socket);
if (index !== -1) {
userSockets[uid].splice(index, 1);
Sockets.userSockets[uid].splice(index, 1);
}
if (userSockets[uid] && userSockets[uid].length === 0) {
if (Sockets.userSockets[uid] && Sockets.userSockets[uid].length === 0) {
delete users[sessionID];
delete userSockets[uid];
delete Sockets.userSockets[uid];
if (uid) {
db.sortedSetRemove('users:online', uid, function(err, data) {
});
}
}
io.sockets.in('global').emit('api:user.isOnline', isUserOnline(uid));
io.sockets.in('global').emit('user.isOnline', isUserOnline(uid));
emitOnlineUserCount();
for (var roomName in rooms) {
if (rooms.hasOwnProperty(roomName)) {
for (var roomName in Sockets.rooms) {
if (Sockets.rooms.hasOwnProperty(roomName)) {
socket.leave(roomName);
if (rooms[roomName][socket.id]) {
delete rooms[roomName][socket.id];
if (Sockets.rooms[roomName][socket.id]) {
delete Sockets.rooms[roomName][socket.id];
}
updateRoomBrowsingText(roomName);
@ -125,72 +132,50 @@ Sockets.init = function() {
});
socket.on('*', function(payload, callback) {
// Ignore all non-api messages
if (payload.name.substr(0, 4) !== 'api:') {
return;
} else {
// Deconstruct the message
var parts = payload.name.slice(4).split('.'),
namespace = parts.slice(0, 1),
methodToCall = parts.reduce(function(prev, cur) {
if (prev !== null && prev[cur]) {
return prev[cur];
} else {
return null;
}
}, Namespaces);
if (methodToCall !== null) {
var sessionData = {
uid: uid,
socket: socket,
rooms: rooms,
server: io,
userSockets: userSockets
},
socketArgs = [];
// Construct the arguments that'll get passed into each socket method
if (payload.args.length) {
socketArgs = socketArgs.concat(payload.args);
}
if (callback !== undefined) {
socketArgs.push(callback);
function callMethod(method) {
method.call(null, socket, payload.args.length ? payload.args[0] : null, function(err, result) {
if (callback) {
callback(err?{message:err.message}:null, result);
}
socketArgs.push(sessionData);
// Call the requested method
if (Namespaces[namespace].before) {
Namespaces[namespace].before(sessionData, function() {
try {
methodToCall.apply(Namespaces, socketArgs);
} catch (e) {
winston.error(e.message);
}
});
});
}
if(!payload.name) {
return winston.warn('[socket.io] Empty method name');
}
var parts = payload.name.toString().split('.'),
namespace = parts.slice(0, 1),
methodToCall = parts.reduce(function(prev, cur) {
if (prev !== null && prev[cur]) {
return prev[cur];
} else {
try {
methodToCall.apply(Namespaces, socketArgs);
} catch (e) {
winston.error(e.message);
}
return null;
}
// winston.info('[socket.io] Executing: ' + payload.name);
} else {
winston.warn('[socket.io] Unrecognized message: ' + payload.name);
}
}, Namespaces);
if(!methodToCall) {
return winston.warn('[socket.io] Unrecognized message: ' + payload.name);
}
if (Namespaces[namespace].before) {
Namespaces[namespace].before(socket, function() {
callMethod(methodToCall);
});
} else {
callMethod(methodToCall);
}
});
});
};
Sockets.logoutUser = function(uid) {
if(userSockets[uid] && userSockets[uid].length) {
for(var i=0; i< userSockets[uid].length; ++i) {
userSockets[uid][i].emit('event:disconnect');
userSockets[uid][i].disconnect();
if(Sockets.userSockets[uid] && Sockets.userSockets[uid].length) {
for(var i=0; i< Sockets.userSockets[uid].length; ++i) {
Sockets.userSockets[uid][i].emit('event:disconnect');
Sockets.userSockets[uid][i].disconnect();
if(!userSockets[uid]) {
if(!Sockets.userSockets[uid]) {
return;
}
}
@ -199,7 +184,7 @@ Sockets.logoutUser = function(uid) {
Sockets.emitUserCount = function() {
db.getObjectField('global', 'userCount', function(err, count) {
io.sockets.emit('user.count', {
io.sockets.emit('user.count', err?{message:err.message}:null, {
count: count
});
});
@ -211,18 +196,18 @@ Sockets.in = function(room) {
};
Sockets.getConnectedClients = function() {
return userSockets;
return Sockets.userSockets;
};
Sockets.getOnlineAnonCount = function () {
return userSockets[0] ? userSockets[0].length : 0;
return Sockets.userSockets[0] ? Sockets.userSockets[0].length : 0;
};
/* Helpers */
Sockets.isUserOnline = isUserOnline;
function isUserOnline(uid) {
return !!userSockets[uid] && userSockets[uid].length > 0;
return !!Sockets.userSockets[uid] && Sockets.userSockets[uid].length > 0;
}
Sockets.updateRoomBrowsingText = updateRoomBrowsingText;
@ -251,15 +236,15 @@ function updateRoomBrowsingText(roomName) {
return anonCount;
}
var uids = getUidsInRoom(rooms[roomName]),
var uids = getUidsInRoom(Sockets.rooms[roomName]),
anonymousCount = getAnonymousCount(roomName);
if (uids.length === 0) {
io.sockets.in(roomName).emit('api:get_users_in_room', { users: [], anonymousCount: anonymousCount });
io.sockets.in(roomName).emit('get_users_in_room', { users: [], anonymousCount: anonymousCount });
} else {
user.getMultipleUserFields(uids, ['uid', 'username', 'userslug', 'picture'], function(err, users) {
if(!err) {
io.sockets.in(roomName).emit('api:get_users_in_room', { users: users, anonymousCount: anonymousCount });
io.sockets.in(roomName).emit('get_users_in_room', { users: users, anonymousCount: anonymousCount });
}
});
}
@ -278,17 +263,17 @@ function emitTopicPostStats(callback) {
};
if (!callback) {
io.sockets.emit('post.stats', stats);
io.sockets.emit('post.stats', null, stats);
} else {
callback(stats);
callback(null, stats);
}
});
}
Sockets.emitOnlineUserCount = emitOnlineUserCount;
function emitOnlineUserCount(callback) {
var anon = userSockets[0] ? userSockets[0].length : 0;
var registered = Object.keys(userSockets).length;
var anon = Sockets.userSockets[0] ? Sockets.userSockets[0].length : 0;
var registered = Object.keys(Sockets.userSockets).length;
if (anon) {
registered = registered - 1;
}
@ -299,9 +284,9 @@ function emitOnlineUserCount(callback) {
};
if (callback) {
callback(returnObj);
callback(null, returnObj);
} else {
io.sockets.emit('api:user.active.get', returnObj);
io.sockets.emit('user.getActiveUsers', null, returnObj);
}
}

@ -7,12 +7,13 @@ var meta = require('../meta'),
nconf = require('nconf'),
gravatar = require('gravatar'),
winston = require('winston'),
server = require('./'),
SocketMeta = {};
SocketMeta.reconnected = function(sessionData) {
var uid = sessionData.uid,
sessionID = sessionData.socket.id;
SocketMeta.reconnected = function(socket) {
var uid = socket.uid,
sessionID = socket.id;
if (uid) {
topics.pushUnreadCount(uid);
@ -28,22 +29,30 @@ SocketMeta.reconnected = function(sessionData) {
}
};
SocketMeta.buildTitle = function(text, callback) {
meta.title.build(text, function(err, title) {
callback(title);
});
SocketMeta.buildTitle = function(socket, text, callback) {
meta.title.build(text, callback);
};
SocketMeta.updateHeader = function(data, callback, sessionData) {
if (sessionData.uid) {
user.getUserFields(sessionData.uid, data.fields, function(err, fields) {
if (!err && fields) {
fields.uid = sessionData.uid;
callback(fields);
SocketMeta.updateHeader = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
if (socket.uid) {
user.getUserFields(socket.uid, data.fields, function(err, fields) {
if(err) {
return callback(err);
}
if (fields) {
fields.uid = socket.uid;
callback(null, fields);
} else {
callback(null, []);
}
});
} else {
callback({
callback(null, {
uid: 0,
username: "Anonymous User",
email: '',
@ -57,7 +66,7 @@ SocketMeta.updateHeader = function(data, callback, sessionData) {
}
};
SocketMeta.getUsageStats = function(callback) {
SocketMeta.getUsageStats = function(socket, data, callback) {
module.parent.exports.emitTopicPostStats(callback);
};
@ -65,19 +74,23 @@ SocketMeta.getUsageStats = function(callback) {
SocketMeta.rooms = {};
SocketMeta.rooms.enter = function(data, sessionData) {
SocketMeta.rooms.enter = function(socket, data) {
if(!data) {
return callback(new Error('invalid data'));
}
if (data.leave !== null) {
sessionData.socket.leave(data.leave);
socket.leave(data.leave);
}
sessionData.socket.join(data.enter);
sessionData.rooms[data.enter] = sessionData.rooms[data.enter] || {};
socket.join(data.enter);
server.rooms[data.enter] = server.rooms[data.enter] || {};
if (sessionData.uid) {
sessionData.rooms[data.enter][sessionData.socket.id] = sessionData.uid;
if (socket.uid) {
server.rooms[data.enter][socket.id] = socket.uid;
if (data.leave && sessionData.rooms[data.leave] && sessionData.rooms[data.leave][sessionData.socket.id] && data.enter !== data.leave) {
delete sessionData.rooms[data.leave][sessionData.socket.id];
if (data.leave && server.rooms[data.leave] && server.rooms[data.leave][socket.id] && data.enter !== data.leave) {
delete server.rooms[data.leave][socket.id];
}
}
@ -88,12 +101,12 @@ SocketMeta.rooms.enter = function(data, sessionData) {
module.parent.exports.updateRoomBrowsingText(data.enter);
if (data.enter != 'admin') {
sessionData.server.sockets.in('admin').emit('event:meta.rooms.update', sessionData.server.sockets.manager.rooms);
server.in('admin').emit('event:meta.rooms.update', null, server.rooms);
}
};
SocketMeta.rooms.getAll = function(callback, sessionData) {
callback(sessionData.server.sockets.manager.rooms);
SocketMeta.rooms.getAll = function(socket, data, callback) {
callback(null, server.rooms);
};
/* Exports */

@ -11,6 +11,7 @@ var posts = require('../posts'),
async = require('async'),
S = require('string'),
winston = require('winston'),
server = require('./'),
SocketModules = {};
@ -18,38 +19,44 @@ var posts = require('../posts'),
SocketModules.composer = {};
SocketModules.composer.push = function(data, callback, sessionData) {
if (parseInt(sessionData.uid, 10) > 0 || parseInt(meta.config.allowGuestPosting, 10) === 1) {
if (parseInt(data.pid, 10) > 0) {
SocketModules.composer.push = function(socket, pid, callback) {
if (socket.uid || parseInt(meta.config.allowGuestPosting, 10)) {
if (parseInt(pid, 10) > 0) {
async.parallel([
function(next) {
posts.getPostFields(data.pid, ['content'], next);
posts.getPostFields(pid, ['content'], next);
},
function(next) {
topics.getTitleByPid(data.pid, function(title) {
topics.getTitleByPid(pid, function(title) {
next(null, title);
});
}
], function(err, results) {
callback({
if(err) {
return callback(err);
}
callback(null, {
title: results[1],
pid: data.pid,
pid: pid,
body: results[0].content
});
});
}
} else {
callback({
error: 'no-uid'
});
callback(new Error('no-uid'));
}
};
SocketModules.composer.editCheck = function(pid, callback) {
SocketModules.composer.editCheck = function(socket, pid, callback) {
posts.getPostField(pid, 'tid', function(err, tid) {
if (err) {
return callback(err);
}
postTools.isMain(pid, tid, function(err, isMain) {
callback({
callback(err, {
titleEditable: isMain
});
});
@ -60,27 +67,27 @@ SocketModules.composer.editCheck = function(pid, callback) {
SocketModules.chats = {};
SocketModules.chats.get = function(data, callback, sessionData) {
var touid = data.touid;
Messaging.getMessages(sessionData.uid, touid, function(err, messages) {
if (err) {
return callback(null);
}
SocketModules.chats.get = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
callback(messages);
});
Messaging.getMessages(socket.uid, data.touid, callback);
};
SocketModules.chats.send = function(data, sessionData) {
SocketModules.chats.send = function(socket, data) {
if(!data) {
return callback(new Error('invalid data'));
}
var touid = data.touid;
if (touid === sessionData.uid || sessionData.uid === 0) {
if (touid === socket.uid || socket.uid === 0) {
return;
}
var msg = S(data.message).stripTags().s;
user.getMultipleUserFields([sessionData.uid, touid], ['username'], function(err, usersData) {
user.getMultipleUserFields([socket.uid, touid], ['username'], function(err, usersData) {
if(err) {
return;
}
@ -91,23 +98,23 @@ SocketModules.chats.send = function(data, sessionData) {
notifText = 'New message from <strong>' + username + '</strong>';
if (!module.parent.exports.isUserOnline(touid)) {
notifications.create(notifText, 'javascript:app.openChat(&apos;' + username + '&apos;, ' + sessionData.uid + ');', 'notification_' + sessionData.uid + '_' + touid, function(nid) {
notifications.create(notifText, 'javascript:app.openChat(&apos;' + username + '&apos;, ' + socket.uid + ');', 'notification_' + socket.uid + '_' + touid, function(nid) {
notifications.push(nid, [touid], function(success) {
});
});
}
Messaging.parse(msg, sessionData.uid, sessionData.uid, toUsername, function(parsed) {
Messaging.addMessage(sessionData.uid, touid, msg, function(err, message) {
Messaging.parse(msg, socket.uid, socket.uid, toUsername, function(parsed) {
Messaging.addMessage(socket.uid, touid, msg, function(err, message) {
var numSockets = 0,
x;
if (sessionData.userSockets[touid]) {
numSockets = sessionData.userSockets[touid].length;
if (server.userSockets[touid]) {
numSockets = server.userSockets[touid].length;
for (x = 0; x < numSockets; ++x) {
sessionData.userSockets[touid][x].emit('event:chats.receive', {
fromuid: sessionData.uid,
server.userSockets[touid][x].emit('event:chats.receive', {
fromuid: socket.uid,
username: username,
// todo this isnt very nice, but can't think of a better way atm
message: parsed.replace("chat-user-you'>You", "'>" + username),
@ -116,12 +123,12 @@ SocketModules.chats.send = function(data, sessionData) {
}
}
if (sessionData.userSockets[sessionData.uid]) {
if (server.userSockets[socket.uid]) {
numSockets = sessionData.userSockets[sessionData.uid].length;
numSockets = server.userSockets[socket.uid].length;
for (x = 0; x < numSockets; ++x) {
sessionData.userSockets[sessionData.uid][x].emit('event:chats.receive', {
server.userSockets[socket.uid][x].emit('event:chats.receive', {
fromuid: touid,
username: toUsername,
message: parsed,
@ -134,30 +141,20 @@ SocketModules.chats.send = function(data, sessionData) {
});
};
SocketModules.chats.list = function(callback, sessionData) {
Messaging.getRecentChats(sessionData.uid, function(err, uids) {
if (err) {
winston.warn('[(socket) api:chats.list] Problem retrieving chats: ' + err.message);
}
callback(uids || []);
});
SocketModules.chats.list = function(socket, data, callback) {
Messaging.getRecentChats(socket.uid, callback);
};
/* Notifications */
SocketModules.notifications = {};
SocketModules.notifications.mark_read = function(nid, sessionData) {
notifications.mark_read(nid, sessionData.uid);
SocketModules.notifications.mark_read = function(socket, nid) {
notifications.mark_read(nid, socket.uid);
};
SocketModules.notifications.mark_all_read = function(data, callback, sessionData) {
notifications.mark_all_read(sessionData.uid, function(err) {
if (!err) {
callback();
}
});
SocketModules.notifications.mark_all_read = function(socket, data, callback) {
notifications.mark_all_read(socket.uid, callback);
};
module.exports = SocketModules;

@ -1,17 +1,15 @@
"use strict";
var user = require('../user'),
SocketNotifs = {};
SocketNotifs.get = function(data, callback, sessionData) {
user.notifications.get(sessionData.uid, function(notifs) {
callback(notifs);
});
SocketNotifs.get = function(socket, data, callback) {
user.notifications.get(socket.uid, callback);
};
SocketNotifs.getCount = function(callback, sessionData) {
user.notifications.getUnreadCount(sessionData.uid, function(err, count) {
callback(err ? err.message : null, count);
});
SocketNotifs.getCount = function(socket, data, callback) {
user.notifications.getUnreadCount(socket.uid, callback);
};
module.exports = SocketNotifs;

@ -3,12 +3,13 @@ var posts = require('../posts'),
topics = require('../topics'),
favourites = require('../favourites'),
postTools = require('../postTools'),
index = require('./index'),
SocketPosts = {};
SocketPosts.reply = function(data, callback, sessionData) {
if (sessionData.uid < 1 && parseInt(meta.config.allowGuestPosting, 10) === 0) {
sessionData.socket.emit('event:alert', {
SocketPosts.reply = function(socket, data, callback) {
if (!socket.uid && !parseInt(meta.config.allowGuestPosting, 10)) {
socket.emit('event:alert', {
title: 'Reply Unsuccessful',
message: 'You don&apos;t seem to be logged in, so you cannot reply.',
type: 'danger',
@ -17,35 +18,39 @@ SocketPosts.reply = function(data, callback, sessionData) {
return;
}
topics.reply(data.topic_id, sessionData.uid, data.content, function(err, postData) {
if(!data || !data.topic_id || !data.content) {
return callback(new Error('invalid data'));
}
topics.reply(data.topic_id, socket.uid, data.content, function(err, postData) {
if(err) {
if (err.message === 'content-too-short') {
module.parent.exports.emitContentTooShortAlert(sessionData.socket);
module.parent.exports.emitContentTooShortAlert(socket);
} else if (err.message === 'too-many-posts') {
module.parent.exports.emitTooManyPostsAlert(sessionData.socket);
module.parent.exports.emitTooManyPostsAlert(socket);
} else if (err.message === 'reply-error') {
sessionData.socket.emit('event:alert', {
socket.emit('event:alert', {
title: 'Reply Unsuccessful',
message: 'Your reply could not be posted at this time. Please try again later.',
type: 'warning',
timeout: 2000
});
} else if (err.message === 'no-privileges') {
sessionData.socket.emit('event:alert', {
socket.emit('event:alert', {
title: 'Unable to post',
message: 'You do not have posting privileges in this category.',
type: 'danger',
timeout: 7500
});
}
return;
return callback(err);
}
if (postData) {
module.parent.exports.emitTopicPostStats();
sessionData.socket.emit('event:alert', {
socket.emit('event:alert', {
title: 'Reply Successful',
message: 'You have successfully replied. Click here to view your reply.',
type: 'success',
@ -54,62 +59,71 @@ SocketPosts.reply = function(data, callback, sessionData) {
var socketData = {
posts: [postData]
};
sessionData.server.sockets.in('topic_' + postData.tid).emit('event:new_post', socketData);
sessionData.server.sockets.in('recent_posts').emit('event:new_post', socketData);
sessionData.server.sockets.in('user/' + postData.uid).emit('event:new_post', socketData);
index.server.sockets.in('topic_' + postData.tid).emit('event:new_post', socketData);
index.server.sockets.in('recent_posts').emit('event:new_post', socketData);
index.server.sockets.in('user/' + postData.uid).emit('event:new_post', socketData);
callback();
}
});
};
SocketPosts.favourite = function(data, sessionData) {
favourites.favourite(data.pid, data.room_id, sessionData.uid, sessionData.socket);
SocketPosts.favourite = function(socket, data) {
if(data && data.pid && data.room_id) {
favourites.favourite(data.pid, data.room_id, socket.uid, socket);
}
};
SocketPosts.unfavourite = function(data, sessionData) {
favourites.unfavourite(data.pid, data.room_id, sessionData.uid, sessionData.socket);
SocketPosts.unfavourite = function(socket, data) {
if(data && data.pid && data.room_id) {
favourites.unfavourite(data.pid, data.room_id, socket.uid, socket);
}
};
SocketPosts.uploadImage = function(data, callback) {
posts.uploadPostImage(data, callback);
SocketPosts.uploadImage = function(socket, data, callback) {
if(data) {
posts.uploadPostImage(data, callback);
}
};
SocketPosts.uploadFile = function(data, callback) {
posts.uploadPostFile(data, callback);
SocketPosts.uploadFile = function(socket, data, callback) {
if(data) {
posts.uploadPostFile(data, callback);
}
};
SocketPosts.getRawPost = function(data, callback) {
posts.getPostField(data.pid, 'content', function(err, raw) {
callback({
post: raw
});
});
SocketPosts.getRawPost = function(socket, pid, callback) {
posts.getPostField(pid, 'content', callback);
};
SocketPosts.edit = function(data, callback, sessionData) {
if(!sessionData.uid) {
sessionData.socket.emit('event:alert', {
SocketPosts.edit = function(socket, data, callback) {
if(!socket.uid) {
socket.emit('event:alert', {
title: 'Can&apos;t edit',
message: 'Guests can&apos;t edit posts!',
type: 'warning',
timeout: 2000
});
return;
} else if(!data || !data.pid || !data.title || !data.content) {
return callback(new Error('invalid data'));
} else if (!data.title || data.title.length < parseInt(meta.config.minimumTitleLength, 10)) {
topics.emitTitleTooShortAlert(sessionData.socket);
topics.emitTitleTooShortAlert(socket);
return;
} else if (!data.content || data.content.length < parseInt(meta.config.minimumPostLength, 10)) {
module.parent.exports.emitContentTooShortAlert(sessionData.socket);
module.parent.exports.emitContentTooShortAlert(socket);
return;
}
postTools.edit(sessionData.uid, data.pid, data.title, data.content, data.images);
postTools.edit(socket.uid, data.pid, data.title, data.content);
callback();
};
SocketPosts.delete = function(data, callback, sessionData) {
postTools.delete(sessionData.uid, data.pid, function(err) {
SocketPosts.delete = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
postTools.delete(socket.uid, data.pid, function(err) {
if(err) {
return callback(err);
@ -117,32 +131,40 @@ SocketPosts.delete = function(data, callback, sessionData) {
module.parent.exports.emitTopicPostStats();
sessionData.server.sockets.in('topic_' + data.tid).emit('event:post_deleted', {
index.server.sockets.in('topic_' + data.tid).emit('event:post_deleted', {
pid: data.pid
});
callback(null);
callback();
});
};
SocketPosts.restore = function(data, callback, sessionData) {
postTools.restore(sessionData.uid, data.pid, function(err) {
SocketPosts.restore = function(socket, data, callback) {
if(!data) {
return callback(new Error('invalid data'));
}
postTools.restore(socket.uid, data.pid, function(err) {
if(err) {
return callback(err);
}
module.parent.exports.emitTopicPostStats();
sessionData.server.sockets.in('topic_' + data.tid).emit('event:post_restored', {
index.server.sockets.in('topic_' + data.tid).emit('event:post_restored', {
pid: data.pid
});
callback(null);
callback();
});
};
SocketPosts.getPrivileges = function(pid, callback, sessionData) {
postTools.privileges(pid, sessionData.uid, function(privileges) {
SocketPosts.getPrivileges = function(socket, pid, callback) {
postTools.privileges(pid, socket.uid, function(err, privileges) {
if(err) {
return callback(err);
}
privileges.pid = parseInt(pid);
callback(privileges);
callback(null, privileges);
});
};

@ -1,12 +1,15 @@
var topics = require('../topics'),
threadTools = require('../threadTools'),
index = require('./index'),
SocketTopics = {};
SocketTopics.post = function(data, callback, sessionData) {
var socket = sessionData.socket;
SocketTopics.post = function(socket, data, callback) {
if(!data) {
return callback(new Error('Invalid data'));
}
if (sessionData.uid < 1 && parseInt(meta.config.allowGuestPosting, 10) === 0) {
if (!socket.uid && !parseInt(meta.config.allowGuestPosting, 10)) {
socket.emit('event:alert', {
title: 'Post Unsuccessful',
message: 'You don&apos;t seem to be logged in, so you cannot reply.',
@ -16,7 +19,7 @@ SocketTopics.post = function(data, callback, sessionData) {
return;
}
topics.post(sessionData.uid, data.title, data.content, data.category_id, function(err, result) {
topics.post(socket.uid, data.title, data.content, data.category_id, function(err, result) {
if(err) {
if (err.message === 'title-too-short') {
module.parent.exports.emitAlert(socket, 'Title too short', 'Please enter a longer title. At least ' + meta.config.minimumTitleLength + ' characters.');
@ -45,9 +48,9 @@ SocketTopics.post = function(data, callback, sessionData) {
}
if (result) {
sessionData.server.sockets.in('category_' + data.category_id).emit('event:new_topic', result.topicData);
sessionData.server.sockets.in('recent_posts').emit('event:new_topic', result.topicData);
sessionData.server.sockets.in('user/' + sessionData.uid).emit('event:new_post', {
index.server.sockets.in('category_' + data.category_id).emit('event:new_topic', result.topicData);
index.server.sockets.in('recent_posts').emit('event:new_topic', result.topicData);
index.server.sockets.in('user/' + socket.uid).emit('event:new_post', {
posts: result.postData
});
@ -59,95 +62,73 @@ SocketTopics.post = function(data, callback, sessionData) {
type: 'success',
timeout: 2000
});
callback();
callback(null);
}
});
};
SocketTopics.postcount = function(tid, callback) {
SocketTopics.postcount = function(socket, tid, callback) {
topics.getTopicField(tid, 'postcount', callback);
};
SocketTopics.markAllRead = function(data, callback, sessionData) {
topics.markAllRead(sessionData.uid, function(err, success) {
if (!err && success) {
callback(true);
sessionData.server.sockets.in('uid_' + sessionData.uid).emit('event:unread.updateCount', 0);
} else {
callback(false);
SocketTopics.markAllRead = function(socket, data, callback) {
topics.markAllRead(socket.uid, function(err) {
if(err) {
return callback(err);
}
index.server.sockets.in('uid_' + socket.uid).emit('event:unread.updateCount', null, 0);
callback(null);
});
};
SocketTopics.delete = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.delete(data.tid, sessionData.uid, function(err) {
if (!err) {
module.parent.exports.emitTopicPostStats();
if (callback) {
callback('api:topic.delete', {
status: 'ok',
tid: data.tid
});
}
}
});
function doTopicAction(action, socket, tid, callback) {
if(!tid) {
return callback(new Error('Invalid tid'));
}
threadTools.privileges(tid, socket.uid, function(err, privileges) {
if(err) {
return callback(err);
}
});
};
SocketTopics.restore = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.restore(data.tid, sessionData.uid, function(err) {
module.parent.exports.emitTopicPostStats();
if(!privileges || !privileges.editable) {
return callback(new Error('not-allowed'));
}
if (callback) {
callback('api:topic.restore', {
status: 'ok',
tid: data.tid
});
}
});
if(threadTools[action]) {
threadTools[action](tid, socket.uid, callback);
}
});
}
SocketTopics.delete = function(socket, tid, callback) {
doTopicAction('delete', socket, tid, callback);
};
SocketTopics.lock = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.lock(data.tid, callback);
}
});
SocketTopics.restore = function(socket, tid, callback) {
doTopicAction('restore', socket, tid, callback);
};
SocketTopics.unlock = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.unlock(data.tid, callback);
}
});
SocketTopics.lock = function(socket, tid, callback) {
doTopicAction('lock', socket, tid, callback);
};
SocketTopics.pin = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.pin(data.tid, callback);
}
});
SocketTopics.unlock = function(socket, tid, callback) {
doTopicAction('unlock', socket, tid, callback);
};
SocketTopics.unpin = function(data, callback, sessionData) {
threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
if (!err && privileges.editable) {
threadTools.unpin(data.tid, callback);
}
});
SocketTopics.pin = function(socket, tid, callback) {
doTopicAction('pin', socket, tid, callback);
};
SocketTopics.unpin = function(socket, tid, callback) {
doTopicAction('unpin', socket, tid, callback);
};
SocketTopics.createTopicFromPosts = function(data, callback, sessionData) {
if(!sessionData.uid) {
SocketTopics.createTopicFromPosts = function(socket, data, callback) {
if(!socket.uid) {
socket.emit('event:alert', {
title: 'Can&apos;t fork',
message: 'Guests can&apos;t fork topics!',
@ -157,13 +138,15 @@ SocketTopics.createTopicFromPosts = function(data, callback, sessionData) {
return;
}
topics.createTopicFromPosts(sessionData.uid, data.title, data.pids, function(err, data) {
callback(err?{message:err.message}:null, data);
});
if(!data || !data.title || !data.pids || !Array.isArray(data.pids)) {
return callback(new Error('invalid data'));
}
topics.createTopicFromPosts(socket.uid, data.title, data.pids, callback);
};
SocketTopics.movePost = function(data, callback, sessionData) {
if(!sessionData.uid) {
SocketTopics.movePost = function(socket, data, callback) {
if(!socket.uid) {
socket.emit('event:alert', {
title: 'Can&apos;t fork',
message: 'Guests can&apos;t fork topics!',
@ -173,65 +156,74 @@ SocketTopics.movePost = function(data, callback, sessionData) {
return;
}
topics.movePostToTopic(data.pid, data.tid, function(err, data) {
callback(err?{message:err.message}:null, data);
});
};
if(!data || !data.pid || !data.tid) {
return callback(new Error('invalid data'));
}
SocketTopics.move = function(data, callback, sessionData) {
threadTools.move(data.tid, data.cid, callback, sessionData);
topics.movePostToTopic(data.pid, data.tid, callback);
};
SocketTopics.followCheck = function(tid, callback, sessionData) {
threadTools.isFollowing(tid, sessionData.uid, function(following) {
callback(following);
SocketTopics.move = function(socket, data, callback) {
if(!data || !data.tid || !data.cid) {
return callback(new Error('invalid data'));
}
threadTools.move(data.tid, data.cid, function(err) {
if(err) {
return callback(err);
}
index.server.sockets.in('topic_' + data.tid).emit('event:topic_moved', {
tid: data.tid
});
callback(null);
});
};
SocketTopics.follow = function(tid, callback, sessionData) {
if (sessionData.uid && sessionData.uid > 0) {
threadTools.toggleFollow(tid, sessionData.uid, function(follow) {
if (follow.status === 'ok') callback(follow);
});
} else {
callback({
status: 'error',
error: 'not-logged-in'
});
SocketTopics.followCheck = function(socket, tid, callback) {
threadTools.isFollowing(tid, socket.uid, callback);
};
SocketTopics.follow = function(socket, tid, callback) {
if(!socket.uid) {
return callback(new Error('not-logged-in'));
}
threadTools.toggleFollow(tid, socket.uid, callback);
};
SocketTopics.loadMore = function(data, callback, sessionData) {
SocketTopics.loadMore = function(socket, data, callback) {
if(!data || !data.tid) {
return callback(new Error('invalid data'));
}
var start = data.after,
end = start + 9;
topics.getTopicPosts(data.tid, start, end, sessionData.uid, function(err, posts) {
callback({
posts: posts
});
topics.getTopicPosts(data.tid, start, end, socket.uid, function(err, posts) {
callback(err, {posts: posts});
});
};
SocketTopics.loadMoreRecentTopics = function(data, callback, sessionData) {
SocketTopics.loadMoreRecentTopics = function(socket, data, callback) {
if(!data || !data.term) {
return callback(new Error('invalid data'));
}
var start = data.after,
end = start + 9;
topics.getLatestTopics(sessionData.uid, start, end, data.term, function(err, latestTopics) {
if (!err) {
callback(latestTopics);
} else {
winston.error('[socket api:topics.loadMoreRecentTopics] ' + err.message);
}
});
topics.getLatestTopics(socket.uid, start, end, data.term, callback);
};
SocketTopics.loadMoreUnreadTopics = function(data, callback, sessionData) {
SocketTopics.loadMoreUnreadTopics = function(socket, data, callback) {
var start = data.after,
end = start + 9;
topics.getUnreadTopics(sessionData.uid, start, end, function(unreadTopics) {
callback(unreadTopics);
});
topics.getUnreadTopics(socket.uid, start, end, callback);
};
module.exports = SocketTopics;

@ -3,149 +3,164 @@ var user = require('../user'),
SocketUser = {};
SocketUser.exists = function(data, sessionData) {
if (data.username) {
user.exists(utils.slugify(data.username), function(exists) {
sessionData.socket.emit('api:user.exists', {
exists: exists
});
});
SocketUser.exists = function(socket, data, callback) {
if (data && data.username) {
user.exists(utils.slugify(data.username), callback);
}
};
SocketUser.count = function(callback) {
SocketUser.count = function(socket, data, callback) {
user.count(callback);
};
SocketUser.emailExists = function(data, callback, sessionData) {
user.email.exists(undefined, data.email, callback);
SocketUser.emailExists = function(socket, data, callback) {
if(data && data.email) {
user.email.exists(data.email, callback);
}
};
// Password Reset
SocketUser.reset = {};
SocketUser.reset.send = function(data, sessionData) {
user.reset.send(sessionData.socket, data.email);
SocketUser.reset.send = function(socket, data, callback) {
if(data && data.email) {
user.reset.send(socket, data.email, callback);
}
};
SocketUser.reset.valid = function(data, sessionData) {
user.reset.validate(sessionData.socket, data.code);
SocketUser.reset.valid = function(socket, data, callback) {
if(data && data.code) {
user.reset.validate(socket, data.code, callback);
}
};
SocketUser.reset.commit = function(data, sessionData) {
user.reset.commit(sessionData.socket, data.code, data.password);
SocketUser.reset.commit = function(socket, data, callback) {
if(data && data.code && data.password) {
user.reset.commit(socket, data.code, data.password, callback);
}
};
SocketUser.isOnline = function(uid, callback) {
callback({
SocketUser.isOnline = function(socket, uid, callback) {
callback(null, {
online: module.parent.exports.isUserOnline(uid),
uid: uid,
timestamp: Date.now()
});
};
SocketUser.changePassword = function(data, callback, sessionData) {
user.changePassword(sessionData.uid, data, callback);
SocketUser.changePassword = function(socket, data, callback) {
if(data) {
user.changePassword(socket.uid, data, callback);
}
};
SocketUser.updateProfile = function(data, callback, sessionData) {
user.updateProfile(sessionData.uid, data, callback);
SocketUser.updateProfile = function(socket, data, callback) {
if(data) {
user.updateProfile(socket.uid, data, callback);
}
};
SocketUser.changePicture = function(data, callback, sessionData) {
SocketUser.changePicture = function(socket, data, callback) {
if(!data) {
return;
}
var type = data.type;
function updateHeader() {
user.getUserFields(sessionData.uid, ['picture'], function(err, fields) {
if (!err && fields) {
fields.uid = sessionData.uid;
sessionData.socket.emit('api:updateHeader', fields);
callback(true);
} else {
callback(false);
user.getUserFields(socket.uid, ['picture'], function(err, fields) {
if(err) {
return callback(err);
}
if (fields) {
fields.uid = socket.uid;
socket.emit('meta.updateHeader', null, fields);
}
callback(null);
});
}
if (type === 'gravatar') {
user.getUserField(sessionData.uid, 'gravatarpicture', function(err, gravatar) {
user.setUserField(sessionData.uid, 'picture', gravatar);
updateHeader();
});
type = 'gravatarpicture';
} else if (type === 'uploaded') {
user.getUserField(sessionData.uid, 'uploadedpicture', function(err, uploadedpicture) {
user.setUserField(sessionData.uid, 'picture', uploadedpicture);
updateHeader();
});
type = 'uploadedpicture';
} else {
callback(false);
return callback(new Error('invalid-image-type'));
}
user.getUserField(socket.uid, type, function(err, picture) {
user.setUserField(socket.uid, 'picture', picture);
updateHeader();
});
};
SocketUser.follow = function(data, callback, sessionData) {
if (sessionData.uid) {
user.follow(sessionData.uid, data.uid, callback);
SocketUser.follow = function(socket, data, callback) {
if (socket.uid && data) {
user.follow(socket.uid, data.uid, callback);
}
};
SocketUser.unfollow = function(data, callback, sessionData) {
if (sessionData.uid) {
user.unfollow(sessionData.uid, data.uid, callback);
SocketUser.unfollow = function(socket, data, callback) {
if (socket.uid && data) {
user.unfollow(socket.uid, data.uid, callback);
}
};
SocketUser.saveSettings = function(data, callback, sessionData) {
if (sessionData.uid) {
user.setUserFields(sessionData.uid, {
SocketUser.saveSettings = function(socket, data, callback) {
if (socket.uid && data) {
user.setUserFields(socket.uid, {
showemail: data.showemail
}, function(err, result) {
callback(err);
});
}, callback);
}
};
SocketUser.get_online_users = function(data, callback) {
SocketUser.getOnlineUsers = function(socket, data, callback) {
var returnData = [];
for (var i = 0; i < data.length; ++i) {
var uid = data[i];
if (module.parent.exports.isUserOnline(uid))
returnData.push(uid);
else
returnData.push(0);
if(data) {
for (var i = 0; i < data.length; ++i) {
var uid = data[i];
if (module.parent.exports.isUserOnline(uid)) {
returnData.push(uid);
} else {
returnData.push(0);
}
}
}
callback(returnData);
callback(null, returnData);
};
SocketUser.getOnlineAnonCount = function(data, callback) {
callback(module.parent.exports.getOnlineAnonCount());
SocketUser.getOnlineAnonCount = function(socket, data, callback) {
callback(null, module.parent.exports.getOnlineAnonCount());
};
SocketUser.getUnreadCount = function(callback, sessionData) {
topics.getUnreadTids(sessionData.uid, 0, 19, function(err, tids) {
callback(tids.length);
SocketUser.getUnreadCount = function(socket, data, callback) {
topics.getUnreadTids(socket.uid, 0, 19, function(err, tids) {
callback(err, tids?tids.length:0);
});
};
SocketUser.getActiveUsers = function(callback) {
SocketUser.getActiveUsers = function(socket, data, callback) {
module.parent.exports.emitOnlineUserCount(callback);
};
SocketUser.loadMore = function(data, callback) {
var start = data.after,
end = start + 19;
SocketUser.loadMore = function(socket, data, callback) {
if(data) {
var start = data.after,
end = start + 19;
user.getUsers(data.set, start, end, function(err, data) {
if(err) {
return callback(err);
}
user.getUsers(data.set, start, end, function(err, data) {
if (err) {
winston.err(err);
} else {
callback({
callback(null, {
users: data
});
}
});
});
}
};
/* Exports */

@ -66,13 +66,16 @@ var winston = require('winston'),
events.logTopicDelete(uid, tid);
websockets.emitTopicPostStats();
websockets.in('topic_' + tid).emit('event:topic_deleted', {
tid: tid,
status: 'ok'
tid: tid
});
if (callback) {
callback(null);
callback(null, {
tid: tid
});
}
}
@ -83,9 +86,10 @@ var winston = require('winston'),
events.logTopicRestore(uid, tid);
websockets.emitTopicPostStats();
websockets.in('topic_' + tid).emit('event:topic_restored', {
tid: tid,
status: 'ok'
tid: tid
});
topics.getTopicField(tid, 'title', function(err, title) {
@ -93,81 +97,75 @@ var winston = require('winston'),
});
if(callback) {
callback(null);
callback(null, {
tid:tid
});
}
}
ThreadTools.lock = function(tid, callback) {
ThreadTools.lock = function(tid, uid, callback) {
topics.setTopicField(tid, 'locked', 1);
websockets.in('topic_' + tid).emit('event:topic_locked', {
tid: tid,
status: 'ok'
tid: tid
});
if (callback) {
callback({
status: 'ok',
callback(null, {
tid: tid
});
}
}
ThreadTools.unlock = function(tid, callback) {
ThreadTools.unlock = function(tid, uid, callback) {
topics.setTopicField(tid, 'locked', 0);
websockets.in('topic_' + tid).emit('event:topic_unlocked', {
tid: tid,
status: 'ok'
tid: tid
});
if (callback) {
callback({
status: 'ok',
callback(null, {
tid: tid
});
}
}
ThreadTools.pin = function(tid, callback) {
ThreadTools.pin = function(tid, uid, callback) {
topics.setTopicField(tid, 'pinned', 1);
topics.getTopicField(tid, 'cid', function(err, cid) {
db.sortedSetAdd('categories:' + cid + ':tid', Math.pow(2, 53), tid);
});
websockets.in('topic_' + tid).emit('event:topic_pinned', {
tid: tid,
status: 'ok'
tid: tid
});
if (callback) {
callback({
status: 'ok',
callback(null, {
tid: tid
});
}
}
ThreadTools.unpin = function(tid, callback) {
ThreadTools.unpin = function(tid, uid, callback) {
topics.setTopicField(tid, 'pinned', 0);
topics.getTopicFields(tid, ['cid', 'lastposttime'], function(err, topicData) {
db.sortedSetAdd('categories:' + topicData.cid + ':tid', topicData.lastposttime, tid);
});
websockets.in('topic_' + tid).emit('event:topic_unpinned', {
tid: tid,
status: 'ok'
tid: tid
});
if (callback) {
callback({
status: 'ok',
callback(null, {
tid: tid
});
}
}
ThreadTools.move = function(tid, cid, callback, sessionData) {
ThreadTools.move = function(tid, cid, callback) {
topics.getTopicFields(tid, ['cid', 'lastposttime'], function(err, topicData) {
var oldCid = topicData.cid;
@ -175,9 +173,7 @@ var winston = require('winston'),
db.sortedSetAdd('categories:' + cid + ':tid', topicData.lastposttime, tid, function(err, result) {
if(err) {
return callback({
status: 'error'
});
return callback(err);
}
topics.setTopicField(tid, 'cid', cid);
@ -193,61 +189,46 @@ var winston = require('winston'),
categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1);
categories.incrementCategoryFieldBy(cid, 'topic_count', 1);
callback({
status: 'ok'
});
sessionData.server.sockets.in('topic_' + tid).emit('event:topic_moved', {
tid: tid
});
callback(null);
});
});
});
}
ThreadTools.isFollowing = function(tid, current_user, callback) {
db.isSetMember('tid:' + tid + ':followers', current_user, function(err, following) {
callback(following);
});
ThreadTools.isFollowing = function(tid, uid, callback) {
db.isSetMember('tid:' + tid + ':followers', uid, callback);
}
ThreadTools.toggleFollow = function(tid, current_user, callback) {
ThreadTools.isFollowing(tid, current_user, function(following) {
if (!following) {
db.setAdd('tid:' + tid + ':followers', current_user, function(err, success) {
if (callback) {
if (!err) {
callback({
status: 'ok',
follow: true
});
} else callback({
status: 'error'
});
}
});
} else {
db.setRemove('tid:' + tid + ':followers', current_user, function(err, success) {
if (callback) {
if (!err) {
callback({
status: 'ok',
follow: false
});
} else callback({
status: 'error'
});
}
});
ThreadTools.toggleFollow = function(tid, uid, callback) {
ThreadTools.isFollowing(tid, uid, function(err, following) {
if(err) {
return callback(err);
}
db[following?'setRemove':'setAdd']('tid:' + tid + ':followers', uid, function(err, success) {
if (callback) {
if(err) {
return callback(err);
}
callback(null, !following);
}
});
});
}
ThreadTools.getFollowers = function(tid, callback) {
db.getSetMembers('tid:' + tid + ':followers', function(err, followers) {
callback(err, followers.map(function(follower) {
return parseInt(follower, 10);
}));
if(err) {
return callback(err);
}
if(followers) {
followers = followers.map(function(follower) {
return parseInt(follower, 10);
});
}
callback(null, followers);
});
}

@ -75,19 +75,24 @@ var async = require('async'),
return callback(new Error('no-privileges'));
} else if (!cid) {
return callback(new Error('invalid-cid'));
} else if (!title || title.length < parseInt(meta.config.minimumTitleLength, 10)) {
}
if (title) {
title = title.trim();
}
if (!title || title.length < parseInt(meta.config.minimumTitleLength, 10)) {
return callback(new Error('title-too-short'), null);
} else if(title.length > parseInt(meta.config.maximumTitleLength, 10)) {
return callback(new Error('title-too-long'), null);
} else if (!content || content.length < meta.config.miminumPostLength) {
return callback(new Error('content-too-short'), null);
}
if (content) {
content = content.trim();
}
if (title) {
title = title.trim();
if (!content || content.length < meta.config.miminumPostLength) {
return callback(new Error('content-too-short'), null);
}
user.getUserField(uid, 'lastposttime', function(err, lastposttime) {
@ -257,7 +262,7 @@ var async = require('async'),
});
function move(pid, next) {
postTools.privileges(pid, uid, function(privileges) {
postTools.privileges(pid, uid, function(err, privileges) {
if(privileges.editable) {
Topics.movePostToTopic(pid, tid, next);
} else {
@ -379,9 +384,7 @@ var async = require('async'),
}
function getPrivileges(next) {
postTools.privileges(tid, current_user, function(privData) {
next(null, privData);
});
postTools.privileges(tid, current_user, next);
}
async.parallel([getFavouritesData, addUserInfoToPosts, getPrivileges], function(err, results) {
@ -449,7 +452,7 @@ var async = require('async'),
}
});
}, function(tids) {
Topics.getTopicsByTids(tids, current_user, function(topicData) {
Topics.getTopicsByTids(tids, 0, current_user, function(err, topicData) {
latestTopics.topics = topicData;
callback(err, latestTopics);
});
@ -471,8 +474,9 @@ var async = require('async'),
function(callback) {
db.getSortedSetRevRange('topics:recent', start, stop, function(err, tids) {
if (err)
if (err) {
return callback(err);
}
if (tids && !tids.length) {
done = true;
@ -494,7 +498,7 @@ var async = require('async'),
});
},
function(err) {
callback({
callback(null, {
count: unreadTids.length
});
}
@ -564,19 +568,22 @@ var async = require('async'),
'show_topic_button': 'hidden',
'show_markallread_button': 'show',
'no_topics_message': 'hidden',
'topic_row_size': 'col-md-12',
'topics': []
};
function noUnreadTopics() {
unreadTopics.no_topics_message = 'show';
unreadTopics.show_markallread_button = 'hidden';
callback(unreadTopics);
callback(null, unreadTopics);
}
function sendUnreadTopics(topicIds) {
Topics.getTopicsByTids(topicIds, uid, function(topicData) {
Topics.getTopicsByTids(topicIds, 0, uid, function(err, topicData) {
if(err) {
return callback(err);
}
unreadTopics.topics = topicData;
unreadTopics.nextStart = stop + 1;
if (!topicData || topicData.length === 0) {
@ -586,13 +593,13 @@ var async = require('async'),
unreadTopics.show_markallread_button = 'hidden';
}
callback(unreadTopics);
callback(null, unreadTopics);
});
}
Topics.getUnreadTids(uid, start, stop, function(err, unreadTids) {
if (err) {
return callback([]);
return callback(err);
}
if (unreadTids.length) {
@ -615,7 +622,7 @@ var async = require('async'),
async.each(uids, function(uid, next) {
Topics.getUnreadTids(uid, 0, 19, function(err, tids) {
websockets.in('uid_' + uid).emit('event:unread.updateCount', tids.length);
websockets.in('uid_' + uid).emit('event:unread.updateCount', null, tids.length);
next();
});
}, function(err) {
@ -629,13 +636,12 @@ var async = require('async'),
});
};
Topics.getTopicsByTids = function(tids, current_user, callback, category_id) {
Topics.getTopicsByTids = function(tids, cid, current_user, callback) {
var retrieved_topics = [];
if (!Array.isArray(tids) || tids.length === 0) {
callback(retrieved_topics);
return;
return callback(null, retrieved_topics);
}
function getTopicInfo(topicData, callback) {
@ -659,19 +665,19 @@ var async = require('async'),
// temporary. I don't think this call should belong here
function getPrivileges(next) {
categoryTools.privileges(category_id, current_user, function(err, user_privs) {
next(err, user_privs);
});
categoryTools.privileges(cid, current_user, next);
}
function getCategoryInfo(next) {
categories.getCategoryFields(topicData.cid, ['name', 'slug', 'icon'], function(err, categoryData) {
next(err, categoryData);
});
categories.getCategoryFields(topicData.cid, ['name', 'slug', 'icon'], next);
}
async.parallel([getUserInfo, hasReadTopic, getTeaserInfo, getPrivileges, getCategoryInfo], function(err, results) {
callback({
if(err) {
return callback(err);
}
callback(null, {
username: results[0].username,
userslug: results[0].userslug,
picture: results[0].picture,
@ -689,13 +695,20 @@ var async = require('async'),
return !deleted || (deleted && topicInfo.privileges.view_deleted) || topicData.uid === current_user;
}
function loadTopic(tid, callback) {
function loadTopic(tid, next) {
Topics.getTopicData(tid, function(err, topicData) {
if(err) {
return next(err);
}
if (!topicData) {
return callback(null);
return next();
}
getTopicInfo(topicData, function(topicInfo) {
getTopicInfo(topicData, function(err, topicInfo) {
if(err) {
return next(err);
}
topicData['pin-icon'] = parseInt(topicData.pinned, 10) === 1 ? 'fa-thumb-tack' : 'none';
topicData['lock-icon'] = parseInt(topicData.locked, 10) === 1 ? 'fa-lock' : 'none';
@ -715,18 +728,17 @@ var async = require('async'),
topicData.teaser_pid = topicInfo.teaserInfo.pid;
topicData.teaser_timestamp = topicInfo.teaserInfo.timestamp ? (new Date(parseInt(topicInfo.teaserInfo.timestamp, 10)).toISOString()) : '';
if (isTopicVisible(topicData, topicInfo))
if (isTopicVisible(topicData, topicInfo)) {
retrieved_topics.push(topicData);
}
callback(null);
next(null);
});
});
}
async.eachSeries(tids, loadTopic, function(err) {
if (!err) {
callback(retrieved_topics);
}
callback(err, retrieved_topics);
});
}
@ -888,7 +900,7 @@ var async = require('async'),
Topics.markAllRead = function(uid, callback) {
db.getSetMembers('topics:tid', function(err, tids) {
if (err) {
return callback(err, null);
return callback(err);
}
if (tids && tids.length) {
@ -897,7 +909,7 @@ var async = require('async'),
}
}
callback(null, true);
callback(null);
});
}

@ -46,7 +46,10 @@ var bcrypt = require('bcrypt'),
}
},
function(next) {
User.exists(userslug, function(exists) {
User.exists(userslug, function(err, exists) {
if (err) {
return next(err);
}
next(exists ? new Error('Username taken!') : null);
});
},
@ -193,9 +196,7 @@ var bcrypt = require('bcrypt'),
function isSignatureValid(next) {
if (data.signature !== undefined && data.signature.length > meta.config.maximumSignatureLength) {
next({
error: 'Signature can\'t be longer than ' + meta.config.maximumSignatureLength + ' characters!'
}, false);
next(new Error('Signature can\'t be longer than ' + meta.config.maximumSignatureLength + ' characters!'), false);
} else {
next(null, true);
}
@ -217,9 +218,7 @@ var bcrypt = require('bcrypt'),
}
if (!available) {
next({
error: 'Email not available!'
}, false);
next(new Error('Email not available!'), false);
} else {
next(null, true);
}
@ -237,16 +236,16 @@ var bcrypt = require('bcrypt'),
}
if(!utils.isUserNameValid(data.username) || !userslug) {
return next({
error: 'Invalid Username!'
}, false);
return next(new Error('Invalid Username!'), false);
}
User.exists(userslug, function(exists) {
User.exists(userslug, function(err, exists) {
if(err) {
return next(err);
}
if(exists) {
next({
error: 'Username not available!'
}, false);
next(new Error('Username not available!'), false);
} else {
next(null, true);
}
@ -348,13 +347,11 @@ var bcrypt = require('bcrypt'),
User.changePassword = function(uid, data, callback) {
if (!utils.isPasswordValid(data.newPassword)) {
return callback({
error: 'Invalid password!'
});
return callback(new Error('Invalid password!'));
}
User.getUserField(uid, 'password', function(err, user_password) {
bcrypt.compare(data.currentPassword, user_password, function(err, res) {
User.getUserField(uid, 'password', function(err, currentPassword) {
bcrypt.compare(data.currentPassword, currentPassword, function(err, res) {
if (err) {
return callback(err);
}
@ -366,9 +363,7 @@ var bcrypt = require('bcrypt'),
callback(null);
});
} else {
callback({
error: 'Your current password is not correct!'
});
callback(new Error('Your current password is not correct!'));
}
});
});
@ -542,31 +537,21 @@ var bcrypt = require('bcrypt'),
User.follow = function(uid, followid, callback) {
db.setAdd('following:' + uid, followid, function(err, data) {
if (!err) {
db.setAdd('followers:' + followid, uid, function(err, data) {
if (!err) {
callback(true);
} else {
console.log(err);
callback(false);
}
});
} else {
console.log(err);
callback(false);
if(err) {
return callback(err);
}
db.setAdd('followers:' + followid, uid, callback);
});
};
User.unfollow = function(uid, unfollowid, callback) {
db.setRemove('following:' + uid, unfollowid, function(err, data) {
if (!err) {
db.setRemove('followers:' + unfollowid, uid, function(err, data) {
callback(data);
});
} else {
console.log(err);
if(err) {
return callback(err);
}
db.setRemove('followers:' + unfollowid, uid, callback);
});
};
@ -667,17 +652,17 @@ var bcrypt = require('bcrypt'),
User.exists = function(userslug, callback) {
User.getUidByUserslug(userslug, function(err, exists) {
callback( !! exists);
callback(err, !! exists);
});
};
User.count = function(callback) {
db.getObjectField('global', 'userCount', function(err, count) {
if(err) {
return;
return callback(err);
}
callback({
callback(null, {
count: count ? count : 0
});
});
@ -785,92 +770,70 @@ var bcrypt = require('bcrypt'),
User.reset = {
validate: function(socket, code, callback) {
if (typeof callback !== 'function') {
callback = null;
}
db.getObjectField('reset:uid', code, function(err, uid) {
if (err) {
return callback(false);
return callback(err);
}
if (uid !== null) {
db.getObjectField('reset:expiry', code, function(err, expiry) {
if (err) {
return callback(false);
return callback(err);
}
if (expiry >= +Date.now() / 1000 | 0) {
if (!callback) {
socket.emit('user:reset.valid', {
valid: true
});
} else {
callback(true);
}
callback(null, true);
} else {
// Expired, delete from db
db.deleteObjectField('reset:uid', code);
db.deleteObjectField('reset:expiry', code);
if (!callback) {
socket.emit('user:reset.valid', {
valid: false
});
} else {
callback(false);
}
callback(null, false);
}
});
} else {
if (!callback) {
socket.emit('user:reset.valid', {
valid: false
});
} else {
callback(false);
}
callback(null, false);
}
});
},
send: function(socket, email) {
send: function(socket, email, callback) {
User.getUidByEmail(email, function(err, uid) {
if (uid !== null) {
// Generate a new reset code
var reset_code = utils.generateUUID();
db.setObjectField('reset:uid', reset_code, uid);
db.setObjectField('reset:expiry', reset_code, (60 * 60) + new Date() / 1000 | 0); // Active for one hour
if(err) {
return callback(err);
}
var reset_link = nconf.get('url') + 'reset/' + reset_code;
if(!uid) {
return callback(new Error('invalid-email'));
}
Emailer.send('reset', uid, {
'site_title': (meta.config['title'] || 'NodeBB'),
'reset_link': reset_link,
// Generate a new reset code
var reset_code = utils.generateUUID();
db.setObjectField('reset:uid', reset_code, uid);
db.setObjectField('reset:expiry', reset_code, (60 * 60) + new Date() / 1000 | 0); // Active for one hour
subject: 'Password Reset Requested - ' + (meta.config['title'] || 'NodeBB') + '!',
template: 'reset',
uid: uid
});
var reset_link = nconf.get('url') + 'reset/' + reset_code;
socket.emit('user.send_reset', {
status: "ok",
message: "code-sent",
email: email
});
} else {
socket.emit('user.send_reset', {
status: "error",
message: "invalid-email",
email: email
});
}
Emailer.send('reset', uid, {
'site_title': (meta.config['title'] || 'NodeBB'),
'reset_link': reset_link,
subject: 'Password Reset Requested - ' + (meta.config['title'] || 'NodeBB') + '!',
template: 'reset',
uid: uid
});
callback(null);
});
},
commit: function(socket, code, password) {
this.validate(socket, code, function(validated) {
commit: function(socket, code, password, callback) {
this.validate(socket, code, function(err, validated) {
if(err) {
return callback(err);
}
if (validated) {
db.getObjectField('reset:uid', code, function(err, uid) {
if (err) {
return;
return callback(err);
}
User.hashPassword(password, function(err, hash) {
@ -881,9 +844,7 @@ var bcrypt = require('bcrypt'),
db.deleteObjectField('reset:uid', code);
db.deleteObjectField('reset:expiry', code);
socket.emit('user:reset.commit', {
status: 'ok'
});
callback(null);
});
}
});
@ -932,9 +893,9 @@ var bcrypt = require('bcrypt'),
});
});
},
exists: function(socket, email, callback) {
exists: function(email, callback) {
User.getUidByEmail(email, function(err, exists) {
callback(!!exists);
callback(err, !!exists);
});
},
confirm: function(code, callback) {
@ -1031,7 +992,7 @@ var bcrypt = require('bcrypt'),
notifications.read.length = maxNotifs - notifications.unread.length;
}
callback(notifications);
callback(err, notifications);
});
},
getAll: function(uid, limit, before, callback) {

@ -44,7 +44,7 @@ describe('Categories', function() {
describe('.getCategoryTopics', function() {
it('should return a list of topics', function(done) {
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(topics) {
Categories.getCategoryTopics(categoryObj.cid, 0, 10, 0, function(err, topics) {
assert(Array.isArray(topics));
assert(topics.every(function(topic) {
return topic instanceof Object;

Loading…
Cancel
Save