diff --git a/src/backend/common/vendor/LastfmApiClient.ts b/src/backend/common/vendor/LastfmApiClient.ts index cdf8242b..b665e640 100644 --- a/src/backend/common/vendor/LastfmApiClient.ts +++ b/src/backend/common/vendor/LastfmApiClient.ts @@ -1,7 +1,7 @@ import dayjs, { type Dayjs, type ManipulateType } from "dayjs"; import type {PlayObject, PlayObjectMinimal, ScrobbleActionResult, UnixTimestamp, URLData, Writeable} from "../../../core/Atomic.ts"; import { nonEmptyStringOrDefault, splitByFirstFound, truncateStringToLength } from "../../../core/StringUtils.ts"; -import { creditsToNames, nameToCredit } from "../../../core/MusicMetadata.ts"; +import { creditsToNames, nameToCredit, withImage } from "../../../core/MusicMetadata.ts"; import { namesToCredits } from "../../../core/MusicMetadata.ts"; import { removeUndefinedKeys } from '../../../core/DataUtils.ts'; import { writeFile } from '../../utils/FSUtils.ts'; @@ -776,11 +776,24 @@ export const formatPlayObj = (obj: LastFMTrackObject, options: FormatPlayObjectO } } + const i = image ?? []; + let imageSizeNum: number = 0; + let imageUrl: string | undefined = undefined; + if(i !== undefined && i !== null && i.length > 0) { + for(const im of i) { + const res = lastfmImageSize.safeParse(im.size); + if(res.success && lastfmImageSizeMap[res.data] > imageSizeNum) { + imageSizeNum = lastfmImageSizeMap[res.data]; + imageUrl = im["#text"]; + } + } + } + const play: PlayObjectMinimal = { data: { artists: creditsWithIds(namesToCredits([...new Set(artistStrings)] as string[]), splitByFirstFound(artistMbid, [',',';'], undefined), 'musicbrainz', 'artist'), track: nameToCredit(title, mbMeta(mbid, 'recording')), - album: nameToCredit(al, mbMeta(albumMbid, 'release')), + album: withImage(nameToCredit(al, mbMeta(albumMbid, 'release')), imageUrl), duration, playDate: time !== undefined ? dayjs.unix(typeof time === 'string' ? Number.parseInt(time, 10) : time) : undefined }, @@ -793,27 +806,6 @@ export const formatPlayObj = (obj: LastFMTrackObject, options: FormatPlayObjectO } } - if(brainz !== undefined && !objectIsEmpty(brainz)) { - play.data.meta = { - brainz - } - } - - const i = image ?? []; - let imageSizeNum: number = 0; - let imageUrl: string | undefined = undefined; - if(i !== undefined && i !== null && i.length > 0) { - for(const im of i) { - const res = lastfmImageSize.safeParse(im.size); - if(res.success && lastfmImageSizeMap[res.data] > imageSizeNum) { - imageSizeNum = lastfmImageSizeMap[res.data]; - imageUrl = im["#text"]; - } - } - } - if(imageUrl !== undefined) { - play.album.image = imageUrl; - } return baseFormatPlayObj(obj, play); } diff --git a/src/backend/common/vendor/tuneshine/TuneshineApiClient.ts b/src/backend/common/vendor/tuneshine/TuneshineApiClient.ts index b0fc10c7..300407a5 100644 --- a/src/backend/common/vendor/tuneshine/TuneshineApiClient.ts +++ b/src/backend/common/vendor/tuneshine/TuneshineApiClient.ts @@ -64,22 +64,13 @@ export class TuneshineApiClient extends AbstractApiClient { } async sendNowPlaying(play: PlayObject) { - let artUrl: string | undefined = undefined; - if(play.meta?.art !== undefined && typeof play.meta.art === 'object' && play.meta.art !== null) { - const { - track, - album, - artist - } = play.meta.art - if(track !== undefined) { - artUrl = track; - this.logger.trace(`Using art from track: ${track}`); - } else if(album !== undefined) { - artUrl = album; - this.logger.trace(`Using art from album: ${album}`); - } else if(artist !== undefined) { - artUrl = artist; - this.logger.trace(`Using art from artist: ${artist}`); + let artUrl: string | undefined = play.data.track?.image ?? play.data.album?.image; + if(artUrl === undefined) { + for(const a of (play.data.artists ?? [])) { + if(a.image !== undefined) { + artUrl = a.image; + break; + } } } if (artUrl === undefined) { @@ -162,13 +153,24 @@ export class TuneshineApiClient extends AbstractApiClient { } } -export const playToPostImageMetadata = (play: PlayObject): components['schemas']['ImageUrlRequest'] => ({ - timeoutMs: nowPlayingExpirationDuration({ play, position: play.meta.trackProgressPosition }).asMilliseconds(), - trackName: play.data.track, - artistName: play.data.artists === undefined ? undefined : play.data.artists.map(x => x.name).join(' / '), - albumName: play.data.album, - serviceName: play.meta.musicService ?? play.meta.source, - itemId: play.meta.trackId ?? play.uid, - imageUrl: play.meta?.art?.track ?? play.meta?.art?.album ?? play.meta?.art?.artist, - contentType: 'track' -}); \ No newline at end of file +export const playToPostImageMetadata = (play: PlayObject): components['schemas']['ImageUrlRequest'] => { + let artUrl: string | undefined = play.data.track?.image ?? play.data.album?.image; + if(artUrl === undefined) { + for(const a of (play.data.artists ?? [])) { + if(a.image !== undefined) { + artUrl = a.image; + break; + } + } + } + return { + timeoutMs: nowPlayingExpirationDuration({ play, position: play.meta.trackProgressPosition }).asMilliseconds(), + trackName: play.data.track?.name, + artistName: play.data.artists === undefined ? undefined : play.data.artists.map(x => x.name).join(' / '), + albumName: play.data.album?.name, + serviceName: play.meta.musicService ?? play.meta.source, + itemId: play.meta.trackId ?? play.uid, + imageUrl: artUrl, + contentType: 'track' + } +}; \ No newline at end of file diff --git a/src/backend/scrobblers/TuneshineScrobbler.ts b/src/backend/scrobblers/TuneshineScrobbler.ts index 2626d7b8..e67a379f 100644 --- a/src/backend/scrobblers/TuneshineScrobbler.ts +++ b/src/backend/scrobblers/TuneshineScrobbler.ts @@ -75,22 +75,13 @@ export default class TuneshineScrobbler extends AbstractScrobbleClient { if(data === undefined || data.play === undefined) { return [true]; } - let artUrl: string | undefined = undefined; - if(data.play.meta?.art !== undefined && typeof data.play.meta.art === 'object' && data.play.meta.art !== null) { - const { - track, - album, - artist - } = data.play.meta.art - if(track !== undefined) { - artUrl = track; - this.logger.trace(`Found track art`); - } else if(album !== undefined) { - artUrl = album; - this.logger.trace(`Found album art`); - } else if(artist !== undefined) { - artUrl = artist; - this.logger.trace(`Found artist art`); + let artUrl: string | undefined = data.play.data.track?.image ?? data.play.data.album?.image; + if(artUrl === undefined) { + for(const a of (data.play.data.artists ?? [])) { + if(a.image !== undefined) { + artUrl = a.image; + break; + } } } if (artUrl === undefined) { diff --git a/src/backend/tests/tuneshine/tuneshine.test.ts b/src/backend/tests/tuneshine/tuneshine.test.ts index 083ac2fc..7f2483e5 100644 --- a/src/backend/tests/tuneshine/tuneshine.test.ts +++ b/src/backend/tests/tuneshine/tuneshine.test.ts @@ -10,7 +10,6 @@ import path from 'path'; import { withRequestInterception } from '../utils/networking.ts'; import { http, HttpResponse } from "msw"; import { generatePlay } from '../../../core/tests/utils/PlayTestUtils.ts'; -import { faker } from '@faker-js/faker'; import { TuneshineApiClient } from '../../common/vendor/tuneshine/TuneshineApiClient.ts'; import fs from 'node:fs/promises'; @@ -32,7 +31,7 @@ describe('Tuneshine API', function () { const client = new TuneshineApiClient('test', {data: {host: 'https://test.local'}}, {cache: memorycache(), logger: loggerTest}); await client.buildData(); - const play = generatePlay(undefined, {art: {album: 'https://test.image/01.png'}}); + const play = generatePlay({album: {name: 'whatever', image: 'https://test.image/01.png'}}); await withRequestInterception( [