diff --git a/database.js b/database.js index a0c201b5..fa5c4f87 100644 --- a/database.js +++ b/database.js @@ -125,6 +125,18 @@ function init() { if(!results) { Logger.errlog.log("! Failed to create password reset table"); } + + // Create user playlist table + query = ["CREATE TABLE IF NOT EXISTS `user_playlists` (", + "`user` VARCHAR(20) NOT NULL,", + "`name` VARCHAR(255) NOT NULL,", + "`contents` MEDIUMTEXT NOT NULL,", + "PRIMARY KEY (`name`))", + "ENGINE = MyISAM;"].join(""); + results = db.querySync(query); + if(!results) { + Logger.errlog.log("! Failed to create playlist table"); + } } /* REGION Global Bans */ @@ -733,6 +745,88 @@ function resetPassword(name) { return pw; } +/* REGION User Playlists */ +function getUserPlaylists(user) { + var db = getConnection(); + if(!db) { + []; + } + + var query = createQuery( + "SELECT name FROM user_playlists WHERE user=?", + [user] + ); + + var results = db.querySync(query); + if(!results) { + Logger.errlog.log("! Failed to query user playlists"); + return []; + } + + return results.fetchAllSync(); +} + +function loadUserPlaylist(user, name) { + var db = getConnection(); + if(!db) { + []; + } + + var query = createQuery( + "SELECT contents FROM user_playlists WHERE user=? AND name=?", + [user, name] + ); + + var results = db.querySync(query); + if(!results) { + Logger.errlog.log("! Failed to query playlists"); + return []; + } + + var row = results.fetchAllSync()[0]; + var pl; + try { + pl = JSON.parse(row.contents); + } + catch(e) { + Logger.errlog.log("! Failed to load playlist "+user+"."+name); + return []; + } + + return pl; +} + +function saveUserPlaylist(pl, user, name) { + var db = getConnection(); + if(!db) { + return false; + } + + // Strip out unnecessary data + var pl2 = []; + for(var i = 0; i < pl.length; i++) { + var e = { + id: pl[i].id, + type: pl[i].type + }; + pl2.push(e); + } + var plstr = JSON.stringify(pl2); + + var query = createQuery( + "INSERT INTO user_playlists VALUES (?, ?, ?)", + [user, name, plstr] + ); + + var results = db.querySync(query); + if(!results) { + Logger.errlog.log("! Failed to insert into playlists"); + return false; + } + + return true; +} + exports.setup = setup; exports.getConnection = getConnection; exports.createQuery = createQuery; @@ -758,3 +852,6 @@ exports.setUserEmail = setUserEmail; exports.generatePasswordReset = generatePasswordReset; exports.recoverPassword = recoverPassword; exports.resetPassword = resetPassword; +exports.getUserPlaylists = getUserPlaylists; +exports.loadUserPlaylist = loadUserPlaylist; +exports.saveUserPlaylist = saveUserPlaylist; diff --git a/user.js b/user.js index cc6d5326..14c87059 100644 --- a/user.js +++ b/user.js @@ -414,6 +414,50 @@ User.prototype.initCallbacks = function() { } } }.bind(this)); + + this.socket.on("listPlaylists", function(data) { + if(this.name == "" || this.rank < 1) { + socket.emit("listPlaylists", { + pllist: [], + error: "You must be logged in to manage playlists" + }); + return; + } + + var list = Database.getUserPlaylists(this.name); + socket.emit("listPlaylists", { + pllist: list, + }); + }.bind(this)); + + this.socket.on("savePlaylist", function(data) { + if(this.rank < 1) { + socket.emit("savePlaylist", { + success: false, + error: "You must be logged in to manage playlists" + }); + return; + } + + if(this.channel == null) { + socket.emit("savePlaylist", { + success: false, + error: "Not in a channel" + }); + return; + } + + if(typeof data.name != "string") { + return; + } + + var pl = this.channel.queue; + var result = Database.saveUserPlaylist(pl, this.name, data.name); + this.socket.emit("savePlaylist", { + success: result, + error: result ? false : "Unknown" + }); + }.bind(this)); } // Handle administration diff --git a/www/assets/js/callbacks.js b/www/assets/js/callbacks.js index 2e5c86d2..5ef24636 100644 --- a/www/assets/js/callbacks.js +++ b/www/assets/js/callbacks.js @@ -573,7 +573,8 @@ Callbacks = { }, queueFail: function() { - alert("Queue failed. Double check your link to make sure the video exists."); + makeAlert("Error", "Queue failed. Check your link to make sure it is valid.", "alert-error") + .insertAfter($("#playlist_controls")); }, setTemp: function(data) { @@ -738,7 +739,17 @@ Callbacks = { closePoll: function() { // Not recursive closePoll(); - } + }, + + savePlaylist: function(data) { + if(data.success) { + makeAlert("Success", "Playlist saved.", "alert-success"); + } + else { + alert("DBG error " + data.error); + makeAlert("Error", data.error, "alert-error"); + } + }, } $.getScript(IO_URL+"/socket.io/socket.io.js", function() { diff --git a/www/assets/js/functions.js b/www/assets/js/functions.js index f42278bd..68981bde 100644 --- a/www/assets/js/functions.js +++ b/www/assets/js/functions.js @@ -1316,3 +1316,23 @@ function hasPermission(key) { } return RANK >= v; } + +function makeAlert(title, text, klass) { + if(!klass) { + klass = "alert-info"; + } + + var al = $("
").addClass("alert") + .addClass(klass) + .text(text); + $("
").prependTo(al); + $("").text(title).prependTo(al); + $("