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
```
This commit is contained in:
calzoneman 2013-05-12 20:41:02 -04:00
parent c6446d6f84
commit ebe48798fe
8 changed files with 83 additions and 50 deletions

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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"
},

View file

@ -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");

25
user.js
View file

@ -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

View file

@ -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) {

View file

@ -36,7 +36,7 @@ var uname = readCookie("sync_uname");
var session = readCookie("sync_session");
var PROFILE = {
image: "",
bio: ""
text: ""
};
function parseBool(x) {

View file

@ -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"));
$("<img/>").addClass("profile-image")
.attr("src", "http://i.imgur.com/P8MIHkc.jpg")
.appendTo(profile);
$("<p/>").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) {
$("<img/>").addClass("profile-image")
.attr("src", data.profile.image)
.appendTo(profile);
}
$("<strong/>").text(data.name).appendTo(profile);
$("<p/>").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 = $("<div/>").addClass("modal hide fade")
.appendTo($("body"));
var head = $("<div/>").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 = $("<div/>").addClass("modal hide fade")
.appendTo($("body"));
var head = $("<div/>").addClass("modal-header")
@ -795,14 +799,14 @@ function showLoginFrame() {
}
var footer = $("<div/>").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 = $("<div/>").addClass("modal hide fade")
.appendTo($("body"));
var head = $("<div/>").addClass("modal-header")
@ -888,8 +892,8 @@ function showUserOpts() {
var profbio = $("<textarea/>");
profbio.attr("rows", 5);
profbio.val(PROFILE.bio);
addOption("Profile Bio", profbio);
profbio.val(PROFILE.text);
addOption("Profile Text", profbio);
if(RANK >= Rank.Moderator) {
$("<hr>").appendTo(form);
@ -906,6 +910,10 @@ function showUserOpts() {
.appendTo(footer);
submit.click(function() {
socket.emit("setProfile", {
image: profimg.val(),
text: profbio.val()
});
USEROPTS.theme = themeselect.val();
USEROPTS.css = usercss.val();
USEROPTS.layout = layoutselect.val();
@ -923,7 +931,7 @@ function showUserOpts() {
});
modal.on("hidden", function() {
$("#ytapiplayer").show();
vid.appendTo($("#videodiv"));
modal.remove();
});
modal.modal();
@ -976,32 +984,6 @@ function applyOpts() {
}
}
function showProfileModal(data) {
$("#ytapiplayer").hide();
var modal = $("<div/>").addClass("modal hide fade")
.appendTo($("body"));
var head = $("<div/>").addClass("modal-header")
.appendTo(modal);
$("<button/>").addClass("close")
.attr("data-dismiss", "modal")
.attr("aria-hidden", "true")
.appendTo(head)[0].innerHTML = "&times;";
$("<h3/>").text(data.name).appendTo(head);
var body = $("<div/>").addClass("modal-body").appendTo(modal);
$("<img/>").attr("src", data.image)
.css("width", "80px")
.css("height", "80px")
.appendTo(body)
$("<p/>").addClass("profile-text").appendTo(body).text(data.text);
//var footer = $("<div/>").addClass("modal-footer").appendTo(modal);
modal.on("hidden", function() {
$("#ytapiplayer").show();
modal.remove();
});
modal.modal();
}
function idToURL(data) {
var entry = "";
switch(data.type) {