musichoard/examples/musicbrainz_api/search.rs

149 lines
3.8 KiB
Rust

use std::{num::ParseIntError, str::FromStr};
use musichoard::{
collection::{album::AlbumDate, musicbrainz::Mbid},
external::musicbrainz::{
api::{
search::{SearchArtistRequest, SearchReleaseGroupRequest},
MusicBrainzClient,
},
http::MusicBrainzHttp,
},
};
use structopt::StructOpt;
use uuid::Uuid;
const USER_AGENT: &str = concat!(
"MusicHoard---examples---musicbrainz-api---search/",
env!("CARGO_PKG_VERSION"),
" ( musichoard@thenineworlds.net )"
);
#[derive(StructOpt)]
struct Opt {
#[structopt(subcommand)]
entity: OptEntity,
}
#[derive(StructOpt)]
enum OptEntity {
#[structopt(about = "Search artist")]
Artist(OptArtist),
#[structopt(about = "Search release group")]
ReleaseGroup(OptReleaseGroup),
}
#[derive(StructOpt)]
struct OptArtist {
#[structopt(help = "Artist search string")]
string: String,
}
#[derive(StructOpt)]
enum OptReleaseGroup {
#[structopt(about = "Search by artist MBID, title(, and date)")]
Title(OptReleaseGroupTitle),
#[structopt(about = "Search by release group MBID")]
Rgid(OptReleaseGroupRgid),
}
#[derive(StructOpt)]
struct OptReleaseGroupTitle {
#[structopt(help = "Release group's artist MBID")]
arid: Uuid,
#[structopt(help = "Release group title")]
title: String,
#[structopt(help = "Release group release date")]
date: Option<Date>,
}
#[derive(StructOpt)]
struct OptReleaseGroupRgid {
#[structopt(help = "Release group MBID")]
rgid: Uuid,
}
struct Date(AlbumDate);
impl FromStr for Date {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut elems = s.split('-');
let elem = elems.next();
let year = elem.map(|s| s.parse()).transpose()?;
let elem = elems.next();
let month = elem.map(|s| s.parse()).transpose()?;
let elem = elems.next();
let day = elem.map(|s| s.parse()).transpose()?;
Ok(Date(AlbumDate::new(year, month, day)))
}
}
impl From<Date> for AlbumDate {
fn from(value: Date) -> Self {
value.0
}
}
fn main() {
let opt = Opt::from_args();
println!("USER_AGENT: {USER_AGENT}");
let http = MusicBrainzHttp::new(USER_AGENT).expect("failed to create API client");
let mut client = MusicBrainzClient::new(http);
match opt.entity {
OptEntity::Artist(opt_artist) => {
let query = SearchArtistRequest::new().string(&opt_artist.string);
println!("Query: {query}");
let matches = client
.search_artist(query)
.expect("failed to make API call");
println!("{matches:#?}");
}
OptEntity::ReleaseGroup(opt_release_group) => {
let arid: Mbid;
let date: AlbumDate;
let title: String;
let rgid: Mbid;
let query = match opt_release_group {
OptReleaseGroup::Title(opt_title) => {
arid = opt_title.arid.into();
date = opt_title.date.map(Into::into).unwrap_or_default();
title = opt_title.title;
SearchReleaseGroupRequest::new()
.arid(&arid)
.and()
.release_group(&title)
.and()
.first_release_date(&date)
}
OptReleaseGroup::Rgid(opt_rgid) => {
rgid = opt_rgid.rgid.into();
SearchReleaseGroupRequest::new().rgid(&rgid)
}
};
println!("Query: {query}");
let matches = client
.search_release_group(query)
.expect("failed to make API call");
println!("{matches:#?}");
}
}
}