fix: use the US iTunes store everywhere for consistent artist naming

Search (web api.js) was JP-first, the download lookups were JP-first, and the Android
client was already US — so the same artist resolved inconsistently: sometimes kanji,
sometimes katakana, sometimes romaji, depending on which path and which store matched.

Switch everything to the US store:
- api.js itunesSearch → country=us (one fetch, matches the Android client)
- metadata.js lookupItunesTrackMeta → US only (drops the JP fetch: consistent names +
  halves the download's iTunes calls, which also eases the rate limit)
- searchItunesAlbumTracks → country=us
- remove the JP-katakana guards in the album/artist download paths (redundant now, and
  they wrongly romanized genuine Japanese artists like 羽岡佳 → "Kei Haneoka")

Titles still come from the source, so a Japanese title the user picked stays Japanese;
only iTunes-derived fields (album_artist, genre, year, artwork) follow the US store.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-07-29 10:37:07 +02:00
1 parent d98978a6c7
commit 9c8b4775ea
5 files changed
+23 -32

No files matched your search

+10 -16
View File
@@ -168,24 +168,18 @@ async function lookupItunesTrackMeta(artist, title) {
);
const titleOnlyMatch = results => results.find(t => normalizeTitle(t.trackName) === normT);
// Fetch both in parallel — JP for correct Japanese titles/artwork, US for English genre names
const [jpResults, usResults] = await Promise.all([fetchItunes('jp'), fetchItunes('us')]);
let match = strictMatch(jpResults);
// titleOnlyMatch (no artist check) is too permissive for Japanese titles/artists —
// common anime/OST titles exist on both JP and US stores under different artists.
// Only use it as a fallback when neither title nor artist contains Japanese characters.
// US store only — one consistent naming source (English/romaji) across search + download, so the
// same artist always resolves the same way instead of "sometimes Japanese, sometimes romaji". A
// single request instead of JP+US also halves the download's iTunes calls (helps the rate limit).
const usResults = await fetchItunes('us');
const JP_RE = /[぀-ヿ㐀-䶿一-鿿]/;
const isJpSearch = JP_RE.test(normT) || JP_RE.test(normA);
let usMatch = strictMatch(usResults) || (!isJpSearch && titleOnlyMatch(usResults));
if (!match) match = usMatch;
// titleOnlyMatch (no artist check) is too permissive when the title is Japanese — common anime/
// OST titles exist under different artists — so only use it as a fallback for non-Japanese titles.
const match = strictMatch(usResults) || (!isJpSearch && titleOnlyMatch(usResults));
if (!match) return {};
// For non-Japanese songs, take the NAMES from the US store: the JP store returns katakana-
// localized artist / album-artist names for Western artists (e.g. "DJスネイク" for DJ Snake),
// which would otherwise become the album_artist tag and the on-disk folder. Japanese songs keep
// the JP names (correct kanji). Numeric fields (year, track#, duration) are store-agnostic.
const naming = (!isJpSearch && usMatch) ? usMatch : match;
// JP genre names are localized (e.g. イージーリスニング); prefer US genre, map JP→EN as fallback
const rawGenre = (usMatch || match).primaryGenreName;
const naming = match;
const rawGenre = match.primaryGenreName;
const genre = rawGenre ? toEnglishGenre(rawGenre) : undefined;
return {
album: naming.collectionName || '',
@@ -225,7 +219,7 @@ async function fetchItunesTracks(collectionId) {
async function searchItunesAlbumTracks(artist, album) {
return new Promise(resolve => {
const q = encodeURIComponent(`${artist} ${album}`);
https.get(`https://itunes.apple.com/search?term=${q}&media=music&entity=album&limit=5&country=jp&explicit=Yes`, res => {
https.get(`https://itunes.apple.com/search?term=${q}&media=music&entity=album&limit=5&country=us&explicit=Yes`, res => {
let d = '';
res.on('data', c => d += c);
res.on('end', () => {