diff --git a/Cargo.lock b/Cargo.lock index 19636a0..b06c77a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,7 +1418,7 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "furumusic" -version = "0.1.20" +version = "0.1.21" dependencies = [ "anyhow", "async-trait", diff --git a/templates/player/scripts.html b/templates/player/scripts.html index dee2ebd..56efe5e 100644 --- a/templates/player/scripts.html +++ b/templates/player/scripts.html @@ -373,6 +373,8 @@ document.addEventListener('alpine:init', () => { }); audio.addEventListener('ended', () => { + this._trackListenedDelta(); + this._maybeScrobble(true); this._recordHistory(true); this.next(); }); @@ -677,6 +679,23 @@ document.addEventListener('alpine:init', () => { this._lastAudioTime = current; }, + _trackDuration() { + const candidates = [ + this.currentTrack?.duration_seconds, + this.duration, + audio.duration, + ]; + for (const value of candidates) { + const duration = Number(value || 0); + if (Number.isFinite(duration) && duration > 0) return duration; + } + return 0; + }, + + _scrobbleThreshold(duration) { + return Math.min(duration / 2, 240); + }, + _sendNowPlaying() { if (this._nowPlayingSent || !this.currentTrack) return; const lastfm = Alpine.store('user')?.lastfm; @@ -689,14 +708,16 @@ document.addEventListener('alpine:init', () => { }).catch(() => {}); }, - _maybeScrobble() { + _maybeScrobble(force = false) { if (this._scrobbleSent || !this.currentTrack) return; const lastfm = Alpine.store('user')?.lastfm; if (!lastfm?.configured || !lastfm?.connected || lastfm?.reauth_required) return; - const duration = Number(this.duration || audio.duration || this.currentTrack.duration_seconds || 0); + const duration = this._trackDuration(); if (!duration || duration <= 30) return; - const threshold = Math.min(duration / 2, 240); - if (this._listenedSeconds < threshold) return; + const threshold = this._scrobbleThreshold(duration); + const listened = force ? this._listenedSeconds + 1 : this._listenedSeconds; + if (listened < threshold) return; + this._listenedSeconds = Math.max(this._listenedSeconds, listened); this._sendScrobble(); },