diff --git a/public/src/forum/admin/topics.js b/public/src/forum/admin/topics.js
index e5490445e9..0d863f4550 100644
--- a/public/src/forum/admin/topics.js
+++ b/public/src/forum/admin/topics.js
@@ -15,37 +15,25 @@ define(function() {
 			switch (action) {
 				case 'pin':
 					if (!$this.hasClass('active')) {
-						socket.emit('topics.pin', {
-							tid: tid
-						}, Topics.pin);
+						socket.emit('topics.pin', tid, Topics.pin);
 					} else {
-						socket.emit('topics.unpin', {
-							tid: tid
-						}, Topics.unpin);
+						socket.emit('topics.unpin', tid, Topics.unpin);
 					}
 					break;
 
 				case 'lock':
 					if (!$this.hasClass('active')) {
-						socket.emit('topics.lock', {
-							tid: tid
-						}, Topics.lock);
+						socket.emit('topics.lock', tid, Topics.lock);
 					} else {
-						socket.emit('topics.unlock', {
-							tid: tid
-						}, Topics.unlock);
+						socket.emit('topics.unlock', tid, Topics.unlock);
 					}
 					break;
 
 				case 'delete':
 					if (!$this.hasClass('active')) {
-						socket.emit('topics.delete', {
-							tid: tid
-						}, Topics.setDeleted);
+						socket.emit('topics.delete', tid, Topics.setDeleted);
 					} else {
-						socket.emit('topics.restore', {
-							tid: tid
-						}, Topics.restore);
+						socket.emit('topics.restore', tid, Topics.restore);
 					}
 					break;
 
@@ -116,8 +104,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 +117,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 +130,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 +155,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');
diff --git a/public/src/forum/topic.js b/public/src/forum/topic.js
index 379eb38b96..6a621551bb 100644
--- a/public/src/forum/topic.js
+++ b/public/src/forum/topic.js
@@ -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('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('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('topics.lock', {
-							tid: tid
-						}, null);
+						socket.emit('topics.lock', tid);
 					} else {
-						socket.emit('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('topics.pin', {
-							tid: tid
-						}, null);
+						socket.emit('topics.pin', tid);
 					} else {
-						socket.emit('topics.unpin', {
-							tid: tid
-						}, null);
+						socket.emit('topics.unpin', tid);
 					}
 					return false;
 				});
@@ -629,45 +619,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) {
diff --git a/public/src/forum/unread.js b/public/src/forum/unread.js
index bec5388f27..57fadb557a 100644
--- a/public/src/forum/unread.js
+++ b/public/src/forum/unread.js
@@ -55,19 +55,19 @@ define(function() {
 
 		$('#mark-allread-btn').on('click', function() {
 			var btn = $(this);
-			socket.emit('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');
 			});
 		});
 
diff --git a/src/socket.io/topics.js b/src/socket.io/topics.js
index de652f0658..f15638b3ea 100644
--- a/src/socket.io/topics.js
+++ b/src/socket.io/topics.js
@@ -5,7 +5,11 @@ var topics = require('../topics'),
 
 SocketTopics.post = function(socket, data, callback) {
 
-	if (socket.uid < 1 && parseInt(meta.config.allowGuestPosting, 10) === 0) {
+	if(!data) {
+		return callback(new Error('Invalid data'));
+	}
+
+	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.',
@@ -58,7 +62,7 @@ SocketTopics.post = function(socket, data, callback) {
 				type: 'success',
 				timeout: 2000
 			});
-			callback();
+			callback(null);
 		}
 	});
 };
@@ -68,122 +72,59 @@ SocketTopics.postcount = function(socket, tid, callback) {
 };
 
 SocketTopics.markAllRead = function(socket, data, callback) {
-	topics.markAllRead(socket.uid, function(err, success) {
-		if (!err && success) {
-			callback(true);
-			index.server.sockets.in('uid_' + socket.uid).emit('event:unread.updateCount', 0);
-		} else {
-			callback(false);
-		}
-	});
-};
-
-SocketTopics.delete = function(socket, data, callback) {
-	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
+	topics.markAllRead(socket.uid, function(err) {
 		if(err) {
 			return callback(err);
 		}
 
-		if(!privileges.editable) {
-			return callback(new Error('not-allowed'));
-		}
+		index.server.sockets.in('uid_' + socket.uid).emit('event:unread.updateCount', 0);
 
-		threadTools.delete(data.tid, socket.uid, function(err) {
-			if(err) {
-				return callback(err);
-			}
-
-			module.parent.exports.emitTopicPostStats();
-
-
-			callback(null, 'topic.delete', {
-				status: 'ok',
-				tid: data.tid
-			});
-		});
+		callback(null);
 	});
 };
 
