MessageHistory: use all aka ids when recalling messages

This commit is contained in:
Pragmatic Software 2021-07-13 15:23:04 -07:00
parent d4e47c0eb1
commit 1dd4180f1f
2 changed files with 313 additions and 236 deletions

View File

@ -34,7 +34,6 @@ sub initialize {
$self->{MSG_NICKCHANGE} = 3; # CHANGED NICK
$self->{pbot}->{registry}->add_default('text', 'messagehistory', 'max_recall_time', $conf{max_recall_time} // 0);
$self->{pbot}->{registry}->add_default('text', 'messagehistory', 'max_messages', 32);
$self->{pbot}->{commands}->register(sub { $self->cmd_recall_message(@_) }, "recall", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_rebuild_aliases(@_) }, "rebuildaliases", 1);
@ -220,11 +219,6 @@ sub cmd_list_also_known_as {
sub cmd_recall_message {
my ($self, $context) = @_;
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
my $usage = 'Usage: recall [nick [history [channel]]] [-c <channel>] [-t <text>] [-b <context before>] [-a <context after>] [-x <filter to nick>] [-n <count>] [-r raw mode] [+ ...]';
my $arguments = $context->{arguments};
@ -338,7 +332,9 @@ sub cmd_recall_message {
}
# skip recall command if recalling self without arguments
$recall_history = $context->{nick} eq $recall_nick ? 2 : 1 if defined $recall_nick and not defined $recall_history;
if (defined $recall_nick and not defined $recall_history) {
$recall_history = $context->{nick} eq $recall_nick ? 2 : 1;
}
# set history to most recent message if not specified
$recall_history = '1' if not defined $recall_history;
@ -352,26 +348,39 @@ sub cmd_recall_message {
$recall_channel = $context->{from};
}
if (not defined $recall_nick and defined $recall_context) { $recall_nick = $recall_context; }
# set nick argument to -x argument if no nick was provided but -x was
if (not defined $recall_nick and defined $recall_context) {
$recall_nick = $recall_context;
}
# message account and stored nickname with proper typographical casing
my ($account, $found_nick);
# get message account and found nick if a nick was provided
if (defined $recall_nick) {
# account and hostmask
($account, $found_nick) = $self->{database}->find_message_account_by_nick($recall_nick);
if (not defined $account) { return "I don't know anybody named $recall_nick."; }
if (not defined $account) {
return "I don't know anybody named $recall_nick.";
}
# keep only nick portion of hostmask
$found_nick =~ s/!.*$//;
}
# matching message found in database, if any
my $message;
if ($random) {
$message = $self->{database}->get_random_message($account, $recall_channel);
# get a random message
$message = $self->{database}->get_random_message($account, $recall_channel, $recall_nick);
} elsif ($recall_history =~ /^\d+$/ and not defined $recall_text) {
# integral history
# if a nick was given, ensure requested history is within range of nick's history count
if (defined $account) {
my $max_messages = $self->{database}->get_max_messages($account, $recall_channel);
my $max_messages = $self->{database}->get_max_messages($account, $recall_channel, $recall_nick);
if ($recall_history < 1 || $recall_history > $max_messages) {
if ($max_messages == 0) {
return "No messages for $recall_nick in $recall_channel yet.";
@ -382,57 +391,81 @@ sub cmd_recall_message {
}
$recall_history--;
$message = $self->{database}->recall_message_by_count($account, $recall_channel, $recall_history, '(?:recall|mock|ftfy|fix|clapper)');
if (not defined $message) {
return "No message found at index $recall_history in channel $recall_channel.";
}
} else {
# regex history
$message = $self->{database}->recall_message_by_text($account, $recall_channel, $recall_history, '(?:recall|mock|ftfy|fix|clapper)');
$message = $self->{database}->recall_message_by_count($account, $recall_channel, $recall_history, '(?:recall|mock|ftfy|fix|clapper)', $recall_nick);
if (not defined $message) {
if (defined $account) {
return "No message for nick $found_nick in channel $recall_channel containing \"$recall_history\"";
return "No message found at index $recall_history for $found_nick in $recall_channel.";
} else {
return "No message in channel $recall_channel containing \"$recall_history\".";
return "No message found at index $recall_history in $recall_channel.";
}
}
} else {
# regex history
$message = $self->{database}->recall_message_by_text($account, $recall_channel, $recall_history, '(?:recall|mock|ftfy|fix|clapper)', $recall_nick);
if (not defined $message) {
if (defined $account) {
return "No message for $found_nick in $recall_channel containing \"$recall_history\"";
} else {
return "No message in $recall_channel containing \"$recall_history\".";
}
}
}
my $context_account;
my ($context_account, $context_nick);
if (defined $recall_context) {
($context_account) = $self->{database}->find_message_account_by_nick($recall_context);
($context_account, $context_nick) = $self->{database}->find_message_account_by_nick($recall_context);
if (not defined $context_account) { return "I don't know anybody named $recall_context."; }
if (not defined $context_account) {
return "I don't know anybody named $recall_context.";
}
# keep only nick portion of hostmask
$context_nick =~ s/!.*$//;
}
my $messages = $self->{database}->get_message_context($message, $recall_before, $recall_after, $recall_count, $recall_history, $context_account);
my $messages = $self->{database}->get_message_context($message, $recall_before, $recall_after, $recall_count, $recall_history, $context_account, $context_nick);
my $max_recall_time = $self->{pbot}->{registry}->get_value('messagehistory', 'max_recall_time');
foreach my $msg (@$messages) {
if ($max_recall_time && time - $msg->{timestamp} > $max_recall_time && not $self->{pbot}->{users}->loggedin_admin($context->{from}, $context->{hostmask})) {
$max_recall_time = duration($max_recall_time);
# optionally limit messages by by a maximum recall duration from the current time, for privacy
if ($max_recall_time && time - $msg->{timestamp} > $max_recall_time
&& not $self->{pbot}->{users}->loggedin_admin($context->{from}, $context->{hostmask}))
{
$max_recall_time = duration $max_recall_time;
$result .= "Sorry, you can not recall messages older than $max_recall_time.";
return $result;
}
my $text = $msg->{msg};
my $ago = concise ago(time - $msg->{timestamp});
my $ago = concise ago (time - $msg->{timestamp});
my $nick;
if (not $raw) {
if ($msg->{hostmask}) {
($nick) = $msg->{hostmask} =~ /^([^!]+)!/;
} else {
$nick = $self->{database}->find_most_recent_hostmask($msg->{id});
($nick) = $nick =~ m/^([^!]+)/;
}
}
if ( $text =~ s/^(NICKCHANGE)\b/changed nick to/
or $text =~ s/^(KICKED|QUIT)\b/lc "$1"/e
or $text =~ s/^MODE ([^ ]+) (.*)/set mode $1 on $2/
or $text =~ s/^(JOIN|PART)\b/lc "$1ed"/e)
{
$text =~ s/^(quit) (.*)/$1 ($2)/; # fix ugly "[nick] quit Quit: Leaving."
$result .= $raw ? "$text\n" : "[$ago] $msg->{nick} $text\n";
} elsif ($text =~ s/^\/me\s+//) {
$result .= $raw ? "$text\n" : "[$ago] * $msg->{nick} $text\n";
} else {
$result .= $raw ? "$text\n" : "[$ago] <$msg->{nick}> $text\n";
$text =~ s/^(quit) (.*)/$1 ($2)/; # fix ugly "[nick] quit Quit: Leaving."
$result .= $raw ? "$text\n" : "[$ago] $nick $text\n";
}
elsif ($text =~ s/^\/me\s+//) {
$result .= $raw ? "$text\n" : "[$ago] * $nick $text\n";
}
else {
$result .= $raw ? "$text\n" : "[$ago] <$nick> $text\n";
}
}
}

View File

@ -139,7 +139,8 @@ CREATE TABLE IF NOT EXISTS Messages (
channel TEXT COLLATE NOCASE,
msg TEXT COLLATE NOCASE,
timestamp NUMERIC,
mode INTEGER
mode INTEGER,
hostmask TEXT COLLATE NOCASE
)
SQL
@ -863,23 +864,24 @@ sub get_hostmasks_for_nickserv {
}
sub add_message {
my ($self, $id, $mask, $channel, $message) = @_;
#$self->{pbot}->{logger}->log("Adding message [$id][$mask][$channel][$message->{msg}][$message->{timestamp}][$message->{mode}]\n");
my ($self, $id, $hostmask, $channel, $message) = @_;
eval {
my $sth = $self->{dbh}->prepare('INSERT INTO Messages VALUES (?, ?, ?, ?, ?)');
$sth->execute($id, $channel, $message->{msg}, $message->{timestamp}, $message->{mode});
my $sth = $self->{dbh}->prepare('INSERT INTO Messages VALUES (?, ?, ?, ?, ?, ?)');
$sth->execute($id, $channel, $message->{msg}, $message->{timestamp}, $message->{mode}, $hostmask);
$self->{new_entries}++;
};
$self->{pbot}->{logger}->log($@) if $@;
$self->update_channel_data($id, $channel, {last_seen => $message->{timestamp}});
$self->update_hostmask_data($mask, {last_seen => $message->{timestamp}});
$self->update_channel_data($id, $channel, { last_seen => $message->{timestamp }});
$self->update_hostmask_data($hostmask, { last_seen => $message->{timestamp }});
}
sub get_recent_messages {
my ($self, $id, $channel, $limit, $mode, $nick) = @_;
$limit = 25 if not defined $limit;
$limit //= 25;
$channel = lc $channel;
@ -887,65 +889,55 @@ sub get_recent_messages {
$mode_query = "AND mode = $mode" if defined $mode;
my $messages = eval {
my $sql = "SELECT msg, mode, timestamp FROM Messages WHERE ";
my $sql = "SELECT * FROM Messages WHERE ";
my %seen_id;
my %akas;
if (defined $mode and $mode == $self->{pbot}->{messagehistory}->{MSG_NICKCHANGE}) { %akas = $self->get_also_known_as($nick); }
else { $akas{'this'} = {id => $id, type => $self->{alias_type}->{STRONG}, nickchange => 0}; }
if (defined $mode and $mode == $self->{pbot}->{messagehistory}->{MSG_NICKCHANGE}) {
%akas = $self->get_also_known_as($nick);
} else {
$akas{$id} = {
id => $id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
my $ids;
my %seen_id;
my $or = '';
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$ids .= "${or}id = ?";
$or = ' OR ';
$seen_id{$akas{$aka}->{id}} = 1;
}
my $ids = join " OR ", map { "id = ?" } keys %seen_id;
$sql .= "($ids) AND channel = ? $mode_query ORDER BY timestamp ASC LIMIT ? OFFSET (SELECT COUNT(*) FROM Messages WHERE ($ids) AND channel = ? $mode_query) - ?";
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
%seen_id = ();
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$sth->bind_param($param++, $akas{$aka}->{id});
}
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $channel);
$sth->bind_param($param++, $limit);
%seen_id = ();
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$sth->bind_param($param++, $akas{$aka}->{id});
}
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $channel);
$sth->bind_param($param, $limit);
$sth->execute();
$sth->execute;
return $sth->fetchall_arrayref({});
};
$self->{pbot}->{logger}->log($@) if $@;
return $messages;
}
sub get_recent_messages_from_channel {
my ($self, $channel, $limit, $mode, $direction) = @_;
$limit = 25 if not defined $limit;
$direction = 'ASC' if not defined $direction;
$limit //= 25;
$direction //= 'ASC';
$channel = lc $channel;
@ -953,7 +945,7 @@ sub get_recent_messages_from_channel {
$mode_query = "AND mode = $mode" if defined $mode;
my $messages = eval {
my $sql = "SELECT id, msg, mode, timestamp FROM Messages WHERE channel = ? $mode_query ORDER BY timestamp $direction LIMIT ?";
my $sql = "SELECT * FROM Messages WHERE channel = ? $mode_query ORDER BY timestamp $direction LIMIT ?";
my $sth = $self->{dbh}->prepare($sql);
$sth->execute($channel, $limit);
return $sth->fetchall_arrayref({});
@ -963,7 +955,39 @@ sub get_recent_messages_from_channel {
}
sub get_message_context {
my ($self, $message, $before, $after, $count, $text, $context_id) = @_;
my ($self, $message, $before, $after, $count, $text, $context_id, $context_nick) = @_;
my %seen_id;
my $ids = '';
my $sql = 'SELECT * FROM Messages WHERE channel = ? ';
if (defined $context_id) {
my %akas;
if (defined $context_nick) {
%akas = $self->get_also_known_as($context_nick);
} else {
$akas{$context_id} = {
id => $context_id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
}
$ids = join " OR ", map { "id = ?" } keys %seen_id;
$ids = "AND ($ids) ";
}
$sql .= $ids;
my ($messages_before, $messages_after, $messages_count);
@ -973,70 +997,50 @@ sub get_message_context {
$search =~ s/\?/_/g;
$messages_count = eval {
my $sth;
if (defined $context_id) {
$sth = $self->{dbh}->prepare(
'SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND msg LIKE ? ESCAPE "\" AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?');
$sth->bind_param(1, $context_id);
$sth->bind_param(2, $message->{channel});
$sth->bind_param(3, $search);
$sth->bind_param(4, $message->{timestamp});
$sth->bind_param(5, $count - 1);
} else {
$sth = $self->{dbh}
->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND msg LIKE ? ESCAPE "\" AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?');
$sth->bind_param(1, $message->{channel});
$sth->bind_param(2, $search);
$sth->bind_param(3, $message->{timestamp});
$sth->bind_param(4, $count - 1);
}
$sth->execute();
$sql .= 'AND msg LIKE ? ESCAPE "\" AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $message->{channel});
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $search);
$sth->bind_param($param++, $message->{timestamp});
$sth->bind_param($param++, $count - 1);
$sth->execute;
return [reverse @{$sth->fetchall_arrayref({})}];
};
$self->{pbot}->{logger}->log($@) if $@;
}
if (defined $before and $before > 0) {
$messages_before = eval {
my $sth;
if (defined $context_id) {
$sth = $self->{dbh}
->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?');
$sth->bind_param(1, $context_id);
$sth->bind_param(2, $message->{channel});
$sth->bind_param(3, $message->{timestamp});
$sth->bind_param(4, $before);
} else {
$sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?');
$sth->bind_param(1, $message->{channel});
$sth->bind_param(2, $message->{timestamp});
$sth->bind_param(3, $before);
}
$sth->execute();
$sql .= ' AND timestamp < ? AND mode = 0 ORDER BY timestamp DESC LIMIT ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $message->{channel});
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $message->{timestamp});
$sth->bind_param($param++, $before);
$sth->execute;
return [reverse @{$sth->fetchall_arrayref({})}];
};
$self->{pbot}->{logger}->log($@) if $@;
}
if (defined $after and $after > 0) {
$messages_after = eval {
my $sth;
if (defined $context_id) {
$sth = $self->{dbh}
->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND timestamp > ? AND mode = 0 ORDER BY timestamp ASC LIMIT ?');
$sth->bind_param(1, $context_id);
$sth->bind_param(2, $message->{channel});
$sth->bind_param(3, $message->{timestamp});
$sth->bind_param(4, $after);
} else {
$sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND timestamp > ? AND mode = 0 ORDER BY timestamp ASC LIMIT ?');
$sth->bind_param(1, $message->{channel});
$sth->bind_param(2, $message->{timestamp});
$sth->bind_param(3, $after);
}
$sth->execute();
$sql .= ' AND timestamp > ? AND mode = 0 ORDER BY timestamp ASC LIMIT ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $message->{channel});
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $message->{timestamp});
$sth->bind_param($param++, $after);
$sth->execute;
return $sth->fetchall_arrayref({});
};
$self->{pbot}->{logger}->log($@) if $@;
}
@ -1046,75 +1050,54 @@ sub get_message_context {
push(@messages, $message);
push(@messages, @$messages_after) if defined $messages_after;
my %nicks;
foreach my $msg (@messages) {
if (not exists $nicks{$msg->{id}}) {
my $hostmask = $self->find_most_recent_hostmask($msg->{id});
my ($nick) = $hostmask =~ m/^([^!]+)/;
$nicks{$msg->{id}} = $nick;
}
$msg->{nick} = $nicks{$msg->{id}};
}
return \@messages;
}
sub recall_message_by_count {
my ($self, $id, $channel, $count, $ignore_command, $use_aliases) = @_;
my $messages;
my $messages = eval {
my $sql = 'SELECT * FROM Messages WHERE ';
my %seen_id;
if (defined $id) {
my %akas;
if (defined $id) {
$messages = eval {
if (defined $use_aliases) {
my %akas = $self->get_also_known_as($use_aliases);
my %seen_id;
my $ids;
my $or = '';
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$ids .= "${or}id = ?";
$or = ' OR ';
}
my $sql = "SELECT id, msg, mode, timestamp, channel FROM Messages WHERE ($ids) AND channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?";
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
%seen_id = ();
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$sth->bind_param($param++, $akas{$aka}->{id});
}
$sth->bind_param($param++, $channel);
$sth->bind_param($param++, $count);
$sth->execute();
return $sth->fetchall_arrayref({});
%akas = $self->get_also_known_as($use_aliases);
} else {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?');
$sth->bind_param(1, $id);
$sth->bind_param(2, $channel);
$sth->bind_param(3, $count);
$sth->execute();
return $sth->fetchall_arrayref({});
$akas{$id} = {
id => $id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
};
} else {
$messages = eval {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?');
$sth->execute($channel, $count);
return $sth->fetchall_arrayref({});
};
}
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
}
my $ids = join " OR ", map { "id = ?" } keys %seen_id;
$sql .= "($ids) AND ";
}
$sql .= 'channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $channel);
$sth->bind_param($param++, $count);
$sth->execute;
return $sth->fetchall_arrayref({});
};
$self->{pbot}->{logger}->log($@) if $@;
@ -1125,33 +1108,64 @@ sub recall_message_by_count {
next if $message->{msg} =~ m/^$botnick.? $ignore_command/ or $message->{msg} =~ m/^$bot_trigger$ignore_command/;
return $message;
}
return undef;
}
return $messages->[0];
}
sub recall_message_by_text {
my ($self, $id, $channel, $text, $ignore_command) = @_;
my ($self, $id, $channel, $text, $ignore_command, $use_aliases) = @_;
my $search = "%$text%";
$search =~ s/\*/%/g;
$search =~ s/\?/_/g;
my $messages;
my $messages = eval {
my $sql = 'SELECT * FROM Messages WHERE channel = ? AND msg LIKE ? ESCAPE "\" ';
if (defined $id) {
$messages = eval {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND msg LIKE ? ESCAPE "\" ORDER BY timestamp DESC LIMIT 10');
$sth->execute($id, $channel, $search);
return $sth->fetchall_arrayref({});
};
} else {
$messages = eval {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND msg LIKE ? ESCAPE "\" ORDER BY timestamp DESC LIMIT 10');
$sth->execute($channel, $search);
return $sth->fetchall_arrayref({});
};
}
my %seen_id;
if (defined $id) {
my %akas;
if (defined $use_aliases) {
%akas = $self->get_also_known_as($use_aliases);
} else {
$akas{$id} = {
id => $id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
}
my $ids = join " OR ", map { "id = ?" } keys %seen_id;
$sql .= "AND ($ids) ";
}
$sql .= 'ORDER BY timestamp DESC LIMIT 10';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $channel);
$sth->bind_param($param++, $search);
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->execute;
return $sth->fetchall_arrayref({});
};
$self->{pbot}->{logger}->log($@) if $@;
@ -1165,29 +1179,61 @@ sub recall_message_by_text {
or $message->{msg} =~ m/^\s*$ignore_command.? $botnick$/i;
return $message;
}
return undef;
}
return $messages->[0];
}
sub get_random_message {
my ($self, $id, $channel) = @_;
my ($self, $id, $channel, $use_aliases) = @_;
my $message;
my $message = eval {
my $sql = 'SELECT * FROM Messages WHERE channel = ? AND mode = ? ';
if (defined $id) {
$message = eval {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND mode = ? ORDER BY RANDOM() LIMIT 1');
$sth->execute($id, $channel, $self->{pbot}->{messagehistory}->{MSG_CHAT});
return $sth->fetchrow_hashref;
};
} else {
$message = eval {
my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND mode = ? ORDER BY RANDOM() LIMIT 1');
$sth->execute($channel, $self->{pbot}->{messagehistory}->{MSG_CHAT});
return $sth->fetchrow_hashref;
};
}
my %seen_id;
if (defined $id) {
my %akas;
if (defined $use_aliases) {
%akas = $self->get_also_known_as($use_aliases);
} else {
$akas{$id} = {
id => $id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
}
my $ids = join " OR ", map { "id = ?" } keys %seen_id;
$sql .= "AND ($ids) ";
}
$sql .= 'ORDER BY RANDOM() LIMIT 1';
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $channel);
$sth->bind_param($param++, $self->{pbot}->{messagehistory}->{MSG_CHAT});
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->execute;
return $sth->fetchrow_hashref;
};
$self->{pbot}->{logger}->log($@) if $@;
@ -1198,46 +1244,44 @@ sub get_max_messages {
my ($self, $id, $channel, $use_aliases) = @_;
my $count = eval {
my $sql = "SELECT COUNT(*) FROM Messages WHERE channel = ? AND ";
my $sql = 'SELECT COUNT(*) FROM Messages WHERE channel = ? AND ';
my %akas;
if (defined $use_aliases) { %akas = $self->get_also_known_as($use_aliases); }
else { $akas{'this'} = {id => $id, type => $self->{alias_type}->{STRONG}, nickchange => 0}; }
my $ids;
if (defined $use_aliases) {
%akas = $self->get_also_known_as($use_aliases);
} else {
$akas{$id} = {
id => $id,
type => $self->{alias_type}->{STRONG},
nickchange => 0,
};
}
my %seen_id;
my $or = '';
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
$ids .= "${or}id = ?";
$or = ' OR ';
$seen_id{$akas{$aka}->{id}} = 1;
}
my $ids = join " OR ", map { "id = ?" } keys %seen_id;
$sql .= "($ids)";
my $sth = $self->{dbh}->prepare($sql);
my $param = 1;
$sth->bind_param($param++, $channel);
%seen_id = ();
foreach my $aka (keys %akas) {
next if $akas{$aka}->{type} == $self->{alias_type}->{WEAK};
next if $akas{$aka}->{nickchange} == 1;
next if exists $seen_id{$akas{$aka}->{id}};
$seen_id{$akas{$aka}->{id}} = 1;
map { $sth->bind_param($param++, $_) } keys %seen_id;
$sth->bind_param($param++, $akas{$aka}->{id});
}
$sth->execute();
my $row = $sth->fetchrow_hashref();
$sth->finish();
return $row->{'COUNT(*)'};
$sth->execute;
return $sth->fetchrow_hashref->{'COUNT(*)'};
};
$self->{pbot}->{logger}->log($@) if $@;
$count = 0 if not defined $count;
return $count;