|
|
@@ -1181,6 +1181,7 @@ class Scrobble(TimeStampedModel):
|
|
|
for page in page_list:
|
|
|
if not page.get("end_ts", None):
|
|
|
page["end_ts"] = int(timezone.now().timestamp())
|
|
|
+ page["duration"] = page["end_ts"] - page.get("start_ts")
|
|
|
|
|
|
page_list.append(
|
|
|
BookPageLogData(
|
|
|
@@ -1198,7 +1199,7 @@ class Scrobble(TimeStampedModel):
|
|
|
scrobble_data.pop("playback_status")
|
|
|
|
|
|
if read_log_page:
|
|
|
- scrobble_data["log"] = BookLogData(page_data=BookPageLogData(page_number=read_log_page, start_ts=int(timezone.now().timestamp())))
|
|
|
+ scrobble_data["log"] = BookLogData(page_data=[BookPageLogData(page_number=read_log_page, start_ts=int(timezone.now().timestamp()))])
|
|
|
|
|
|
logger.info(
|
|
|
f"[scrobbling] creating new scrobble",
|
|
|
@@ -1392,6 +1393,9 @@ class Scrobble(TimeStampedModel):
|
|
|
if class_name in LONG_PLAY_MEDIA.values():
|
|
|
self.finish_long_play()
|
|
|
|
|
|
+ if class_name == "Book":
|
|
|
+ self.calculate_reading_stats()
|
|
|
+
|
|
|
logger.info(
|
|
|
f"[scrobbling] stopped",
|
|
|
extra={
|
|
|
@@ -1487,3 +1491,40 @@ class Scrobble(TimeStampedModel):
|
|
|
beyond_completion = False
|
|
|
|
|
|
return beyond_completion
|
|
|
+
|
|
|
+ def calculate_reading_stats(self, commit=True):
|
|
|
+ # --- Sort safely by numeric page_number ---
|
|
|
+ def safe_page_number(entry):
|
|
|
+ try:
|
|
|
+ return int(entry.get("page_number", 0))
|
|
|
+ except (ValueError, TypeError):
|
|
|
+ return float("inf") # push invalid entries to the end
|
|
|
+
|
|
|
+ page_data = self.log.get("page_data")
|
|
|
+
|
|
|
+ if not page_data:
|
|
|
+ logger.warning("No page data found to calculate")
|
|
|
+ return
|
|
|
+
|
|
|
+ if isinstance(page_data, dict):
|
|
|
+ logger.warning("Page data is dict, migrate koreader data")
|
|
|
+ return
|
|
|
+
|
|
|
+ page_data.sort(key=safe_page_number)
|
|
|
+
|
|
|
+ # --- Extract valid numeric page numbers ---
|
|
|
+ valid_pages = []
|
|
|
+ for page in page_data:
|
|
|
+ try:
|
|
|
+ valid_pages.append(int(page["page_number"]))
|
|
|
+ except (ValueError, TypeError):
|
|
|
+ continue
|
|
|
+
|
|
|
+ # --- Compute stats ---
|
|
|
+ if valid_pages:
|
|
|
+ self.log["page_start"] = min(valid_pages)
|
|
|
+ self.log["page_end"] = max(valid_pages)
|
|
|
+ self.log["pages_read"] = len(set(valid_pages))
|
|
|
+
|
|
|
+ if commit:
|
|
|
+ self.save(update_fields=["log"])
|