[scrobbles] Radically simplify stopping ... may need to roll this back
This commit is contained in:
@ -404,7 +404,7 @@ class Album(TimeStampedModel):
|
|||||||
|
|
||||||
|
|
||||||
class Track(ScrobblableMixin):
|
class Track(ScrobblableMixin):
|
||||||
COMPLETION_PERCENT = getattr(settings, "MUSIC_COMPLETION_PERCENT", 95)
|
COMPLETION_PERCENT = getattr(settings, "MUSIC_COMPLETION_PERCENT", 99)
|
||||||
|
|
||||||
class Opinion(models.IntegerChoices):
|
class Opinion(models.IntegerChoices):
|
||||||
DOWN = -1, "Thumbs down"
|
DOWN = -1, "Thumbs down"
|
||||||
|
|||||||
@ -32,10 +32,7 @@ from profiles.utils import (
|
|||||||
)
|
)
|
||||||
from scrobbles.constants import LONG_PLAY_MEDIA
|
from scrobbles.constants import LONG_PLAY_MEDIA
|
||||||
from scrobbles.stats import build_charts
|
from scrobbles.stats import build_charts
|
||||||
from scrobbles.utils import (
|
from scrobbles.utils import media_class_to_foreign_key
|
||||||
check_scrobble_for_finish,
|
|
||||||
media_class_to_foreign_key,
|
|
||||||
)
|
|
||||||
from sports.models import SportEvent
|
from sports.models import SportEvent
|
||||||
from videogames import retroarch
|
from videogames import retroarch
|
||||||
from videogames.models import VideoGame
|
from videogames.models import VideoGame
|
||||||
@ -961,46 +958,60 @@ class Scrobble(TimeStampedModel):
|
|||||||
return [s.geo_location for s in past_scrobbles]
|
return [s.geo_location for s in past_scrobbles]
|
||||||
|
|
||||||
def update(self, scrobble_data: dict) -> "Scrobble":
|
def update(self, scrobble_data: dict) -> "Scrobble":
|
||||||
logger.info(
|
|
||||||
"[scrobbling] update",
|
|
||||||
extra={
|
|
||||||
"scrobble_id": self.id,
|
|
||||||
"scrobble_data": scrobble_data,
|
|
||||||
"media_type": self.media_type,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
# Status is a field we get from Mopidy, which refuses to poll us
|
# Status is a field we get from Mopidy, which refuses to poll us
|
||||||
scrobble_status = scrobble_data.pop("mopidy_status", None)
|
scrobble_status = scrobble_data.pop("mopidy_status", None)
|
||||||
if not scrobble_status:
|
if not scrobble_status:
|
||||||
scrobble_status = scrobble_data.pop("jellyfin_status", None)
|
scrobble_status = scrobble_data.pop("jellyfin_status", None)
|
||||||
|
|
||||||
if self.percent_played < 100:
|
logger.info(
|
||||||
# Only worry about ticks if we haven't gotten to the end
|
"[scrobbling] update called",
|
||||||
self.update_ticks(scrobble_data)
|
extra={
|
||||||
|
"scrobble_id": self.id,
|
||||||
|
"scrobble_data": scrobble_data,
|
||||||
|
"media_type": self.media_type,
|
||||||
|
"scrobble_status": scrobble_status,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# This is really expensive on the DB ... do we need to track this?
|
||||||
|
# if self.percent_played < 100:
|
||||||
|
# # Only worry about ticks if we haven't gotten to the end
|
||||||
|
# self.update_ticks(scrobble_data)
|
||||||
|
|
||||||
|
if self.beyond_completion_percent:
|
||||||
|
scrobble_status = "stopped"
|
||||||
|
|
||||||
# On stop, stop progress and send it to the check for completion
|
|
||||||
if scrobble_status == "stopped":
|
if scrobble_status == "stopped":
|
||||||
self.stop()
|
self.stop()
|
||||||
# On pause, set is_paused and stop scrobbling
|
|
||||||
if scrobble_status == "paused":
|
if scrobble_status == "paused":
|
||||||
self.pause()
|
self.pause()
|
||||||
if scrobble_status == "resumed":
|
if scrobble_status == "resumed":
|
||||||
self.resume()
|
self.resume()
|
||||||
|
|
||||||
check_scrobble_for_finish(self)
|
|
||||||
|
|
||||||
if scrobble_status != "resumed":
|
if scrobble_status != "resumed":
|
||||||
scrobble_data["stop_timestamp"] = (
|
scrobble_data["stop_timestamp"] = (
|
||||||
scrobble_data.pop("timestamp", None) or timezone.now()
|
scrobble_data.pop("timestamp", None) or timezone.now()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# timestamp is should be more-or-less immutable
|
||||||
scrobble_data.pop("timestamp", None)
|
scrobble_data.pop("timestamp", None)
|
||||||
|
|
||||||
update_fields = []
|
update_fields = []
|
||||||
for key, value in scrobble_data.items():
|
for key, value in scrobble_data.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
update_fields.append(key)
|
update_fields.append(key)
|
||||||
self.save(update_fields=update_fields)
|
self.save(update_fields=update_fields)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"[scrobbling] update finished",
|
||||||
|
extra={
|
||||||
|
"scrobble_id": self.id,
|
||||||
|
"scrobble_data": scrobble_data,
|
||||||
|
"scrobble_status": scrobble_status,
|
||||||
|
"media_type": self.media_type,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -1016,9 +1027,9 @@ class Scrobble(TimeStampedModel):
|
|||||||
|
|
||||||
def stop(self, force_finish=False) -> None:
|
def stop(self, force_finish=False) -> None:
|
||||||
self.stop_timestamp = timezone.now()
|
self.stop_timestamp = timezone.now()
|
||||||
if force_finish:
|
self.played_to_completion = True
|
||||||
self.played_to_completion = True
|
|
||||||
self.in_progress = False
|
self.in_progress = False
|
||||||
|
|
||||||
if not self.playback_position_seconds:
|
if not self.playback_position_seconds:
|
||||||
self.playback_position_seconds = int(
|
self.playback_position_seconds = int(
|
||||||
(self.stop_timestamp - self.timestamp).total_seconds()
|
(self.stop_timestamp - self.timestamp).total_seconds()
|
||||||
@ -1110,3 +1121,25 @@ class Scrobble(TimeStampedModel):
|
|||||||
"scrobble_id": self.id,
|
"scrobble_id": self.id,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def beyond_completion_percent(self) -> bool:
|
||||||
|
"""Returns true if our media is beyond our completion percent, unless
|
||||||
|
our type is geolocation in which case we always return false
|
||||||
|
"""
|
||||||
|
beyond_completion = (
|
||||||
|
self.percent_played >= self.media_obj.COMPLETION_PERCENT
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.media_type == "GeoLocation":
|
||||||
|
logger.info(
|
||||||
|
f"[scrobbling] locations are ONLY completed when new one is created",
|
||||||
|
extra={
|
||||||
|
"scrobble_id": self.id,
|
||||||
|
"media_type": self.media_type,
|
||||||
|
"beyond_completion": beyond_completion,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
beyond_completion = False
|
||||||
|
|
||||||
|
return beyond_completion
|
||||||
|
|||||||
@ -88,54 +88,6 @@ def parse_mopidy_uri(uri: str) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def check_scrobble_for_finish(
|
|
||||||
scrobble: "Scrobble", force_to_100=False, force_finish=False
|
|
||||||
) -> None:
|
|
||||||
completion_percent = scrobble.media_obj.COMPLETION_PERCENT
|
|
||||||
|
|
||||||
if scrobble.media_type == "GeoLocation" and not force_finish:
|
|
||||||
logger.info(
|
|
||||||
f"[scrobbling] not complete, locations are ONLY completed when new one is created, use force_finish",
|
|
||||||
extra={
|
|
||||||
"scrobble_id": scrobble.id,
|
|
||||||
"media_type": scrobble.media_type,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
is_complete = False
|
|
||||||
if scrobble.percent_played >= completion_percent or force_finish:
|
|
||||||
is_complete = True
|
|
||||||
# A hack to fix overruns on time ... default to media taking as long as needed to finish
|
|
||||||
scrobble.playback_position_seconds = (
|
|
||||||
scrobble.media_obj.run_time_seconds
|
|
||||||
)
|
|
||||||
|
|
||||||
scrobble.in_progress = False
|
|
||||||
scrobble.is_paused = False
|
|
||||||
scrobble.played_to_completion = True
|
|
||||||
|
|
||||||
scrobble.save(
|
|
||||||
update_fields=[
|
|
||||||
"in_progress",
|
|
||||||
"is_paused",
|
|
||||||
"played_to_completion",
|
|
||||||
"playback_position_seconds",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
logger.info(
|
|
||||||
f"[scrobbling] checked for completion",
|
|
||||||
extra={
|
|
||||||
"scrobble_id": scrobble.id,
|
|
||||||
"media_type": scrobble.media_type,
|
|
||||||
"percent_played": scrobble.percent_played,
|
|
||||||
"completion_percent": completion_percent,
|
|
||||||
"is_complete": is_complete,
|
|
||||||
"force_finish": force_finish,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
|
def get_scrobbles_for_media(media_obj, user: User) -> models.QuerySet:
|
||||||
Scrobble = apps.get_model(app_label="scrobbles", model_name="Scrobble")
|
Scrobble = apps.get_model(app_label="scrobbles", model_name="Scrobble")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user