github vavallee/bindery v1.17.0

4 hours ago

Added

  • Post-import drop folder for external library tools (#941) — a new way to hand finished downloads to a tool that owns your library (Calibre-Web-Automated, Calibre auto-ingest, Storyteller). With Import Mode set to External, Bindery now renames each completed download into a configurable drop folder (copy or hardlink — never a move, so torrents keep seeding) instead of leaving it in the download directory, then reconciles the managed copy the external tool produces on the next library scan. Previously this was impossible: normal modes wrote into the library and the CWA mirror (so the file landed in both places and CWA fought Bindery over the library dir), while plain External mode left the file unrenamed in the download dir. Configurable layout (flat file in the folder root vs templated {Author}/{Title}/… tree) and placement (copy/hardlink) under Settings → General → File Naming. New settings import.drop_folder / import.drop_layout / import.drop_link_mode; the existing cwa.ingest_path mirror is unchanged for the "Bindery owns the library" topology. Fixes the recurring CWA ingest-routing reports and is the foundation for Storyteller pair-gated handoff (#942). See docs/DEPLOYMENT.md → "Handing off to another library tool".
  • Outbound proxy support (#986) — route Bindery's remote-facing outbound HTTP through an http/https/socks5 proxy via BINDERY_OUTBOUND_PROXY (e.g. a VPN container's Privoxy on :8118, or socks5://gluetun:1080), the same capability Sonarr/Radarr expose. In scope: indexer searches, metadata/cover providers, webhook notifications, and the telemetry ping; download clients and OIDC discovery stay direct. LAN / loopback / single-label destinations (e.g. a Docker prowlarr / jackett) are dialled direct by default so a local indexer manager stays reachable — tune with BINDERY_OUTBOUND_PROXY_BYPASS_LOCAL (default true) and BINDERY_OUTBOUND_PROXY_NO_PROXY (comma-separated hosts / domain suffixes / CIDRs). Parsed once at startup into a shared, proxy-aware transport in internal/httpsec; credentials travel in the URL userinfo and are never logged. Env-var only — no new dependency (stdlib dials all three schemes).
  • Refresh metadata for every author (#863) — a one-click "Refresh all metadata" background job on the Authors page that re-fetches each author's metadata and catalogue, with progress that survives a page reload. Useful after a first import to backfill descriptions, covers, and missing books.
  • Per-indexer priority is now editable in the UI (#1009) — the add/edit indexer form exposes the priority the searcher already uses to break ties when the same release is found on multiple indexers (e.g. prefer your Usenet indexers over torrent ones). Manually-added indexers previously had no way to set it, so it was stuck at 0; default is unchanged.

Changed

  • Loopback URLs are now allowed for admin-configured service endpoints — download clients, indexers, Prowlarr, the Audiobookshelf base URL, and the Calibre plugin URL now accept http://127.0.0.1:… / localhost (new PolicyLANLoopback SSRF tier). Previously the SSRF guard blocked all loopback with no escape hatch, which made a legitimate, common topology impossible: a companion service bound to 127.0.0.1, or both containers on network_mode: host, could not be reached (e.g. SABnzbd on 127.0.0.1:50155 was rejected with "url not allowed: points to loopback address"). These endpoints are admin-only and CSRF-gated, so the loopback block bought ~no security. Untrusted paths are unchanged: proxied cover images and outbound webhooks still block loopback, and link-local + cloud-metadata (e.g. 169.254.169.254) remain blocked everywhere. The release/torrent download URLs returned by indexers also still block loopback (a malicious indexer must not be able to point Bindery at internal services).

Fixed

  • Transmission: indexer links that redirect to a magnet now work (#1006) — public trackers (The Pirate Bay, Knaben, …) surfaced via Prowlarr/Jackett often serve an http(s) download link that 30x-redirects to a magnet: URI. Bindery fetched that link with Go's HTTP client, which tried to follow the redirect and failed with unsupported protocol scheme "magnet", so the grab never reached Transmission. The Transmission client now follows redirects manually (re-validating each hop against the SSRF policy) and hands a redirected magnet straight to Transmission's filename arg — matching how the qBittorrent client already behaves (internal/downloader/transmission/client.go).
  • Library scan now records a result on early returns (#965) — when the library directory was literally unset, or the book listing failed mid-scan, ScanLibrary returned without persisting anything, so the Settings → General "Library Scan" section kept showing a stale prior scan instead of reflecting the failure (and the #962 "no files found" warning never fired for an unset directory). Both paths now persist a scan result carrying a scan_error message ("library directory not configured" / "scan failed: …") that the UI renders the same way as other scan-outcome warnings. Additive, backward-compatible result field (scan_error); the matching logic is unchanged (internal/importer/scanner.go).
  • Retired the dead CSV searchOnAdd column (#966) — after CSV import began always fetching each author's catalogue (#963), the optional third searchOnAdd column no longer gated anything and never triggered downloads. It is now dropped from the documented format and treated as ignored. The parser stays lenient, so existing users' three-column files keep importing unchanged; the dead field/plumbing is removed (internal/migrate/csv.go).
  • Backlist books no longer show a misleading "Wanted" pill (#977) — status and monitored are orthogonal (every book starts status=wanted; backlist siblings are added unmonitored), but the status pill rendered status alone, so an unmonitored backlist book read "Wanted" while correctly never appearing on the Wanted page (which lists status=wanted AND monitored). A shared bookStatusBadge helper now makes the pill monitored-aware across the book detail page, book lists, and author rows: wanted + monitored → "Wanted"; wanted + unmonitored → "Not monitored" (muted). No status/model/DB change.
  • Authors and Books pages now reach past the first 100 entries (#1010) — the list, search, sort, and filters are applied server-side and paginated, so libraries with more than 100 authors or books are fully browsable. Previously only the first page loaded, author/book name search was limited to that page, and the footer always read "1–100 of 100". Author/book name search is now matched on the server (book search also matches the author's name).

Don't miss a new bindery release

NewReleases is sending notifications on new releases.