From 30d176f6bbd6a4a5c8dc28c5c2afc73ac60c03c4 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Fri, 1 Oct 2021 20:52:53 -0700 Subject: [PATCH] Prepare v2.2.0 for release --- Changes.md | 31 +++++++ README.md | 1 + docs/brain.md | 10 +-- docs/html/lang.coffee.html | 7 +- docs/html/lang.javascript.html | 5 +- docs/html/parser.html | 67 +++++++------- docs/html/rivescript.html | 158 ++++++++++++++++----------------- docs/html/sessions.html | 36 ++++---- docs/html/utils.html | 7 +- docs/rivescript.md | 46 +++++----- docs/sessions.md | 12 +-- package.json | 4 +- src/rivescript.js | 2 +- 13 files changed, 208 insertions(+), 178 deletions(-) diff --git a/Changes.md b/Changes.md index fc56f2d..938df7e 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,36 @@ # Changes +## 2.2.0 - Oct 1 2021 + +This release includes various bugfixes and features from the GitHub +community. + +There is a new algorithm for handling the nestable tags (such as +``, ``, ``, and other variable getter/setter tags) +and it works with `` tags, too! Thanks, +[@lee-orr](https://github.com/lee-orr)! (PR #377) + +``` ++ * +- add_hello > + ^ The answer is: . + +> object add_hello javascript + return "hello:" + args[0]; +< object +``` + +- Bugfix: missing 'let' in for loop (#340) +- If an error is raised within an object macro, include the error in the + bot's response (#341) +- Fix a truthiness check for whether bot/env vars are 'undefined' (#350) +- Fix the _ word wildcard not working when multiple are in the same + trigger (#356) +- Add example: json-server-async (#207) +- An option to treat user inputs as case-sensitive instead of always + lowercasing them (#246/#378) +- Various Dependabot dependency updates. + ## 2.1.0 - Mar 13 2020 - The RiveScript `shell.js` script is now installed as a command line program diff --git a/README.md b/README.md index b1303d9..21e2d66 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ The shell accepts a few command line parameters: * `--watch`: watch the reply folder for changes and automatically reload the bot when files are modified. * `--utf8`: enables UTF-8 mode. +* `--case`: enable case-sensitive user messages. ## DOCUMENTATION diff --git a/docs/brain.md b/docs/brain.md index 5ca84c1..494acad 100644 --- a/docs/brain.md +++ b/docs/brain.md @@ -2,11 +2,11 @@ Create a Brain object which handles the actual process of fetching a reply. -## async reply (string user, string msg[, scope]) -> string +## async reply (string user, string msg[, scope]) Fetch a reply for the user. This returns a Promise that may be awaited on. -## private async _getReply (string user, string msg, string context, int step, scope) -> string +## async _getReply (string user, string msg, string context, int step, scope) The internal reply method. DO NOT CALL THIS DIRECTLY. @@ -19,15 +19,15 @@ The internal reply method. DO NOT CALL THIS DIRECTLY. Format a user's message for safe processing. -## async triggerRegexp (string user, string trigger) -> string +## async triggerRegexp (string user, string trigger) Prepares a trigger for the regular expression engine. -## async processTags (string user, string msg, string reply, string[] stars, string[] botstars, int step, scope) -> string +## string processTags (string user, string msg, string reply, string[] stars, string[] botstars, int step, scope) Process tags in a reply element. ## string substitute (string msg, string type) Run substitutions against a message. `type` is either "sub" or "person" for -the type of substitution to run. +the type of substitution to run. \ No newline at end of file diff --git a/docs/html/lang.coffee.html b/docs/html/lang.coffee.html index 781ceb3..18eba76 100644 --- a/docs/html/lang.coffee.html +++ b/docs/html/lang.coffee.html @@ -9,10 +9,9 @@

CoffeeObjectHandler (RiveScript master)

CoffeeScript Language Support for RiveScript Macros. This language is not enabled by default; to enable CoffeeScript object macros:

