diff --git a/lib/channel.js b/lib/channel.js index 5eff2676..edf8807f 100644 --- a/lib/channel.js +++ b/lib/channel.js @@ -2186,6 +2186,10 @@ Channel.prototype.tryUpdateMotd = function(user, data) { /* REGION Chat */ Channel.prototype.tryChat = function(user, data) { + if (data.meta === undefined) { + data.meta = {}; + } + if(user.name == "") { return; } @@ -2219,14 +2223,21 @@ Channel.prototype.tryChat = function(user, data) { var msgobj = { username: user.name, msg: msg, - msgclass: "", + meta: data.meta, time: Date.now() }; user.socket.emit("chatMsg", msgobj); return; } - this.chainMessage(user, msg); + if (msg.indexOf("/") === 0) { + ChatCommand.handle(this, user, msg, data.meta); + } else { + if (msg.indexOf(">") === 0) { + data.meta.addClass = "greentext"; + } + this.sendMessage(user, msg, data.meta); + } } Channel.prototype.chainMessage = function(user, msg, data) { @@ -2271,7 +2282,29 @@ Channel.prototype.filterMessage = function(msg) { return subs.join(""); } -Channel.prototype.sendMessage = function(username, msg, msgclass, data) { +Channel.prototype.sendMessage = function (user, msg, meta, filter) { + msg = sanitize(msg).escape(); + msg = this.filterMessage(msg); + var msgobj = { + username: user.name, + msg: msg, + meta: meta, + time: Date.now() + } + + if (filter && filter.byRank !== undefined) { + this.sendAllWithRank("chatMsg", msgobj, filter.byRank); + } else { + this.sendAll("chatMsg", msgobj); + this.chatbuffer.push(msgobj); + if(this.chatbuffer.length > 15) + this.chatbuffer.shift(); + var unescaped = sanitize(msg).entityDecode(); + this.logger.log("<" + user.name + "> " + unescaped); + } +}; + +Channel.prototype.sendMessageOld = function(username, msg, msgclass, data) { // I don't want HTML from strangers msg = sanitize(msg).escape(); msg = this.filterMessage(msg); diff --git a/lib/chatcommand.js b/lib/chatcommand.js index d133d094..00a64df1 100644 --- a/lib/chatcommand.js +++ b/lib/chatcommand.js @@ -12,7 +12,77 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI var Logger = require("./logger.js"); var Poll = require("./poll").Poll; -function handle(chan, user, msg, data) { +var handlers = { + "me": function (chan, user, msg, meta) { + meta.addClass = "action"; + meta.action = true; + chan.sendMessage(user, msg, meta); + }, + "sp": function (chan, user, msg, meta) { + meta.addClass = "spoiler"; + chan.sendMessage(user, msg, meta); + }, + "say": function (chan, user, msg, meta) { + if (user.rank >= 1.5) { + meta.addClass = "shout"; + meta.forceShowName = true; + chan.sendMessage(user, msg, meta); + } + }, + "afk": function (chan, user, msg, meta) { + user.setAFK(!user.meta.afk); + }, + "a": function (chan, user, msg, meta) { + var superadminflair = { + labelclass: "label-important", + icon: "icon-globe" + }; + + var args = msg.split(" "); + var cargs = []; + for (var i = 0; i < args.length; i++) { + var a = args[i]; + if (a.indexOf("!icon-") === 0) { + superadminflair.icon = a.substring(1); + } else if (a.indexOf("!label-") === 0) { + superadminflair.labelclass = a.substring(1); + } else { + cargs.push(a); + } + } + + meta.superadminflair = superadminflair; + meta.forceShowName = true; + chan.sendMessage(user, cargs.join(" "), meta); + }, + "mute": function (chan, user, msg, meta) { + handleMute(chan, user, msg.split(" ")); + }, + "smute": function (chan, user, msg, meta) { + handleShadowMute(chan, user, msg.split(" ")); + } +}; + +var handlerList = []; +for (var key in handlers) { + handlerList.push({ + sub: key.length + 2, + re: new RegExp("^\\/" + key + "(?:\\s|$)"), + fn: handlers[key] + }); +} + +function handle(chan, user, msg, meta) { + for (var i = 0; i < handlerList.length; i++) { + var h = handlerList[i]; + if (msg.match(h.re)) { + h.fn(chan, user, msg.substring(h.sub), meta); + break; + } + } +} + +function handleOld(chan, user, msg, data) { if(msg.indexOf("/me ") == 0) chan.sendMessage(user.name, msg.substring(4), "action", data); else if(msg.indexOf("/sp ") == 0) diff --git a/www/assets/js/ui.js b/www/assets/js/ui.js index 6858bb7b..cbff5142 100644 --- a/www/assets/js/ui.js +++ b/www/assets/js/ui.js @@ -150,13 +150,20 @@ $("#chatline").keydown(function(ev) { if(ev.keyCode == 13) { var msg = $("#chatline").val(); if(msg.trim()) { + var meta = {}; if (USEROPTS.adminhat && CLIENT.rank >= 255) { msg = "/a " + msg; - } else if(USEROPTS.modhat && CLIENT.rank >= Rank.Moderator) { - msg = "/m " + msg; + } else 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(4); + } + socket.emit("chatMsg", { - msg: msg + msg: msg, + meta: meta }); CHATHIST.push($("#chatline").val()); CHATHISTIDX = CHATHIST.length; diff --git a/www/assets/js/util.js b/www/assets/js/util.js index c3fa0a21..21994f9e 100644 --- a/www/assets/js/util.js +++ b/www/assets/js/util.js @@ -1442,6 +1442,61 @@ function sendVideoUpdate() { /* chat */ function formatChatMessage(data) { + var skip = data.username === LASTCHATNAME; + if (data.meta.forceShowName) { + skip = false; + } + if(data.msgclass == "server-whisper") + skip = true; + // Prevent impersonation by abuse of the bold filter + if(data.msg.match(/^\s*\w+\s*:\s*<\/strong>\s*/)) + skip = false; + LASTCHATNAME = data.username; + LASTCHATTIME = data.time; + var div = $("
"); + if (USEROPTS.show_timestamps) { + var time = $("").addClass("timestamp").appendTo(div); + var timestamp = new Date(data.time).toTimeString().split(" ")[0]; + time.text("["+timestamp+"] "); + if (data.meta.addClass && + data.meta.addClass.match(/shout|server-whisper/)) { + time.addClass(data.meta.addClass); + } + } + + var name = $(""); + if (!skip) { + name.appendTo(div); + } + $("").addClass("username").text(data.username + ": ").appendTo(name); + if (data.meta.modflair) { + name.addClass(getNameColor(data.meta.modflair)); + } + if (data.meta.addClass) { + name.addClass(data.meta.addClass); + } + if (data.meta.superadminflair) { + name.addClass("label") + .addClass(data.meta.superadminflair.labelclass); + $("").addClass(data.meta.superadminflair.icon) + .addClass("icon-white") + .prependTo(name); + } + + var message = $("").appendTo(div); + message[0].innerHTML = data.msg; + + if (data.meta.action) { + name.remove(); + message[0].innerHTML = data.username + " " + data.msg; + } + if (data.meta.addClass) { + message.addClass(data.meta.addClass); + } + return div; +} + +function oldFormatChatMessage(data) { var skip = data.username == LASTCHATNAME; if(data.msgclass == "drink" || data.msgclass == "shout") { skip = false;