sessions / 83a046111bb65c27023b56b6fe76b301b554d944

/home/powellc/src/code.unbl.ink/secstate/vrobbler

This commit has no recorded session.

diff

ignore whitespace

commit 83a046111bb65c27023b56b6fe76b301b554d944Author: Colin Powell <colin@unbl.ink>Date:   Tue Jun 16 09:27:40 2026 -0400    [webpages] Async pushing to archiveboxdiff --git a/AGENTS.md b/AGENTS.mdindex 32d31a9..c71e5ba 100644--- a/AGENTS.md+++ b/AGENTS.md@@ -15,6 +15,8 @@ ro class method should call the utility function. Be sure to check pyproject.toml for project defaults. Specifically for black and isort expectations. +Imports in python files should always be top level if possible.+ All tasks live in the PROJECT.org file and include an org ID that is a uuid to make them unique.  In local development, environment variables for various sensitive values live in a .envrc filediff --git a/PROJECT.org b/PROJECT.orgindex 2e19c50..95989ef 100644--- a/PROJECT.org+++ b/PROJECT.org@@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [0/20] :vrobbler:project:personal:+* Backlog [1/21] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles: :PROPERTIES: :ID:       702462cf-d54b-48c6-8a7c-78b8de751deb@@ -594,6 +594,17 @@ named constants for maintainability.   - ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"=   - ~vrobbler/apps/scrobbles/importers/tsv.py~ (line 55) -- ="S"= completion status +** DONE [#B] Make ArchiveBox push asynchronous :archivebox:async:+:PROPERTIES:+:ID:       17c116a7-5952-db37-e56c-2987c2fc456b+:END:+*** Description++=push_to_archivebox()= runs synchronously during the request. Should be moved to a+Celery task or similar background worker.+    +File: ~vrobbler/apps/webpages/models.py~ (line 133)+ * Version 52.2 [1/1] ** DONE [#A] Fix bug in recomputing long play seconds taking forever :bug:longplay:commands: :PROPERTIES:diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.pyindex b213515..bc22ef0 100644--- a/vrobbler/apps/scrobbles/models.py+++ b/vrobbler/apps/scrobbles/models.py@@ -952,27 +952,6 @@ class Scrobble(TimeStampedModel):         self.share_token_version += 1         self.save(update_fields=["share_token_version"]) -    def push_to_archivebox(self):-        pushable_media = hasattr(self.media_obj, "push_to_archivebox") and callable(-            self.media_obj.push_to_archivebox-        )--        if pushable_media and self.user.profile.archivebox_url:-            try:-                self.media_obj.push_to_archivebox(-                    url=self.user.profile.archivebox_url,-                    username=self.user.profile.archivebox_username,-                    password=self.user.profile.archivebox_password,-                )-            except Exception:-                logger.info(-                    "Failed to push URL to archivebox",-                    extra={-                        "archivebox_url": self.user.profile.archivebox_url,-                        "archivebox_username": self.user.profile.archivebox_username,-                    },-                )-     @property     def logdata(self) -> Optional[logdata.BaseLogData]:         if self.media_obj:diff --git a/vrobbler/apps/scrobbles/scrobblers.py b/vrobbler/apps/scrobbles/scrobblers.pyindex 4758b84..a3b75df 100644--- a/vrobbler/apps/scrobbles/scrobblers.py+++ b/vrobbler/apps/scrobbles/scrobblers.py@@ -32,6 +32,7 @@ from scrobbles.constants import ( ) from scrobbles.models import Scrobble from scrobbles.notifications import ScrobbleNtfyNotification+from scrobbles.tasks import push_scrobble_to_archivebox from scrobbles.utils import (     convert_to_seconds,     extract_domain,@@ -1028,8 +1029,7 @@ def manual_scrobble_webpage(     if action == "stop":         scrobble.stop(force_finish=True)     else:-        # possibly async this?-        scrobble.push_to_archivebox()+        push_scrobble_to_archivebox.delay(scrobble.id)      return scrobble diff --git a/vrobbler/apps/scrobbles/tasks.py b/vrobbler/apps/scrobbles/tasks.pyindex bbc4fe7..5d04bdf 100644--- a/vrobbler/apps/scrobbles/tasks.py+++ b/vrobbler/apps/scrobbles/tasks.py@@ -252,6 +252,25 @@ def update_charts_for_timestamp(user_id, year, month, day, week):         logger.error(f"[charts] Failed to update charts: {e}")  +@shared_task+def push_scrobble_to_archivebox(scrobble_id):+    from scrobbles.models import Scrobble++    scrobble = Scrobble.objects.filter(id=scrobble_id).first()+    if not scrobble:+        logger.warning(+            "Scrobble %s not found for archivebox push", scrobble_id+        )+        return+    webpage = scrobble.web_page+    if not webpage:+        logger.warning(+            "Scrobble %s has no web_page for archivebox push", scrobble_id+        )+        return+    webpage.push_to_archivebox(scrobble.user)++ # ── Crontab replacements ──────────────────────────────────────────────────────  diff --git a/vrobbler/apps/webpages/models.py b/vrobbler/apps/webpages/models.pyindex ab55f1f..3b6a8e8 100644--- a/vrobbler/apps/webpages/models.py+++ b/vrobbler/apps/webpages/models.py@@ -17,6 +17,7 @@ from htmldate import find_date from imagekit.models import ImageSpecField from imagekit.processors import ResizeToFit from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin+from scrobbles.tasks import push_scrobble_to_archivebox from taggit.managers import TaggableManager  logger = logging.getLogger(__name__)@@ -130,8 +131,7 @@ class WebPage(ScrobblableMixin):             },         )         scrobble = Scrobble.create_or_update(self, user_id, scrobble_data)-        # TODO Possibly make this async?-        scrobble.push_to_archivebox()+        push_scrobble_to_archivebox.delay(scrobble.id)         return scrobble      def scrobbles(self, user):@@ -183,7 +183,13 @@ class WebPage(ScrobblableMixin):         if save:             self.save(update_fields=["date"]) -    def push_to_archivebox(self, url: str, username: str, password: str):+    def push_to_archivebox(self, user):+        profile = user.profile+        url = profile.archivebox_url+        if not url:+            return+        username = profile.archivebox_username+        password = profile.archivebox_password         login_url = requests.compat.urljoin(url, "admin/login/")         session = requests.Session()         response = session.get(login_url)