Finalize BanList refactor; add updater

This commit is contained in:
Pragmatic Software 2020-04-28 22:36:13 -07:00
parent 013fa6b51c
commit f347d1798b
10 changed files with 102 additions and 47 deletions

View File

@ -397,7 +397,7 @@ sub check_flood {
} elsif ($mode == $self->{pbot}->{messagehistory}->{MSG_CHAT}) {
if ($chan =~ /^#/) { #channel flood (opposed to private message or otherwise)
# don't increment offenses again if already banned
if ($self->{pbot}->{chanops}->has_ban_timeout($chan, "*!$user\@" . $self->address_to_mask($host))) {
if ($self->{pbot}->{banlist}->has_ban_timeout($chan, "*!$user\@" . $self->address_to_mask($host))) {
$self->{pbot}->{logger}->log("$nick $chan flood offense disregarded due to existing ban\n");
next;
}
@ -496,7 +496,7 @@ sub check_flood {
$chan_data->{enter_abuses}++;
if ($chan_data->{enter_abuses} >= $enter_abuse_max_offenses) {
if ($self->{pbot}->{registry}->get_value('antiflood', 'enforce')) {
if ($self->{pbot}->{chanops}->has_ban_timeout($chan, "*!$user\@" . $self->address_to_mask($host))) {
if ($self->{pbot}->{banlist}->has_ban_timeout($chan, "*!$user\@" . $self->address_to_mask($host))) {
$self->{pbot}->{logger}->log("$nick $chan enter abuse offense disregarded due to existing ban\n");
next;
}
@ -594,13 +594,13 @@ sub unbanme {
foreach my $baninfo (@$baninfos) {
my $u = $self->{pbot}->{users}->loggedin($baninfo->{channel}, "$nick!$user\@$host");
my $whitelisted = $self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted');
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{banmask}) || $whitelisted) {
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost banned as $baninfo->{banmask} in $baninfo->{channel}, but allowed through whitelist\n");
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{mask}) || $whitelisted) {
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost banned as $baninfo->{mask} in $baninfo->{channel}, but allowed through whitelist\n");
} else {
if ($channel eq lc $baninfo->{channel}) {
my $mode = $baninfo->{type} eq "+b" ? "banned" : "quieted";
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost $mode as $baninfo->{banmask} in $baninfo->{channel} by $baninfo->{owner}, unbanme rejected\n");
return "/msg $nick You have been $mode as $baninfo->{banmask} by $baninfo->{owner}, unbanme will not work until it is removed.";
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost $mode as $baninfo->{mask} in $baninfo->{channel} by $baninfo->{owner}, unbanme rejected\n");
return "/msg $nick You have been $mode as $baninfo->{mask} by $baninfo->{owner}, unbanme will not work until it is removed.";
}
}
}
@ -803,7 +803,7 @@ sub check_bans {
}
my $baninfo = {};
$baninfo->{banmask} = $alias;
$baninfo->{mask} = $alias;
$baninfo->{channel} = $channel;
$baninfo->{owner} = 'blacklist';
$baninfo->{when} = 0;
@ -821,7 +821,7 @@ sub check_bans {
foreach my $baninfo (@$baninfos) {
if (time - $baninfo->{when} < 5) {
$self->{pbot}->{logger}
->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{banmask} in $baninfo->{channel}, but within 5 seconds of establishing ban; giving another chance\n");
->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{mask} in $baninfo->{channel}, but within 5 seconds of establishing ban; giving another chance\n");
my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'validated');
if ($channel_data->{validated} & $self->{NICKSERV_VALIDATED}) {
$channel_data->{validated} &= ~$self->{NICKSERV_VALIDATED};
@ -833,18 +833,18 @@ sub check_bans {
my $u = $self->{pbot}->{users}->loggedin($baninfo->{channel}, $mask);
my $whitelisted = $self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted');
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{banmask}) || $whitelisted) {
#$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{banmask} in $baninfo->{channel}, but allowed through whitelist\n");
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{mask}) || $whitelisted) {
#$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{mask} in $baninfo->{channel}, but allowed through whitelist\n");
next;
}
# special case for twkm clone bans
if ($baninfo->{banmask} =~ m/\?\*!\*@\*$/) {
$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{banmask} in $baninfo->{channel}, but disregarded due to clone ban\n");
if ($baninfo->{mask} =~ m/\?\*!\*@\*$/) {
$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask [$alias] evaded $baninfo->{mask} in $baninfo->{channel}, but disregarded due to clone ban\n");
next;
}
my $banmask_regex = quotemeta $baninfo->{banmask};
my $banmask_regex = quotemeta $baninfo->{mask};
$banmask_regex =~ s/\\\*/.*/g;
$banmask_regex =~ s/\\\?/./g;
@ -853,7 +853,7 @@ sub check_bans {
next;
}
if (defined $nickserv and $baninfo->{type} eq '+q' and $baninfo->{banmask} =~ /^\$a:(.*)/ and lc $1 eq $nickserv and $nickserv eq $current_nickserv_account) {
if (defined $nickserv and $baninfo->{type} eq '+q' and $baninfo->{mask} =~ /^\$a:(.*)/ and lc $1 eq $nickserv and $nickserv eq $current_nickserv_account) {
$self->{pbot}->{logger}->log("anti-flood: [check-bans] Hostmask ($mask) matches quiet on account ($nickserv), disregarding\n");
next;
}
@ -861,7 +861,7 @@ sub check_bans {
if (not defined $bans) { $bans = []; }
$self->{pbot}->{logger}
->log("anti-flood: [check-bans] Hostmask ($mask [$alias" . (defined $nickserv ? "/$nickserv" : "") . "]) matches $baninfo->{type} $baninfo->{banmask}, adding ban\n");
->log("anti-flood: [check-bans] Hostmask ($mask [$alias" . (defined $nickserv ? "/$nickserv" : "") . "]) matches $baninfo->{type} $baninfo->{mask}, adding ban\n");
push @$bans, $baninfo;
goto GOT_BAN;
}
@ -877,7 +877,7 @@ sub check_bans {
my ($user, $host) = $mask =~ m/[^!]+!([^@]+)@(.*)/;
if ($host =~ m{^([^/]+)/.+} and $1 ne 'gateway' and $1 ne 'nat') { $banmask = "*!*\@$host"; }
elsif ( $current_nickserv_account
and $baninfo->{banmask} !~ m/^\$a:/i
and $baninfo->{mask} !~ m/^\$a:/i
and not $self->{pbot}->{banlist}->{banlist}->exists($baninfo->{channel}, "\$a:$current_nickserv_account"))
{
$banmask = "\$a:$current_nickserv_account";
@ -890,10 +890,10 @@ sub check_bans {
}
}
$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask evaded $baninfo->{banmask} banned in $baninfo->{channel} by $baninfo->{owner}, banning $banmask\n");
$self->{pbot}->{logger}->log("anti-flood: [check-bans] $mask evaded $baninfo->{mask} banned in $baninfo->{channel} by $baninfo->{owner}, banning $banmask\n");
my ($bannick) = $mask =~ m/^([^!]+)/;
if ($self->{pbot}->{registry}->get_value('antiflood', 'enforce')) {
if ($self->{pbot}->{chanops}->has_ban_timeout($baninfo->{channel}, $banmask)) {
if ($self->{pbot}->{banlist}->has_ban_timeout($baninfo->{channel}, $banmask)) {
$self->{pbot}->{logger}->log("anti-flood: [check-bans] $banmask already banned in $channel, disregarding\n");
return;
}
@ -915,7 +915,7 @@ sub check_bans {
else {
my $owner = $baninfo->{owner};
$owner =~ s/!.*$//;
$self->{pbot}->{chanops}->add_op_command($baninfo->{channel}, "kick $baninfo->{channel} $bannick Evaded $baninfo->{banmask} set by $owner");
$self->{pbot}->{chanops}->add_op_command($baninfo->{channel}, "kick $baninfo->{channel} $bannick Evaded $baninfo->{mask} set by $owner");
}
$self->{pbot}->{banlist}->ban_user_timed(
$banmask, $baninfo->{channel},

View File

@ -75,7 +75,7 @@ sub banlist_cmd {
if ($self->{banlist}->exists($arguments)) {
my $count = $self->{banlist}->get_keys($arguments);
$result .= "$count bans:\n";
$result .= "$count ban" . ($count == 1 ? '' : 's') . ":\n";
foreach my $mask ($self->{banlist}->get_keys($arguments)) {
my $data = $self->{banlist}->get_data($arguments, $mask);
$result .= " $mask banned ";
@ -100,7 +100,7 @@ sub banlist_cmd {
if ($self->{quietlist}->exists($arguments)) {
my $count = $self->{quietlist}->get_keys($arguments);
$result .= "$count mutes:\n";
$result .= "$count mute" . ($count == 1 ? '' : 's') . ":\n";
foreach my $mask ($self->{quietlist}->get_keys($arguments)) {
my $data = $self->{quietlist}->get_data($arguments, $mask);
$result .= " $mask muted ";
@ -120,9 +120,10 @@ sub banlist_cmd {
$result .= ";\n";
}
} else {
$result .= "quiets: none;\n";
$result .= "quiets: none\n";
}
$result =~ s/ ;/;/g;
return $result;
}
@ -166,7 +167,7 @@ sub on_banlist_entry {
my $timestamp = $event->{event}->{args}[4];
my $ago = concise ago(gettimeofday - $timestamp);
$self->{pbot}->{logger}->log("banlist: [banlist entry] $channel: $target banned by $source $ago.\n");
$self->{pbot}->{logger}->log("Ban List: [banlist entry] $channel: $target banned by $source $ago.\n");
$self->{temp_banlist}->{$channel}->{'+b'}->{$target} = [$source, $timestamp];
return 0;
}
@ -180,7 +181,7 @@ sub on_quietlist_entry {
my $timestamp = $event->{event}->{args}[5];
my $ago = concise ago(gettimeofday - $timestamp);
$self->{pbot}->{logger}->log("banlist: [quietlist entry] $channel: $target quieted by $source $ago.\n");
$self->{pbot}->{logger}->log("Ban List: [quietlist entry] $channel: $target quieted by $source $ago.\n");
$self->{temp_banlist}->{$channel}->{'+q'}->{$target} = [$source, $timestamp];
return 0;
}
@ -189,7 +190,7 @@ sub compare_banlist {
my ($self, $event_type, $event) = @_;
my $channel = lc $event->{event}->{args}[1];
$self->{pbot}->{logger}->log("Finalizing ban list for $channel\n");
$self->{pbot}->{logger}->log("Finalizing Ban List for $channel\n");
# first check for saved bans no longer in channel
foreach my $mask ($self->{banlist}->get_keys($channel)) {
@ -226,7 +227,8 @@ sub compare_banlist {
$self->{banlist}->add($channel, $mask, $data, 1);
}
$self->{banlist}->save;
$self->{banlist}->save if keys %{$self->{temp_banlist}->{$channel}->{'+b'}};
delete $self->{temp_banlist}->{$channel}->{'+b'};
}
sub compare_quietlist {
@ -253,7 +255,8 @@ sub compare_quietlist {
$self->{quietlist}->add($channel, $mask, $data, 1);
}
$self->{quietlist}->save;
$self->{quietlist}->save if keys %{$self->{temp_banlist}->{$channel}->{'+q'}};
delete $self->{temp_banlist}->{$channel}->{'+q'};
}
sub track_mode {
@ -265,7 +268,7 @@ sub track_mode {
$mask = lc $mask;
if ($mode eq "+b" or $mode eq "+q") {
$self->{pbot}->{logger}->log("banlist: $mask " . ($mode eq '+b' ? 'banned' : 'quieted') . " by $source in $channel.\n");
$self->{pbot}->{logger}->log("Ban List: $mask " . ($mode eq '+b' ? 'banned' : 'quieted') . " by $source in $channel.\n");
my $data = {
owner => $source,
@ -280,7 +283,7 @@ sub track_mode {
$self->{pbot}->{antiflood}->devalidate_accounts($mask, $channel);
} elsif ($mode eq "-b" or $mode eq "-q") {
$self->{pbot}->{logger}->log("banlist: $mask " . ($mode eq '-b' ? 'unbanned' : 'unquieted') . " by $source in $channel.\n");
$self->{pbot}->{logger}->log("Ban List: $mask " . ($mode eq '-b' ? 'unbanned' : 'unquieted') . " by $source in $channel.\n");
if ($mode eq "-b") {
$self->{banlist}->remove($channel, $mask);
@ -323,7 +326,7 @@ sub track_mode {
if (not $self->{banlist}->exists($channel, $mask)) {
$self->{pbot}->{logger}->log("Temp ban for $mask in $channel.\n");
my $data = {
reason => 'Temp ban for *!*@... banmask',
reason => 'Temp ban for *!*@host',
timeout => gettimeofday + $timeout,
owner => $self->{pbot}->{registry}->get_value('irc', 'botnick'),
timestamp => gettimeofday,
@ -383,14 +386,14 @@ sub unmode_user {
my %unbanned;
if (not defined $bans) {
push @$bans, { banmask => $mask, type => "+$mode" };
push @$bans, { mask => $mask, type => "+$mode" };
}
foreach my $ban (@$bans) {
next if $ban->{type} ne "+$mode";
next if exists $unbanned{$ban->{banmask}};
$unbanned{$ban->{banmask}} = 1;
$self->add_to_unban_queue($channel, $mode, $ban->{banmask});
next if exists $unbanned{$ban->{mask}};
$unbanned{$ban->{mask}} = 1;
$self->add_to_unban_queue($channel, $mode, $ban->{mask});
}
$self->flush_unban_queue if $immediately;
@ -695,7 +698,8 @@ sub enqueue_timeouts {
foreach my $channel ($list->get_keys) {
foreach my $mask ($list->get_keys($channel)) {
my $timeout = $list->get_data($channel, $mask, 'timeout');
next if $timeout <= 0;
next if defined $timeout and $timeout <= 0;
next if not defined $timeout;
my $interval = $timeout - $now;
$interval = 10 if $interval < 10;
$self->enqueue_unban($channel, $mode, $mask, $interval);

View File

@ -19,8 +19,8 @@ use LWP::UserAgent;
# These are set automatically by the misc/update_version script
use constant {
BUILD_NAME => "PBot",
BUILD_REVISION => 3522,
BUILD_DATE => "2020-04-24",
BUILD_REVISION => 3536,
BUILD_DATE => "2020-04-28",
};
sub initialize {

View File

@ -103,7 +103,7 @@ sub check_queue {
# ensure they're not banned (+z allows us to see +q/+b messages as normal ones)
my $banned = $self->{pbot}->{banlist}->is_banned($nick, $user, $host, $channel);
$self->{pbot}->{logger}
->log("[RelayUnreg] $nick!$user\@$host $banned->{mode} as $banned->{banmask} in $banned->{channel} by $banned->{owner}, not relaying unregistered message\n")
->log("[RelayUnreg] $nick!$user\@$host $banned->{mode} as $banned->{mask} in $banned->{channel} by $banned->{owner}, not relaying unregistered message\n")
if $banned;
$self->{pbot}->{conn}->privmsg($channel, "(unreg) <$nick> $msg") unless $banned;
}

View File

@ -90,7 +90,7 @@ sub generic_command {
if ($command eq 'unban') {
my $reason = $self->{pbot}->{banlist}->checkban($channel, 'b', $target);
if ($reason =~ m/moderator ban/) {
$self->{pbot}->{chanops}->unban_user($channel, 'b', $target, 1);
$self->{pbot}->{banlist}->unban_user($channel, 'b', $target, 1);
return "";
} else {
return "I don't think so. That ban was not set by a moderator.";

4
data/banlist vendored
View File

@ -1,8 +1,8 @@
{
"$metadata$" : {
"$metadata$" : {
"update_version" : 3503,
"name" : "Ban List"
"name" : "Ban List",
"update_version" : "3536"
}
}
}

2
data/last_update vendored
View File

@ -1 +1 @@
3512
3536

4
data/quietlist vendored
View File

@ -1,8 +1,8 @@
{
"$metadata$" : {
"$metadata$" : {
"update_version" : 3503,
"name" : "Quiet List"
"name" : "Quiet List",
"update_version" : "3536"
}
}
}

6
data/registry vendored
View File

@ -1,8 +1,8 @@
{
"$metadata$" : {
"$metadata$" : {
"update_version" : 3503,
"name" : "Registry"
"name" : "Registry",
"update_version" : "3536"
}
},
"antiaway" : {
@ -123,7 +123,7 @@
"value" : "900,1800,3600"
}
},
"bantracker" : {
"banlist" : {
"chanserv_ban_timeout" : {
"type" : "text",
"value" : "604800"

51
updates/3536_update_banlist.pl Executable file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env perl
# Convert unmute_timeouts and unban_timeouts to quietlist and banlist
# Rename bantracker to banlist in registry
use warnings; use strict;
BEGIN {
use File::Basename;
my $location = -l __FILE__ ? dirname readlink __FILE__ : dirname __FILE__;
unshift @INC, $location;
}
use lib3512::DualIndexHashObject;
use lib3503::PBot;
my ($data_dir, $version, $last_update) = @ARGV;
print "Updating ban list data... version: $version, last_update: $last_update, data_dir: $data_dir\n";
my $pbot = lib3503::PBot->new();
my $unmutes = lib3512::DualIndexHashObject->new(name => 'old unmute timeouts', filename => "$data_dir/unmute_timeouts", pbot => $pbot);
$unmutes->load;
$unmutes->set('$metadata$', '$metadata$', 'name', 'Quiet List', 1);
$unmutes->set('$metadata$', '$metadata$', 'update_version', '3536');
my $unbans = lib3512::DualIndexHashObject->new(name => 'old unban timeouts', filename => "$data_dir/unban_timeouts", pbot => $pbot);
$unbans->load;
$unbans->set('$metadata$', '$metadata$', 'name', 'Ban List', 1);
$unbans->set('$metadata$', '$metadata$', 'update_version', '3536');
use File::Copy;
move("$data_dir/unmute_timeouts", "$data_dir/quietlist") or die "Failed to move unmute_timeouts -> quietlist: $!";
move("$data_dir/unban_timeouts", "$data_dir/banlist") or die "Failed to move unban_timeouts -> banlist: $!";
my $registry = lib3512::DualIndexHashObject->new(name => 'Registry', filename => "$data_dir/registry", pbot => $pbot);
$registry->load;
my $data = $registry->get_data('bantracker');
$registry->remove('bantracker', undef, undef, 1);
foreach my $key (keys %{$data}) {
$registry->add('banlist', $key, $data->{$key}, 1);
}
$registry->set('$metadata$', '$metadata$', 'update_version', '3536');
exit 0;