[books] Fix resume reading link and page calc
All checks were successful
build & deploy / test (push) Successful in 1m44s
build & deploy / build-and-deploy (push) Successful in 33s

This commit is contained in:
2026-05-19 21:03:42 -04:00
parent af8b1d4f8a
commit 217e2443e2
4 changed files with 63 additions and 34 deletions

View File

@ -208,6 +208,10 @@ class Book(LongPlayScrobblableMixin):
def get_absolute_url(self):
return reverse("books:book_detail", kwargs={"slug": self.uuid})
@property
def resume_start_url(self):
return reverse("scrobbles:start", kwargs={"uuid": self.uuid}) + "?resume=1"
@classmethod
def get_from_comicvine(
cls, title: str, overwrite: bool = False, force_new: bool = False

View File

@ -593,6 +593,17 @@ class Scrobble(TimeStampedModel):
self.stop_timestamp - self.timestamp
).seconds
if (
self.log
and isinstance(self.log, dict)
and self.log.get("page_start") is not None
and self.log.get("page_end") is not None
and "pages_read" not in self.log
):
self.log["pages_read"] = (
self.log["page_end"] - self.log["page_start"] + 1
)
return super(Scrobble, self).save(*args, **kwargs)
def get_absolute_url(self):
@ -1452,38 +1463,38 @@ class Scrobble(TimeStampedModel):
return False
def calculate_reading_stats(self, commit=True):
# --- Sort safely by numeric page_number ---
def safe_page_number(entry):
try:
return int(getattr("page_number", entry), 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 page_data:
# --- Sort safely by numeric page_number ---
def safe_page_number(entry):
try:
return int(getattr("page_number", entry), 0)
except (ValueError, TypeError):
return float("inf")
if isinstance(page_data, dict):
logger.warning("Page data is dict, migrate koreader data")
return
if isinstance(page_data, dict):
logger.warning("Page data is dict, migrate koreader data")
return
page_data.sort(key=safe_page_number)
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
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 valid_pages:
self.log["page_start"] = min(valid_pages)
self.log["page_end"] = max(valid_pages)
self.log["pages_read"] = len(set(valid_pages))
else:
page_start = self.log.get("page_start")
page_end = self.log.get("page_end")
if page_start is not None and page_end is not None:
self.log["pages_read"] = page_end - page_start + 1
if commit:
self.save(update_fields=["log"])
if commit and "pages_read" in self.log:
self.save(update_fields=["log"])

View File

@ -768,7 +768,25 @@ def scrobble_start(request, uuid):
scrobble = None
user_id = request.user.id
if media_obj:
media_obj.scrobble_for_user(user_id)
log_data = None
if (
request.GET.get("resume")
and media_obj.__class__.__name__ == Scrobble.MediaType.BOOK
):
last_scrobble = (
Scrobble.objects.filter(
book=media_obj,
user_id=user_id,
)
.filter(Q(long_play_complete=False) | Q(long_play_complete__isnull=True))
.filter(log__page_end__isnull=False)
.order_by("-timestamp")
.first()
)
if last_scrobble and last_scrobble.logdata:
next_page = last_scrobble.logdata.page_end + 1
log_data = {"page_start": next_page}
media_obj.scrobble_for_user(user_id, log=log_data)
if scrobble:
messages.add_message(

View File

@ -35,11 +35,7 @@
<p>{{scrobbles.count}} scrobbles</p>
{% for s in scrobbles %}
{% if forloop.first %}
<p><a href="{{s.logdata.resume_url}}">Resume reading</a></p>
{% endif %}
{% endfor %}
<p><a href="{{object.resume_start_url}}">Resume reading</a></p>
</div>
{% if charts %}
<div class="row">