fix: iTunes JP-first with US fallback; romaji filter in playlist/starred search

This commit is contained in:
Honey committed 2026-05-27 17:16:57 +02:00
1 parent a9463917e3
commit 3837783225
3 files changed
+17 -9

No files matched your search

+4 -2
View File
@@ -92,13 +92,15 @@ async function lookupItunesTrackMeta(artist, title) {
// e.g. "don't rush - slowed" → search "don't rush" so iTunes finds the single // e.g. "don't rush - slowed" → search "don't rush" so iTunes finds the single
const baseTitle = title.replace(/\s*[-–]\s*\S[^-]*$/, '').trim() || title; const baseTitle = title.replace(/\s*[-–]\s*\S[^-]*$/, '').trim() || title;
const searchTitle = baseTitle !== title ? baseTitle : title; const searchTitle = baseTitle !== title ? baseTitle : title;
const url = `https://itunes.apple.com/search?term=${encodeURIComponent(artist + ' ' + searchTitle)}&media=music&entity=musicTrack&limit=10&country=jp&explicit=Yes`; const fetchItunes = (country) => new Promise((resolve, reject) => {
const results = await new Promise((resolve, reject) => { const url = `https://itunes.apple.com/search?term=${encodeURIComponent(artist + ' ' + searchTitle)}&media=music&entity=musicTrack&limit=10&country=${country}&explicit=Yes`;
https.get(url, res => { https.get(url, res => {
let d = ''; res.on('data', c => d += c); let d = ''; res.on('data', c => d += c);
res.on('end', () => { try { resolve(JSON.parse(d).results || []); } catch { reject(new Error('parse')); } }); res.on('end', () => { try { resolve(JSON.parse(d).results || []); } catch { reject(new Error('parse')); } });
}).on('error', reject); }).on('error', reject);
}); });
let results = await fetchItunes('jp');
if (!results.length) results = await fetchItunes('us');
const normT = normalizeTitle(title); const normT = normalizeTitle(title);
const normA = (artist || '').toLowerCase().trim(); const normA = (artist || '').toLowerCase().trim();
// Split by space OR comma/semicolon/slash so "VXLLAIN, iGRES" → "vxllain" not "vxllain," // Split by space OR comma/semicolon/slash so "VXLLAIN, iGRES" → "vxllain" not "vxllain,"
+6 -4
View File
@@ -135,10 +135,12 @@ function _itunesBase() {
export async function itunesSearch(query, entity='musicTrack', limit=25) { export async function itunesSearch(query, entity='musicTrack', limit=25) {
try { try {
const r = await fetch(`${_itunesBase()}/search?term=${encodeURIComponent(query)}&media=music&entity=${entity}&limit=${limit}&country=jp&explicit=Yes`); const base = `${_itunesBase()}/search?term=${encodeURIComponent(query)}&media=music&entity=${entity}&limit=${limit}&explicit=Yes`;
const text = await r.text(); const rJp = await fetch(`${base}&country=jp`);
if (!text) return []; const jpResults = JSON.parse(await rJp.text()).results || [];
return JSON.parse(text).results || []; if (jpResults.length) return jpResults;
const rUs = await fetch(`${base}&country=us`);
return JSON.parse(await rUs.text()).results || [];
} catch { return []; } } catch { return []; }
} }
+7 -3
View File
@@ -6,7 +6,7 @@ import { playQueue, dlSongLocal, playPreview, toggleStar, parseArtists } from '.
import { showCtxMenu, openEditPlModal, openDlModal, closeSidebar, switchNavMode } from './ui.js'; import { showCtxMenu, openEditPlModal, openDlModal, closeSidebar, switchNavMode } from './ui.js';
import { closeNowPlaying, closeNpMenu } from './nowplaying.js'; import { closeNowPlaying, closeNpMenu } from './nowplaying.js';
import { makeCard, makeAlbumCard, makeSongItem, makeGlobalTrackItem, mkSection } from './components.js'; import { makeCard, makeAlbumCard, makeSongItem, makeGlobalTrackItem, mkSection } from './components.js';
import { fetchRomajiIndex, dispArtistById } from './api.js'; import { fetchRomajiIndex, dispArtistById, romajiLookup } from './api.js';
import { loadSpotifyImporter } from './spotify.js'; import { loadSpotifyImporter } from './spotify.js';
import { loadSoundCloudImporter } from './soundcloud.js'; import { loadSoundCloudImporter } from './soundcloud.js';
@@ -748,7 +748,9 @@ export function filterPlaylist(val) {
document.querySelectorAll('#playlist-songs .song-item').forEach(item => { document.querySelectorAll('#playlist-songs .song-item').forEach(item => {
const title = (item.querySelector('.song-title')?.textContent || '').toLowerCase(); const title = (item.querySelector('.song-title')?.textContent || '').toLowerCase();
const artist = (item.querySelector('.song-artist')?.textContent || '').toLowerCase(); const artist = (item.querySelector('.song-artist')?.textContent || '').toLowerCase();
item.style.display = (!q || title.includes(q) || artist.includes(q)) ? '' : 'none'; if (!q || title.includes(q) || artist.includes(q)) { item.style.display = ''; return; }
const rm = romajiLookup(item.dataset.songId);
item.style.display = ((rm?.titleRomaji||'').toLowerCase().includes(q) || (rm?.artistRomaji||'').toLowerCase().includes(q)) ? '' : 'none';
}); });
} }
@@ -916,7 +918,9 @@ export function filterStarred(val) {
document.querySelectorAll('#starred-songs .song-item').forEach(item => { document.querySelectorAll('#starred-songs .song-item').forEach(item => {
const title = (item.querySelector('.song-title')?.textContent || '').toLowerCase(); const title = (item.querySelector('.song-title')?.textContent || '').toLowerCase();
const artist = (item.querySelector('.song-artist')?.textContent || '').toLowerCase(); const artist = (item.querySelector('.song-artist')?.textContent || '').toLowerCase();
item.style.display = (!q || title.includes(q) || artist.includes(q)) ? '' : 'none'; if (!q || title.includes(q) || artist.includes(q)) { item.style.display = ''; return; }
const rm = romajiLookup(item.dataset.songId);
item.style.display = ((rm?.titleRomaji||'').toLowerCase().includes(q) || (rm?.artistRomaji||'').toLowerCase().includes(q)) ? '' : 'none';
}); });
} }