Skip to content

fix: use ebookProgress field for ebook reading progress#166

Closed
OnlyTerp wants to merge 9 commits intorohit-purandare:mainfrom
OnlyTerp:fix/ebook-progress-v2
Closed

fix: use ebookProgress field for ebook reading progress#166
OnlyTerp wants to merge 9 commits intorohit-purandare:mainfrom
OnlyTerp:fix/ebook-progress-v2

Conversation

@OnlyTerp
Copy link
Copy Markdown

@OnlyTerp OnlyTerp commented Mar 8, 2026

Fixes #162

Problem

ShelfBridge reads progress instead of ebookProgress for ebooks, causing ebook reading progress to always show as 0%.

Root Cause

The previous fix (PR #164) used nullish coalescing (??) to fall back from progressData.progress to progressData.ebookProgress. However, for ebooks the ABS API returns progress: 0 (not null or undefined), so ?? never triggered the fallback — 0 ?? ebookProgress returns 0.

The media type detection (isEbook) also had fragility issues — if media.ebookFile wasn't detected correctly (e.g., dual-format items, unexpected API structure), the code would take the audiobook path and never check ebookProgress.

Fix

1. Progress field selection (src/audiobookshelf-client.js)

Matches ABS's own client logic: if progress is falsy (0) and ebookProgress > 0, use ebookProgress. This completely avoids relying on media type detection for choosing the right progress field.

\\js
// Before (broken): 0 ?? ebookProgress === 0
const rawProgress = isEbook
? (progressData.ebookProgress ?? progressData.progress)
: (progressData.progress ?? progressData.ebookProgress);

// After (matches ABS client): 0 is falsy, so ebookProgress is used
const rawProgress = (!progressData.progress && progressData.ebookProgress > 0)
? progressData.ebookProgress
: (progressData.progress || 0);
\\

2. Ebook format detection (src/matching/utils/audiobookshelf-extractor.js)

  • Uses has_ebook_progress (derived from ebookProgress > 0) as the strongest signal for ebook format detection, overriding fragile mediaType/media.ebookFile checks
  • Handles dual-format items (both ebookFile and audioFiles) by checking which format has actual user progress

Changes

File What changed
src/audiobookshelf-client.js Progress field selection matches ABS client logic; stores has_ebook_progress and ebook_location on item data
src/matching/utils/audiobookshelf-extractor.js has_ebook_progress as top-priority format signal; dual-format item handling

Testing

  • All 124 existing tests pass ✅
  • All 26 completion detection tests pass ✅
  • No new dependencies
  • Minimal, focused diff (2 files, ~35 lines changed)

rohit-purandare and others added 9 commits March 2, 2026 08:19
Audiobookshelf returns ebook progress in a separate ebookProgress
field while the progress field is always 0 for ebooks. Prefer
ebookProgress when available, falling back to progress for audiobooks.
Fixes issue where books finished naturally in Audiobookshelf were not
updating to 100% completion in Hardcover.

Root cause: extractFinishedFlag() only checked is_finished boolean but
ignored finished_at timestamp. When users finish books naturally by
listening to the end, Audiobookshelf sets finished_at but is_finished
may remain false.

Changes:
- Check finished_at timestamp in addition to is_finished flag
- Return null (not false) when no completion indicators found, allowing
  position-based and percentage-based detection to proceed
- Reduce time-remaining threshold from 120s to 60s for audiobooks
- Add aggressive 98% completion threshold for all formats
- Fix parameter name mismatch in isBookComplete() method

Tests:
- Add comprehensive test suite with 28 tests covering all scenarios
- All existing tests still pass (127 total)
- Includes integration test reproducing exact bug scenario
…ress

The ?? operator doesn't fall through when ebookProgress is 0 (not nullish),
causing all audiobooks to report 0% progress. Using || correctly falls
through to the progress field when ebookProgress is 0 (falsy).
Remove stale files that were accidentally left in the repo:
DUPLICATE_MATCHING_FIX.md, SECURITY_NOTE.md,
TESTING_WANT_TO_READ_STATUS_UPDATE.md, run-all-tests.sh,
test-release-targeting.txt, test-signing.md, wait-and-test.sh
Two-stage title/author matches store the book ID at match.book.id when
the book isn't in the user's library, but sync-manager only checked
match.userBook?.book?.id (undefined when userBook is null). Also fix
edition ID being cached as undefined since _cacheSuccessfulMatch used
bestMatch.id instead of bestMatch.edition.id for two-stage results.
…and format

Audiobookshelf uses mediaType 'book' for both audiobooks and ebooks.
Previously this always resolved to 'audiobook', causing ebooks to match
audiobook editions and report wrong progress (e.g. 62.5% → 0.0%).

Now check media.ebookFile and media.audioFiles to distinguish ebooks
from audiobooks. Also use the correct progress field per item type:
ebookProgress for ebooks, progress for audiobooks.
The log used edition.reading_format?.format which is only present on
raw Hardcover editions. Two-stage title/author matches flatten this to
edition.format. Fall back to edition.format so the log isn't undefined.
Root cause: ShelfBridge used nullish coalescing (??) to fall back from
progress to ebookProgress, but for ebooks the ABS API returns progress=0
(not null/undefined), so ?? never triggered the fallback.

Changes:
- audiobookshelf-client.js: Match ABS client logic - use ebookProgress
  when progress is falsy (0) and ebookProgress > 0. This avoids relying
  on fragile media type detection for choosing the progress field.
- audiobookshelf-client.js: Store has_ebook_progress and ebook_location
  on item data for downstream format detection.
- audiobookshelf-extractor.js: Use has_ebook_progress as the strongest
  signal for ebook format detection (overrides mediaType checks).
- audiobookshelf-extractor.js: Handle dual-format items (both ebookFile
  and audioFiles) by checking which format has actual progress.
@OnlyTerp OnlyTerp closed this by deleting the head repository Mar 11, 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.

[bug] Shelfbridge reads progress instead of ebookProgress for ebooks

2 participants