diff --git a/vrobbler/apps/scrobbles/models.py b/vrobbler/apps/scrobbles/models.py index 258da1e..cb1ac98 100644 --- a/vrobbler/apps/scrobbles/models.py +++ b/vrobbler/apps/scrobbles/models.py @@ -892,8 +892,9 @@ class Scrobble(TimeStampedModel): if self.played_to_completion: if self.playback_position_seconds: return self.playback_position_seconds - if self.media_obj.run_time_seconds: + if self.media_obj and self.media_obj.run_time_seconds: return self.media_obj.run_time_seconds + return (timezone.now() - self.timestamp).seconds @property diff --git a/vrobbler/apps/scrobbles/utils.py b/vrobbler/apps/scrobbles/utils.py index 659bf10..ee548b7 100644 --- a/vrobbler/apps/scrobbles/utils.py +++ b/vrobbler/apps/scrobbles/utils.py @@ -2,6 +2,7 @@ import hashlib import logging import re from datetime import datetime, timedelta +from typing import TYPE_CHECKING, Optional from urllib.parse import urlparse from zoneinfo import ZoneInfo @@ -13,7 +14,10 @@ from django.utils import timezone from profiles.models import UserProfile from profiles.utils import now_user_timezone from scrobbles.constants import LONG_PLAY_MEDIA -from scrobbles.notifications import MoodNtfyNotification, ScrobbleNtfyNotification +from scrobbles.notifications import ( + MoodNtfyNotification, + ScrobbleNtfyNotification, +) from scrobbles.tasks import ( process_koreader_import, process_lastfm_import, @@ -21,6 +25,9 @@ from scrobbles.tasks import ( ) from webdav.client import get_webdav_client +if TYPE_CHECKING: + from scrobbles.models import Scrobble + logger = logging.getLogger(__name__) User = get_user_model() @@ -345,3 +352,22 @@ def extract_domain(url): + parsed_url.netloc.split(".")[-1] ) return domain + +def fix_playback_position_seconds(*scrobbles: "Scrobble", commit=True) -> list["Scrobble"]: + updated_scrobbles = list() + for scrobble in scrobbles: + if not scrobble.media_obj: + logger.info(f"No media object found for scrobble {scrobble.id}, cannot update elapsed time") + continue + + if scrobble.media_type == "Track" and scrobble.media_obj.run_time_seconds: + too_long = scrobble.playback_position_seconds > scrobble.media_obj.run_time_seconds + zero = scrobble.playback_position_seconds == 0 + null = not scrobble.playback_position_seconds + if too_long or zero or null: + scrobble.playback_position_seconds = scrobble.media_obj.run_time_seconds + updated_scrobbles.append(scrobble) + if commit: + scrobble.save(update_fields=["playback_position_seconds"]) + + return updated_scrobbles