3
0
mirror of https://github.com/pragma-/pbot.git synced 2025-02-08 18:44:17 +01:00

NickList now tracks user modes as metadata

This commit is contained in:
Pragmatic Software 2018-08-03 12:31:45 -07:00
parent f18426be16
commit 772ea03ddf
2 changed files with 110 additions and 28 deletions

View File

@ -18,7 +18,7 @@ use Data::Dumper;
$Data::Dumper::Sortkeys = 1; $Data::Dumper::Sortkeys = 1;
sub new { sub new {
if(ref($_[1]) eq 'HASH') { if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference"); Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
} }
@ -64,7 +64,7 @@ sub initialize {
sub default_handler { sub default_handler {
my ($self, $conn, $event) = @_; my ($self, $conn, $event) = @_;
if(not defined $self->{pbot}->{event_dispatcher}->dispatch_event("irc.$event->{type}", { conn => $conn, event => $event })) { if (not defined $self->{pbot}->{event_dispatcher}->dispatch_event("irc.$event->{type}", { conn => $conn, event => $event })) {
if ($self->{pbot}->{registry}->get_value('irc', 'log_default_handler')) { if ($self->{pbot}->{registry}->get_value('irc', 'log_default_handler')) {
$self->{pbot}->{logger}->log(Dumper $event); $self->{pbot}->{logger}->log(Dumper $event);
} }
@ -160,13 +160,13 @@ sub on_notice {
return 0 if not length $host; return 0 if not length $host;
if($nick eq 'NickServ') { if ($nick eq 'NickServ') {
if($text =~ m/This nickname is registered/) { if ($text =~ m/This nickname is registered/) {
$self->{pbot}->{logger}->log("Identifying with NickServ . . .\n"); $self->{pbot}->{logger}->log("Identifying with NickServ . . .\n");
$event->{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'));
} elsif($text =~ m/You are now identified/) { } elsif ($text =~ m/You are now identified/) {
$event->{conn}->nick($self->{pbot}->{registry}->get_value('irc', 'botnick')); $event->{conn}->nick($self->{pbot}->{registry}->get_value('irc', 'botnick'));
} elsif($text =~ m/has been ghosted/) { } elsif ($text =~ m/has been ghosted/) {
$event->{conn}->nick($self->{pbot}->{registry}->get_value('irc', 'botnick')); $event->{conn}->nick($self->{pbot}->{registry}->get_value('irc', 'botnick'));
} }
} else { } else {
@ -196,47 +196,56 @@ sub on_mode {
($nick, $user, $host) = $self->normalize_hostmask($nick, $user, $host); ($nick, $user, $host) = $self->normalize_hostmask($nick, $user, $host);
my ($mode, $modifier); my ($mode, $mode_char, $modifier);
my $i = 0; my $i = 0;
my $target; my $target;
while($mode_string =~ m/(.)/g) { while($mode_string =~ m/(.)/g) {
my $char = $1; my $char = $1;
if($char eq '-' or $char eq '+') { if ($char eq '-' or $char eq '+') {
$modifier = $char; $modifier = $char;
next; next;
} }
$mode = $modifier . $char; $mode = $modifier . $char;
$mode_char = $char;
$target = $event->{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");
if($mode eq "-b" or $mode eq "+b" or $mode eq "-q" or $mode eq "+q") { if ($mode eq "-b" or $mode eq "+b" or $mode eq "-q" or $mode eq "+q") {
$self->{pbot}->{bantracker}->track_mode("$nick!$user\@$host", $mode, $target, $channel); $self->{pbot}->{bantracker}->track_mode("$nick!$user\@$host", $mode, $target, $channel);
} }
if(defined $target && $target eq $event->{conn}->nick) { # bot targeted if (defined $target) {
if($mode eq "+o") { if ($modifier eq '-') {
$self->{pbot}->{nicklist}->delete_meta($channel, $target, "+$mode_char");
} else {
$self->{pbot}->{nicklist}->set_meta($channel, $target, $mode, 1);
}
}
if (defined $target && $target eq $event->{conn}->nick) { # bot targeted
if ($mode eq "+o") {
$self->{pbot}->{logger}->log("$nick opped me in $channel\n"); $self->{pbot}->{logger}->log("$nick opped me in $channel\n");
my $timeout = $self->{pbot}->{registry}->get_value($channel, 'deop_timeout') // $self->{pbot}->{registry}->get_value('general', 'deop_timeout'); my $timeout = $self->{pbot}->{registry}->get_value($channel, 'deop_timeout') // $self->{pbot}->{registry}->get_value('general', 'deop_timeout');
$self->{pbot}->{chanops}->{is_opped}->{$channel}{timeout} = gettimeofday + $timeout; $self->{pbot}->{chanops}->{is_opped}->{$channel}{timeout} = gettimeofday + $timeout;
delete $self->{pbot}->{chanops}->{op_requested}->{$channel}; delete $self->{pbot}->{chanops}->{op_requested}->{$channel};
$self->{pbot}->{chanops}->perform_op_commands($channel); $self->{pbot}->{chanops}->perform_op_commands($channel);
} }
elsif($mode eq "-o") { elsif ($mode eq "-o") {
$self->{pbot}->{logger}->log("$nick removed my ops in $channel\n"); $self->{pbot}->{logger}->log("$nick removed my ops in $channel\n");
delete $self->{pbot}->{chanops}->{is_opped}->{$channel}; delete $self->{pbot}->{chanops}->{is_opped}->{$channel};
} }
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.");
$event->{conn}->privmsg("chanserv", "unban $channel"); $event->{conn}->privmsg("chanserv", "unban $channel");
} }
} }
else { # bot not targeted else { # bot not targeted
if($mode eq "+b") { if ($mode eq "+b") {
if($nick eq "ChanServ" or $target =~ m/##fix_your_connection$/i) { if ($nick eq "ChanServ" or $target =~ m/##fix_your_connection$/i) {
if ($self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($self->{pbot}->{chanops}->can_gain_ops($channel)) {
$self->{pbot}->{chanops}->{unban_timeout}->hash->{$channel}->{$target}{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout'); $self->{pbot}->{chanops}->{unban_timeout}->hash->{$channel}->{$target}{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout');
$self->{pbot}->{chanops}->{unban_timeout}->save; $self->{pbot}->{chanops}->{unban_timeout}->save;
@ -257,8 +266,8 @@ sub on_mode {
} }
} }
} }
elsif($mode eq "+q") { elsif ($mode eq "+q") {
if($nick ne $event->{conn}->nick) { if ($nick ne $event->{conn}->nick) { # bot muted
if ($self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($self->{pbot}->{chanops}->can_gain_ops($channel)) {
$self->{pbot}->{chanops}->{unmute_timeout}->hash->{$channel}->{$target}{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'mute_timeout'); $self->{pbot}->{chanops}->{unmute_timeout}->hash->{$channel}->{$target}{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'mute_timeout');
$self->{pbot}->{chanops}->{unmute_timeout}->save; $self->{pbot}->{chanops}->{unmute_timeout}->save;
@ -338,7 +347,7 @@ sub on_kick {
my ($message_account) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($target); my ($message_account) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($target);
my $hostmask; my $hostmask;
if(defined $message_account) { if (defined $message_account) {
$hostmask = $self->{pbot}->{messagehistory}->{database}->find_most_recent_hostmask($message_account); $hostmask = $self->{pbot}->{messagehistory}->{database}->find_most_recent_hostmask($message_account);
my ($target_nick, $target_user, $target_host) = $hostmask =~ m/^([^!]+)!([^@]+)@(.*)/; my ($target_nick, $target_user, $target_host) = $hostmask =~ m/^([^!]+)!([^@]+)@(.*)/;
@ -353,7 +362,7 @@ sub on_kick {
$message_account = $self->{pbot}->{messagehistory}->{database}->get_message_account_id("$nick!$user\@$host"); $message_account = $self->{pbot}->{messagehistory}->{database}->get_message_account_id("$nick!$user\@$host");
if(defined $message_account) { if (defined $message_account) {
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});
} }
@ -372,7 +381,7 @@ sub on_departure {
my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host); my $message_account = $self->{pbot}->{messagehistory}->get_message_account($nick, $user, $host);
if($text =~ m/^QUIT/) { if ($text =~ m/^QUIT/) {
# QUIT messages must be dispatched to each channel the user is on # QUIT messages must be dispatched to each channel the user is on
my $channels = $self->{pbot}->{nicklist}->get_channels($nick); my $channels = $self->{pbot}->{nicklist}->get_channels($nick);
foreach my $chan (@$channels) { foreach my $chan (@$channels) {
@ -389,7 +398,7 @@ sub on_departure {
$self->{pbot}->{messagehistory}->{MSG_DEPARTURE}); $self->{pbot}->{messagehistory}->{MSG_DEPARTURE});
my $admin = $self->{pbot}->{admins}->find_admin($channel, "$nick!$user\@$host"); my $admin = $self->{pbot}->{admins}->find_admin($channel, "$nick!$user\@$host");
if(defined $admin and $admin->{loggedin} and not $admin->{stayloggedin}) { if (defined $admin and $admin->{loggedin} and not $admin->{stayloggedin}) {
$self->{pbot}->{logger}->log("Whoops, $nick left while still logged in.\n"); $self->{pbot}->{logger}->log("Whoops, $nick left while still logged in.\n");
$self->{pbot}->{logger}->log("Logged out $nick.\n"); $self->{pbot}->{logger}->log("Logged out $nick.\n");
delete $admin->{loggedin}; delete $admin->{loggedin};
@ -439,7 +448,7 @@ sub on_nickchange {
if ($newnick eq $self->{pbot}->{registry}->get_value('irc', 'botnick') and not $self->{pbot}->{joined_channels}) { if ($newnick eq $self->{pbot}->{registry}->get_value('irc', 'botnick') and not $self->{pbot}->{joined_channels}) {
my $chans; my $chans;
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}) {
$chans .= "$chan,"; $chans .= "$chan,";
} }
} }

View File

@ -54,7 +54,20 @@ sub initialize {
sub dumpnicks { sub dumpnicks {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $nicklist = Dumper($self->{nicklist}); my $nicklist;
if (not length $arguments) {
$nicklist = Dumper($self->{nicklist});
} else {
my @args = split / /, $arguments;
if (@args == 1) {
$nicklist = Dumper($self->{nicklist}->{$arguments});
} else {
$nicklist = Dumper($self->{nicklist}->{$args[0]}->{$args[1]});
}
}
return $nicklist; return $nicklist;
} }
@ -104,6 +117,51 @@ sub get_channels {
return \@channels; return \@channels;
} }
sub set_meta {
my ($self, $channel, $nick, $key, $value) = @_;
$channel = lc $channel;
$nick = lc $nick;
if (not exists $self->{nicklist}->{$channel} or not exists $self->{nicklist}->{$channel}->{$nick}) {
$self->{pbot}->{logger}->log("Nicklist: Attempt to set invalid meta ($key => $value) for $nick in $channel.\n");
return 0;
}
$self->{nicklist}->{$channel}->{$nick}->{$key} = $value;
return 1;
}
sub delete_meta {
my ($self, $channel, $nick, $key) = @_;
$channel = lc $channel;
$nick = lc $nick;
if (not exists $self->{nicklist}->{$channel}
or not exists $self->{nicklist}->{$channel}->{$nick}
or not exists $self->{nicklist}->{$channel}->{$nick}->{$key}) {
return undef;
}
return delete $self->{nicklist}->{$channel}->{$nick}->{$key};
}
sub get_meta {
my ($self, $channel, $nick, $key) = @_;
$channel = lc $channel;
$nick = lc $nick;
if (not exists $self->{nicklist}->{$channel}
or not exists $self->{nicklist}->{$channel}->{$nick}
or not exists $self->{nicklist}->{$channel}->{$nick}->{$key}) {
return undef;
}
return $self->{nicklist}->{$channel}->{$nick}->{$key};
}
sub is_present_any_channel { sub is_present_any_channel {
my ($self, $nick) = @_; my ($self, $nick) = @_;
@ -189,10 +247,23 @@ sub random_nick {
sub on_namreply { sub on_namreply {
my ($self, $event_type, $event) = @_; my ($self, $event_type, $event) = @_;
my ($channel, $nicks) = ($event->{event}->{args}[2], $event->{event}->{args}[3]); my ($channel, $nicks) = ($event->{event}->{args}[2], $event->{event}->{args}[3]);
foreach my $nick (split ' ', $nicks) { foreach my $nick (split ' ', $nicks) {
$nick =~ s/^[@+%]//; # remove OP/Voice/etc indicator from nick my $stripped_nick = $nick;
$self->add_nick($channel, $nick); $stripped_nick =~ s/^[@+%]//g; # remove OP/Voice/etc indicator from nick
$self->add_nick($channel, $stripped_nick);
if ($nick =~ m/\@/) {
$self->set_meta($channel, $stripped_nick, '+o', 1);
}
if ($nick =~ m/\+/) {
$self->set_meta($channel, $stripped_nick, '+v', 1);
}
if ($nick =~ m/\%/) {
$self->set_meta($channel, $stripped_nick, '+h', 1);
}
} }
return 0; return 0;
@ -245,8 +316,10 @@ sub on_nickchange {
foreach my $channel (keys %{ $self->{nicklist} }) { foreach my $channel (keys %{ $self->{nicklist} }) {
if ($self->is_present($channel, $nick)) { if ($self->is_present($channel, $nick)) {
$self->remove_nick($channel, $nick); my $meta = delete $self->{nicklist}->{$channel}->{lc $nick};
$self->add_nick($channel, $newnick); $meta->{nick} = $newnick;
$meta->{timestamp} = gettimeofday;
$self->{nicklist}->{$channel}->{lc $newnick} = $meta;
} }
} }