fix: resolve birth country from area hierarchy instead of MB country field

Add resolve_area_country() that walks the MB area hierarchy up to
the country level (e.g., Frankfurt -> Hessen -> Germany).

Use it in v2_musicbrainz_get_artist_metadata to get the real birth
country instead of MB's "country" field (which is where the artist
is active, not where they were born).

Hans Zimmer now shows "Frankfurt am Main, Germany" and clicking
the location shows German composers, not American ones.

cc
This commit is contained in:
vicrodh committed 2026-03-31 17:17:01 -06:00
1 parent 305cffa08e
commit 1953774d03
2 files changed
+73 -1

No files matched your search

@@ -651,6 +651,64 @@ impl MusicBrainzClient {
Ok(None)
}
/// 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"
///
/// Returns None if the country cannot be determined within max_hops.
pub async fn resolve_area_country(
&self,
area_id: &str,
) -> IntegrationResult<Option<String>> {
let mut current_id = area_id.to_string();
let max_hops = 5;
for _hop in 0..max_hops {
let detail = self.get_area_with_relations(&current_id).await?;
// If current area IS a country, return it
if detail
.area_type
.as_deref()
.map(|t| t.eq_ignore_ascii_case("country"))
.unwrap_or(false)
{
return Ok(Some(detail.name));
}
// Find "part of" parent
let parent = detail
.relations
.as_ref()
.and_then(|rels| {
rels.iter()
.find(|rel| {
rel.relation_type == "part of"
&& rel.direction.as_deref() == Some("backward")
})
.and_then(|rel| rel.area.as_ref())
});
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()));
}
current_id = p.id.clone();
}
None => return Ok(None),
}
}
Ok(None)
}
// ============ Internal Helpers ============
async fn check_enabled(&self) -> IntegrationResult<()> {
+15 -1
View File
@@ -10145,7 +10145,21 @@ pub async fn v2_musicbrainz_get_artist_metadata(
drop(client);
// Extract metadata using the location discovery module (now uses V2 types)
let metadata = crate::musicbrainz::location_discovery::extract_metadata(&artist);
let mut metadata = crate::musicbrainz::location_discovery::extract_metadata(&artist);
// Resolve real country from begin_area hierarchy (MB's "country" field is
// where the artist is active, not where they were born/formed)
if let Some(ref mut loc) = metadata.location {
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);
}
}
}
}
// Cache to V2 cache
{