-SocketTopics.restore = function(socket, data, callback) {
-	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
-		if(err) {
-			return callback(err);
-		}
-
-		if(!privileges.editable) {
-			return callback(new Error('not-allowed'));
-		}
-
-		threadTools.restore(data.tid, socket.uid, function(err) {
-			if(err) {
-				return callback(err);
-			}
-
-			module.parent.exports.emitTopicPostStats();
-
-			callback(null, 'topic.restore', {
-				status: 'ok',
-				tid: data.tid
-			});
-		});
-
-	});
-};
+function doTopicAction(action, socket, tid, callback) {
+	if(!tid) {
+		return callback(new Error('Invalid tid'));
+	}
 
-SocketTopics.lock = function(socket, data, callback) {
-	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
+	threadTools.privileges(tid, socket.uid, function(err, privileges) {
 		if(err) {
 			return callback(err);
 		}
 
-		if (!privileges.editable) {
+		if(!privileges || !privileges.editable) {
 			return callback(new Error('not-allowed'));
 		}
 
-		threadTools.lock(data.tid, callback);
-	});
-};
-
-SocketTopics.unlock = function(socket, data, callback) {
-	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
-		if(err) {
-			return callback(err);
+		if(threadTools[action]) {
+			threadTools[action](tid, socket.uid, callback);
 		}
-
-		if (!privileges.editable) {
-			return callback(new Error('not-allowed'));
-		}
-
-		threadTools.unlock(data.tid, callback);
 	});
-};
+}
 
-SocketTopics.pin = function(socket, data, callback) {
-	threadTools.privileges(data.tid, sessionData.uid, function(err, privileges) {
-		if(err) {
-			return callback(err);
-		}
+SocketTopics.delete = function(socket, tid, callback) {
+	doTopicAction('delete', socket, tid, callback);
+};
 
-		if (!privileges.editable) {
-			return callback(new Error('not-allowed'));
-		}
+SocketTopics.restore = function(socket, tid, callback) {
+	doTopicAction('restore', socket, tid, callback);
+};
 
-		threadTools.pin(data.tid, callback);
-	});
+SocketTopics.lock = function(socket, tid, callback) {
+	doTopicAction('lock', socket, tid, callback);
 };
 
-SocketTopics.unpin = function(socket, data, callback) {
-	threadTools.privileges(data.tid, socket.uid, function(err, privileges) {
-		if(err) {
-			return callback(err);
-		}
+SocketTopics.unlock = function(socket, tid, callback) {
+	doTopicAction('unlock', socket, tid, callback);
+};
 
-		if (!privileges.editable) {
-			return callback(new Error('not-allowed'));
-		}
+SocketTopics.pin = function(socket, tid, callback) {
+	doTopicAction('pin', socket, tid, callback);
+};
 
-		threadTools.unpin(data.tid, callback);
-	});
+SocketTopics.unpin = function(socket, tid, callback) {
+	doTopicAction('unpin', socket, tid, callback);
 };
 
 SocketTopics.createTopicFromPosts = function(socket, data, callback) {
diff --git a/src/threadTools.js b/src/threadTools.js
index aa1ce99dba..8ba6ee7e71 100644
--- a/src/threadTools.js
+++ b/src/threadTools.js
@@ -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,75 +97,69 @@ 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
 			});
 		}
@@ -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,10 +189,7 @@ var winston = require('winston'),
 					categories.incrementCategoryFieldBy(oldCid, 'topic_count', -1);
 					categories.incrementCategoryFieldBy(cid, 'topic_count', 1);
 
-					callback({
-						status: 'ok'
-					});
-
+					callback(null);
 				});
 			});
 		});
diff --git a/src/topics.js b/src/topics.js
index f2e245d72a..fb754cdf78 100644
--- a/src/topics.js
+++ b/src/topics.js
@@ -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) {
@@ -888,7 +893,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 +902,7 @@ var async = require('async'),
 				}
 			}
 
-			callback(null, true);
+			callback(null);
 		});
 	}