From 1442485d0bea771ecbfc8d73b88eb77da378602a Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Sun, 28 Aug 2016 03:49:27 -0700 Subject: [PATCH] Support account-notify and extended-join capabilities --- PBot/AntiFlood.pm | 38 +++++++++++++++++++++++++++++++++----- PBot/IRC/Connection.pm | 5 +++-- PBot/IRC/Event.pm | 2 ++ PBot/IRCHandlers.pm | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/PBot/AntiFlood.pm b/PBot/AntiFlood.pm index a63544b4..39eaeafe 100644 --- a/PBot/AntiFlood.pm +++ b/PBot/AntiFlood.pm @@ -80,9 +80,10 @@ sub initialize { $self->{pbot}->{commands}->register(sub { return $self->unbanme(@_) }, "unbanme", 0); $self->{pbot}->{commands}->register(sub { return $self->whitelist(@_) }, "whitelist", 10); - $self->{pbot}->{event_dispatcher}->register_handler('irc.whoisaccount', sub { $self->on_whoisaccount(@_) }); - $self->{pbot}->{event_dispatcher}->register_handler('irc.whoisuser', sub { $self->on_whoisuser(@_) }); - $self->{pbot}->{event_dispatcher}->register_handler('irc.endofwhois', sub { $self->on_endofwhois(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.whoisaccount', sub { $self->on_whoisaccount(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.whoisuser', sub { $self->on_whoisuser(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.endofwhois', sub { $self->on_endofwhois(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.account', sub { $self->on_accountnotify(@_) }); } sub whitelisted { @@ -270,7 +271,9 @@ sub update_join_watch { } # check QUIT message for Ping timeout or Excess Flood elsif($text =~ /^QUIT Ping timeout/ or $text =~ /^QUIT Excess Flood/) { - # ignore these (used to treat aggressively) + # treat these as an extra join so they're snagged more quickly since these usually will keep flooding + $channel_data->{join_watch}++; + $self->{pbot}->{messagehistory}->{database}->update_channel_data($account, $channel, $channel_data); } else { # some other type of QUIT or PART } @@ -993,7 +996,6 @@ sub on_whoisuser { my $nick = $event->{event}->{args}[1]; my $gecos = lc $event->{event}->{args}[5]; - my ($id) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($nick); if ($self->{pbot}->{registry}->get_value('antiflood', 'debug_checkban') >= 2) { @@ -1021,6 +1023,32 @@ sub on_whoisaccount { return 0; } +sub on_accountnotify { + my ($self, $event_type, $event) = @_; + + if ($event->{event}->{args}[0] eq '*') { + $self->{pbot}->{logger}->log("$event->{event}->{from} logged out of NickServ\n"); + } else { + $self->{pbot}->{logger}->log("$event->{event}->{from} logged into NickServ account $event->{event}->{args}[0]\n"); + + my $nick = $event->{event}->nick; + my ($id, $hostmask) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($nick); + $self->{pbot}->{messagehistory}->{database}->link_aliases($id, undef, $event->{event}->{args}[0]) if $id; + $self->check_nickserv_accounts($nick, $event->{event}->{args}[0]); + + $self->{pbot}->{messagehistory}->{database}->devalidate_all_channels($id); + + my $channels = $self->{pbot}->{nicklist}->get_channels($nick); + foreach my $channel (@$channels) { + next unless $channel =~ /^#/; + my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($id, $channel, 'validated'); + if ($channel_data->{validated} & $self->{NEEDS_CHECKBAN} or not $channel_data->{validated} & $self->{NICKSERV_VALIDATED}) { + $self->check_bans($id, $hostmask, $channel); + } + } + } +} + sub adjust_offenses { my $self = shift; diff --git a/PBot/IRC/Connection.pm b/PBot/IRC/Connection.pm index 3f8da0c3..b37b707b 100644 --- a/PBot/IRC/Connection.pm +++ b/PBot/IRC/Connection.pm @@ -997,7 +997,8 @@ sub parse { } elsif ($type eq "public" or $type eq "msg" or $type eq "notice" or $type eq "mode" or $type eq "join" or $type eq "part" or - $type eq "topic" or $type eq "invite" or $type eq "whoisaccount" ) { + $type eq "topic" or $type eq "invite" or + $type eq "whoisaccount" or $type eq "cap") { $ev = PBot::IRC::Event->new( $type, # pragma_ 2011/21/01 $from, @@ -1005,7 +1006,7 @@ sub parse { $type, @stuff, ); - } elsif ($type eq "quit" or $type eq "nick") { + } elsif ($type eq "quit" or $type eq "nick" or $type eq "account") { $ev = PBot::IRC::Event->new( $type, # pragma_ 2011/21/01 $from, diff --git a/PBot/IRC/Event.pm b/PBot/IRC/Event.pm index a100220a..8839ec80 100644 --- a/PBot/IRC/Event.pm +++ b/PBot/IRC/Event.pm @@ -470,6 +470,8 @@ sub trans { 'nick' => 'nick', 'pong' => 'pong', 'invite' => 'invite', + 'cap' => 'cap', + 'account' => 'account', ); diff --git a/PBot/IRCHandlers.pm b/PBot/IRCHandlers.pm index 4d9c5882..50fa14fe 100644 --- a/PBot/IRCHandlers.pm +++ b/PBot/IRCHandlers.pm @@ -45,6 +45,7 @@ sub initialize { $self->{pbot}->{event_dispatcher}->register_handler('irc.nick', sub { $self->on_nickchange(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.nicknameinuse', sub { $self->on_nicknameinuse(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.invite', sub { $self->on_invite(@_) }); + $self->{pbot}->{event_dispatcher}->register_handler('irc.cap', sub { $self->on_cap(@_) }); } sub default_handler { @@ -69,6 +70,9 @@ sub on_connect { $self->{pbot}->{logger}->log("Connected!\n"); $event->{conn}->{connected} = 1; + $self->{pbot}->{logger}->log("Requesting account-notify and extended-join . . .\n"); + $event->{conn}->sl("CAP REQ :account-notify extended-join"); + $self->{pbot}->{logger}->log("Identifying with NickServ . . .\n"); $event->{conn}->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password')); @@ -229,7 +233,24 @@ sub on_join { my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host); $self->{pbot}->{messagehistory}->add_message($message_account, "$nick!$user\@$host", $channel, "JOIN", $self->{pbot}->{messagehistory}->{MSG_JOIN}); - $self->{pbot}->{antiflood}->check_flood($channel, $nick, $user, $host, "JOIN", + + my $msg = 'JOIN'; + + if (exists $self->{pbot}->{capabilities}->{'extended-join'}) { + $msg .= " $event->{event}->{args}[0] :$event->{event}->{args}[1]"; + + $self->{pbot}->{messagehistory}->{database}->update_gecos($message_account, $event->{event}->{args}[1], scalar gettimeofday); + + if ($event->{event}->{args}[0] ne '*') { + $self->{pbot}->{messagehistory}->{database}->link_aliases($message_account, undef, $event->{event}->{args}[0]); + $self->{pbot}->{antiflood}->check_nickserv_accounts($nick, $event->{event}->{args}[0]); + + $self->{pbot}->{messagehistory}->{database}->devalidate_all_channels($message_account); + $self->{pbot}->{antiflood}->check_bans($message_account, $event->{event}->from, $channel); + } + } + + $self->{pbot}->{antiflood}->check_flood($channel, $nick, $user, $host, $msg, $self->{pbot}->{registry}->get_value('antiflood', 'join_flood_threshold'), $self->{pbot}->{registry}->get_value('antiflood', 'join_flood_time_threshold'), $self->{pbot}->{messagehistory}->{MSG_JOIN}); @@ -316,6 +337,21 @@ sub on_departure { return 0; } +sub on_cap { + my ($self, $event_type, $event) = @_; + + if ($event->{event}->{args}->[0] eq 'ACK') { + $self->{pbot}->{logger}->log("Client capabilities granted: " . $event->{event}->{args}->[1] . "\n"); + + my @caps = split / /, $event->{event}->{args}->[1]; + foreach my $cap (@caps) { + $self->{pbot}->{capabilities}->{$cap} = 1; + } + } else { + $self->{pbot}->{logger}->log(Dumper $event->{event}); + } +} + sub on_nickchange { my ($self, $event_type, $event) = @_; my ($nick, $user, $host, $newnick) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->args);