A feature release built around library management. Two new tools for keeping an
existing library tidy — Rename files (reorganize files to the current
naming template) and Match to book (rescue a completed download the
auto-matcher couldn't place) — plus a guard against auto-grab pulling in
unrelated movie/TV releases and a fix for German National Library catalogues
showing one book per printing.
Added
- Rename files: reorganize an existing library to the naming template
(#1181) — the naming template used to apply only at import time, so changing
it later, importing a pre-existing library, or ending up with a half-renamed
mix left no way to reconcile files short of deleting and re-importing. A new
Rename files action (on the book detail page and the author page) previews
every tracked file'scurrent → proposedpath under the current template and,
once confirmed, moves the ones that differ — updating the library index and
recording a rename in history. It is always a move within the library (never a
copy), refuses to overwrite an existing destination, skips files already in
the right place, and leaves anything not on disk untouched. Ebooks move as
single files; audiobooks move as whole folders. Backed by
GET /api/v1/reorganize/previewandPOST /api/v1/reorganize/apply(both
admin-only). Whole-library scope is available through the API; the UI exposes
the per-book and per-author scopes. - Manually match an unmatched download in the queue (#1589) — a download the
auto-matcher couldn't tie to a book ("could not match any book to this
download") used to sit in the queue as a dead-end import failure. Import-failed
items now have a Match to book control: search your library, pick the book
the files belong to, and Bindery imports the already-downloaded files against
it — attaching the file and flipping the download to imported, with inline
feedback. The scanner now records where an unmatched download's files are (it
previously discarded that path), so the match can import them directly instead
of hoping the download client still remembers the release; downloads without a
recorded path fall back to a client re-poll. Downloads the scanner terminally
blocked after exhausting their import-retry budget (the "stuck after three
attempts" case) are recoverable too — the Match to book and Retry import
controls now appear forimportBlockeditems, and a match re-imports the
recorded files (or re-arms the scanner with a fresh retry budget) instead of
leaving them permanently stuck.
Fixed
- Auto-grab no longer selects or imports unrelated video releases (#1591) —
an automatic audiobook search could pick a movie, TV, or music release that
shared a few words with the book title, download it, and move the whole folder
(video file included) into the audiobook library marked as imported. Two new
guards close this: release names carrying video-only markers (1080p,x265,
WEBRip,S01E02, and similar) and results the indexer filed under a
movie/TV/console/PC category are now dropped from book search results; and at
import time, a download whose largest file is a video file is blocked for
manual review instead of being imported (an explicit format chosen through
manual import overrides the block). - DNB author catalogues collapse editions into one book per work (#1585,
#1586) — the Deutsche Nationalbibliothek issues one MARC record per edition,
printing, and volume with no work abstraction, so adding a DNB-primary
author's catalogue produced a wall of near-duplicate books for the same work.
The author-works path now groups records by work and volume, drops the
combined volume-0 record when a work has numbered volumes, and rebuilds each
representative's title from its series/volume statement, so one work becomes
one book. Existing libraries keep any duplicate rows already imported (the
author sync is add-only); remove them manually or via a future merge (#1358). - Security: the wanted/missing list is now scoped per user (#1600) — under
multi-user tenancy (BINDERY_ENFORCE_TENANCY),GET /api/v1/wanted/missing
returned every user's wanted/missing books to any non-admin instead of just
their own, the one book-list route that had missed theowner_user_idscope
applied everywhere else. It now filters like the main book list; admins,
API-key, and single-tenant deployments are unaffected.
Changed
- The queue Retry import control now also revives downloads the scanner
terminally blocked (importBlocked) after exhausting their retry budget, not
onlyimportFailedones — previously it silently no-op'd on blocked items.
(Part of #1589.) - Dependencies:
modernc.org/sqlite1.53 → 1.54, the distroless base image
for the main binary and the discord-stats/telemetry sidecars, and seven
minor/patch web dependencies (#1582, #1583, #1584, #1554, #1555).
Docs
- Clarified that
BINDERY_LIBRARY_DIRis a scan/reconcile target in External
import mode, not a destination Bindery writes to (#1558).