diff --git a/user.js b/user.js index d693afd2..354ccf18 100644 --- a/user.js +++ b/user.js @@ -28,6 +28,8 @@ var User = function(socket, ip) { this.meta = { afk: false }; + this.throttle = {}; + this.flooded = {}; this.initCallbacks(); if(Server.announcement != null) { @@ -35,6 +37,38 @@ var User = function(socket, ip) { } }; +// Throttling/cooldown +User.prototype.noflood = function(name, hz) { + var time = new Date().getTime(); + if(!(name in this.throttle)) { + this.throttle[name] = [time]; + return false; + } + else if(name in this.flooded && time < this.flooded[name]) { + this.socket.emit("noflood", { + action: name, + msg: "You're still on cooldown!" + }); + return true; + } + else { + this.throttle[name].push(time); + var diff = (time - this.throttle[name][0]) / 1000.0; + if(diff > 1.0) { + var rate = this.throttle[name].length / diff; + this.throttle[name] = [time]; + if(rate > hz) { + this.flooded[name] = time + 5000; + this.socket.emit("noflood", { + action: name, + msg: "Stop doing that so fast! Cooldown: 5s" + }); + return true; + } + return false; + } + } +} User.prototype.initCallbacks = function() { this.socket.on("disconnect", function() { @@ -258,6 +292,7 @@ User.prototype.initCallbacks = function() { this.socket.on("requestAcl", function() { if(this.channel != null) { this.channel.sendACL(this); + this.noflood("requestAcl", 0.25); } }.bind(this)); diff --git a/www/assets/js/callbacks.js b/www/assets/js/callbacks.js index 82646141..5c3eaa50 100644 --- a/www/assets/js/callbacks.js +++ b/www/assets/js/callbacks.js @@ -29,6 +29,15 @@ function initCallbacks() { .addClass("server-msg-disconnect") .text("Kicked: " + data.reason) .appendTo($("#messagebuffer")); + $("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight")); + }); + + socket.on("noflood", function(data) { + $("
") + .addClass("server-msg-disconnect") + .text(data.action + ": " + data.msg) + .appendTo($("#messagebuffer")); + $("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight")); }); socket.on("channelNotRegistered", function() { @@ -67,6 +76,7 @@ function initCallbacks() { PAGETITLE = opts.pagetitle; $("#opt_customcss").val(opts.customcss); $("#opt_customjs").val(opts.customjs); + $("#opt_chat_antiflood").prop("checked", opts.chat_antiflood); $("#customCss").remove(); if(opts.customcss.trim() != "") { $("").attr("rel", "stylesheet") diff --git a/www/assets/js/client.js b/www/assets/js/client.js index 08873afc..4bb49f97 100644 --- a/www/assets/js/client.js +++ b/www/assets/js/client.js @@ -125,6 +125,7 @@ socket.on("connect", function() { $("
").addClass("server-msg-reconnect") .text("Connected") .appendTo($("#messagebuffer")); + $("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight")); setTimeout(function() { $("#reconnect_box").remove(); }, 3000); }); @@ -377,7 +378,8 @@ $("#opt_submit").click(function() { voteskip_ratio: ratio, pagetitle: ptitle, customcss: css, - customjs: $("#opt_customjs").val() + customjs: $("#opt_customjs").val(), + chat_antiflood: $("#opt_chat_antiflood").prop("checked") }; socket.emit("channelOpts", opts); }); diff --git a/www/assets/js/functions.js b/www/assets/js/functions.js index 9f014b9b..f175df6e 100644 --- a/www/assets/js/functions.js +++ b/www/assets/js/functions.js @@ -16,6 +16,7 @@ function handleDisconnect() { .addClass("server-msg-disconnect") .text("Disconnected from server. Attempting reconnection...") .appendTo($("#messagebuffer")); + $("#messagebuffer").scrollTop($("#messagebuffer").prop("scrollHeight")); } // Adds a user to the chatbox userlist diff --git a/www/index.html b/www/index.html index 2597fd0f..23b4fb34 100644 --- a/www/index.html +++ b/www/index.html @@ -167,6 +167,11 @@ +
+