Add private messaging

This commit is contained in:
calzoneman 2014-02-15 01:40:14 -06:00
parent 573e59680e
commit b41529d4aa
7 changed files with 208 additions and 7 deletions

View File

@ -2865,6 +2865,57 @@ Channel.prototype.handleChat = function (user, data) {
}
};
Channel.prototype.handlePm = function (user, data) {
if (typeof data.meta !== "object") {
data.meta = {};
}
if (!user.name) {
return;
}
if (typeof data.msg !== "string" || typeof data.to !== "string") {
return;
}
var msg = data.msg.substring(0, 240);
var to = null;
for (var i = 0; i < this.users.length; i++) {
if (this.users[i].name.toLowerCase() === data.to) {
to = this.users[i];
break;
}
}
if (!to) {
return;
}
var meta = {};
if (user.rank >= 2) {
if ("modflair" in data.meta && data.meta.modflair === user.rank) {
meta.modflair = data.meta.modflair;
}
}
if (msg.indexOf(">") === 0) {
meta.addClass = "greentext";
}
msg = XSS.sanitizeText(msg);
msg = this.filterMessage(msg);
var msgobj = {
username: user.name,
to: data.to,
msg: msg,
meta: meta,
time: Date.now()
};
to.socket.emit("pm", msgobj);
user.socket.emit("pm", msgobj);
};
/**
* Filters a chat message
*/

View File

