Skip to content

feature: abs propagation - #133

Open
benjitobz wants to merge 8 commits into
Chaptarr:developfrom
benjitobz:feature/abs-propagation
Open

benjitobz wants to merge 8 commits into
Chaptarr:developfrom
benjitobz:feature/abs-propagation

Conversation

@benjitobz

Copy link
Copy Markdown

Description

AudioBookShelf keeps its own copy of an item's metadata and only re-reads it when files are renamed, so a change Chaptarr makes to a book would otherwise never show up there. This sends the current title, description, publisher, series, and cover to the matching AudioBookShelf item whenever the owning library changes, behind a per-connection setting that says what the push actually carries. Items are matched by library-relative path across the connection's mapped libraries. AudioBookShelf is never read back — it stays a consumer, not a source.

Fixes # - n/a (feature)

Database Migration

NO - The setting lives in the connection's existing JSON settings blob

How was this tested?

Docker (linux/amd64) on an Ubuntu server host, image built with Dockerfile.build, against a live Audiobookshelf instance.

  • Metadata edits propagated: changed fields (description, tags-as-genres, series) arrived on the matching ABS item, located by library-relative path.
  • Cover updates delivered via the item cover endpoint from the library's cover URL.
  • With the setting off, nothing is pushed — default behaviour unchanged.
  • Confirmed no reverse flow: ABS-side edits are never read back into Chaptarr.

Screenshots (UI changes only)

image

A note on AI: We know AI/agentic coding is everywhere and only getting
more popular. We won't insist that you disclose whether you used it or which
models you used, but in the same spirit, please don't take offense if your PR
is scrutinized and changes are requested.

Review time: The longer the PR and the more lines changed, the longer the
review will take. Small, focused PRs merge fastest. If yours is big, please be
patient.

AudioBookShelf keeps its own copy of an item's metadata and only re-reads it
when files are renamed, so a change Chaptarr makes to a book would otherwise
never show up there.

Send the current title, description, publisher, series and cover to the
matching item whenever the owning library changes, behind a per-connection
setting that says what the push actually carries.
Implements the IExternalLibraryEditTarget seam so sources like the
Grimmory forwarder can land metadata and cover edits on mapped items,
gated on Push Library Edits. Covers upload as bytes because a target
cannot fetch behind another service's auth. Also brings the targeted
updates fixture in line with the propagation-era proxy and ctor.
@benjitobz benjitobz changed the title Feature/abs propagation feature: abs propagation Sep 9, 2026
benjitobz and others added 5 commits September 9, 2026 18:36
AudioBookShelf keeps resized thumbnails in its cache and does not invalidate
them when the cover bytes change, so the item kept rendering the stale
thumbnail after a push.
Keep only the comments that record something the code cannot: that
AudioBookShelf flags deleted items missing rather than removing them, that
it serves stale resized thumbnails after a cover is re-pointed at the same
path, that a rescan must precede a metadata push, and that title stays
Chaptarr's when a forwarded edit is applied. The two notes at the
PurgeCoverCache call sites restated the one on the method itself.

Use the IsNullOrWhiteSpace extension the rest of the proxy already uses,
import System.IO and System.Globalization rather than qualifying inline,
and move the library-items response type down with the other private
members instead of leaving it between two public methods.

Order the two new AudioBookShelf fields in the file the way their
FieldDefinition indexes order them, and drop the guards that cannot fire:
repository books are never null, and the only PushBooksMetadata caller
already filters the list it passes.

Remove the stray note on CalibreChanges.Series, which sat between the
attribute and the property and described the opposite of what
NullValueHandling.Include does.
AudioBookShelfLibraryEditService handles MediaCoversUpdatedEvent and pushed the
whole metadata block, so a cover refresh restated Chaptarr's title, description,
publisher, series and genres over whatever the AudioBookShelf item held. Genres
curated in AudioBookShelf were silently reverted.

That event is not an edit. It is raised by routine work - an author refresh, the
daily cover repair, the deferred cover flush that runs after every import - and
carries no information about metadata having changed, so there is nothing to
push but the cover.

Real library edits are unaffected: they arrive through PushExternalLibraryEdit
with a payload describing what changed, which is a separate path.
…tten

AudioBookShelfLibraryEditService and ExtraService both handle
MediaCoversUpdatedEvent. ExtraService rewrites the cover.jpg in the book
folder; the AudioBookShelf handler then tells AudioBookShelf to copy that
same file. Their relative order was unspecified, and when the push ran
first AudioBookShelf stored the previous cover. Pinning a different
audiobook edition showed it: the new square cover landed in the folder
about 60 ms after AudioBookShelf had already copied the old rectangular one.

Mark the AudioBookShelf handler EventHandleOrder.Last so the file it points
at is always the one this event produced.
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.

1 participant