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:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user