-
CoffeeObjectHandler = require "rivescript/lang/coffee"
-bot.setHandler "coffee", new CoffeeObjectHandler
-
- +
CoffeeObjectHandler = require "rivescript/lang/coffee"
+bot.setHandler "coffee", new CoffeeObjectHandler
+

void load (string name, string[] code)

Called by the RiveScript object to load CoffeeScript code.

diff --git a/docs/html/lang.javascript.html b/docs/html/lang.javascript.html index 9d2e6be..5182f93 100644 --- a/docs/html/lang.javascript.html +++ b/docs/html/lang.javascript.html @@ -10,9 +10,8 @@

JSObjectHandler (RiveScript master)

JavaScript Language Support for RiveScript Macros. This support is enabled by default in RiveScript.js; if you don't want it, override the javascript language handler to null, like so:

-
bot.setHandler("javascript", null);
-
- +
bot.setHandler("javascript", null);
+

void load (string name, string[]|function code)

Called by the RiveScript object to load JavaScript code.

diff --git a/docs/html/parser.html b/docs/html/parser.html index 769fc39..910a2bb 100644 --- a/docs/html/parser.html +++ b/docs/html/parser.html @@ -11,40 +11,39 @@

Parser (RiveScript master)

object parse (string filename, string code[, func onError])

Read and parse a RiveScript document. Returns a data structure that represents all of the useful contents of the document, in this format:

-
{
-  "begin": { // "begin" data
-    "global": {}, // ! global vars
-    "var": {},    // ! bot vars
-    "sub": {},    // ! sub substitutions
-    "person": {}, // ! person substitutions
-    "array": {},  // ! array lists
-  },
-  "topics": { // main reply data
-    "random": { // (topic name)
-      "includes": {}, // included topics
-      "inherits": {}, // inherited topics
-      "triggers": [ // array of triggers
-        {
-          "trigger": "hello bot",
-          "reply": [], // array of replies
-          "condition": [], // array of conditions
-          "redirect": "",  // @ redirect command
-          "previous": null, // % previous command
-        },
-        ...
-      ]
-    }
-  },
-  "objects": [ // parsed object macros
-    {
-      "name": "",     // object name
-      "language": "", // programming language
-      "code": [],     // object source code (in lines)
-    }
-  ]
-}
-
- +
{
+  "begin": { // "begin" data
+    "global": {}, // ! global vars
+    "var": {},    // ! bot vars
+    "sub": {},    // ! sub substitutions
+    "person": {}, // ! person substitutions
+    "array": {},  // ! array lists
+  },
+  "topics": { // main reply data
+    "random": { // (topic name)
+      "includes": {}, // included topics
+      "inherits": {}, // inherited topics
+      "triggers": [ // array of triggers
+        {
+          "trigger": "hello bot",
+          "reply": [], // array of replies
+          "condition": [], // array of conditions
+          "redirect": "",  // @ redirect command
+          "previous": null, // % previous command
+        },
+        ...
+      ]
+    }
+  },
+  "objects": [ // parsed object macros
+    {
+      "name": "",     // object name
+      "language": "", // programming language
+      "code": [],     // object source code (in lines)
+    }
+  ]
+}
+

onError function receives: (err string[, filename str, line_no int])

string stringify (data deparsed)

diff --git a/docs/html/rivescript.html b/docs/html/rivescript.html index 07e7611..0386c8d 100644 --- a/docs/html/rivescript.html +++ b/docs/html/rivescript.html @@ -19,25 +19,32 @@

Notice to Developers

RiveScript (hash options)

Create a new RiveScript interpreter. options is an object with the following keys:

