mirror of
				https://github.com/pragma-/pbot.git
				synced 2025-11-04 08:37:24 +01:00 
			
		
		
		
	MessageHistory: fix aka tracking for nick-changes
Add registry entry `irc.cloak` for setting user-cloak value to, e.g., "user" or "unaffiliated". Defaults to "user".
This commit is contained in:
		
							parent
							
								
									569463df28
								
							
						
					
					
						commit
						d7b12a1da2
					
				@ -15,8 +15,8 @@ use parent 'PBot::Class';
 | 
			
		||||
use PBot::Imports;
 | 
			
		||||
 | 
			
		||||
use DBI;
 | 
			
		||||
use Carp qw(shortmess);
 | 
			
		||||
use Time::HiRes qw(gettimeofday);
 | 
			
		||||
use Carp              qw/shortmess/;
 | 
			
		||||
use Time::HiRes       qw/time/;
 | 
			
		||||
use Text::CSV;
 | 
			
		||||
use Text::Levenshtein qw/fastdistance/;
 | 
			
		||||
use Time::Duration;
 | 
			
		||||
@ -291,7 +291,7 @@ sub add_message_account {
 | 
			
		||||
 | 
			
		||||
    eval {
 | 
			
		||||
        my $sth = $self->{dbh}->prepare('INSERT INTO Hostmasks VALUES (?, ?, ?, 0, ?, ?, ?)');
 | 
			
		||||
        $sth->execute($mask, $id, scalar gettimeofday, $nick, $user, $host);
 | 
			
		||||
        $sth->execute($mask, $id, scalar time, $nick, $user, $host);
 | 
			
		||||
        $self->{new_entries}++;
 | 
			
		||||
 | 
			
		||||
        if ((not defined $link_id) || ((defined $link_id) && ($link_type == $self->{alias_type}->{WEAK}))) {
 | 
			
		||||
@ -393,77 +393,110 @@ sub get_message_account {
 | 
			
		||||
    my $id   = $self->get_message_account_id($mask);
 | 
			
		||||
    return $id if defined $id;
 | 
			
		||||
 | 
			
		||||
    $self->{pbot}->{logger}->log("Getting new message account for $nick!$user\@$host...\n");
 | 
			
		||||
    $self->{pbot}->{logger}->log("Getting new message account for $nick!$user\@$host\n");
 | 
			
		||||
    $self->{pbot}->{logger}->log("Nick-changing from $orig_nick\n") if defined $orig_nick;
 | 
			
		||||
 | 
			
		||||
    my $do_nothing = 0;
 | 
			
		||||
    my $sth;
 | 
			
		||||
 | 
			
		||||
    my ($rows, $link_type) = eval {
 | 
			
		||||
        my ($account1) = $host =~ m{/([^/]+)$};
 | 
			
		||||
        $account1 = '' if not defined $account1;
 | 
			
		||||
        $account1 //= '';
 | 
			
		||||
 | 
			
		||||
        # extract ips from hosts like 75-42-36-105.foobar.com as 75.42.36.105
 | 
			
		||||
        my $hostip;
 | 
			
		||||
 | 
			
		||||
        my $hostip = undef;
 | 
			
		||||
        if ($host =~ m/(\d+[[:punct:]]\d+[[:punct:]]\d+[[:punct:]]\d+)\D/) {
 | 
			
		||||
            $hostip = $1;
 | 
			
		||||
            $hostip =~ s/[[:punct:]]/./g;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        # nick-change from $orig_nick to $nick
 | 
			
		||||
        if (defined $orig_nick) {
 | 
			
		||||
            my $orig_id                = $self->get_message_account_id("$orig_nick!$user\@$host");
 | 
			
		||||
            my @orig_nickserv_accounts = $self->get_nickserv_accounts($orig_id);
 | 
			
		||||
            # get original nick's account id
 | 
			
		||||
            my $orig_id = $self->get_message_account_id("$orig_nick!$user\@$host");
 | 
			
		||||
 | 
			
		||||
            # changing nick to a Guest
 | 
			
		||||
            if ($nick =~ m/^Guest\d+$/) {
 | 
			
		||||
                $sth = $self->{dbh}->prepare('SELECT id, hostmask, last_seen FROM Hostmasks WHERE user = ? and host = ? ORDER BY last_seen DESC');
 | 
			
		||||
                # find most recent *!user@host, if any
 | 
			
		||||
                $sth = $self->{dbh}->prepare('SELECT id, hostmask, last_seen FROM Hostmasks WHERE user = ? and host = ? ORDER BY last_seen DESC LIMIT 1');
 | 
			
		||||
                $sth->execute($user, $host);
 | 
			
		||||
 | 
			
		||||
                my $rows = $sth->fetchall_arrayref({});
 | 
			
		||||
 | 
			
		||||
                # found a probable match
 | 
			
		||||
                if (defined $rows->[0]) {
 | 
			
		||||
                    my $link_type = $self->{alias_type}->{STRONG};
 | 
			
		||||
                    if (gettimeofday - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
 | 
			
		||||
                    # if 48 hours have elapsed since this *!user@host was seen
 | 
			
		||||
                    # then still link the Guest to this account, but weakly
 | 
			
		||||
                    if (time - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
                        $link_type = $self->{alias_type}->{WEAK};
 | 
			
		||||
 | 
			
		||||
                        $self->{pbot}->{logger}->log(
 | 
			
		||||
                            "Longer than 48 hours (" . concise duration(gettimeofday - $rows->[0]->{last_seen}) . ") for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n");
 | 
			
		||||
                            "Longer than 48 hours (" . concise duration(time - $rows->[0]->{last_seen}) . ")"
 | 
			
		||||
                            . " for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n"
 | 
			
		||||
                        );
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    # log match and return link
 | 
			
		||||
                    $self->{pbot}->{logger}->log("6: nick-change guest match: $rows->[0]->{id}: $rows->[0]->{hostmask}\n");
 | 
			
		||||
                    $orig_nick = undef;
 | 
			
		||||
                    $orig_nick = undef; # nick-change handled
 | 
			
		||||
                    return ($rows, $link_type);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # find all accounts that match nick!*@*, sorted by last-seen
 | 
			
		||||
            $sth = $self->{dbh}->prepare('SELECT id, hostmask, last_seen FROM Hostmasks WHERE nick = ? ORDER BY last_seen DESC');
 | 
			
		||||
            $sth->execute($nick);
 | 
			
		||||
            my $rows = $sth->fetchall_arrayref({});
 | 
			
		||||
 | 
			
		||||
            # no nicks found, strongly link to original account
 | 
			
		||||
            if (not defined $rows->[0]) {
 | 
			
		||||
                $rows->[0] = {id => $orig_id, hostmask => "$orig_nick!$user\@$host"};
 | 
			
		||||
                $rows->[0] = { id => $orig_id, hostmask => "$orig_nick!$user\@$host" };
 | 
			
		||||
                $orig_nick = undef; # nick-change handled
 | 
			
		||||
                return ($rows, $self->{alias_type}->{STRONG});
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            # look up original nick's NickServ accounts outside of upcoming loop
 | 
			
		||||
            my @orig_nickserv_accounts = $self->get_nickserv_accounts($orig_id);
 | 
			
		||||
 | 
			
		||||
            # go over the list of nicks and see if any identifying details match
 | 
			
		||||
            my %processed_nicks;
 | 
			
		||||
            my %processed_akas;
 | 
			
		||||
 | 
			
		||||
            foreach my $row (@$rows) {
 | 
			
		||||
                $self->{pbot}->{logger}->log("Found matching nickchange account: [$row->{id}] $row->{hostmask}\n");
 | 
			
		||||
                $self->{pbot}->{logger}->log("Found matching nick-change account: [$row->{id}] $row->{hostmask}\n");
 | 
			
		||||
                my ($tnick) = $row->{hostmask} =~ m/^([^!]+)!/;
 | 
			
		||||
 | 
			
		||||
                # don't process duplicates
 | 
			
		||||
                next if exists $processed_nicks{lc $tnick};
 | 
			
		||||
                $processed_nicks{lc $tnick} = 1;
 | 
			
		||||
 | 
			
		||||
                # get all akas for this nick
 | 
			
		||||
                my %akas = $self->get_also_known_as($tnick);
 | 
			
		||||
 | 
			
		||||
                # check each aka for identifying details
 | 
			
		||||
                foreach my $aka (keys %akas) {
 | 
			
		||||
                    # skip dubious links
 | 
			
		||||
                    next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
 | 
			
		||||
                    next if $akas{$aka}->{nickchange} == 1;
 | 
			
		||||
 | 
			
		||||
                    # don't process duplicates
 | 
			
		||||
                    next if exists $processed_akas{$akas{$aka}->{id}};
 | 
			
		||||
                    $processed_akas{$akas{$aka}->{id}} = 1;
 | 
			
		||||
 | 
			
		||||
                    $self->{pbot}->{logger}->log("Testing alias [$akas{$aka}->{id}] $aka\n");
 | 
			
		||||
                    my $match = 0;
 | 
			
		||||
 | 
			
		||||
                    # account ids or *!user@host matches
 | 
			
		||||
                    if ($akas{$aka}->{id} == $orig_id || $aka =~ m/^.*!\Q$user\E\@\Q$host\E$/i) {
 | 
			
		||||
                        $self->{pbot}->{logger}->log("1: match: $akas{$aka}->{id} vs $orig_id // $aka vs *!$user\@$host\n");
 | 
			
		||||
                        $match = 1;
 | 
			
		||||
                        goto MATCH;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    # check if any nickserv accounts match
 | 
			
		||||
                    if (@orig_nickserv_accounts) {
 | 
			
		||||
                        my @nickserv_accounts = $self->get_nickserv_accounts($akas{$aka}->{id});
 | 
			
		||||
                        foreach my $ns1 (@orig_nickserv_accounts) {
 | 
			
		||||
@ -477,6 +510,7 @@ sub get_message_account {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    # check if hosts match
 | 
			
		||||
                    my ($thost) = $aka =~ m/@(.*)$/;
 | 
			
		||||
 | 
			
		||||
                    if ($thost =~ m{/}) {
 | 
			
		||||
@ -487,11 +521,15 @@ sub get_message_account {
 | 
			
		||||
                            next;
 | 
			
		||||
                        } else {
 | 
			
		||||
                            $self->{pbot}->{logger}->log("Cloaked hosts match: $host vs $thost\n");
 | 
			
		||||
                            $rows->[0] = {id => $self->get_ancestor_id($akas{$aka}->{id}), hostmask => $aka};
 | 
			
		||||
                            $rows->[0] = {
 | 
			
		||||
                                id       => $self->get_ancestor_id($akas{$aka}->{id}),
 | 
			
		||||
                                hostmask => $aka,
 | 
			
		||||
                            };
 | 
			
		||||
                            return ($rows, $self->{alias_type}->{STRONG});
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    # fuzzy match hosts
 | 
			
		||||
                    my $distance = fastdistance($host, $thost);
 | 
			
		||||
                    my $length   = (length($host) > length($thost)) ? length $host : length $thost;
 | 
			
		||||
 | 
			
		||||
@ -530,12 +568,12 @@ sub get_message_account {
 | 
			
		||||
 | 
			
		||||
            my $new_id = $self->add_message_account($mask);
 | 
			
		||||
            $self->link_alias($orig_id, $new_id, $self->{alias_type}->{WEAK});
 | 
			
		||||
            $self->update_hostmask_data($mask, {nickchange => 1, last_seen => scalar gettimeofday});
 | 
			
		||||
            $self->update_hostmask_data($mask, {nickchange => 1, last_seen => scalar time});
 | 
			
		||||
 | 
			
		||||
            $do_nothing = 1;
 | 
			
		||||
            $rows->[0] = {id => $new_id};
 | 
			
		||||
            return ($rows, 0);
 | 
			
		||||
        }
 | 
			
		||||
        } # end nick-change
 | 
			
		||||
 | 
			
		||||
        if ($host =~ m{^gateway/web/irccloud.com}) {
 | 
			
		||||
            $sth = $self->{dbh}->prepare('SELECT id, hostmask, last_seen FROM Hostmasks WHERE host = ? ORDER BY last_seen DESC');
 | 
			
		||||
@ -576,10 +614,10 @@ sub get_message_account {
 | 
			
		||||
            my $rows = $sth->fetchall_arrayref({});
 | 
			
		||||
            if (defined $rows->[0]) {
 | 
			
		||||
                my $link_type = $self->{alias_type}->{STRONG};
 | 
			
		||||
                if (gettimeofday - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
                if (time - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
                    $link_type = $self->{alias_type}->{WEAK};
 | 
			
		||||
                    $self->{pbot}->{logger}->log(
 | 
			
		||||
                        "Longer than 48 hours (" . concise duration(gettimeofday - $rows->[0]->{last_seen}) . ") for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n");
 | 
			
		||||
                        "Longer than 48 hours (" . concise duration(time - $rows->[0]->{last_seen}) . ") for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n");
 | 
			
		||||
                }
 | 
			
		||||
                $self->{pbot}->{logger}->log("6: guest match: $rows->[0]->{id}: $rows->[0]->{hostmask}\n");
 | 
			
		||||
                return ($rows, $link_type);
 | 
			
		||||
@ -667,10 +705,10 @@ sub get_message_account {
 | 
			
		||||
            $sth->execute($user, $host);
 | 
			
		||||
            $rows = $sth->fetchall_arrayref({});
 | 
			
		||||
 | 
			
		||||
            if (defined $rows->[0] and gettimeofday - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
            if (defined $rows->[0] and time - $rows->[0]->{last_seen} > 60 * 60 * 48) {
 | 
			
		||||
                $link_type = $self->{alias_type}->{WEAK};
 | 
			
		||||
                $self->{pbot}->{logger}->log(
 | 
			
		||||
                    "Longer than 48 hours (" . concise duration(gettimeofday - $rows->[0]->{last_seen}) . ") for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n");
 | 
			
		||||
                    "Longer than 48 hours (" . concise duration(time - $rows->[0]->{last_seen}) . ") for $rows->[0]->{hostmask} for $nick!$user\@$host, degrading to weak link\n");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
=cut
 | 
			
		||||
@ -684,20 +722,28 @@ sub get_message_account {
 | 
			
		||||
 | 
			
		||||
        return ($rows, $link_type);
 | 
			
		||||
    };
 | 
			
		||||
    $self->{pbot}->{logger}->log($@) if $@;
 | 
			
		||||
 | 
			
		||||
    if (my $exception = $@) {
 | 
			
		||||
        $self->{pbot}->{logger}->log("Exception getting account: $exception");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    # nothing else to do here for nick-change, return id
 | 
			
		||||
    return $rows->[0]->{id} if $do_nothing;
 | 
			
		||||
 | 
			
		||||
    if (defined $rows->[0] and not defined $orig_nick) {
 | 
			
		||||
        if ($link_type == $self->{alias_type}->{STRONG}) {
 | 
			
		||||
            my $host1 = lc "$nick!$user\@$host";
 | 
			
		||||
            my $host2 = lc $rows->[0]->{hostmask};
 | 
			
		||||
 | 
			
		||||
            my ($nick1) = $host1 =~ m/^([^!]+)!/;
 | 
			
		||||
            my ($nick2) = $host2 =~ m/^([^!]+)!/;
 | 
			
		||||
 | 
			
		||||
            my $distance = fastdistance($nick1, $nick2);
 | 
			
		||||
            my $length   = (length $nick1 > length $nick2) ? length $nick1 : length $nick2;
 | 
			
		||||
 | 
			
		||||
            if ($distance > 1 && ($nick1 !~ /^guest/ && $nick2 !~ /^guest/) && ($host1 !~ /unaffiliated/ || $host2 !~ /unaffiliated/)) {
 | 
			
		||||
            my $irc_cloak = $self->{pbot}->{registry}->get_value('irc', 'cloak') // 'user';
 | 
			
		||||
 | 
			
		||||
            if ($distance > 1 && ($nick1 !~ /^guest/ && $nick2 !~ /^guest/) && ($host1 !~ /$irc_cloak/ || $host2 !~ /$irc_cloak/)) {
 | 
			
		||||
                my $id = $rows->[0]->{id};
 | 
			
		||||
                $self->{pbot}->{logger}->log("[$nick1][$nick2] $distance / $length\n");
 | 
			
		||||
                $self->{pbot}->{logger}->log("Possible bogus account: ($id) $host1 vs ($id) $host2\n");
 | 
			
		||||
@ -705,20 +751,24 @@ sub get_message_account {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $self->{pbot}->{logger}->log("message-history: [get-account] $nick!$user\@$host "
 | 
			
		||||
              . ($link_type == $self->{alias_type}->{WEAK} ? "weakly linked to" : "added to account")
 | 
			
		||||
              . " $rows->[0]->{hostmask} with id $rows->[0]->{id}\n");
 | 
			
		||||
            . ($link_type == $self->{alias_type}->{WEAK} ? "weakly linked to" : "added to account")
 | 
			
		||||
            . " $rows->[0]->{hostmask} with id $rows->[0]->{id}\n"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $self->add_message_account("$nick!$user\@$host", $rows->[0]->{id}, $link_type);
 | 
			
		||||
        $self->devalidate_all_channels($rows->[0]->{id});
 | 
			
		||||
        $self->update_hostmask_data("$nick!$user\@$host", {last_seen => scalar gettimeofday});
 | 
			
		||||
        $self->update_hostmask_data("$nick!$user\@$host", { last_seen => scalar time });
 | 
			
		||||
 | 
			
		||||
        my @nickserv_accounts = $self->get_nickserv_accounts($rows->[0]->{id});
 | 
			
		||||
        foreach my $nickserv_account (@nickserv_accounts) {
 | 
			
		||||
            $self->{pbot}->{logger}->log("$nick!$user\@$host [$rows->[0]->{id}] seen with nickserv account [$nickserv_account]\n");
 | 
			
		||||
            $self->{pbot}->{antiflood}->check_nickserv_accounts($nick, $nickserv_account, "$nick!$user\@$host");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $rows->[0]->{id};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $self->{pbot}->{logger}->log("No account found for mask [$mask], adding new account\n");
 | 
			
		||||
    $self->{pbot}->{logger}->log("No account found for $mask, adding new account\n");
 | 
			
		||||
    return $self->add_message_account($mask);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1342,7 +1392,7 @@ sub link_aliases {
 | 
			
		||||
            $sth->execute($host);
 | 
			
		||||
            my $rows = $sth->fetchall_arrayref({});
 | 
			
		||||
 | 
			
		||||
            my $now = gettimeofday;
 | 
			
		||||
            my $now = time;
 | 
			
		||||
 | 
			
		||||
            foreach my $row (@$rows) {
 | 
			
		||||
                my $idhost = $self->find_most_recent_hostmask($row->{id}) if $debug_link >= 2 && $row->{id} != $account;
 | 
			
		||||
@ -1491,7 +1541,8 @@ sub link_alias {
 | 
			
		||||
        my ($nick2) = $host2 =~ m/^([^!]+)!/;
 | 
			
		||||
        my $distance = fastdistance($nick1, $nick2);
 | 
			
		||||
        my $length   = (length $nick1 > length $nick2) ? length $nick1 : length $nick2;
 | 
			
		||||
        if ($distance > 1 && ($nick1 !~ /^guest/ && $nick2 !~ /^guest/) && ($host1 !~ /unaffiliated/ || $host2 !~ /unaffiliated/)) {
 | 
			
		||||
        my $irc_cloak = $self->{pbot}->{registry}->get_value('irc', 'cloak') // 'user';
 | 
			
		||||
        if ($distance > 1 && ($nick1 !~ /^guest/ && $nick2 !~ /^guest/) && ($host1 !~ /$irc_cloak/ || $host2 !~ /$irc_cloak/)) {
 | 
			
		||||
            $self->{pbot}->{logger}->log("[$nick1][$nick2] $distance / $length\n");
 | 
			
		||||
            $self->{pbot}->{logger}->log("Possible bogus link: ($id) $host1 vs ($alias) $host2\n");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user