sessions / c8292d1c069db38aec5f9a71fc5947dd731fbb6d

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

This commit has no recorded session.

diff

ignore whitespace

commit c8292d1c069db38aec5f9a71fc5947dd731fbb6dAuthor: Colin Powell <colin@unbl.ink>Date:   Tue Jun 9 13:15:57 2026 -0400    [scrobbles] Back fill visibility fielddiff --git a/PROJECT.org b/PROJECT.orgindex 8fbf326..3ed7036 100644--- a/PROJECT.org+++ b/PROJECT.org@@ -88,7 +88,7 @@ fetching and simple saving. *** Metadata sources **** Scraper -* Backlog [0/15] :vrobbler:project:personal:+* Backlog [1/16] :vrobbler:project:personal: ** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :vrobbler:personal:bug:music:scrobbles: :PROPERTIES: :ID:       702462cf-d54b-48c6-8a7c-78b8de751deb@@ -551,6 +551,71 @@ Additionally, users's should have links in their settings to see what scrobbles are either public, shared or private. Probably this could be done with a ?visbility=<> filter on the /scrobbles/ page.          +** DONE [#A] Fix bug with missing default visbility for scrobbles :bug:scrobbles:sharing:+:PROPERTIES:+:ID:       20843992-6453-9a9a-cde6-2c2b6677db23+:END:++*** Description++We can't scrobble anything now because visbility is not null, but has no default+value.++*** Notes+- Note taken on [2026-06-09 Tue 13:14]+  The full stack trace:+  #+begin_src sh+    File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 1430, in create_or_update+        elif "log" in scrobble_data.keys() and scrobble.log:+        ^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 1583, in create+        )++    File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method+        return getattr(self.get_queryset(), name)(*args, **kwargs)+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 658, in create+        obj.save(force_insert=True, using=self.db)+    File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 870, in save+        if self.media_obj:+            ^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django_extensions/db/models.py", line 22, in save+        super().save(**kwargs)+    File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 814, in save+        self.save_base(+    File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 877, in save_base+        updated = self._save_table(+                ^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1020, in _save_table+        results = self._do_insert(+                ^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1061, in _do_insert+        return manager._insert(+            ^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method+        return getattr(self.get_queryset(), name)(*args, **kwargs)+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1805, in _insert+        return query.get_compiler(using=using).execute_sql(returning_fields)+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1822, in execute_sql+        cursor.execute(sql, params)+    File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute+        return self._execute_with_wrappers(+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers+        return executor(sql, params, many, context)+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute+        with self.db.wrap_database_errors:+    File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__+        raise dj_exc_value.with_traceback(traceback) from exc_value+    File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute+        return self.cursor.execute(sql, params)+            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^+    django.db.utils.IntegrityError: null value in column "visibility" of relation "scrobbles_scrobble" violates not-null constraint+    DETAIL:  Failing row contains (373813, 2026-06-09 17:13:38.11355+00, 2026-06-09 17:13:38.113566+00, 2026-06-09 17:13:36+00, 0, f, f, Todoist, 1, null, t, {"title": "Animal chores", "labels": ["chore", "farm"], "todoist..., null, null, null, 68680dbf-f9a9-476c-b1c7-adbd231bbab6, null, null, null, null, , null, Task, null, null, null, America/New_York, null, null, , null, null, , 72, null, null, null, null, null, null, null, null, null, null).+    #+end_src         * Version 49.0 [1/1] ** DONE [#A] Fix broken tests with new sharing and add tests :scrobbles:sharing:tests: :PROPERTIES:diff --git a/vrobbler/apps/scrobbles/importers/lastfm.py b/vrobbler/apps/scrobbles/importers/lastfm.pyindex 842bba3..70c08b5 100644--- a/vrobbler/apps/scrobbles/importers/lastfm.py+++ b/vrobbler/apps/scrobbles/importers/lastfm.py@@ -76,6 +76,7 @@ class LastFM:                 in_progress=False,                 media_type=Scrobble.MediaType.TRACK,                 timezone=tz_timestamp.tzinfo.name,+                visibility="private",             )             # Vrobbler scrobbles on finish, LastFM scrobbles on start             seconds_eariler = timestamp - timedelta(seconds=20)diff --git a/vrobbler/apps/scrobbles/importers/scale.py b/vrobbler/apps/scrobbles/importers/scale.pyindex c8d3aa5..5f4f284 100644--- a/vrobbler/apps/scrobbles/importers/scale.py+++ b/vrobbler/apps/scrobbles/importers/scale.py@@ -111,6 +111,7 @@ def import_scale_csv(file_path, user_id):                 played_to_completion=True,                 in_progress=False,                 media_type=Scrobble.MediaType.TASK,+                visibility="private",             )             new_scrobbles.append(new_scrobble) diff --git a/vrobbler/apps/scrobbles/importers/trail_gpx.py b/vrobbler/apps/scrobbles/importers/trail_gpx.pyindex 56c7197..e1f1408 100644--- a/vrobbler/apps/scrobbles/importers/trail_gpx.py+++ b/vrobbler/apps/scrobbles/importers/trail_gpx.py@@ -305,6 +305,7 @@ def import_trail_gpx(file_path, user_id, original_filename=None):         played_to_completion=True,         in_progress=False,         media_type=Scrobble.MediaType.TRAIL,+        visibility="private",     )      _, ext = os.path.splitext(file_path)diff --git a/vrobbler/apps/scrobbles/importers/tsv.py b/vrobbler/apps/scrobbles/importers/tsv.pyindex 2a722c4..978f52c 100644--- a/vrobbler/apps/scrobbles/importers/tsv.py+++ b/vrobbler/apps/scrobbles/importers/tsv.py@@ -80,6 +80,7 @@ def import_audioscrobbler_tsv_file(file_path, user_id):             in_progress=False,             media_type=Scrobble.MediaType.TRACK,             timezone=timestamp.tzinfo.name,+            visibility="private",         )         existing = Scrobble.objects.filter(             timestamp=timestamp, track=track, user=userdiff --git a/vrobbler/apps/scrobbles/migrations/0095_backfill_null_visibility.py b/vrobbler/apps/scrobbles/migrations/0095_backfill_null_visibility.pynew file mode 100644index 0000000..165291d--- /dev/null+++ b/vrobbler/apps/scrobbles/migrations/0095_backfill_null_visibility.py@@ -0,0 +1,20 @@+from django.db import migrations+++def backfill_null_visibility(apps, schema_editor):+    Scrobble = apps.get_model("scrobbles", "Scrobble")+    Scrobble.objects.filter(visibility__isnull=True).update(visibility="private")+++class Migration(migrations.Migration):++    dependencies = [+        ("scrobbles", "0094_scrobble_share_view_count_alter_scrobble_visibility_and_more"),+    ]++    operations = [+        migrations.RunPython(+            backfill_null_visibility,+            reverse_code=migrations.RunPython.noop,+        ),+    ]diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.pyindex fd65440..985ab5d 100644--- a/vrobbler/apps/scrobbles/models.py+++ b/vrobbler/apps/scrobbles/models.py@@ -1612,6 +1612,8 @@ class Scrobble(TimeStampedModel):         cls,         scrobble_data: dict,     ) -> "Scrobble":+        if "visibility" not in scrobble_data:+            scrobble_data["visibility"] = Visibility.PRIVATE         scrobble = cls.objects.create(**scrobble_data)         if not (             scrobble.media_type == cls.MediaType.GEO_LOCATION