1
0
mirror of https://github.com/janeczku/calibre-web synced 2026-05-08 14:32:13 +00:00

fix(opds): atom:updated reflects last modification, not date added

Books.atom_timestamp returned Books.timestamp (date added), which is
set at import and never changes. OPDS clients use atom:updated to
decide whether a book has changed on the server, so cover swaps,
metadata edits, and any other post-import change were invisible to
sync clients; they would keep serving the stale cover and title
until a manual refresh.

Atom RFC 4287 defines updated as "the most recent instant in time
when an entry or feed was modified", and Calibre already tracks that
field as last_modified, bumping it on every metadata and cover edit.
Switching the property to return last_modified (with a fallback to
timestamp when last_modified is NULL) aligns Calibre-Web's behaviour
with the Atom contract.

This change only affects the OPDS feed's atom:updated element. Kobo
sync uses its own last_modified comparison path, so it is unaffected.
This commit is contained in:
haraldpdl
2026-04-19 10:51:45 +02:00
parent fca580505c
commit ab17992ebb
+10 -1
View File
@@ -449,7 +449,16 @@ class Books(Base):
@property
def atom_timestamp(self):
return self.timestamp.strftime('%Y-%m-%dT%H:%M:%S+00:00') or ''
# OPDS atom:updated is defined as "the most recent instant in time
# when the entry was modified". Books.timestamp is the date added and
# never changes after import, so metadata and cover edits were
# invisible to OPDS sync clients. Use last_modified, which Calibre
# updates on every metadata or cover change; fall back to timestamp
# only if last_modified happens to be missing.
t = self.last_modified or self.timestamp
if t is None:
return ''
return t.strftime('%Y-%m-%dT%H:%M:%S+00:00') or ''
class CustomColumns(Base):