3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-12-24 03:33:06 +01:00

Improve handling of interpreter result and module execution

This commit is contained in:
Pragmatic Software 2014-03-14 10:05:11 +00:00
parent 4a110848e9
commit 36b7e1fa6f
4 changed files with 103 additions and 87 deletions

View File

@ -38,12 +38,11 @@ sub initialize {
Carp::croak("Missing pbot reference to PBot::FactoidModuleLauncher");
}
$self->{child} = 0;
$self->{pbot} = $pbot;
}
sub execute_module {
my ($self, $from, $tonick, $nick, $user, $host, $keyword, $arguments) = @_;
my ($self, $from, $tonick, $nick, $user, $host, $command, $keyword, $arguments, $preserve_whitespace) = @_;
my $text;
$arguments = "" if not defined $arguments;
@ -51,7 +50,8 @@ sub execute_module {
my ($channel, $trigger) = $self->{pbot}->factoids->find_factoid($from, $keyword);
if(not defined $trigger) {
return "/msg $nick Failed to find module for '$keyword' in channel $from\n";
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", "/msg $nick Failed to find module for '$keyword' in channel $from\n", 1, 0);
return;
}
my $module = $self->{pbot}->factoids->factoids->hash->{$channel}->{$trigger}->{action};
@ -110,16 +110,21 @@ sub execute_module {
}
}
pipe(my $reader, my $writer);
my $pid = fork;
if(not defined $pid) {
$self->{pbot}->logger->log("Could not fork module: $!\n");
return "/me groans loudly.";
close $reader;
close $writer;
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", "/me groans loudly.\n", 1, 0);
return;
}
# FIXME -- add check to ensure $module} exists
# FIXME -- add check to ensure $module exists
if($pid == 0) { # start child block
$self->{child} = 1; # set to be killed after returning
close $reader;
# don't quit the IRC client when the child dies
no warnings;
@ -142,25 +147,37 @@ sub execute_module {
$text =~ s/^\/([^ ]+) \Q$nick\E:\s+/\/$1 /;
$text =~ s/^\Q$nick\E:\s+//;
return "$tonick: $text";
} else {
return "";
print $writer "$from $tonick: $text\n";
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", "$tonick: $text", 0, $preserve_whitespace);
}
exit 0;
} else {
if(exists $self->{pbot}->factoids->factoids->hash->{$channel}->{$trigger}->{add_nick} and $self->{pbot}->factoids->factoids->hash->{$channel}->{$trigger}->{add_nick} != 0) {
return "$nick: $text";
print $writer "$from $nick: $text";
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", "$nick: $text", 0, $preserve_whitespace);
} else {
return $text;
print $writer "$from $text";
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", $text, 0, $preserve_whitespace);
}
exit 0;
}
return "/me moans loudly."; # er, didn't execute the module?
# er, didn't execute the module?
print $writer "$from /me moans loudly.\n";
$self->{pbot}->{interpreter}->handle_result($from, $nick, $user, $host, $command, "$keyword $arguments", "/me moans loudly.", 0, 0);
exit 0;
} # end child block
else {
$self->{child} = 0;
close $writer;
$self->{pbot}->{select_handler}->add_reader($reader, sub { $self->module_pipe_reader(@_) });
return "";
}
return ""; # child returns bot command, not parent -- so return blank/no command
}
sub module_pipe_reader {
my ($self, $buf) = @_;
my ($channel, $text) = split / /, $buf, 2;
$self->{pbot}->antiflood->check_flood($channel, $self->{pbot}->{botnick}, $self->{pbot}->{username}, 'localhost', $text, 0, 0, 0);
}
1;

View File

