Adopt the books you already have, requester accounts, client diagnosis and unattended discovery
Books a library scan could not match now wait on the Import page, where one click adopts them where they sit, with nothing moved and nothing downloaded. A new requester role lets someone browse the library and ask for a book, and an admin approves it. Every saved download client gets a Diagnose button that walks its paths, categories and hardlinks and puts the first thing to fix at the top. And Bindery can now check your monitored authors for new releases on its own, so a followed author's next book turns up without anyone clicking Refresh. Discovery ships off: turn it on in Settings, General, New release discovery. The top bar is down to five entries as well, with Library and Activity groups, and the rest of the release is fixes.
Added
- Adopt the books a library scan could not match (#2547): they now wait on the Import page under In your library, which is where
/importopens. Each row is a book rather than a file, so a 193 track audiobook is one row, a disc set is one row named after its folder, andDune.epubbesideDune.mobiis one row. A close title by the same author is one click to confirm, a weaker one is offered as a possible match to check first. Books by an author who is not in your library yet are one row with a single Add author. Any row opens in place to pick a book, search your library, or search metadata, and metadata providers are only asked when you press Search. Adopting registers the files where they are: nothing is moved and nothing is searched for, a book added from metadata comes in unmonitored in the format you adopted, and Undo reverses it exactly. Ignored books stay hidden across scans until you unignore them. Admins see how many books need a decision on the Import nav entry. - Requester role with admin approval: a new
requesterrole can browse the library read only, search for a book or an author and request it, and follow each request on My requests, but cannot grab, download, delete, use OPDS or see any settings. Admins get a Requests page with a pending count, where approving opens the usual add choices (profile, root folder, monitoring, format, search on add) and the added books are owned by the requester; declining takes an optional reason the requester sees. Set the role on the Users page, or make it the default for new OIDC logins withBINDERY_OIDC_DEFAULT_ROLE=requester. A requester signed in is held to the role in every auth mode, but indisabledandlocal-onlymode anyone who signs out is served as the admin, so useenabledorproxymode for requester accounts. A new Request webhook toggle announces new requests; it is off until you turn it on. A requester may have 25 requests waiting at once by default (requests.max_pending_per_user). - Diagnose a download client from Settings (refs #2031): a Diagnose button beside Test on each saved download client runs a short checklist and puts the first thing to fix at the top. It checks the saved settings, the connection, that the category exists, where Bindery's grabs actually land for ebooks and for audiobooks, for all six client types (the save path Bindery sends, the category folder, a Deluge label's move path or the client default, and it says which), which path remap applies, whether Bindery can read and write the resulting folder (naming a letter case mismatch or the user Bindery runs as), and whether imports can hardlink into each library folder. A last row always says Bindery cannot test whether the client reaches your indexers. Bindery only looks at a folder the client names when it sits under a configured download or library folder, and Copy report leaves out the host, port and username so it can be pasted into an issue.
- New releases arrive on their own (#2236): monitored authors can now be checked for new books on a schedule, so a followed author's next book joins your library without clicking Refresh. It ships off: turn it on in Settings, General, New release discovery, where Weekly is the interval to pick if you are not sure, with Daily and Monthly alongside it. Checks are spread over the interval a few authors an hour, pause while you run Refresh all or a bulk refresh, and stop early when a metadata provider rate limits or keeps failing; new books follow each author's monitor mode and metadata profile, and grabbing still waits for the wanted search and auto grab. Authors set to Monitor new items: Don't add them are never checked. Thanks to ianepreston for the detailed report.
- New book webhook alert (#2236): a new
bookAnnouncedevent lists the books a refresh or scheduled discovery added to an author you already had. It is off for every webhook, existing and new, until you turn on New book in the webhook's triggers. - Re-bind a book by searching the provider, not only by pasting an id (refs #492, #515): the book Re-bind dialog now searches OpenLibrary works and Hardcover books and lets you pick the right record from the results, with a Links menu to open each one upstream first, alongside the exact provider id entry it already had (Enter submits) and the existing author mismatch confirmation. OpenLibrary editions can still be viewed upstream but cannot be picked for a re-bind. Results already in your library are marked and linked, and a record another library book owns cannot be selected. The dialog is translated into all eight supported languages.
- Previous and Next on the book page (#2548): step through the books on the Books list, an author's own book list, or the Wanted list you came from, with no server round trip. It works within the currently loaded list page and does not survive a direct link or a freshly opened tab; a same tab reload keeps it, since it rides on the browser's own history state.
Changed
- The top bar is down to five entries: Library (Authors, Books, Series), Activity (Wanted, Queue, History, and Requests for an admin), Import, Calendar and Discover. Opening a group lands on its first page and a row of tabs above the content switches between the rest. Nothing moved: every page keeps the address it always had, bookmarks and the back button still work, the Import count and the pending requests count are still on the bar, and the phone menu lists the same pages indented under their group.
- The unmatched files table in Settings and the bulk folder scan in Settings > Import moved to the Import page (#2547). Settings now shows how many books need a decision with a link to review them, and the folder scan is Import > From a folder. The old list stopped at 1000 files; the new one has no such cap for ordinary libraries (it lists up to 20,000 books per scan and says when there are more). The
library.lastScansummary keeps its counters, addsunmatched_units,ignored_unitsandunits_truncated, and returnsunmatched_filesas an empty list for one release. - Refreshing an author whose profile filters on page count or ISBN no longer fetches editions for books it already has (#2236), so refreshes of large authors make far fewer provider calls.
- Every notification trigger says what sends it: in Settings, Notifications, each trigger (Grab, Import, Failure, Upgrade, Health, New book, Request) now carries a plain description, as a line under the chips and as a tooltip. Upgrade says it has no sender today rather than implying it fires.
- Notifications moved to Integrations in Settings' left nav, alongside the other outbound connections, instead of sitting under Sources next to Indexers and Download Clients.
- On a phone, Add Author is now the first button in the Authors toolbar, instead of wrapping onto a second row under Refresh all metadata, Merge and Add Book. The desktop layout is unchanged.
Fixed
-
Library scan: a series or box set folder no longer renames the books inside it (#2171). A file under
Author/The Wheel of Time/01 - The Eye of the World (1990).epubwas titled from its folder, so it reconciled onto whatever book the folder happened to name and the book it really is stayed Wanted, with the scan reporting success either way. The file's own name is now tried first and the folder is the fallback, which is how bulk import has always read the same layout. A leading position number is stripped from a folder title too, so a01 - The Eye of the World (1990)book folder matches as well. Audiobooks are unchanged in every layout: there the folder is the book and the files are its tracks. Thanks to nick7129 and hoxtonia for the reports.This stops new wrong matches; it does not repair old ones. A file that is already attached to the wrong book stays attached, because the scan skips anything it already tracks. To fix one, open the book it landed on, find the file in its Files list and use Fix match to move it to the right book. Removing the file from the wrong book and rescanning works too.
One layout loses by this change: if your folders are authoritative and your filenames carry the series rather than the book, as in
Robert Jordan/The Eye of the World/The Wheel of Time 01.epub, the scan now reads the filename and titles that file "The Wheel of Time". The folder is still tried when the filename matches nothing at all. -
Books stored under a "translated / original" title are searched by the translated title (#2391): some metadata gives a translated book a two language display title, such as "El imperio final / The Final Empire". Bindery sent that whole string to the indexers, where no release is named that way, so the book never found anything and never grabbed, while a search by hand on the indexer worked. When a title is exactly two parts joined by a spaced slash, and the book or your metadata profile names a language other than English (or the book's original title matches one part), Bindery now searches and matches on the translated part. Bundles such as "Second Nature / One Summer" on an English book, titles with more than one slash, and slashes inside brackets are left whole. Thanks IfritDMC, whose work in #2391 this is taken from.
-
Audiobookshelf imports no longer relink a book to a fallback provider while the primary is down (#2642): the ISBN match
enrichBookuses to relink a row walks past a primary provider that times out and takes the next provider's record, so an OpenLibrary blip could attach a DNB, Google Books or Hardcover id to an existing book for good. Once the primary was back, a lookup by its key missed the relinked row, which is where the duplicates come from (#2117, #2271, #2332). The relink is now skipped for that item with abook relink skippedreason naming the provider that did not answer, the row keeps the identity it already had, and the next import retries. A primary that answers and simply has no record for the ISBN still lets the fallback's record through, as before (#2237). This is the same guard the author path gained in #2271 and the Add Book dialog in #2612. -
Find better metadata can put an author back on a record it was linked to before (#2688): relinking wrote the old provider id into the author's identifier list so books added under it kept resolving, and the candidate picker then treated every one of those ids as already attached and hid it. Moving from a good record to a sparse duplicate was therefore a one way door, with adding the good record as a second author the only way back, which is exactly the duplicate the identifier list exists to prevent. The picker now hides only the record the author is linked to right now, and shows a quiet "previously linked" marker on records it used to be on so you can tell them apart. Relinking back keeps both ids on the author, one row each, and leaves the existing books alone. Thanks to flaevers for the report and the before and after ids.
-
Refreshing an author now fills in the series of books you already have (#2328): series membership used to be written only for books a refresh created, so on an imported library, where every book is already there and the author is not taking new ones, a refresh updated ratings, covers and genres and could never link a series. Relinking an author to a better metadata record and refreshing now repairs the series too. A link that is already stored is left exactly as it is, position included, so a position you corrected by hand is never overwritten; only missing links are added.
-
Search buttons no longer report success when automatic grabbing is off (#2669): the global auto grab switch stops every search at one chokepoint, including the ones you start by hand, but the bulk Search actions had already answered
{"ok":true}by the time the fan out hit it. The button flashed, the selection cleared, and the only trace was anauto-grab disabled globally, skipping searchline in the server log. Every bulk Search surface now refuses up front and says so: the author page "Search wanted" and its multi select Search, the Wanted page bulk Search, and the Authors and Books page bulk Search. The message names the setting to change, and your selection is kept so you can retry after flipping the switch. A single book Search Indexers still runs and still lets you grab a release by hand, which is the way to search with the switch off. Nothing else about the switch changed: the scheduled sweep, discovery and series fill all behave exactly as before. The Auto grab hint in Settings promised the opposite of what the code did, and now describes what actually happens. Thanks to ThatDeltaGuy for the report and the log lines. -
Calibre author names no longer keep the
|Calibre uses for a comma (#2666): a comma separates authors in Calibre's comma joined author columns, so a literal comma in a name is stored as|, and the Calibre library import copied the column straight through. Authors arrived asScalzi| John, a separate catalogue record that no metadata provider matches, with the sort name mangled the same way. Both columns are now unescaped per author row, the way Calibre's own readers do it; a book with co-authors still imports them as separate authors. -
A refresh that cannot read an author's books now stops instead of carrying on (#2236): it used to go on as if the author had none, which could bring back books you had excluded or add a second entry for a book you already had.
-
OIDC group sync no longer resets a non admin's role: with
BINDERY_OIDC_ADMIN_GROUPset, a login outside the admin group used to set the role touserevery time. Now only admin is decided by the group: an admin who leaves the group gets the default role, and everyone else keeps the role an admin gave them. -
The Authors page no longer scrolls sideways on a phone: its header kept the title and the whole toolbar on one line, which squeezed the title and pushed Merge, Add Book, Add Series, Add Author and Refresh all metadata off the right edge. The title now sits on its own line and the buttons sit under it at phone widths, the way the Books, Series and History headers already did. Every button is still there and does the same thing. Calendar's month controls and the Search Indexers box had the same problem at narrow widths and are fixed the same way.
-
Discover's "recommendations are off" screen links straight to the setting that turns them on: it used to send you to Settings with no tab, and the toggle is on the Metadata tab, not General. The screen, the button and the setting all say "book recommendations" now, and Refresh is hidden while the feature is off, since refreshing could never produce anything in that state.
-
Settings, General, File Naming, Import Mode reads properly again: the help text ran words together, reading "the library.Auto (the default)" and "keeps working.Move relocates". The missing spaces are back.
-
The Requests page titles the browser tab "Requests · Bindery" like every other page, instead of leaving it at "Bindery".
-
History and Requests have proper empty states: both were bare while Queue, Discover and Import had centered ones with a next step. Both are centered now, each with a line saying what will show up there.
-
A refused folder scan path now names the library roots it was checked against, rather than only saying it was outside them, so you can see what a valid path looks like. It also says so plainly when no root folder is configured yet. Lookup and manual import give the same answer.
Security
- A requester can only reach the routes the role allows: every API route a requester may call is on a single allow list, and every other route, including ones added later, answers 403 for that role. Paths that are encoded, doubled or dotted in a way that could route differently are refused, metadata searches, request creates and cover images are rate limited per requester, the pending cap holds under concurrent creates,
GET /auth/confignever returns the API key to a requester, and request text sent to webhooks has control characters removed, is length capped, and cannot mention a channel, use a Slack escape, form a markdown link or autolink a URL. A requester can trigger at most 10 of those webhooks an hour. - Book announcements no longer let a provider title forge a mention or a link (#2676): the
bookAnnouncedwebhook put provider text into the payload with only control characters stripped and a length cap, so a title from a publicly editable source such as OpenLibrary could carry@everyone, a Slack<!channel>escape, or a masked markdown link and render as a real mention or a clickable link in the operator's channel. Every provider string in the payload now goes throughnotifier.SafeText, the same sanitiser the request notifications use, which strips control and invisible characters, caps the length, and neutralises mention, escape and link syntax. Ordinary titles are unchanged.