149 lines
3.8 KiB
Rust
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:#?}");
|
|
}
|
|
}
|
|
}
|