fix(search): trim leading aesthetic punctuation in artist lookups

Artists like ".diedlonely" (leading dot, †, ✝, _ …) weren't surfaced by iTunes,
so the download's metadata lookup fell through to a titleOnly match — grabbing a
same-titled track by another artist (e.g. the "In the Bleak Midwinter" Christmas
carol: Holiday genre, 176s single) and steering the YouTube search to the wrong
(slowed) version.

- backend/metadata.js: strip leading non-alphanumeric from the search artist and
  the first-word comparison so the real artist matches (and the right album/genre/
  duration are used).
- android ExploreViewModel: strip leading symbols from the search term so the
  Explore tab finds these artists.

Keeps the original name for display/storage — only the search/compare is trimmed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-07-03 22:34:44 +02:00
1 parent d50e22b62d
commit 1775ec5b9b
2 files changed
+9 -3

No files matched your search

@@ -102,10 +102,13 @@ class ExploreViewModel(app: Application) : AndroidViewModel(app) {
}
private fun search(q: String) {
// Strip leading aesthetic punctuation (".diedlonely", "†…") so iTunes actually surfaces the
// artist instead of nothing. Falls back to the raw query if it was only symbols.
val term = q.trimStart { !it.isLetterOrDigit() }.trim().ifBlank { q }
viewModelScope.launch {
_state.value = _state.value.copy(isSearching = true, error = null)
try {
val resp = ItunesClient.search(q)
val resp = ItunesClient.search(term)
val results = resp.results
_state.value = _state.value.copy(
artists = results.filter { it.wrapperType == "artist" },
+5 -2
View File
@@ -148,7 +148,10 @@ async function lookupItunesTrackMeta(artist, title) {
// 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 searchTitle = baseTitle !== title ? baseTitle : title;
const searchArtist = artist.split(/[;,&]/)[0].trim();
// Strip leading aesthetic punctuation many artists use (".diedlonely", "†", "✝", "_x")
// so the iTunes search actually surfaces them instead of a same-titled track by someone else.
const stripLeadSym = s => (s || '').replace(/^[^\p{L}\p{N}]+/u, '').trim();
const searchArtist = stripLeadSym(artist.split(/[;,&]/)[0].trim());
const fetchItunes = (country) => new Promise((resolve, reject) => {
const url = `https://itunes.apple.com/search?term=${encodeURIComponent(searchArtist + ' ' + searchTitle)}&media=music&entity=musicTrack&limit=10&country=${country}&explicit=Yes`;
https.get(url, res => {
@@ -159,7 +162,7 @@ async function lookupItunesTrackMeta(artist, title) {
const normT = normalizeTitle(title);
const normA = (searchArtist || '').toLowerCase().trim();
// Split by space OR comma/semicolon/slash so "VXLLAIN, iGRES" → "vxllain" not "vxllain,"
const firstWord = s => (s || '').toLowerCase().split(/[\s,;/]/)[0];
const firstWord = s => stripLeadSym((s || '').toLowerCase()).split(/[\s,;/]/)[0];
const strictMatch = results => results.find(t =>
normalizeTitle(t.trackName) === normT && firstWord(t.artistName) === firstWord(normA)
);