Skip to content

v1.35.0

Latest

Choose a tag to compare

@github-actions github-actions released this 09 Sep 01:16
· 1 commit to main since this release
881eaaf

Search and author identity, largely rebuilt. Read the two warnings below before upgrading.

Forty eight entries from twenty eight merged pull requests, and most of them are
one piece of work. Bindery had four separate ideas about what makes two pieces of
text the same, and they disagreed with each other. Library search folded only the 26 ASCII
letters, so muller never found Müller. There are now three alphabets, one
each for search, identity and comparison, and the differences between them are
deliberate and tested rather than accidental.

What that fixes, in the places you would notice it: searching finds accented,
non-Latin and punctuated titles, and ranks the results instead of listing them
alphabetically. Foundation & Empire and Foundation and Empire stop being two
books. José Saramago stops being two authors. A metadata profile set to
Brazilian Portuguese no longer accepts a book and then hides every release of it.
And author sort names follow the Library of Congress rule, so Ursula K. Le Guin
files under L instead of under G.

Matching is stricter, and some things that used to resolve now ask you

This is the change most likely to look like a regression, so it is worth saying
plainly. Deciding two names are the same person used to come down to one
similarity score, and that score is dominated by whatever two names have in
common. Christopher Ross and Christopher Rose scored high enough to be merged
into a single author. Names are now compared field by field, and a short surname
has to match exactly.

The result is that some pairs which used to resolve silently now go to review
instead: Robert Jordan against Robert Jordon, Isaac Asimov against Issac
Asimov
, Brandon Sanderson against Brendon Sanderson. One letter apart on a
surname is two different people at least as often as it is a typo. In the same
spirit, a canonical book match now declines when the winner is barely ahead of the
runner up, and an ISBN whose check digit does not verify is no longer used to
search indexers.

Going the other way, J.R.R. Tolkien and John Ronald Reuel Tolkien now resolve
on their own, which is the commonest way a release name and a catalogue record
disagree about the same person.

Authors already merged the old way stay merged until you split them. Splitting
them will now stick.

Your first start after upgrading will take a moment

An existing library runs five one time repair passes on the first boot: book
comparison keys, author sort keys, book sort keys, the new search keys, and
Audiobookshelf ASIN casing. Each is gated on its own marker so it runs exactly
once, and a fresh install skips all five. A large library will pause visibly on
that one start. Nothing is wrong.

Two other things worth knowing. New imports of an author with a name particle
land in a differently named folder, and nothing on disk is renamed; existing
folders move when you next run a reorganize. And the metadata profile setting
"Minimum popularity" is gone, for reasons in the Removed section; the stored
column and the API field stay, so nothing is migrated.

