Add getArtists endpoint for ID3-based artist browsing

This commit is contained in:
2025-12-07 23:21:20 +00:00
parent c377cb7833
commit 42df9a3c04

View File

@@ -208,6 +208,49 @@ router.get('/getMusicDirectory.view', authenticateSubsonic, async (req, res) =>
}
});
// Get artists (ID3 tags)
router.get('/getArtists.view', authenticateSubsonic, async (req, res) => {
try {
const artists = await all(`
SELECT DISTINCT artist, COUNT(DISTINCT album) as album_count
FROM tracks
GROUP BY artist
ORDER BY artist
`);
// Group by first letter
const grouped = {};
artists.forEach(artist => {
const firstChar = (artist.artist || 'Unknown')[0].toUpperCase();
const letter = /[A-Z]/.test(firstChar) ? firstChar : '#';
if (!grouped[letter]) grouped[letter] = [];
const artistId = crypto.createHash('md5').update(`artist-${artist.artist}`).digest('hex');
grouped[letter].push({
id: artistId,
name: artist.artist,
albumCount: artist.album_count
});
});
let artistsXml = '<artists ignoredArticles="The El La Los Las Le Les">\n';
Object.keys(grouped).sort().forEach(letter => {
artistsXml += ` <index name="${letter}">\n`;
grouped[letter].forEach(artist => {
artistsXml += ` <artist id="${artist.id}" name="${escapeXml(artist.name)}" albumCount="${artist.albumCount}"/>\n`;
});
artistsXml += ` </index>\n`;
});
artistsXml += '</artists>';
sendSubsonicResponse(res, artistsXml);
} catch (error) {
sendSubsonicError(res, 0, error.message);
}
});
// Get indexes (artists)
router.get('/getIndexes.view', authenticateSubsonic, async (req, res) => {
try {