diff --git a/.gitea/workflows/gitea-ci.yaml b/.gitea/workflows/gitea-ci.yaml index 0ec458d..256d779 100644 --- a/.gitea/workflows/gitea-ci.yaml +++ b/.gitea/workflows/gitea-ci.yaml @@ -33,6 +33,7 @@ jobs: --source-dir . --ignore-not-existing --ignore "build.rs" + --ignore "examples/*" --ignore "tests/*" --ignore "src/main.rs" --ignore "src/bin/musichoard-edit.rs" diff --git a/Cargo.toml b/Cargo.toml index cc6e479..52c31d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,5 +44,15 @@ required-features = ["bin", "database-json", "library-beets", "library-beets-ssh name = "musichoard-edit" required-features = ["bin", "database-json"] +[[example]] +name = "musicbrainz-api---lookup-artist-release-groups" +path = "examples/musicbrainz_api/lookup_artist_release_groups.rs" +required-features = ["bin", "musicbrainz-api"] + +[[example]] +name = "musicbrainz-api---search-release-group" +path = "examples/musicbrainz_api/search_release_group.rs" +required-features = ["bin", "musicbrainz-api"] + [package.metadata.docs.rs] all-features = true diff --git a/README.md b/README.md index 77cd1da..457e635 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ grcov codecov/debug/profraw \ --source-dir . \ --ignore-not-existing \ --ignore "build.rs" \ + --ignore "examples/*" \ --ignore "tests/*" \ --ignore "src/main.rs" \ --ignore "src/bin/musichoard-edit.rs" \ diff --git a/examples/musicbrainz_api/lookup_artist_release_groups.rs b/examples/musicbrainz_api/lookup_artist_release_groups.rs new file mode 100644 index 0000000..51a2e86 --- /dev/null +++ b/examples/musicbrainz_api/lookup_artist_release_groups.rs @@ -0,0 +1,36 @@ +#![allow(non_snake_case)] + +use musichoard::{ + external::musicbrainz::api::{client::MusicBrainzApiClient, MusicBrainzApi}, + interface::musicbrainz::{IMusicBrainz, Mbid}, +}; +use structopt::StructOpt; +use uuid::Uuid; + +const USER_AGENT: &str = concat!( + "MusicHoard---examples---musicbrainz-api---lookup-artist-release-groups/", + env!("CARGO_PKG_VERSION"), + " ( musichoard@thenineworlds.net )" +); + +#[derive(StructOpt)] +struct Opt { + #[structopt(help = "Artist MBID to lookup")] + mbid: Uuid, +} + +fn main() { + let opt = Opt::from_args(); + + println!("USER_AGENT: {USER_AGENT}"); + + let client = MusicBrainzApiClient::new(USER_AGENT).expect("failed to create API client"); + let mut api = MusicBrainzApi::new(client); + + let mbid: Mbid = opt.mbid.into(); + let albums = api + .lookup_artist_release_groups(&mbid) + .expect("failed to make API call"); + + println!("{albums:#?}"); +} diff --git a/examples/musicbrainz_api/search_release_group.rs b/examples/musicbrainz_api/search_release_group.rs new file mode 100644 index 0000000..2a84ab7 --- /dev/null +++ b/examples/musicbrainz_api/search_release_group.rs @@ -0,0 +1,74 @@ +#![allow(non_snake_case)] + +use std::{num::ParseIntError, str::FromStr}; + +use musichoard::{ + collection::album::{Album, AlbumDate, AlbumId}, + external::musicbrainz::api::{client::MusicBrainzApiClient, MusicBrainzApi}, + interface::musicbrainz::{IMusicBrainz, Mbid}, +}; +use structopt::StructOpt; +use uuid::Uuid; + +const USER_AGENT: &str = concat!( + "MusicHoard---examples---musicbrainz-api---search-release-group/", + env!("CARGO_PKG_VERSION"), + " ( musichoard@thenineworlds.net )" +); + +#[derive(StructOpt)] +struct Opt { + #[structopt(help = "Release group's artist MBID")] + arid: Uuid, + + #[structopt(help = "Release group title")] + title: String, + + #[structopt(help = "Release group release date")] + date: Option, +} + +struct Date(AlbumDate); + +impl FromStr for Date { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + 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 for AlbumDate { + fn from(value: Date) -> Self { + value.0 + } +} + +fn main() { + let opt = Opt::from_args(); + + println!("USER_AGENT: {USER_AGENT}"); + + let client = MusicBrainzApiClient::new(USER_AGENT).expect("failed to create API client"); + let mut api = MusicBrainzApi::new(client); + + let arid: Mbid = opt.arid.into(); + let date: AlbumDate = opt.date.map(Into::into).unwrap_or_default(); + let album = Album::new(AlbumId::new(opt.title), date, None, vec![]); + let matches = api + .search_release_group(&arid, album) + .expect("failed to make API call"); + + println!("{matches:#?}"); +} diff --git a/src/external/musicbrainz/api/mod.rs b/src/external/musicbrainz/api/mod.rs index 488ff48..3c649b4 100644 --- a/src/external/musicbrainz/api/mod.rs +++ b/src/external/musicbrainz/api/mod.rs @@ -74,7 +74,7 @@ impl IMusicBrainz for MusicBrainzApi { ) -> Result>, Error> { let title = &album.id.title; let arid = arid.uuid().as_hyphenated().to_string(); - let mut query = format!("\"{title}\" AND arid:{arid}"); + let mut query = format!("releasegroup:\"{title}\" AND arid:{arid}"); if let Some(year) = album.date.year { query.push_str(&format!(" AND firstreleasedate:{year}")); @@ -292,7 +292,7 @@ mod tests { let url = format!( "https://musicbrainz.org/ws/2\ /release-group\ - ?query=%22{title}%22+AND+arid%3A{arid}+AND+firstreleasedate%3A{year}", + ?query=releasegroup%3A%22{title}%22+AND+arid%3A{arid}+AND+firstreleasedate%3A{year}", title = "an+album", arid = "00000000-0000-0000-0000-000000000000", year = "1986"