Added

  • A description of every setting, over the API (#2311). GET /api/v1/settings/descriptors returns each key Bindery knows about with its type, its default, the values it accepts, a one line explanation, whether a change needs a restart, and whether anything reads it at all. That last part matters: two keys are still stored purely for compatibility and are read by nothing, so a client can now say so instead of offering a control that does nothing.

Changed

  • New imports of authors with a particle land in a differently named folder (#1660) — the {SortAuthor} naming token uses the corrected sort name, so a newly imported Ursula K. Le Guin goes to Le Guin, Ursula K. rather than Guin, Ursula K. Le. Folders already on disk are not renamed. They move when you next run a reorganize, the same way every other file move works here, so until then a library can hold both spellings for the same author. Only names carrying a particle are affected; most authors, including Vincent van Gogh and every plain two-word name, produce exactly the folder they did before.
  • Existing libraries repair their book comparison keys once on the first start after upgrading (#1660) — the ampersand change alters the stored key for any title containing one, so the keys are recomputed on the next boot. This is a single pass and is not repeated.
  • Search results are ranked rather than alphabetical (#1660) — an exact title or author match comes first, then titles starting with what you typed, then whole-word matches, then everything else, with shorter titles preferred within a tier. Searching the hobbit lists The Hobbit above The Hobbit: Illustrated Edition, and searching thor lists Brad Thor above Thornton Wilder.
  • The Books A–Z list sorts accented titles in place (#1347) — Ödland, Ångström and Łódź sorted after Zebra because ordering used the raw title. The Authors list was fixed in v1.23.1; the Books list now uses the same accent-folded key. Existing libraries fill the new keys once on the first start after upgrading.
  • Settings now refuse a key Bindery does not recognise (#2311). Saving a setting through the API used to accept any key at all, so a typo such as serch.interval saved, reported success and then did nothing forever with no way to tell it apart from a setting that was working. The write is now rejected with the key named. Reading and deleting are unchanged, so a row left behind by another build is still listed and can still be removed.
  • A book is left unmatched rather than matched to whichever candidate scored one point higher (#2343) — when metadata lookup found several possible works for a book, it took the highest-scoring one and reported no uncertainty, even if the runner-up was a single point behind on a fuzzy title comparison. It now requires the winner to be clearly ahead, or to be an exact title, an ISBN lookup, or another edition of the same work. Where nothing is clearly ahead the book stays unmatched and can be matched by hand, which is recoverable in a way that silently attaching another book's metadata is not.
  • Language handling comes from one table (#2463) — the four separate and disagreeing lists of language codes are now one, so a language Bindery understands in one place it understands everywhere: in the book filter, in the release filter, and when importing from Audible. A new test fails the build if a language can be normalised to a code the profile editor does not offer.
  • Abbreviated first names now match the name they abbreviate (#2473) — J.R.R. Tolkien and John Ronald Reuel Tolkien share a surname and every initial lines up, but as strings they have little in common, so they used to land in the review queue rather than resolving to one author. The same goes for N. Lane against Nick Lane and J. K. Rowling against Joanne Rowling. This is the commonest way a release name and a catalogue record disagree about the same person, and it now resolves on its own.
  • A bare first name and surname swap is now a review rather than a certainty (#2473) — Stanley Paul and Paul Stanley were treated as definitely the same person because the words match once reordered. They might be, and they might be two writers, and the names alone cannot say. A comma settles it (Haywood, R.R. is still the same person as R.R. Haywood), and so does an initial, since an initial is never a surname.
  • Matching a downloaded file to a book in your library is stricter about the author (#2473) — the last-resort author check there accepted anything scoring 0.80, which paired Jane Doe with Jane Smith. It now uses the same rule as the rest of Bindery. A release naming only a surname, such as Tolkien, now matches the right book, which the old check was too blunt to do.
  • Notices have three severity tiers now, and the tier means something (#2443). Every notice used to pick its own colour and amber usually won, so a catalogue refresh that skipped books exactly as your metadata profile told it to looked the same as an indexer with nowhere to send its grabs. There is one shared Alert component with three tiers: neutral for what was configured to happen, amber for something that wants attention but is not blocking, red for blocked or action required. The author refresh notice is neutral now. It leads with the count and keeps the link to the metadata profile on screen, and the per filter breakdown and example titles sit behind a "Show details" toggle, so nothing was taken away and every reason is one click deep. The manual clipboard fallback stopped being amber too, since a browser refusing the clipboard over plain HTTP is expected and the textarea holding the answer is right there. Real warnings kept their amber: the half-configured setup banner, an enabled indexer with no download client for its protocol, the file move warning in Fix Match, the author mismatch check when re-binding metadata, and the ABS conflicts marked "Needs review". A failed save on Settings → Authentication became a red alert instead of a line of small red text that was easy to miss.

Fixed

  • An author's alternate names are now recognised whatever the accents or capitalisation (#1660) — the lookup that decides which author an alternate name belongs to compared with SQLite's LOWER(), which folds the 26 ASCII letters and nothing else, so a name recorded as östergaard was not found when a provider or an import offered Östergaard, and a name typed on macOS (which produces decomposed accents) never met the same name stored from a metadata provider (which sends composed ones). Both spellings now resolve to the same author, so importing or adding that author stops creating a second copy of them. When the same name has somehow been recorded against two different authors, Bindery now declines to pick one and logs a warning naming both, instead of silently binding your books to whichever row it happened to read first. Merging two authors no longer carries across an alternate name the surviving author already has under a different spelling.
  • Authors with a name particle now sort where a library catalogue would put them (#1660) — the sort name was produced by flipping the last word to the front, so Johann Wolfgang von Goethe became "Goethe, Johann Wolfgang von" correctly by luck, while Ursula K. Le Guin became "Guin, Ursula K. Le" and filed under G. Sort names now follow the Library of Congress rule: a Dutch van, German von, Portuguese da or Spanish de moves to the end after the forename, while a French Le, La or Du, a Spanish El, and the patronymics Mac, Mc, O' and Fitz stay attached to the surname. A generational suffix such as Jr. follows the forename. Names already written surname-first, single names, and names written entirely in Chinese, Japanese or Korean are left exactly as they are, since inverting those loses rather than helps.
  • Books written with & and with and are no longer treated as two different books (#1660) — the key that decides whether two records are the same edition treated an ampersand as punctuation and dropped it, so Foundation & Empire keyed as "foundation empire" and Foundation and Empire as "foundation and empire". Providers disagree about which form to send, so the same book could be added twice and a release named with one spelling would not match a book stored with the other. An ampersand is now read as the word it stands for.
  • Authors whose names arrive in full-width or ligature form no longer duplicate (#1660) — some catalogues send Haruki Murakami or a name containing a typographic ligature. Those forms did not compare equal to the ordinary spelling, so the same author could be created twice depending on which source a record came from.
  • Authors with accented names no longer duplicate across metadata providers (#1660) — the key used to decide "these two records are the same person" kept only letters and digits, and an accent is neither, so a name arriving decomposed (as macOS and some providers send it) was cut short at the accent and did not match the same name arriving composed. José Saramago, Jörg Müller and Фёдор Достоевский could each end up as two authors.
  • DNB authors written in non-Latin scripts no longer collide (#1660) — when a Deutsche Nationalbibliothek record has no authority link, Bindery synthesises an identifier from the author's name by reducing it to ASCII. Any name with no ASCII letters in it — Chinese, Japanese, Cyrillic, Greek, Hebrew, Arabic — reduced to nothing, so every such author shared one identifier and collapsed onto a single row. Existing identifiers are unchanged.
  • Metadata search no longer drops a provider's result over punctuation (#1660) — the key that decides "these two search results are the same book" was built with the library search fold, which is deliberately lossy so that typing part of a title finds it. Used as an identity it could judge two different books identical and hide one of them. It now uses the fold built for title identity.
  • Library search now finds accented, non-Latin and punctuated titles (#1660) — searching the Books or Authors list matched with SQLite's LIKE, which folds the 26 ASCII letters and nothing else, so muller never found Müller, nesbo never found Jo Nesbø, poseidons arrow never found Poseidon's Arrow, and foundation and empire never found Foundation & Empire. Both the query and the stored title/name are now reduced through one Unicode-aware fold, so any of those spellings finds the book. A query typed on macOS (which produces decomposed accents) also finds rows stored from a metadata provider (which sends composed ones), and CJK queries of one or two characters work.
  • Old English and Old Norse spellings now fold onto one search key (#1660) — the accent-folding step ran before the step that maps letters like æ and ø to ASCII, so a name written Ǣlfric and the same name written Ælfric produced two keys that could not find each other, and Ǣlfric still sorted after Z in the A–Z list. Six letters were affected (ǣ ǽ ǿ and their capitals). A series whose title contains one of them is re-identified once on the next metadata refresh.
  • A different book with a similar name no longer counts as a perfect match (#2343) — the title similarity score took the best of four measurements, and one of them scores any title contained inside another as a flawless 100. So Dune matched Dune Messiah perfectly, It matched a fifty-character listing of itself perfectly, and a book sharing a single word with the one you wanted could outrank the real thing. Length now counts: when one title is much longer than the other, the containment is worth progressively less, and two titles of similar length are compared on their whole text.
  • A book whose title carries an edition note still matches itself (#2343) — the same change would have punished The Hobbit (Illustrated Edition) against The Hobbit just as hard, so a trailing note in brackets or parentheses is now removed before comparing, as is a series position appended by a scanner (The Way of Kings: The Stormlight Archive, Book One). Such a pair scores just short of a perfect match, so an exact title still wins. A real subtitle is left alone, because dropping it would make Mistborn: The Final Empire and Mistborn: The Well of Ascension look like the same book, and stripping can never merge two volumes of one series.
  • Download the file you picked, when a book has more than one (#2408). A book holding several ebooks offered a single Download button that always served the same file, because the endpoint could only resolve one path per format. Every file in the list now has its own Download link, and the download endpoint takes ?path= to name one. Audiobook folders still come down as a zip. Thanks to flaevers for the report.
  • Searches for authors whose name mixes scripts now use their romanised aliases (#2419) — an author written as 村上 Haruki, with a Chinese, Japanese, Korean, Cyrillic or Greek given name beside a Latin surname, had romanised aliases like Haruki Murakami saved and honoured on Calibre import, but the search path judged the author by surname alone. It saw a Latin surname, decided the aliases were not needed, and dropped every release named the romanised way. All three paths now judge the whole name.
  • Accented Latin authors no longer collect unrelated authors as aliases (#2419) — the check for "is this name written in another script" tested for plain 7-bit ASCII, so Jo Nesbø, Bodil Östergaard, Łukasz Orbitowski and every other accented Latin name counted as non-Latin. Every name their metadata provider listed as an alternate name was saved as an alias and treated as proof of identity, which is how a co-author or an unrelated real person could end up filed under them. It is the same bug fixed for plain ASCII names in v1.32.0, still live for anyone with an accent in their name. Their own name written without the accent still binds, so searches are unaffected; what stops binding is a different person's name. Existing alias rows are left in place, so if an author of yours was merged this way, splitting them apart will now stick.
  • Accented romanisations of non-Latin authors now count as aliases (#2419) — the same ASCII test refused a Latin alias that carried an accent, so a romanisation like Nikolái Gógol was never saved for a Cyrillic-named author and never widened a search.
  • The author refresh notice now says how many works were already in your library (#2449). It reported how many the filters skipped and left everything else unexplained, so on an author with a full catalogue the numbers looked like books had gone missing. They had not: a work that is already on your shelf just had no counter. The notice now reads "1 added, 103 already in your library, 2 skipped by the language filter", and a refresh that fails to save a book says so instead of leaving it in the logs.
  • A metadata profile no longer accepts a book and then hides every release of it (#2463) — the language list was read twice on the way to a download, and the two readings did not agree. The book side understood a language written with a region or script on it (pt-BR, pt_BR, zh-Hans, and the very common en-US), the release side did not. So a profile set to Brazilian Portuguese let the book in, then dropped every Portuguese release found for it, and the book sat wanted forever with no explanation. Both sides now read the profile the same way.
  • Books reported in the other legal spelling of a language are filtered as that language (#2463) — ISO 639 gives many languages two three-letter codes, and providers use either, so a profile allowing German (ger) rejected any book a provider reported as deu, French rejected fra, Dutch rejected nld, Chinese rejected zho, and the same for Czech, Romanian and Greek. All twenty affected languages now match either spelling.
  • Audiobooks whose language arrives as a word are matched correctly (#2463) — Audible reports a language as German or English rather than as a code. Two copies of the translation table existed and one had fallen five languages behind, so the same audiobook could be filed under a different language depending on which lookup path reached it first. Hungarian, Romanian, Catalan and Latin audiobooks were affected. German edition matching also now recognises German, Deutsch and de-DE, not only ger, deu and de.
  • A stalled download is now removed from your download client (#2367) — when a torrent sat stalled long enough for Bindery to give up on it, Bindery marked it failed, blocklisted the release and searched for a replacement, but never told the download client. The stalled torrent stayed in qBittorrent forever while its replacement downloaded, so the queue filled with dead entries Bindery had already written off, and the history line said "stalled release removed" when nothing had been removed. It is now deleted from the client, with its partial data, since a download that never started has nothing worth keeping. If the client cannot be reached the blocklist and the re-search still happen, because those are the actual recovery.
  • An audiobook grabbed from the Search page can find its book again (#2470). Searching from the Search page rather than a book's own page does not tie the download to a book, so the importer works out which one it is afterwards. It read the ebook's embedded metadata and the filenames inside the download, neither of which tells you anything about an audiobook made of track files, and it never read the release name you actually picked. It does now, and it checks the author agrees before matching, so a one word title cannot pull in the wrong book. Thanks to daize0 for the report and for the second example, which is what pinned it down.
  • Two authors with the same first name and similar short surnames are no longer merged into one (#2473) — deciding whether two names are the same person came down to a single similarity score over the whole name, and that score is dominated by whatever the two names have in common. Christopher Ross and Christopher Rose scored 0.9750 out of 1, comfortably over the line, so an import filed both writers' books under one author and the review queue never saw it. Names are now compared field by field, surname against surname and first name against first name, and a surname of five letters or fewer has to match exactly before anything is merged on the strength of it. Pairs like this are surfaced for review instead of being merged silently. Authors already merged this way stay merged until you split them, and splitting them will now stick.
  • An Audiobookshelf audiobook's ASIN no longer stays invisible to the file importer — Audiobookshelf hands back the ASIN in whatever case its metadata was written in, and the shelf import stored it as-is while every other source stored it upper case. Because an ASIN is matched exactly, a book imported as b0b2rjrf1k never matched a downloaded file named ... B0B2RJRF1K ..., and the same book could sit in the library under two identifiers. ASINs are now stored the same way whatever wrote them, and the ASINs already in your library are corrected once on the first start after upgrading.
  • An ISBN pasted with the wrong kind of dash now finds the book — Add Book and Manual Import only stripped the plain -, so an ISBN copied out of a PDF, a publisher's page or a word processor (which use an en dash, a non-breaking hyphen, a minus sign or an invisible soft hyphen) was treated as a title, searched as one, and found nothing, with nothing on screen to say why. Every dash is now stripped, on the search box and on the server.
  • A mistyped ISBN is no longer converted into a real-looking one — when Bindery needed the ISBN-13 form of a book that only had an ISBN-10, it threw the ISBN-10's check digit away and computed a fresh one, so a typo or an OCR error came back out as a perfectly well-formed ISBN-13 belonging to a different book, and that wrong number was then used to search indexers. Both forms are now check-digit verified, and one that fails is treated as no ISBN at all rather than being converted.
  • An ISBN ending in X is no longer dropped from an Audiobookshelf import — the shelf import kept only the digits of an ISBN, so the one ISBN-10 in ten that ends in the check digit X came out a character short, matched nothing, and was discarded instead of being saved on the edition.
  • A German National Library record with a spaced ISBN keeps it — the DNB reader stopped at the first space, so an ISBN written 978 3 446 12345 6 was read as 978 and thrown away. EPUB files, DNB records and Audiobookshelf items now all read an ISBN the same way, so the identifier a book ends up with no longer depends on which importer saw it first.
  • A book that gains a second format is searched for it again (#1634). A book you already owned as an ebook could be widened to dual format by Hardcover list sync or edition hydration. The book kept its "imported" status, so the Wanted page, the scheduled search sweep and the author bulk search all treated it as complete, and the newly monitored format was never searched. Widening now reopens the book as wanted, and an upgrade repairs any book already left in that state.
  • Rolling back a Calibre import no longer leaves its file rows behind (#1635). The library import registers a tracked file for every format Calibre reports, but those rows were not covered by the run's rollback, so undoing a run against books that already existed left the files it had claimed still attached. Rollback now untracks them, and only the rows that run actually created, so a path a download placed is never touched. The files on disk are never modified.
  • A torrent grab that never reached your download client now says so (#2505). Grabbing from the web UI could report success while the indexer was answering 401, because the download URL went out without its apikey. Bindery restores that key from the indexer named on the grab, and when that indexer's stored address did not match the address the link pointed at, it gave up and sent the URL unsigned rather than trying the other indexers it has. Prowlarr builds its links from its own configured address, so an indexer saved with a port and a link emitted without one was enough to do it, and nothing was written to the log at any level. It now falls back to matching on the address, and says in the log when it had to. Separately, a download the client has no record of is failed after ten minutes with a reason on it, rather than sitting at "downloading" forever looking like a torrent waiting for peers. Thanks to callum-todd96 for the report, and for testing the generated URL by hand, which is what found it.
  • A failed audiobook import no longer turns into a duplicate folder on the next try (#2504). When placing an audiobook failed after its destination folder had been created, the empty folder was left behind. The next attempt saw a folder already sitting there, decided it was a clash, and put the book in "Title (2)" instead, leaving the empty original beside it. One reporter got six of those out of a single batch that hit a passing permission error. Both paths that could do this now remove the folder they made, and neither touches a folder with anything in it, so a shared folder holding the book's ebook is safe. Thanks to ColinAgnew for the report.
  • A Hardcover series no longer lists every translation and box set as if each were its own volume (#2496). Hardcover records a translated edition as a separate book that keeps the original's position in the series, and files an omnibus under the position of the first book it contains. Both arrive from the API as ordinary entries, so Harry Potter came back as 34 books for a series of seven: Harry Potter Collection #1-6, Harry Potter Boxed Set, The Harry Potter Trilogy and the novel itself all sat at position 1, followed by the Dutch, French, Norwegian, Polish, Portuguese, Russian and Spanish editions of each volume. Their titles all differ, so the existing title dedup had nothing to match on and kept every one, leaving a series page that had to be added in bulk and pruned by hand. Compilations are now excluded when the series is fetched, and where several books still share a position Bindery keeps the one the most readers hold. The margin is rarely close: the English Philosopher's Stone has some seventeen thousand readers where the other entries at position 1 have none. A book with no position is left alone, being an extra the series accumulated rather than a duplicate of a volume, and a book listed at two positions still resolves to the lower of them as before. Thanks to totza2010 for the report and the fix.
  • A release that spells out "and" or "of" now matches its book (#2465). Bindery reduces a title to its meaningful words before matching, dropping small ones like "and", "of" and "the", but nothing dropped them from the release name, and the check that the words appear together in order allowed only punctuation between them. So Foundation.and.Empire.1952.RETAIL.EPUB-GRP failed against Foundation & Empire and against Foundation and Empire alike, and The.Rise.of.Endymion and Bury.My.Heart.at.Wounded.Knee were the same miss. A fallback still matched on the words alone, so these were demoted rather than lost outright, but that fallback is the tier that cannot tell a real match from an incidental overlap of words. Those small words may now sit inside the phrase, and only those: a release with a real word in the gap is still a different book.
  • Two Japanese authors whose names differ by a voicing mark are no longer treated as one person (#2452). Deciding whether two records are the same author ran the name through a step that removed every accent, which is right for José and Jose and wrong for kana, where the dakuten and handakuten change the letter rather than decorate it. So ズ collapsed onto ス, がっこう onto かっこう, and ヴィクトル onto ウィクトル, and two different writers could be filed under one author on import, on alias binding, on an Audiobookshelf import and on cross provider matching. The step now leaves a mark alone unless it sits on a Latin or Greek letter, which is the rule the search and slug alphabets already follow. The Cyrillic breve on й is covered by the same change. Nothing is stored in this form, so nothing is migrated, but authors already merged this way stay merged until you split them.

Removed

  • Metadata profile "Minimum popularity" (#2450). It compared a work's OpenLibrary ratings count against a number you picked, and OpenLibrary ratings are far too sparse for that to mean anything: an instant New York Times bestseller has one rating there, and Little Brother has 58. Worse, zero ratings counted as "unknown" and passed, so a book started being filtered the moment a second person rated it. The setting came from Readarr, which scored rating times votes against Goodreads, where a mainstream novel has tens of thousands. The control is gone from Settings then Metadata. The stored column and the API field stay, so nothing is migrated and existing profiles load unchanged.

Security

  • The OIDC login flow can no longer be started for you by someone else (#2362). On HTTPS the flow cookie is now named __Host-bindery_oidc_flow, which browsers refuse to let another host under your domain, or any plain HTTP response, write. Without that, an attacker could ask Bindery for a genuine login cookie, plant it in your browser and walk you onto the callback, leaving you signed in to their account. The cookie is also signed and bound to the provider it was issued for, so a forged or re-pointed one is rejected before it is parsed. Installs served over plain HTTP cannot use the prefix and stay exposed; put Bindery behind TLS, or set BINDERY_COOKIE_SECURE=always if TLS terminates at a proxy.