From ca57eabf8796653a3f648507fee3a5b55c3d0375 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 31 Jan 2023 10:28:54 -0500 Subject: [PATCH] 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. --- vrobbler/apps/scrobbles/models.py | 17 ++++++++++++++--- vrobbler/apps/scrobbles/scrobblers.py | 20 +++++--------------- vrobbler/apps/scrobbles/utils.py | 1 - 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.py index 443b2e0..c904277 100644 --- a/vrobbler/apps/scrobbles/models.py +++ b/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) diff --git a/vrobbler/apps/scrobbles/scrobblers.py b/vrobbler/apps/scrobbles/scrobblers.py index 13880d1..396a627 100644 --- a/vrobbler/apps/scrobbles/scrobblers.py +++ b/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" diff --git a/vrobbler/apps/scrobbles/utils.py b/vrobbler/apps/scrobbles/utils.py index 165b382..c7d6498 100644 --- a/vrobbler/apps/scrobbles/utils.py +++ b/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"] )