diff --git a/PBot/AntiFlood.pm b/PBot/AntiFlood.pm index c32fb6b1..bdd598bf 100644 --- a/PBot/AntiFlood.pm +++ b/PBot/AntiFlood.pm @@ -392,16 +392,32 @@ sub address_to_mask { sub check_nickserv_accounts { my ($self, $nick, $account) = @_; + my $banned_channel = undef; + foreach my $mask (keys %{ $self->{message_history} }) { if(exists $self->{message_history}->{$mask}->{nickserv_account}) { if(lc $self->{message_history}->{$mask}->{nickserv_account} eq lc $account) { $self->{pbot}->logger->log("anti-flood: [check-account] $nick [nickserv: $account] seen previously as $mask.\n"); + my $baninfo = $self->{pbot}->bantracker->get_baninfo($mask); + if(defined $baninfo) { + $self->{pbot}->logger->log("anti-flood: [check-bans] $mask is banned in $baninfo->{channel} by $baninfo->{owner}\n"); + $banned_channel = $baninfo->{channel}; + } } } else { if($mask =~ m/^\Q$nick\E!/i) { $self->{pbot}->logger->log("anti-flood: $mask: setting nickserv account to [$account]\n"); $self->message_history->{$mask}->{nickserv_account} = $account; + + if(defined $banned_channel) { + my $banmask; + $mask =~ m/[^@]+\@(.*)/; + $banmask = "*!*\@$1"; + + $self->{pbot}->logger->log("anti-flood: [$account] is banned in $banned_channel, banning $banmask.\n"); + $self->{pbot}->chanops->ban_user_timed($banmask, $banned_channel, 60 * 60 * 5); + } } } } diff --git a/PBot/BanTracker.pm b/PBot/BanTracker.pm index c931f669..9087ac90 100644 --- a/PBot/BanTracker.pm +++ b/PBot/BanTracker.pm @@ -56,7 +56,31 @@ sub get_banlist { delete $self->{banlist}->{$channel}; $self->{pbot}->logger->log("Retrieving banlist for $channel.\n"); - $conn->sl("mode $channel +b"); + $conn->sl("mode $channel +bq"); +} + +sub get_baninfo { + my ($self, $mask) = @_; + + $mask = quotemeta $mask; + + $mask =~ s/\\\*/.*?/g; + $mask =~ s/\\\?/./g; + + $self->{pbot}->logger->log("get-baninfo: mask regex: $mask\n"); + + foreach my $channel (keys %{ $self->{banlist} }) { + foreach my $banmask (keys %{ $self->{banlist}{$channel} }) { + if($banmask =~ m/$mask/i) { + my $baninfo = {}; + $baninfo->{channel} = $channel; + $baninfo->{owner} = $self->{banlist}{$channel}[0]; + return $baninfo; + } + } + } + + return undef; } sub on_banlistentry { @@ -76,11 +100,11 @@ sub track_mode { my $self = shift; my ($source, $mode, $target, $channel) = @_; - if($mode eq "+b") { + if($mode eq "+b" or $mode eq "+q") { $self->{pbot}->logger->log("ban-tracker: $target banned by $source in $channel.\n"); $self->{banlist}->{$channel}->{$target} = [ $source, gettimeofday ]; } - elsif($mode eq "-b") { + elsif($mode eq "-b" or $mode eq "-q") { $self->{pbot}->logger->log("ban-tracker: $target unbanned by $source in $channel.\n"); delete $self->{banlist}->{$channel}->{$target}; } else { diff --git a/PBot/ChanOps.pm b/PBot/ChanOps.pm index abb70075..cca0e6d3 100644 --- a/PBot/ChanOps.pm +++ b/PBot/ChanOps.pm @@ -75,9 +75,9 @@ sub perform_op_commands { $self->{pbot}->logger->log(" executing kick on $1 $2 $3\n"); } shift(@{ $self->{op_commands} }); + $self->{pbot}->{irc}->flush_output_queue(); + $self->{pbot}->{irc}->do_one_loop(); } - $self->{pbot}->{irc}->flush_output_queue(); - $self->{pbot}->{irc}->do_one_loop(); $self->{pbot}->logger->log("Done.\n"); } diff --git a/PBot/IRCHandlers.pm b/PBot/IRCHandlers.pm index f956ea3c..23ccba0b 100644 --- a/PBot/IRCHandlers.pm +++ b/PBot/IRCHandlers.pm @@ -116,59 +116,77 @@ sub on_action { sub on_mode { my ($self, $conn, $event) = @_; my ($nick, $user, $host) = ($event->nick, $event->user, $event->host); - my $mode = $event->{args}[0]; - my $target = $event->{args}[1]; + my $mode_string = $event->{args}[0]; my $channel = $event->{to}[0]; $channel = lc $channel; - $self->{pbot}->logger->log("Got mode: source: $nick!$user\@$host, mode: $mode, target: " . (defined $target ? $target : "(undef)") . ", channel: $channel\n"); + my ($mode, $modifier); + my $i = 0; + my $target; - if($mode eq "-b" or $mode eq "+b") { - $self->{pbot}->bantracker->track_mode("$nick!$user\@$host", $mode, $target, $channel); - } + use Data::Dumper; + print Dumper($event), "\n"; - if(defined $target && $target eq $self->{pbot}->botnick) { # bot targeted - if($mode eq "+o") { - $self->{pbot}->logger->log("$nick opped me in $channel\n"); + while($mode_string =~ m/(.)/g) { + my $char = $1; - if(exists $self->{pbot}->chanops->{is_opped}->{$channel}) { - $self->{pbot}->logger->log("erm, I was already opped?\n"); - } - - $self->{pbot}->chanops->{is_opped}->{$channel}{timeout} = gettimeofday + 300; # 5 minutes - $self->{pbot}->chanops->perform_op_commands(); - } - elsif($mode eq "-o") { - $self->{pbot}->logger->log("$nick removed my ops in $channel\n"); - - if(not exists $self->{pbot}->chanops->{is_opped}->{$channel}) { - $self->{pbot}->logger->log("warning: erm, I wasn't opped?\n"); - } - - delete $self->{pbot}->chanops->{is_opped}->{$channel}; + if($char eq '-' or $char eq '+') { + $modifier = $char; + next; } - elsif($mode eq "+b") { - $self->{pbot}->logger->log("Got banned in $channel, attempting unban."); - $conn->privmsg("chanserv", "unban $channel"); - } - } - else { # bot not targeted - if($mode eq "+b") { - if($nick eq "ChanServ") { - $self->{pbot}->chanops->{unban_timeout}->hash->{$target}{timeout} = gettimeofday + 3600 * 2; # 2 hours - $self->{pbot}->chanops->{unban_timeout}->hash->{$target}{channel} = $channel; - $self->{pbot}->chanops->{unban_timeout}->save_hash(); - } - } - elsif($mode eq "+e" && $channel eq $self->{pbot}->botnick) { - foreach my $chan (keys %{ $self->{pbot}->channels->channels->hash }) { - if($self->channels->channels->hash->{$chan}{enabled}) { - $self->{pbot}->logger->log("Joining channel: $chan\n"); - $self->{pbot}->conn->join($chan); - } - } - $self->{pbot}->{joined_channels} = 1; + $mode = $modifier . $char; + $target = $event->{args}[++$i]; + + $self->{pbot}->logger->log("Got mode: source: $nick!$user\@$host, mode: $mode, target: " . (defined $target ? $target : "(undef)") . ", channel: $channel\n"); + + if($mode eq "-b" or $mode eq "+b" or $mode eq "-q" or $mode eq "+q") { + $self->{pbot}->bantracker->track_mode("$nick!$user\@$host", $mode, $target, $channel); + } + + if(defined $target && $target eq $self->{pbot}->botnick) { # bot targeted + if($mode eq "+o") { + $self->{pbot}->logger->log("$nick opped me in $channel\n"); + + if(exists $self->{pbot}->chanops->{is_opped}->{$channel}) { + $self->{pbot}->logger->log("erm, I was already opped?\n"); + } + + $self->{pbot}->chanops->{is_opped}->{$channel}{timeout} = gettimeofday + 300; # 5 minutes + $self->{pbot}->chanops->perform_op_commands(); + } + elsif($mode eq "-o") { + $self->{pbot}->logger->log("$nick removed my ops in $channel\n"); + + if(not exists $self->{pbot}->chanops->{is_opped}->{$channel}) { + $self->{pbot}->logger->log("warning: erm, I wasn't opped?\n"); + } + + delete $self->{pbot}->chanops->{is_opped}->{$channel}; + } + elsif($mode eq "+b") { + $self->{pbot}->logger->log("Got banned in $channel, attempting unban."); + $conn->privmsg("chanserv", "unban $channel"); + } + } + else { # bot not targeted + if($mode eq "+b") { + if($nick eq "ChanServ") { + $self->{pbot}->chanops->{unban_timeout}->hash->{$target}{timeout} = gettimeofday + 3600 * 2; # 2 hours + $self->{pbot}->chanops->{unban_timeout}->hash->{$target}{channel} = $channel; + $self->{pbot}->chanops->{unban_timeout}->save_hash(); + } + } + elsif($mode eq "+e" && $channel eq $self->{pbot}->botnick) { + foreach my $chan (keys %{ $self->{pbot}->channels->channels->hash }) { + if($self->channels->channels->hash->{$chan}{enabled}) { + $self->{pbot}->logger->log("Joining channel: $chan\n"); + $self->{pbot}->conn->join($chan); + } + } + + $self->{pbot}->{joined_channels} = 1; + } } } } diff --git a/PBot/VERSION.pm b/PBot/VERSION.pm index 059d5a45..f66c850f 100644 --- a/PBot/VERSION.pm +++ b/PBot/VERSION.pm @@ -13,7 +13,7 @@ use warnings; # These are set automatically by the build/commit script use constant { BUILD_NAME => "PBot", - BUILD_REVISION => 312, + BUILD_REVISION => 313, BUILD_DATE => "2011-02-13", };