我在拥有数百名用户的公共频道中运行我的机器人。昨天有人进来,只是滥用了它。
我想让任何人使用机器人,但是如果他们连续发送垃圾邮件命令,并且当我调试时他们不像我这样的机器人“所有者”那么我想将它们添加到一个被忽略的列表中一个小时左右。
我想的一种方法是在所有用户中保存所有命令,例如:
({
'meder@freenode': [{command:'.weather 20851', timestamp: 209323023 }],
'jack@efnet': [{command:'.seen john' }]
})
我会设置一个cron作业来每24小时清除一次,但我基本上会确定一个人是否在15秒的时间内发出了X个命令并将它们添加到忽略列表中。
实际上,当我写这个答案时,我想到了一个更好的想法..也许不是存储每个用户的命令,只是将机器人的命令存储在一个列表中并继续推动直到达到限制,15
lastCommands = [], limit = 5;
function handleCommand( timeObj, action ) {
if ( lastCommands.length < limit ) {
action();
} else {
// enumerate through lastCommands and compare the timestamps of all 5 commands
// if the user is the same for all 5 commands, and...
// if the timestamps are all within the vicinity of 20 seconds
// add the user to the ignoreList
}
}
watch_for('command', function() {
handleCommand({timestamp: 2093293032, user: user}, function(){ message.say('hello there!') })
});
我很感激有关此事的任何建议。
答案 0 :(得分:11)
这是一个简单的算法:
在执行命令之前和递增用户计数器之后,检查它是否超过你的魔法最大值(上面的15)。如果是,请在执行命令之前退出。
这使您可以在一段时间后对限制操作进行评级并原谅过度行为。将您期望的禁令长度除以减量周期,以找到当用户超过您的阈值(100以上)时要设置的数字。如果特定用户在被禁止后继续发送命令,您也可以添加该号码。
答案 1 :(得分:3)
Nathon已经提供了解决方案,但是可以减少所需的代码。
var user = {};
user.lastCommandTime = new Date().getTime(); // time the user send his last command
user.commandCount = 0; // command limit counter
user.maxCommandsPerSecond = 1; // commands allowed per second
function handleCommand(obj, action) {
var user = obj.user, now = new Date().getTime();
var timeDifference = now - user.lastCommandTime;
user.commandCount = Math.max(user.commandCount - (timeDifference / 1000 * user.maxCommandsPerSecond), 0) + 1;
user.lastCommandTime = now;
if (user.commandCount <= user.maxCommandsPerSecond) {
console.log('command!');
} else {
console.log('flooding');
}
}
var obj = {user: user};
var e = 0;
function foo() {
handleCommand(obj, 'foo');
e += 250;
setTimeout(foo, 400 + e);
}
foo();
在这个实现中,每X秒不需要列表或一些全局回调,而是每次有新消息时我们只减少commandCount
,基于与最后一个命令的时差,它也是可能的允许特定用户使用不同的命令率。
我们需要的只是用户对象上的3个新属性:)
答案 2 :(得分:3)
我会使用疯狂快速的高级键值存储redis来写这样的东西,因为:
我自己真的很喜欢node_redis作为redis客户端。它是一个非常快的redis客户端,可以使用npm轻松安装。
我认为我的算法看起来像这样:
为每个用户创建一个唯一键,用于对连续执行的命令进行计数。此外,设置过期到您不再将用户标记为垃圾邮件发送者的时间。我们假设垃圾邮件发送者的昵称为x
,expire
15
。
redis-cli内部
incr x
到期x 15
15秒后执行get x
时,该键不再存在。
如果key的值大于阈值,则将用户标记为垃圾邮件发送者。
获取x
答案 3 :(得分:-1)
这些答案似乎是错误的。
如果客户端或僵尸程序一般充斥着某个频道或服务器,则无论您是否正在“调试”,IRC服务器都会断开您的客户端。
使用方法@nmichaels进行全面的防洪控制,但是在机器人与服务器本身的网络连接上。