mirror of
				https://github.com/pragma-/pbot.git
				synced 2025-11-04 00:27:23 +01:00 
			
		
		
		
	Support IRCv3 message tags; misc refactoring
PBot now finally supports IRCv3 message tags. The `account-tag` capability is now enabled for improved NickServ account tracking. Refactored CAP negotiation. Minor clean-ups in AntiFlood.pm (which ought to be completely rewritten from the ground-up). Misc clean-ups and refactoring of various things.
This commit is contained in:
		
							parent
							
								
									19d8170af3
								
							
						
					
					
						commit
						999c07f237
					
				@ -25,8 +25,10 @@ sub initialize {
 | 
			
		||||
    my ($self, %conf) = @_;
 | 
			
		||||
 | 
			
		||||
    # flags for 'validated' field
 | 
			
		||||
    $self->{NICKSERV_VALIDATED} = (1 << 0);
 | 
			
		||||
    $self->{NEEDS_CHECKBAN}     = (1 << 1);
 | 
			
		||||
    use constant {
 | 
			
		||||
        NICKSERV_VALIDATED => (1 << 0),
 | 
			
		||||
        NEEDS_CHECKBAN     => (1 << 1),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    $self->{channels}      = {};    # per-channel statistics, e.g. for optimized tracking of last spoken nick for enter-abuse detection, etc
 | 
			
		||||
    $self->{nickflood}     = {};    # statistics to track nickchange flooding
 | 
			
		||||
@ -188,6 +190,29 @@ sub check_flood {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $needs_checkban = 0;
 | 
			
		||||
 | 
			
		||||
    if (defined $context && defined $context->{tags}) {
 | 
			
		||||
        my $tags = $self->{pbot}->{irc}->get_tags($context->{tags});
 | 
			
		||||
 | 
			
		||||
        if (defined $tags->{account}) {
 | 
			
		||||
            my $nickserv_account = $tags->{account};
 | 
			
		||||
            my $current_nickserv_account = $self->{pbot}->{messagehistory}->{database}->get_current_nickserv_account($account);
 | 
			
		||||
 | 
			
		||||
            if ($self->{pbot}->{registry}->get_value('irc', 'debug_tags')) {
 | 
			
		||||
                $self->{pbot}->{logger}->log("($account) $mask got account-tag $nickserv_account\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($current_nickserv_account ne $nickserv_account) {
 | 
			
		||||
                $self->{pbot}->{logger}->log("[MH] ($account) $mask updating NickServ to $nickserv_account\n");
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->set_current_nickserv_account($account, $nickserv_account);
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->update_nickserv_account($account, $nickserv_account, scalar gettimeofday);
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->link_aliases($account, $mask, $nickserv_account);
 | 
			
		||||
                $needs_checkban = 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    my $channels;
 | 
			
		||||
    if ($mode == MSG_NICKCHANGE) {
 | 
			
		||||
        $channels = $self->{pbot}->{nicklist}->get_channels($oldnick);
 | 
			
		||||
@ -205,14 +230,16 @@ sub check_flood {
 | 
			
		||||
        if ($chan =~ /^#/ and $mode == MSG_DEPARTURE) {
 | 
			
		||||
            # remove validation on PART or KICK so we check for ban-evasion when user returns at a later time
 | 
			
		||||
            my $chan_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($account, $chan, 'validated');
 | 
			
		||||
            if ($chan_data->{validated} & $self->{NICKSERV_VALIDATED}) {
 | 
			
		||||
                $chan_data->{validated} &= ~$self->{NICKSERV_VALIDATED};
 | 
			
		||||
            if ($chan_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
                $chan_data->{validated} &= ~NICKSERV_VALIDATED;
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->update_channel_data($account, $chan, $chan_data);
 | 
			
		||||
            }
 | 
			
		||||
            next;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted')) { next; }
 | 
			
		||||
        next if $self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted');
 | 
			
		||||
 | 
			
		||||
        $self->check_bans($account, $mask, $chan) if $needs_checkban;
 | 
			
		||||
 | 
			
		||||
        if ($max_messages > $self->{pbot}->{registry}->get_value('messagehistory', 'max_messages')) {
 | 
			
		||||
            $self->{pbot}->{logger}->log("Warning: max_messages greater than max_messages limit; truncating.\n");
 | 
			
		||||
@ -223,7 +250,7 @@ sub check_flood {
 | 
			
		||||
        if ($chan =~ m/^#/) {
 | 
			
		||||
            my $validated = $self->{pbot}->{messagehistory}->{database}->get_channel_data($account, $chan, 'validated')->{'validated'};
 | 
			
		||||
 | 
			
		||||
            if ($validated & $self->{NEEDS_CHECKBAN} or not $validated & $self->{NICKSERV_VALIDATED}) {
 | 
			
		||||
            if ($validated & NEEDS_CHECKBAN or not $validated & NICKSERV_VALIDATED) {
 | 
			
		||||
                if ($mode == MSG_DEPARTURE) {
 | 
			
		||||
                    # don't check for evasion on PART/KICK
 | 
			
		||||
                } elsif ($mode == MSG_NICKCHANGE) {
 | 
			
		||||
@ -575,8 +602,8 @@ sub devalidate_accounts {
 | 
			
		||||
 | 
			
		||||
    foreach my $account (@message_accounts) {
 | 
			
		||||
        my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($account, $channel, 'validated');
 | 
			
		||||
        if (defined $channel_data and $channel_data->{validated} & $self->{NICKSERV_VALIDATED}) {
 | 
			
		||||
            $channel_data->{validated} &= ~$self->{NICKSERV_VALIDATED};
 | 
			
		||||
        if (defined $channel_data and $channel_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
            $channel_data->{validated} &= ~NICKSERV_VALIDATED;
 | 
			
		||||
 | 
			
		||||
            #$self->{pbot}->{logger}->log("Devalidating account $account\n");
 | 
			
		||||
            $self->{pbot}->{messagehistory}->{database}->update_channel_data($account, $channel, $channel_data);
 | 
			
		||||
@ -605,16 +632,16 @@ sub check_bans {
 | 
			
		||||
    if (defined $current_nickserv_account and length $current_nickserv_account) {
 | 
			
		||||
        $self->{pbot}->{logger}->log("anti-flood: [check-bans] current nickserv [$current_nickserv_account] found for $mask\n") if $debug_checkban >= 2;
 | 
			
		||||
        my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'validated');
 | 
			
		||||
        if ($channel_data->{validated} & $self->{NEEDS_CHECKBAN}) {
 | 
			
		||||
            $channel_data->{validated} &= ~$self->{NEEDS_CHECKBAN};
 | 
			
		||||
        if ($channel_data->{validated} & NEEDS_CHECKBAN) {
 | 
			
		||||
            $channel_data->{validated} &= ~NEEDS_CHECKBAN;
 | 
			
		||||
            $self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (not exists $self->{pbot}->{irc_capabilities}->{'account-notify'}) {
 | 
			
		||||
            # mark this account as needing check-bans when nickserv account is identified
 | 
			
		||||
            my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'validated');
 | 
			
		||||
            if (not $channel_data->{validated} & $self->{NEEDS_CHECKBAN}) {
 | 
			
		||||
                $channel_data->{validated} |= $self->{NEEDS_CHECKBAN};
 | 
			
		||||
            if (not $channel_data->{validated} & NEEDS_CHECKBAN) {
 | 
			
		||||
                $channel_data->{validated} |= NEEDS_CHECKBAN;
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
 | 
			
		||||
            }
 | 
			
		||||
            $self->{pbot}->{logger}->log("anti-flood: [check-bans] no account for $mask; marking for later validation\n") if $debug_checkban >= 1;
 | 
			
		||||
@ -685,8 +712,8 @@ sub check_bans {
 | 
			
		||||
                        $self->{pbot}->{logger}
 | 
			
		||||
                          ->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};
 | 
			
		||||
                        if ($channel_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
                            $channel_data->{validated} &= ~NICKSERV_VALIDATED;
 | 
			
		||||
                            $self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
 | 
			
		||||
                        }
 | 
			
		||||
                        $do_not_validate = 1;
 | 
			
		||||
@ -792,8 +819,8 @@ sub check_bans {
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            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};
 | 
			
		||||
            if ($channel_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
                $channel_data->{validated} &= ~NICKSERV_VALIDATED;
 | 
			
		||||
                $self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
@ -802,8 +829,8 @@ sub check_bans {
 | 
			
		||||
 | 
			
		||||
    unless ($do_not_validate) {
 | 
			
		||||
        my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'validated');
 | 
			
		||||
        if (not $channel_data->{validated} & $self->{NICKSERV_VALIDATED}) {
 | 
			
		||||
            $channel_data->{validated} |= $self->{NICKSERV_VALIDATED};
 | 
			
		||||
        if (not $channel_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
            $channel_data->{validated} |= NICKSERV_VALIDATED;
 | 
			
		||||
            $self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -825,7 +852,7 @@ sub on_endofwhois {
 | 
			
		||||
    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}) {
 | 
			
		||||
        if ($channel_data->{validated} & NEEDS_CHECKBAN or not $channel_data->{validated} & NICKSERV_VALIDATED) {
 | 
			
		||||
            $self->check_bans($id, $hostmask, $channel);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -870,7 +897,7 @@ sub on_accountnotify {
 | 
			
		||||
 | 
			
		||||
    my $mask = $event->{event}->{from};
 | 
			
		||||
    my ($nick, $user, $host) = $mask =~ m/^([^!]+)!([^@]+)@(.*)/;
 | 
			
		||||
    my $account = $event->{event}->{args}[0];
 | 
			
		||||
    my $account = $event->{event}{args}[0];
 | 
			
		||||
    my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
 | 
			
		||||
 | 
			
		||||
    $self->{pbot}->{messagehistory}->{database}->update_hostmask_data($mask, {last_seen => scalar gettimeofday});
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,8 @@ package PBot::Core::Handlers::Cap;
 | 
			
		||||
use PBot::Imports;
 | 
			
		||||
use parent 'PBot::Core::Class';
 | 
			
		||||
 | 
			
		||||
use POSIX qw/EXIT_FAILURE/;
 | 
			
		||||
 | 
			
		||||
sub initialize {
 | 
			
		||||
    my ($self, %conf) = @_;
 | 
			
		||||
 | 
			
		||||
@ -22,28 +24,16 @@ sub initialize {
 | 
			
		||||
sub on_cap {
 | 
			
		||||
    my ($self, $event_type, $event) = @_;
 | 
			
		||||
 | 
			
		||||
    # configure client capabilities that PBot currently supports
 | 
			
		||||
    my %desired_caps = (
 | 
			
		||||
        'account-notify' => 1,
 | 
			
		||||
        'extended-join'  => 1,
 | 
			
		||||
 | 
			
		||||
        # TODO: unsupported capabilities worth looking into
 | 
			
		||||
        'away-notify'    => 0,
 | 
			
		||||
        'chghost'        => 0,
 | 
			
		||||
        'identify-msg'   => 0,
 | 
			
		||||
        'multi-prefix'   => 0,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if ($event->{event}->{args}->[0] eq 'LS') {
 | 
			
		||||
        my $capabilities;
 | 
			
		||||
        my $caps_done = 0;
 | 
			
		||||
        my $caps_listed = 0;
 | 
			
		||||
 | 
			
		||||
        if ($event->{event}->{args}->[1] eq '*') {
 | 
			
		||||
            # more CAP LS messages coming
 | 
			
		||||
            $capabilities = $event->{event}->{args}->[2];
 | 
			
		||||
        } else {
 | 
			
		||||
            # final CAP LS message
 | 
			
		||||
            $caps_done    = 1;
 | 
			
		||||
            $caps_listed    = 1;
 | 
			
		||||
            $capabilities = $event->{event}->{args}->[1];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -51,36 +41,20 @@ sub on_cap {
 | 
			
		||||
 | 
			
		||||
        my @caps = split /\s+/, $capabilities;
 | 
			
		||||
 | 
			
		||||
        # store available capabilities
 | 
			
		||||
        foreach my $cap (@caps) {
 | 
			
		||||
            my $value;
 | 
			
		||||
 | 
			
		||||
            if ($cap =~ /=/) {
 | 
			
		||||
                ($cap, $value) = split /=/, $cap;
 | 
			
		||||
            } else {
 | 
			
		||||
                $value = 1;
 | 
			
		||||
            }
 | 
			
		||||
            ($cap, $value) = split /=/, $cap;
 | 
			
		||||
            $value //= 1;
 | 
			
		||||
 | 
			
		||||
            # store available capability
 | 
			
		||||
            $self->{pbot}->{irc_capabilities_available}->{$cap} = $value;
 | 
			
		||||
 | 
			
		||||
            # request desired capabilities
 | 
			
		||||
            if ($desired_caps{$cap}) {
 | 
			
		||||
                $self->{pbot}->{logger}->log("Requesting client capability $cap\n");
 | 
			
		||||
                $event->{conn}->sl("CAP REQ :$cap");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # capability negotiation done
 | 
			
		||||
        # now we either start SASL authentication or we send CAP END
 | 
			
		||||
        if ($caps_done) {
 | 
			
		||||
            # start SASL authentication if enabled
 | 
			
		||||
            if ($self->{pbot}->{registry}->get_value('irc', 'sasl')) {
 | 
			
		||||
                $self->{pbot}->{logger}->log("Requesting client capability sasl\n");
 | 
			
		||||
                $event->{conn}->sl("CAP REQ :sasl");
 | 
			
		||||
            } else {
 | 
			
		||||
                $self->{pbot}->{logger}->log("Completed client capability negotiation\n");
 | 
			
		||||
                $event->{conn}->sl("CAP END");
 | 
			
		||||
            }
 | 
			
		||||
        # all capabilities listed?
 | 
			
		||||
        if ($caps_listed) {
 | 
			
		||||
            # request desired capabilities
 | 
			
		||||
            $self->request_caps($event);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    elsif ($event->{event}->{args}->[0] eq 'ACK') {
 | 
			
		||||
@ -89,7 +63,10 @@ sub on_cap {
 | 
			
		||||
        my @caps = split /\s+/, $event->{event}->{args}->[1];
 | 
			
		||||
 | 
			
		||||
        foreach my $cap (@caps) {
 | 
			
		||||
            $self->{pbot}->{irc_capabilities}->{$cap} = 1;
 | 
			
		||||
            my ($key, $val) = split '=', $cap;
 | 
			
		||||
            $val //= 1;
 | 
			
		||||
 | 
			
		||||
            $self->{pbot}->{irc_capabilities}->{$key} = $val;
 | 
			
		||||
 | 
			
		||||
            if ($cap eq 'sasl') {
 | 
			
		||||
                # begin SASL authentication
 | 
			
		||||
@ -111,4 +88,45 @@ sub on_cap {
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sub request_caps {
 | 
			
		||||
    my ($self, $event) = @_;
 | 
			
		||||
 | 
			
		||||
    # configure client capabilities that PBot currently supports
 | 
			
		||||
    my %desired_caps = (
 | 
			
		||||
        'account-notify' => 1,
 | 
			
		||||
        'account-tag'    => 1,
 | 
			
		||||
        'extended-join'  => 1,
 | 
			
		||||
        'message-tags'   => 1,
 | 
			
		||||
        # sasl is gated by the irc.sasl registry entry instead
 | 
			
		||||
 | 
			
		||||
        # TODO: unsupported capabilities worth looking into
 | 
			
		||||
        'away-notify'    => 0,
 | 
			
		||||
        'chghost'        => 0,
 | 
			
		||||
        'identify-msg'   => 0,
 | 
			
		||||
        'multi-prefix'   => 0,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    foreach my $cap (keys $self->{pbot}->{irc_capabilities_available}->%*) {
 | 
			
		||||
        # request desired capabilities
 | 
			
		||||
        if ($desired_caps{$cap}) {
 | 
			
		||||
            $self->{pbot}->{logger}->log("Requesting client capability $cap\n");
 | 
			
		||||
            $event->{conn}->sl("CAP REQ :$cap");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # request SASL capability if enabled, otherwise end cap negotiation
 | 
			
		||||
    if ($self->{pbot}->{registry}->get_value('irc', 'sasl')) {
 | 
			
		||||
        if (not exists $self->{pbot}->{irc_capabilities_available}->{sasl}) {
 | 
			
		||||
            $self->{pbot}->{logger}->log("SASL is not supported by this IRC server\n");
 | 
			
		||||
            $self->{pbot}->exit(EXIT_FAILURE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $self->{pbot}->{logger}->log("Requesting client capability sasl\n");
 | 
			
		||||
        $event->{conn}->sl("CAP REQ :sasl");
 | 
			
		||||
    } else {
 | 
			
		||||
        $self->{pbot}->{logger}->log("Completed client capability negotiation\n");
 | 
			
		||||
        $event->{conn}->sl("CAP END");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
@ -52,18 +52,19 @@ sub on_notice {
 | 
			
		||||
sub on_public {
 | 
			
		||||
    my ($self, $event_type, $event) = @_;
 | 
			
		||||
 | 
			
		||||
    my ($from, $nick, $user, $host, $text) = (
 | 
			
		||||
    my ($from, $nick, $user, $host, $text, $tags) = (
 | 
			
		||||
        $event->{event}->{to}->[0],
 | 
			
		||||
        $event->{event}->nick,
 | 
			
		||||
        $event->{event}->user,
 | 
			
		||||
        $event->{event}->host,
 | 
			
		||||
        $event->{event}->{args}->[0],
 | 
			
		||||
        $event->{event}->{args}->[1],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    ($nick, $user, $host) = $self->{pbot}->{irchandlers}->normalize_hostmask($nick, $user, $host);
 | 
			
		||||
 | 
			
		||||
    # send text to be processed for bot commands, anti-flood enforcement, etc
 | 
			
		||||
    $event->{interpreted} = $self->{pbot}->{interpreter}->process_line($from, $nick, $user, $host, $text);
 | 
			
		||||
    $event->{interpreted} = $self->{pbot}->{interpreter}->process_line($from, $nick, $user, $host, $text, $tags);
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
@ -82,17 +83,18 @@ sub on_action {
 | 
			
		||||
sub on_msg {
 | 
			
		||||
    my ($self, $event_type, $event) = @_;
 | 
			
		||||
 | 
			
		||||
    my ($nick, $user, $host, $text) = (
 | 
			
		||||
    my ($nick, $user, $host, $text, $tags) = (
 | 
			
		||||
        $event->{event}->nick,
 | 
			
		||||
        $event->{event}->user,
 | 
			
		||||
        $event->{event}->host,
 | 
			
		||||
        $event->{event}->{args}->[0],
 | 
			
		||||
        $event->{event}->{args}->[1],
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    ($nick, $user, $host) = $self->{pbot}->{irchandlers}->normalize_hostmask($nick, $user, $host);
 | 
			
		||||
 | 
			
		||||
    # send text to be processed as a bot command, in "channel" $nick
 | 
			
		||||
    $event->{interpreted} = $self->{pbot}->{interpreter}->process_line($nick, $nick, $user, $host, $text, 1);
 | 
			
		||||
    $event->{interpreted} = $self->{pbot}->{interpreter}->process_line($nick, $nick, $user, $host, $text, $tags, 1);
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ package PBot::Core::Handlers::SASL;
 | 
			
		||||
use PBot::Imports;
 | 
			
		||||
use parent 'PBot::Core::Class';
 | 
			
		||||
 | 
			
		||||
use POSIX qw/EXIT_SUCCESS EXIT_FAILURE/;
 | 
			
		||||
use POSIX qw/EXIT_FAILURE/;
 | 
			
		||||
use Encode;
 | 
			
		||||
use MIME::Base64;
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,7 @@ sub on_sasl_authenticate {
 | 
			
		||||
 | 
			
		||||
sub on_rpl_loggedin {
 | 
			
		||||
    my ($self, $event_type, $event) = @_;
 | 
			
		||||
    $self->{pbot}->{logger}->log($event->{event}->{args}->[1] . "\n");
 | 
			
		||||
    $self->{pbot}->{logger}->log($event->{event}->{args}->[3] . "\n");
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -260,6 +260,23 @@ sub timeout {
 | 
			
		||||
    return $self->{_timeout};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# parses message tags into a hashref
 | 
			
		||||
sub get_tags {
 | 
			
		||||
    my ($self, $tags) = @_;
 | 
			
		||||
 | 
			
		||||
    $self->{_pbot}->{logger}->log("Message tags: [$tags]\n");
 | 
			
		||||
 | 
			
		||||
    my @list = split ';', $tags;
 | 
			
		||||
    my %hash;
 | 
			
		||||
 | 
			
		||||
    foreach my $tag (@list) {
 | 
			
		||||
        my ($key, $val) = split '=', $tag;
 | 
			
		||||
        $hash{$key} = $val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return \%hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
__END__
 | 
			
		||||
 | 
			
		||||
@ -508,9 +508,9 @@ sub handler {
 | 
			
		||||
        croak "Not enough arguments to handler()";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    print STDERR "Trying to handle event '$ev'.\n" if $self->{_debug};
 | 
			
		||||
    print STDERR "--- Trying to handle event '$ev'.\n" if $self->{_debug};
 | 
			
		||||
 | 
			
		||||
    if ($self->{_debug}) {
 | 
			
		||||
    if ($self->{_debug} > 1) {
 | 
			
		||||
        use Data::Dumper;
 | 
			
		||||
        print STDERR "ev: ", Dumper($ev), "\nevent: ", Dumper($event), "\n";
 | 
			
		||||
    }
 | 
			
		||||
@ -535,7 +535,7 @@ sub handler {
 | 
			
		||||
        confess "Bad parameter passed to handler(): rp=$rp";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    print STDERR "Handler for '$ev' called.\n" if $self->{_debug};
 | 
			
		||||
    print STDERR "--- Handler for '$ev' called.\n" if $self->{_debug};
 | 
			
		||||
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
@ -838,7 +838,7 @@ sub oper {
 | 
			
		||||
# appropriate handler. Takes no args, really.
 | 
			
		||||
sub parse {
 | 
			
		||||
    my ($self) = shift;
 | 
			
		||||
    my ($from, $type, $message, @stuff, $itype, $ev, @lines, $line);
 | 
			
		||||
    my ($from, $type, $message, @stuff, $itype, $ev, @lines, $line, $tags);
 | 
			
		||||
 | 
			
		||||
    my $n;
 | 
			
		||||
 | 
			
		||||
@ -920,7 +920,9 @@ sub parse {
 | 
			
		||||
            # Spurious backslashes are for the benefit of cperl-mode.
 | 
			
		||||
            # Assumption:  all non-numeric message types begin with a letter
 | 
			
		||||
        } elsif (
 | 
			
		||||
            $line =~ /^:?
 | 
			
		||||
            $line =~ /^
 | 
			
		||||
            (?:\@\S+\s)?             # Optional message tags
 | 
			
		||||
            :?                       # Initial colon
 | 
			
		||||
            (?:[][}{\w\\\`^|\-]+?    # The nick (valid nickname chars)
 | 
			
		||||
             !                       # The nick-username separator
 | 
			
		||||
             .+?                     # The username
 | 
			
		||||
@ -932,6 +934,8 @@ sub parse {
 | 
			
		||||
            /x
 | 
			
		||||
          )    # That ought to do it for now...
 | 
			
		||||
        {
 | 
			
		||||
            $tags = undef;
 | 
			
		||||
            $tags = $1 if $line =~ s/^@(\S+)\s//;
 | 
			
		||||
            $line = substr $line, 1 if $line =~ /^:/;
 | 
			
		||||
 | 
			
		||||
            # Patch submitted for v.0.72
 | 
			
		||||
@ -939,7 +943,7 @@ sub parse {
 | 
			
		||||
            # ($from, $line) = split ":", $line, 2;
 | 
			
		||||
            ($from, $line) = $line =~ /^(?:|)(\S+\s+[^:]+):?(.*)/;
 | 
			
		||||
 | 
			
		||||
            print STDERR "from: [$from], line: [$line]\n" if $self->{_debug};
 | 
			
		||||
            print STDERR "from: [$from], line: [$line]\n" if $self->{_debug} > 2;
 | 
			
		||||
 | 
			
		||||
            ($from, $type, @stuff) = split /\s+/, $from;
 | 
			
		||||
            $type = lc $type;
 | 
			
		||||
@ -986,8 +990,9 @@ sub parse {
 | 
			
		||||
            #                  quotemeta($_)));  /$from/ }
 | 
			
		||||
            # ($self->ignore($type), $self->ignore("all"));
 | 
			
		||||
 | 
			
		||||
            # Add $line to @stuff for the handlers
 | 
			
		||||
            # Add $line and $tags to @stuff for the handlers
 | 
			
		||||
            push @stuff, $line if defined $line;
 | 
			
		||||
            push @stuff, $tags if defined $tags;
 | 
			
		||||
 | 
			
		||||
            # Now ship it off to the appropriate handler and forget about it.
 | 
			
		||||
            if ($itype eq "ctcp") {    # it's got CTCP in it!
 | 
			
		||||
@ -1251,6 +1256,9 @@ sub privmsg {
 | 
			
		||||
 | 
			
		||||
    my $buf    = CORE::join '', @_;
 | 
			
		||||
    my $length = $self->{_maxlinelen} - 11 - length($to);
 | 
			
		||||
 | 
			
		||||
    print STDERR "privmsg trunc length: $length; msg len: " . (length $buf) . "\n" if $self->{_debug};
 | 
			
		||||
 | 
			
		||||
    my $line;
 | 
			
		||||
 | 
			
		||||
    if (ref($to) =~ /^(GLOB|IO::Socket)/) {
 | 
			
		||||
@ -1261,8 +1269,11 @@ sub privmsg {
 | 
			
		||||
    } else {
 | 
			
		||||
        while (length($buf) > 0) {
 | 
			
		||||
            ($line, $buf) = unpack("a$length a*", $buf);
 | 
			
		||||
            if   (ref $to eq 'ARRAY') { $self->sl("PRIVMSG ", CORE::join(',', @$to), " :$line"); }
 | 
			
		||||
            else                      { $self->sl("PRIVMSG $to :$line"); }
 | 
			
		||||
            if (ref $to eq 'ARRAY') {
 | 
			
		||||
                $self->sl("PRIVMSG ", CORE::join(',', @$to), " :$line");
 | 
			
		||||
            } else {
 | 
			
		||||
                $self->sl("PRIVMSG $to :$line");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1319,7 +1330,7 @@ sub schedule {
 | 
			
		||||
    unless ($coderef)                { croak 'Not enough arguments to Connection->schedule()'; }
 | 
			
		||||
    unless (ref($coderef) eq 'CODE') { croak 'Second argument to schedule() isn\'t a coderef'; }
 | 
			
		||||
 | 
			
		||||
    print STDERR "Scheduling event with time [$time]\n" if $self->{_debug};
 | 
			
		||||
    print STDERR "Scheduling event with time [$time]\n" if $self->{_debug} > 1;
 | 
			
		||||
    $time += time;
 | 
			
		||||
    $self->parent->enqueue_scheduled_event($time, $coderef, $self, @_);
 | 
			
		||||
}
 | 
			
		||||
@ -1332,7 +1343,7 @@ sub schedule_output_event {
 | 
			
		||||
    unless ($coderef)                { croak 'Not enough arguments to Connection->schedule()'; }
 | 
			
		||||
    unless (ref($coderef) eq 'CODE') { croak 'Second argument to schedule() isn\'t a coderef'; }
 | 
			
		||||
 | 
			
		||||
    print STDERR "Scheduling output event with time [$time] [$_[0]]\n" if $self->{_debug};
 | 
			
		||||
    print STDERR "Scheduling output event with time [$time] [$_[0]]\n" if $self->{_debug} > 1;
 | 
			
		||||
    $time += time;
 | 
			
		||||
    $self->parent->enqueue_output_event($time, $coderef, $self, @_);
 | 
			
		||||
}
 | 
			
		||||
@ -1395,6 +1406,10 @@ sub sl {
 | 
			
		||||
    if ($self->{_slcount} < 10) {
 | 
			
		||||
        $self->{_slcount}++;
 | 
			
		||||
        $self->{_lastsl} = time;
 | 
			
		||||
 | 
			
		||||
        ### DEBUG DEBUG DEBUG
 | 
			
		||||
        if ($self->{_debug} > 1) { print STDERR "S-> 0 " . (length ($line) + 2) . " $line\n"; }
 | 
			
		||||
 | 
			
		||||
        return $self->schedule_output_event(0, \&sl_real, $line);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1413,7 +1428,7 @@ sub sl {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ### DEBUG DEBUG DEBUG
 | 
			
		||||
    if ($self->{_debug}) { print STDERR "S-> $seconds $line\n"; }
 | 
			
		||||
    if ($self->{_debug} > 1) { print STDERR "S-> $seconds " . (length ($line) + 2) . " $line\n"; }
 | 
			
		||||
 | 
			
		||||
    $self->schedule_output_event($seconds, \&sl_real, $line);
 | 
			
		||||
}
 | 
			
		||||
@ -1428,7 +1443,7 @@ sub sl_real {
 | 
			
		||||
    unless ($line) { croak "Not enough arguments to sl_real()"; }
 | 
			
		||||
 | 
			
		||||
    ### DEBUG DEBUG DEBUG
 | 
			
		||||
    if ($self->{_debug}) { print STDERR ">>> $line\n"; }
 | 
			
		||||
    if ($self->{_debug}) { print STDERR ">>> (" . (length ($line) + 2) . ") $line\n"; }
 | 
			
		||||
 | 
			
		||||
    return unless defined $self->socket;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ sub initialize {
 | 
			
		||||
# this is the main entry point for a message to be parsed into commands
 | 
			
		||||
# and to execute those commands and process their output
 | 
			
		||||
sub process_line {
 | 
			
		||||
    my ($self, $from, $nick, $user, $host, $text, $is_command) = @_;
 | 
			
		||||
    my ($self, $from, $nick, $user, $host, $text, $tags, $is_command) = @_;
 | 
			
		||||
 | 
			
		||||
    # lowercase `from` field for case-insensitivity
 | 
			
		||||
    $from = lc $from;
 | 
			
		||||
@ -57,6 +57,7 @@ sub process_line {
 | 
			
		||||
        host     => $host,                 # hostname/ip address
 | 
			
		||||
        hostmask => "$nick!$user\@$host",  # full hostmask
 | 
			
		||||
        text     => $text,                 # message contents
 | 
			
		||||
        tags     => $tags,                 # message tags
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    # add hostmask to user/message tracking database and get their account id
 | 
			
		||||
 | 
			
		||||
@ -68,7 +68,7 @@ sub stdin_reader {
 | 
			
		||||
    my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick');
 | 
			
		||||
 | 
			
		||||
    # process input as a bot command
 | 
			
		||||
    return $self->{pbot}->{interpreter}->process_line('stdin@pbot', $botnick, "stdin", "pbot", $input, 1);
 | 
			
		||||
    return $self->{pbot}->{interpreter}->process_line('stdin@pbot', $botnick, "stdin", "pbot", $input, undef, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
1;
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,8 @@ use PBot::Imports;
 | 
			
		||||
# These are set by the /misc/update_version script
 | 
			
		||||
use constant {
 | 
			
		||||
    BUILD_NAME     => "PBot",
 | 
			
		||||
    BUILD_REVISION => 4605,
 | 
			
		||||
    BUILD_DATE     => "2023-01-24",
 | 
			
		||||
    BUILD_REVISION => 4606,
 | 
			
		||||
    BUILD_DATE     => "2023-01-27",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
sub initialize {}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user