R16 – Community-Driven Interactive Code Evaluation
1 Configuration
2 The Trick Environment
3 Discord Frontend
3.1 Discord Configuration
3.2 Trick Environment Extensions
8.2

R16 – Community-Driven Interactive Code Evaluation

R16 is a "trick bot". It saves snippets of code, which can then be recalled and executed on user-provided input.

As of the time of writing, there exists one frontend, for Discord. More are planned, so this manual is structured by frontend.

1 Configuration

The bot is run by invoking its main.rkt file, and stores its configuration in a JSON file that is read on startup. See the -h output for precise details about command-line flags.

The configuration file must contain a top level object with the following keys and associated values:

A working default configuration for the Discord frontend:
{
  "storage": "/home/r16bot/r16_save_data",
  "frontend": {
    "module": "r16/frontends/discord",
    "bot_token": "<your bot token here>"
  }
}

2 The Trick Environment

Tricks are stored as plain text, and invoked in a sandbox using racket/sandbox.

The following values are available in the sandbox’s namespace:

procedure

(call-trick name argument)  any/c

  name : (or/c symbol? string?)
  argument : any/c
Invokes another trick named by name and return its result. If argument is #f, then an empty string is passed to the subtrick. Otherwise, (~a argument) is passed.

value

string-args : string?

Text of the message after the bot command, as a string.

value

trick-name : string?

The name of the currently running trick, as a string. For ad-hoc evaluations, the string is empty.

procedure

(read-args)  (or/c (listof any/c) #f)

Function that returns string-args, but as a list of datums read by read. If there is a read failure, #f is returned.

value

parent-context : (or/c (hash/c symbol? any/c) #f)

If the currently executing trick is a top-level trick invocation, #f. Otherwise, a mapping of all the provided symbols (such as string-args, etc.) in the context of the parent that executed call-trick.

3 Discord Frontend

This frontend provides integration with the Discord chat service.

Commands to the bot are issued by prefixing Discord messages with a configurable prefix value. The rest of the message is then treated as a command. For more details, send the message <bot_prefix> help in your Discord server.

The frontend also has a configurable trick shorthand prefix. Messages of the form <trick_prefix>foo bar ... are equivalent to <bot_prefix> call foo bar ....

3.1 Discord Configuration

The frontend object in the configuration file can have the following keys and values:
  • module must be the string "r16/frontends/discord".

  • bot_token must be a string containing your Discord bot token.

  • bot_prefix is a string specifying the bot’s trigger prefix. If not present, defaults to "!rkt ".

  • trick_prefix is a string specifying the bot’s shorthand prefix. If not present, defaults to "!!".

3.2 Trick Environment Extensions

In additional to the bindings described above, the following items are available in the trick environment.

procedure

(delete-caller)  void?

Delete the message that invoked this sandbox.

procedure

(emote-lookup name)  (or/c string? #f)

  name : string?
Function that returns the ID for emote with name name, or #f if it doesn’t exist.

procedure

(emote-image id)  (or/c bytes? #f)

  id : string?
Function that returns the PNG data of the emote with ID id, or #f if it doesn’t exist.

procedure

(make-attachment payload name mime)  any/c

  payload : bytes?
  name : (or/c string? bytes?)
  mime : (or/c symbol? string? bytes?)
Creates an attachment with payload payload, filename name, and MIME-type mime. This object must be returned from the trick to be sent to Discord. If more than one attachment is returned, an unspecified one is sent.

value

message-contents : string?

Full text of the message that invoked this trick.

procedure

(read-storage type)  any/c

  type : (or/c 'guild 'channel 'user)
Reads "trick-local storage" type and return its result, or #f if the result is uninitialized.

A trick’s "trick-local storage" can be per-guild, per-channel, or per-user.

This will always return #f for the eval command.

procedure

(write-storage type data)  boolean?

  type : (or/c 'guild 'channel 'user)
  data : any/c
Writes data to the trick’s "trick-local storage," overwriting any existing value, and returns whether the write succeeded. All data supported by write can be written.

A trick’s "trick-local storage" can be per-guild, per-channel, or per-user; each type of storage has its own limitation on size:

Type

 

Size Limit

guild

 

64 KiB

channel

 

8 KiB

user

 

2 KiB

This will always be a no-op when invoked from the eval command.

procedure

(attachment-data attachment)  bytes?

  attachment : any/c
Get the payload of an attachment created with make-attachment.

procedure

(open-attachment [index])  (or/c input-port? #f)

  index : natural? = 0
Opens the indexth attachment of the message that invoked this sandbox, as an input port.

Returns #f if the message doesn’t have an indexth attachment, or if the attachment couldn’t be opened for any other reason.

procedure

(open-reply-attachment [index])  (or/c input-port? #f)

  index : natural? = 0
Same as open-attachment, except fetching the attachment of the message that the invoking message replied to.

value

attachment-count : natural?

The number of files attached to the message that invoked this sandbox.

value

reply-attachment-count : natural?

The number of files attached to the message that the invoking message replied to.