fix subsonic album artist and album list count

This commit is contained in:
Kendall Garner 2025-06-20 18:35:11 -07:00
parent b7fb7c7f94
commit 87c9963354
No known key found for this signature in database
GPG key ID: 9355F387FE765C94
3 changed files with 32 additions and 153 deletions

View file

@ -347,8 +347,8 @@ export const SubsonicController: ControllerEndpoint = {
type = AlbumListSortType.BY_YEAR; type = AlbumListSortType.BY_YEAR;
} }
let fromYear; let fromYear: number | undefined;
let toYear; let toYear: number | undefined;
if (query.minYear) { if (query.minYear) {
fromYear = query.minYear; fromYear = query.minYear;
@ -398,124 +398,8 @@ export const SubsonicController: ControllerEndpoint = {
totalRecordCount: null, totalRecordCount: null,
}; };
}, },
getAlbumListCount: async (args) => { getAlbumListCount: async (args) =>
const { apiClientProps, query } = args; SubsonicController.getAlbumList(args).then((res) => res!.totalRecordCount!),
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;
},
getArtistList: async (args) => { getArtistList: async (args) => {
const { apiClientProps, query } = args; const { apiClientProps, query } = args;

View file

@ -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: item:
| z.infer<typeof ssType._response.album> | z.infer<typeof ssType._response.album>
| z.infer<typeof ssType._response.albumListEntry> | z.infer<typeof ssType._response.albumListEntry>
| z.infer<typeof ssType._response.song>, | z.infer<typeof ssType._response.song>,
) => { ) => {
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<string, RelatedArtist[]> = null; let participants: null | Record<string, RelatedArtist[]> = null;
if (item.contributors) { if (item.contributors) {
@ -94,7 +86,7 @@ const getArtists = (
} }
} }
return { albumArtists, artists, participants }; return participants;
}; };
const getGenres = ( const getGenres = (
@ -139,9 +131,10 @@ const normalizeSong = (
return { return {
album: item.album || '', album: item.album || '',
albumArtists: getArtistList(item.albumArtists, item.artistId, item.artist),
albumId: item.albumId?.toString() || '', albumId: item.albumId?.toString() || '',
artistName: item.artist || '', artistName: item.artist || '',
...getArtists(item), artists: getArtistList(item.artists, item.artistId, item.artist),
bitRate: item.bitRate || 0, bitRate: item.bitRate || 0,
bpm: item.bpm || null, bpm: item.bpm || null,
channels: null, channels: null,
@ -167,6 +160,7 @@ const normalizeSong = (
lastPlayedAt: null, lastPlayedAt: null,
lyrics: null, lyrics: null,
name: item.title, name: item.title,
participants: getParticipants(item),
path: item.path, path: item.path,
peak: peak:
item.replayGain && (item.replayGain.albumPeak || item.replayGain.trackPeak) item.replayGain && (item.replayGain.albumPeak || item.replayGain.trackPeak)
@ -243,7 +237,8 @@ const normalizeAlbum = (
return { return {
albumArtist: item.artist, albumArtist: item.artist,
...getArtists(item), albumArtists: getArtistList(item.artists, item.artistId, item.artist),
artists: [],
backdropImageUrl: null, backdropImageUrl: null,
comment: null, comment: null,
createdAt: item.created, createdAt: item.created,
@ -258,6 +253,7 @@ const normalizeAlbum = (
mbzId: null, mbzId: null,
name: item.name, name: item.name,
originalDate: null, originalDate: null,
participants: getParticipants(item),
playCount: null, playCount: null,
releaseDate: item.year ? new Date(Date.UTC(item.year, 0, 1)).toISOString() : null, releaseDate: item.year ? new Date(Date.UTC(item.year, 0, 1)).toISOString() : null,
releaseYear: item.year ? Number(item.year) : null, releaseYear: item.year ? Number(item.year) : null,

View file

@ -115,7 +115,6 @@ const song = z.object({
const album = z.object({ const album = z.object({
album: z.string(), album: z.string(),
albumArtists: z.array(simpleArtist),
artist: z.string(), artist: z.string(),
artistId: id, artistId: id,
artists: z.array(simpleArtist), artists: z.array(simpleArtist),