@ -256,6 +256,14 @@ User.prototype.initChannelCallbacks = function () {
self.channel.handleChat(self, data);
});
wrapTypecheck("pm", function (data) {
if (typeof data.msg !== "string" || typeof data.to !== "string") {
return;
}
self.channel.handlePm(self, data);
});
wrapTypecheck("newPoll", function (data) {
self.channel.handleOpenPoll(self, data);

View File

@ -202,6 +202,7 @@ html(lang="en")
mixin permeditor()
.modal-footer
button.btn.btn-default(type="button", data-dismiss="modal") Close
#pmbar
include footer
mixin footer()
script(src=sioSource)

View File

@ -461,6 +461,25 @@ Callbacks = {
addChatMessage(data);
},
pm: function (data) {
var name = data.username;
if (IGNORED.indexOf(name) !== -1) {
return;
}
if (data.username === CLIENT.name) {
name = data.to;
}
var pm = initPm(name);
var msg = formatChatMessage(data, pm.data("last"));
var buffer = pm.find(".pm-buffer");
msg.appendTo(buffer);
buffer.scrollTop(buffer.prop("scrollHeight"));
if (pm.find(".panel-body").is(":hidden")) {
pm.removeClass("panel-default").addClass("panel-primary");
}
},
joinMessage: function(data) {
if(USEROPTS.joinmessage)
addChatMessage(data);

View File

@ -56,8 +56,9 @@ var CHATHIST = [];
var CHATHISTIDX = 0;
var CHATTHROTTLE = false;
var SCROLLCHAT = true;
var LASTCHATNAME = "";
var LASTCHATTIME = 0;
var LASTCHAT = {
name: ""
};
var FOCUSED = true;
var PAGETITLE = "CyTube";
var TITLE_BLINK;

View File

@ -199,6 +199,15 @@ function addUserDropdown(entry) {
ignore.text("Unignore User");
}
/* pm button */
var pm = $("<button/>").addClass("btn btn-xs btn-default")
.text("Private Message")
.appendTo(btngroup)
.click(function () {
initPm(name).find(".panel-heading").click();
menu.hide();
});
/* give/remove leader (moderator+ only) */
if (hasPermission("leaderctl")) {
var ldr = $("<button/>").addClass("btn btn-xs btn-default")
@ -1251,7 +1260,7 @@ function sendVideoUpdate() {
/* chat */
function formatChatMessage(data) {
function formatChatMessage(data, last) {
// Backwards compat
if (!data.meta || data.msgclass) {
data.meta = {
@ -1261,7 +1270,7 @@ function formatChatMessage(data) {
};
}
// Phase 1: Determine whether to show the username or not
var skip = data.username === LASTCHATNAME;
var skip = data.username === last.name;
if(data.meta.addClass === "server-whisper")
skip = true;
// Prevent impersonation by abuse of the bold filter
@ -1272,8 +1281,7 @@ function formatChatMessage(data) {
data.msg = execEmotes(data.msg);
LASTCHATNAME = data.username;
LASTCHATTIME = data.time;
last.name = data.username;
var div = $("<div/>");
/* drink is a special case because the entire container gets the class, not
just the message */
@ -1332,7 +1340,7 @@ function addChatMessage(data) {
if(IGNORED.indexOf(data.username) !== -1) {
return;
}
var div = formatChatMessage(data);
var div = formatChatMessage(data, LASTCHAT);
// Incoming: a bunch of crap for the feature where if you hover over
// a message, it highlights messages from that user
div.data("sender", data.username);
@ -2265,3 +2273,72 @@ function execEmotes(msg) {
return msg;
}
function initPm(user) {
if ($("#pm-" + user).length > 0) {
return $("#pm-" + user);
}
var pm = $("<div/>").addClass("panel panel-default pm-panel")
.appendTo($("#pmbar"))
.data("last", { name: "" })
.attr("id", "pm-" + user);
var title = $("<div/>").addClass("panel-heading").text(user).appendTo(pm);
var close = $("<button/>").addClass("close pull-right")
.html("&times;")
.appendTo(title).click(function () {
pm.remove();
$("#pm-placeholder-" + user).remove();
});
var body = $("<div/>").addClass("panel-body").appendTo(pm).hide();
var placeholder;
title.click(function () {
body.toggle();
pm.removeClass("panel-primary").addClass("panel-default");
if (!body.is(":hidden")) {
placeholder = $("<div/>").addClass("pm-panel-placeholder")
.attr("id", "pm-placeholder-" + user)
.insertAfter(pm);
var left = pm.position().left;
pm.css("position", "absolute")
.css("bottom", "0px")
.css("left", left);
} else {
pm.css("position", "");
$("#pm-placeholder-" + user).remove();
}
});
var buffer = $("<div/>").addClass("pm-buffer linewrap").appendTo(body);
$("<hr/>").appendTo(body);
var input = $("<input/>").addClass("form-control pm-input").attr("type", "text")
.appendTo(body);
input.keyup(function (ev) {
if (ev.keyCode === 13) {
var meta = {};
var msg = input.val();
if (msg.trim() === "") {
return;
}
if (USEROPTS.modhat && CLIENT.rank >= Rank.Moderator) {
meta.modflair = CLIENT.rank;
}
if (CLIENT.rank >= 2 && msg.indexOf("/m ") === 0) {
meta.modflair = CLIENT.rank;
msg = msg.substring(3);
}
socket.emit("pm", {
to: user,
msg: msg,
meta: meta
});
input.val("");
}
});
return pm;
}

View File

@ -500,3 +500,47 @@ li.ui-sortable-helper, li.ui-sortable-placeholder + li.queue_entry {
#cs-emotes td:nth-child(3) {
max-width: 300px;
}
#pmbar {
position: fixed;
bottom: 0;
}
.pm-panel, .pm-panel-placeholder {
margin-left: 5px;
margin-bottom: 20px;
float: left;
width: 250px;
}
.pm-panel {
margin-bottom: 0!important;
border-radius: 0!important;
border-radius: 0!important;
}
.pm-panel > .panel-heading {
cursor: pointer;
border-radius: 0!important;
border-radius: 0!important;
}
.pm-panel > .panel-body {
padding: 0;
}
.pm-panel > .panel-body > .pm-buffer {
height: 200px;
overflow-y: scroll;
}
.pm-panel > .panel-body > hr {
margin: 0;
}
.pm-input {
margin: 0;
width: 100%;
border-top-left-radius: 0!important;
border-top-right-radius: 0!important;
}