Merge pull request #311 from calzoneman/chatthrottle

Chat Throttle
This commit is contained in:
Calvin Montgomery 2013-11-21 15:51:07 -08:00
commit 7f3561bd27
8 changed files with 91 additions and 4 deletions

View File

@ -84,14 +84,19 @@ var Channel = function(name) {
self.opts = { self.opts = {
allow_voteskip: true, allow_voteskip: true,
voteskip_ratio: 0.5, voteskip_ratio: 0.5,
afk_timeout: 180, afk_timeout: 600,
pagetitle: self.name, pagetitle: self.name,
maxlength: 0, maxlength: 0,
externalcss: "", externalcss: "",
externaljs: "", externaljs: "",
chat_antiflood: false, chat_antiflood: false,
chat_antiflood_params: {
burst: 4,
sustained: 1,
cooldown: 4
},
show_public: false, show_public: false,
enable_link_regex: true enable_link_regex: true,
}; };
self.filters = [ self.filters = [
new Filter("monospace", "`([^`]+)`", "g", "<code>$1</code>"), new Filter("monospace", "`([^`]+)`", "g", "<code>$1</code>"),
@ -2108,12 +2113,25 @@ Channel.prototype.tryUpdateOptions = function(user, data) {
if(key in adminonly && user.rank < 3) { if(key in adminonly && user.rank < 3) {
continue; continue;
} }
if (key === "chat_antiflood_params") {
var b = parseInt(data[key].burst);
if (isNaN(b) || b < 0)
b = 1;
var s = parseFloat(data[key].sustained);
if (isNaN(s) || s <= 0)
s = 1;
var c = b / s;
this.opts.chat_antiflood_params.burst = b;
this.opts.chat_antiflood_params.sustained = s;
this.opts.chat_antiflood_params.cooldown = c;
continue;
}
this.opts[key] = data[key];
if(key === "afk_timeout" && this.opts[key] != data[key]) { if(key === "afk_timeout" && this.opts[key] != data[key]) {
this.users.forEach(function (u) { this.users.forEach(function (u) {
u.autoAFK(); u.autoAFK();
}); });
} }
this.opts[key] = data[key];
} }
} }
@ -2231,7 +2249,10 @@ Channel.prototype.tryChat = function(user, data) {
if(msg.length > 240) { if(msg.length > 240) {
msg = msg.substring(0, 240); msg = msg.substring(0, 240);
} }
if(this.opts.chat_antiflood && user.noflood("chat", 2.0)) {
if (user.rank < 2 && this.opts.chat_antiflood &&
user.chatLimiter.throttle(this.opts.chat_antiflood_params)) {
user.socket.emit("chatCooldown", 1000/this.opts.chat_antiflood_params.sustained);
return; return;
} }

View File

@ -36,6 +36,7 @@ var User = function (socket) {
this.throttle = {}; this.throttle = {};
this.flooded = {}; this.flooded = {};
this.queueLimiter = $util.newRateLimiter(); this.queueLimiter = $util.newRateLimiter();
this.chatLimiter = $util.newRateLimiter();
this.profile = { this.profile = {
image: "", image: "",
text: "" text: ""

View File

@ -127,6 +127,43 @@ Callbacks = {
scrollChat(); scrollChat();
}, },
chatCooldown: function (time) {
time = time + 200;
/*
var msg = $("#chat-cooldown-msg");
if (msg.length > 0) {
var timer = msg.data("timer");
if (timer) {
clearTimeout(timer);
}
} else {
msg = $("<div/>")
.addClass("server-msg-disconnect")
.attr("id", "chat-cooldown-msg")
.text("Chat rate limit exceeded, please wait before sending another message")
.appendTo($("#messagebuffer"));
}
if (SCROLLCHAT) {
scrollChat();
}
*/
$("#chatline").css("color", "#ff0000");
if (CHATTHROTTLE && $("#chatline").data("throttle_timer")) {
clearTimeout($("#chatline").data("throttle_timer"));
}
CHATTHROTTLE = true;
$("#chatline").data("throttle_timer", setTimeout(function () {
CHATTHROTTLE = false;
$("#chatline").css("color", "");
/*
msg.remove();
if (SCROLLCHAT) {
scrollChat();
}
*/
}, time));
},
channelNotRegistered: function() { channelNotRegistered: function() {
var div = $("<div/>").addClass("alert alert-info") var div = $("<div/>").addClass("alert alert-info")
.attr("id", "chregnotice") .attr("id", "chregnotice")

View File

@ -67,6 +67,10 @@
else { else {
len = parseInt(hms[0]); len = parseInt(hms[0]);
} }
var sus = parseFloat($("#opt_chat_antiflood_sustained").val()) || 0;
if (sus <= 0) {
sus = 1;
}
socket.emit("setOptions", { socket.emit("setOptions", {
allow_voteskip: $("#opt_allow_voteskip").prop("checked"), allow_voteskip: $("#opt_allow_voteskip").prop("checked"),
voteskip_ratio: parseFloat($("#opt_voteskip_ratio").val()), voteskip_ratio: parseFloat($("#opt_voteskip_ratio").val()),
@ -75,6 +79,10 @@
externalcss: $("#opt_externalcss").val(), externalcss: $("#opt_externalcss").val(),
externaljs: $("#opt_externaljs").val(), externaljs: $("#opt_externaljs").val(),
chat_antiflood: $("#opt_chat_antiflood").prop("checked"), chat_antiflood: $("#opt_chat_antiflood").prop("checked"),
chat_antiflood_params: {
burst: $("#opt_chat_antiflood_burst").val(),
sustained: $("#opt_chat_antiflood_sustained").val()
},
show_public: $("#opt_show_public").prop("checked"), show_public: $("#opt_show_public").prop("checked"),
enable_link_regex: $("#opt_enable_link_regex").prop("checked"), enable_link_regex: $("#opt_enable_link_regex").prop("checked"),
afk_timeout: parseInt($("#opt_afktimeout").val()) afk_timeout: parseInt($("#opt_afktimeout").val())

View File

@ -54,6 +54,7 @@ var socket = {
var IGNORED = []; var IGNORED = [];
var CHATHIST = []; var CHATHIST = [];
var CHATHISTIDX = 0; var CHATHISTIDX = 0;
var CHATTHROTTLE = false;
var SCROLLCHAT = true; var SCROLLCHAT = true;
var LASTCHATNAME = ""; var LASTCHATNAME = "";
var LASTCHATTIME = 0; var LASTCHATTIME = 0;

View File

@ -148,6 +148,9 @@ $("#messagebuffer").mouseleave(function() { SCROLLCHAT = true; });
$("#chatline").keydown(function(ev) { $("#chatline").keydown(function(ev) {
if(ev.keyCode == 13) { if(ev.keyCode == 13) {
if (CHATTHROTTLE) {
return;
}
var msg = $("#chatline").val(); var msg = $("#chatline").val();
if(msg.trim()) { if(msg.trim()) {
var meta = {}; var meta = {};

View File

@ -1010,6 +1010,8 @@ function handleModPermissions() {
$("#opt_externaljs").val(CHANNEL.opts.externaljs); $("#opt_externaljs").val(CHANNEL.opts.externaljs);
$("#opt_externaljs").attr("disabled", CLIENT.rank < 3); $("#opt_externaljs").attr("disabled", CLIENT.rank < 3);
$("#opt_chat_antiflood").prop("checked", CHANNEL.opts.chat_antiflood); $("#opt_chat_antiflood").prop("checked", CHANNEL.opts.chat_antiflood);
$("#opt_chat_antiflood_burst").val(CHANNEL.opts.chat_antiflood_params.burst);
$("#opt_chat_antiflood_sustained").val(CHANNEL.opts.chat_antiflood_params.sustained);
$("#opt_show_public").prop("checked", CHANNEL.opts.show_public); $("#opt_show_public").prop("checked", CHANNEL.opts.show_public);
$("#opt_show_public").attr("disabled", CLIENT.rank < 3); $("#opt_show_public").attr("disabled", CLIENT.rank < 3);
$("#opt_enable_link_regex").prop("checked", CHANNEL.opts.enable_link_regex); $("#opt_enable_link_regex").prop("checked", CHANNEL.opts.enable_link_regex);

View File

@ -29,6 +29,20 @@
<input type="checkbox" id="opt_chat_antiflood"> <input type="checkbox" id="opt_chat_antiflood">
</div> </div>
</div> </div>
<!-- chat flood burst -->
<div class="control-group">
<label class="control-label" for="opt_chat_antiflood_burst" title="The number of messages someone can send with no restriction before the rate limit is applied"># of messages allowed before throttling</label>
<div class="controls">
<input type="text" id="opt_chat_antiflood_burst">
</div>
</div>
<!-- chat flood sustained -->
<div class="control-group">
<label class="control-label" for="opt_chat_antiflood_sustained" title="The number of messages (after the burst is exceeded) per second a non-moderator can send"># of messages allowed per second (sustained)</label>
<div class="controls">
<input type="text" id="opt_chat_antiflood_sustained">
</div>
</div>
<!-- convert URLs to links --> <!-- convert URLs to links -->
<div class="control-group"> <div class="control-group">
<label class="control-label" for="opt_enable_link_regex">Convert URLs in chat to links</label> <label class="control-label" for="opt_enable_link_regex">Convert URLs in chat to links</label>