From 87c996335454c441c7a94df1dab82809b65d0fcb Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Fri, 20 Jun 2025 18:35:11 -0700 Subject: [PATCH] fix subsonic album artist and album list count --- .../api/subsonic/subsonic-controller.ts | 124 +----------------- src/shared/api/subsonic/subsonic-normalize.ts | 60 ++++----- src/shared/api/subsonic/subsonic-types.ts | 1 - 3 files changed, 32 insertions(+), 153 deletions(-) diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index 2692ab59..9eb8e05d 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -347,8 +347,8 @@ export const SubsonicController: ControllerEndpoint = { type = AlbumListSortType.BY_YEAR; } - let fromYear; - let toYear; + let fromYear: number | undefined; + let toYear: number | undefined; if (query.minYear) { fromYear = query.minYear; @@ -398,124 +398,8 @@ export const SubsonicController: ControllerEndpoint = { totalRecordCount: null, }; }, - getAlbumListCount: async (args) => { - const { apiClientProps, query } = args; - - if (query.searchTerm) { - let fetchNextPage = true; - let startIndex = 0; - let totalRecordCount = 0; - - while (fetchNextPage) { - const res = await ssApiClient(apiClientProps).search3({ - query: { - albumCount: 500, - albumOffset: startIndex, - artistCount: 0, - artistOffset: 0, - query: query.searchTerm || '""', - songCount: 0, - songOffset: 0, - }, - }); - - if (res.status !== 200) { - throw new Error('Failed to get album list count'); - } - - const albumCount = (res.body.searchResult3?.album || [])?.length; - - totalRecordCount += albumCount; - startIndex += albumCount; - - // The max limit size for Subsonic is 500 - fetchNextPage = albumCount === 500; - } - - return totalRecordCount; - } - - if (query.favorite) { - const res = await ssApiClient(apiClientProps).getStarred({ - query: { - musicFolderId: query.musicFolderId, - }, - }); - - if (res.status !== 200) { - throw new Error('Failed to get album list'); - } - - return (res.body.starred?.album || []).length || 0; - } - - let type = AlbumListSortType.ALPHABETICAL_BY_NAME; - - let fetchNextPage = true; - let startIndex = 0; - let totalRecordCount = 0; - - if (query.genres?.length) { - type = AlbumListSortType.BY_GENRE; - } - - if (query.minYear || query.maxYear) { - type = AlbumListSortType.BY_YEAR; - } - - let fromYear; - let toYear; - - if (query.minYear) { - fromYear = query.minYear; - toYear = dayjs().year(); - } - - if (query.maxYear) { - toYear = query.maxYear; - - if (!query.minYear) { - fromYear = 0; - } - } - - while (fetchNextPage) { - const res = await ssApiClient(apiClientProps).getAlbumList2({ - query: { - fromYear, - genre: query.genres?.length ? query.genres[0] : undefined, - musicFolderId: query.musicFolderId, - offset: startIndex, - size: 500, - toYear, - type, - }, - }); - - const headers = res.headers; - - // Navidrome returns the total count in the header - if (headers.get('x-total-count')) { - fetchNextPage = false; - totalRecordCount = Number(headers.get('x-total-count')); - break; - } - - if (res.status !== 200) { - throw new Error('Failed to get album list count'); - } - - const albumCount = res.body.albumList2.album.length; - - totalRecordCount += albumCount; - startIndex += albumCount; - - // The max limit size for Subsonic is 500 - fetchNextPage = albumCount === 500; - } - - return totalRecordCount; - }, + getAlbumListCount: async (args) => + SubsonicController.getAlbumList(args).then((res) => res!.totalRecordCount!), getArtistList: async (args) => { const { apiClientProps, query } = args; diff --git a/src/shared/api/subsonic/subsonic-normalize.ts b/src/shared/api/subsonic/subsonic-normalize.ts index 5a400eb1..a380868e 100644 --- a/src/shared/api/subsonic/subsonic-normalize.ts +++ b/src/shared/api/subsonic/subsonic-normalize.ts @@ -36,40 +36,32 @@ const getCoverArtUrl = (args: { ); }; -const getArtists = ( +const getArtistList = ( + artists?: typeof ssType._response.song._type.artists, + artistId?: number | string, + artistName?: string, +) => { + return artists + ? artists.map((item) => ({ + id: item.id.toString(), + imageUrl: null, + name: item.name, + })) + : [ + { + id: artistId?.toString() || '', + imageUrl: null, + name: artistName || '', + }, + ]; +}; + +const getParticipants = ( item: | z.infer | z.infer | z.infer, ) => { - const albumArtists: RelatedArtist[] = item.albumArtists - ? item.albumArtists.map((item) => ({ - id: item.id.toString(), - imageUrl: null, - name: item.name, - })) - : [ - { - id: item.artistId?.toString() || '', - imageUrl: null, - name: item.artist || '', - }, - ]; - - const artists: RelatedArtist[] = item.artists - ? item.artists.map((item) => ({ - id: item.id.toString(), - imageUrl: null, - name: item.name, - })) - : [ - { - id: item.artistId?.toString() || '', - imageUrl: null, - name: item.artist || '', - }, - ]; - let participants: null | Record = null; if (item.contributors) { @@ -94,7 +86,7 @@ const getArtists = ( } } - return { albumArtists, artists, participants }; + return participants; }; const getGenres = ( @@ -139,9 +131,10 @@ const normalizeSong = ( return { album: item.album || '', + albumArtists: getArtistList(item.albumArtists, item.artistId, item.artist), albumId: item.albumId?.toString() || '', artistName: item.artist || '', - ...getArtists(item), + artists: getArtistList(item.artists, item.artistId, item.artist), bitRate: item.bitRate || 0, bpm: item.bpm || null, channels: null, @@ -167,6 +160,7 @@ const normalizeSong = ( lastPlayedAt: null, lyrics: null, name: item.title, + participants: getParticipants(item), path: item.path, peak: item.replayGain && (item.replayGain.albumPeak || item.replayGain.trackPeak) @@ -243,7 +237,8 @@ const normalizeAlbum = ( return { albumArtist: item.artist, - ...getArtists(item), + albumArtists: getArtistList(item.artists, item.artistId, item.artist), + artists: [], backdropImageUrl: null, comment: null, createdAt: item.created, @@ -258,6 +253,7 @@ const normalizeAlbum = ( mbzId: null, name: item.name, originalDate: null, + participants: getParticipants(item), playCount: null, releaseDate: item.year ? new Date(Date.UTC(item.year, 0, 1)).toISOString() : null, releaseYear: item.year ? Number(item.year) : null, diff --git a/src/shared/api/subsonic/subsonic-types.ts b/src/shared/api/subsonic/subsonic-types.ts index 96c80105..3ab30ae4 100644 --- a/src/shared/api/subsonic/subsonic-types.ts +++ b/src/shared/api/subsonic/subsonic-types.ts @@ -115,7 +115,6 @@ const song = z.object({ const album = z.object({ album: z.string(), - albumArtists: z.array(simpleArtist), artist: z.string(), artistId: id, artists: z.array(simpleArtist),