diff --git a/src/backend/common/vendor/bluesky/AbstractBlueSkyApiClient.ts b/src/backend/common/vendor/bluesky/AbstractBlueSkyApiClient.ts index e8b902a8..03ab04a6 100644 --- a/src/backend/common/vendor/bluesky/AbstractBlueSkyApiClient.ts +++ b/src/backend/common/vendor/bluesky/AbstractBlueSkyApiClient.ts @@ -124,13 +124,16 @@ export const playToRecord = (play: PlayObject): ScrobbleRecord => { } export const playToStatusRecord = (play: PlayObject, notPlaying: boolean, position?: number): StatusRecord => { - const { $type, ...item } = playToRecord(play); + const { $type, ...item } = notPlaying + ? { trackName: "", artists: [] } + : playToRecord(play); return { $type: "fm.teal.alpha.actor.status", time: dayjs().toISOString(), - // expiry is 1min ago if paused, (now + duration - position) if position is available, or fallback to (now + 10mins) + // 1min ago if paused -> try now + (duration - position) -> try now + duration -> fallback to now + 10mins expiry: notPlaying ? dayjs().subtract(1, 'minute').toISOString() - : position !== undefined ? dayjs().add(play.data.duration - position, 'second').toISOString() + : position !== undefined && play.data.duration !== undefined ? dayjs().add(play.data.duration - position, 'second').toISOString() + : play.data.duration !== undefined ? dayjs().add(play.data.duration, 'second').toISOString() : dayjs().add(10, 'minute').toISOString(), item }; diff --git a/src/backend/scrobblers/TealfmScrobbler.ts b/src/backend/scrobblers/TealfmScrobbler.ts index 1050f37b..94b2c2e9 100644 --- a/src/backend/scrobblers/TealfmScrobbler.ts +++ b/src/backend/scrobblers/TealfmScrobbler.ts @@ -17,7 +17,6 @@ export default class TealScrobbler extends AbstractScrobbleClient { requiresAuth = true; requiresAuthInteraction = false; - clearedStatus = false; // tracks if a user's status has been cleared on their repo declare config: TealClientConfig; @@ -127,21 +126,25 @@ export default class TealScrobbler extends AbstractScrobbleClient { const notPlaying = [CALCULATED_PLAYER_STATUSES.stopped, CALCULATED_PLAYER_STATUSES.paused].includes(data.status.calculated as ReportedPlayerStatus); try { await this.client.updateStatusRecord(playToStatusRecord(data.play, notPlaying, data.position)); - this.clearedStatus = notPlaying; } catch (e) { throw e; } } + wasLastStatusCleared = () => { + return this.nowPlayingLastPlay !== undefined + && [CALCULATED_PLAYER_STATUSES.stopped, CALCULATED_PLAYER_STATUSES.paused].includes(this.nowPlayingLastPlay.status.calculated as ReportedPlayerStatus) + } + shouldUpdatePlayingNowPlatformSpecific = async (data: SourcePlayerObj): Promise<[boolean, string?, LogLevel?]> => { - if ([CALCULATED_PLAYER_STATUSES.stopped, CALCULATED_PLAYER_STATUSES.paused].includes(data.status.calculated as ReportedPlayerStatus) && !this.clearedStatus + if ([CALCULATED_PLAYER_STATUSES.stopped, CALCULATED_PLAYER_STATUSES.paused].includes(data.status.calculated as ReportedPlayerStatus) && !this.wasLastStatusCleared() || [CALCULATED_PLAYER_STATUSES.playing].includes(data.status.calculated as ReportedPlayerStatus) || (data.nowPlayingMode && !CALCULATED_PLAYER_STATUSES.stopped)) { return [true]; } else { if(!data.nowPlayingMode && ![CALCULATED_PLAYER_STATUSES.stopped, CALCULATED_PLAYER_STATUSES.paused, CALCULATED_PLAYER_STATUSES.playing].includes(data.status.calculated as ReportedPlayerStatus)) { return [false,`player is not in state: stopped | paused | playing => Found '${data.status.calculated }'`]; - } else if (this.clearedStatus) { + } else if (this.wasLastStatusCleared()) { return [false, 'teal.fm status has already been set to expired']; } else if (data.nowPlayingMode && CALCULATED_PLAYER_STATUSES.stopped) { this.npLogger.trace(`Will not update because now playing player is stopped => Found ${data.status.calculated}`);