소스 검색

[tasks] Fix source url generation

Colin Powell 7 달 전
부모
커밋
3c0a75755b

+ 1 - 1
vrobbler/apps/scrobbles/dataclasses.py

@@ -99,7 +99,7 @@ class BoardGameScoreLogData(JSONDataclass):
 @dataclass
 class BoardGameLogData(LongPlayLogData):
     serial_scrobble_id: Optional[int] = None
-    long_play_complete: bool = False
+    long_play_complete: Optional[bool] = None
     players: Optional[list[BoardGameScoreLogData]] = None
     location: Optional[str] = None
     geo_location_id: Optional[int] = None

+ 17 - 3
vrobbler/apps/scrobbles/mixins.py

@@ -114,10 +114,24 @@ class LongPlayScrobblableMixin(ScrobblableMixin):
     def get_longplay_finish_url(self):
         return reverse("scrobbles:longplay-finish", kwargs={"uuid": self.uuid})
 
-    def last_long_play_scrobble_for_user(self, user) -> Optional["Scrobble"]:
+    def first_long_play_scrobble_for_user(self, user) -> Optional["Scrobble"]:
         return (
             get_scrobbles_for_media(self, user)
-            .filter(long_play_complete=False)
-            .order_by("-timestamp")
+            .filter(
+                log__long_play_complete=False,
+                log__serial_scrobble_id__isnull=True,
+            )
+            .order_by("timestamp")
             .first()
         )
+
+    def last_long_play_scrobble_for_user(self, user) -> Optional["Scrobble"]:
+        return (
+            get_scrobbles_for_media(self, user)
+            .filter(
+                log__long_play_complete=False,
+                log__serial_scrobble_id__isnull=False,
+            )
+            .order_by("timestamp")
+            .last()
+        )

+ 6 - 2
vrobbler/apps/scrobbles/utils.py

@@ -48,10 +48,14 @@ def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
         media_query = models.Q(book=media_obj)
     if media_class == "VideoGame":
         media_query = models.Q(video_game=media_obj)
+    if media_class == "Brickset":
+        media_query = models.Q(brickset=media_obj)
+    if media_class == "Task":
+        media_query = models.Q(task=media_obj)
 
     if not media_query:
-        logger.warn("Do not know about media {media_class} 🙍")
-        return []
+        logger.warn(f"Do not know about media {media_class} 🙍")
+        return QuerySet()
     return Scrobble.objects.filter(media_query, user=user)
 
 

+ 31 - 0
vrobbler/apps/tasks/migrations/0002_task_source_task_source_url_pattern.py

@@ -0,0 +1,31 @@
+# Generated by Django 4.2.16 on 2024-09-30 20:46
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("tasks", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="task",
+            name="source",
+            field=models.CharField(blank=True, max_length=255, null=True),
+        ),
+        migrations.AddField(
+            model_name="task",
+            name="source_url_pattern",
+            field=models.CharField(
+                blank=True,
+                choices=[
+                    ("Shortcut", "https://app.shortcut.com/sure/story/{id}"),
+                    ("Todoist", "https://app.todoist.com/app/task/{id}"),
+                ],
+                max_length=255,
+                null=True,
+            ),
+        ),
+    ]

+ 33 - 6
vrobbler/apps/tasks/models.py

@@ -1,30 +1,43 @@
+from dataclasses import dataclass
 from enum import Enum
 from typing import Optional
+
 from django.apps import apps
 from django.db import models
 from django.urls import reverse
 from scrobbles.dataclasses import LongPlayLogData
-from scrobbles.mixins import ScrobblableMixin
+from scrobbles.mixins import LongPlayScrobblableMixin
 
 BNULL = {"blank": True, "null": True}
 
+TASK_SOURCE_URL_PATTERNS = [
+    ("https://app.shortcut.com/sure/story/{id}", "Shortcut"),
+    ("https://app.todoist.com/app/task/{id}", "Todoist"),
+]
+
 
+@dataclass
 class TaskLogData(LongPlayLogData):
-    serial_scrobble_id: Optional[int]
-    long_play_complete: bool = False
+    source_id: Optional[str] = None
+    serial_scrobble_id: Optional[int] = None
+    long_play_complete: Optional[bool] = None
 
 
 class TaskType(Enum):
-    WOODS = "Professional"
-    ROAD = "Amateur"
+    PRO = "Professional"
+    AMATEUR = "Amateur"
 
 
-class Task(ScrobblableMixin):
+class Task(LongPlayScrobblableMixin):
     """Basically a holder for task sources ... Shortcut, JIRA, Todoist, Org-mode
     and any other otherwise generic tasks.
 
     """
 
+    source = models.CharField(max_length=255, **BNULL)
+    source_url_pattern = models.CharField(
+        max_length=255, choices=TASK_SOURCE_URL_PATTERNS, **BNULL
+    )
     description = models.TextField(**BNULL)
 
     def __str__(self):
@@ -37,6 +50,20 @@ class Task(ScrobblableMixin):
     def logdata_cls(self):
         return TaskLogData
 
+    def source_url_for_user(self, user_id):
+        url = str(self.source_url_pattern).replace("{id}", "")
+        scrobble = self.scrobbles(user_id).first()
+        if scrobble.logdata.source_id and self.source_url_pattern:
+            url = str(self.source_url_pattern).format(
+                id=scrobble.logdata.source_id
+            )
+
+        return url
+
+    def subtitle_for_user(self, user_id):
+        scrobble = self.scrobbles(user_id).first()
+        return scrobble.logdata.source_id or ""
+
     @classmethod
     def find_or_create(cls, title: str) -> "Task":
         return cls.objects.filter(title=title).first()