r9k bot for matrix
0

Configure Feed

Select the types of activity you want to include in your feed.

Rust 98.3%
Dockerfile 1.7%
2 1 0

Clone this repository

https://git.vm.fail/dsx.sh/matrix-r9k https://git.vm.fail/did:plc:bxvdm3oqjvy3m52vvoddkgke
ssh://git@knot.vlan.foo:2222/dsx.sh/matrix-r9k ssh://git@knot.vlan.foo:2222/did:plc:bxvdm3oqjvy3m52vvoddkgke

For self-hosted knots, clone URLs may differ based on your setup.


README.md

r9k-bot#

An encrypted Matrix Robot9000-style moderation bot. Each room gets a permanent set of previously posted text. While R9K mode is enabled, a message whose content is already in that set is redacted.

Behavior#

  • Text, notices, and emotes share one room-local uniqueness set.
  • Repeats by the original sender are duplicates too.
  • Unicode is normalized to NFC, so canonically equivalent text collides.
  • Emoji in message bodies participates in duplicate detection.
  • Reactions, media, state events, and bot commands are ignored.
  • Reply fallback quotations are removed before comparison.
  • Edits claim their new content without releasing the original content.
  • Disabling enforcement does not stop collection.

The bot stores keyed BLAKE3 digests, not message plaintext. A one-time forward history pass seeds each room with all decryptable text visible to the bot. Historical duplicates are not retroactively redacted.

Matrix setup#

Use a dedicated Matrix account with password login enabled:

  1. Start the bot and invite its account to a room.
  2. Give the account enough room power to redact other users' events.
  3. As a room moderator, send !r9k on.

The bot accepts invitations from users on its own homeserver by default. R9K_TRUSTED_INVITERS can replace that behavior with an explicit comma-separated user-ID allowlist.

Room commands:

!r9k on
!r9k off
!r9k status

Commands are acknowledged with reactions, which do not enter the uniqueness set. Only users with power level 50 or higher can control the mode.

Configuration#

Required environment variables:

Variable Purpose
MATRIX_USERNAME Full bot user ID, such as @r9k:example.org
MATRIX_PASSWORD Bot account password
R9K_STORE_PASSPHRASE Encrypts the Matrix SDK's persistent store
R9K_HASH_KEY Exactly 32 random bytes encoded as 64 hexadecimal characters

Optional variables:

Variable Default Purpose
MATRIX_HOMESERVER http://tuwunel:6167 Client API base URL
MATRIX_DEVICE_ID R9KBOT Stable Matrix device ID
MATRIX_RECOVERY_KEY unset Recovers secret storage and room-key backups
R9K_DATA_DIR /data Persistent SDK and ledger directory
R9K_TRUSTED_INVITERS local users Comma-separated invitation allowlist
RUST_LOG info Standard tracing filter

Generate the independent storage secrets with:

openssl rand -hex 32
openssl rand -hex 32

Do not reuse either value as the Matrix password or recovery key.

Run locally#

The project requires Rust 1.93 or newer:

cargo test
cargo run

The data directory must be persistent. SQLite and the Matrix SDK crypto store should use a local filesystem rather than NFS.

Container#

docker build -t git.dragonfruit.dev/ryphon/r9k-bot:latest .
docker run --rm \
  --env-file .env \
  --volume r9k-data:/data \
  git.dragonfruit.dev/ryphon/r9k-bot:latest

The image runs as UID/GID 10001 and requires write access to /data.