Fix kobo sync to include magic shelf-only books

include magic shelf book IDs in allow-list when syncing only specific shelves
prevent deletions of magic-shelf-only books
ensure reading-state sync respects magic shelf allow-list
resolves Issue #976 (magic shelf books not syncing to Kobo)

[bug] MagicShelf exclusive books don't sync to kobo
Fixes #976
This commit is contained in:
crocodilestick
2026-01-31 13:02:20 +01:00
parent ae95cab402
commit 09cdddff05
3 changed files with 51 additions and 19 deletions
+5 -4
View File
@@ -12,7 +12,7 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
# Upstream Contributors (janeczku/calibre-web)
- OzzieIsaacs (anon) (2794 commits)
- Ozzie Isaacs (anon) (269 commits)
- Ozzie Isaacs (anon) (272 commits)
- cbartondock (96 commits)
- idalin (69 commits)
- cervinko (68 commits)
@@ -38,10 +38,10 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
- kyos (anon) (18 commits)
- quarz12 (18 commits)
- Thore Schillmann (anon) (18 commits)
- webysther (16 commits)
- mapi68 (15 commits)
- ok11 (13 commits)
- pwr (13 commits)
- webysther (13 commits)
- Kyosfonica (11 commits)
- otapi (11 commits)
- andy29485 (10 commits)
@@ -281,6 +281,7 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
- robochud (1 commits)
- ruben-herold (1 commits)
- ryanlong1004 (1 commits)
- sakuyamaij (1 commits)
- sartoshi-foot-dao (1 commits)
- schnabelewobski (1 commits)
- shsm0520 (1 commits)
@@ -315,7 +316,7 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
- zhiyue (1 commits)
# Fork Contributors (crocodilestick/calibre-web-automated)
- crocodilestick (1045 commits)
- crocodilestick (1047 commits)
- jmarmstrong1207 (73 commits)
- demitrix (30 commits)
- sirwolfgang (29 commits)
@@ -335,6 +336,7 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
- Calychas (3 commits)
- ceruleandeep (anon) (3 commits)
- deadbone (3 commits)
- github-actions[bot] (3 commits)
- PulsarFTW (3 commits)
- stewie83 (3 commits)
- zikasak (3 commits)
@@ -344,7 +346,6 @@ Copyright (C) 2024-2026 Calibre-Web Automated contributors
- coissac (2 commits)
- doxxx (2 commits)
- FennyFatal (2 commits)
- github-actions[bot] (2 commits)
- itsmarcy (2 commits)
- JamesRy96 (2 commits)
- Olen (2 commits)
+45 -14
View File
@@ -126,6 +126,28 @@ def convert_to_kobo_timestamp_string(timestamp):
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def get_magic_shelf_book_ids_for_kobo(user_id):
if not config.config_kobo_sync_magic_shelves:
return set()
magic_shelves = ub.session.query(ub.MagicShelf).filter_by(user_id=user_id, kobo_sync=True).all()
if not magic_shelves:
return set()
book_ids = set()
for shelf in magic_shelves:
books, _ = magic_shelf.get_books_for_magic_shelf(
shelf.id, page=1, page_size=None
)
for book in books:
book_ids.add(book.id)
if book_ids:
log.debug("Kobo Sync: magic shelf allowed books: %s", len(book_ids))
return book_ids
@kobo.route("/v1/library/sync")
@requires_kobo_auth
# @download_required
@@ -158,7 +180,9 @@ def HandleSyncRequest():
# Two-Way-Sync Deletion Logic
magic_shelf_book_ids = set()
if current_user.kobo_only_shelves_sync:
magic_shelf_book_ids = get_magic_shelf_book_ids_for_kobo(current_user.id)
try:
# Check all books that are on Kobo according to the database
synced_books_query = ub.session.query(ub.KoboSyncedBooks.book_id).filter(ub.KoboSyncedBooks.user_id == current_user.id)
@@ -169,6 +193,8 @@ def HandleSyncRequest():
.join(ub.Shelf, ub.BookShelf.shelf == ub.Shelf.id)
.filter(ub.Shelf.user_id == current_user.id, ub.Shelf.kobo_sync == True))
allowed_book_ids = {item.book_id for item in allowed_books_query}
if magic_shelf_book_ids:
allowed_book_ids |= magic_shelf_book_ids
# Spot the difference: books that need to be deleted
books_to_delete_ids = synced_book_ids - allowed_book_ids
@@ -213,18 +239,21 @@ def HandleSyncRequest():
ub.ArchivedBook.user_id == current_user.id))
.filter(db.Books.id.notin_(calibre_db.session.query(ub.KoboSyncedBooks.book_id)
.filter(ub.KoboSyncedBooks.user_id == current_user.id)))
.filter(or_(
ub.BookShelf.date_added > sync_token.books_last_modified,
db.Books.last_modified > sync_token.books_last_modified,
))
.filter(or_(
ub.BookShelf.date_added > sync_token.books_last_modified,
db.Books.last_modified > sync_token.books_last_modified,
db.Books.id.in_(magic_shelf_book_ids) if magic_shelf_book_ids else False
))
.filter(db.Data.format.in_(KOBO_FORMATS))
.filter(calibre_db.common_filters(allow_show_archived=True))
.order_by(db.Books.last_modified)
.order_by(db.Books.id)
.join(ub.BookShelf, db.Books.id == ub.BookShelf.book_id)
.join(ub.Shelf)
.filter(ub.Shelf.user_id == current_user.id)
.filter(ub.Shelf.kobo_sync)
.outerjoin(ub.BookShelf, db.Books.id == ub.BookShelf.book_id)
.outerjoin(ub.Shelf, ub.Shelf.id == ub.BookShelf.shelf)
.filter(or_(
and_(ub.Shelf.user_id == current_user.id, ub.Shelf.kobo_sync == True),
db.Books.id.in_(magic_shelf_book_ids) if magic_shelf_book_ids else False
))
.distinct())
else:
changed_entries = calibre_db.session.query(db.Books,
@@ -297,12 +326,14 @@ def HandleSyncRequest():
log.debug("Kobo Sync: rstate last modified: {}".format(sync_token.reading_state_last_modified))
if only_kobo_shelves:
changed_reading_states = changed_reading_states.join(ub.BookShelf,
ub.KoboReadingState.book_id == ub.BookShelf.book_id)\
.join(ub.Shelf)\
.filter(current_user.id == ub.Shelf.user_id)\
.filter(ub.Shelf.kobo_sync,
ub.KoboReadingState.last_modified > sync_token.reading_state_last_modified)\
changed_reading_states = changed_reading_states.outerjoin(ub.BookShelf,
ub.KoboReadingState.book_id == ub.BookShelf.book_id)\
.outerjoin(ub.Shelf, ub.Shelf.id == ub.BookShelf.shelf)\
.filter(ub.KoboReadingState.last_modified > sync_token.reading_state_last_modified)\
.filter(or_(
and_(current_user.id == ub.Shelf.user_id, ub.Shelf.kobo_sync == True),
ub.KoboReadingState.book_id.in_(magic_shelf_book_ids) if magic_shelf_book_ids else False
))\
.distinct()
else:
changed_reading_states = changed_reading_states.filter(
+1 -1
View File
@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: Calibre-Web Automated v4.0.2\n"
"Report-Msgid-Bugs-To: https://github.com/crocodilestick/Calibre-Web-"
"Automated\n"
"POT-Creation-Date: 2026-01-31 12:15+0100\n"
"POT-Creation-Date: 2026-01-31 13:02+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"