3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-26 13:59:47 +01:00
pbot/PBot/BanTracker.pm
Pragmatic Software dd7f84ceff bantracker: track +q and +b separately to prevent loss of information
bantracker: do not ban someone if their hostmask matches their +q mask
bantracker: remove ban timeouts on -q/-b
antiflood: unbanme will not work if manual ban/quiet set in place
2011-12-17 11:43:21 +00:00

139 lines
3.8 KiB
Perl

# File: BanTracker.pm
# Author: pragma_
#
# Purpose: Populates and maintains channel banlists by checking mode +b on
# joining channels and by tracking modes +b and -b in channels.
#
# Does NOT do banning or unbanning.
package PBot::BanTracker;
use warnings;
use strict;
use vars qw($VERSION);
$VERSION = $PBot::PBot::VERSION;
use Time::HiRes qw/gettimeofday/;
use Time::Duration;
use Data::Dumper;
use Carp ();
sub new {
if(ref($_[1]) eq 'HASH') {
Carp::croak("Options to BanTracker should be key/value pairs, not hash reference");
}
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
}
sub initialize {
my ($self, %conf) = @_;
my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to BanTracker");
$self->{pbot} = $pbot;
$self->{banlist} = {};
$pbot->commands->register(sub { return $self->dumpbans(@_) }, "dumpbans", 60);
}
sub dumpbans {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $bans = Dumper($self->{banlist});
return $bans;
}
sub get_banlist {
my ($self, $conn, $event) = @_;
my $channel = lc $event->{args}[1];
delete $self->{banlist}->{$channel};
$self->{pbot}->logger->log("Retrieving banlist for $channel.\n");
$conn->sl("mode $channel +b");
$conn->sl("mode $channel +q");
}
sub get_baninfo {
my ($self, $mask) = @_;
foreach my $channel (keys %{ $self->{banlist} }) {
foreach my $mode (keys %{ $self->{banlist}{$channel} }) {
foreach my $banmask (keys %{ $self->{banlist}{$channel}{$mode} }) {
my $banmask_key = $banmask;
$banmask = quotemeta $banmask;
$banmask =~ s/\\\*/.*?/g;
$banmask =~ s/\\\?/./g;
if($mask =~ m/^$banmask$/i) {
my $baninfo = {};
$baninfo->{banmask} = $banmask_key;
$baninfo->{channel} = $channel;
$baninfo->{owner} = $self->{banlist}{$channel}{$mode}{$banmask_key}[0];
$baninfo->{when} = $self->{banlist}{$channel}{$mode}{$banmask_key}[1];
$baninfo->{type} = $mode;
$self->{pbot}->logger->log("get-baninfo: dump: " . Dumper($baninfo) . "\n");
return $baninfo;
}
}
}
}
return undef;
}
sub on_quietlist_entry {
my ($self, $conn, $event) = @_;
my $channel = lc $event->{args}[1];
my $target = lc $event->{args}[3];
my $source = lc $event->{args}[4];
my $timestamp = $event->{args}[5];
my $ago = ago(gettimeofday - $timestamp);
$self->{pbot}->logger->log("ban-tracker: [quietlist entry] $channel: $target quieted by $source $ago.\n");
$self->{banlist}->{$channel}->{'+q'}->{$target} = [ $source, $timestamp ];
}
sub on_banlist_entry {
my ($self, $conn, $event) = @_;
my $channel = lc $event->{args}[1];
my $target = lc $event->{args}[2];
my $source = lc $event->{args}[3];
my $timestamp = $event->{args}[4];
my $ago = ago(gettimeofday - $timestamp);
$self->{pbot}->logger->log("ban-tracker: [banlist entry] $channel: $target banned by $source $ago.\n");
$self->{banlist}->{$channel}->{'+b'}->{$target} = [ $source, $timestamp ];
}
sub track_mode {
my $self = shift;
my ($source, $mode, $target, $channel) = @_;
if($mode eq "+b" or $mode eq "+q") {
$self->{pbot}->logger->log("ban-tracker: $target " . ($mode eq '+b' ? 'banned' : 'quieted') . " by $source in $channel.\n");
$self->{banlist}->{$channel}->{$mode}->{$target} = [ $source, gettimeofday ];
}
elsif($mode eq "-b" or $mode eq "-q") {
$self->{pbot}->logger->log("ban-tracker: $target " . ($mode eq '-b' ? 'unbanned' : 'unquieted') . " by $source in $channel.\n");
delete $self->{banlist}->{$channel}->{$mode eq "-b" ? "+b" : "+q"}->{$target};
delete $self->{pbot}->chanops->{unban_timeout}->hash->{$target};
$self->{pbot}->chanops->{unban_timeout}->save_hash();
} else {
$self->{pbot}->logger->log("BanTracker: Unknown mode '$mode'\n");
}
}
1;