From 8646fd68816a2dde175567367dc887cffa1bbe1d Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 25 Jul 2023 15:22:23 -0400 Subject: [PATCH] Add ScrobbledPage model to start book transition --- vrobbler/apps/scrobbles/admin.py | 11 ++++ .../commands/migrate_page_to_scrobbledpage.py | 63 +++++++++++++++++++ .../migrations/0043_scrobbledpage.py | 63 +++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 vrobbler/apps/scrobbles/management/commands/migrate_page_to_scrobbledpage.py create mode 100644 vrobbler/apps/scrobbles/migrations/0043_scrobbledpage.py diff --git a/vrobbler/apps/scrobbles/admin.py b/vrobbler/apps/scrobbles/admin.py index 8651b8d..f9bab52 100644 --- a/vrobbler/apps/scrobbles/admin.py +++ b/vrobbler/apps/scrobbles/admin.py @@ -7,6 +7,7 @@ from scrobbles.models import ( LastFmImport, RetroarchImport, Scrobble, + ScrobbledPage, ) from scrobbles.mixins import Genre @@ -119,3 +120,13 @@ class ScrobbleAdmin(admin.ModelAdmin): def playback_percent(self, obj): return obj.percent_played + + +@admin.register(ScrobbledPage) +class ScrobbledPageAdmin(admin.ModelAdmin): + list_display = ( + "number", + "scrobble", + "notes", + ) + raw_id_fields = ("scrobble",) diff --git a/vrobbler/apps/scrobbles/management/commands/migrate_page_to_scrobbledpage.py b/vrobbler/apps/scrobbles/management/commands/migrate_page_to_scrobbledpage.py new file mode 100644 index 0000000..c171774 --- /dev/null +++ b/vrobbler/apps/scrobbles/management/commands/migrate_page_to_scrobbledpage.py @@ -0,0 +1,63 @@ +from books.models import Book +from django.core.management.base import BaseCommand, no_translations +from scrobbles.models import ScrobbledPage + + +class Command(BaseCommand): + def add_arguments(self, parser): + parser.add_argument( + "--commit", + action="store_true", + help="Actually populate data", + ) + + def handle(self, *args, **options): + dry_run = True + if options["commit"]: + dry_run = False + + pages_to_create = [] + associated_scrobble = None + last_scrobble = None + for book in Book.objects.all(): + for page in book.page_set.all().order_by("number"): + notes = "" + last_scrobble = associated_scrobble + if ( + not associated_scrobble + or page.number > associated_scrobble.book_pages_read + ): + associated_scrobble = page.user.scrobble_set.filter( + book=page.book, + timestamp__gte=page.start_time, + timestamp__lte=page.end_time, + ).first() + + if ( + last_scrobble + and not associated_scrobble + and page.number > last_scrobble.book_pages_read + ): + associated_scrobble = last_scrobble + notes = f"Extrapolated reading from scrobble {associated_scrobble.id}" + + pages_to_create.append( + ScrobbledPage( + scrobble=associated_scrobble, + number=page.number, + start_time=page.start_time, + end_time=page.end_time, + duration_seconds=page.duration_seconds, + notes=notes, + ) + ) + + pages_to_move_len = len(pages_to_create) + if dry_run: + print( + f"Found {pages_to_move_len} to migrate. Use --commit to move them" + ) + return + + ScrobbledPage.objects.bulk_create(pages_to_create) + print(f"Migrated {pages_to_move_len} generic pages to scrobbled pages") diff --git a/vrobbler/apps/scrobbles/migrations/0043_scrobbledpage.py b/vrobbler/apps/scrobbles/migrations/0043_scrobbledpage.py new file mode 100644 index 0000000..c19a798 --- /dev/null +++ b/vrobbler/apps/scrobbles/migrations/0043_scrobbledpage.py @@ -0,0 +1,63 @@ +# Generated by Django 4.1.7 on 2023-07-16 05:23 + +from django.db import migrations, models +import django.db.models.deletion +import django_extensions.db.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ("scrobbles", "0042_scrobble_videogame_screenshot"), + ] + + operations = [ + migrations.CreateModel( + name="ScrobbledPage", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + django_extensions.db.fields.CreationDateTimeField( + auto_now_add=True, verbose_name="created" + ), + ), + ( + "modified", + django_extensions.db.fields.ModificationDateTimeField( + auto_now=True, verbose_name="modified" + ), + ), + ("number", models.IntegerField()), + ("start_time", models.DateTimeField(blank=True, null=True)), + ("end_time", models.DateTimeField(blank=True, null=True)), + ( + "duration_seconds", + models.IntegerField(blank=True, null=True), + ), + ( + "notes", + models.CharField(blank=True, max_length=255, null=True), + ), + ( + "scrobble", + models.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + to="scrobbles.scrobble", + ), + ), + ], + options={ + "get_latest_by": "modified", + "abstract": False, + }, + ), + ]