App-RoboBot
view release on metacpan or search on metacpan
contain any number of elements, from *0* to *n*. If the first element of the list
is a symbol that matches a function name, it is considered a function expression,
and the remainder of the list will be supplied to that function as its arguments.
List elements may themselves be expressions, permitting the nesting of function
calls. As a simple example, we can express the mathematical operations of "Add
the numbers two and three together, then multiply their sum by five" by writing
the following:
```
(* (+ 2 3) 5)
```
This syntax applies to all interactions with RoboBot, except in cases where a
plugin hooks into the pre-evaluation phase and parses text from the raw incoming
messages itself (see the *Karma* plugin for an example of parsing meaning from
the raw messages directly).
### Multi-Network
RoboBot can be configured to connect to many chat networks simultaneously, all
managed by the same parent process. The event loop is managed through AnyEvent
to provide a portable interface for possibly embedding RoboBot into other code
which uses any of the common Perl event libraries. Internally, RoboBot
constructs a new RoboBot::Network object (actually, a sub-class specific to the
protocol used by the individual networks) for each connection made. Aside from
memory and the volume of incoming messages, there is no real limit on the
number of networks a single instance of RoboBot may listen on.
### Multi-Protocol
RoboBot is not strictly limited to IRC. Any text-based chat protocol can be
supported via the network plugin interface. Out of the box, RoboBot supports
standard IRC networks (with or without SSL), the Slack RTM API, and Mattermost
WebSockets/Web Services APIs. A single instance of RoboBot may mix and match
connections to as many different chat protocols as you wish.
Other chat protocols, such as the various instant messaging platforms, could be
added fairly easily, providing there is already a CPAN module (compatible with
AnyEvent) or you are willing to write one. Network plugins need only implement
a handful of methods (connect, disconnect, join\_channel, and send) as well as
register any callbacks required to deal with messages coming in over the wire.
Any functionality beyond that is generally optional, though some protocols may
require some additional support (e.g. Slack support requires ID<->name mappings
via Slack API calls for both channels and participants).
### Plugins
The bulk of RoboBot's functionality is implemented through a generic plugin
interface, allowing developers to export functions for direct use by channel
members, or to hook into message and response parsing phases before and after
expression evaluation.
RoboBot itself handles all the work of parsing input, passing arguments between
functions, enforcing access restrictions, and properly formatting and limiting
its output back to channels or individual recipients. Plugin authors need only
focus on the implementation details of their specific functions.
Refer to the section *Developing Plugins* below for more details.
### Macros
RoboBot provides a basic evaluation-phase macro system, which permits any
authorized users to extend the functionality of RoboBot directly from channels
without having to author a plugin. Macros can invoke functions or other macros.
Macros can even define other macros.
```
(defmacro add-one [n] '(+ n 1))
(add-one 5)
6
```
### Message Variables
The Variables plugin provides functions for setting and unsetting variables in
the context of a single message. These variables may then be reused anywhere else
in the message, though they will be discarded at the end and no longer accessible
(or defined) for subsequent messages.
Currently, you may not store a function in a variable (only the result of the
function), though support for functions as variables is planned for a future
release.
### Programmability
Combining the features already mentioned, RoboBot provides what amounts to a full
(though fairly simplified) programming environment within each message sent to
it. Variable state is reset with every message (unless a plugin were written to
provide a state-preserving feature), so programs are effectively limited to the
size of your chat server's message limit (typically a few hundred characters on
IRC, or about 16 kilobytes on Slack; other networks will vary).
But between the built-in functions, and the writing of macros by users, it is in
theory possible to develop non-trivial functionality entirely within the context
of a chat message.
### Access Control
RoboBot provides basic access control functionality, allowing you to define who
is permitted to call individual functions. It is recommended that sensitive
functions (such as those granting operator status, changing topics, and particularly
those allowing modification of the access control lists) be restricted to only
trusted users.
Access is granted/revoked by chat nickname, which means the controls are only as
good as your chat server's ability to authenticate/identify nicks. This should by
no means be considered a very strong access control mechanism.
### Legacy Bang Syntax
Admittedly, the S-Expression syntax can be a bit of a hurdle for new users. To
ease the introduction of RoboBot's functionality, a simplified alternate syntax
is supported. Functions and macros may be invoked without the parenthetical
expressions by simply prefacing the function or macro name with an exclamation
mark. Arguments follow as they normally would in the list context, separated by
whitespace (single multi-word arguments can still be double-quoted).
```
!roll 20 2
```
Is equivalent to:
```
(roll 20 2)
( run in 0.553 second using v1.01-cache-2.11-cpan-39bf76dae61 )