prosolis 8c295d183b Session 5: Dockerfile, config example, README rewrite
Multi-stage alpine Dockerfile builds with -tags goolm so libolm isn't
needed at runtime. Annotated config.example.yaml documents every field
and shows ${ENV_VAR} usage for secrets. README is rewritten for the Go
bot — Python-era web-portal docs are gone.
2026-05-24 20:29:13 -07:00

Bellhop

A Matrix bot that adds movies, TV, and music to Radarr/Sonarr/Lidarr from chat. Invite the bot to a room, allowlist the room ID, and any member can type !movie dune to add the top search hit.

Command UX

!movie <query>   — add the top Radarr hit
!tv <query>      — add the top Sonarr hit
!music <query>   — add the top Lidarr hit
!help            — show the command list

The bot replies in a thread under the request so a busy room stays readable. No numbered picker, no reaction selector — the top search result is what gets added. If you want something other than the top hit, narrow the query.

Authorization

Any member of an allowlisted room may issue commands. The bot auto-joins on invite, but the room ID must appear under matrix.allowed_rooms in the config before commands are honored.

Configuration

Copy config.example.yaml to config.yaml and edit. The loader expands ${ENV_VAR} references at load time, so secrets can come from the environment.

Required:

  • matrix.homeserver, matrix.user_id, matrix.password
  • matrix.allowed_rooms (at least one room ID)
  • At least one of services.radarr / services.sonarr / services.lidarr

Per-service: url, api_key, quality_profile_id, root_folder. Lidarr also needs metadata_profile_id.

Omit a service block to disable its command — !movie with no radarr block replies "Radarr is not configured".

Finding quality profile IDs:

curl -H "X-Api-Key: YOUR_KEY" https://radarr.example.com/api/v3/qualityprofile

Running

Local

go build -tags goolm -o bellhop ./
./bellhop -config config.yaml

The goolm tag uses the pure-Go olm implementation so libolm isn't needed.

Docker

docker build -t bellhop .
docker run -d \
  --name bellhop \
  -v "$PWD/config.yaml:/app/config.yaml:ro" \
  -v bellhop-data:/app/data \
  bellhop

The data volume holds the Matrix device file and the E2EE crypto store. Losing it forces a re-login and re-verification on next start.

E2EE notes

The bot bootstraps cross-signing on first run and persists Olm/Megolm sessions in data/crypto.db. If you rotate the bot's password or wipe data/, the bot logs in as a new device — existing rooms will need to re-share keys, which mautrix handles automatically on the next message.

Project layout

main.go
internal/
  config/   — YAML loader with ${ENV_VAR} expansion
  matrix/   — mautrix client: login, device persistence, E2EE, sync loop
  arr/      — Radarr/Sonarr/Lidarr HTTP clients
  bot/      — command parser + dispatch + threaded replies

License

See repository for license details.

Description
Frontend interface for placing requests to *arr instances.
Readme 102 KiB
Languages
Go 98.6%
Dockerfile 1.4%