From e2ef03b97accbad4c27649ea53fb288c2c5edcfb Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:09:05 +0000 Subject: [PATCH 1/8] User Guide: the Audiobookshelf import's match hints, its certificate error and the import inside setup An import now brings Audiobookshelf's ASIN and ISBN as match hints that show nothing until a match run applies, so Past imports and the setup step offer Match automatically. An import with no listening can't replace one already applied. A self-signed https address fails with its own message: use ABS's plain http:// address. The setup step runs the import inline and waits for the first scan. Part of KodeStar/audiosilo-server#366. --- docs-users/admin/health.md | 18 ++++-- docs-users/admin/import.md | 55 +++++++++++++++++-- .../coming-from-audiobookshelf.md | 6 +- docs-users/getting-started/first-run.md | 8 ++- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/docs-users/admin/health.md b/docs-users/admin/health.md index d9f57d05..af86cd96 100644 --- a/docs-users/admin/health.md +++ b/docs-users/admin/health.md @@ -95,8 +95,8 @@ was deleted." Once the folder is back, **Retry** scans it. See **Not matched to community metadata** has a **Match automatically** card above its list. It looks up every book in the list in one pass. Nothing changes until you review and apply what it found. While there are unmatched books, the -overview and **Library > Books** show how many, with a **Match automatically** -button that opens this list. +overview, **Library > Books** and an applied import's **Past imports** show how +many, with a **Match automatically** button that opens this list. 1. Pick a library and click **Find matches**. You can leave the page while it runs. @@ -150,9 +150,17 @@ If you don't trust where your tags came from, check **Confident** before you apply. Correct the tag, or match the book by hand, to stop it coming back. ::: -An ASIN from an Audiobookshelf `metadata.json` counts as the book's own straight -away (see -[Audiobookshelf's metadata.json files](../getting-started/organizing-your-library.md#coming-from-audiobookshelf)). +### Audiobookshelf's ASINs and ISBNs + +Audiobookshelf's identifiers reach AudioSilo in two ways, and they count +differently: + +- **From an [Audiobookshelf import](import.md#match-your-books-after-an-import).** + They are match hints, like tags. A match looks them up before the book's tags, + and the book stays **Not matched** until a match applies. +- **From a `metadata.json` file beside the book.** The ASIN or ISBN counts as the + book's own straight away, so the book is matched (see + [Audiobookshelf's metadata.json files](../getting-started/organizing-your-library.md#coming-from-audiobookshelf)). ### Store listings with no ASIN or ISBN diff --git a/docs-users/admin/import.md b/docs-users/admin/import.md index 4683320e..758b710b 100644 --- a/docs-users/admin/import.md +++ b/docs-users/admin/import.md @@ -1,11 +1,14 @@ --- title: "Import your Audiobookshelf history" -description: "Moving from Audiobookshelf? Copy each person's listening history, progress and bookmarks into AudioSilo, check it, and undo it if needed." +description: "Moving from Audiobookshelf? Copy each person's listening history, progress and bookmarks into AudioSilo, bring its ASINs and ISBNs for matching, check it, and undo it if needed." --- Moving from Audiobookshelf? **Server > Settings > Import** in the [admin console](console-tour.md) copies each person's listening history over, so their stats, streaks and progress carry on instead of starting at zero. +It also brings Audiobookshelf's ASIN and ISBN for your books, so they can be +matched to community metadata. The setup flow runs the same import in its +[Coming from Audiobookshelf step](../getting-started/first-run.md#step-6-coming-from-audiobookshelf). You need to be an admin. AudioSilo only reads from Audiobookshelf and changes nothing there. You check each import before anything is written, and you can @@ -19,6 +22,8 @@ undo it. - **How far they got in each book**, and when they started and finished it. Progress only ever moves forward: an import never rewinds a book. - **Bookmarks**, skipping ones they already have here. +- **Audiobookshelf's ASIN and ISBN** for each book it has them for, as match + hints. See [Match your books after an import](#match-your-books-after-an-import). What doesn't come over: podcasts, collections and playlists, accounts and passwords, and books that aren't in your AudioSilo libraries. @@ -36,7 +41,11 @@ passwords, and books that aren't in your AudioSilo libraries. - **The Audiobookshelf address, as the AudioSilo server sees it.** The server fetches the history itself, so the address must work from the machine AudioSilo runs on. If both run in the same Docker Compose project, use the - service name, for example `http://audiobookshelf`. + service name, for example `http://audiobookshelf`. Use the plain `http://` + address on your network if Audiobookshelf's `https://` one has a self-signed + certificate (see [When a fetch fails](#when-a-fetch-fails)). +- **A finished scan.** The import pairs Audiobookshelf's books with the books + AudioSilo has found, so let a new library's first scan finish. ## Import the history @@ -51,7 +60,8 @@ passwords, and books that aren't in your AudioSilo libraries. 5. Press **Fetch history for 1 person** (or *n* people). Nothing is written yet. A long history can take a minute, and you can leave the page. 6. Under **Imports to review**, check each person's figures: hours, sessions, - books matched and books not matched. + books matched, books not matched, and books given an **ASIN or ISBN for + matching**. 7. Press **Apply for *person*** and confirm. The import then moves to **Past imports**. @@ -76,12 +86,43 @@ then by title and author. The review lists each skipped book with the reason: Then import that person again. A new import replaces the previous one, so nothing is counted twice. +## Match your books after an import + +An import doesn't match your books. It brings Audiobookshelf's ASIN and ISBN for +every book Audiobookshelf has them for, whoever listened to it. A match run then +looks them up in the community database. + +- The server pairs these books with yours by folder path, then by title and + author. +- It leaves out a book two Audiobookshelf books pair with, and a book that is + already matched here. +- The identifiers are **match hints**. They never become the book's ASIN or + ISBN and never show in the apps. +- A match looks Audiobookshelf's identifiers up ahead of any in the book's + tags. + +So nothing shows until a match run applies. Once an import is applied, **Past +imports** says how many books are not matched, with a **Match automatically** +button. It opens the unmatched books in Library health, where you start the run, +review what it found and apply it. See +[Matching every book at once](health.md#matching-every-book-at-once). + +An import with no listening for its person still brings the identifiers, and +you can apply it for those alone. It can't replace an import already applied +for that person, because applying it would undo their history and add none. +**Apply** stays off and the review says so. Undo the applied one first if you +want to replace it. + ## Undoing an import **Past imports** lists every import. **Undo** removes the sessions and bookmarks it added and puts the person's progress back. Anything the person changed since, such as listening further, is kept. +Undo also removes the match hints that import brought. Each book keeps the hint +of the import applied last, so undoing the latest import removes its hints even +where an earlier import carried the same ones. Matches you already applied stay. + A person's **Listening** tab also lists their imports, with **Undo**. See [A person's page](users-and-invites.md#listening). @@ -94,7 +135,13 @@ Activity > Sessions, they show "Imported from Audiobookshelf". ## When a fetch fails -The import card says why. Check that Audiobookshelf is running, that its +**Connect** checks the address and token first and says what's wrong under the +field. If it says Audiobookshelf's certificate isn't trusted, its `https://` +address uses a certificate the AudioSilo server doesn't trust, usually a +self-signed one. Use its plain `http://` address on your network instead, for +example `http://192.168.1.20:13378`. + +For a fetch that fails later, the import card says why. Check that Audiobookshelf is running, that its address works from the AudioSilo server, and that the token is right (use an admin or root account's token to import other people). Then **Discard** it and start again. Nothing was written. diff --git a/docs-users/getting-started/coming-from-audiobookshelf.md b/docs-users/getting-started/coming-from-audiobookshelf.md index 5694ad70..c4e2bc44 100644 --- a/docs-users/getting-started/coming-from-audiobookshelf.md +++ b/docs-users/getting-started/coming-from-audiobookshelf.md @@ -23,11 +23,13 @@ A book with a `metadata.json` file then shows its Audiobookshelf details in Audi ## Bring listening history across -**Server > Settings > Import** copies each person's listening sessions, progress and bookmarks from Audiobookshelf. [Invite](../admin/users-and-invites.md#inviting-someone) everyone first, so each person has an account to import into. See [Import your Audiobookshelf history](../admin/import.md). +**Server > Settings > Import** copies each person's listening sessions, progress and bookmarks from Audiobookshelf. It also brings Audiobookshelf's ASIN and ISBN for your books, as hints for matching. The setup flow's **Coming from Audiobookshelf?** step runs the same import. + +[Invite](../admin/users-and-invites.md#inviting-someone) everyone first, so each person has an account to import into. Give the import Audiobookshelf's plain `http://` address on your network. AudioSilo refuses an `https://` address whose certificate it doesn't trust, such as a self-signed one. See [Import your Audiobookshelf history](../admin/import.md). ## Match your books -A scan matches no book by itself, apart from books whose `metadata.json` names an ASIN or ISBN. An ASIN in a book's tags is only a hint for the next step. To match the rest: +A scan matches no book by itself, apart from books whose `metadata.json` names an ASIN or ISBN. An ASIN in a book's tags, or one the import brought, is only a hint for the next step. After an import, its **Past imports** list has a **Match automatically** button that opens the list in step 1. To match the rest: 1. Open **Health** in the admin console and select **Not matched to community metadata**. This is the list of your unmatched books. 2. On its **Match automatically** card, pick the library and select **Find matches**. diff --git a/docs-users/getting-started/first-run.md b/docs-users/getting-started/first-run.md index bbee5de5..1588726e 100644 --- a/docs-users/getting-started/first-run.md +++ b/docs-users/getting-started/first-run.md @@ -151,7 +151,13 @@ See [Reach your server from outside your home](./remote-access.md). ![Step 6: the Audiobookshelf import](/img/screenshots/setup/abs.png) -**Open the import** brings each person's listening progress across from Audiobookshelf (see [the import](../admin/import.md)), in a new tab. AudioSilo also reads the `metadata.json` files Audiobookshelf leaves beside your books. [Move over from Audiobookshelf](./coming-from-audiobookshelf.md) covers the rest. +This step runs the [Audiobookshelf import](../admin/import.md) right here. Connect to Audiobookshelf, review what matches for each person, then apply it. It brings each person's listening progress across, and Audiobookshelf's ASIN and ISBN for your books as hints for matching. + +- **Wait for the scan to finish.** The import pairs Audiobookshelf's books with the ones the scan finds, so **Connect** stays off while the library's first scan runs. +- **Then match your books.** If community metadata is on and books are not matched, the step says how many, with **Match automatically**. It opens Library health in a new tab, where you start the run and review what it found. Nothing is matched until you apply it. +- **Continue** moves on whether or not you imported anything. The import stays in **Server > Settings > Import**. + +AudioSilo also reads the `metadata.json` files Audiobookshelf leaves beside your books. [Move over from Audiobookshelf](./coming-from-audiobookshelf.md) covers the rest. ### Step 7: Backups and updates From e19fc2e47426faad77a3721c86720c28cb5c6007 Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:09:05 +0000 Subject: [PATCH 2/8] Developer Docs: book_hints (0074), QueryFor's hint order, abs_certificate and the setup abs step The reference gains the imports summary's identifiers, the 502 abs_certificate code and the 409 import_not_ready refusal of an apply with no listening that would undo an applied import. The data model documents book_hints, who owns a hint and QueryFor's exact order (own ids, then an import's, a tag ASIN only without an import identifier, a tag ISBN beside an import ASIN). A LibriVox placement drops the path's hints too. web-ui covers the inline import and the match offer; the mapping table gains a listening-imports row. Part of KodeStar/audiosilo-server#366. --- .../architecture/cross-repo-contract.md | 6 +- docs-developers/bridge/librivox.md | 2 +- docs-developers/contributing/documentation.md | 1 + docs-developers/server/api/reference.md | 78 +++++++++++++++---- docs-developers/server/data-model.md | 76 ++++++++++++++++-- docs-developers/server/web-ui.md | 22 ++++-- 6 files changed, 156 insertions(+), 29 deletions(-) diff --git a/docs-developers/architecture/cross-repo-contract.md b/docs-developers/architecture/cross-repo-contract.md index b5a0006b..3166fa03 100644 --- a/docs-developers/architecture/cross-repo-contract.md +++ b/docs-developers/architecture/cross-repo-contract.md @@ -800,7 +800,9 @@ or `pkg/release` reaches the server through its `go.mod`. The match dialog sends `GET /works/match` the book's tag and path facts: - Its `language` and repeatable `narrator`. An older `metaserve` ignores them. -- Its tag hints, as `asin` and `isbn`. +- Its hints, as `asin` and `isbn`, when it has neither of its own: an Audiobookshelf + import's, else its tags' (`matchrun.QueryFor`, see the + [data model](../server/data-model.md#match-hints-from-an-import)). Against a `metaserve` that predates the route, the server falls back to `lookup` and `works/search`. The candidates pass `metaserve`'s `score` and `reasons` through to @@ -1632,7 +1634,7 @@ not quiet, deduped per library and project, and in no module. folder. The server does not read it yet, and its scanner skips the name. - The server folds a done result into the book's `book_matches` row ([Matches by work id](#matches-by-work-id)), by `adopted`: a placed book - replaces the path's match and drops its leftover ASIN and ISBN, an adopted one + replaces the path's match and drops its leftover ASIN, ISBN and match hints, an adopted one keeps a match already there. The `bridge_job_finished` event carries `librivox_match` (`matched`, `kept`, `unmatched`). diff --git a/docs-developers/bridge/librivox.md b/docs-developers/bridge/librivox.md index 6934f2d8..85446547 100644 --- a/docs-developers/bridge/librivox.md +++ b/docs-developers/bridge/librivox.md @@ -168,7 +168,7 @@ book's path depends on the result's `adopted`: | `adopted` | The folder | The fold | |---|---|---| -| `false` | was vacant until this run placed it | replaces the path's `book_matches` row, and drops the path's ASIN and ISBN `book_overrides` (whoever set them) and its `book_enrichment` row, then rebuilds the book's effective metadata. Those rows are a deleted book's leftovers, and `/meta` would ask them before the match. | +| `false` | was vacant until this run placed it | replaces the path's `book_matches` row, and drops the path's ASIN and ISBN `book_overrides` (whoever set them), its `book_enrichment` row and its `book_hints` (an Audiobookshelf import's match hints, which the match dialog would send), then rebuilds the book's effective metadata. Those rows are a deleted book's leftovers, and `/meta` would ask them before the match. | | `true` | is an earlier fetch's book | inserts the match only when the path has none, so an admin's rematch stays, and touches nothing else | | absent (an older Bridge) | not known | replaces the match and touches nothing else | diff --git a/docs-developers/contributing/documentation.md b/docs-developers/contributing/documentation.md index 01c55f6b..76b12123 100644 --- a/docs-developers/contributing/documentation.md +++ b/docs-developers/contributing/documentation.md @@ -116,6 +116,7 @@ mappings: | Generated characters, recaps and descriptions: `.audiosilo/` (the server's `library/attachments.go`, `metadata/attachments.go`, `catalog/attachments.go`, `meta/generated.go`; the Bridge's `internal/generate`, `internal/pipeline/describe_stage.go`), the console's Description part (`describe-section.tsx`) or the player's generate action, mark and About (`src/components/bridge/`, `GeneratedMark`, `aboutContent`) | [bridge/attachments.md](../bridge/attachments.md) + [bridge/generating.md](../bridge/generating.md) + [server/scanner.md](../server/scanner.md#the-bridges-attachments) + the `/meta` [generated content](../server/api/reference.md#generated-content) + [frontend/book-page.md](../frontend/book-page.md#the-primary-action-and-the-action-row) (and its About) + `/users/admin/generating-characters-and-recaps`, `/users/listening/recaps-and-characters`, `/users/listening/book-page` (About) + the `admin/book-description.png` and `web-player/book-about-generated.png` screenshots | | Community matching: `internal/matchrun` (`Classify`, `ReviewFloor`, `tidyTitle`, `workers`, `maxRequestsPerSecond`, `maxFailStreak`), `internal/meta/match.go`, `internal/meta/pacer.go`, a run's waits in `internal/meta/client.go`, the tag hints (`metadata.setHints`, `0067`), the recorded match (`catalog/bookmatches.go`, `book_matches`, `0069`, `0070`, `catalog.matchedExpr`, the book aside's Community card and Unlink, the match dialog's `match`), `health/bulk-match.tsx`, the Add it link (`lib/meta-site.ts`, `add-to-community.tsx`) and the not-matched notice (`unmatched-prompt.tsx`); `works/match`'s params and `expand` in audiosilo-meta | the [reference](../server/api/reference.md#bulk-community-matching) (outcomes, scopes, [what a run asks of the service](../server/api/reference.md#what-a-run-asks-of-the-community-service)) and its [match endpoint](../server/api/reference.md#get-apiv1adminlibrariesidbookmatch) + [configuration.md](../server/configuration.md#community-metadata-metadata) (the waits) + [data-model.md](../server/data-model.md#tag-hints) (and `book_matches` under [durable per-library config](../server/data-model.md#durable-per-library-config-path-keyed-no-fk-to-books)) + [scanner.md](../server/scanner.md) + [web-ui.md](../server/web-ui.md) + [meta/api.md](../meta/api.md#apiv1worksmatch) (and its [rate limit](../meta/api.md#rate-limit-and-caching), which names `workers` and `maxRequestsPerSecond`) + the [cross-repo contract](../architecture/cross-repo-contract.md#13-community-metadata-a-three-repo-seam) (after the workspace `CROSS-REPO.md` §17) + `/users/admin/health#matching-every-book-at-once`, `/users/admin/books#matching-with-community-metadata` (and `#books-matched-to-a-store-listing`, `#unlinking-a-community-match`), `/users/admin/activity` (the coverage wording), `/users/admin/server#community-metadata`, `/users/faq` (what matching sends), `/users/community/meta-site#adding-a-missing-book` (Add it) + the site's `src/pages/metadata.astro` (privacy copy, kept in step with the console's `health.bulkMatch.privacy`) + the `admin/health-bulk-match.png` and `admin/book-community-match.png` screenshots | | The unknown-ASIN report (LibraForge C3): the server's `internal/coverage`, `catalog/coverage.go` (`UnknownASINCandidates`), `meta/report.go`, `unknown_asin_reports` (`0068`), the `unknown_asin_report` server state, `metadata.report_unknown` and `metadata.report_status`, Settings > Metadata's *Help complete the community database* switch; metaserve's intake queue | [configuration.md](../server/configuration.md#the-unknown-asin-report-metadatareport_unknown) + the [reference](../server/api/reference.md#get-apiv1adminsettings) (`metadata.report_unknown`, `metadata.report_status`) + [data-model.md](../server/data-model.md#unknown-asin-reports) + the [cross-repo contract](../architecture/cross-repo-contract.md#13-community-metadata-a-three-repo-seam) + [meta/api.md](../meta/api.md#unknown-asin-intake-queue-optional) and [meta/sync-bot.md](../meta/sync-bot.md#the-reported-asin-lane) + `/users/admin/server#helping-complete-the-community-database`, `/users/admin/books`, `/users/admin/health` (tag hints), `/users/faq` (what is sent) + the `admin/settings-metadata.png` screenshot | +| Listening imports: `internal/importer` (the ABS client and its codes, `abs_certificate` among them; matching, planning, `identifiersFor`), `catalog/imports.go`, the match hints (`catalog/hints.go`, `book_hints`, `0074`, `matchrun.QueryFor`'s order), the console's `features/imports/` (`ImportFlow`, also in the setup flow's abs step) | the [reference](../server/api/reference.md#admin-listening-imports) (its [identifiers](../server/api/reference.md#identifiers-match-hints)) + [data-model.md](../server/data-model.md#listening-imports) (and [match hints](../server/data-model.md#match-hints-from-an-import)) + [web-ui.md](../server/web-ui.md#the-first-run-setup-flow) (the abs step) + `/users/admin/import`, `/users/getting-started/coming-from-audiobookshelf`, `/users/getting-started/first-run` (step 6), `/users/admin/health` (Audiobookshelf's ASINs and ISBNs) + the `admin/settings-import.png` and `setup/abs.png` screenshots | | Metadata mirror mode (`metadata.mode`, `internal/metamirror`, `internal/meta/mirror.go`, the Source card, the mirror panel on Health > System) | [server/configuration.md](../server/configuration.md#mirror-mode-metadatamode-mirror) + the mirror routes in [api/reference.md](../server/api/reference.md#the-local-copys-status-metadatamirror) + `/users/admin/server` (Keeping a local copy), `/users/admin/health` (the local copy), `/users/faq` (privacy) | | `pkg/query`, `pkg/query/querytest`, `pkg/release` in audiosilo-meta, or the artifact schema | [meta/overview.md](../meta/overview.md#public-go-packages) + [meta/data-model.md](../meta/data-model.md#the-compiled-artifact-and-schema-versioning) + the [cross-repo contract](../architecture/cross-repo-contract.md#13-community-metadata-a-three-repo-seam) (mirror-mode servers read the artifact directly) | | Meta schemas, `metaserve` API, or intake tooling (`route.yml`, the intake denylist included) | [meta developer pages](../meta/overview.md) (data model, API, contributing) - and the [cross-repo contract](../architecture/cross-repo-contract.md) when the server's `/meta` envelope is affected, and `/users/community/contributing-from-your-server` when the limits that hold a Bridge's submission change | diff --git a/docs-developers/server/api/reference.md b/docs-developers/server/api/reference.md index 461f0019..1ce960d9 100644 --- a/docs-developers/server/api/reference.md +++ b/docs-developers/server/api/reference.md @@ -7155,8 +7155,9 @@ wrong: is the book's author (mostly a composer tag filled with the author, which says nothing of the recording); - `q`, and the ASIN/ISBN: the typed ones, or the book's own when nothing was - typed, or with neither of its own its [tag hints](../data-model.md#tag-hints), - which metaserve looks up itself. + typed, or with neither of its own its hints by `matchrun.QueryFor`'s rule + ([an Audiobookshelf import's](../data-model.md#match-hints-from-an-import), else + its [tags'](../data-model.md#tag-hints)), which metaserve looks up itself. An older metaserve ignores `language` and `narrator`. @@ -7294,8 +7295,8 @@ again. A `503` (over metaserve's match budget) or any other `5xx` from 10% (`meta.PlausibleRuntimeOff`) off the book's length, none of the book's narrators reads it, and another recording of the same work is within 10%. The run then proposes the recording this rule picks among those, `auto` when it has an - ASIN or ISBN (an identifier hit whose length now fits). A tag hint can name - another edition of the right work. + ASIN or ISBN (an identifier hit whose length now fits). A hint, from the tags or + an Audiobookshelf import, can name another edition of the right work. - A narrator reading the named recording keeps it: `auto` within 20%, else held as `length_differs` (see [the outcomes](#bulk-community-matching)). - A plain book never moves onto a dramatization the rule above refuses. @@ -7423,7 +7424,7 @@ Each book's **outcome**: | Outcome | Meaning | |---|---| -| `auto` | Confident (`matchrun.Classify`): the best candidate scores **90** or more, at least **10** ahead of the next, its recording has an ASIN or ISBN (from 2.6.0, one with neither on firmer ground: see below the table), and, when both lengths are known, the recording's runtime is within **10%** of the book's (the closest recording of a work can still be another edition), or, from 2.6.0, within **20%** (`meta.NarratedRuntimeOff`) when the book's narrator reads it (`matchrun.narratorReads`: `reasons.narrator` is `full` and the proposed recording's own credit names one of the book's narrators, `meta.ReadBy`; a placeholder credit such as `Full Cast`, `GraphicAudio`, `Various` or `Unknown` never counts, `meta.PersonNarrator`, as it agrees with every recording carrying it). An identifier hit (`reasons.identifier`: in a match run always a tag hint) needs no lead, unless the next candidate is one too (`review`; a guard, as metaserve names one work per request today). From 2.7.0 the book must also agree with it (`matchrun.identifierAgrees`): `reasons.title`, when judged, at least **0.65** (`IdentifierTitleAgree`), or at least **0.9** (`IdentifierTitleSame`) when `reasons.series` is `conflict`, as the same title at another position is the series numbered another way (a conflict with no title judged is held). Else `review`. So a wrong tag ASIN naming a book with a similar title within 10% of the length is still `auto`, and so, from 2.6.0, is one naming another edition of the right work when a recording of it within 10% takes its place (`meta.FitRecording`, [the dialog's rule](#get-apiv1adminlibrariesidbookmatch)). Applied unless the admin leaves it out. A repick's offers are all `auto`. | +| `auto` | Confident (`matchrun.Classify`): the best candidate scores **90** or more, at least **10** ahead of the next, its recording has an ASIN or ISBN (from 2.6.0, one with neither on firmer ground: see below the table), and, when both lengths are known, the recording's runtime is within **10%** of the book's (the closest recording of a work can still be another edition), or, from 2.6.0, within **20%** (`meta.NarratedRuntimeOff`) when the book's narrator reads it (`matchrun.narratorReads`: `reasons.narrator` is `full` and the proposed recording's own credit names one of the book's narrators, `meta.ReadBy`; a placeholder credit such as `Full Cast`, `GraphicAudio`, `Various` or `Unknown` never counts, `meta.PersonNarrator`, as it agrees with every recording carrying it). An identifier hit (`reasons.identifier`: in a match run always a hint, an Audiobookshelf import's or the tags') needs no lead, unless the next candidate is one too (`review`; a guard, as metaserve names one work per request today). From 2.7.0 the book must also agree with it (`matchrun.identifierAgrees`): `reasons.title`, when judged, at least **0.65** (`IdentifierTitleAgree`), or at least **0.9** (`IdentifierTitleSame`) when `reasons.series` is `conflict`, as the same title at another position is the series numbered another way (a conflict with no title judged is held). Else `review`. So a wrong hinted ASIN naming a book with a similar title within 10% of the length is still `auto`, and so, from 2.6.0, is one naming another edition of the right work when a recording of it within 10% takes its place (`meta.FitRecording`, [the dialog's rule](#get-apiv1adminlibrariesidbookmatch)). Applied unless the admin leaves it out. A repick's offers are all `auto`. | | `review` | A candidate that isn't confident. Applied only if the admin puts it in. One held because its recording's length is more than 10% from the book's, or 20% when the book's narrator reads it (a match run's, as for `auto`, or a refresh's), carries `detail: "length_differs"` (from 2.4.0), worded with the item's `book.duration` and the proposal's `runtime_min`. One whose work holds only dramatizations the book doesn't state it is, none of them the book's by length ([`default_recording_id`](#get-apiv1adminlibrariesidbookmatch), from 2.6.0), carries `detail: "dramatization_only"` (`DetailDramatizationOnly`) and no recording, so nothing is attached unasked. One found by a tag ASIN or ISBN the book doesn't agree with (see `auto`, from 2.7.0) carries `detail: "identifier_disagrees"` (`DetailIdentifierDisagrees`), ahead of `dramatization_only` and `length_differs` when either would also apply. | | `none` | No candidate; or, in a match run, a best candidate scoring under **60** (`matchrun.ReviewFloor`) on metaserve's scale, with `detail: "weak_match"` (`DetailWeakMatch`), its `score` kept for the review's wording and its `proposal` empty (from 2.6.0). A candidate without `reasons` (an older metaserve's fallback search, on another scale) stays `review`. The match dialog has no such floor: it lists its candidates (up to 6) however low they scored. | | `error` | The service failed for this book (`detail: "metadata_unavailable"`), from 2.7.0 also when the best candidate's work can't be read for any reason but a `404` (a gone work gives way to the next). [Ten in a row](#what-a-run-asks-of-the-community-service) stop the run. | @@ -8627,7 +8628,8 @@ the person's access. The console's **Server > Settings > Import**: another server's listening history copied into a person's own, so someone moving to AudioSilo keeps their -stats. v1 reads **Audiobookshelf** (ABS) only and is **admin only**: no +stats, and Audiobookshelf's ASIN and ISBN for the books here kept as +[match hints](../data-model.md#match-hints-from-an-import) (`book_hints`). v1 reads **Audiobookshelf** (ABS) only and is **admin only**: no capability flag, no player route (the console ships inside the server). The work is `internal/importer` (the ABS client, matching, planning, the background fetch); the rows are `catalog/imports.go`; the handlers @@ -8645,7 +8647,9 @@ the server stopped mid-way can't resume (it fails as `interrupted`). The ABS client is read-only (`GET`s), checks `GET /status` says `audiobookshelf` (and `isInit`) **before** sending the token anywhere, accepts only `http`/`https` addresses without credentials, a query or a fragment, follows redirects only to -the same host (never `https` → `http`, at most 4 of them), caps every response size +the same host (never `https` → `http`, at most 4 of them), trusts only the +certificates the system trusts (a self-signed one fails as `abs_certificate`, and +there is no setting to skip the check), caps every response size and times out each request (3 minutes) and the whole fetch (30 minutes). Its errors are fixed English sentences with a code; an ABS response body never reaches a response or a log. There is no private-address block: ABS usually @@ -8686,7 +8690,8 @@ An **import** reads: "finished": 161, "bookmarks": 73, "first_listen": "2021-02-03T20:11:09Z", - "last_listen": "2026-03-13T22:40:51Z" + "last_listen": "2026-03-13T22:40:51Z", + "identifiers": { "books": 640, "asin": 612, "isbn": 41, "by_title": 22, "already_matched": 95 } } } ``` @@ -8698,7 +8703,7 @@ An **import** reads: | `cutoff` | sessions **starting at or after** it are skipped; RFC 3339 UTC to the second (rounded down); `null` = none. Always the resolved value, never `"auto"` | | `cutoff_utc_offset` | the server's offset from UTC at the cutoff, in minutes (that date's, daylight saving included); `null` without a cutoff. A client shows and edits the cutoff in server time with it (a chosen day is the server's midnight), whatever its own zone | | `created_at`, `applied_at` | RFC 3339 UTC; `applied_at` `null` until applied | -| `error`, `error_code` | `""` unless `failed`. `error` is a safe English sentence; `error_code` is `abs_unreachable` (also a timeout), `abs_unauthorized`, `not_abs`, `fetch_failed` or `interrupted` | +| `error`, `error_code` | `""` unless `failed`. `error` is a safe English sentence; `error_code` is `abs_unreachable` (also a timeout), `abs_certificate`, `abs_unauthorized`, `not_abs`, `fetch_failed` or `interrupted` | | `summary` | `null` while fetching or when the fetch failed; planned at review (recounted by a cutoff change) and rewritten at apply with what was written | The fetched history is kept (gzipped, in `import_payloads`) only while the @@ -8721,7 +8726,14 @@ or deleted. - `finished`: the books given a finish (or a missing finish date) from ABS; - `bookmarks`: the bookmarks added; - `first_listen` / `last_listen`: the earliest and latest imported session start - (`null` without sessions). + (`null` without sessions); +- `identifiers`: the books here the import gives Audiobookshelf's ASIN or ISBN as + a match hint (see [Identifiers](#identifiers-match-hints) below). `books` counts + them, `asin` and `isbn` the books given each, `by_title` those paired by title + and author rather than by path, and `already_matched` the paired books left out + because they are matched here already. Absent from a summary planned before the + server carried identifiers, and all zero once such an import is planned again, + as its stored fetch holds none. A client treats a missing `identifiers` as none. `GET /admin/imports/{id}` adds the books that will be skipped, most listened first, at most 500: @@ -8766,6 +8778,30 @@ deleted items that resolve to one book all match it, with at most one item still in ABS, and their sessions merge. The apply matches again, so a book added since the review is found. +#### Identifiers (match hints) + +The fetch also keeps every ABS book with a valid ASIN or ISBN in the libraries the +token sees (`Payload.identified`, whoever's history it is in). Review and apply pair +them with books here (`importer.identifiersFor`): + +- among **every** book here, whatever the target user can access, as the hints are + the server's, not the person's; +- by the **path** tier, then the **title and author** tier, never by ASIN or ISBN + (those are what is being carried). A title pairing is guarded later by the match + run's agreement check (`matchrun.identifierAgrees`); +- leaving out a book two identified ABS books pair with (contested), an ABS folder + this server splits into disc books, and a book already matched here + (`catalog.matchedExpr`: its own ASIN or ISBN, or a recorded match), which is + counted as `already_matched`. + +The imports of one fetch carry the same identifiers, whichever person each is for. An apply writes them to `book_hints` (source `abs`, +`import_id` the import), replacing each book's hint whole, so the import applied +last owns a book's hint. They never become `books.asin` or `isbn` and never reach the +player wire. A hinted book stays unmatched until a match run's apply or the match +dialog writes a match, which is why the console offers **Match automatically** once +an import is applied. How a match sends them is +[`QueryFor`'s rule](../data-model.md#match-hints-from-an-import). + **Cutoff** values, in a start or a `PATCH`: `"auto"` (each user's first listening recorded here, `catalog.ListeningStart`: their earliest non-imported session or non-estimated rolled-up day; `null` when they have none), `null` @@ -8800,7 +8836,7 @@ with the same username (any case), if any. |---|---| | `200` | the server's version and its users | | `400` | `invalid request`; `code: "invalid_url"` - not an absolute `http`/`https` URL, or it carries credentials, a query or a fragment; `code: "invalid_import"` - the token is empty, over 8 KiB or holds a line break or NUL (ABS is not contacted) | -| `502` | `code: "abs_unreachable"` (no answer, a timeout or a `5xx`), `"not_abs"` (`/status` didn't answer as an initialised Audiobookshelf), `"abs_unauthorized"` (the token was refused) or `"fetch_failed"` (an unreadable answer) | +| `502` | `code: "abs_unreachable"` (no answer, a timeout or a `5xx`), `"abs_certificate"` (the `https` handshake refused ABS's certificate: untrusted, often self-signed, for another name, or expired; the console points at ABS's plain `http://` address), `"not_abs"` (`/status` didn't answer as an initialised Audiobookshelf), `"abs_unauthorized"` (the token was refused) or `"fetch_failed"` (an unreadable answer) | Not audited (it changes nothing). @@ -8865,9 +8901,18 @@ Applies a `review` import. The import moves to `applying`, then one transaction: `undone`, so a re-import never double counts; 2. matches and plans again against the user's state; 3. writes it: sessions, a `listening_history` span per session, estimates, - progress and bookmarks; + progress, bookmarks and the [match hints](#identifiers-match-hints); 4. marks it `applied`. +An import that writes no listening for the person (identifiers at most) applies when +the person has no applied import from the source. When they have one, step 1 would +take it back and replace it with nothing, so the apply is refused +(`catalog.ErrImportNoListening`), the transaction rolls back and the previous import +stays applied. Listening is a session, a rolled-up day, a bookmark, or a progress row +the import creates or moves on (position, finish or finish date); a row whose only +change is an earlier start date is not. The console turns **Apply** off for that +case (`wouldOnlyUndo`). Undo the applied import first to replace it. + A session already older than the session retention (`activity.session_days` as set when the apply runs) is written as the `listening_daily` totals the daily prune would make of it, rather than as a session. So it shows in the stats and @@ -8881,13 +8926,16 @@ Audible. The request's cancellation doesn't stop it. A failure puts it back in | Status | Meaning | |---|---| | `404` | `code: "import_not_found"` | -| `409` | `code: "import_not_ready"` - it isn't in `review` | +| `409` | `code: "import_not_ready"` - it isn't in `review`, or it writes no listening for the person while they have an applied import from the source (the message says to undo that one first) | ### `POST /api/v1/admin/imports/{id}/undo` Takes an applied import back out. Its sessions, rolled-up days, estimates, -history spans and bookmarks are deleted by `import_id`; a bookmark the person -edited or labelled since is kept and becomes theirs. Each progress row it changed +history spans, bookmarks and match hints are deleted by `import_id`. A hint a later +import rewrote is that import's and stays, and a hint this import rewrote from an +earlier one goes, even while that earlier import is still applied. Matches already +applied stay. A bookmark the person edited or labelled since is kept and becomes +theirs. Each progress row it changed is restored to what it was before, unless it changed since through a player's save or an edit, in which case it stays. Answers `200` with the import (`undone`). Audited as `import.undo` (`import`). A row restored from one an Audible account diff --git a/docs-developers/server/data-model.md b/docs-developers/server/data-model.md index 262d3b01..448737b2 100644 --- a/docs-developers/server/data-model.md +++ b/docs-developers/server/data-model.md @@ -25,7 +25,7 @@ to understand before you change the schema. `collection_items` and `ratings`; - per-library config: `folder_overrides`, `book_enrichment`, `issue_ignores`, `book_overrides`, `chapter_overrides`, `chapter_choices`, - `book_covers` and `book_matches`. + `book_covers`, `book_matches` and `book_hints`. The rest of a listener's own state hangs off the account rather than a path: `collections`, `collection_shares`, `listening_goals` and @@ -110,6 +110,7 @@ erDiagram libraries ||--o{ chapter_overrides : "durable config" libraries ||--o{ book_covers : "durable config" libraries ||--o{ book_matches : "durable config" + libraries ||--o{ book_hints : "durable config" libraries ||--o{ issue_ignores : "durable config" libraries ||--o{ scan_runs : "scan history" libraries ||--o{ community_chapters : "path-keyed, NO FK to books" @@ -1178,7 +1179,8 @@ else. `(user_id, id)`. - **`import_payloads`**: PK `import_id` (FK CASCADE). It holds the fetched history as gzipped JSON: the user's book items, sessions, progress and - bookmarks, and nothing secret. A cutoff change and the apply therefore never + bookmarks, and every ABS book with an ASIN or ISBN (`identified`, for the + [match hints](#match-hints-from-an-import)), and nothing secret. A cutoff change and the apply therefore never fetch again. It is a table of its own so that reading `imports` never walks a large blob's overflow pages. The row is deleted once the import is applied, undone or deleted. @@ -1254,6 +1256,15 @@ import from the same source. the two, and a finished row with no finish date takes ABS's. - A changed row's `version` goes up by one, and its before and after go in `import_progress_prior`. +- **Match hints.** A `book_hints` row (source `abs`, `import_id` the import) for + each book here the identified ABS books pair with (see + [Match hints from an import](#match-hints-from-an-import)). + +An apply that writes no listening (no session, day, bookmark, or progress row +created or moved on) is refused with `catalog.ErrImportNoListening` when the person +has a previous applied import from the source. Taking that one back to write +nothing would only lose their listening, so the transaction rolls back and it +stays applied. The cutoff gates sessions and estimates only. Its default (`"auto"`) is the person's first listening recorded here (`catalog.ListeningStart`): their @@ -1264,7 +1275,8 @@ counted once. #### Undo, retention and restarts **Undo**, and an apply replacing the previous import, deletes the import's -sessions, daily rows, history spans and untouched bookmarks by `import_id`. It +sessions, daily rows, history spans, untouched bookmarks and `book_hints` rows by +`import_id`. It restores each `import_progress_prior` row whose progress is still exactly as the import wrote it (`sameProgress`: path, version, `updated_at`, position, finish and dates). A restored row gets a version above the import's. @@ -1801,6 +1813,10 @@ keeps the report to once a day across restarts. The run status is the backup. - **`book_matches`** *(0069; `offered_asin` and `offered_isbn` in 0070)*: a book's recorded community match, described after this list. +- **`book_hints`** *(0074)*: PK `(library_id, path, source)`, `asin`, `isbn`, + `import_id`, `set_at`. Identifiers another app gave a book, kept as hints for a + community match only. See + [Match hints from an import](#match-hints-from-an-import). - **`issue_ignores`** *(0017)*: PK `(library_id, path, kind)`, `created_by` (FK to `users`, `ON DELETE SET NULL`), `created_at`. An admin's "ignore this" on a Health issue. `kind` is one of `catalog.IssueKinds` (`scan_error`, @@ -1842,7 +1858,8 @@ Two things write it: - the fold of a done `librivox.fetch` (`catalog.FoldLibrivoxFetch`), for the book the Bridge placed: `how` `accepted`, `set_by` the admin who asked, no run and no offered identifiers. By the result's `adopted`, it replaces a row already at - that path (a placed book, which also drops the path's leftover ASIN and ISBN), + that path (a placed book, which also drops the path's leftover ASIN, ISBN and + `book_hints`), keeps it (an adopted book), or replaces it and drops nothing (no `adopted`, an older Bridge). It touches no other path (see [Add from LibriVox](../bridge/librivox.md#the-books-identity)). @@ -2018,7 +2035,8 @@ never on the wire. Only `GetBook` and a run's subjects read them, and a tagged book stays `unmatched`. `matchrun.QueryFor` sends a hint as `BookASIN` or `BookISBN` when the book has -neither of its own. A hint the community database knows is then confident when +neither of its own, after an import's (see +[Match hints from an import](#match-hints-from-an-import) for the order). A hint the community database knows is then confident when its length fits and the book agrees with its title (see [Bulk community matching](api/reference.md#bulk-community-matching)). It becomes the book's ASIN only by an apply. A match run may propose another @@ -2037,6 +2055,53 @@ it stays an identifier. These are scanned values, like `released`, and every index rewrites them. +### Match hints from an import + +`book_hints` (migration 0074) holds the ASIN and ISBN another app gave a book. +Today the only source is `abs`: an applied +[Audiobookshelf import](#listening-imports) writes one row for each book here that +an ABS book with an identifier pairs with (`importer.identifiersFor`, by path, then +by title and author, across every book; see +[Identifiers](api/reference.md#identifiers-match-hints)). Like a tag hint, it is a +hint for a community match only. It is never `books.asin` or `isbn`, never on the +wire, and a hinted book stays `unmatched` until a match run's apply or the match +dialog writes its match. Only `GetBook` (a sub-select) and a run's subjects (a +`LEFT JOIN`, `matchSubjectJoin`) read it, as `Book.HintASIN` and `HintISBN` +(`json:"-"`). + +**What a match sends** (`matchrun.QueryFor`, for the match dialog and a run alike): + +1. A book with an ASIN or ISBN of its own sends only its own ASIN and ISBN, and + no hint. +2. Otherwise, with an import ISBN, it sends the import's ASIN and ISBN and nothing + from its tags. +3. Otherwise it sends the import's ASIN, else the tag's ASIN, and beside it the + tag's ISBN. + +So the import's identifiers go ahead of the tags'. A tag ASIN is sent only when the +import gave no identifier. A tag ISBN may go beside an import's ASIN, because +metaserve asks the ASIN first and the ISBN only when it doesn't know that one, so +the tag's ISBN is only a fallback. A tag ASIN beside an import ISBN would be asked +first, ahead of the import, so it never goes. A hit is judged as a tag hint's is +(`Classify`, `identifierAgrees`). The unknown-ASIN report sends a book's tag ASIN +only, never its import hint (`catalog.UnknownASINCandidates`). + +**Ownership.** An apply replaces each book's `abs` row whole, with its own +`import_id`, so the import applied last owns a book's hint. An undo, or an apply +replacing the person's previous import, deletes that import's rows by `import_id` +(index `idx_book_hints_import`). A row a later import took over stays with it, and +a row this import took over from an earlier one goes, even while the earlier import +is still applied. `import_id` has no foreign key: like `book_matches.run_id`, the +row outlives the import's record. + +**Durability.** The table is path-keyed with no FK to `books`, so a rebuild keeps +it. A move carries it (`moveBookState`). A disc join copies the first part's row +from each source. Deleting the library drops it (`ON DELETE CASCADE`). A book +the Bridge places from LibriVox drops the row at its path with the path's other +leftover identifiers (`catalog.FoldLibrivoxFetch`, see +[Add from LibriVox](../bridge/librivox.md#the-books-identity)), and an adopted +folder keeps it. + ### Labels: genres and tags `genres` and `tags` (`catalog/labels.go`) are override fields like any other, @@ -2166,6 +2231,7 @@ The migration history so far: | 0070 | `book_match_offered` | `book_matches.offered_asin` and `offered_isbn` (`TEXT NOT NULL DEFAULT ''`): the identifiers the [recorded community match](#durable-per-library-config-path-keyed-no-fk-to-books) offered. `match_run_items.unchanged` (`TEXT NOT NULL DEFAULT ''`): the comma-separated scopes under which a refresh item had nothing to change when recorded; an apply under one leaves it out without reading the book again. No backfill: `''` behaves as before. No data moves | | 0071 | `audible_sync_followups` | The `audible_title_match_update` trigger, recreated so a `preorder` title is left out of the sync and its release re-offers the book's place; `audible_accounts.refusal_ended_at` (see [The Bridge](#the-bridge)). No data moves | | 0073 | `podcast_episode_indexed` | `podcast_episodes.indexed_at`, backfilled from each episode's `books.indexed_at` (see [Podcasts](#podcasts)) | +| 0074 | `book_hints` | [Match hints from an import](#match-hints-from-an-import): `book_hints` (`library_id` `ON DELETE CASCADE`, `path`, `source`, `asin` and `isbn` `TEXT NOT NULL DEFAULT ''`, `import_id` `INTEGER NOT NULL DEFAULT 0`, `set_at`; primary key `(library_id, path, source)`) and the index `idx_book_hints_import` on `import_id`. No data moves | ## SQLite choices diff --git a/docs-developers/server/web-ui.md b/docs-developers/server/web-ui.md index 92b235a8..f577cb2d 100644 --- a/docs-developers/server/web-ui.md +++ b/docs-developers/server/web-ui.md @@ -524,8 +524,10 @@ The Overview is built on `GET /admin/stats`, `GET /admin/sessions/live`, `features/health/unmatched-prompt.tsx`): the `unmatched` category's count, ignored books left out, with **Match automatically** opening Health's Not matched list. It shows only while that count is above zero, so never while - community metadata is off. Library > Books shows the same notice while - browsing. + community metadata is off. It never starts a run. Library > Books shows the + same notice while browsing, Settings > Import's Past imports card once an import + is applied, and the setup flow's abs step (there with `newTab`, so Health opens + in a new tab and the flow stays open). - **Listening now** (`GET /admin/sessions/live`) has one card per live session, playing first, each linking to Activity > Live now. A card's second line is the chapter label described under [Activity > Live now](#activity--live-now), else the author or device. @@ -1906,7 +1908,7 @@ outside `AppShell`. `Root` signs the admin in, then `SignedIn` renders the bare shows with the setup state loaded decides, once (`redirectDecision` in `setup-model.ts`). The Overview, where a plain visit to `/admin` lands, goes to the flow. Any other page stays: a bookmark, a reload, the flow itself, or a link -the flow opens in a new tab (the ABS step's **Open the import**, the Reach +the flow opens in a new tab (the ABS step's **Match automatically**, the Reach step's HTTPS settings), which starts a session of its own. Either way the session is marked, so later pages in it are never redirected: **Finish later** (a link to Overview) and moving on from a deep link stay where they go. @@ -2018,9 +2020,17 @@ bridge phone` (`SETUP_STEPS`). Each step has Skip and, after the first, Back (`addressMismatch`). - The TLS mode, with what it means for phones, plus `tls_home_http` in self-signed mode. These are restart settings, badged. -6. **abs.** Points to Server > Settings > Import (in a new tab) and says that - ABS `metadata.json` files are read. An info-only step: Continue records - `done`, Skip `skipped`. +6. **abs.** The listening import itself, inline: Settings > Import's + `ImportFlow` (`features/imports/import-topic.tsx`) with `embedded` (no step + counter). It also says that ABS `metadata.json` files are read. + - While a books library is scanning or waiting to (`booksScanning` over the + polled libraries, no wire field), `blocked` turns Connect off with "Wait for + the scan to finish", because the import pairs ABS's books with the ones the + scan finds. Only Connect waits; the fields, Continue and Skip don't. + - `offerMatch` shows the `UnmatchedPrompt` once no books library is scanning, + before any import is applied. After an apply, the Past imports card shows it + instead (one render site). Either way it opens Health in a new tab. + - Continue records `done` whatever was imported, Skip `skipped`. 7. **backups.** `backups.schedule` and `keep` (1-365), the backup folder shown read-only, and `general.update_check`. `backups.dir` is restart-only and read-only in the settings API. From 58d3adbafbcb051fc23a28d06d87cd99d642f2a2 Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:10:46 +0000 Subject: [PATCH 3/8] Screenshots: the setup abs step with the import inline and the match offer Captured against the server's feat/abs-import-setup build: the step now holds the Connect to Audiobookshelf form and, once the first scan is done, the books not matched offer. The capture waits for both and takes the step's full height. Part of KodeStar/audiosilo-server#366. --- screenshots/capture-setup.mjs | 10 ++++++++-- screenshots/manifest.mjs | 2 +- static/img/screenshots/setup/abs.png | Bin 53913 -> 98967 bytes 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/screenshots/capture-setup.mjs b/screenshots/capture-setup.mjs index f9b9a4ab..c2dc8f7f 100644 --- a/screenshots/capture-setup.mjs +++ b/screenshots/capture-setup.mjs @@ -160,8 +160,14 @@ await step('the console flow', async () => { await tall('setup/reach.png'); await leave('Continue', 'Coming from Audiobookshelf?'); - // 6. Audiobookshelf: an info-only step, so Continue records it done. - await shoot(page, 'setup/abs.png'); + // 6. Audiobookshelf: the import inline (its empty Connect form, on now the scan + // has finished) and, below it, the not-matched offer once the issues load + // (community metadata is on and no book is matched). No Audiobookshelf is + // needed; Continue records the step done. + await page.getByLabel('Audiobookshelf address').waitFor({timeout: 15000}); + await page.getByRole('link', {name: 'Match automatically'}).waitFor({timeout: 15000}).catch(() => {}); + await sleep(600); + await tall('setup/abs.png'); await leave('Continue', 'Backups and updates'); // 7. Backups and updates. diff --git a/screenshots/manifest.mjs b/screenshots/manifest.mjs index d89a7727..ca553df7 100644 --- a/screenshots/manifest.mjs +++ b/screenshots/manifest.mjs @@ -189,7 +189,7 @@ export const SHOTS = [ {file: 'setup/naming.png', capture: 'setup', title: 'Setup - Book names', hint: 'step 3: four sample books named from tags and from folders side by side (the disagreeing rows marked), Folder names first preselected as Suggested (as tall as the page)'}, {file: 'setup/metadata.png', capture: 'setup', title: 'Setup - Community metadata', hint: 'step 4: community metadata on, the marketplace preselected from the browser (en-GB: United Kingdom), the service or a local copy, and the line saying Continue adds the library'}, {file: 'setup/reach.png', capture: 'setup', title: 'Setup - Addresses', hint: 'step 5, the library\'s scan done above it: the address the browser uses (a .local name) with Use as the home / public address, the two address fields, HTTPS: Off set by the config'}, - {file: 'setup/abs.png', capture: 'setup', title: 'Setup - Audiobookshelf', hint: 'step 6: what the Audiobookshelf import brings across, metadata.json read as it is, Open the import'}, + {file: 'setup/abs.png', capture: 'setup', title: 'Setup - Audiobookshelf', hint: 'step 6: what the Audiobookshelf import brings across, metadata.json read as it is, the import inline (the empty Connect to Audiobookshelf form, Connect on once the scan has finished), then the N books not matched offer with Match automatically'}, {file: 'setup/backups.png', capture: 'setup', title: 'Setup - Backups and updates', hint: 'step 7: the backup schedule (daily at 03:00), how many to keep (7), the backup folder (shown, set in config) and the update check'}, {file: 'setup/bridge.png', capture: 'setup', title: 'Setup - Add a Bridge', hint: 'step 8 with no Bridge paired: what a Bridge does, the compose snippet, Connect a bridge, Skip (as tall as the page)'}, {file: 'setup/phone.png', capture: 'setup', title: 'Setup - Connect a phone', hint: 'step 9, the last: the pairing QR code, New code, How signing in works with Invite someone, Open the web player, the ffmpeg line and the household note (as tall as the page)'}, diff --git a/static/img/screenshots/setup/abs.png b/static/img/screenshots/setup/abs.png index 0a929ace4555466bf599905e07824ba768fea44f..539df15b9280647ea2080ac555b606856901bbb0 100644 GIT binary patch literal 98967 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 z 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 dGp5$S3hs7(&-tx84f;acLkkS+y* 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�@4HN_$ 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 Date: Sat, 14 Nov 2026 19:12:58 +0000 Subject: [PATCH 4/8] Say an import's identifiers are sent by a match, in Features and What matching sends The console's privacy line now names an ASIN or ISBN from an Audiobookshelf import beside the tags', so the User Guide says the same. Also tidies two mid-sentence colons and a symbol name in the new Developer Docs text. Part of KodeStar/audiosilo-server#366. --- docs-developers/server/api/reference.md | 4 ++-- docs-developers/server/data-model.md | 6 +++--- docs-users/admin/books.md | 4 +++- docs-users/features.md | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs-developers/server/api/reference.md b/docs-developers/server/api/reference.md index 1ce960d9..52906599 100644 --- a/docs-developers/server/api/reference.md +++ b/docs-developers/server/api/reference.md @@ -8628,7 +8628,7 @@ the person's access. The console's **Server > Settings > Import**: another server's listening history copied into a person's own, so someone moving to AudioSilo keeps their -stats, and Audiobookshelf's ASIN and ISBN for the books here kept as +stats. It also keeps Audiobookshelf's ASIN and ISBN for the books here as [match hints](../data-model.md#match-hints-from-an-import) (`book_hints`). v1 reads **Audiobookshelf** (ABS) only and is **admin only**: no capability flag, no player route (the console ships inside the server). The work is `internal/importer` (the ABS client, matching, planning, the background @@ -8781,7 +8781,7 @@ added since the review is found. #### Identifiers (match hints) The fetch also keeps every ABS book with a valid ASIN or ISBN in the libraries the -token sees (`Payload.identified`, whoever's history it is in). Review and apply pair +token sees (`Payload.Identified`, JSON `identified`, whoever's history it is in). Review and apply pair them with books here (`importer.identifiersFor`): - among **every** book here, whatever the target user can access, as the hints are diff --git a/docs-developers/server/data-model.md b/docs-developers/server/data-model.md index 448737b2..f0a7df78 100644 --- a/docs-developers/server/data-model.md +++ b/docs-developers/server/data-model.md @@ -2058,7 +2058,7 @@ These are scanned values, like `released`, and every index rewrites them. ### Match hints from an import `book_hints` (migration 0074) holds the ASIN and ISBN another app gave a book. -Today the only source is `abs`: an applied +Today the only source is `abs`. An applied [Audiobookshelf import](#listening-imports) writes one row for each book here that an ABS book with an identifier pairs with (`importer.identifiersFor`, by path, then by title and author, across every book; see @@ -2091,8 +2091,8 @@ only, never its import hint (`catalog.UnknownASINCandidates`). replacing the person's previous import, deletes that import's rows by `import_id` (index `idx_book_hints_import`). A row a later import took over stays with it, and a row this import took over from an earlier one goes, even while the earlier import -is still applied. `import_id` has no foreign key: like `book_matches.run_id`, the -row outlives the import's record. +is still applied. `import_id` has no foreign key, so the row outlives the import's record, as +`book_matches.run_id` does. **Durability.** The table is path-keyed with no FK to `books`, so a rebuild keeps it. A move carries it (`moveBookState`). A disc join copies the first part's row diff --git a/docs-users/admin/books.md b/docs-users/admin/books.md index 0b22923c..43b85719 100644 --- a/docs-users/admin/books.md +++ b/docs-users/admin/books.md @@ -84,7 +84,9 @@ with community metadata** or run [Match automatically](health.md#matching-every- - the book's tagged title, author, series, narrators and language, and its length; -- any ASIN or ISBN, and what you type; +- its ASIN or ISBN, else one from its tags or an + [Audiobookshelf import](import.md#match-your-books-after-an-import), and what + you type; - up to three names from its path (the author, series and book folders), never the full path. diff --git a/docs-users/features.md b/docs-users/features.md index 69658dab..2ecb97f0 100644 --- a/docs-users/features.md +++ b/docs-users/features.md @@ -66,7 +66,7 @@ Everything else works with the server alone. - [Back up your Audible books](admin/audible.md) and keep your places in step with Audible. **(Bridge)** - [Add free books from LibriVox](admin/librivox.md): search LibriVox and download a public-domain audiobook into a library, already matched. **(Bridge)** - [Contribute from your server](community/contributing-from-your-server.md): share corrections and recaps with the community. **(Bridge)** -- [Import from Audiobookshelf](admin/import.md): bring over listening history, progress and bookmarks. +- [Import from Audiobookshelf](admin/import.md): bring over listening history, progress and bookmarks, and Audiobookshelf's ASINs and ISBNs for matching. ## Running the server From 11315a706afea5c7c461df1ae0f002679d55136f Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:17:03 +0000 Subject: [PATCH 5/8] Point hint order, ownership and the apply refusal at one description The match dialog's params and the cross-repo contract summarised QueryFor's order as "an import's, else its tags'", which misses a tag ISBN going beside an import ASIN; they now link to the data model's rule. Hint ownership on undo and what counts as listening for the apply refusal were spelled out twice with differing detail; each now lives in one place with a link from the other. Long lines re-wrapped. Part of KodeStar/audiosilo-server#366. --- .../architecture/cross-repo-contract.md | 8 ++--- docs-developers/server/api/reference.md | 33 ++++++++++--------- docs-developers/server/data-model.md | 25 +++++++------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs-developers/architecture/cross-repo-contract.md b/docs-developers/architecture/cross-repo-contract.md index 3166fa03..ef80817c 100644 --- a/docs-developers/architecture/cross-repo-contract.md +++ b/docs-developers/architecture/cross-repo-contract.md @@ -801,8 +801,8 @@ The match dialog sends `GET /works/match` the book's tag and path facts: - Its `language` and repeatable `narrator`. An older `metaserve` ignores them. - Its hints, as `asin` and `isbn`, when it has neither of its own: an Audiobookshelf - import's, else its tags' (`matchrun.QueryFor`, see the - [data model](../server/data-model.md#match-hints-from-an-import)). + import's and its tags' (`matchrun.QueryFor`, in + [this order](../server/data-model.md#match-hints-from-an-import)). Against a `metaserve` that predates the route, the server falls back to `lookup` and `works/search`. The candidates pass `metaserve`'s `score` and `reasons` through to @@ -1634,8 +1634,8 @@ not quiet, deduped per library and project, and in no module. folder. The server does not read it yet, and its scanner skips the name. - The server folds a done result into the book's `book_matches` row ([Matches by work id](#matches-by-work-id)), by `adopted`: a placed book - replaces the path's match and drops its leftover ASIN, ISBN and match hints, an adopted one - keeps a match already there. The `bridge_job_finished` event carries + replaces the path's match and drops its leftover ASIN, ISBN and match hints, an + adopted one keeps a match already there. The `bridge_job_finished` event carries `librivox_match` (`matched`, `kept`, `unmatched`). See [Add from LibriVox](../bridge/librivox.md). diff --git a/docs-developers/server/api/reference.md b/docs-developers/server/api/reference.md index 52906599..901bf567 100644 --- a/docs-developers/server/api/reference.md +++ b/docs-developers/server/api/reference.md @@ -7155,9 +7155,10 @@ wrong: is the book's author (mostly a composer tag filled with the author, which says nothing of the recording); - `q`, and the ASIN/ISBN: the typed ones, or the book's own when nothing was - typed, or with neither of its own its hints by `matchrun.QueryFor`'s rule - ([an Audiobookshelf import's](../data-model.md#match-hints-from-an-import), else - its [tags'](../data-model.md#tag-hints)), which metaserve looks up itself. + typed, or, with neither of its own, its hints from an Audiobookshelf import and + its [tags](../data-model.md#tag-hints) (`matchrun.QueryFor`, + [the order](../data-model.md#match-hints-from-an-import)). metaserve looks them + up itself. An older metaserve ignores `language` and `narrator`. @@ -8629,8 +8630,8 @@ the person's access. The console's **Server > Settings > Import**: another server's listening history copied into a person's own, so someone moving to AudioSilo keeps their stats. It also keeps Audiobookshelf's ASIN and ISBN for the books here as -[match hints](../data-model.md#match-hints-from-an-import) (`book_hints`). v1 reads **Audiobookshelf** (ABS) only and is **admin only**: no -capability flag, no player route (the console ships inside the server). The +[match hints](../data-model.md#match-hints-from-an-import) (`book_hints`). v1 +reads **Audiobookshelf** (ABS) only and is **admin only**: no capability flag, no player route (the console ships inside the server). The work is `internal/importer` (the ABS client, matching, planning, the background fetch); the rows are `catalog/imports.go`; the handlers (`api/handlers_import.go`) are transport only. What an applied import writes @@ -8781,8 +8782,8 @@ added since the review is found. #### Identifiers (match hints) The fetch also keeps every ABS book with a valid ASIN or ISBN in the libraries the -token sees (`Payload.Identified`, JSON `identified`, whoever's history it is in). Review and apply pair -them with books here (`importer.identifiersFor`): +token sees (`Payload.Identified`, JSON `identified`, whoever's history it is in). +Review and apply pair them with books here (`importer.identifiersFor`): - among **every** book here, whatever the target user can access, as the hints are the server's, not the person's; @@ -8794,9 +8795,10 @@ them with books here (`importer.identifiersFor`): (`catalog.matchedExpr`: its own ASIN or ISBN, or a recorded match), which is counted as `already_matched`. -The imports of one fetch carry the same identifiers, whichever person each is for. An apply writes them to `book_hints` (source `abs`, -`import_id` the import), replacing each book's hint whole, so the import applied -last owns a book's hint. They never become `books.asin` or `isbn` and never reach the +The imports of one fetch carry the same identifiers, whichever person each is +for. An apply writes them to `book_hints` (source `abs`, `import_id` the import), +replacing each book's hint whole, so the import applied last owns a book's hint +([ownership](../data-model.md#match-hints-from-an-import)). They never become `books.asin` or `isbn` and never reach the player wire. A hinted book stays unmatched until a match run's apply or the match dialog writes a match, which is why the console offers **Match automatically** once an import is applied. How a match sends them is @@ -8931,12 +8933,11 @@ Audible. The request's cancellation doesn't stop it. A failure puts it back in ### `POST /api/v1/admin/imports/{id}/undo` Takes an applied import back out. Its sessions, rolled-up days, estimates, -history spans, bookmarks and match hints are deleted by `import_id`. A hint a later -import rewrote is that import's and stays, and a hint this import rewrote from an -earlier one goes, even while that earlier import is still applied. Matches already -applied stay. A bookmark the person edited or labelled since is kept and becomes -theirs. Each progress row it changed -is restored to what it was before, unless it changed since through a player's save +history spans, bookmarks and match hints are deleted by `import_id` (a hint +belongs to the import that wrote it last, see +[ownership](../data-model.md#match-hints-from-an-import)). Matches already applied +stay. A bookmark the person edited or labelled since is kept and becomes theirs. +Each progress row it changed is restored to what it was before, unless it changed since through a player's save or an edit, in which case it stays. Answers `200` with the import (`undone`). Audited as `import.undo` (`import`). A row restored from one an Audible account wrote comes back under **no** device (`progressPrior.restored`), never as diff --git a/docs-developers/server/data-model.md b/docs-developers/server/data-model.md index f0a7df78..79f541c8 100644 --- a/docs-developers/server/data-model.md +++ b/docs-developers/server/data-model.md @@ -1180,8 +1180,8 @@ else. - **`import_payloads`**: PK `import_id` (FK CASCADE). It holds the fetched history as gzipped JSON: the user's book items, sessions, progress and bookmarks, and every ABS book with an ASIN or ISBN (`identified`, for the - [match hints](#match-hints-from-an-import)), and nothing secret. A cutoff change and the apply therefore never - fetch again. It is a table of its own so that reading `imports` never walks a + [match hints](#match-hints-from-an-import)). Nothing secret. A cutoff change + and the apply therefore never fetch again. It is a table of its own so that reading `imports` never walks a large blob's overflow pages. The row is deleted once the import is applied, undone or deleted. - **`import_id`** on `listening_sessions`, `listening_daily`, @@ -1260,11 +1260,10 @@ import from the same source. each book here the identified ABS books pair with (see [Match hints from an import](#match-hints-from-an-import)). -An apply that writes no listening (no session, day, bookmark, or progress row -created or moved on) is refused with `catalog.ErrImportNoListening` when the person -has a previous applied import from the source. Taking that one back to write -nothing would only lose their listening, so the transaction rolls back and it -stays applied. +An apply that writes no listening is refused (`catalog.ErrImportNoListening`) +when the person has a previous applied import from the source, so that one stays +applied (see the +[apply route](api/reference.md#post-apiv1adminimportsidapply) for what counts). The cutoff gates sessions and estimates only. Its default (`"auto"`) is the person's first listening recorded here (`catalog.ListeningStart`): their @@ -1276,8 +1275,7 @@ counted once. **Undo**, and an apply replacing the previous import, deletes the import's sessions, daily rows, history spans, untouched bookmarks and `book_hints` rows by -`import_id`. It -restores each `import_progress_prior` row whose progress is still exactly as the +`import_id`. It restores each `import_progress_prior` row whose progress is still exactly as the import wrote it (`sameProgress`: path, version, `updated_at`, position, finish and dates). A restored row gets a version above the import's. @@ -2036,8 +2034,9 @@ book stays `unmatched`. `matchrun.QueryFor` sends a hint as `BookASIN` or `BookISBN` when the book has neither of its own, after an import's (see -[Match hints from an import](#match-hints-from-an-import) for the order). A hint the community database knows is then confident when -its length fits and the book agrees with its title (see +[Match hints from an import](#match-hints-from-an-import) for the order). A hint +the community database knows is then confident when its length fits and the book +agrees with its title (see [Bulk community matching](api/reference.md#bulk-community-matching)). It becomes the book's ASIN only by an apply. A match run may propose another recording of the hint's work that fits the book's length better @@ -2091,8 +2090,8 @@ only, never its import hint (`catalog.UnknownASINCandidates`). replacing the person's previous import, deletes that import's rows by `import_id` (index `idx_book_hints_import`). A row a later import took over stays with it, and a row this import took over from an earlier one goes, even while the earlier import -is still applied. `import_id` has no foreign key, so the row outlives the import's record, as -`book_matches.run_id` does. +is still applied. `import_id` has no foreign key, so the row outlives the +import's record, as `book_matches.run_id` does. **Durability.** The table is path-keyed with no FK to `books`, so a rebuild keeps it. A move carries it (`moveBookState`). A disc join copies the first part's row From a3c051950e2e2922c623fd495487aafd0c00fcbc Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:17:03 +0000 Subject: [PATCH 6/8] Link the certificate advice and the match run instead of repeating them Moving from Audiobookshelf restated the self-signed certificate advice the import page already gives; it now links to When a fetch fails. The setup step's Match automatically line links to Matching every book at once. Part of KodeStar/audiosilo-server#366. --- docs-users/admin/import.md | 7 ++++--- docs-users/getting-started/coming-from-audiobookshelf.md | 2 +- docs-users/getting-started/first-run.md | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs-users/admin/import.md b/docs-users/admin/import.md index 758b710b..bd52f161 100644 --- a/docs-users/admin/import.md +++ b/docs-users/admin/import.md @@ -141,9 +141,10 @@ address uses a certificate the AudioSilo server doesn't trust, usually a self-signed one. Use its plain `http://` address on your network instead, for example `http://192.168.1.20:13378`. -For a fetch that fails later, the import card says why. Check that Audiobookshelf is running, that its -address works from the AudioSilo server, and that the token is right (use an -admin or root account's token to import other people). Then **Discard** it and +For a fetch that fails later, the import card says why. Check that +Audiobookshelf is running, that its address works from the AudioSilo server, and +that the token is right (use an admin or root account's token to import other +people). Then **Discard** it and start again. Nothing was written. ## Good to know diff --git a/docs-users/getting-started/coming-from-audiobookshelf.md b/docs-users/getting-started/coming-from-audiobookshelf.md index c4e2bc44..8c59501d 100644 --- a/docs-users/getting-started/coming-from-audiobookshelf.md +++ b/docs-users/getting-started/coming-from-audiobookshelf.md @@ -25,7 +25,7 @@ A book with a `metadata.json` file then shows its Audiobookshelf details in Audi **Server > Settings > Import** copies each person's listening sessions, progress and bookmarks from Audiobookshelf. It also brings Audiobookshelf's ASIN and ISBN for your books, as hints for matching. The setup flow's **Coming from Audiobookshelf?** step runs the same import. -[Invite](../admin/users-and-invites.md#inviting-someone) everyone first, so each person has an account to import into. Give the import Audiobookshelf's plain `http://` address on your network. AudioSilo refuses an `https://` address whose certificate it doesn't trust, such as a self-signed one. See [Import your Audiobookshelf history](../admin/import.md). +[Invite](../admin/users-and-invites.md#inviting-someone) everyone first, so each person has an account to import into. Give the import Audiobookshelf's plain `http://` address on your network if its `https://` one has a self-signed certificate (see [When a fetch fails](../admin/import.md#when-a-fetch-fails)). See [Import your Audiobookshelf history](../admin/import.md). ## Match your books diff --git a/docs-users/getting-started/first-run.md b/docs-users/getting-started/first-run.md index 1588726e..3f21f2e0 100644 --- a/docs-users/getting-started/first-run.md +++ b/docs-users/getting-started/first-run.md @@ -154,7 +154,7 @@ See [Reach your server from outside your home](./remote-access.md). This step runs the [Audiobookshelf import](../admin/import.md) right here. Connect to Audiobookshelf, review what matches for each person, then apply it. It brings each person's listening progress across, and Audiobookshelf's ASIN and ISBN for your books as hints for matching. - **Wait for the scan to finish.** The import pairs Audiobookshelf's books with the ones the scan finds, so **Connect** stays off while the library's first scan runs. -- **Then match your books.** If community metadata is on and books are not matched, the step says how many, with **Match automatically**. It opens Library health in a new tab, where you start the run and review what it found. Nothing is matched until you apply it. +- **Then match your books.** If community metadata is on and books are not matched, the step says how many, with **Match automatically**. It opens Library health in a new tab, where you [start the run](../admin/health.md#matching-every-book-at-once) and review what it found. Nothing is matched until you apply it. - **Continue** moves on whether or not you imported anything. The import stays in **Server > Settings > Import**. AudioSilo also reads the `metadata.json` files Audiobookshelf leaves beside your books. [Move over from Audiobookshelf](./coming-from-audiobookshelf.md) covers the rest. From 106ba09245eab40812812a47f9d3e90fa5e9c1c5 Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:21:02 +0000 Subject: [PATCH 7/8] Say import hints reach identifier_disagrees and leave books unmatched The review outcome still named only a tag ASIN or ISBN as the source of identifier_disagrees, and the unmatched issue rule said only tag hints don't count, though matchedExpr ignores book_hints too. The setup abs step's offer also needs a books library, and an older Bridge's LibriVox fold keeps a path's hints as an adopted one does. Part of KodeStar/audiosilo-server#366. --- docs-developers/server/api/reference.md | 2 +- docs-developers/server/data-model.md | 4 ++-- docs-developers/server/scanner.md | 2 +- docs-developers/server/web-ui.md | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs-developers/server/api/reference.md b/docs-developers/server/api/reference.md index 901bf567..1bb31382 100644 --- a/docs-developers/server/api/reference.md +++ b/docs-developers/server/api/reference.md @@ -7426,7 +7426,7 @@ Each book's **outcome**: | Outcome | Meaning | |---|---| | `auto` | Confident (`matchrun.Classify`): the best candidate scores **90** or more, at least **10** ahead of the next, its recording has an ASIN or ISBN (from 2.6.0, one with neither on firmer ground: see below the table), and, when both lengths are known, the recording's runtime is within **10%** of the book's (the closest recording of a work can still be another edition), or, from 2.6.0, within **20%** (`meta.NarratedRuntimeOff`) when the book's narrator reads it (`matchrun.narratorReads`: `reasons.narrator` is `full` and the proposed recording's own credit names one of the book's narrators, `meta.ReadBy`; a placeholder credit such as `Full Cast`, `GraphicAudio`, `Various` or `Unknown` never counts, `meta.PersonNarrator`, as it agrees with every recording carrying it). An identifier hit (`reasons.identifier`: in a match run always a hint, an Audiobookshelf import's or the tags') needs no lead, unless the next candidate is one too (`review`; a guard, as metaserve names one work per request today). From 2.7.0 the book must also agree with it (`matchrun.identifierAgrees`): `reasons.title`, when judged, at least **0.65** (`IdentifierTitleAgree`), or at least **0.9** (`IdentifierTitleSame`) when `reasons.series` is `conflict`, as the same title at another position is the series numbered another way (a conflict with no title judged is held). Else `review`. So a wrong hinted ASIN naming a book with a similar title within 10% of the length is still `auto`, and so, from 2.6.0, is one naming another edition of the right work when a recording of it within 10% takes its place (`meta.FitRecording`, [the dialog's rule](#get-apiv1adminlibrariesidbookmatch)). Applied unless the admin leaves it out. A repick's offers are all `auto`. | -| `review` | A candidate that isn't confident. Applied only if the admin puts it in. One held because its recording's length is more than 10% from the book's, or 20% when the book's narrator reads it (a match run's, as for `auto`, or a refresh's), carries `detail: "length_differs"` (from 2.4.0), worded with the item's `book.duration` and the proposal's `runtime_min`. One whose work holds only dramatizations the book doesn't state it is, none of them the book's by length ([`default_recording_id`](#get-apiv1adminlibrariesidbookmatch), from 2.6.0), carries `detail: "dramatization_only"` (`DetailDramatizationOnly`) and no recording, so nothing is attached unasked. One found by a tag ASIN or ISBN the book doesn't agree with (see `auto`, from 2.7.0) carries `detail: "identifier_disagrees"` (`DetailIdentifierDisagrees`), ahead of `dramatization_only` and `length_differs` when either would also apply. | +| `review` | A candidate that isn't confident. Applied only if the admin puts it in. One held because its recording's length is more than 10% from the book's, or 20% when the book's narrator reads it (a match run's, as for `auto`, or a refresh's), carries `detail: "length_differs"` (from 2.4.0), worded with the item's `book.duration` and the proposal's `runtime_min`. One whose work holds only dramatizations the book doesn't state it is, none of them the book's by length ([`default_recording_id`](#get-apiv1adminlibrariesidbookmatch), from 2.6.0), carries `detail: "dramatization_only"` (`DetailDramatizationOnly`) and no recording, so nothing is attached unasked. One found by a hinted ASIN or ISBN (its tags' or an Audiobookshelf import's) the book doesn't agree with (see `auto`, from 2.7.0) carries `detail: "identifier_disagrees"` (`DetailIdentifierDisagrees`), ahead of `dramatization_only` and `length_differs` when either would also apply. | | `none` | No candidate; or, in a match run, a best candidate scoring under **60** (`matchrun.ReviewFloor`) on metaserve's scale, with `detail: "weak_match"` (`DetailWeakMatch`), its `score` kept for the review's wording and its `proposal` empty (from 2.6.0). A candidate without `reasons` (an older metaserve's fallback search, on another scale) stays `review`. The match dialog has no such floor: it lists its candidates (up to 6) however low they scored. | | `error` | The service failed for this book (`detail: "metadata_unavailable"`), from 2.7.0 also when the best candidate's work can't be read for any reason but a `404` (a gone work gives way to the next). [Ten in a row](#what-a-run-asks-of-the-community-service) stop the run. | diff --git a/docs-developers/server/data-model.md b/docs-developers/server/data-model.md index 79f541c8..0e107003 100644 --- a/docs-developers/server/data-model.md +++ b/docs-developers/server/data-model.md @@ -2098,8 +2098,8 @@ it. A move carries it (`moveBookState`). A disc join copies the first part's row from each source. Deleting the library drops it (`ON DELETE CASCADE`). A book the Bridge places from LibriVox drops the row at its path with the path's other leftover identifiers (`catalog.FoldLibrivoxFetch`, see -[Add from LibriVox](../bridge/librivox.md#the-books-identity)), and an adopted -folder keeps it. +[Add from LibriVox](../bridge/librivox.md#the-books-identity)). An adopted +folder keeps it, as does an older Bridge's fold (no `adopted`). ### Labels: genres and tags diff --git a/docs-developers/server/scanner.md b/docs-developers/server/scanner.md index 4b841118..3c830da2 100644 --- a/docs-developers/server/scanner.md +++ b/docs-developers/server/scanner.md @@ -1770,7 +1770,7 @@ predicate over `books b`, shared by the counts (`IssueCounts`) and the lists | `suspect` | `suspect_parts >= 2`, and the folder has no `book` override | | `split_discs` | it is the **first** disc (by `rel_path`) of a book split across disc folders. `split_parent` is set, and that folder has no override of either mode (either one settles how it reads). Its fix sets `book` on `split_parent`, which joins the discs | | `no_cover` | a scan has checked it (`has_cover` not `NULL`), and it has no sidecar image, no embedded art and no custom cover | -| `unmatched` | it has no ASIN, no ISBN and no recorded community match (`book_matches`, see [Data model](data-model.md#durable-per-library-config-path-keyed-no-fk-to-books); `NOT catalog.matchedExpr`). [Tag hints](data-model.md#tag-hints) don't count. Offered only while community metadata is on | +| `unmatched` | it has no ASIN, no ISBN and no recorded community match (`book_matches`, see [Data model](data-model.md#durable-per-library-config-path-keyed-no-fk-to-books); `NOT catalog.matchedExpr`). [Tag hints](data-model.md#tag-hints) and an import's [match hints](data-model.md#match-hints-from-an-import) don't count. Offered only while community metadata is on | | `unknown_asin` | its own ASIN is one the [unknown-ASIN report](configuration.md#the-unknown-asin-report-metadatareport_unknown) found the community database doesn't know (an `unknown_asin_reports` row with `unknown = 1`, matched on the upper-cased, trimmed ASIN; `unknownASINExpr`), and it has no ISBN, no `book_matches` row and no ASIN a community match gave it (`book_overrides` of source `community`), so matching it by hand settles it. It still counts as matched (`matchedExpr`), so Match automatically skips it. The summary lists the kind only while the report is on, since only its lookups fill the table | | `series_spellings` | another book of its library spells its main series another way: the same `series_key`, a different `series`. This takes two range seeks on `idx_books_series_key`, for a spelling below its own or above. `SeriesSpellingGroups` lists them per series from the same predicate, and the console's fix sets one spelling with a bulk edit | | `no_chapters` | it is longer than **2 hours** and has at most one chapter. The console shows why community chapters weren't used from the row's `chapters_check` (a failed [community chapter check](community-chapters.md)) | diff --git a/docs-developers/server/web-ui.md b/docs-developers/server/web-ui.md index f577cb2d..51a24f94 100644 --- a/docs-developers/server/web-ui.md +++ b/docs-developers/server/web-ui.md @@ -2027,9 +2027,10 @@ bridge phone` (`SETUP_STEPS`). Each step has Skip and, after the first, Back polled libraries, no wire field), `blocked` turns Connect off with "Wait for the scan to finish", because the import pairs ABS's books with the ones the scan finds. Only Connect waits; the fields, Continue and Skip don't. - - `offerMatch` shows the `UnmatchedPrompt` once no books library is scanning, - before any import is applied. After an apply, the Past imports card shows it - instead (one render site). Either way it opens Health in a new tab. + - `offerMatch` shows the `UnmatchedPrompt` once the server has a books library + and none is scanning, before any import is applied. After an apply, the + Past imports card shows it instead (one render site). Either way it opens + Health in a new tab. - Continue records `done` whatever was imported, Skip `skipped`. 7. **backups.** `backups.schedule` and `keep` (1-365), the backup folder shown read-only, and `general.update_check`. `backups.dir` is restart-only and From 3778085df9ef1a48a646bab72125964d4bc99d2b Mon Sep 17 00:00:00 2001 From: KodeStar Date: Sat, 14 Nov 2026 19:21:02 +0000 Subject: [PATCH 8/8] Say how to settle a wrong import hint and when the match offer shows An Audiobookshelf hint goes ahead of the tags, so correcting a tag does not stop a wrong one coming back; matching the book by hand does. The import only sees the libraries its token can see, and Past imports offers Match automatically only with community metadata on. Part of KodeStar/audiosilo-server#366. --- docs-users/admin/health.md | 3 ++- docs-users/admin/import.md | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs-users/admin/health.md b/docs-users/admin/health.md index af86cd96..284faa8c 100644 --- a/docs-users/admin/health.md +++ b/docs-users/admin/health.md @@ -157,7 +157,8 @@ differently: - **From an [Audiobookshelf import](import.md#match-your-books-after-an-import).** They are match hints, like tags. A match looks them up before the book's tags, - and the book stays **Not matched** until a match applies. + and the book stays **Not matched** until a match applies. A wrong one can look + confident too, and correcting the tag doesn't stop it: match the book by hand. - **From a `metadata.json` file beside the book.** The ASIN or ISBN counts as the book's own straight away, so the book is matched (see [Audiobookshelf's metadata.json files](../getting-started/organizing-your-library.md#coming-from-audiobookshelf)). diff --git a/docs-users/admin/import.md b/docs-users/admin/import.md index bd52f161..86d26ea6 100644 --- a/docs-users/admin/import.md +++ b/docs-users/admin/import.md @@ -89,8 +89,9 @@ nothing is counted twice. ## Match your books after an import An import doesn't match your books. It brings Audiobookshelf's ASIN and ISBN for -every book Audiobookshelf has them for, whoever listened to it. A match run then -looks them up in the community database. +every book Audiobookshelf has them for in the libraries the token can see, +whoever listened to it. A match run then looks them up in the community +database. - The server pairs these books with yours by folder path, then by title and author. @@ -101,9 +102,9 @@ looks them up in the community database. - A match looks Audiobookshelf's identifiers up ahead of any in the book's tags. -So nothing shows until a match run applies. Once an import is applied, **Past -imports** says how many books are not matched, with a **Match automatically** -button. It opens the unmatched books in Library health, where you start the run, +So nothing shows until a match run applies. Once an import is applied, with +community metadata on, **Past imports** says how many books are not matched, +with a **Match automatically** button. It opens the unmatched books in Library health, where you start the run, review what it found and apply it. See [Matching every book at once](health.md#matching-every-book-at-once).