Skip to content

Book labels: tags, genres, subtitle, publisher, language and abridged - #145

Merged
KodeStar merged 6 commits into
mainfrom
feat/book-labels
Oct 16, 2026
Merged

KodeStar merged 6 commits into
mainfrom
feat/book-labels

Conversation

@KodeStar

Copy link
Copy Markdown
Owner

Closes #136. Also covers the report that /item doesn't expose genres, publisher, language, subtitle or abridged, and that export rows can't be tied back to items.

What changes

  • Six layered book fields (path-keyed overrides with provenance, surviving rescans): subtitle, publisher, language, abridged (absent = unknown), genres, tags. Precedence scan -> metadata.json -> community -> edited.
  • Sources:
    • the files' genre tag: split on ; and NUL, never ,, since a store category like "Mystery, Thriller & Suspense" has one; placeholders like "Audiobook" dropped;
    • Audiobookshelf metadata.json, which now reads subtitle, publisher, language, abridged (true only), genres and tags; chapters are still not read;
    • a community match, which fills subtitle, language, publisher and abridged; no community genres yet.
  • Migration 0049:
    • adds the columns and a derived book_labels index;
    • recreates books_fts with genres and tags;
    • re-reads each metadata.json and each primary file's genre once on the next scan, without a re-index.
  • Player API: the fields go on /item, list and search books (omitempty, additive). GET /libraries/{id}/books?genre=&tag=, and search matches labels.
  • Admin:
    • the book page edits them: chip input, abridged select;
    • /admin/books and facets take genre=/tag= (the top 100 plus the chosen one);
    • bulk edit and the book PATCH take add/remove for genres and tags, merged into each book's own list.
  • Export: rows gain subtitle, publisher, language, abridged and genres (version stays 1). Paths and the admin's own tags appear only with ?include=paths,tags ("Export with file paths and tags...", behind a warning, downloaded as -private.json). The default file stays safe to attach to a public meta import issue.

Verification

  • Go and console tests on every layer, including:
    • the migration and its backfill;
    • precedence, and an edit surviving a rescan;
    • filters and FTS;
    • bulk add/remove keeping each book's own labels;
    • export with and without each include;
    • denied for non-admins.
  • Real browser: an existing 0048 database migrated cleanly, and its first scan filled the fields with 0 books re-indexed.
    • The console's chips, facets, bulk add/remove, search, and both exports checked.
    • The player built from the frontend branch shows the subtitle, About facts and chips, and its Library Genre/Tag pickers filter.
  • Gates: build-admin, go build/vet/test -race and golangci-lint green.

Follow-ups (not in this PR)

  • Community genres need audiosilo-meta to put genres on match candidates.
  • A bulk add then remove that ends at the files' list keeps an (empty) edited lock rather than reverting.
  • Facets show the top 100 labels plus the chosen one, so there's no type-ahead for rare tags.

Pairs with KodeStar/audiosilo-frontend (feat/book-labels). Docs: KodeStar/audiosilo-docs (docs/book-labels).

… as layered fields; genre/tag filters, search, bulk add/remove, and the export's paths (0049)
…abridged on the book page; bulk add/remove of labels, genre and tag facets, and the export with file paths
The export keeps tags out unless asked (include=paths,tags; a row no longer
names its library), the facet counts by a semi-join named by seriesName, the
label filters stay in the library, an edit that changes nothing on a book
leaves its row alone, 0049 re-reads only books with a metadata.json, and the
kinds are the field names. One canonical-list encoder, one scanned-snapshot
writer, one abridged rule; SplitGenres leaves cleaning to CleanLabels. The
console shares one label chip, one isLabelField guard and cleanLabels.
A chip's x removes it in Safari and Firefox (the click no longer ends the
edit first); a label typed in a bulk box without Enter goes with the edit; a
private export downloads as -private.json and reads every include= value;
merged rows take every copy's tags; a chosen label beyond the top 100 facets
keeps its count; the label filters leave the library index alone; a genre
tag is never split on a comma (a store's category holds one).
@KodeStar
KodeStar merged commit 1dfd7a9 into main Oct 16, 2026
3 checks passed
@KodeStar
KodeStar deleted the feat/book-labels branch October 16, 2026 12:24
@KodeStar KodeStar mentioned this pull request Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing feature: Tags

1 participant