# 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 — add the top Radarr hit !tv — add the top Sonarr hit !music — 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.toml` to `config.toml` 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:** ```bash curl -H "X-Api-Key: YOUR_KEY" https://radarr.example.com/api/v3/qualityprofile ``` ## Running ### Local ```bash go build -tags goolm -o bellhop ./ ./bellhop -config config.toml ``` The `goolm` tag uses the pure-Go olm implementation so libolm isn't needed. ### Docker ```bash docker build -t bellhop . docker run -d \ --name bellhop \ -v "$PWD/config.toml:/app/config.toml: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/ — TOML 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.