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:
+5
-4
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user