-
Notifications
You must be signed in to change notification settings - Fork 3
Variables and math
As of v0.4, BotBot now supports user-created variables!
All user-created variables are stored as strings.
To set a variable, use either of the following two formats:
!var name = value
!var name value
The first format is recommended for readability and to reduce ambiguity. The name can be any string of nonzero length consisting entirely of non-whitespace characters. The value can be any string starting with a non-whitespace character.
To retrieve a variable, the new-style syntax is preferred:
${variable_name}
This will be replaced with the appropriate value in both the regex and the response.
The old-style syntax (variable_name) also works in the response, but it is deprecated.
Please note: When using the new syntax ${variable_name}, the expression is parsed at compile-time. This means that you cannot construct a ${variable_name} expression dynamically. For example, backreferences (\1, \2, etc.) in a ${variable_name} expression will not work as expected.
In v0.4, you could use BotBot response expressions, such as random choices [a, b, c], as part of the ${variable_name} expression.
In v0.5, this has been dropped in favor of math operations, which should allow you to perform similar functionality.
In v0.4, nonexistent variables (using the new-style syntax) were replaced with '' (the empty string).
In v0.5, nonexistent variables cause an error, and are replaced with [Error: simpleeval.NameNotDefined: 'variable_name' is not defined for expression 'variable_name']. To avoid this error, use the math operations introduced in v0.5 to check for existence of the variable.
As of v0.5, BotBot now supports a limited subset of Python, allowing bots to perform math!
This uses the new-style variable syntax, as in ${1 + 2}, and is quite powerful compared to other BotBot features.
Please note: As mentioned above, ${math} expressions are parsed at compile-time. This means that you cannot construct a ${math} expression dynamically. You also cannot nest expressions, as in ${math ${more math\}}. If you need to evaluate a ${math} expression at runtime (e.g. from user input), you can use the eval function, as in eval('1 + 2').
Also note: If a closing curly bracket } or backslash \ is used in your expression, it must be escaped with a backslash, as in \} or \\.
You can use the following Python features to construct a dynamic math expression.
Please note that most variables are strings, and so must be converted to numeric types using functions like int(x) or float(x) to be used as numbers. The result of a ${math} expression is converted to a string automatically.
| Variable name | Description |
|---|---|
sender |
Nickname of the person who sent the message that triggered a response from the bot. |
@sender |
@-mention for the sender. |
atsender |
Alias for @sender, since it cannot be used directly as a variable in the new syntax in v0.5. |
self |
Current nickname of the bot. |
@self |
@-mention for the bot. |
atself |
Alias for @self. |
creator |
Nickname of the person who created the bot. |
@creator |
@-mention for the creator. |
atcreator |
Alias for @creator. |
room |
The room in which the trigger message was sent, without the preceding ampersand &. |
uptimeutc |
The time at which the bot started listening for messages, as a UTC timestamp. |
uptime |
The amount of time for which the bot has been up, in days, hours, minutes, and seconds. |
uuid |
The unique identifier for the bot, assigned at creation of the bot. |
variables |
A dict containing all variables; useful for referring to variables with unusual names. |
groups |
A list of capturing groups in the regex. groups[0] refers to the whole match. |
| User variables | Any variables by the bot created with the !var command, as strings. |
The following functions are available for use in your math expression.
| Function signature | Description |
|---|---|
rand() |
Python's random.random() function. Returns a random float in [0.0, 1.0). |
randint(top) |
Returns a random integer in [0, top). |
int(x, base=10) |
Python's int() function. Returns x as an integer. |
float([x]) |
Python's float() function. Returns x as a float. |
str(object='') |
Python's str() function. Returns object as a string. |
bool([x]) |
Python's bool() function. Returns x as a Boolean value. |
repr(object) |
Python's repr() function. Returns a string representation of object that will often reproduce it when passed to eval(). |
len(s) |
Python's len() function. Returns the length of s. |
time() |
Python's time.time() function. Returns the number of seconds since the Unix epoch as a float. |
eval(code) |
Evaluates the string code (as if it was written as ${code}) and returns the result. |
to_json(object) |
Returns the JSON string representation of object. |
from_json(json) |
Returns the evaluated form of the JSON-encoded string json. |
mention(name) |
Returns an @-mention for the given nickname. |
unwhitespace(s) |
Returns the string s with each whitespace character replaced by an underscore. |
If an error occurs in a ${math} expression, the whole expression will be replaced with an error description in the following format:
[Error: ErrorName: description of error, usually including the expression where the error occurred]
try statements are currently not supported.
In order to check for a variable's existence to avoid an error, you can check for its existence in the variables dictionary using the in or not in keywords in a ternary statement. For example, the following returns the variable x if it exists, otherwise returning 0.
${x if 'x' in variables else 0}
You can also use the variables.get(key[, default]) function to get a variable if it exists or return default if it does not, thereby avoiding an error.
Please note that access to attributes starting with an underscore _ or with func_ has been disallowed for security purposes.
If you find a way to "break out" and access something you should not be able to access, please let me know by filing a new issue on GitHub with example code that is able to exploit the vulnerability.
As of v0.5.2, BotBot has an initialization trigger that gives your bot a chance to initialize variables when it starts up. This initialization trigger is the invalid regular expression (+init), which is special-cased in the BotBot code to run on the bot's creation.
For example:
-
(+init) -> Hello, world!
When the bot is created, it will send the message, "Hello, world!" -
(+init) -> !var initialized = yes
When the bot is created, it will set the variableinitializedto the string value'yes'. -
(+init) -> {Hello\, world!, !var initialized = yes}
When the bot is created, it will both send the message, "Hello, world!" and set the variableinitializedto the string value'yes'.
This functionality is brand new, so if you spot a bug, please let me know by filing a new issue on GitHub.
If there's something missing from the current functionality that you would like to see added, feel free to request a feature by filing a new issue on GitHub.