mirror of https://github.com/pragma-/pbot.git
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) {
|
||||
# get original nick's account id
|
||||
my $orig_id = $self->get_message_account_id("$orig_nick!$user\@$host");
|
||||
my @orig_nickserv_accounts = $self->get_nickserv_accounts($orig_id);
|
||||
|
||||
# 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");
|
||||
|
@ -706,19 +752,23 @@ 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");
|
||||
. " $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…
Reference in New Issue