Merge branch 'master' of github.com:pragma-/pbot

This commit is contained in:
Pragmatic Software 2021-07-13 14:58:28 -07:00
commit 355adcfced
2 changed files with 82 additions and 31 deletions

View File

@ -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");
}

View File

@ -16,8 +16,8 @@ use LWP::UserAgent;
# These are set automatically by the misc/update_version script
use constant {
BUILD_NAME => "PBot",
BUILD_REVISION => 4173,
BUILD_DATE => "2021-07-10",
BUILD_REVISION => 4176,
BUILD_DATE => "2021-07-11",
};
sub initialize {