diff --git a/socketserver/db_mysql.js b/socketserver/db_mysql.js index 580d40b..244d095 100644 --- a/socketserver/db_mysql.js +++ b/socketserver/db_mysql.js @@ -139,6 +139,12 @@ var MysqlDB = function(){ `time` DATETIME\ );\ \ + CREATE TABLE IF NOT EXISTS `user_blocks` (\ + `from` INTEGER UNSIGNED NOT NULL,\ + `to` INTEGER UNSIGNED NOT NULL,\ + PRIMARY KEY(`from`, `to`)\ + );\ + \ UPDATE `users` SET `lastdj` = false;\ ", null, function(err, res){ if(err) throw new Error(err); @@ -476,12 +482,16 @@ MysqlDB.prototype.getUserNoLogin = function(uid, callback){ un: res.un, uid: res.id, salt: res.salt, + blocked: [], } - that.execute("SELECT `id` FROM `playlists` WHERE `owner` = ?;", [ uid ], function(err, res) { + that.execute("SELECT `id` FROM `playlists` WHERE ?; SELECT `to` FROM `user_blocks` WHERE ?", [ { owner: uid, }, { from: uid,} ], function(err, res) { - for(var ind in res) - data.playlists.push(res[ind].id); + for(var ind in res[0]) + data.playlists.push(res[0][ind].id); + + for(var ind in res[1]) + data.blocked.push(res[1][ind].to); callback(null, data); }); @@ -634,11 +644,15 @@ MysqlDB.prototype.loginUser = function(obj, callback) { }; MysqlDB.prototype.putUser = function(email, data, callback) { + var that = this; + callback = callback || function(){}; var newData = {}; util._extend(newData, data); + var blocked = newData.blocked.map(function(x) { return [data.uid, x]; }); + newData.badge_bottom = newData.badge.bottom; newData.badge_top = newData.badge.top; newData.recovery_timeout = new Date(newData.recovery.timeout); @@ -649,9 +663,17 @@ MysqlDB.prototype.putUser = function(email, data, callback) { delete newData.uid; delete newData.badge; delete newData.playlists; - this.execute("INSERT INTO `users`(??) VALUES(?) ON DUPLICATE KEY UPDATE ?;", [ Object.keys(newData), _.values(newData), newData ], function(err, res) { - if(err) callback(err); - else callback(null, res.insertId); + delete newData.blocked; + + this.execute("INSERT INTO `users`(??) VALUES(?) ON DUPLICATE KEY UPDATE ?; DELETE FROM `user_blocks` WHERE ?;", [ Object.keys(newData), _.values(newData), newData, { from: data.uid } ], function(err, res) { + if(err) + callback(err); + else + callback(null, res.insertId); + + if(blocked.length) { + that.execute("INSERT INTO `user_blocks`(??) VALUES ?;", [ [ 'from', 'to' ], blocked ]); + } }); }; diff --git a/socketserver/socketserver.js b/socketserver/socketserver.js index 48e3eb3..fead46a 100644 --- a/socketserver/socketserver.js +++ b/socketserver/socketserver.js @@ -3078,6 +3078,74 @@ var SocketServer = function(server){ else DB.getUserByUid(~~(data.data.uid), { getPlaylists: false }, cb); break; + case 'blockUser': + /* + Expects { + type: 'blockUser', + data: { + uid: uid, + } + } + */ + + //Check for props + if (!(data.data.uid = +data.data.uid) || uid < 0){ + returnObj.data = { + error: 'WrongProps' + }; + socket.sendJSON(returnObj); + break; + } + + //Add blocked user + socket.user.addBlockedUser(data.data.uid, function(err) { + if(err) { + returnObj.data = { + error: err + } + } else { + returnObj.data = { + success: true + } + } + + socket.sendJSON(returnObj); + }); + break; + case 'unblockUser': + /* + Expects { + type: 'unblockUser', + data: { + uid: uid, + } + } + */ + + //Check for props + if (!(data.data.uid = +data.data.uid)){ + returnObj.data = { + error: 'WrongProps' + }; + socket.sendJSON(returnObj); + break; + } + + //Remove blocked user + socket.user.removeBlockedUser(data.data.uid, function(err) { + if(err) { + returnObj.data = { + error: err + } + } else { + returnObj.data = { + success: true + } + } + + socket.sendJSON(returnObj); + }); + break; } }); }); diff --git a/socketserver/user.js b/socketserver/user.js index 2d47a6b..a37a2c9 100644 --- a/socketserver/user.js +++ b/socketserver/user.js @@ -23,6 +23,7 @@ var defaultObj = function(){ temp_uptime: Date.now(), lastdj: false, salt: '', + blocked: [], }; }; @@ -39,6 +40,7 @@ var fieldsNotSent = [ 'created', 'lastdj', 'salt', + 'blocked', ]; // These fields (key from defaultObj) are not saved in the db @@ -180,6 +182,35 @@ User.prototype.removePlaylist = function (pid, callback) { callback('PlaylistNotFound'); }; +User.prototype.addBlockedUser = function(uid, callback) { + var index = this.data.blocked.indexOf(uid); + + if(index != -1) { + callback('UserAlreadyBlocked'); + + } else if(this.data.uid == uid) { + callback('CannotBlockSelf'); + + } else { + this.data.blocked.push(uid); + this.updateUser(); + callback(null, true); + } +}; + +User.prototype.removeBlockedUser = function(uid, callback) { + var index = this.data.blocked.indexOf(uid); + + if(index == -1) { + callback('UserNotBlocked'); + + } else { + this.data.blocked.splice(index, 1); + this.updateUser(); + callback(null, true); + } +} + /** * getClientObj() Returns public information to be sent to clients * @@ -361,4 +392,14 @@ Object.defineProperty( User.prototype, 'salt', { } }); +Object.defineProperty( User.prototype, 'blocked', { + get: function() { + return this.data.blocked; + }, + set: function(val) { + this.data.blocked = val; + this.updateUser(); + } +}); + module.exports = User; \ No newline at end of file diff --git a/webserver/public/lib/js/app.js b/webserver/public/lib/js/app.js index f38032c..a35b1b3 100644 --- a/webserver/public/lib/js/app.js +++ b/webserver/public/lib/js/app.js @@ -261,6 +261,7 @@ historylimit: 50, lastdj: false, description: '', + blockedusers: [], }, isOnWaitlist: function(uid){ if (MP.session.queue.currentdj && MP.session.queue.currentdj.uid == uid) return true; @@ -1580,6 +1581,54 @@ $('#creds-back').hide(); $('.dash, #app-left, #app-right').show(); }, + user: { + isBlocked: function(uid) { + return MP.session.blockedusers.indexOf(uid) != -1; + }, + block: function(uid, callback) { + if(!(uid = +uid)) + return false + + var obj = { + type: 'blockUser', + data: { + uid: uid + } + } + + obj.id = MP.addCallback(obj.type, function(err, data) { + MP.session.blockedusers.push(uid); + + if(callback) + callback(err, data); + }); + + socket.sendJSON(obj); + }, + unblock: function(uid, callback) { + if(!(uid = +uid)) + return false + + var obj = { + type: 'unblockUser', + data: { + uid: uid + } + } + + obj.id = MP.addCallback(obj.type, function(err, data) { + var index = MP.session.blockedusers.indexOf(uid); + + if(index != -1) + MP.session.blockedusers.splice(index, 1); + + if(callback) + callback(err, data); + }); + + socket.sendJSON(obj); + } + }, }, mediaPreview : { isOpened: function(){return MP.session.mediaPreview.player != null;}, @@ -1923,6 +1972,9 @@ } var user = data.user || MP.findUser(data.uid); + if(MP.api.user.isBlocked(user.uid)) + return; + var queue_pos = MP.findPosInWaitlist(); var mention = ''; @@ -2550,6 +2602,38 @@ }); }, }, + + block: { + description: 'Blocks or unblocks a user, blocking will remove any further messages from him', + exec: function(arr){ + arr.shift(); + + if (arr.length != 1 || typeof arr[0] != 'string' || arr[0].charAt(0)!='@' || (arr[1] = +arr[1])){ + return API.chat.log('
Try /block @username', 'Block a user'); + } + + var user = MP.api.room.getUserByName(arr[0].substring(1)); + + if (!user) + return API.chat.log('User ' + arr[0] + ' is not in the pad', 'Block or unblock a user'); + + if(MP.api.user.isBlocked(user.uid)) { + MP.api.user.unblock(user.uid, function(err) { + if(err) + return API.chat.log('Could not unblock user ' + arr[0]); + + API.chat.log('User ' + arr[0] + ' successfully unblocked'); + }) + } else { + MP.api.user.block(user.uid, function(err) { + if(err) + return API.chat.log('Could not block user ' + arr[0]); + + API.chat.log('User ' + arr[0] + ' successfully blocked'); + }) + } + }, + }, }, sendMessage: function(message, staff){ staff = staff || false; @@ -4256,7 +4340,7 @@