如何在我的IRC机器人上实施反垃圾邮件技术?

时间:2010-11-29 16:45:21

标签: node.js irc

我在拥有数百名用户的公共频道中运行我的机器人。昨天有人进来,只是滥用了它。

我想让任何人使用机器人,但是如果他们连续发送垃圾邮件命令,并且当我调试时他们不像我这样的机器人“所有者”那么我想将它们添加到一个被忽略的列表中一个小时左右。

我想的一种方法是在所有用户中保存所有命令,例如:

({
  '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!') })
});

我很感激有关此事的任何建议。

4 个答案:

答案 0 :(得分:11)

这是一个简单的算法:

  • 每次用户向机器人发送命令时,都会增加与该用户绑定的数字。如果这是新用户,请为其创建号码并将其设置为1.
  • 当用户的号码增加到某个值(比如15)时,将其设置为100.
  • 每个&lt;期间&gt;秒,遍历列表并将所有数字递减1.零表示可以释放用户的号码。

在执行命令之前和递增用户计数器之后,检查它是否超过你的魔法最大值(上面的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的

我会使用疯狂快速的高级键值存储redis来写这样的东西,因为:

  • 这是非常快的。
  • 不需要cronjob,因为您可以在键上设置expire
  • 它具有increment
  • 的原子操作
  • 您可以使用redis-cli进行原型设计。

我自己真的很喜欢node_redis作为redis客户端。它是一个非常快的redis客户端,可以使用npm轻松安装。

Algorithme

我认为我的算法看起来像这样:

  1. 为每个用户创建一个唯一键,用于对连续执行的命令进行计数。此外,设置过期到您不再将用户标记为垃圾邮件发送者的时间。我们假设垃圾邮件发送者的昵称为xexpire 15

    redis-cli内部 incr x
    到期x 15

    15秒后执行get x时,该键不再存在。

  2. 如果key的值大于阈值,则将用户标记为垃圾邮件发送者。

    获取x

答案 3 :(得分:-1)

这些答案似乎是错误的。

如果客户端或僵尸程序一般充斥着某个频道或服务器,则无论您是否正在“调试”,IRC服务器都会断开您的客户端。

使用方法@nmichaels进行全面的防洪控制,但是在机器人与服务器本身的网络连接上。