Как я могу внедрить технику защиты от спама на своем IRC-боте? - PullRequest
2 голосов
/ 29 ноября 2010

Я запускаю своего бота на общедоступном канале с сотнями пользователей.Вчера пришел человек и просто злоупотребил им.

Я хотел бы разрешить кому-либо использовать бота, но если они последовательно рассылают спам-команды и если они не являются "владельцем" бота, как я, то во время отладки яЯ хотел бы добавить их в список игнорируемых, срок действия которого истекает через час или около того.

Один из способов, который я думаю, - сохранить все команды всех пользователей в словаре, например:

({
  'meder@freenode': [{command:'.weather 20851', timestamp: 209323023 }],
  'jack@efnet': [{command:'.seen john' }]
})

Я бы настроил задание cron, чтобы очищать его каждые 24 часа, но я бы в основном определил, сделал ли человек X команд за период, скажем, 15 секунд, и добавил бы их в список игнорирования.

На самом деле, когда я пишу этот ответ, я подумал о лучшей идее ... возможно, вместо того, чтобы хранить команды каждого пользователя, просто сохраните команды бота в списке и продолжайте нажимать, пока он не достигнет предела, скажем,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 ]

11 голосов
/ 29 ноября 2010

Вот простой алгоритм:

  • Каждый раз, когда пользователь отправляет команду боту, увеличивайте число, привязанное к этому пользователю.Если это новый пользователь, создайте для него номер и установите его на 1.
  • Когда номер пользователя увеличивается до определенного значения (скажем, 15), установите его на 100.
  • Каждые секунд пробегайте список и уменьшайте все числа на 1. Ноль означает, что номер пользователя может быть освобожден.

Перед выполнением команды и после увеличения счетчика пользователя, проверьте, чтобы увидетьесли оно превышает ваше волшебное максимальное значение (15 выше).Если это произойдет, выйдите перед выполнением команды.

Это позволяет вам ограничить количество действий и простить излишки через некоторое время.Разделите желаемую длину бана на период уменьшения, чтобы найти число, которое нужно установить, когда пользователь превысит ваш порог (100 выше).Вы также можете добавить к номеру, если определенный пользователь продолжает отправлять команды после того, как они были забанены.

3 голосов
/ 30 ноября 2010

Redis

Я бы использовал безумно быстрое расширенное хранилище значений ключей redis , чтобы написать что-то вроде этого, потому что:

  • Это безумно быстро.
  • Нет необходимости в cronjob, потому что вы можете установить expire для клавиш.
  • Он имеет атомарные операции для приращение key
  • Вы можете использовать redis-cli для создания прототипов.

Мне самому нравится node_redis в качестве клиента redis.Это действительно быстрый Redis-клиент, который можно легко установить с помощью npm.

Алгоритм

Я думаю, что мой алгоритм будет выглядеть примерно так:

  1. Для каждого пользователя создайте уникальный ключ, который подсчитывает последовательно выполненные команды.Также установите expire на время, когда вы больше не будете помечать пользователя как спамера.Давайте предположим, что спамер имеет псевдоним x и expire 15.

    Внутри redis-cli вкл. Хистекает x 15

    Когда вы делаете get x через 15 секунд, тогда ключ больше не существует.

  2. Если значение ключа больше, чем порог, тогда отметьте пользователякак спамер.

    получить х

3 голосов
/ 29 ноября 2010

Ну, Натон уже предложил решение, но можно сократить необходимый код.

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 новых свойства объекта пользователя:)

0 голосов
/ 14 декабря 2010

Похоже, что эти ответы идут неправильно по этому поводу.

IRC-серверы отключат ваш клиент независимо от того, выполняете ли вы «отладку» или нет, если клиент или бот наводняет канал или сервер в целом.

Сделать общий контроль потока, используя метод @ nmichaels подробно, но о сетевом подключении бота к самому серверу.

...