Skip to content

feat: optional Hardcover wishlist sync with automated, library-aware downloading#1047

Open
InfiniteAvenger wants to merge 9 commits into
calibrain:mainfrom
InfiniteAvenger:main
Open

feat: optional Hardcover wishlist sync with automated, library-aware downloading#1047
InfiniteAvenger wants to merge 9 commits into
calibrain:mainfrom
InfiniteAvenger:main

Conversation

@InfiniteAvenger

Copy link
Copy Markdown

Summary

Adds an opt-in automation pipeline that syncs a Hardcover reading shelf into
Shelfmark requests and (optionally) downloads them, skipping anything already in an
Audiobookshelf library. Everything is disabled by default — with all toggles off,
behavior is identical to today.

What this adds

A new Settings → Hardcover Sync tab with three independently-toggleable capabilities:

  • Hardcover wishlist sync — pull a Hardcover shelf (e.g. "Want to Read") into
    Shelfmark as requests on a schedule (configurable in minutes or hours) or via a
    "Sync now" button. Synced requests carry full metadata and cover art.
  • Automatic downloads — auto-approve and download synced requests, choosing the best
    release from a drag-to-reorder source-priority list. A strict title/author/
    audiobook-format (and seeder) match guard avoids grabbing the wrong file; anything
    without a confident match is left as a pending request for manual review.
  • Library-aware de-duplication — check an Audiobookshelf library (ISBN + fuzzy
    title/author) and skip books already owned. Fails open (proceeds) if ABS is
    unreachable, so the pipeline never stalls.

Design

  • Opt-in, no default behavior change — all features gated behind settings that
    default to off.
  • Reuses existing systems — synced books flow through the normal request →
    fulfil_requestqueue_release download path; there's no parallel pipeline.
  • One behavior-preserving refactor — extracts the per-source release search out of
    the /api/releases route into a reusable helper so the auto-picker and the route
    share it.
  • Conservative matching — biased toward leaving items pending rather than
    downloading the wrong file.
  • In-process scheduler modeled on the existing download coordinator (daemon thread).

New modules

core/text_match.py, core/release_search.py, core/auto_download.py,
core/hardcover_sync.py, core/hardcover_scheduler.py, core/library_index.py,
config/hardcover_sync_settings.py; plus wiring in main.py (scheduler start + search
refactor) and config/settings.py (tab registration).

Testing

  • ruff clean on all changed files.
  • Existing tests/core suite (request/release/search/requests-service) passes.
  • Verified end-to-end against a live Hardcover account and Audiobookshelf instance:
    wishlist → request (with cover) → strict-matched auto-download, plus owned-book skip
    and fail-open when ABS is down.

Scope note

I'm aware the README lists library integration, automation, and monitoring as explicit
non-goals, so this may simply be out of scope — totally understand if so. I built it for
my own setup and figured I'd offer it in case it's useful. It's entirely opt-in and off
by default, so it has no effect on the core tool for anyone who doesn't enable it. Happy
to keep maintaining it as a fork either way.

InfiniteAvenger and others added 9 commits June 5, 2026 23:29
Move the activity/status toast notifications from the bottom-right to the
bottom-left corner and flip the pop-up slide-in animation to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…orkflow

Populate missing request metadata (cover, year, subtitle) from the configured
metadata provider and proxy cover URLs in both the REST request endpoints and
the activity snapshot the sidebar actually consumes, so requests show artwork.
Also allow the request workflow to operate in no-auth mode (resolve the admin
as user 1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…aware dedup

Add an end-to-end pipeline that syncs a Hardcover reading shelf into Shelfmark
requests and (optionally) auto-downloads them, configurable from a new
"Hardcover Sync" settings tab.

- hardcover_sync: pull the configured shelf via the Hardcover provider (covers
  included) and create pending requests, with provider-id / download-history /
  library dedup.
- auto_download: walk a user-ordered release-source priority list, apply a
  strict title/author/audiobook-format(+seeders) match guard, and queue the
  best candidate via the normal fulfil path; no confident match leaves the
  request pending for manual review.
- hardcover_scheduler: in-process daemon scheduler (minutes/hours interval) plus
  a manual "Sync now" action.
- library_index: check the Audiobookshelf library (ISBN + fuzzy title/author)
  and skip books already owned; fail-open if ABS is unreachable.
- release_search: extract the per-source release search out of the /api/releases
  route into a reusable helper (route delegates to it, behavior-preserving).
- text_match: shared fuzzy token/ISBN matching reused by the release and library
  matchers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a fork notice crediting upstream calibrain/shelfmark, document the added
automation (Hardcover wishlist sync, automatic downloads, Audiobookshelf
library-aware de-duplication) in a new "Fork Additions" section, and remove the
upstream maintenance note plus the Project Scope / Contributing sections (whose
non-goals this fork intentionally diverges from). Point Support at the fork.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The create-aliases job re-tagged images under Shelfmark's former name
(calibre-web-automated-book-downloader) for upstream backwards-compatibility. It
built the reference from the repository owner verbatim, which fails on this fork
because Docker repository names must be lowercase ("InfiniteAvenger/..."). The
fork has no legacy users, so remove the job entirely; the image build/publish
jobs are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Document that the Hardcover integration is designed to complement ShelfBridge
(Audiobookshelf -> Hardcover progress sync) by syncing the other direction
(Hardcover wishlist -> library).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the README/docs curl commands and the compose-file image references to
this fork (raw.githubusercontent.com/InfiniteAvenger and
ghcr.io/infiniteavenger/shelfmark[-lite]) so following the install steps deploys
the fork rather than upstream. Upstream attribution links are intentionally
preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update the footer "source" link and header "report issue" link to the fork repo,
the Apprise notification logo URL to the fork's raw logo, and the bypasser lab's
LATEST_IMAGE to the fork image. LEGACY_IMAGE stays on upstream v1.0.2 as a
historical baseline (the fork has no equivalent tag). Upstream attribution links
in the README are intentionally preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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