fix: use iTunes lookup endpoint for explicit artist tracks
iTunes search endpoint always returns cleaned versions. Added itunesLookupArtistSongs() using /lookup?explicit=Yes which returns the actual explicit tracks. Used in artist profile (global search) and artist detail page (library). Album track lookup also gets explicit=Yes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
fc951d103b
commit
3c5048f017
2 files changed
+16
-5
No files matched your search
+8
-1
@@ -43,7 +43,14 @@ export async function itunesSearch(query, entity='musicTrack', limit=25) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function itunesLookupAlbum(collectionId) {
|
export async function itunesLookupAlbum(collectionId) {
|
||||||
const r = await fetch(`${ITUNES}/lookup?id=${collectionId}&entity=song`);
|
const r = await fetch(`${ITUNES}/lookup?id=${collectionId}&entity=song&explicit=Yes`);
|
||||||
|
const d = await r.json();
|
||||||
|
return (d.results || []).filter(x => x.wrapperType === 'track');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns actual explicit tracks for an artist via lookup (search endpoint only returns cleaned versions)
|
||||||
|
export async function itunesLookupArtistSongs(artistId, limit=15) {
|
||||||
|
const r = await fetch(`${ITUNES}/lookup?id=${artistId}&entity=song&limit=${limit}&country=us&explicit=Yes`);
|
||||||
const d = await r.json();
|
const d = await r.json();
|
||||||
return (d.results || []).filter(x => x.wrapperType === 'track');
|
return (d.results || []).filter(x => x.wrapperType === 'track');
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -1,7 +1,7 @@
|
|||||||
import { S } from './state.js';
|
import { S } from './state.js';
|
||||||
import { esc, formatDur, toast } from './utils.js';
|
import { esc, formatDur, toast } from './utils.js';
|
||||||
import { api, coverUrl } from './api.js';
|
import { api, coverUrl } from './api.js';
|
||||||
import { itunesSearch, itunesLookupAlbum, itunesTopCharts, itunesTopSongs } from './api.js';
|
import { itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesTopCharts, itunesTopSongs } from './api.js';
|
||||||
// Circular imports — safe (only used inside function bodies)
|
// Circular imports — safe (only used inside function bodies)
|
||||||
import { playQueue, dlSongLocal, toggleStar, playPreview } from './player.js';
|
import { playQueue, dlSongLocal, toggleStar, playPreview } from './player.js';
|
||||||
import { showCtxMenu, openEditPlModal, openPlModal, openDlModal, closeSidebar, switchNavMode, closeNowPlaying, closeNpMenu } from './ui.js';
|
import { showCtxMenu, openEditPlModal, openPlModal, openDlModal, closeSidebar, switchNavMode, closeNowPlaying, closeNpMenu } from './ui.js';
|
||||||
@@ -230,14 +230,18 @@ export async function loadArtistDetail(artist) {
|
|||||||
g.innerHTML = '<div class="spinner"></div>';
|
g.innerHTML = '<div class="spinner"></div>';
|
||||||
document.getElementById('artist-itunes-extra')?.remove();
|
document.getElementById('artist-itunes-extra')?.remove();
|
||||||
|
|
||||||
const [imgRes, albumRes, infoRes, topRes, itunesTracksRes, itunesAlbumsRes] = await Promise.allSettled([
|
const [imgRes, albumRes, infoRes, topRes, itunesArtistRes, itunesAlbumsRes] = await Promise.allSettled([
|
||||||
getArtistImage(artist.id),
|
getArtistImage(artist.id),
|
||||||
api('getArtist', `&id=${artist.id}`),
|
api('getArtist', `&id=${artist.id}`),
|
||||||
api('getArtistInfo2', `&id=${artist.id}&count=8`),
|
api('getArtistInfo2', `&id=${artist.id}&count=8`),
|
||||||
api('getTopSongs', `&artist=${encodeURIComponent(artist.name)}&count=10`),
|
api('getTopSongs', `&artist=${encodeURIComponent(artist.name)}&count=10`),
|
||||||
itunesSearch(artist.name, 'musicTrack', 10),
|
itunesSearch(artist.name, 'musicArtist', 1),
|
||||||
itunesSearch(artist.name, 'album', 20),
|
itunesSearch(artist.name, 'album', 20),
|
||||||
]);
|
]);
|
||||||
|
const itunesArtistId = itunesArtistRes.status==='fulfilled' ? (itunesArtistRes.value[0]?.artistId ?? null) : null;
|
||||||
|
const itunesTracksRes = itunesArtistId
|
||||||
|
? await Promise.allSettled([itunesLookupArtistSongs(itunesArtistId, 10)])[0]
|
||||||
|
: { status: 'rejected' };
|
||||||
|
|
||||||
const img = imgRes.status==='fulfilled' ? imgRes.value : null;
|
const img = imgRes.status==='fulfilled' ? imgRes.value : null;
|
||||||
if(img) {
|
if(img) {
|
||||||
@@ -625,7 +629,7 @@ export async function loadItunesArtistResults(artistId, artistName) {
|
|||||||
try {
|
try {
|
||||||
const [albums, topTracks] = await Promise.all([
|
const [albums, topTracks] = await Promise.all([
|
||||||
itunesSearch(artistName, 'album', 20),
|
itunesSearch(artistName, 'album', 20),
|
||||||
itunesSearch(artistName, 'musicTrack', 10),
|
itunesLookupArtistSongs(artistId, 15),
|
||||||
]);
|
]);
|
||||||
const artistAlbums = albums.filter(a => a.artistId===artistId || a.artistName===artistName);
|
const artistAlbums = albums.filter(a => a.artistId===artistId || a.artistName===artistName);
|
||||||
const artistTracks = topTracks.filter(t => t.wrapperType==='track' && (t.artistId===artistId || t.artistName===artistName));
|
const artistTracks = topTracks.filter(t => t.wrapperType==='track' && (t.artistId===artistId || t.artistName===artistName));
|
||||||
|
|||||||
Reference in new issue
Block a user