diff options
author | gregor herrmann <gregoa@debian.org> | 2011-09-24 21:04:07 +0200 |
---|---|---|
committer | gregor herrmann <gregoa@debian.org> | 2011-09-24 21:04:07 +0200 |
commit | dbabd8a373b0e5dbc1977405046288fff6a50dfd (patch) | |
tree | fe03d1a79cfb413dc78884ec8d414e07f41ded58 /bin | |
parent | 6f4db1999c2225c9067411c262ba29e8a7ce38a5 (diff) |
Imported Upstream version 1.22
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/rivescript | 363 | ||||
-rwxr-xr-x | bin/rsdemo | 161 |
2 files changed, 363 insertions, 161 deletions
diff --git a/bin/rivescript b/bin/rivescript new file mode 100755 index 0000000..ab7560e --- /dev/null +++ b/bin/rivescript @@ -0,0 +1,363 @@ +#!/usr/bin/perl + +# A front-end to RiveScript. +# See `rivescript --help` for help. + +use strict; +use warnings; +use RiveScript; +use JSON; +use Getopt::Long; +use Pod::Text; + +#------------------------------------------------------------------------------# +# Command Line Arguments # +#------------------------------------------------------------------------------# + +my $opt = { + debug => 0, # --debug, enables debug mode + verbose => 1, # Private, verbose mode for RS + log => "", # --log, debug logs to file instead of terminal + json => 0, # --json, running in batch mode + depth => 50, # depth variable + strict => 1, # --strict, strict mode + help => 0, # --help +}; +GetOptions ( + 'debug|d' => \$opt->{debug}, + 'log=s' => \$opt->{log}, + 'help|h|?' => \$opt->{help}, + 'json|j' => \$opt->{json}, + 'depth=i' => \$opt->{depth}, + 'strict!' => \$opt->{strict}, +); + +# Asking for help? +if ($opt->{help}) { + # Give them our POD instructions. + my $pod = Pod::Text->new (sentence => 0, width => 78); + $pod->parse_from_filehandle(*DATA); + exit(0); +} + +# Debug mode options. +if ($opt->{log}) { + # Logging automatically enables debugging. + $opt->{debug} = 1; + $opt->{verbose} = 0; +} + +#------------------------------------------------------------------------------# +# Main Program Begins Here # +#------------------------------------------------------------------------------# + +# A brain has been specified? +my $root = scalar(@ARGV) ? $ARGV[0] : $RiveScript::basedir . "/demo"; + +# Create the RiveScript interpreter. +my $rs = init(); +my $json; # JSON interpreter if we need it. + +# Interactive mode? +if (!$opt->{json}) { + # If called with no arguments, hint about the --help option. + unless (scalar(@ARGV)) { + print "Hint: use `rivescript --help` for documentation on this command.\n\n"; + } + + print "RiveScript Interpreter - Interactive Mode\n" + . "-----------------------------------------\n" + . "RiveScript Version: $RiveScript::VERSION\n" + . " Reply Root: $root\n\n" + . "You are now chatting with the RiveScript bot. Type a message and press Return to send it.\n" + . "When finished, type '/quit' to exit the program. Type '/help' for other options.\n\n"; + + while (1) { + print "You> "; + chomp(my $input = <STDIN>); + + # Commands. + if ($input =~ /^\/help/i) { + print "> Supported Commands:\n" + . "> /help - Displays this message.\n" + . "> /reload - Reload the RiveScript brain.\n" + . "> /quit - Exit the program.\n"; + } + elsif ($input =~ /^\/reload/i) { + # Reload the brain. + undef $rs; + $rs = init(); + print "> RiveScript has been reloaded.\n\n"; + } + elsif ($input =~ /^\/(?:quit|exit)/i) { + # Quit. + exit(0); + } + else { + # Get a response. + my $reply = $rs->reply("localuser", $input); + print "Bot> $reply\n"; + } + } +} +else { + # JSON mode. + $json = JSON->new->pretty(); + + # Read from standard input. + my $buffer = ""; + my $stateful = 0; + while (my $line = <STDIN>) { + chomp($line); + $line =~ s/[\x0D\x0A]+//g; + + # Look for the __END__ line. + if ($line =~ /^__END__$/i) { + # Process it. + $stateful = 1; # This is a stateful session. + json_in($buffer, 1); + $buffer = ""; + next; + } + + $buffer .= "$line\n"; + } + + # We got the EOF. If the session was stateful, just exit, otherwise + # process what we just read. + if ($stateful) { + exit(0); + } + + json_in($buffer); + exit(0); +} + +sub init { + my $rs = RiveScript->new ( + debug => $opt->{debug}, + verbose => $opt->{verbose}, + debugfile => $opt->{log}, + depth => $opt->{depth}, + strict => $opt->{strict}, + ); + + $rs->loadDirectory($root); + $rs->sortReplies(); + return $rs; +} + +sub json_in { + my $buffer = shift; + my $end = shift; + + my $data = {}; + my $reply = { + status => "ok", + }; + + # Try to decode their input. + eval { + $data = $json->decode($buffer); + }; + + # Error? + if ($@) { + $reply->{status} = "error"; + $reply->{reply} = "Failed to decode your input: $@"; + } + else { + # Decode their variables. + my $username = exists $data->{username} ? $data->{username} : "localuser"; + if (ref($data->{vars}) eq "HASH") { + foreach my $key (keys %{$data->{vars}}) { + next if ref($data->{vars}->{$key}); + $rs->setUservar($username, $key, $data->{vars}->{$key}); + } + } + + # Get their answer. + $reply->{reply} = $rs->reply($username, $data->{message}); + + # Retrieve vars. + $reply->{vars} = {}; + my $vars = $rs->getUservars($username); + foreach my $key (keys %{$vars}) { + next if ref($vars->{$key}); + $reply->{vars}->{$key} = $vars->{$key}; + } + } + + # Encode and print. + print $json->encode($reply); + print "__END__\n" if $end; +} + +__DATA__ + +=head1 NAME + +rivescript - A command line frontend to the Perl RiveScript interpreter. + +=head1 SYNOPSIS + + $ rivescript [options] [path to RiveScript documents] + +=head1 DESCRIPTION + +This is a command line front-end to the RiveScript interpreter. This script +obsoletes the old C<rsdemo>, and can also be used non-interactively by third +party programs. To that end, it supports a variety of input/output and session +handling methods. + +If no RiveScript document path is given, it will default to the example brain +that ships with the RiveScript module, which is based on the Eliza bot. + +=head1 OPTIONS + +=over 4 + +=item --debug, -d + +Enables debug mode. This will print all debug data from RiveScript to your +terminal. If you'd like it to log to a file instead, use the C<--log> option +instead of C<--debug>. + +=item --log FILE + +Enables debug mode and prints the debug output to C<FILE> instead of to your +terminal. + +=item --json, -j + +Runs C<rivescript> in JSON mode, for running the script in a non-interactive +way (for example, to use RiveScript in a programming language that doesn't have +a native RiveScript library). See L<"JSON Mode"> for details. + +=item --strict, --nostrict + +Enables strict mode for the RiveScript parser. It's enabled by default, use +C<--nostrict> to disable it. Strict mode prevents the parser from continuing +when it finds a syntax error in the RiveScript documents. + +=item --depth=50 + +Override the default recursion depth limit. This controls how many times +RiveScript will recursively follow redirects to other replies. The default is +C<50>. + +=item --help + +Displays this documentation in your terminal. + +=back + +=head1 USAGE + +=head2 Interactive Mode + +This is the default mode used when you run C<rivescript> without specifying +another mode. This mode behaves similarly to the old C<rsdemo> script and lets +you chat one-on-one with your RiveScript bot. + +This mode can be used to test your RiveScript bot. Example: + + $ rivescript /path/to/rs/files + +=head2 JSON Mode + +This mode should be used when calling from a third party program. In this mode, +data that enters and leaves the script are encoded in JSON. + +Example: + + $ rivescript --json /path/to/rs/files + +The format for incoming JSON data is as follows: + + { + "username": "localuser", + "message": "Hello bot!", + "vars": { + "name": "Aiden" + } + } + +Here, C<username> is a unique name for the user, C<message> is their message to +the bot, and C<vars> is a hash of any user variables your program might be +keeping track of (such as the user's name and age). + +The response from C<rivescript> will look like the following: + + { + "status": "ok", + "reply": "Hello, human!", + "vars": { + "name": "Aiden" + } + } + +Here, C<status> will be C<"ok"> or C<"error">, C<reply> is the bot's response to +your message, and C<vars> is a hash of the current variables for the user (so +that your program can save them somewhere). + +=head3 End of Message + +There are two ways you can use the JSON mode: "fire and forget," or keep a +stateful session open. + +In "fire and forget," you open the program, print your JSON input and send the +EOF signal, and then C<rivescript> sends you the JSON response and exits. + +In a stateful session mode, you must send the text C<__END__> on a line by +itself after you finish sending your JSON data. Then C<rivescript> will +process it, return its JSON response and then also say C<__END__> at the end. + +Example: + + { + "username": "localuser", + "message": "Hello bot!", + "vars": {} + } + __END__ + +And the response: + + { + "status": "ok", + "reply": "Hello, human!", + "vars": {} + } + __END__ + +This way you can reuse the same pipe to send and receive multiple messages. + +=head1 SEE ALSO + +L<RiveScript>, the Perl RiveScript interpreter. + +=head1 AUTHOR + +Noah Petherbridge, http://www.kirsle.net + +=head1 LICENSE + + RiveScript - Rendering Intelligence Very Easily + Copyright (C) 2011 Noah Petherbridge + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +=cut diff --git a/bin/rsdemo b/bin/rsdemo deleted file mode 100755 index ad4a25e..0000000 --- a/bin/rsdemo +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/perl -w - -use strict; -use warnings; -use lib "./lib"; -use RiveScript; - -print "Welcome to the Perl RiveScript Interpreter. This script is a demonstration\n" - . "of RiveScript. The bot's replies are taken from the files in the\n" - . "'RiveScript/demo' directory, which by default are based on some of Eliza's\n" - . "triggers and responses. To load a different set of replies, provide\n" - . "a path to a directory on the command line, e.g. rsdemo /opt/rs/brain\n\n"; - -# Get a directory name from the command line. -my $brain = undef; -my @opts = (); -my $help = 0; -if (@ARGV) { - foreach my $v (@ARGV) { - if ($v =~ /^\-*?debug$/i) { - push (@opts, 'debug', 1); - next; - } - elsif ($v =~ /^\-*?(?:debug|)(?:f|file)=(.+?)$/i) { - push (@opts, 'debugfile', $1); - next; - } - elsif ($v =~ /^\-*?(?:v|verbose)=(.+?)$/i) { - push (@opts, 'verbose', $1); - next; - } - elsif ($v =~ /^\-*?(nostrict)$/i) { - push (@opts, 'strict', 0); - next; - } - elsif ($v =~ /^\-*?(h|help|\?)$/i) { - $help = 1; - next; - } - else { - if (-d $v) { - $brain = $v; - } - else { - warn "Can't load brain from $v: not a directory\n"; - } - } - } -} - -if ($help) { - print "Usage: rsdemo [--debug] [directory]\n"; - exit(0); -} - -my $rs = new RiveScript(@opts); - -# Read the test directory. -my $replies = (defined $brain ? $brain : ($RiveScript::basedir . "/demo")); -print "Loading RiveScript brain from directory:\n$replies\n\n"; -$rs->loadDirectory ($replies); -$rs->sortReplies(); - -print "You\'re now chatting with the RiveScript bot. Why not say hello? When\n" - . "you get tired of this, type \"quit\" to exit this demonstration.\n\n"; - -while (1) { - print "You> "; - chomp (my $msg = <STDIN>); - - if ($msg =~ /^quit/i) { - exit(0); - } - - my $reply = $rs->reply ('localuser',$msg); - - print "Bot> $reply\n"; -} - -=head1 NAME - -rsdemo - Command-line demonstration and development tool for RiveScript. - -=head1 SYNOPSIS - - Usage: rsdemo - rsdemo --debug - rsdemo /path/to/replies - rsdemo --debug /path/to/replies - -=head1 DESCRIPTION - -B<rsdemo> is a program for testing and developing RiveScript code via the -command line. Run with no arguments, rsdemo loads the default set of RiveScript -replies that are installed in your Perl lib. The default set is based on the -classic Eliza bot's personality, with additional triggers for learning and -repeating user information. - -If you have a different directory containing RiveScript documents, pass the -path to that directory on the command line, and C<rsdemo> will load replies -from there instead. - -=head1 OPTIONS - -=over 4 - -=item --debug - -This will enable RiveScript debug mode. A B<lot> of information is printed to -the terminal when debug mode is active. - -=item --debugfile=?, --file=?, -f=? - -Specify an external file for debug lines to be printed to. Since a lot of debug -information gets printed, you might want to use this in conjunction with -C<--verbose=0>. - -=item --verbose=?, -v=? - -Enable or disable verbose (debug) mode. This option only has an effect if debug -mode is on. If verbose is C<1> (the default), all debug information is printed -to the terminal. Set verbose to C<0> and this information will NOT go to the -terminal. - -If C<debugfile> is provided, all debug information will (also) be printed to the -debug file. - -=item --nostrict - -Turn off strict mode when parsing the RiveScript documents. When strict mode -is enabled (default), a syntax error in the RiveScript code is a fatal error. -When turned off, it results in a warning, and the rest of the file that caused -the error is skipped. - -=item --help - -Prints the usage of the command. - -=back - -=head1 DEBUGGING - -The C<rsdemo> tool can be used for debugging a custom set of RiveScript replies. -If you pass the C<--debug> option, debug mode is activated. By default, all -debug information will be printed to the terminal, which is likely going to be -more lines than your scrollback buffer can display. Unless you have a very small -amount of replies you're debugging, it'll be more practical to pipe the debug -information into a file and not display it on the terminal. - -Here's an example: - - rsdemo --debug --verbose=0 --file=debug.txt /path/to/replies - -Or a shortened example: - - rsdemo --debug -v=0 -f=debug.txt /path/to/replies - -In this case, the terminal would act as normal and allow you to chat with the -bot, and all debug information would be written to debug.txt. - -=cut |