1 # -*- Mode: perl; indent-tabs-mode: nil -*-
2 # $Id: Flood.bm,v 1.2 2003/10/03 15:46:54 ian%hixie.ch Exp $
3 ###########################
4 # Flood Protection module #
5 ###########################
7 package BotModules::Flood;
14 $self->SUPER::RegisterConfig(@_);
16 foreach my $chan (@{$self->{'channels'}}) {
17 $self->registerVariables( ["join_$chan", 0, 0, []] );
19 $self->registerVariables(
20 ['numberOfJoins', 1, 1, '7'],
21 ['secondsToTrigger', 1, 1, '2'],
22 ['minutesToProtect', 1, 1, '5'],
30 '' => 'This module will help control "join flood" attacks on IRC',
34 # Set - called to set a variable to a particular value.
37 my ($event, $variable, $value) = @_;
38 # If changing the setting for numberOfJoins make sure
39 # that the arrays are empty. Otherwise, reducing the
40 # numberOfJoins value would not work properly.
41 if ($variable eq 'numberOfJoins') {
42 foreach my $chan (@{$self->{'channels'}}) {
43 @{$self->{"join_$chan"}} = ();
46 # now actually do the setting of the variable
47 return $self->SUPER::Set($event, $variable, $value);
52 my ($event, $channel) = @_;
53 $self->registerVariables( ["join_$channel", 0, 0, []] );
54 return $self->SUPER::JoinedChannel($event, $channel); # call inherited method
59 my ($event, $channel, $who) = @_;
60 # If numberOfJoins or secondsToTrigger is not a positive Integer, don't do anything
61 if ($self->{'numberOfJoins'} !~ m/^[1-9][0-9]*$/o || $self->{'secondsToTrigger'} !~ m/^[1-9][0-9]*$/o) {
62 # We didn't do anything, so don't pretend like we did :)
63 return $self->SUPER::SpottedJoin($event, $channel, $who);
65 # Here we have the 'join_times' array to push and shift to/from
66 push(@{$self->{"join_$channel"}}, $event->{'time'});
67 if (scalar(@{$self->{"join_$channel"}}) >= $self->{'numberOfJoins'}) {
68 my $oldest = shift(@{$self->{"join_$channel"}});
69 my $timechange = $event->{'time'} - $oldest;
70 if ($self->{'secondsToTrigger'} >= $timechange) {
71 # We have just seen many joins happen very quickly. This channel should
72 # have its mode set to +i until an op can figure out what went wrong.
73 $self->mode($event, $event->{'channel'}, '+i');
75 # If minutesToProtect is a positive integer we should set mode -i after
76 # that number of minutes has passed.
77 if ($self->{'minutesToProtect'} =~ m/^[1-9][0-9]*$/o) {
78 my $seconds = $self->{'minutesToProtect'} * 60;
79 my @mode = ('mode', $event->{'channel'}, '-i');
80 $self->schedule($event, $seconds, 1, @mode);
81 $extra_text = "I'll set it -i in $self->{'minutesToProtect'} minutes";
83 $self->say($event, "I just saw a lot of joins happen very quickly. Because of " .
84 "that I set this channel's mode to be Invite Only... $extra_text");
87 # By returning 0 we ensure that a join won't be processed more than once.
93 my ($event, @data) = @_;
95 my $what = shift(@data);
96 if ($what eq 'mode') {
97 $self->mode($event, @data);
99 # Call the inherited event
100 return $self->SUPER::Schedule(@_);