diff --git a/src/plugins/lastfm/index.tsx b/src/plugins/lastfm/index.tsx index a87931e4c..cbf0875cb 100644 --- a/src/plugins/lastfm/index.tsx +++ b/src/plugins/lastfm/index.tsx @@ -304,21 +304,22 @@ export default definePlugin({ return null; } - const trackData = json.payload.listens[0]; + const trackData = json.payload?.listens?.[0]; - if (!trackData?.playing_now) + if (!trackData?.playing_now || !trackData.track_metadata) return null; - const trackAddInfo = trackData.track_metadata.additional_info; + const trackMeta = trackData.track_metadata; + const trackAddInfo = trackMeta.additional_info; - let recordingMbid = trackAddInfo.recording_mbid; - let releaseMbid = trackAddInfo.release_mbid; + let recordingMbid = trackAddInfo?.recording_mbid; + let releaseMbid = trackAddInfo?.release_mbid; if (!recordingMbid || !releaseMbid) { const metadata = await this.lookupListenBrainzMetadata( - trackData.track_metadata.artist_name, - trackData.track_metadata.track_name, - trackData.track_metadata.release_name + trackMeta.artist_name, + trackMeta.track_name, + trackMeta.release_name ); recordingMbid = recordingMbid || metadata.recording_mbid; @@ -326,11 +327,10 @@ export default definePlugin({ } return { - name: trackData.track_metadata.track_name, - album: trackData.track_metadata.release_name, - artist: trackData.track_metadata.artist_name, - url: trackAddInfo.origin_url || - recordingMbid && `https://musicbrainz.org/recording/${recordingMbid}`, + name: trackMeta.track_name || "Unknown", + album: trackMeta.release_name || "Unknown", + artist: trackMeta.artist_name || "Unknown", + url: trackAddInfo?.origin_url || recordingMbid && `https://musicbrainz.org/recording/${recordingMbid}`, imageUrl: releaseMbid && `https://coverartarchive.org/release/${releaseMbid}/front`, timestamps: settings.store.sendTimestamps ? await this.getListenBrainzTimestamps(trackData) : undefined, client: trackAddInfo?.music_service_name || trackAddInfo?.music_service || trackAddInfo?.media_player @@ -371,64 +371,68 @@ export default definePlugin({ // pausing while listening and unpausing before the track would've ended will throw this off // but other than that it's pretty accurate, at least accurate enough :p async getListenBrainzTimestamps(trackData: any) { - if (!trackData.track_metadata.additional_info?.duration && !trackData.track_metadata.additional_info?.duration_ms) - return undefined; + try { + if (!trackData.track_metadata.additional_info?.duration && !trackData.track_metadata.additional_info?.duration_ms) + return undefined; - const now = Date.now(); + const now = Date.now(); + const duration = trackData.track_metadata.additional_info.duration_ms || + trackData.track_metadata.additional_info.duration * 1000; - const res = await fetch(`https://api.listenbrainz.org/1/user/${settings.store.listenBrainzUsername}/listens?count=1`); - if (!res.ok) throw `${res.status} ${res.statusText}`; - - const json = await res.json(); - if (json.error) { - logger.error("Error from ListenBrainz API", `${json.error}: ${json.message}`); - return undefined; - } - - const duration = trackData.track_metadata.additional_info.duration_ms || - trackData.track_metadata.additional_info.duration * 1000; - - const trackMetadataJson = JSON.stringify(trackData.track_metadata); - // track obviously changed - if (trackMetadataJson !== this.timestampStuff.lastTrack) { - this.timestampStuff.lastTrack = trackMetadataJson; - this.timestampStuff.lastTrackChange = now; - } - // track probably changed because current time exceeded expected track end time - else if (now > this.timestampStuff.lastTrackChange + duration) { - this.timestampStuff.lastTrackChange = now; - } - - const listenAddInfo = json.payload.count >= 1 && json.payload.listens[0].track_metadata.additional_info; - if (listenAddInfo?.duration || listenAddInfo?.duration_ms) { - const listenDuration = listenAddInfo.duration_ms || listenAddInfo.duration * 1000; - const listenStart = json.payload.listens[0].listened_at * 1000; - const listenEnd = listenStart + listenDuration; - - // this listen is current! we have accurate info! - if (now <= listenEnd) { - return { - start: listenStart, - end: listenEnd - }; + const trackMetadataJson = JSON.stringify(trackData.track_metadata); + // track obviously changed + if (trackMetadataJson !== this.timestampStuff.lastTrack) { + this.timestampStuff.lastTrack = trackMetadataJson; + this.timestampStuff.lastTrackChange = now; + } + // track probably changed because current time exceeded expected track end time + else if (now > this.timestampStuff.lastTrackChange + duration) { + this.timestampStuff.lastTrackChange = now; } - // it is Pretty Safe to assume we are listening to music sequentially without stopping Most Of The Time - if (now <= listenEnd + duration) { - return { - start: listenEnd, - end: listenEnd + duration - }; - } - } + const res = await fetch(`https://api.listenbrainz.org/1/user/${settings.store.listenBrainzUsername}/listens?count=1`); + if (!res.ok) throw `${res.status} ${res.statusText}`; - // this technically won't be accurate but good enough - // until we get accurate info halfway through or 4 minutes into the track - // or it's not the first track we are listening to in a row - return { - start: this.timestampStuff.lastTrackChange, - end: this.timestampStuff.lastTrackChange + duration - }; + const json = await res.json(); + if (json.error) { + logger.error("Error from ListenBrainz API", `${json.error}: ${json.message}`); + return undefined; + } + + const listenAddInfo = json.payload.count >= 1 && json.payload.listens[0].track_metadata.additional_info; + if (listenAddInfo?.duration || listenAddInfo?.duration_ms) { + const listenDuration = listenAddInfo.duration_ms || listenAddInfo.duration * 1000; + const listenStart = json.payload.listens[0].listened_at * 1000; + const listenEnd = listenStart + listenDuration; + + // this listen is current! we have accurate info! + if (now <= listenEnd) { + return { + start: listenStart, + end: listenEnd + }; + } + + // it is Pretty Safe to assume we are listening to music sequentially without stopping Most Of The Time + if (now <= listenEnd + duration) { + return { + start: listenEnd, + end: listenEnd + duration + }; + } + } + + // this technically won't be accurate but good enough + // until we get accurate info halfway through or 4 minutes into the track + // or it's not the first track we are listening to in a row + return { + start: this.timestampStuff.lastTrackChange, + end: this.timestampStuff.lastTrackChange + duration + }; + } catch (e) { + logger.error("Failed to query ListenBrainz API", e); + return undefined; + } }, async updatePresence() {