Compare commits

...

6 Commits
32 ... 33

7 changed files with 35 additions and 11 deletions

View File

@ -92,7 +92,7 @@ fetching and simple saving.
:LOGBOOK:
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
:END:
* Backlog [2/26]
* Backlog [1/27]
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :vrobbler:personal:bug:music:scrobbles:
** TODO [#C] Move to using more robust mopidy-webhooks pacakge form pypi :utility:improvement:
:PROPERTIES:
@ -479,6 +479,22 @@ https://life.lab.unbl.ink/scrobble/e39779c8-62a5-46a6-bdef-fb7662810dc6/start/
- Note taken on [2025-09-30 Tue 09:33]
This may have already been resolved ... need to just confirm it.
** TODO [#A] Find page numbers for comic books from ComicVine :vrobbler:feature:books:personal:project:
* Version 33.0 [3/3]
** DONE [#A] Fix bug where scrobble is_stale only uses seconds not total_seconds :vrobbler:bug:scrobbles:personal:project:
:PROPERTIES:
:ID: 7f6070ac-4f67-011d-ebd5-f3dc47da46ed
:END:
** DONE [#B] Fix duplicatged Read next issue for Comic books :vrobbler:bug:books:personal:project:
:PROPERTIES:
:ID: 97943040-1f03-b0b7-b0aa-123a783e4f7b
:END:
** DONE [#A] Add API authentication to BGG calls :vrobbler:bug:boardgames:personal:project:
:PROPERTIES:
:ID: 4955cc34-0882-50db-92f7-f36a95bf57a4
:END:
<2025-10-28 Tue>
* Version 32.0 [2/2]
** DONE [#B] Save path to reading source on book scrobbles and show it on the detail page :vrobbler:feature:books:personal:project:
:PROPERTIES:
:ID: f1ef3945-e6e4-66c1-b72e-3cede7a0f84a

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Optional
import requests
from bs4 import BeautifulSoup
from django.contrib.auth import get_user_model
from django.conf import settings
User = get_user_model()
if TYPE_CHECKING:
@ -17,6 +18,8 @@ SEARCH_ID_URL = (
"https://boardgamegeek.com/xmlapi/search?search={query}&exact=1"
)
GAME_ID_URL = "https://boardgamegeek.com/xmlapi/boardgame/{id}"
BGG_ACCESS_TOKEN = getattr(settings, "BGG_ACCESS_TOKEN", "")
BASE_HEADERS = {"User-Agent": "Vrobbler 31.0", "Authorization": f"Bearer {BGG_ACCESS_TOKEN}"}
def take_first(thing: Optional[list]) -> str:
@ -37,10 +40,9 @@ def take_first(thing: Optional[list]) -> str:
def lookup_boardgame_id_from_bgg(title: str) -> Optional[int]:
soup = None
headers = {"User-Agent": "Vrobbler 0.11.12"}
game_id = None
url = SEARCH_ID_URL.format(query=title)
r = requests.get(url, headers=headers)
r = requests.get(url, headers=BASE_HEADERS)
if r.status_code == 200:
soup = BeautifulSoup(r.text, "xml")
@ -57,7 +59,6 @@ def lookup_boardgame_id_from_bgg(title: str) -> Optional[int]:
def lookup_boardgame_from_bgg(lookup_id: str) -> dict:
soup = None
game_dict = {}
headers = {"User-Agent": "Vrobbler 0.11.12"}
title = ""
bgg_id = None
@ -73,7 +74,7 @@ def lookup_boardgame_from_bgg(lookup_id: str) -> dict:
bgg_id = lookup_boardgame_id_from_bgg(title)
url = GAME_ID_URL.format(id=bgg_id)
r = requests.get(url, headers=headers)
r = requests.get(url, headers=BASE_HEADERS)
if r.status_code == 200:
soup = BeautifulSoup(r.text, "xml")
@ -109,7 +110,8 @@ def push_scrobble_to_bgg(scrobble: "Scrobble", user: User) -> Optional[bool]:
login_payload = {
"credentials": {"username": bgg_username, "password": bgg_password}
}
headers = {"content-type": "application/json"}
headers = BASE_HEADERS
headers["content-type"] = "application/json"
# TODO Look up past plays for scrobble.media_obj.bggeek_id, and make sure we haven't scrobbled this before

View File

@ -822,7 +822,7 @@ class Scrobble(TimeStampedModel):
"""
is_stale = False
now = timezone.now()
seconds_since_last_update = (now - self.modified).seconds
seconds_since_last_update = (now - self.modified).total_seconds()
if seconds_since_last_update >= self.media_obj.SECONDS_TO_STALE:
is_stale = True
return is_stale

View File

@ -317,7 +317,10 @@ def manual_scrobble_book(
if action == "stop":
if url:
scrobble.log["resume_url"] = next_url_if_exists(url)
if isinstance(scrobble.log, "BookLogData"):
scrobble.log.resume_url = next_url_if_exists(url)
else:
scrobble.log["resume_url"] = next_url_if_exists(url)
scrobble.save(update_fields=["log"])
scrobble.stop(force_finish=True)

View File

@ -394,7 +394,10 @@ def get_daily_calories_for_user_by_day(user_id: int, date: date| str) -> int:
if isinstance(date, str):
date = pendulum.parse(date)
qs = base_scrobble_qs(user_id).filter(day=date)
try:
qs = base_scrobble_qs(user_id).filter(day=date)
except AttibuteError as e:
logger.warning(f"Can't generate calorie total: {e}")
agg = qs.aggregate(total_calories=models.Sum("calories_int"))
return agg["total_calories"] or 0

View File

@ -68,6 +68,7 @@ LASTFM_SECRET_KEY = os.getenv("VROBBLER_LASTFM_SECRET_KEY")
IGDB_CLIENT_ID = os.getenv("VROBBLER_IGDB_CLIENT_ID")
IGDB_CLIENT_SECRET = os.getenv("VROBBLER_IGDB_CLIENT_SECRET")
COMICVINE_API_KEY = os.getenv("VROBBLER_COMICVINE_API_KEY")
BGG_ACCESS_TOKEN = os.getenv("VROBBLER_BGG_ACCESS_TOKEN", "")
GEOLOC_ACCURACY = os.getenv("VROBBLER_GEOLOC_ACCURACY", 3)
GEOLOC_PROXIMITY = os.getenv("VROBBLER_GEOLOC_PROXIMITY", "0.0001")
POINTS_FOR_MOVEMENT_HISTORY = os.getenv(

View File

@ -26,9 +26,8 @@
</div>
</div>
<div class="row">
<p><a href="{{s.logdata.restart_url}}">Read again</a></p>
{% if object.readcomics_url %}
<p><a href="{{object.readcomics_url}}">Read next issue</a></p>
<p><a href="{{object.readcomics_url}}">Read again</a></p>
{% endif %}
{% if object.next_readcomics_url %}
<p><a href="{{object.next_readcomics_url}}">Read next issue</a></p>