[READ-ONLY] Mirror of https://github.com/FoxxMD/multi-scrobbler. Scrobble plays from multiple sources to multiple clients docs.multi-scrobbler.app
deezer docker jellyfin koito lastfm listenbrainz maloja mopidy mpris music music-assistant plex scrobble self-hosted spotify subsonic tautulli youtube-music
0

Configure Feed

Select the types of activity you want to include in your feed.

fix: Add last played data and check for repeat on new Play #318

FoxxMD (Jul 17, 2025, 3:45 PM UTC) db547614 aa9f20f5

+13
+13
src/backend/sources/PlayerState/AbstractPlayerState.ts
··· 82 82 stateLastUpdatedAt: Dayjs = dayjs(); 83 83 84 84 lastPlay?: PlayObject 85 + lastPlayUpdatedAt?: Dayjs 85 86 86 87 protected constructor(logger: Logger, platformId: PlayPlatformId, opts: PlayerStateOptions = DefaultPlayerStateOptions) { 87 88 this.platformId = platformId; ··· 186 187 const played = this.getPlayedObject(true); 187 188 this.isRepeatPlay = false; 188 189 this.lastPlay = played; 190 + this.lastPlayUpdatedAt = dayjs(); 189 191 this.setCurrentPlay(state, {reportedTS}); 190 192 if (this.calculatedStatus !== CALCULATED_PLAYER_STATUSES.playing) { 191 193 this.calculatedStatus = CALCULATED_PLAYER_STATUSES.unknown; ··· 200 202 const played = this.getPlayedObject(true); 201 203 play.data.playDate = dayjs(); 202 204 this.isRepeatPlay = true; 205 + this.logger.debug('New Play is a repeat'); 203 206 this.setCurrentPlay(state, {reportedTS}); 204 207 return [this.getPlayedObject(), played]; 205 208 } else { ··· 219 222 } 220 223 } else { 221 224 this.isRepeatPlay = false; 225 + // compensate for Players that report as STOPPED between Plays 226 + // -- should we check for closeToPlayStart() as well? 227 + if(this.lastPlay !== undefined) { 228 + const lastPlayDiff = Math.abs(this.lastPlayUpdatedAt.diff(dayjs(), 's')); 229 + const shortDiff = lastPlayDiff < 20; 230 + const lastPlayMatch = playObjDataMatch(play, this.lastPlay); 231 + this.isRepeatPlay = shortDiff && lastPlayMatch; 232 + this.logger.debug(`Last Play ${shortDiff ? 'was' : 'was not'} within 20s of new Player session and ${lastPlayMatch ? 'does' : 'does not'} match new Play -- ${this.isRepeatPlay ? 'is' : 'is not'} a repeat Play`); 233 + } 222 234 223 235 this.setCurrentPlay(state); 224 236 this.calculatedStatus = CALCULATED_PLAYER_STATUSES.unknown; ··· 235 247 236 248 protected clearPlayer() { 237 249 this.lastPlay = this.currentPlay; 250 + this.lastPlayUpdatedAt = dayjs(); 238 251 this.currentPlay = undefined; 239 252 this.playLastUpdatedAt = undefined; 240 253 this.playFirstSeenAt = undefined;