diff --git a/channel.js b/channel.js
index cd40d2f3..153fd1eb 100644
--- a/channel.js
+++ b/channel.js
@@ -65,6 +65,7 @@ var Channel = function(name) {
playlistclear: 2,
pollctl: 1.5,
pollvote: -1,
+ mute: 1.5,
kick: 1.5,
ban: 2,
motdedit: 3,
@@ -1719,6 +1720,14 @@ Channel.prototype.tryChat = function(user, data) {
if(!this.hasPermission(user, "chat"))
return;
+ if(user.muted) {
+ user.socket.emit("noflood", {
+ action: "chat",
+ msg: "You have been muted on this channel."
+ });
+ return;
+ }
+
if(typeof data.msg !== "string") {
return;
}
@@ -1770,6 +1779,7 @@ Channel.prototype.filterMessage = function(msg) {
Channel.prototype.sendMessage = function(username, msg, msgclass, data) {
// I don't want HTML from strangers
+ msg = msg.replace(/&/g, "&");
msg = msg.replace(//g, ">");
msg = this.filterMessage(msg);
var msgobj = {
diff --git a/chatcommand.js b/chatcommand.js
index 65285fea..6ae9a9e9 100644
--- a/chatcommand.js
+++ b/chatcommand.js
@@ -55,6 +55,12 @@ function handle(chan, user, msg, data) {
chan.chainMessage(user, cargs.join(" "), flair);
}
}
+ else if(msg.indexOf("/mute ") == 0) {
+ handleMute(chan, user, msg.substring(6).split(" "));
+ }
+ else if(msg.indexOf("/unmute ") == 0) {
+ handleUnmute(chan, user, msg.substring(8).split(" "));
+ }
else if(msg.indexOf("/kick ") == 0) {
handleKick(chan, user, msg.substring(6).split(" "));
}
@@ -85,6 +91,46 @@ function handle(chan, user, msg, data) {
}
}
+function handleMute(chan, user, args) {
+ if(chan.hasPermission(user, "mute") && args.length > 0) {
+ args[0] = args[0].toLowerCase();
+ var person = false;
+ for(var i = 0; i < chan.users.length; i++) {
+ if(chan.users[i].name.toLowerCase() == args[0]) {
+ person = chan.users[i];
+ break;
+ }
+ }
+
+ if(person) {
+ person.meta.icon = "icon-volume-off";
+ person.muted = true;
+ chan.broadcastUserUpdate(person);
+ chan.logger.log("*** " + user.name + " muted " + args[0]);
+ }
+ }
+}
+
+function handleUnmute(chan, user, args) {
+ if(chan.hasPermission(user, "mute") && args.length > 0) {
+ args[0] = args[0].toLowerCase();
+ var person = false;
+ for(var i = 0; i < chan.users.length; i++) {
+ if(chan.users[i].name.toLowerCase() == args[0]) {
+ person = chan.users[i];
+ break;
+ }
+ }
+
+ if(person) {
+ person.meta.icon = false;
+ person.muted = false;
+ chan.broadcastUserUpdate(person);
+ chan.logger.log("*** " + user.name + " unmuted " + args[0]);
+ }
+ }
+}
+
function handleKick(chan, user, args) {
if(chan.hasPermission(user, "kick") && args.length > 0) {
args[0] = args[0].toLowerCase();
diff --git a/user.js b/user.js
index b2dee674..26a74ae1 100644
--- a/user.js
+++ b/user.js
@@ -30,8 +30,10 @@ var User = function(socket, ip) {
this.channel = null;
this.name = "";
this.meta = {
- afk: false
+ afk: false,
+ icon: false
};
+ this.muted = false;
this.throttle = {};
this.flooded = {};
this.profile = {
diff --git a/www/assets/js/util.js b/www/assets/js/util.js
index f4f48253..353e56cb 100644
--- a/www/assets/js/util.js
+++ b/www/assets/js/util.js
@@ -98,6 +98,9 @@ function formatUserlistItem(div, data) {
name.css("font-style", "italic");
$("").addClass("icon-time").appendTo(flair);
}
+ if(data.meta && data.meta.icon) {
+ $("").addClass(data.meta.icon).prependTo(flair);
+ }
}
function getNameColor(rank) {
@@ -1294,6 +1297,7 @@ function genPermissionsEditor() {
makeOption("Vote", "pollvote", standard, CHANNEL.perms.pollvote+"");
addDivider("Moderation");
+ makeOption("Mute users", "mute", modleader, CHANNEL.perms.mute+"");
makeOption("Kick users", "kick", modleader, CHANNEL.perms.kick+"");
makeOption("Ban users", "ban", modplus, CHANNEL.perms.ban+"");
makeOption("Edit MOTD", "motdedit", modplus, CHANNEL.perms.motdedit+"");