Added artist bio and art stuff
This commit is contained in:
@@ -5,8 +5,8 @@ use tokio::time::{Duration, Instant};
|
||||
use crate::cleaning::escape_lucene;
|
||||
use crate::error::{TagError, TagResult};
|
||||
use crate::provider::{
|
||||
ArtistSearchResult, DiscographyEntry, MetadataProvider, RecordingDetails, RecordingMatch,
|
||||
ReleaseGroupEntry, ReleaseMatch, ReleaseRef, ReleaseTrack,
|
||||
ArtistInfo, ArtistSearchResult, ArtistUrl, DiscographyEntry, MetadataProvider,
|
||||
RecordingDetails, RecordingMatch, ReleaseGroupEntry, ReleaseMatch, ReleaseRef, ReleaseTrack,
|
||||
};
|
||||
|
||||
const BASE_URL: &str = "https://musicbrainz.org/ws/2";
|
||||
@@ -61,6 +61,36 @@ impl MusicBrainzClient {
|
||||
let resp: MbArtistLookup = self.get_json(&url).await?;
|
||||
Ok((resp.name, resp.disambiguation.filter(|s| !s.is_empty())))
|
||||
}
|
||||
|
||||
/// Look up detailed artist info by MBID, including URLs and metadata.
|
||||
pub async fn get_artist_info(&self, mbid: &str) -> TagResult<ArtistInfo> {
|
||||
let url = format!("{BASE_URL}/artist/{mbid}?inc=url-rels&fmt=json");
|
||||
let resp: MbArtistFull = self.get_json(&url).await?;
|
||||
|
||||
let begin_year = resp.life_span
|
||||
.and_then(|ls| ls.begin)
|
||||
.and_then(|d| d.split('-').next().map(String::from));
|
||||
|
||||
let urls = resp.relations
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter_map(|rel| {
|
||||
rel.url.map(|u| ArtistUrl {
|
||||
url: u.resource,
|
||||
link_type: rel.relation_type,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(ArtistInfo {
|
||||
name: resp.name,
|
||||
disambiguation: resp.disambiguation.filter(|s| !s.is_empty()),
|
||||
country: resp.country.filter(|s| !s.is_empty()),
|
||||
artist_type: resp.artist_type,
|
||||
begin_year,
|
||||
urls,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MetadataProvider for MusicBrainzClient {
|
||||
@@ -334,6 +364,35 @@ struct MbArtistLookup {
|
||||
disambiguation: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MbArtistFull {
|
||||
name: String,
|
||||
disambiguation: Option<String>,
|
||||
country: Option<String>,
|
||||
#[serde(rename = "type")]
|
||||
artist_type: Option<String>,
|
||||
#[serde(rename = "life-span")]
|
||||
life_span: Option<MbLifeSpan>,
|
||||
relations: Option<Vec<MbRelation>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MbLifeSpan {
|
||||
begin: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MbRelation {
|
||||
#[serde(rename = "type")]
|
||||
relation_type: String,
|
||||
url: Option<MbRelationUrl>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MbRelationUrl {
|
||||
resource: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MbRecordingSearchResponse {
|
||||
recordings: Vec<MbRecordingResult>,
|
||||
|
||||
@@ -50,6 +50,24 @@ pub struct RecordingDetails {
|
||||
pub secondary_artists: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
/// Detailed artist info from a direct MBID lookup.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ArtistInfo {
|
||||
pub name: String,
|
||||
pub disambiguation: Option<String>,
|
||||
pub country: Option<String>,
|
||||
pub artist_type: Option<String>,
|
||||
pub begin_year: Option<String>,
|
||||
pub urls: Vec<ArtistUrl>,
|
||||
}
|
||||
|
||||
/// An external URL linked to an artist on MusicBrainz.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ArtistUrl {
|
||||
pub url: String,
|
||||
pub link_type: String,
|
||||
}
|
||||
|
||||
/// An artist match from a search query.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ArtistSearchResult {
|
||||
|
||||
Reference in New Issue
Block a user