From ecd2bad0668654b599f2f6db064079ebf56a3010 Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Sun, 28 Dec 2014 00:44:15 +0000 Subject: [PATCH] Add anti-kick-auto-rejoin module that temporarily kickbans offenders who immediately auto-rejoin after having been kicked --- PBot/AntiKickAutoRejoin.pm | 74 ++++++++++++++++++++++++++++++++++++++ PBot/PBot.pm | 34 +++++++++--------- PBot/VERSION.pm | 4 +-- 3 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 PBot/AntiKickAutoRejoin.pm diff --git a/PBot/AntiKickAutoRejoin.pm b/PBot/AntiKickAutoRejoin.pm new file mode 100644 index 00000000..3d22be52 --- /dev/null +++ b/PBot/AntiKickAutoRejoin.pm @@ -0,0 +1,74 @@ +# File: AntiKickAutoRejoin.pm +# Author: pragma_ +# +# Purpose: Temporarily bans people who immediately auto-rejoin after a kick. + +package PBot::AntiKickAutoRejoin; + +use warnings; +use strict; + +use Carp (); +use Time::HiRes qw/gettimeofday/; +use Time::Duration; + +sub new { + Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH'; + my ($class, %conf) = @_; + my $self = bless {}, $class; + $self->initialize(%conf); + return $self; +} + +sub initialize { + my ($self, %conf) = @_; + + $self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__); + + $self->{pbot}->{registry}->add_default('array', 'antikickautorejoin', 'punishment', '300,900,1800,3600,28800'); + $self->{pbot}->{registry}->add_default('text', 'antikickautorejoin', 'threshold', '4'); + + $self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) }); + + $self->{kicks} = {}; +} + +sub on_kick { + my ($self, $event_type, $event) = @_; + my ($nick, $user, $host, $target, $channel, $reason) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to, $event->{event}->{args}[0], $event->{event}->{args}[1]); + + if (not exists $self->{kicks}->{$channel} + or not exists $self->{kicks}->{$channel}->{$target}) { + $self->{kicks}->{$channel}->{$target}->{rejoins} = 0; + } + + $self->{kicks}->{$channel}->{$target}->{last_kick} = gettimeofday; + + return 0; +} + +sub on_join { + my ($self, $event_type, $event) = @_; + my ($nick, $user, $host, $channel) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to); + + if (exists $self->{kicks}->{$channel} + and exists $self->{kicks}->{$channel}->{$nick}) { + my $now = gettimeofday; + + if ($now - $self->{kicks}->{$channel}->{$nick}->{last_kick} <= $self->{pbot}->{registry}->get_value('antikickautorejoin', 'threshold')) { + my $timeout = $self->{pbot}->{registry}->get_array_value('antikickautorejoin', 'punishment', $self->{kicks}->{$channel}->{$nick}->{rejoins}); + my $duration = duration($timeout); + $duration =~ s/s$//; # hours -> hour, minutes -> minute + + $self->{pbot}->{chanops}->ban_user_timed("*!$user\@$host", $channel, $timeout); + $self->{pbot}->{chanops}->add_op_command($channel, "kick $channel $nick $duration ban for auto-rejoining after kick"); + $self->{pbot}->{chanops}->gain_ops($channel); + $self->{kicks}->{$channel}->{$nick}->{rejoins}++; + } + } + + return 0; +} + +1; diff --git a/PBot/PBot.pm b/PBot/PBot.pm index cb247b61..56bd9aff 100644 --- a/PBot/PBot.pm +++ b/PBot/PBot.pm @@ -47,6 +47,7 @@ use PBot::IgnoreList; use PBot::Quotegrabs; use PBot::Timer; use PBot::AntiAway; +use PBot::AntiKickAutoRejoin; sub new { if(ref($_[1]) eq 'HASH') { @@ -101,23 +102,24 @@ sub initialize { $self->{registry}->add_trigger('irc', 'botnick', sub { $self->change_botnick_trigger(@_) }); $self->{registry}->add_trigger('irc', 'debug', sub { $self->irc_debug_trigger(@_) }); - $self->{event_dispatcher} = PBot::EventDispatcher->new(pbot => $self, %conf); - $self->{select_handler} = PBot::SelectHandler->new(pbot => $self, %conf); - $self->{stdin_reader} = PBot::StdinReader->new(pbot => $self, %conf); - $self->{admins} = PBot::BotAdmins->new(pbot => $self, filename => delete $conf{admins_file}, %conf); - $self->{bantracker} = PBot::BanTracker->new(pbot => $self, %conf); - $self->{nicklist} = PBot::NickList->new(pbot => $self, %conf); - $self->{lagchecker} = PBot::LagChecker->new(pbot => $self, %conf); - $self->{messagehistory} = PBot::MessageHistory->new(pbot => $self, filename => delete $conf{messagehistory_file}, %conf); - $self->{antiflood} = PBot::AntiFlood->new(pbot => $self, %conf); - $self->{ignorelist} = PBot::IgnoreList->new(pbot => $self, filename => delete $conf{ignorelist_file}, %conf); - $self->{irc} = PBot::IRC->new(); - $self->{irchandlers} = PBot::IRCHandlers->new(pbot => $self, %conf); - $self->{channels} = PBot::Channels->new(pbot => $self, filename => delete $conf{channels_file}, %conf); - $self->{chanops} = PBot::ChanOps->new(pbot => $self, %conf); - $self->{antiaway} = PBot::AntiAway->new(pbot => $self, %conf); + $self->{event_dispatcher} = PBot::EventDispatcher->new(pbot => $self, %conf); + $self->{select_handler} = PBot::SelectHandler->new(pbot => $self, %conf); + $self->{stdin_reader} = PBot::StdinReader->new(pbot => $self, %conf); + $self->{admins} = PBot::BotAdmins->new(pbot => $self, filename => delete $conf{admins_file}, %conf); + $self->{bantracker} = PBot::BanTracker->new(pbot => $self, %conf); + $self->{nicklist} = PBot::NickList->new(pbot => $self, %conf); + $self->{lagchecker} = PBot::LagChecker->new(pbot => $self, %conf); + $self->{messagehistory} = PBot::MessageHistory->new(pbot => $self, filename => delete $conf{messagehistory_file}, %conf); + $self->{antiflood} = PBot::AntiFlood->new(pbot => $self, %conf); + $self->{ignorelist} = PBot::IgnoreList->new(pbot => $self, filename => delete $conf{ignorelist_file}, %conf); + $self->{irc} = PBot::IRC->new(); + $self->{irchandlers} = PBot::IRCHandlers->new(pbot => $self, %conf); + $self->{channels} = PBot::Channels->new(pbot => $self, filename => delete $conf{channels_file}, %conf); + $self->{chanops} = PBot::ChanOps->new(pbot => $self, %conf); + $self->{antiaway} = PBot::AntiAway->new(pbot => $self, %conf); + $self->{antikickautorejoin} = PBot::AntiKickAutoRejoin->new(pbot => $self, %conf); - $self->{interpreter} = PBot::Interpreter->new(pbot => $self, %conf); + $self->{interpreter} = PBot::Interpreter->new(pbot => $self, %conf); $self->{interpreter}->register(sub { return $self->{commands}->interpreter(@_); }); $self->{interpreter}->register(sub { return $self->{factoids}->interpreter(@_); }); diff --git a/PBot/VERSION.pm b/PBot/VERSION.pm index 3fbd1159..6253eb6b 100644 --- a/PBot/VERSION.pm +++ b/PBot/VERSION.pm @@ -13,8 +13,8 @@ use warnings; # These are set automatically by the build/commit script use constant { BUILD_NAME => "PBot", - BUILD_REVISION => 805, - BUILD_DATE => "2014-12-26", + BUILD_REVISION => 806, + BUILD_DATE => "2014-12-27", }; 1;