Fix Mopidy resuming messing things up
This commit is contained in:
@ -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")
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
Reference in New Issue
Block a user