Trinity is an experimental bot framework written in Rust and using matrix-rust-sdk, as well as commands / modules compiled to WebAssembly, with convenient developer features like modules hot-reload.
This started as a fun weekend project where I've written a new generic Matrix bot framework. It is written in Rust from scratch using the fantastic matrix-rust-sdk crate.
Bot commands can be implemented as WebAssembly components, using Wasmtime as the WebAssembly virtual machine, and wit-bindgen for conveniently implementing interfaces between the host and wasm modules.
See for instance the uuid
and horsejs
modules.
Make sure to install cargo-component
first
to be able to build wasm components. We're using a pinned revision of this that can automatically
be installed with ./modules/install-cargo-component.sh
at the moment; we hope to lift that
limitation in the future.
Modules can be hot-reloaded, making it trivial to deploy new modules, or replace existing modules already running on a server. It is also nice during development iterations on modules. Basically one can do the following to see changes in close to real-time:
- run trinity with
cargo run
cd modules/ && cargo watch -x "component build --target=wasm32-unknown-unknown --release"
in another terminal
The overall generic design is inspired from my previous bot, botzilla, that was written in JavaScript and was very specialized for Mozilla needs.
At this point I expect this to be more of a weekend project, so I won't commit to any of those, but here's my ideas of things to implement in the future. If you feel like implementing some of these ideas, please go ahead :)
- fetch and cache user names
- make it possible to answer privately / to the full room / as a reply to the original message / as a thread reply.
- add ability to set emojis on specific messages (? this was useful for the admin module in botzilla)
- moonshot: JS host so one can test the chat modules on a Web browser, without requiring a matrix
account
- marsshot: existing modules built from CI and pushed to a simple Web app on github-pages that allows selecting an individual module and trying it.
- seek other
TODO
in code :p
- post on twitter. Example:
!tweet Inflammatory take that will receive millions of likes and quote-tweets
- same requirements as mastodon, likely
- gitlab auto-link to issues/merge requests: e.g. if someone types
!123
, post a link tohttps://{GITLAB_REPO_URL}/-/issues/123
.- would require the room to be configured with a gitlab repository
- same for github would be sweet
- ask what's the weather in some city, is it going to rain in the next hour, etc.
- YOUR BILLION DOLLARS IDEA HERE
If you want, you can use the image published on Docker (bnjbvr/trinity) -- it might be lagging behind by a few commits -- or build the Docker image yourself:
docker build -t bnjbvr/trinity .
Then start it with the right environment variables (see also .env.example
):
docker run -e HOMESERVER="matrix.example.com" \
-e BOT_USER_ID="@trinity:example.com" \
-e BOT_PWD="hunter2" \
-e ADMIN_USER_ID="@admin:example.com" \
-v /host/path/to/data/directory:/opt/trinity/data \
-ti bnjbvr/trinity
Data is saved in the /opt/trinity/data
directory, and it is recommended to make it a volume so as
to be able to decrypt messages over multiple sessions and so on.
If you want, you can specify a custom modules directory using the MODULES_PATHS
environment
variable and adding another data volume for it. This can be useful for hacking modules only without
having to compile the host runtime. Here's an example using Docker:
docker run -e HOMESERVER="matrix.example.com" \
-e BOT_USER_ID="@trinity:example.com" \
-e BOT_PWD="hunter2" \
-e ADMIN_USER_ID="@admin:example.com" \
-e MODULES_PATH="/wasm-modules" \
-v /host/path/to/data/directory:/opt/trinity/data \
-v /host/path/to/modules:/wasm-modules \
-ti bnjbvr/trinity
Trinity can be configured via config file. The config file can be passed in from the command line:
cargo run -- config.toml
Or it can be placed in $XDG_CONFIG_HOME
, typically ~/.config/trinity/config.toml
on XDG
compliant systems. Configuration lives in the document root, for example:
home_server = "matrix.example.com"
user_id = "@trinity:example.com"
password = "hunter2"
matrix_store_path = "/path/to/store"
redb_path = "/path/to/redb"
admin_user_id = "@admin:example.com"
modules_path = ["/wasm-modules"]
It's also possible to pass arbitrary configuration down to specific modules in the config file. For example:
[modules_config.pun]
format = "image"
This passes the object {"format": "image"}
to the pun
module's init
function. It's
up to specific modules to handle this configuration.
Yes.
We welcome community contributions to this project.
This is a Matrix bot, coded in Rust and WebAssembly, forming a holy trinity of technologies I love. And, Trinity is also a bad-ass character from the Matrix movie franchise.