@ -388,7 +388,7 @@ sub interpreter {
$self->factoids->hash->{$channel}->{$keyword}->{last_referenced_on} = gettimeofday;
$self->factoids->hash->{$channel}->{$keyword}->{last_referenced_in} = $from || "stdin";
return $ref_from . $self->{factoidmodulelauncher}->execute_module($from, $tonick, $nick, $user, $host, $keyword, $arguments);
return $ref_from . $self->{factoidmodulelauncher}->execute_module($from, $tonick, $nick, $user, $host, "$keyword $arguments", $keyword, $arguments, 1);
}
elsif($self->factoids->hash->{$channel}->{$keyword}->{type} eq 'text') {
$self->{pbot}->logger->log("Found factoid\n");

View File

@ -87,7 +87,7 @@ sub process_line {
my $self = shift;
my ($from, $nick, $user, $host, $text) = @_;
my ($command, $args, $result);
my $command;
my $has_url;
my $has_code;
my $nick_override;
@ -133,80 +133,79 @@ sub process_line {
}
if(defined $has_url) {
$result = $self->{pbot}->factoids->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, "title", "$nick http://$has_url");
$self->{pbot}->factoids->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, $text, "title", "$nick http://$has_url", $preserve_whitespace);
} elsif(defined $has_code) {
$result = $self->{pbot}->factoids->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, "compiler_block", (defined $nick_override ? $nick_override : $nick) . " $from $has_code }");
$self->{pbot}->factoids->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, $text, "compiler_block", (defined $nick_override ? $nick_override : $nick) . " $from $has_code }", $preserve_whitespace);
} else {
$result = $self->interpret($from, $nick, $user, $host, 1, $command);
}
if(defined $result && length $result > 0) {
my $original_result = $result;
$result =~ s/[\n\r]+/ /g;
if($preserve_whitespace == 0 && defined $command) {
my ($cmd, $args) = split / /, $command, 2;
#$self->{pbot}->logger->log("calling find_factoid in Interpreter.pm, process_line() for preserve_whitespace\n");
my ($chan, $trigger) = $self->{pbot}->factoids->find_factoid($from, $cmd, $args, 0, 1);
if(defined $trigger) {
$preserve_whitespace = $self->{pbot}->factoids->factoids->hash->{$chan}->{$trigger}->{preserve_whitespace};
$preserve_whitespace = 0 if not defined $preserve_whitespace;
}
}
$result =~ s/\s+/ /g unless $preserve_whitespace;
if(length $result > $pbot->max_msg_len) {
my $link = paste_sprunge("[" . (defined $from ? $from : "stdin") . "] <$nick> $text\n\n$original_result");
my $trunc = "... [truncated; see $link for full text.]";
$pbot->logger->log("Message truncated -- pasted to $link\n");
my $trunc_len = length $result < $pbot->max_msg_len ? length $result : $pbot->max_msg_len;
$result = substr($result, 0, $trunc_len);
substr($result, $trunc_len - length $trunc) = $trunc;
}
$pbot->logger->log("Final result: $result\n");
if($result =~ s/^\/say\s+//i) {
$pbot->conn->privmsg($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0);
} elsif($result =~ s/^\/me\s+//i) {
$pbot->conn->me($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', '/me ' . $result, 0, 0, 0);
} elsif($result =~ s/^\/msg\s+([^\s]+)\s+//i) {
my $to = $1;
if($to =~ /,/) {
$pbot->logger->log("[HACK] Possible HACK ATTEMPT /msg multiple users: [$nick!$user\@$host] [$command] [$result]\n");
}
elsif($to =~ /.*serv$/i) {
$pbot->logger->log("[HACK] Possible HACK ATTEMPT /msg *serv: [$nick!$user\@$host] [$command] [$result]\n");
}
elsif($result =~ s/^\/me\s+//i) {
$pbot->conn->me($to, $result) if $to !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($to, $pbot->{botnick}, $pbot->{username}, 'localhost', '/me ' . $result, 0, 0, 0);
} else {
$result =~ s/^\/say\s+//i;
$pbot->conn->privmsg($to, $result) if $to !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($to, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0);
}
} else {
$pbot->conn->privmsg($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0);
}
}
$pbot->logger->log("---------------------------------------------\n");
# TODO: move this to FactoidModuleLauncher somehow, completely out of Interpreter!
if($pbot->factoids->{factoidmodulelauncher}->{child} != 0) {
# if this process is a child, it must die now
$pbot->logger->log("Terminating module.\n");
exit 0;
$self->handle_result($from, $nick, $user, $host, $text, $command, $self->interpret($from, $nick, $user, $host, 1, $command), 1, $preserve_whitespace);
}
}
}
sub handle_result {
my ($self, $from, $nick, $user, $host, $text, $command, $result, $checkflood, $preserve_whitespace) = @_;
my ($pbot, $mynick) = ($self->{pbot}, $self->{pbot}->{botnick});
if(not defined $result or length $result == 0) {
return;
}
my $original_result = $result;
$result =~ s/[\n\r]+/ /g;
if($preserve_whitespace == 0 && defined $command) {
my ($cmd, $args) = split / /, $command, 2;
#$self->{pbot}->logger->log("calling find_factoid in Interpreter.pm, process_line() for preserve_whitespace\n");
my ($chan, $trigger) = $self->{pbot}->factoids->find_factoid($from, $cmd, $args, 0, 1);
if(defined $trigger) {
$preserve_whitespace = $self->{pbot}->factoids->factoids->hash->{$chan}->{$trigger}->{preserve_whitespace};
$preserve_whitespace = 0 if not defined $preserve_whitespace;
}
}
$result =~ s/\s+/ /g unless $preserve_whitespace;
if(length $result > $pbot->max_msg_len) {
my $link = paste_sprunge("[" . (defined $from ? $from : "stdin") . "] <$nick> $text\n\n$original_result");
my $trunc = "... [truncated; see $link for full text.]";
$pbot->logger->log("Message truncated -- pasted to $link\n");
my $trunc_len = length $result < $pbot->max_msg_len ? length $result : $pbot->max_msg_len;
$result = substr($result, 0, $trunc_len);
substr($result, $trunc_len - length $trunc) = $trunc;
}
$pbot->logger->log("Final result: [$result]\n");
if($result =~ s/^\/say\s+//i) {
$pbot->conn->privmsg($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0) if $checkflood;
} elsif($result =~ s/^\/me\s+//i) {
$pbot->conn->me($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', '/me ' . $result, 0, 0, 0) if $checkflood;
} elsif($result =~ s/^\/msg\s+([^\s]+)\s+//i) {
my $to = $1;
if($to =~ /,/) {
$pbot->logger->log("[HACK] Possible HACK ATTEMPT /msg multiple users: [$nick!$user\@$host] [$command] [$result]\n");
}
elsif($to =~ /.*serv$/i) {
$pbot->logger->log("[HACK] Possible HACK ATTEMPT /msg *serv: [$nick!$user\@$host] [$command] [$result]\n");
}
elsif($result =~ s/^\/me\s+//i) {
$pbot->conn->me($to, $result) if $to !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($to, $pbot->{botnick}, $pbot->{username}, 'localhost', '/me ' . $result, 0, 0, 0) if $checkflood;
} else {
$result =~ s/^\/say\s+//i;
$pbot->conn->privmsg($to, $result) if $to !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($to, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0) if $checkflood;
}
} else {
$pbot->conn->privmsg($from, $result) if defined $from && $from !~ /\Q$mynick\E/i;
$pbot->antiflood->check_flood($from, $pbot->{botnick}, $pbot->{username}, 'localhost', $result, 0, 0, 0) if $checkflood;
}
$pbot->logger->log("---------------------------------------------\n");
}
sub interpret {
my $self = shift;
my ($from, $nick, $user, $host, $count, $command, $tonick) = @_;

View File

@ -13,8 +13,8 @@ use warnings;
# These are set automatically by the build/commit script
use constant {
BUILD_NAME => "PBot",
BUILD_REVISION => 524,
BUILD_DATE => "2014-03-13",
BUILD_REVISION => 525,
BUILD_DATE => "2014-03-14",
};
1;