3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-10-03 01:48:38 +02:00

Add event dispatcher module to allow modules to dispatch events and

to register handlers to listen for events.

Update IRCHandlers module to use new event dispatcher to dispatch
irc.events.  Update several modules to register with dispatcher
to listen for irc.events.

Improve handling of reconnection upon unexpected disconnection.

Todo: update more things to use new event dispatcher logic.
This commit is contained in:
Pragmatic Software 2014-11-01 00:15:21 +00:00
parent bc604d3ce2
commit d1e7abc175
8 changed files with 249 additions and 176 deletions

View File

@ -77,6 +77,8 @@ sub initialize {
$self->{pbot}->{commands}->register(sub { return $self->unbanme(@_) }, "unbanme", 0); $self->{pbot}->{commands}->register(sub { return $self->unbanme(@_) }, "unbanme", 0);
$self->{pbot}->{commands}->register(sub { return $self->whitelist(@_) }, "whitelist", 10); $self->{pbot}->{commands}->register(sub { return $self->whitelist(@_) }, "whitelist", 10);
$self->{pbot}->{event_dispatcher}->register_handler('irc.whoisaccount', sub { $self->on_whoisaccount(@_) });
} }
sub ban_whitelisted { sub ban_whitelisted {
@ -735,12 +737,13 @@ sub check_nickserv_accounts {
} }
sub on_whoisaccount { sub on_whoisaccount {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my $nick = $event->{args}[1]; my $nick = $event->{event}->{args}[1];
my $account = lc $event->{args}[2]; my $account = lc $event->{event}->{args}[2];
$self->{pbot}->{logger}->log("$nick is using NickServ account [$account]\n"); $self->{pbot}->{logger}->log("$nick is using NickServ account [$account]\n");
$self->check_nickserv_accounts($nick, $account); $self->check_nickserv_accounts($nick, $account);
return 0;
} }
sub adjust_offenses { sub adjust_offenses {

View File

@ -31,14 +31,16 @@ sub new {
sub initialize { sub initialize {
my ($self, %conf) = @_; my ($self, %conf) = @_;
my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to BanTracker"); $self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to BanTracker");
$self->{pbot} = $pbot;
$self->{banlist} = {}; $self->{banlist} = {};
$self->{pbot}->{registry}->add_default('text', 'bantracker', 'chanserv_ban_timeout', '604800'); $self->{pbot}->{registry}->add_default('text', 'bantracker', 'chanserv_ban_timeout', '604800');
$pbot->{commands}->register(sub { return $self->dumpbans(@_) }, "dumpbans", 60); $self->{pbot}->{commands}->register(sub { $self->dumpbans(@_) }, "dumpbans", 60);
$self->{pbot}->{event_dispatcher}->register_handler('irc.endofnames', sub { $self->get_banlist(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.banlist', sub { $self->on_banlist_entry(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quietlist', sub { $self->on_quietlist_entry(@_) });
} }
sub dumpbans { sub dumpbans {
@ -49,14 +51,43 @@ sub dumpbans {
} }
sub get_banlist { sub get_banlist {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my $channel = lc $event->{args}[1]; my $channel = lc $event->{event}->{args}[1];
delete $self->{banlist}->{$channel}; delete $self->{banlist}->{$channel};
$self->{pbot}->{logger}->log("Retrieving banlist for $channel.\n"); $self->{pbot}->{logger}->log("Retrieving banlist for $channel.\n");
$conn->sl("mode $channel +b"); $event->{conn}->sl("mode $channel +b");
$conn->sl("mode $channel +q"); $event->{conn}->sl("mode $channel +q");
return 0;
}
sub on_banlist_entry {
my ($self, $event_type, $event) = @_;
my $channel = lc $event->{event}->{args}[1];
my $target = lc $event->{event}->{args}[2];
my $source = lc $event->{event}->{args}[3];
my $timestamp = $event->{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 ];
return 0;
}
sub on_quietlist_entry {
my ($self, $event_type, $event) = @_;
my $channel = lc $event->{event}->{args}[1];
my $target = lc $event->{event}->{args}[3];
my $source = lc $event->{event}->{args}[4];
my $timestamp = $event->{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 ];
return 0;
} }
sub get_baninfo { sub get_baninfo {
@ -102,32 +133,6 @@ sub get_baninfo {
return $bans; return $bans;
} }
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 { sub track_mode {
my $self = shift; my $self = shift;
my ($source, $mode, $target, $channel) = @_; my ($source, $mode, $target, $channel) = @_;

48
PBot/EventDispatcher.pm Normal file
View File

@ -0,0 +1,48 @@
package PBot::EventDispatcher;
use warnings;
use strict;
use IO::Select;
use Carp ();
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 in " . __FILE__);
$self->{handlers} = { any => [] };
}
sub register_handler {
my ($self, $event_type, $sub) = @_;
push @{$self->{handlers}->{$event_type}}, $sub;
}
sub dispatch_event {
my ($self, $event_type, $event_data) = @_;
my $ret = undef;
if (exists $self->{handlers}->{$event_type}) {
foreach my $handler (@{$self->{handlers}->{$event_type}}) {
$ret = $handler->($event_type, $event_data);
return $ret if $ret;
}
}
foreach my $handler (@{$self->{handlers}->{any}}) {
$ret = $handler->($event_type, $event_data);
return $ret if $ret;
}
return $ret;
}
1;

View File

@ -14,7 +14,7 @@ use Data::Dumper;
sub new { sub new {
if(ref($_[1]) eq 'HASH') { if(ref($_[1]) eq 'HASH') {
Carp::croak("Options to IRCHandlers should be key/value pairs, not hash reference"); Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
} }
my ($class, %conf) = @_; my ($class, %conf) = @_;
@ -27,34 +27,34 @@ sub new {
sub initialize { sub initialize {
my ($self, %conf) = @_; my ($self, %conf) = @_;
my $pbot = delete $conf{pbot}; $self->{pbot} = delete $conf{pbot};
Carp::croak("Missing pbot parameter to IRCHandlers") if not defined $pbot; Carp::croak("Missing pbot parameter to " . __FILE__) if not defined $self->{pbot};
$self->{pbot} = $pbot; $self->{pbot}->{event_dispatcher}->register_handler('irc.welcome', sub { $self->on_connect(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.disconnect', sub { $self->on_disconnect(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.motd', sub { $self->on_motd(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.notice', sub { $self->on_notice(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.caction', sub { $self->on_action(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.msg', sub { $self->on_msg(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.mode', sub { $self->on_mode(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.nick', sub { $self->on_nickchange(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.bannickchange', sub { $self->on_bannickchange(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.notregistered', sub { $self->on_notregistered(@_) });
} }
sub default_handler { sub default_handler {
my ($self, $conn, $event) = @_; my ($self, $conn, $event) = @_;
if ($self->{pbot}->{registry}->get_value('irc', 'log_default_handler')) { if(not defined $self->{pbot}->{event_dispatcher}->dispatch_event("irc.$event->{type}", { conn => $conn, event => $event })) {
my $dump = Dumper $event; if ($self->{pbot}->{registry}->get_value('irc', 'log_default_handler')) {
$self->{pbot}->{logger}->log($dump); my $dump = Dumper $event;
} $self->{pbot}->{logger}->log($dump);
} }
sub on_connect {
my ($self, $conn) = @_;
$self->{pbot}->{logger}->log("Connected!\n");
$conn->{connected} = 1;
}
sub on_disconnect {
my ($self, $conn, $event) = @_;
$self->{pbot}->{logger}->log("Disconnected, attempting to reconnect...\n");
$conn->connect();
if(not $conn->connected) {
sleep(5);
$self->on_disconnect($self, $conn, $event);
} }
} }
@ -65,76 +65,95 @@ sub on_init {
$self->{pbot}->{logger}->log("*** @args\n"); $self->{pbot}->{logger}->log("*** @args\n");
} }
sub on_connect {
my ($self, $event_type, $event) = @_;
$self->{pbot}->{logger}->log("Connected!\n");
$event->{conn}->{connected} = 1;
return 0;
}
sub on_disconnect {
my ($self, $event_type, $event) = @_;
$self->{pbot}->{logger}->log("Disconnected...\n");
$self->{pbot}->{connected} = 0;
return 0;
}
sub on_motd { sub on_motd {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
if ($self->{pbot}->{registry}->get_value('irc', 'show_motd')) { if ($self->{pbot}->{registry}->get_value('irc', 'show_motd')) {
my $server = $event->{from}; my $server = $event->{event}->{from};
my $msg = $event->{args}[1]; my $msg = $event->{event}->{args}[1];
$self->{pbot}->{logger}->log("MOTD from $server :: $msg\n"); $self->{pbot}->{logger}->log("MOTD from $server :: $msg\n");
} }
return 0;
} }
sub on_public { sub on_public {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my $from = $event->{to}[0]; my $from = $event->{event}->{to}[0];
my $nick = $event->nick; my $nick = $event->{event}->nick;
my $user = $event->user; my $user = $event->{event}->user;
my $host = $event->host; my $host = $event->{event}->host;
my $text = $event->{args}[0]; my $text = $event->{event}->{args}[0];
$self->{pbot}->{interpreter}->process_line($from, $nick, $user, $host, $text); $self->{pbot}->{interpreter}->process_line($from, $nick, $user, $host, $text);
return 0;
} }
sub on_msg { sub on_msg {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $host) = ($event->nick, $event->host); my ($nick, $host) = ($event->{event}->nick, $event->{event}->host);
my $text = $event->{args}[0]; my $text = $event->{event}->{args}[0];
my $bot_trigger = $self->{pbot}->{registry}->get_value('general', 'trigger'); my $bot_trigger = $self->{pbot}->{registry}->get_value('general', 'trigger');
$text =~ s/^\Q$bot_trigger\E?(.*)/$bot_trigger$1/; $text =~ s/^\Q$bot_trigger\E?(.*)/$bot_trigger$1/;
$event->{to}[0] = $nick; $event->{event}->{to}[0] = $nick;
$event->{args}[0] = $text; $event->{event}->{args}[0] = $text;
$self->on_public($conn, $event); $self->on_public($event_type, $event);
return 0;
} }
sub on_notice { sub on_notice {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $host) = ($event->nick, $event->host); my ($nick, $host) = ($event->{event}->nick, $event->{event}->host);
my $text = $event->{args}[0]; my $text = $event->{event}->{args}[0];
$self->{pbot}->{logger}->log("Received NOTICE from $nick $host '$text'\n"); $self->{pbot}->{logger}->log("Received NOTICE from $nick $host '$text'\n");
if($nick eq "NickServ" && $text =~ m/This nickname is registered/) { if($nick eq 'NickServ' && $text =~ m/This nickname is registered/) {
$self->{pbot}->{logger}->log("Identifying with NickServ . . .\n"); $self->{pbot}->{logger}->log("Identifying with NickServ . . .\n");
$conn->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'identify_password')); $event->{conn}->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
} }
if($nick eq "NickServ" && $text =~ m/You are now identified/) { if($nick eq 'NickServ' && $text =~ m/You are now identified/) {
foreach my $chan (keys %{ $self->{pbot}->{channels}->{channels}->hash }) { foreach my $chan (keys %{ $self->{pbot}->{channels}->{channels}->hash }) {
if($self->{pbot}->{channels}->{channels}->hash->{$chan}{enabled}) { if($self->{pbot}->{channels}->{channels}->hash->{$chan}{enabled}) {
$self->{pbot}->{logger}->log("Joining channel: $chan\n"); $self->{pbot}->{logger}->log("Joining channel: $chan\n");
$conn->join($chan); $event->{conn}->join($chan);
} }
} }
$self->{pbot}->{joined_channels} = 1; $self->{pbot}->{joined_channels} = 1;
} }
return 0;
} }
sub on_action { sub on_action {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
$event->{args}[0] = "/me " . $event->{args}[0]; $event->{event}->{args}[0] = "/me " . $event->{event}->{args}[0];
$self->on_public($conn, $event); $self->on_public($event_type, $event);
return 0;
} }
sub on_mode { sub on_mode {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $user, $host) = ($event->nick, $event->user, $event->host); my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my $mode_string = $event->{args}[0]; my $mode_string = $event->{event}->{args}[0];
my $channel = $event->{to}[0]; my $channel = $event->{event}->{to}[0];
$channel = lc $channel; $channel = lc $channel;
my ($mode, $modifier); my ($mode, $modifier);
@ -150,7 +169,7 @@ sub on_mode {
} }
$mode = $modifier . $char; $mode = $modifier . $char;
$target = $event->{args}[++$i]; $target = $event->{event}->{args}[++$i];
$self->{pbot}->{logger}->log("Got mode: source: $nick!$user\@$host, mode: $mode, target: " . (defined $target ? $target : "(undef)") . ", channel: $channel\n"); $self->{pbot}->{logger}->log("Got mode: source: $nick!$user\@$host, mode: $mode, target: " . (defined $target ? $target : "(undef)") . ", channel: $channel\n");
@ -171,7 +190,7 @@ sub on_mode {
} }
elsif($mode eq "+b") { elsif($mode eq "+b") {
$self->{pbot}->{logger}->log("Got banned in $channel, attempting unban."); $self->{pbot}->{logger}->log("Got banned in $channel, attempting unban.");
$conn->privmsg("chanserv", "unban $channel"); $event->{conn}->privmsg("chanserv", "unban $channel");
} }
} }
else { # bot not targeted else { # bot not targeted
@ -187,19 +206,19 @@ sub on_mode {
foreach my $chan (keys %{ $self->{pbot}->{channels}->{channels}->hash }) { foreach my $chan (keys %{ $self->{pbot}->{channels}->{channels}->hash }) {
if($self->{channels}->{channels}->hash->{$chan}{enabled}) { if($self->{channels}->{channels}->hash->{$chan}{enabled}) {
$self->{pbot}->{logger}->log("Joining channel: $chan\n"); $self->{pbot}->{logger}->log("Joining channel: $chan\n");
$self->{pbot}->{conn}->join($chan); $event->{conn}->join($chan);
} }
} }
$self->{pbot}->{joined_channels} = 1; $self->{pbot}->{joined_channels} = 1;
} }
} }
} }
return 0;
} }
sub on_join { sub on_join {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $user, $host, $channel) = ($event->nick, $event->user, $event->host, $event->to); my ($nick, $user, $host, $channel) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to);
my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host); 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}->{messagehistory}->add_message($message_account, "$nick!$user\@$host", $channel, "JOIN", $self->{pbot}->{messagehistory}->{MSG_JOIN});
@ -207,11 +226,12 @@ sub on_join {
$self->{pbot}->{registry}->get_value('antiflood', 'join_flood_threshold'), $self->{pbot}->{registry}->get_value('antiflood', 'join_flood_threshold'),
$self->{pbot}->{registry}->get_value('antiflood', 'join_flood_time_threshold'), $self->{pbot}->{registry}->get_value('antiflood', 'join_flood_time_threshold'),
$self->{pbot}->{messagehistory}->{MSG_JOIN}); $self->{pbot}->{messagehistory}->{MSG_JOIN});
return 0;
} }
sub on_kick { sub on_kick {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $user, $host, $target, $channel, $reason) = ($event->nick, $event->user, $event->host, $event->to, $event->{args}[0], $event->{args}[1]); 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]);
$self->{pbot}->{logger}->log("$nick!$user\@$host kicked $target from $channel ($reason)\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host kicked $target from $channel ($reason)\n");
@ -237,13 +257,14 @@ sub on_kick {
my $text = "KICKED " . (defined $hostmask ? $hostmask : $target) . " from $channel ($reason)"; my $text = "KICKED " . (defined $hostmask ? $hostmask : $target) . " from $channel ($reason)";
$self->{pbot}->{messagehistory}->add_message($message_account, "$nick!$user\@$host", $channel, $text, $self->{pbot}->{messagehistory}->{MSG_CHAT}); $self->{pbot}->{messagehistory}->add_message($message_account, "$nick!$user\@$host", $channel, $text, $self->{pbot}->{messagehistory}->{MSG_CHAT});
} }
return 0;
} }
sub on_departure { sub on_departure {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $user, $host, $channel, $args) = ($event->nick, $event->user, $event->host, $event->to, $event->args); my ($nick, $user, $host, $channel, $args) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to, $event->{event}->args);
my $text = uc $event->type; my $text = uc $event->{event}->type;
$text .= " $args"; $text .= " $args";
my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host); my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host);
@ -270,31 +291,12 @@ sub on_departure {
$self->{pbot}->{logger}->log("Logged out $nick.\n"); $self->{pbot}->{logger}->log("Logged out $nick.\n");
delete $admin->{loggedin}; delete $admin->{loggedin};
} }
} return 0;
sub on_notregistered {
my ($self, $conn, $event) = @_;
my ($addr, $msg) = $event->args;
$self->{pbot}->{logger}->log("Received NOTREGISTERED from $addr: $msg\n");
$conn->privmsg("nickserv", "ghost " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$conn->privmsg("nickserv", "release " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$conn->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
}
sub on_bannickchange {
my ($self, $conn, $event) = @_;
my ($addr, $nick, $msg) = $event->args;
$self->{pbot}->{logger}->log("Received BANNICKCHANGE from $addr: $nick ($msg)\n");
$conn->privmsg("nickserv", "ghost " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$conn->privmsg("nickserv", "release " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$conn->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
} }
sub on_nickchange { sub on_nickchange {
my ($self, $conn, $event) = @_; my ($self, $event_type, $event) = @_;
my ($nick, $user, $host, $newnick) = ($event->nick, $event->user, $event->host, $event->args); my ($nick, $user, $host, $newnick) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->args);
$self->{pbot}->{logger}->log("$nick!$user\@$host changed nick to $newnick\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host changed nick to $newnick\n");
@ -314,6 +316,30 @@ sub on_nickchange {
$self->{pbot}->{registry}->get_value('antiflood', 'nick_flood_threshold'), $self->{pbot}->{registry}->get_value('antiflood', 'nick_flood_threshold'),
$self->{pbot}->{registry}->get_value('antiflood', 'nick_flood_time_threshold'), $self->{pbot}->{registry}->get_value('antiflood', 'nick_flood_time_threshold'),
$self->{pbot}->{messagehistory}->{MSG_NICKCHANGE}); $self->{pbot}->{messagehistory}->{MSG_NICKCHANGE});
return 0;
}
# todo: fix the following two subroutines so they work properly (e.g., change nick to randomly generated nick and await responses)
sub on_notregistered {
my ($self, $event_type, $event) = @_;
my ($addr, $msg) = $event->{event}->args;
$self->{pbot}->{logger}->log("Received NOTREGISTERED from $addr: $msg\n");
$event->{conn}->privmsg("nickserv", "ghost " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$event->{conn}->privmsg("nickserv", "release " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$event->{conn}->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
return 0;
}
sub on_bannickchange {
my ($self, $event_type, $event) = @_;
my ($addr, $nick, $msg) = $event->{event}->args;
$self->{pbot}->{logger}->log("Received BANNICKCHANGE from $addr: $nick ($msg)\n");
$event->{conn}->privmsg("nickserv", "ghost " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$event->{conn}->privmsg("nickserv", "release " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
$event->{conn}->privmsg("nickserv", "identify " . $self->{pbot}->{registry}->get_value('irc', 'botnick') . ' ' . $self->{pbot}->{registry}->get_value('irc', 'identify_password'));
return 0;
} }
1; 1;

View File

@ -148,6 +148,7 @@ sub check_ignore {
} }
} }
=cut
if(exists $self->{ignore_flood_counter}->{$channel} and $self->{ignore_flood_counter}->{$channel} > 5) { if(exists $self->{ignore_flood_counter}->{$channel} and $self->{ignore_flood_counter}->{$channel} > 5) {
$self->{commands}->ignore_user("", "floodcontrol", "", "", ".* $channel 300"); $self->{commands}->ignore_user("", "floodcontrol", "", "", ".* $channel 300");
$self->{ignore_flood_counter}->{$channel} = 0; $self->{ignore_flood_counter}->{$channel} = 0;
@ -157,6 +158,7 @@ sub check_ignore {
return 1; return 1;
} }
} }
=cut
} }
foreach my $ignored (keys %{ $self->{ignore_list} }) { foreach my $ignored (keys %{ $self->{ignore_list} }) {

View File

@ -33,6 +33,12 @@ sub initialize {
my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to LagChecker"); my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to LagChecker");
$self->{pbot} = $pbot; $self->{pbot} = $pbot;
$self->{lag_average} = undef; # average of entries in lag history, in seconds
$self->{lag_string} = undef; # string representation of lag history and lag average
$self->{lag_history} = []; # history of previous PING/PONG timings
$self->{pong_received} = undef; # tracks pong replies; undef if no ping sent; 0 if ping sent but no pong reply yet; 1 if ping/pong completed
$self->{ping_send_time} = undef; # when last ping was sent
# maximum number of lag history entries to retain # maximum number of lag history entries to retain
$pbot->{registry}->add_default('text', 'lagchecker', 'lag_history_max', $conf{lag_history_max} // 3); $pbot->{registry}->add_default('text', 'lagchecker', 'lag_history_max', $conf{lag_history_max} // 3);
# lagging is true if lag_average reaches or exceeds this threshold, in seconds # lagging is true if lag_average reaches or exceeds this threshold, in seconds
@ -42,12 +48,6 @@ sub initialize {
$pbot->{registry}->add_trigger('lagchecker', 'lag_history_interval', sub { $self->lag_history_interval_trigger(@_) }); $pbot->{registry}->add_trigger('lagchecker', 'lag_history_interval', sub { $self->lag_history_interval_trigger(@_) });
$self->{lag_average} = undef; # average of entries in lag history, in seconds
$self->{lag_string} = undef; # string representation of lag history and lag average
$self->{lag_history} = []; # history of previous PING/PONG timings
$self->{pong_received} = undef; # tracks pong replies; undef if no ping sent; 0 if ping sent but no pong reply yet; 1 if ping/pong completed
$self->{ping_send_time} = undef; # when last ping was sent
$pbot->{timer}->register( $pbot->{timer}->register(
sub { $self->send_ping }, sub { $self->send_ping },
$pbot->{registry}->get_value('lagchecker', 'lag_history_interval'), $pbot->{registry}->get_value('lagchecker', 'lag_history_interval'),
@ -55,6 +55,8 @@ sub initialize {
); );
$pbot->{commands}->register(sub { return $self->lagcheck(@_) }, "lagcheck", 0); $pbot->{commands}->register(sub { return $self->lagcheck(@_) }, "lagcheck", 0);
$self->{pbot}->{event_dispatcher}->register_handler('irc.pong', sub { $self->on_pong(@_) });
} }
sub lag_history_interval_trigger { sub lag_history_interval_trigger {
@ -104,6 +106,7 @@ sub on_pong {
$self->{lag_average} = $lag_total / $len; $self->{lag_average} = $lag_total / $len;
$self->{lag_string} .= "; average: $self->{lag_average}"; $self->{lag_string} .= "; average: $self->{lag_average}";
return 0;
} }
sub lagging { sub lagging {

View File

@ -30,6 +30,7 @@ use PBot::Registry;
use PBot::SelectHandler; use PBot::SelectHandler;
use PBot::StdinReader; use PBot::StdinReader;
use PBot::IRC; use PBot::IRC;
use PBot::EventDispatcher;
use PBot::IRCHandlers; use PBot::IRCHandlers;
use PBot::Channels; use PBot::Channels;
use PBot::BanTracker; use PBot::BanTracker;
@ -98,20 +99,21 @@ sub initialize {
$self->{registry}->add_trigger('irc', 'botnick', sub { $self->change_botnick_trigger(@_) }); $self->{registry}->add_trigger('irc', 'botnick', sub { $self->change_botnick_trigger(@_) });
$self->{registry}->add_trigger('irc', 'debug', sub { $self->irc_debug_trigger(@_) }); $self->{registry}->add_trigger('irc', 'debug', sub { $self->irc_debug_trigger(@_) });
$self->{select_handler} = PBot::SelectHandler->new(pbot => $self, %conf); $self->{event_dispatcher} = PBot::EventDispatcher->new(pbot => $self, %conf);
$self->{stdin_reader} = PBot::StdinReader->new(pbot => $self, %conf); $self->{select_handler} = PBot::SelectHandler->new(pbot => $self, %conf);
$self->{admins} = PBot::BotAdmins->new(pbot => $self, filename => delete $conf{admins_file}, %conf); $self->{stdin_reader} = PBot::StdinReader->new(pbot => $self, %conf);
$self->{bantracker} = PBot::BanTracker->new(pbot => $self, %conf); $self->{admins} = PBot::BotAdmins->new(pbot => $self, filename => delete $conf{admins_file}, %conf);
$self->{lagchecker} = PBot::LagChecker->new(pbot => $self, %conf); $self->{bantracker} = PBot::BanTracker->new(pbot => $self, %conf);
$self->{messagehistory} = PBot::MessageHistory->new(pbot => $self, filename => delete $conf{messagehistory_file}, %conf); $self->{lagchecker} = PBot::LagChecker->new(pbot => $self, %conf);
$self->{antiflood} = PBot::AntiFlood->new(pbot => $self, %conf); $self->{messagehistory} = PBot::MessageHistory->new(pbot => $self, filename => delete $conf{messagehistory_file}, %conf);
$self->{ignorelist} = PBot::IgnoreList->new(pbot => $self, filename => delete $conf{ignorelist_file}, %conf); $self->{antiflood} = PBot::AntiFlood->new(pbot => $self, %conf);
$self->{irc} = PBot::IRC->new(); $self->{ignorelist} = PBot::IgnoreList->new(pbot => $self, filename => delete $conf{ignorelist_file}, %conf);
$self->{irchandlers} = PBot::IRCHandlers->new(pbot => $self, %conf); $self->{irc} = PBot::IRC->new();
$self->{channels} = PBot::Channels->new(pbot => $self, filename => delete $conf{channels_file}, %conf); $self->{irchandlers} = PBot::IRCHandlers->new(pbot => $self, %conf);
$self->{chanops} = PBot::ChanOps->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->{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->{commands}->interpreter(@_); });
$self->{interpreter}->register(sub { return $self->{factoids}->interpreter(@_); }); $self->{interpreter}->register(sub { return $self->{factoids}->interpreter(@_); });
@ -156,43 +158,24 @@ sub connect {
$self->{logger}->log("Connecting to $server ...\n"); $self->{logger}->log("Connecting to $server ...\n");
$self->{conn} = $self->{irc}->newconn( while (not $self->{conn} = $self->{irc}->newconn(
Nick => $self->{registry}->get_value('irc', 'botnick'), Nick => $self->{registry}->get_value('irc', 'botnick'),
Username => $self->{registry}->get_value('irc', 'username'), Username => $self->{registry}->get_value('irc', 'username'),
Ircname => $self->{registry}->get_value('irc', 'ircname'), Ircname => $self->{registry}->get_value('irc', 'ircname'),
Server => $server, Server => $server,
SSL => $self->{registry}->get_value('irc', 'SSL'), SSL => $self->{registry}->get_value('irc', 'SSL'),
SSL_ca_file => $self->{registry}->get_value('irc', 'SSL_ca_file'), SSL_ca_file => $self->{registry}->get_value('irc', 'SSL_ca_file'),
SSL_ca_path => $self->{registry}->get_value('irc', 'SSL_ca_path'), SSL_ca_path => $self->{registry}->get_value('irc', 'SSL_ca_path'),
Port => $self->{registry}->get_value('irc', 'port')) Port => $self->{registry}->get_value('irc', 'port'))) {
or Carp::croak "$0: Can't connect to IRC server.\n"; $self->{logger}->log("$0: Can't connect to IRC server. Retrying in 15 seconds...\n");
sleep 15;
}
$self->{connected} = 1; $self->{connected} = 1;
#set up handlers for the IRC engine #set up handlers for the IRC engine
$self->{conn}->add_default_handler(sub { $self->{irchandlers}->default_handler(@_) }, 1); $self->{conn}->add_default_handler(sub { $self->{irchandlers}->default_handler(@_) }, 1);
$self->{conn}->add_handler([ 251,252,253,254,255,302 ], sub { $self->{irchandlers}->on_init(@_) });
$self->{conn}->add_handler([ 251,252,253,254,302,255 ], sub { $self->{irchandlers}->on_init(@_) });
$self->{conn}->add_handler(376 , sub { $self->{irchandlers}->on_connect(@_) });
$self->{conn}->add_handler('disconnect' , sub { $self->{irchandlers}->on_disconnect(@_) });
$self->{conn}->add_handler('motd' , sub { $self->{irchandlers}->on_motd(@_) });
$self->{conn}->add_handler('notice' , sub { $self->{irchandlers}->on_notice(@_) });
$self->{conn}->add_handler('caction' , sub { $self->{irchandlers}->on_action(@_) });
$self->{conn}->add_handler('public' , sub { $self->{irchandlers}->on_public(@_) });
$self->{conn}->add_handler('msg' , sub { $self->{irchandlers}->on_msg(@_) });
$self->{conn}->add_handler('mode' , sub { $self->{irchandlers}->on_mode(@_) });
$self->{conn}->add_handler('part' , sub { $self->{irchandlers}->on_departure(@_) });
$self->{conn}->add_handler('join' , sub { $self->{irchandlers}->on_join(@_) });
$self->{conn}->add_handler('kick' , sub { $self->{irchandlers}->on_kick(@_) });
$self->{conn}->add_handler('quit' , sub { $self->{irchandlers}->on_departure(@_) });
$self->{conn}->add_handler('nick' , sub { $self->{irchandlers}->on_nickchange(@_) });
$self->{conn}->add_handler('pong' , sub { $self->{lagchecker}->on_pong(@_) });
$self->{conn}->add_handler('whoisaccount' , sub { $self->{antiflood}->on_whoisaccount(@_) });
$self->{conn}->add_handler('banlist' , sub { $self->{bantracker}->on_banlist_entry(@_) });
$self->{conn}->add_handler('endofnames' , sub { $self->{bantracker}->get_banlist(@_) });
$self->{conn}->add_handler(728 , sub { $self->{bantracker}->on_quietlist_entry(@_) });
$self->{conn}->add_handler('bannickchange' , sub { $self->{irchandlers}->on_bannickchange(@_) });
$self->{conn}->add_handler('notregistered' , sub { $self->{irchandlers}->on_notregistered(@_) });
# ignore these events # ignore these events
$self->{conn}->add_handler(['whoisuser', $self->{conn}->add_handler(['whoisuser',
@ -202,6 +185,7 @@ sub connect {
'whoisidle', 'whoisidle',
'endofwhois', 'endofwhois',
'motdstart', 'motdstart',
'endofmotd',
'away', 'away',
'endofbanlist'], sub {}); 'endofbanlist'], sub {});
} }
@ -215,8 +199,10 @@ sub do_one_loop {
sub start { sub start {
my $self = shift; my $self = shift;
$self->connect() if not $self->{connected}; while(1) {
while(1) { $self->do_one_loop(); } $self->connect() if not $self->{connected};
$self->do_one_loop() if $self->{connected};
}
} }
sub register_signal_handlers { sub register_signal_handlers {

View File

@ -13,7 +13,7 @@ use warnings;
# These are set automatically by the build/commit script # These are set automatically by the build/commit script
use constant { use constant {
BUILD_NAME => "PBot", BUILD_NAME => "PBot",
BUILD_REVISION => 798, BUILD_REVISION => 799,
BUILD_DATE => "2014-10-31", BUILD_DATE => "2014-10-31",
}; };