Hardened the indexing for blink-182

This commit is contained in:
Connor Johnstone
2026-03-03 13:30:51 -05:00
parent f5f0273853
commit 60a1d704dd
4 changed files with 104 additions and 26 deletions

View File

@@ -79,6 +79,30 @@ impl LastfmClient {
Ok(Some(body))
}
/// Normalize Unicode hyphens to ASCII and fetch by artist name.
fn fetch_by_name(
&self,
method: &str,
artist_name: Option<&str>,
extra_params: &str,
) -> Result<Option<String>, Box<dyn std::error::Error>> {
if let Some(name) = artist_name {
let name = name.replace('\u{2010}', "-")
.replace('\u{2011}', "-")
.replace('\u{2012}', "-")
.replace('\u{2013}', "-")
.replace('\u{2014}', "-")
.replace('\u{2015}', "-");
let encoded = urlencoding::encode(&name);
let url = format!(
"{}?method={}&artist={}&api_key={}{}&format=json",
BASE_URL, method, encoded, self.api_key, extra_params
);
return self.fetch_or_none(&url);
}
Ok(None)
}
/// Try fetching by MBID first, fall back to artist name.
fn fetch_with_fallback(
&self,
@@ -95,19 +119,7 @@ impl LastfmClient {
return Ok(Some(body));
}
// Fall back to artist name
if let Some(name) = artist_name {
let encoded = urlencoding::encode(name);
let url = format!(
"{}?method={}&artist={}&api_key={}{}&format=json",
BASE_URL, method, encoded, self.api_key, extra_params
);
if let Some(body) = self.fetch_or_none(&url)? {
return Ok(Some(body));
}
}
Ok(None)
self.fetch_by_name(method, artist_name, extra_params)
}
pub fn get_similar_artists(
@@ -125,7 +137,7 @@ impl LastfmClient {
};
let resp: SimilarArtistsResponse = serde_json::from_str(&body)?;
Ok(resp
let results: Vec<SimilarArtist> = resp
.similarartists
.artist
.into_iter()
@@ -137,7 +149,29 @@ impl LastfmClient {
match_score: a.match_score.parse().unwrap_or(0.0),
}
})
.collect())
.collect();
// MBID lookup can return valid but empty results; retry with name
if results.is_empty() {
if let Some(body) = self.fetch_by_name("artist.getSimilar", artist_name, "&limit=500")? {
let resp: SimilarArtistsResponse = serde_json::from_str(&body)?;
return Ok(resp
.similarartists
.artist
.into_iter()
.map(|a| {
let mbid = a.mbid.filter(|s| !s.is_empty());
SimilarArtist {
name: a.name,
mbid,
match_score: a.match_score.parse().unwrap_or(0.0),
}
})
.collect());
}
}
Ok(results)
}
pub fn get_top_tracks(
@@ -155,7 +189,7 @@ impl LastfmClient {
};
let resp: TopTracksResponse = serde_json::from_str(&body)?;
Ok(resp
let results: Vec<TopTrack> = resp
.toptracks
.track
.into_iter()
@@ -165,6 +199,25 @@ impl LastfmClient {
playcount: t.playcount.parse().unwrap_or(0),
listeners: t.listeners.parse().unwrap_or(0),
})
.collect())
.collect();
if results.is_empty() {
if let Some(body) = self.fetch_by_name("artist.getTopTracks", artist_name, "&limit=1000")? {
let resp: TopTracksResponse = serde_json::from_str(&body)?;
return Ok(resp
.toptracks
.track
.into_iter()
.map(|t| TopTrack {
name: t.name,
mbid: t.mbid.filter(|s| !s.is_empty()),
playcount: t.playcount.parse().unwrap_or(0),
listeners: t.listeners.parse().unwrap_or(0),
})
.collect());
}
}
Ok(results)
}
}