Adapted from Pete: password login + device persistence, cryptohelper with cross-signing bootstrap, sync loop with auto-join on invite, and PostThreadedReply for command responses. Messages outside allowed_rooms are dropped.
58 lines
2.8 KiB
Markdown
58 lines
2.8 KiB
Markdown
# Bellhop Go Rewrite — Session Plan
|
|
|
|
Rewriting Bellhop from a Python FastAPI web portal into a Go-based Matrix command bot, modeled after [Pete](../pete). Users issue commands like `!movie dune` in allowlisted Matrix rooms; the bot performs the top-hit search against Radarr/Sonarr/Lidarr and adds the result.
|
|
|
|
## Design decisions (locked in)
|
|
|
|
- **Command UX:** top-hit auto-add (no numbered picker, no reaction selector).
|
|
- **Authz:** any member of an allowlisted room ID can issue commands. No per-user list.
|
|
- **Old Python code:** deleted, clean-slate Go rewrite.
|
|
- **Module layout:** mirrors Pete (`main.go` + `internal/<pkg>/`).
|
|
- **Config:** YAML with `${ENV_VAR}` expansion (Pete-style).
|
|
- **Matrix client:** mautrix-go with cryptohelper for E2EE support.
|
|
|
|
## Session breakdown
|
|
|
|
- [x] **Session 1 — Foundation**
|
|
- Delete Python (`app/`, `requirements.txt`, `Dockerfile`, `.env.example`)
|
|
- Reset `.gitignore` / `.dockerignore` for Go
|
|
- `go.mod` (mautrix + yaml)
|
|
- `internal/config/config.go` — YAML loader: matrix creds, `allowed_rooms`, `services.{radarr,sonarr,lidarr}`
|
|
|
|
- [x] **Session 2 — Matrix client** (`internal/matrix/`)
|
|
- Adapt Pete's `client.go`: login + device persistence + cryptohelper
|
|
- Sync loop, auto-join on invite
|
|
- Message handler scoped to `allowed_rooms` (not channel-name map like Pete)
|
|
- Threaded reply helper for command responses
|
|
- Drop Pete-specific bits: image upload, reaction handler, story formatting
|
|
|
|
- [ ] **Session 3 — *arr clients** (`internal/arr/`)
|
|
- One file per service or a single generic client (TBD in session)
|
|
- `Search(term) → []Result` and `Add(result) → error`
|
|
- Radarr: `/api/v3/movie/lookup` + POST `/api/v3/movie`
|
|
- Sonarr: `/api/v3/series/lookup` + POST `/api/v3/series`
|
|
- Lidarr: `/api/v1/artist/lookup` + POST `/api/v1/artist`
|
|
- All adds: monitored=true, search-on-add=true, quality profile + root folder from config
|
|
- Unit tests with httptest
|
|
|
|
- [ ] **Session 4 — Command dispatch + main** (`internal/bot/`, `main.go`)
|
|
- Parse `<prefix><cmd> <query>` (default prefix `!`)
|
|
- Commands: `movie`, `tv`, `music`, `help`
|
|
- On match: search → take `[0]` → add → reply with title/year (or error)
|
|
- "Service not configured" reply if the corresponding *arr block is absent
|
|
- `main.go`: load config, init matrix, wire handler, SIGINT/SIGTERM shutdown
|
|
|
|
- [ ] **Session 5 — Ship polish**
|
|
- Multi-stage Dockerfile (`golang:1.25-alpine` → `alpine:3.21`, build with `-tags goolm`)
|
|
- `config.example.yaml`
|
|
- Rewrite `README.md`: command UX, install, config reference, Docker
|
|
- `go build ./...` + `go vet ./...` clean
|
|
|
|
## Out of scope (for now)
|
|
|
|
- Reaction-based result picker
|
|
- Per-user allowlist or power-level gating
|
|
- Persistent request audit log (the Matrix room itself is the audit trail since requests are in-channel)
|
|
- Removal/cancellation commands
|
|
- Search-only mode (browse without adding)
|