fix: resolve correct artist and country for MusicBrainz metadata

Three fixes:
- resolve_artist now prefers exact name matches over highest score,
  fixing "The Warning" resolving to "Fates Warning" (score=100 but
  wrong name vs score=97 exact match)
- resolve_area_country now returns ISO country code alongside name,
  fixing flag display (was showing US flag for German artists)
- country_code updated in location metadata for correct flag rendering

cc
This commit is contained in:
vicrodh committed 2026-03-31 17:23:00 -06:00
1 parent 1953774d03
commit 1e019becfd
2 files changed
+39 -12

No files matched your search

@@ -263,10 +263,25 @@ impl MusicBrainzClient {
}
/// Resolve an artist to get MusicBrainz ID
///
/// Prefers exact name matches over highest score to avoid disambiguation
/// issues (e.g., multiple artists named "The Warning").
pub async fn resolve_artist(&self, name: &str) -> IntegrationResult<Option<ResolvedArtist>> {
let response = self.search_artist(name, 5).await?;
let response = self.search_artist(name, 10).await?;
if let Some(artist) = response.artists.first() {
if response.artists.is_empty() {
return Ok(None);
}
// Prefer exact name match (case-insensitive)
let target = name.trim().to_lowercase();
let best = response
.artists
.iter()
.find(|a| a.name.trim().to_lowercase() == target && a.score.unwrap_or(0) >= 90)
.or_else(|| response.artists.first());
if let Some(artist) = best {
let confidence = MatchConfidence::from_score(artist.score);
return Ok(Some(ResolvedArtist {
@@ -653,14 +668,14 @@ impl MusicBrainzClient {
/// Resolve the country that an area belongs to by walking up the hierarchy.
///
/// Frankfurt am Main → Hessen → Germany → returns "Germany"
/// Monterrey → Nuevo León → Mexico → returns "Mexico"
/// Frankfurt am Main → Hessen → Germany → returns ("Germany", Some("de"))
/// Monterrey → Nuevo León → Mexico → returns ("Mexico", Some("mx"))
///
/// Returns None if the country cannot be determined within max_hops.
/// Returns (country_name, country_code_lowercase) or None.
pub async fn resolve_area_country(
&self,
area_id: &str,
) -> IntegrationResult<Option<String>> {
) -> IntegrationResult<Option<(String, Option<String>)>> {
let mut current_id = area_id.to_string();
let max_hops = 5;
@@ -674,7 +689,12 @@ impl MusicBrainzClient {
.map(|t| t.eq_ignore_ascii_case("country"))
.unwrap_or(false)
{
return Ok(Some(detail.name));
let code = detail
.iso_codes
.as_ref()
.and_then(|c| c.first())
.map(|c| c.to_lowercase());
return Ok(Some((detail.name, code)));
}
// Find "part of" parent
@@ -692,13 +712,17 @@ impl MusicBrainzClient {
match parent {
Some(p) => {
// If parent is a country, return it directly
if p.area_type
.as_deref()
.map(|t| t.eq_ignore_ascii_case("country"))
.unwrap_or(false)
{
return Ok(Some(p.name.clone()));
let code = p
.iso_codes
.as_ref()
.and_then(|c| c.first())
.map(|c| c.to_lowercase());
return Ok(Some((p.name.clone(), code)));
}
current_id = p.id.clone();
}
+6 -3
View File
@@ -10153,9 +10153,12 @@ pub async fn v2_musicbrainz_get_artist_metadata(
if loc.city.is_some() {
if let Some(ref area_id) = loc.area_id {
let client = state.client.lock().await;
if let Ok(Some(real_country)) = client.resolve_area_country(area_id).await {
loc.display_name = format!("{}, {}", loc.display_name, real_country);
loc.country = Some(real_country);
if let Ok(Some((country_name, country_code))) =
client.resolve_area_country(area_id).await
{
loc.display_name = format!("{}, {}", loc.display_name, country_name);
loc.country = Some(country_name);
loc.country_code = country_code;
}
}
}