Procházet zdrojové kódy

Another attempt to fix the Jellyfin issue

This time, we simplify the progress updates, aggressively mark tracks as
100 played if they are marked played_to_completion, and implement a hack
for Jellyfin spamming us with progress updates less than a second apart.
Colin Powell před 2 roky
rodič
revize
ca57eabf87

+ 14 - 3
vrobbler/apps/scrobbles/models.py

@@ -12,6 +12,7 @@ from podcasts.models import Episode
 from scrobbles.utils import check_scrobble_for_finish
 from sports.models import SportEvent
 from videos.models import Series, Video
+from vrobbler.apps.profiles.utils import now_user_timezone
 
 logger = logging.getLogger(__name__)
 User = get_user_model()
@@ -146,7 +147,7 @@ class Scrobble(TimeStampedModel):
             playback_ticks = (timezone.now() - self.timestamp).seconds * 1000
 
             if self.played_to_completion:
-                playback_ticks = self.media_obj.run_time_ticks
+                return 100
 
         percent = int((playback_ticks / self.media_obj.run_time_ticks) * 100)
         return percent
@@ -210,17 +211,26 @@ class Scrobble(TimeStampedModel):
             cls.objects.filter(
                 track=track,
                 user_id=user_id,
+                played_to_completion=False,
             )
             .order_by('-modified')
             .first()
         )
-        if scrobble and scrobble.percent_played <= 100:
+        if scrobble:
             logger.debug(
                 f"Found existing scrobble for track {track}, updating",
                 {"scrobble_data": scrobble_data},
             )
             return cls.update(scrobble, scrobble_data)
 
+        if 'jellyfin_status' in scrobble_data.keys():
+            last_scrobble = Scrobble.objects.last()
+            if (
+                scrobble_data['timestamp'] - last_scrobble.timestamp
+            ).seconds <= 1:
+                logger.warning('Jellyfin spammed us with duplicate updates')
+                return last_scrobble
+
         logger.debug(
             f"No existing scrobble for track {track}, creating",
             {"scrobble_data": scrobble_data},
@@ -311,7 +321,6 @@ class Scrobble(TimeStampedModel):
         for key, value in scrobble_data.items():
             setattr(scrobble, key, value)
         scrobble.save()
-        check_scrobble_for_finish(scrobble)
         return scrobble
 
     @classmethod
@@ -334,6 +343,7 @@ class Scrobble(TimeStampedModel):
         check_scrobble_for_finish(self, force_finish)
 
     def pause(self) -> None:
+        print('Trying to pause it')
         if self.is_paused:
             logger.warning("Scrobble already paused")
             return
@@ -346,6 +356,7 @@ class Scrobble(TimeStampedModel):
             self.is_paused = False
             self.in_progress = True
             return self.save(update_fields=["is_paused", "in_progress"])
+        logger.warning("Resume called but in progress or not paused")
 
     def cancel(self) -> None:
         check_scrobble_for_finish(self, force_finish=True)

+ 5 - 15
vrobbler/apps/scrobbles/scrobblers.py

@@ -99,26 +99,15 @@ def create_jellyfin_scrobble_dict(data_dict: dict, user_id: int) -> dict:
     jellyfin_status = "resumed"
     if data_dict.get("IsPaused"):
         jellyfin_status = "paused"
-    if data_dict.get("PlayedToCompletion"):
+    if data_dict.get("NotificationType") == 'PlaybackStop':
         jellyfin_status = "stopped"
 
-    playback_position_ticks = None
-    if data_dict.get("PlaybackPositionTicks"):
-        playback_position_ticks = (
-            data_dict.get("PlaybackPositionTicks") // 10000
-        )
-        if playback_position_ticks <= 0:
-            playback_position_ticks = None
-
-    playback_position = data_dict.get("PlaybackPosition")
-    if playback_position:
-        playback_position = convert_to_seconds(playback_position)
-
     return {
         "user_id": user_id,
         "timestamp": parse(data_dict.get("UtcTimestamp")),
-        "playback_position_ticks": playback_position_ticks,
-        "playback_position": playback_position,
+        "playback_position_ticks": data_dict.get("PlaybackPositionTicks", "")
+        // 10000,
+        "playback_position": data_dict.get("PlaybackPosition", ""),
         "source": data_dict.get("ClientName", "Vrobbler"),
         "source_id": data_dict.get('MediaSourceId'),
         "jellyfin_status": jellyfin_status,
@@ -128,6 +117,7 @@ def create_jellyfin_scrobble_dict(data_dict: dict, user_id: int) -> dict:
 def jellyfin_scrobble_track(
     data_dict: dict, user_id: Optional[int]
 ) -> Optional[Scrobble]:
+
     if not data_dict.get("Provider_musicbrainztrack", None):
         logger.error(
             "No MBrainz Track ID received. This is likely because all metadata is bad, not scrobbling"

+ 0 - 1
vrobbler/apps/scrobbles/utils.py

@@ -77,7 +77,6 @@ def check_scrobble_for_finish(
         scrobble.in_progress = False
         scrobble.is_paused = False
         scrobble.played_to_completion = True
-        scrobble.playback_position_ticks = scrobble.media_obj.run_time_ticks
         scrobble.save(
             update_fields=["in_progress", "is_paused", "played_to_completion"]
         )