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:
parent
c6446d6f84
commit
ebe48798fe
19
channel.js
19
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
18
database.js
18
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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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
25
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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -36,7 +36,7 @@ var uname = readCookie("sync_uname");
|
|||
var session = readCookie("sync_session");
|
||||
var PROFILE = {
|
||||
image: "",
|
||||
bio: ""
|
||||
text: ""
|
||||
};
|
||||
|
||||
function parseBool(x) {
|
||||
|
|
|
@ -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 = "×";
|
||||
$("<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) {
|
||||
|
|
Loading…
Reference in a new issue