From ebe48798fe37989712971d82924864d08c8d125d Mon Sep 17 00:00:00 2001 From: calzoneman Date: Sun, 12 May 2013 20:41:02 -0400 Subject: [PATCH] Implement user profiles Existing installations will have to apply the following SQL: ```sql ALTER TABLE `registrations` ADD `profile_image` VARCHAR( 255 ) NOT NULL , ADD `profile_text` TEXT NOT NULL ``` --- channel.js | 19 +++++++----- database.js | 18 ++++++++++++ package.json | 2 +- server.js | 2 +- user.js | 25 ++++++++++++++++ www/assets/js/callbacks.js | 5 ++++ www/assets/js/client.js | 2 +- www/assets/js/functions.js | 60 +++++++++++++------------------------- 8 files changed, 83 insertions(+), 50 deletions(-) diff --git a/channel.js b/channel.js index d2efd3da..9ddcf526 100644 --- a/channel.js +++ b/channel.js @@ -502,7 +502,8 @@ Channel.prototype.sendUserlist = function(user) { name: this.users[i].name, rank: this.users[i].rank, leader: this.users[i] == this.leader, - meta: this.users[i].meta + meta: this.users[i].meta, + profile: this.users[i].profile }); } } @@ -550,7 +551,8 @@ Channel.prototype.broadcastNewUser = function(user) { name: user.name, rank: user.rank, leader: this.leader == user, - meta: user.meta + meta: user.meta, + profile: user.profile }); this.sendRankStuff(user); if(user.rank > Rank.Guest) { @@ -558,12 +560,13 @@ Channel.prototype.broadcastNewUser = function(user) { } } -Channel.prototype.broadcastRankUpdate = function(user) { +Channel.prototype.broadcastUserUpdate = function(user) { this.sendAll("updateUser", { name: user.name, rank: user.rank, leader: this.leader == user, - meta: user.meta + meta: user.meta, + profile: user.profile }); this.sendRankStuff(user); } @@ -1317,7 +1320,7 @@ Channel.prototype.tryPromoteUser = function(actor, data) { if(receiver.loggedIn) { this.saveRank(receiver); } - this.broadcastRankUpdate(receiver); + this.broadcastUserUpdate(receiver); } else { Database.saveChannelRank(this.name, { @@ -1357,7 +1360,7 @@ Channel.prototype.tryDemoteUser = function(actor, data) { if(receiver.loggedIn) { this.saveRank(receiver); } - this.broadcastRankUpdate(receiver); + this.broadcastUserUpdate(receiver); } else { Database.saveChannelRank(this.name, { @@ -1374,7 +1377,7 @@ Channel.prototype.changeLeader = function(name) { if(this.leader != null) { var old = this.leader; this.leader = null; - this.broadcastRankUpdate(old); + this.broadcastUserUpdate(old); } if(name == "") { this.logger.log("*** Resuming autolead"); @@ -1389,7 +1392,7 @@ Channel.prototype.changeLeader = function(name) { if(this.users[i].name == name) { this.logger.log("*** Assigned leader: " + name); this.leader = this.users[i]; - this.broadcastRankUpdate(this.leader); + this.broadcastUserUpdate(this.leader); } } } diff --git a/database.js b/database.js index 861b9d04..b431677c 100644 --- a/database.js +++ b/database.js @@ -69,6 +69,8 @@ exports.init = function() { `global_rank` INT NOT NULL, \ `session_hash` VARCHAR(64) NOT NULL, \ `expire` BIGINT NOT NULL, \ + `profile_image` VARCHAR( 255 ) NOT NULL , \ + `profile_text` TEXT NOT NULL, \ PRIMARY KEY (`id`)) \ ENGINE = MyISAM;"; var results = db.querySync(query); @@ -384,3 +386,19 @@ exports.getChannelRanks = function(channame) { return []; } } + +exports.setProfile = function(name, data) { + var db = exports.getConnection(); + if(!db) { + return false; + } + + var query = "UPDATE registrations SET profile_image='{1}',profile_text='{2}' WHERE uname='{3}'" + .replace("{1}", sqlEscape(data.image)) + .replace("{2}", sqlEscape(data.text)) + .replace("{3}", sqlEscape(name)); + + var results = db.querySync(query); + db.closeSync(); + return results; +} diff --git a/package.json b/package.json index 42dcb622..b43919f3 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Calvin Montgomery", "name": "CyTube", "description": "Online media synchronizer and chat", - "version": "1.6.5", + "version": "1.7.0", "repository": { "url": "http://github.com/calzoneman/sync" }, diff --git a/server.js b/server.js index c9538967..14ea2e42 100644 --- a/server.js +++ b/server.js @@ -9,7 +9,7 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -const VERSION = "1.6.5"; +const VERSION = "1.7.0"; var fs = require("fs"); var Logger = require("./logger.js"); diff --git a/user.js b/user.js index 1e0afb3a..6423696f 100644 --- a/user.js +++ b/user.js @@ -31,6 +31,10 @@ var User = function(socket, ip) { }; this.throttle = {}; this.flooded = {}; + this.profile = { + image: "", + text: "" + }; this.initCallbacks(); if(Server.announcement != null) { @@ -322,6 +326,23 @@ User.prototype.initCallbacks = function() { this.channel.tryVoteskip(this); } }.bind(this)); + + this.socket.on("setProfile", function(data) { + if(!this.name) { + return; + } + data.image = data.image || ""; + data.text = data.text || ""; + if(data.text.length > 4000) { + data.text = data.text.substring(0, 4000); + } + if(Database.setProfile(this.name, data)) { + this.profile = data; + if(this.channel != null) { + this.channel.broadcastUserUpdate(this); + } + } + }.bind(this)); } // Handle administration @@ -415,6 +436,10 @@ User.prototype.login = function(name, pw, session) { session: row.session_hash }); Logger.syslog.log(this.ip + " logged in as " + name); + this.profile = { + image: row.profile_image, + text: row.profile_text + }; var chanrank = (this.channel != null) ? this.channel.getRank(name) : Rank.Guest; var rank = (chanrank > row.global_rank) ? chanrank diff --git a/www/assets/js/callbacks.js b/www/assets/js/callbacks.js index e925c8fb..515dccab 100644 --- a/www/assets/js/callbacks.js +++ b/www/assets/js/callbacks.js @@ -406,6 +406,11 @@ Callbacks = { } } div.appendTo($("#userlist")); + + if(data.name == uname) { + PROFILE.image = data.profile.image; + PROFILE.text = data.profile.text; + } }, updateUser: function(data) { diff --git a/www/assets/js/client.js b/www/assets/js/client.js index dbd0a7b7..b5e6b97b 100644 --- a/www/assets/js/client.js +++ b/www/assets/js/client.js @@ -36,7 +36,7 @@ var uname = readCookie("sync_uname"); var session = readCookie("sync_session"); var PROFILE = { image: "", - bio: "" + text: "" }; function parseBool(x) { diff --git a/www/assets/js/functions.js b/www/assets/js/functions.js index f961b5c9..1a63889a 100644 --- a/www/assets/js/functions.js +++ b/www/assets/js/functions.js @@ -15,6 +15,7 @@ function formatUserlistItem(div, data) { $(name).removeClass(); $(name).css("font-style", ""); $(name).addClass(getNameColor(data.rank)); + $(div).find(".profile-box").remove(); var profile; $(name).mouseenter(function(ev) { @@ -22,11 +23,14 @@ function formatUserlistItem(div, data) { .addClass("profile-box") .css("top", (ev.pageY + 5) + "px") .css("left", ev.pageX + "px") - .appendTo($("body")); - $("").addClass("profile-image") - .attr("src", "http://i.imgur.com/P8MIHkc.jpg") - .appendTo(profile); - $("

").text("I'm calzoneman, the developer of this site. Feel free to contact me with queries, comments, or praise about the site.").appendTo(profile); + .appendTo(div); + if(data.profile.image) { + $("").addClass("profile-image") + .attr("src", data.profile.image) + .appendTo(profile); + } + $("").text(data.name).appendTo(profile); + $("

").text(data.profile.text).appendTo(profile); }); $(name).mousemove(function(ev) { profile.css("top", (ev.pageY + 5) + "px") @@ -649,7 +653,7 @@ function onWindowFocus() { } function newPollMenu() { - $("#ytapiplayer").hide(); + var vid = $("#ytapiplayer").detach(); var modal = $("

").addClass("modal hide fade") .appendTo($("body")); var head = $("
").addClass("modal-header") @@ -708,14 +712,14 @@ function newPollMenu() { .appendTo(footer) .click(submit); modal.on("hidden", function() { - $("#ytapiplayer").show(); + vid.appendTo($("#videodiv")); modal.remove(); }); modal.modal(); } function showLoginFrame() { - $("#ytapiplayer").hide(); + var vid = $("#ytapiplayer").detach(); var modal = $("
").addClass("modal hide fade") .appendTo($("body")); var head = $("
").addClass("modal-header") @@ -795,14 +799,14 @@ function showLoginFrame() { } var footer = $("
").addClass("modal-footer").appendTo(modal); modal.on("hidden", function() { - $("#ytapiplayer").show(); + vid.appendTo($("#videodiv")); modal.remove(); }); modal.modal(); } function showUserOpts() { - $("#ytapiplayer").hide(); + var vid = $("#ytapiplayer").detach(); var modal = $("
").addClass("modal hide fade") .appendTo($("body")); var head = $("
").addClass("modal-header") @@ -888,8 +892,8 @@ function showUserOpts() { var profbio = $("