diff --git a/PBot/MessageHistory.pm b/PBot/MessageHistory.pm index acee9328..02503207 100644 --- a/PBot/MessageHistory.pm +++ b/PBot/MessageHistory.pm @@ -123,7 +123,7 @@ sub recall_message { return ""; } - my $usage = 'Usage: recall [nick [history [channel]]] [-c,channel ] [-t,text,h,history ] [+ ...]'; + my $usage = 'Usage: recall [nick [history [channel]]] [-c,channel ] [-t,text,h,history ] [-b,before ] [-a,after ] [+ ...]'; if(not defined $arguments or not length $arguments) { return $usage; @@ -142,11 +142,13 @@ sub recall_message { my $recall_text; foreach my $recall (@recalls) { - my ($recall_nick, $recall_history, $recall_channel); + my ($recall_nick, $recall_history, $recall_channel, $recall_before, $recall_after); my ($ret, $args) = GetOptionsFromString($recall, - 'channel|c=s' => \$recall_channel, - 'text|t|history|h=s' => \$recall_history); + 'channel|c=s' => \$recall_channel, + 'text|t|history|h=s' => \$recall_history, + 'before|b=s' => \$recall_before, + 'after|a=s' => \$recall_after); return "$getopt_error -- $usage" if defined $getopt_error; @@ -156,6 +158,8 @@ sub recall_message { $recall_nick = shift @$args; $recall_history = shift @$args if not defined $recall_history; $recall_channel = shift @$args if not defined $recall_channel; + $recall_before = 0 if not defined $recall_before; + $recall_after = 0 if not defined $recall_after; # swap nick and channel if recall nick looks like channel and channel wasn't specified if(not $channel_arg and $recall_nick =~ m/^#/) { @@ -220,28 +224,30 @@ sub recall_message { } } - if(defined $message->{id}) { - my $hostmask = $self->{database}->find_most_recent_hostmask($message->{id}); - ($found_nick) = $hostmask =~ m/^([^!]+)/; - $recall_nick = $found_nick; + if ($recall_before + $recall_after > 200) { + return "You may only select 200 lines of surrounding context."; } - $self->{pbot}->{logger}->log("$nick ($from) recalled <$recall_nick/$recall_channel> $message->{msg}\n"); + my $messages = $self->{database}->get_message_context($message, $recall_before, $recall_after); - my $text = $message->{msg}; - my $ago = ago(gettimeofday - $message->{timestamp}); + foreach my $msg (@$messages) { + $self->{pbot}->{logger}->log("$nick ($from) recalled <$msg->{nick}/$msg->{channel}> $msg->{msg}\n"); - if(not defined $recall_text) { - if($text =~ s/^\/me\s+// or $text =~ m/^KICKED /) { - $recall_text = "[$ago] * $found_nick $text"; + my $text = $msg->{msg}; + my $ago = ago(gettimeofday - $msg->{timestamp}); + + if(not defined $recall_text) { + if($text =~ s/^\/me\s+// or $text =~ m/^KICKED /) { + $recall_text = "[$ago] * $msg->{nick} $text\n"; + } else { + $recall_text = "[$ago] <$msg->{nick}> $text\n"; + } } else { - $recall_text = "[$ago] <$found_nick> $text"; - } - } else { - if($text =~ s/^\/me\s+// or $text =~ m/^KICKED /) { - $recall_text .= " [$ago] * $found_nick $text"; - } else { - $recall_text .= " [$ago] <$found_nick> $text"; + if($text =~ s/^\/me\s+// or $text =~ m/^KICKED /) { + $recall_text .= "[$ago] * $msg->{nick} $text\n"; + } else { + $recall_text .= "[$ago] <$msg->{nick}> $text\n"; + } } } } diff --git a/PBot/MessageHistory_SQLite.pm b/PBot/MessageHistory_SQLite.pm index 0ce4ed2c..b1c07e9d 100644 --- a/PBot/MessageHistory_SQLite.pm +++ b/PBot/MessageHistory_SQLite.pm @@ -441,6 +441,53 @@ SQL return $messages; } +sub get_message_context { + my ($self, $message, $before, $after) = @_; + + my ($messages_before, $messages_after); + + if (defined $before and $before > 0) { + $messages_before = eval { + my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND timestamp < ? AND mode != 1 ORDER BY timestamp DESC LIMIT ?'); + $sth->bind_param(1, $message->{channel}); + $sth->bind_param(2, $message->{timestamp}); + $sth->bind_param(3, $before); + $sth->execute(); + return [reverse @{$sth->fetchall_arrayref({})}]; + }; + $self->{pbot}->{logger}->log($@) if $@; + } + + if (defined $after and $after > 0) { + $messages_after = eval { + my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND timestamp > ? AND mode != 1 LIMIT ?'); + $sth->bind_param(1, $message->{channel}); + $sth->bind_param(2, $message->{timestamp}); + $sth->bind_param(3, $after); + $sth->execute(); + return $sth->fetchall_arrayref({}); + }; + $self->{pbot}->{logger}->log($@) if $@; + } + + my @messages; + push(@messages, @$messages_before) if defined $messages_before; + 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) = @_; @@ -448,7 +495,7 @@ sub recall_message_by_count { if(defined $id) { $messages = eval { - my $sth = $self->{dbh}->prepare('SELECT msg, mode, timestamp FROM Messages WHERE id = ? AND channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?'); + 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); @@ -457,7 +504,7 @@ sub recall_message_by_count { }; } else { $messages = eval { - my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp FROM Messages WHERE channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?'); + my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? ORDER BY timestamp DESC LIMIT 10 OFFSET ?'); $sth->bind_param(1, $channel); $sth->bind_param(2, $count); $sth->execute(); @@ -489,7 +536,7 @@ sub recall_message_by_text { if(defined $id) { $messages = eval { - my $sth = $self->{dbh}->prepare('SELECT msg,mode,timestamp FROM Messages WHERE id = ? AND channel = ? AND msg LIKE ? ORDER BY timestamp DESC LIMIT 10'); + my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE id = ? AND channel = ? AND msg LIKE ? ORDER BY timestamp DESC LIMIT 10'); $sth->bind_param(1, $id); $sth->bind_param(2, $channel); $sth->bind_param(3, "%$text%"); @@ -498,7 +545,7 @@ sub recall_message_by_text { }; } else { $messages = eval { - my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp FROM Messages WHERE channel = ? AND msg LIKE ? ORDER BY timestamp DESC LIMIT 10'); + my $sth = $self->{dbh}->prepare('SELECT id, msg, mode, timestamp, channel FROM Messages WHERE channel = ? AND msg LIKE ? ORDER BY timestamp DESC LIMIT 10'); $sth->bind_param(1, $channel); $sth->bind_param(2, "%$text%"); $sth->execute();