R16 — Community-Driven Interactive Code Evaluation
1 Configuration
2 The Trick Environment
3 Discord Frontend
3.1 Discord Configuration
3.2 Discord Trick Environment Extensions
4 HTTP Frontend
4.1 HTTP Frontend Configuration
4.2 HTTP Trick Environment Extensions
8.12

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.

This manual is structured by frontend. A frontend is a way through which users can interact with the bot.

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",
  "frontends": [
    {
      "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 "!!".

  • delete_time is a nonnegative integer specifying a time in seconds. If any invocation of R16 is deleted within this time, then R16 will also delete its response. This helps with spam due to incorrect trick invocations. If not present, defaults to 5 minutes (300 seconds). Set to 0 to disable this feature.

3.2 Discord 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. The emotes of the guild that the triggering message was sent in are searched first, then the emotes of other guilds the bot is part of are searched in unspecified order.

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.

value

reply-contents : (or/c string? #f)

The full message content of the message that the invoking message replied to.

4 HTTP Frontend🔗

The HTTP frontend turns R16 into a web application. On startup, R16 starts an HTTP server on the local machine at the given port, which allows tricks to be registered and called from HTML forms.

Caveat: R16 will only bind to localhost, and will not use TLS. Please set up a reverse proxy with TLS termination in front of the bot if you plan to expose it to the internet.

4.1 HTTP Frontend Configuration🔗

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

  • port is an integer specifying which port to bind the web server to. If not present, defaults to 8080.

4.2 HTTP Trick Environment Extensions🔗

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

procedure

(make-image png-bytes)  any

  png-bytes : bytes?
Returns an opaque value representing a PNG image containing the given bytes. If a trick invocation returns such a value, then the image is rendered to the user inline in the browser.