# Architecture nzbstr is a two-halves daemon: - **Reader** (Phase 1+): subscribes to Nostr relays for kind 2003 (torrent) and kind 2004 (torrent comment) events, indexes them locally in SQLite, and exposes a Torznab-compatible HTTP API. - **Writer** (Phase 4+): watches a download client (qBittorrent / Transmission / Deluge) for completed downloads, builds NIP-35 events signed by your npub, and publishes them to configured outbox relays. ## Data flow ``` Sonarr / Radarr / Lidarr / Readarr / Prowlarr | v Torznab HTTP/XML | +-----------+ | nzbstr | | reader | <-- subscribes to relays via WebSocket | writer | --> publishes via WebSocket +-----------+ ^ ^ | | v v Nostr relays qBittorrent / Transmission / Deluge (NIP-35 events) (download client) ``` ## Components ### `cmd/nzbstr` — main daemon Entry point. Loads config, opens the SQLite database (applying any pending migrations), starts the HTTP server, and installs signal handlers for graceful shutdown. ### `internal/config` koanf-based configuration loading. Load order: compiled-in defaults → YAML file → environment variables (`NZBSTR_` prefix). Missing files are silently skipped so the daemon can start with all defaults. ### `internal/db` SQLite access via `modernc.org/sqlite` (pure Go, no CGO). Includes an embedded migration runner that applies numbered SQL files from `internal/db/migrations/` on startup. Uses WAL journal mode and a single writer connection for safe concurrent reads. ### `internal/server` chi-based HTTP server. Phase 0 exposes only `/health`. Phase 1 adds `/api?t=caps`, `/api?t=search`, etc. ### `internal/nostr` (Phase 1+) Relay subscription loop using `github.com/nbd-wtf/go-nostr`. NIP-77 negentropy bootstrap for efficient historical sync. Parses kind 2003 events into the internal `Torrent` struct and writes them to SQLite. ### `internal/torznab` (Phase 1+) chi routes for the Torznab API. Auth middleware validates API keys. Returns XML in Torznab RSS format. Categories mapped from NIP-35 `i` tags to newznab integer codes. ### `internal/enrich` (Phase 2+) Title parser (extracts season/episode/quality/source from release names) and TMDB client for backfilling IMDB/TMDB/TVDB IDs on events that lack them. ### `internal/wot` (Phase 3+) Web-of-Trust filter. Fetches the operator's kind 3 follow list and optionally follows-of-follows to build an allowed-pubkey set. Integrates with NIP-51 curation sets. ### `internal/publisher` (Phase 4+) qBittorrent / Transmission / watch-dir integration. Polls for completed downloads in the configured category, builds kind 2003 events, signs them via NIP-46 bunker or local key, and publishes to outbox relays. ## Storage Single SQLite file at `/var/lib/nzbstr/nzbstr.db`. Schema managed by embedded SQL migrations in `internal/db/migrations/`. FTS5 virtual table on `(title, description)` with triggers to keep it in sync. ## Deployment Single static binary + systemd unit. No external services required. Sits behind nginx for TLS termination. See `deploy/nzbstr.service` and `deploy/nginx.conf.example`.