Fix Mopidy resuming messing things up

This commit is contained in:
2023-01-16 16:12:01 -05:00
parent 0634b94368
commit 6cdcf4ff6f
4 changed files with 40 additions and 33 deletions

View File

@ -78,8 +78,7 @@ class Scrobble(TimeStampedModel):
def __str__(self):
return f"Scrobble of {self.media_obj} {self.timestamp.year}-{self.timestamp.month}"
@property
def resumable(self):
def resumable(self, playback_ticks):
"""Check if a scrobble is not finished or beyond the configured resume limit.
The idea here is to check whether a scrobble should be resumed, or a new
@ -98,6 +97,10 @@ class Scrobble(TimeStampedModel):
beyond_resume_limit = False
now = timezone.now()
if self.playback_position_ticks == playback_ticks:
# shortcircut in the case where we've resumed a track at the same playback ticks
return True
if self.video:
diff = timedelta(seconds=Video.RESUME_LIMIT)
percent_for_completion = Video.COMPLETION_PERCENT
@ -140,7 +143,9 @@ class Scrobble(TimeStampedModel):
.order_by('-modified')
.first()
)
if scrobble and scrobble.resumable:
if scrobble and scrobble.resumable(
scrobble_data['playback_position_ticks']
):
logger.info(
f"Found existing scrobble for video {video}, updating",
{"scrobble_data": scrobble_data},
@ -169,7 +174,9 @@ class Scrobble(TimeStampedModel):
.order_by('-modified')
.first()
)
if scrobble and scrobble.resumable:
if scrobble and scrobble.resumable(
scrobble_data['playback_position_ticks']
):
logger.debug(
f"Found existing scrobble for track {track}, updating",
{"scrobble_data": scrobble_data},
@ -195,7 +202,9 @@ class Scrobble(TimeStampedModel):
.order_by('-modified')
.first()
)
if scrobble and scrobble.resumable:
if scrobble and scrobble.resumable(
scrobble_data['playback_position_ticks']
):
logger.debug(
f"Found existing scrobble for podcast {episode}, updating",
{"scrobble_data": scrobble_data},
@ -220,7 +229,9 @@ class Scrobble(TimeStampedModel):
.order_by('-modified')
.first()
)
if scrobble and scrobble.resumable:
if scrobble and scrobble.resumable(
scrobble_data['playback_position_ticks']
):
logger.debug(
f"Found existing scrobble for sport event {event}, updating",
{"scrobble_data": scrobble_data},
@ -236,30 +247,25 @@ class Scrobble(TimeStampedModel):
return cls.create(scrobble_data)
@classmethod
def update(cls, scrobble: "Scrobble", scrobble_data: dict):
def update(cls, scrobble: "Scrobble", scrobble_data: dict) -> "Scrobble":
# Status is a field we get from Mopidy, which refuses to poll us
scrobble_status = scrobble_data.pop('mopidy_status', None)
if not scrobble_status:
scrobble_status = scrobble_data.pop('jellyfin_status', None)
if not scrobble_status:
logger.warning(
f"No status update found in message, not scrobbling"
)
return
scrobble_status = 'resumed'
logger.debug(f"Scrobbling to {scrobble} with status {scrobble_status}")
scrobble.update_ticks(scrobble_data)
# On stop, stop progress and send it to the check for completion
if scrobble_status == "stopped":
return scrobble.stop()
scrobble.stop()
# On pause, set is_paused and stop scrobbling
if scrobble_status == "paused":
return scrobble.pause()
scrobble.pause()
if scrobble_status == "resumed":
return scrobble.resume()
scrobble.resume()
for key, value in scrobble_data.items():
setattr(scrobble, key, value)
@ -287,7 +293,7 @@ class Scrobble(TimeStampedModel):
check_scrobble_for_finish(self)
def pause(self) -> None:
if self.is_paused:
if self.is_paused and not self.played_to_completion:
logger.warning("Scrobble already paused")
return
self.is_paused = True
@ -295,10 +301,15 @@ class Scrobble(TimeStampedModel):
check_scrobble_for_finish(self)
def resume(self) -> None:
if self.is_paused or not self.in_progress:
if self.is_paused or not self.played_to_completion:
self.is_paused = False
self.in_progress = True
return self.save(update_fields=["is_paused", "in_progress"])
return self.save(
update_fields=[
"is_paused",
"in_progress",
]
)
def update_ticks(self, data) -> None:
self.playback_position_ticks = data.get("playback_position_ticks")

View File

@ -86,15 +86,12 @@ def mopidy_scrobble_track(
"mopidy_status": data_dict.get("status"),
}
scrobble = None
# Jellyfin MB ids suck, so always overwrite with Mopidy if they're offering
track.musicbrainz_id = data_dict.get("musicbrainz_track_id")
track.save()
scrobble = Scrobble.create_or_update_for_track(track, user_id, mopidy_data)
if track:
# Jellyfin MB ids suck, so always overwrite with Mopidy if they're offering
track.musicbrainz_id = data_dict.get("musicbrainz_track_id")
track.save()
scrobble = Scrobble.create_or_update_for_track(
track, user_id, mopidy_data
)
return scrobble

View File

@ -76,6 +76,9 @@ def check_scrobble_for_finish(scrobble: "Scrobble") -> None:
settings, "PODCAST_COMPLETION_PERCENT", 25
)
if scrobble.percent_played >= completion_percent:
logger.debug(
f"Beyond completion percent {completion_percent}, finishing scrobble"
)
scrobble.in_progress = False
scrobble.is_paused = False
scrobble.played_to_completion = True

View File

@ -148,9 +148,7 @@ def jellyfin_websocket(request):
if not scrobble:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{'scrobble_id': scrobble.id}, status=status.HTTP_201_CREATED
)
return Response({'scrobble_id': scrobble.id}, status=status.HTTP_200_OK)
@csrf_exempt
@ -171,6 +169,4 @@ def mopidy_websocket(request):
if not scrobble:
return Response({}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{'scrobble_id': scrobble.id}, status=status.HTTP_201_CREATED
)
return Response({'scrobble_id': scrobble.id}, status=status.HTTP_200_OK)