-
* bool debug:     Debug mode               (default false)
-* int  depth:     Recursion depth limit    (default 50)
-* bool strict:    Strict mode              (default true)
-* bool utf8:      Enable UTF-8 mode        (default false, see below)
-* bool forceCase: Force-lowercase triggers (default false, see below)
-* func onDebug:   Set a custom handler to catch debug log messages (default null)
-* obj  errors:    Customize certain error messages (see below)
-* str  concat:    Globally replace the default concatenation mode when parsing
-                  RiveScript source files (default `null`. be careful when
-                  setting this option if using somebody else's RiveScript
-                  personality; see below)
-* sessionManager: provide a custom session manager to store user variables.
+
    +
  • bool debug: Debug mode (default false)
  • +
  • int depth: Recursion depth limit (default 50)
  • +
  • bool strict: Strict mode (default true)
  • +
  • bool utf8: Enable UTF-8 mode (default false, see below)
  • +
  • bool forceCase: Force-lowercase triggers (default false, see below)
  • +
  • func onDebug: Set a custom handler to catch debug log messages (default null)
  • +
  • obj errors: Customize certain error messages (see below)
  • +
  • str concat: Globally replace the default concatenation mode when parsing + RiveScript source files (default null. be careful when + setting this option if using somebody else's RiveScript + personality; see below)
  • +
  • sessionManager: provide a custom session manager to store user variables. The default is to store variables in memory, but you may use any async data store by providing an implementation of - RiveScript's SessionManager. See the - [sessions](./sessions.md) documentation. -
- - + RiveScript's SessionManager. See the + sessions documentation. +
  • bool caseSensitive: + The user's message will not be lowercased when processed + by the bot; so their original capitalization will be + preserved when repeated back in tags.
  • +
  • regexp unicodePunctuation: + You may provide a custom regexp for what you define to be + punctuation characters to be stripped from the user's + message in UTF-8 mode.
  • +

    UTF-8 Mode

    In UTF-8 mode, most characters in a user's message are left intact, except for certain metacharacters like backslashes and common punctuation characters like @@ -45,10 +52,9 @@

    UTF-8 Mode

    If you want to override the punctuation regexp, you can provide a new one by assigning the unicodePunctuation attribute of the bot object after initialization. Example:

    -
    var bot = new RiveScript({utf8: true});
    -bot.unicodePunctuation = new RegExp(/[.,!?;:]/g);
    -
    - +
    var bot = new RiveScript({utf8: true});
    +bot.unicodePunctuation = new RegExp(/[.,!?;:]/g);
    +

    Force Case

    This option to the constructor will make RiveScript lowercase all the triggers @@ -93,10 +99,9 @@

    Custom Error Messages

    Note: the recommended way to handle this case is to provide a trigger of simply *, which serves as the catch-all trigger and is the default one that will match if nothing else matches the user's message. Example:

    -
    + *
    -- I don't know what to say to that!
    -
    - +
    + *
    +- I don't know what to say to that!
    +
    • replyNotFound: This message is returned when the user did in fact match @@ -108,11 +113,10 @@

      Custom Error Messages

      Note: the recommended way to handle this case is to provide at least one normal reply (with the - command) to every trigger to cover the cases where none of the conditions are true. Example:

      -
      + hello
      +
      + hello
       * <get name> != undefined => Hello there, <get name>.
       - Hi there.
      -
      - +
      • objectNotFound: This message is inserted into the bot's reply in-line when @@ -128,15 +132,14 @@

        Custom Error Messages

        These custom error messages can be provided during the construction of the RiveScript object, or set afterwards on the object's errors property.

        Examples:

        -
        var bot = new RiveScript({
        -errors: {
        -replyNotFound: "I don't know how to reply to that."
        -}
        -});
        -
        -bot.errors.objectNotFound = "Something went terribly wrong.";
        -
        +
        var bot = new RiveScript({
        +errors: {
        +replyNotFound: "I don't know how to reply to that."
        +}
        +});
         
        +bot.errors.objectNotFound = "Something went terribly wrong.";
        +

        string version ()

        Returns the version number of the RiveScript.js library.

        @@ -227,10 +230,9 @@

        void setHandler(string lang, object)

        By default, JavaScript object macros are enabled. If you want to disable these (e.g. for security purposes when loading untrusted third-party code), just set the JavaScript handler to null:

        -
        var bot = new RiveScript();
        -bot.setHandler("javascript", null);
        -
        - +
        var bot = new RiveScript();
        +bot.setHandler("javascript", null);
        +

        void setSubroutine(string name, function)

        Define a JavaScript object macro from your program.

        @@ -270,8 +272,8 @@

        async freezeUservars (string user)

        thawUservars()

        async thawUservars (string user[, string action])

        Thaw a user's frozen variables. The action can be one of the following: - discard: Don't restore the variables, just delete the frozen copy. - keep: Keep the frozen copy after restoring +* discard: Don't restore the variables, just delete the frozen copy. +* keep: Keep the frozen copy after restoring * thaw: Restore the variables and delete the frozen copy (default)

        async lastMatch (string user) -> string

        Retrieve the trigger that the user matched most recently.

        @@ -314,42 +316,39 @@

        Promise reply (string username, string message[, scope])

        was called. For an example of this, refer to the eg/scope directory in the source distribution of RiveScript-JS.

        Example:

        -
        // Normal usage as a promise
        -bot.reply(username, message, this).then(function(reply) {
        -    console.log("Bot>", reply);
        -});
        -
        -// Async-Await usage in an async function.
        -async function getReply(username, message) {
        -    var reply = await bot.reply(username, message);
        -    console.log("Bot>", reply);
        -}
        -
        +
        // Normal usage as a promise
        +bot.reply(username, message, this).then(function(reply) {
        +    console.log("Bot>", reply);
        +});
         
        +// Async-Await usage in an async function.
        +async function getReply(username, message) {
        +    var reply = await bot.reply(username, message);
        +    console.log("Bot>", reply);
        +}
        +

        Promise replyAsync (string username, string message [[, scope], callback])

        Obsolete as of v2.0.0 -- use reply() instead in new code.

        Asyncronous version of reply. Use replyAsync if at least one of the subroutines used with the <call> tag returns a promise.

        Example: using promises

        -
        rs.replyAsync(user, message).then(function(reply) {
        -  console.log("Bot>", reply);
        -}).catch(function(error) {
        -  console.error("Error: ", error);
        -});
        -
        - +
        rs.replyAsync(user, message).then(function(reply) {
        +  console.log("Bot>", reply);
        +}).catch(function(error) {
        +  console.error("Error: ", error);
        +});
        +

        Example: using the callback

        -
        rs.replyAsync(username, msg, this, function(error, reply) {
        -  if (!error) {
        -    console.log("Bot>", reply);
        -  } else {
        -    console.error("Error: ", error);
        -  }
        -});
        -
        - +
        rs.replyAsync(username, msg, this, function(error, reply) {
        +  if (!error) {
        +    console.log("Bot>", reply);
        +  } else {
        +    console.error("Error: ", error);
        +  }
        +});
        +

        Promise Promise

        DEPRECATED

        @@ -359,20 +358,19 @@

        Promise Promise

        object macros.

        This enables you to create a JavaScript object macro that returns a promise for asynchronous tasks (e.g. polling a web API or database). Example:

        -
        rs.setSubroutine("asyncHelper", function (rs, args) {
        - return new rs.Promise(function (resolve, reject) {
        -   resolve(42);
        - });
        -});
        -
        - +
        rs.setSubroutine("asyncHelper", function (rs, args) {
        + return new rs.Promise(function (resolve, reject) {
        +   resolve(42);
        + });
        +});
        +

        If you're using promises in your object macros, you need to get a reply from the bot using the replyAsync() method instead of reply(), for example:

        -
        rs.replyAsync(username, message, this).then(function(reply) {
        -   console.log("Bot> ", reply);
        -});
        -
        +
        rs.replyAsync(username, message, this).then(function(reply) {
        +   console.log("Bot> ", reply);
        +});
        +
        \ No newline at end of file diff --git a/docs/html/sessions.html b/docs/html/sessions.html index 9be1706..1cc1595 100644 --- a/docs/html/sessions.html +++ b/docs/html/sessions.html @@ -20,15 +20,14 @@

        SessionManager

        session manager with one that implements that backend (or write one yourself that implements this SessionManager API).

        To use a session manager, you'd typically do something like:

        -
        const RedisSessions = require("rivescript-contrib-redis");
        -
        -// Provide the sessionManager option to use this instead of
        -// the default MemorySessionManager.
        -var bot = new RiveScript({
        -    sessionManager: new RedisSessions("localhost:6379")
        -});
        -
        +
        const RedisSessions = require("rivescript-contrib-redis");
         
        +// Provide the sessionManager option to use this instead of
        +// the default MemorySessionManager.
        +var bot = new RiveScript({
        +    sessionManager: new RedisSessions("localhost:6379")
        +});
        +

        To implement your own session manager, you should extend the SessionManager class and implement a compatible object.

        @@ -52,17 +51,16 @@

        async getAll() -> object

        Retrieve all variables about all users.

        This should return an object that maps usernames to an object of their variables. For example:

        -
        { "user1": {
        -    "topic": "random",
        -       "name": "Alice"
        -  },
        -  "user2": {
        -    "topic": "random",
        -    "name": "Bob"
        -  }
        -}
        -
        - +
        { "user1": {
        +    "topic": "random",
        +       "name": "Alice"
        +  },
        +  "user2": {
        +    "topic": "random",
        +    "name": "Bob"
        +  }
        +}
        +

        async reset(string username)

        Reset all variables stored about a particular user.

        diff --git a/docs/html/utils.html b/docs/html/utils.html index 2173d7a..be606b8 100644 --- a/docs/html/utils.html +++ b/docs/html/utils.html @@ -36,10 +36,9 @@

        []string parseCallArgs

        means each word in the string becomes an item in the result, but quoted sections of the input will come back as a single item.

        Example:

        -
        console.log( parseCallArgs('please google "writing chat bot"'));
        -// ["please", "google", "writing chat bot"]
        -
        - +
        console.log( parseCallArgs('please google "writing chat bot"'));
        +// ["please", "google", "writing chat bot"]
        +

        object clone (object)

        Clone an object.

        diff --git a/docs/rivescript.md b/docs/rivescript.md index bb33b50..325ba45 100644 --- a/docs/rivescript.md +++ b/docs/rivescript.md @@ -16,7 +16,6 @@ near future. Create a new RiveScript interpreter. `options` is an object with the following keys: -``` * bool debug: Debug mode (default false) * int depth: Recursion depth limit (default 50) * bool strict: Strict mode (default true) @@ -25,15 +24,22 @@ following keys: * func onDebug: Set a custom handler to catch debug log messages (default null) * obj errors: Customize certain error messages (see below) * str concat: Globally replace the default concatenation mode when parsing - RiveScript source files (default `null`. be careful when - setting this option if using somebody else's RiveScript - personality; see below) + RiveScript source files (default `null`. be careful when + setting this option if using somebody else's RiveScript + personality; see below) * sessionManager: provide a custom session manager to store user variables. - The default is to store variables in memory, but you may - use any async data store by providing an implementation of - RiveScript's SessionManager. See the - [sessions](./sessions.md) documentation. -``` + The default is to store variables in memory, but you may + use any async data store by providing an implementation of + RiveScript's SessionManager. See the + [sessions](./sessions.md) documentation. +* bool caseSensitive: + The user's message will not be lowercased when processed + by the bot; so their original capitalization will be + preserved when repeated back in tags. +* regexp unicodePunctuation: + You may provide a custom regexp for what you define to be + punctuation characters to be stripped from the user's + message in UTF-8 mode. ## UTF-8 Mode @@ -309,11 +315,11 @@ Set the value to `undefined` to delete a substitution. Set a person substitution. This is equivalent to `! person` in RiveScript. Set the value to `undefined` to delete a person substitution. -## async setUservar (string user, string name, string value) -> void +## async setUservar (string user, string name, string value) Set a user variable for a user. -## async setUservars (string user, object data) -> void +## async setUservars (string user, object data) Set multiple user variables by providing an object of key/value pairs. Equivalent to calling `setUservar()` for each pair in the object. @@ -332,18 +338,18 @@ defined. Get all variables about a user. If no user is provided, returns all data about all users. -## async clearUservars ([string user]) -> void +## async clearUservars ([string user]) Clear all a user's variables. If no user is provided, clears all variables for all users. -## async freezeUservars (string user) -> void +## async freezeUservars (string user) Freeze the variable state of a user. This will clone and preserve the user's entire variable state, so that it can be restored later with `thawUservars()` -## async thawUservars (string user[, string action]) -> void +## async thawUservars (string user[, string action]) Thaw a user's frozen variables. The action can be one of the following: * discard: Don't restore the variables, just delete the frozen copy. @@ -413,13 +419,13 @@ Example: ```javascript // Normal usage as a promise bot.reply(username, message, this).then(function(reply) { - console.log("Bot>", reply); + console.log("Bot>", reply); }); // Async-Await usage in an async function. async function getReply(username, message) { - var reply = await bot.reply(username, message); - console.log("Bot>", reply); + var reply = await bot.reply(username, message); + console.log("Bot>", reply); } ``` @@ -445,9 +451,9 @@ Example: using the callback ```javascript rs.replyAsync(username, msg, this, function(error, reply) { if (!error) { - console.log("Bot>", reply); + console.log("Bot>", reply); } else { - console.error("Error: ", error); + console.error("Error: ", error); } }); ``` @@ -480,4 +486,4 @@ the bot using the `replyAsync()` method instead of `reply()`, for example: rs.replyAsync(username, message, this).then(function(reply) { console.log("Bot> ", reply); }); -``` +``` \ No newline at end of file diff --git a/docs/sessions.md b/docs/sessions.md index 690df85..ee9c290 100644 --- a/docs/sessions.md +++ b/docs/sessions.md @@ -30,7 +30,7 @@ var bot = new RiveScript({ To implement your own session manager, you should extend the `SessionManager` class and implement a compatible object. -## async set(string username, object data) -> void +## void set(string username, object data) Set user variables for the user `username`. The `args` should be an object of key/value pairs. The values are usually strings, but they can be other @@ -74,21 +74,21 @@ variables. For example: } ``` -## async reset(string username) -> void +## async reset(string username) Reset all variables stored about a particular user. -## async resetAll() -> void +## async resetAll() Reset all data about all users. -## async freeze(string username) -> void +## async freeze(string username) Make a snapshot of the user's variables so that they can be restored later via `thaw()`. This is the implementation for `RiveScript.freezeUservars()` -## async thaw(string username, string action) -> void +## async thaw(string username, string action) Restore the frozen snapshot of variables for a user. @@ -126,4 +126,4 @@ RiveScript with an alternative session store. # NullSessionManager This is a session manager implementation that does not remember any user -variables. It is mostly useful for unit tests. +variables. It is mostly useful for unit tests. \ No newline at end of file diff --git a/package.json b/package.json index 0ead8f5..8f4e846 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rivescript", - "version": "2.1.0", + "version": "2.2.0", "description": "RiveScript is a scripting language for chatterbots, making it easy to write trigger/response pairs for building up a bot's intelligence.", "keywords": [ "bot", @@ -77,4 +77,4 @@ "bin": { "riveshell": "./shell.js" } -} +} \ No newline at end of file diff --git a/src/rivescript.js b/src/rivescript.js index 1369719..8c0fca7 100644 --- a/src/rivescript.js +++ b/src/rivescript.js @@ -22,7 +22,7 @@ near future. */ // Constants -const VERSION = "2.1.0"; +const VERSION = "2.2.0"; // Helper modules const Parser = require("./parser");