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:
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(¤t_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<()> {
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user