diff --git a/PBot/Commands.pm b/PBot/Commands.pm index b0b24450..bd6b7ee1 100644 --- a/PBot/Commands.pm +++ b/PBot/Commands.pm @@ -86,7 +86,7 @@ sub exists { sub interpreter { my $self = shift; - my ($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick) = @_; + my ($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick, $unused, $referenced) = @_; my $result; my $pbot = $self->{pbot}; @@ -98,8 +98,13 @@ sub interpreter { foreach my $ref (@{ $self->{handlers} }) { if($ref->{name} eq $keyword) { if($level >= $ref->{level}) { - return &{ $ref->{subref} }($from, $nick, $user, $host, $arguments); + my $result = &{ $ref->{subref} }($from, $nick, $user, $host, $arguments); + if ($referenced) { + return undef if $result =~ m/(?:usage:|no results)/i; + } + return $result; } else { + return undef if $referenced; if($level == 0) { return "/msg $nick You must login to use this command."; } else { diff --git a/PBot/FactoidModuleLauncher.pm b/PBot/FactoidModuleLauncher.pm index bccdb9e5..b16c5348 100644 --- a/PBot/FactoidModuleLauncher.pm +++ b/PBot/FactoidModuleLauncher.pm @@ -39,7 +39,7 @@ sub initialize { } sub execute_module { - my ($self, $from, $tonick, $nick, $user, $host, $command, $keyword, $arguments, $preserve_whitespace) = @_; + my ($self, $from, $tonick, $nick, $user, $host, $command, $keyword, $arguments, $preserve_whitespace, $referenced) = @_; my $text; $arguments = "" if not defined $arguments; @@ -152,6 +152,10 @@ sub execute_module { $text = `./$module $arguments 2>> $module-stderr`; + if ($referenced) { + exit 0 if $text =~ m/(?:no results)/i; + } + if(defined $tonick) { $self->{pbot}->{logger}->log("($from): $nick!$user\@$host) sent to $tonick\n"); if(defined $text && length $text > 0) { diff --git a/PBot/Factoids.pm b/PBot/Factoids.pm index b8e57b4d..b70734b4 100644 --- a/PBot/Factoids.pm +++ b/PBot/Factoids.pm @@ -454,11 +454,11 @@ sub expand_action_arguments { sub interpreter { my $self = shift; - my ($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick, $ref_from) = @_; + my ($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick, $ref_from, $referenced) = @_; my ($result, $channel); my $pbot = $self->{pbot}; - #$self->{pbot}->{logger}->log("enter factoid interpreter [$keyword][" . (defined $arguments ? $arguments : '') . "]\n"); + #$self->{pbot}->{logger}->log("enter factoid interpreter [$keyword][" . (defined $arguments ? $arguments : '') . "] referenced = $referenced\n"); return undef if not length $keyword or $depth > $self->{pbot}->{registry}->get_value('interpreter', 'max_recursion'); $from = lc $from; @@ -508,22 +508,24 @@ sub interpreter { # if multiple channels have this keyword, then ask user to disambiguate if($found > 1) { + return undef if $referenced; return $ref_from . "Ambiguous keyword '$original_keyword' exists in multiple channels (use 'fact ' to choose one): $chans"; } # if there's just one other channel that has this keyword, trigger that instance elsif($found == 1) { $pbot->{logger}->log("Found '$original_keyword' as '$fwd_trig' in [$fwd_chan]\n"); - return $pbot->{factoids}->interpreter($from, $nick, $user, $host, ++$depth, $fwd_trig, $arguments, $tonick, $fwd_chan); + return $pbot->{factoids}->interpreter($from, $nick, $user, $host, ++$depth, $fwd_trig, $arguments, $tonick, $fwd_chan, $referenced); } # otherwise keyword hasn't been found, display similiar matches for all channels else { # if a non-nick argument was supplied, e.g., a sentence using the bot's nick, don't say anything - return "" if length $arguments and not $self->{pbot}->{nicklist}->is_present($from, $arguments); + return undef if length $arguments and not $self->{pbot}->{nicklist}->is_present($from, $arguments); my $matches = $self->{commands}->factfind($from, $nick, $user, $host, quotemeta $original_keyword); # found factfind matches if($matches !~ m/^No factoids/) { + return undef if $referenced; return "No such factoid '$original_keyword'; $matches"; } @@ -532,11 +534,14 @@ sub interpreter { # don't say anything if nothing similiar was found return undef if $matches eq 'none'; + return undef if $referenced; return $ref_from . "No such factoid '$original_keyword'; did you mean $matches?"; } } + return undef if $referenced and $self->{factoids}->hash->{$channel}->{$keyword}->{noembed}; + if(exists $self->{factoids}->hash->{$channel}->{$keyword}->{last_referenced_on}) { if(exists $self->{factoids}->hash->{$channel}->{$keyword}->{last_referenced_in}) { if($self->{factoids}->hash->{$channel}->{$keyword}->{last_referenced_in} eq $from) { @@ -567,7 +572,7 @@ sub interpreter { } else { if ($self->{factoids}->hash->{$channel}->{$keyword}->{type} eq 'text') { my $target = $self->{pbot}->{nicklist}->is_present($from, $arguments); - if ($target) { + if ($target and $action !~ /\$nick/) { if ($action !~ m/^(\/[^ ]+) /) { $action =~ s/^/\/say $target: $keyword is / unless defined $tonick; } else { @@ -601,7 +606,7 @@ sub interpreter { } $pbot->{logger}->log("[" . (defined $from ? $from : "stdin") . "] ($nick!$user\@$host) [$keyword] aliased to: [$command]\n"); - return $pbot->{interpreter}->interpret($from, $nick, $user, $host, $depth, $command, $tonick); + return $pbot->{interpreter}->interpret($from, $nick, $user, $host, $depth, $command, $tonick, $referenced); } if(defined $tonick) { # !tell foo about bar @@ -624,6 +629,11 @@ sub interpreter { $self->{pbot}->{logger}->log("(" . (defined $from ? $from : "(undef)") . "): $nick!$user\@$host: $keyword: action: \"$action\"\n"); + if ($referenced) { + return undef if $action =~ m/\$(?:nick|arg)/; + return undef if $arguments =~ m/\$(?:nick|arg)/; + } + $action =~ s/\$nick/$nick/g; $action =~ s/\$channel/$from/g; $action =~ s/\$randomnick/my $random = $self->{pbot}->{nicklist}->random_nick($from); $random ? $random : $nick/ge; @@ -639,7 +649,7 @@ sub interpreter { my $preserve_whitespace = $self->{factoids}->hash->{$channel}->{$keyword}->{preserve_whitespace}; $preserve_whitespace = 0 if not defined $preserve_whitespace; - return $ref_from . $self->{factoidmodulelauncher}->execute_module($from, $tonick, $nick, $user, $host, "$keyword $arguments", $keyword, $arguments, $preserve_whitespace); + return $ref_from . $self->{factoidmodulelauncher}->execute_module($from, $tonick, $nick, $user, $host, "$keyword $arguments", $keyword, $arguments, $preserve_whitespace, $referenced); } elsif($self->{factoids}->hash->{$channel}->{$keyword}->{type} eq 'text') { $self->{pbot}->{logger}->log("Found factoid\n"); @@ -689,7 +699,7 @@ sub interpreter { $cmd = $action; } - $result = $pbot->{interpreter}->interpret($from, $nick, $user, $host, $depth, $cmd, $tonick); + $result = $pbot->{interpreter}->interpret($from, $nick, $user, $host, $depth, $cmd, $tonick, $referenced); return $result; }; diff --git a/PBot/Interpreter.pm b/PBot/Interpreter.pm index 721de651..f96b46cd 100644 --- a/PBot/Interpreter.pm +++ b/PBot/Interpreter.pm @@ -89,24 +89,44 @@ sub process_line { $bot_trigger = $pbot->{registry}->get_value('general', 'trigger'); } - if($cmd_text =~ /^(?:$bot_trigger|$botnick.?)?\s*{\s*(.*)\s*}\s*$/) { - $has_code = $1 if length $1; - $preserve_whitespace = 1; - } elsif($cmd_text =~ /^$bot_trigger(.*)$/) { - $command = $1; - } elsif($cmd_text =~ /^.?$botnick.?\s*(.*?)$/i) { - $command = $1; - } elsif($cmd_text =~ /^(.*?),?\s*$botnick[?!.]*$/i) { - $command = $1; - } elsif($cmd_text =~ /https?:\/\/([^\s]+)/i) { - $has_url = $1; - } elsif($cmd_text =~ /^\s*([^,:\(\)\+\*\/ ]+)[,:]*\s*{\s*(.*)\s*}\s*$/) { - $nick_override = $1; - $has_code = $2 if length $2 and $nick_override ne 'enum' and $nick_override ne 'struct'; - $preserve_whitespace = 1; - } + my $referenced; + my $count = 0; + while (++$count <= 3) { + $referenced = 0; + $command = undef; + $has_url = undef; + $has_code = undef; + + if($cmd_text =~ s/^(?:$bot_trigger|$botnick.?)?\s*{\s*(.*)\s*}\s*$//) { + $has_code = $1 if length $1; + $preserve_whitespace = 1; + } elsif($cmd_text =~ s/^$bot_trigger(.*)$//) { + $command = $1; + } elsif($cmd_text =~ s/^.?$botnick.?\s*(.*?)$//i) { + $command = $1; + } elsif($cmd_text =~ s/^(.*?),?\s*$botnick[?!.]*$//i) { + $command = $1; + } elsif($cmd_text =~ s/https?:\/\/([^\s]+)//i) { + $has_url = $1; + } elsif($cmd_text =~ s/^\s*([^,:\(\)\+\*\/ ]+)[,:]*\s*{\s*(.*)\s*}\s*$//) { + $nick_override = $1; + $has_code = $2 if length $2 and $nick_override ne 'enum' and $nick_override ne 'struct'; + $preserve_whitespace = 1; + } elsif ($cmd_text =~ s/\B$bot_trigger([^ ]+)//) { + my $cmd = $1; + $cmd =~ s/(.)[.!?;,)]$/$1/; + my ($nick) = $cmd_text =~ m/^([^ ,:;]+)/; + $nick = $self->{pbot}->{nicklist}->is_present($from, $nick); + if ($nick) { + $command = "tell $nick about $cmd"; + } else { + $command = $cmd; + } + $referenced = 1; + } + + last if not defined $command and not defined $has_url and not defined $has_code; - if(defined $command || defined $has_url || defined $has_code) { if((defined $command && $command !~ /^login/i) || defined $has_url || defined $has_code) { if(defined $from && $pbot->{ignorelist}->check_ignore($nick, $user, $host, $from)) { my $admin = $pbot->{admins}->loggedin($from, "$nick!$user\@$host"); @@ -115,31 +135,31 @@ sub process_line { return; } } - } - if(defined $has_url) { - if($pbot->{registry}->get_value('general', 'show_url_titles') and not $pbot->{registry}->get_value($from, 'no_url_titles') - and not grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'show_url_titles_ignore_channels') - and grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'show_url_titles_channels')) { - $pbot->{factoids}->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, $text, "title", "$nick http://$has_url", $preserve_whitespace); - } - } elsif(defined $has_code) { - if($pbot->{registry}->get_value('general', 'compile_blocks') and not $pbot->{registry}->get_value($from, 'no_compile_blocks') - and not grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'compile_blocks_ignore_channels') - and grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'compile_blocks_channels')) { - if (not defined $nick_override or (defined $nick_override and $self->{pbot}->{nicklist}->is_present($from, $nick_override))) { - $pbot->{factoids}->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, $text, "compiler_block", (defined $nick_override ? $nick_override : $nick) . " $from $has_code }", $preserve_whitespace); + if(defined $has_url) { + if($pbot->{registry}->get_value('general', 'show_url_titles') and not $pbot->{registry}->get_value($from, 'no_url_titles') + and not grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'show_url_titles_ignore_channels') + and grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'show_url_titles_channels')) { + $pbot->{factoids}->{factoidmodulelauncher}->execute_module($from, undef, $nick, $user, $host, $text, "title", "$nick http://$has_url", $preserve_whitespace); } + } elsif(defined $has_code) { + if($pbot->{registry}->get_value('general', 'compile_blocks') and not $pbot->{registry}->get_value($from, 'no_compile_blocks') + and not grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'compile_blocks_ignore_channels') + and grep { $from =~ /$_/i } $pbot->{registry}->get_value('general', 'compile_blocks_channels')) { + if (not defined $nick_override or (defined $nick_override and $self->{pbot}->{nicklist}->is_present($from, $nick_override))) { + $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 { + $self->handle_result($from, $nick, $user, $host, $text, $command, $self->interpret($from, $nick, $user, $host, 1, $command, undef, $referenced), 1, $preserve_whitespace); } - } else { - $self->handle_result($from, $nick, $user, $host, $text, $command, $self->interpret($from, $nick, $user, $host, 1, $command), 1, $preserve_whitespace); } } } sub interpret { my $self = shift; - my ($from, $nick, $user, $host, $depth, $command, $tonick) = @_; + my ($from, $nick, $user, $host, $depth, $command, $tonick, $referenced) = @_; my ($keyword, $arguments) = ("", ""); my $text; my $pbot = $self->{pbot}; @@ -194,7 +214,7 @@ sub interpret { return undef; } - return $self->SUPER::execute_all($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick); + return $self->SUPER::execute_all($from, $nick, $user, $host, $depth, $keyword, $arguments, $tonick, undef, $referenced); } sub truncate_result {