A wrapper around the musicbrainz API
![MusicBrainz] Rust
[![Latest Version]][crates.io] [![Build Status]][Action]
[Build Status]: https://github.com/RustyNova016/musicbrainzrs/actions/workflows/rustcheck.yaml/badge.svg [Action]: https://github.com/RustyNova016/musicbrainzrs/actions/workflows/rustcheck.yaml [Latest Version]: https://img.shields.io/crates/v/musicbrainz_rs.svg [crates.io]: https://www.crates.io/crates/musicbrainz_rs [MusicBrainz]: https://static.metabrainz.org/MB/header-logo-1f7dc2a.svg
MusicBrainz rust is a utility crate for the the MusicBrainz API.
you may be looking for :
Usage
You can choose to use either the default async client or a blocking one.
async client:
musicbrainz_rs = "0.9.0"
blocking client:
musicbrainz_rs = { version = "0.9.0", default-features = false, features = ["blocking"] }
Features
Note: All the example below use the blocking feature for the sake of conciseness.
Fetch query
To perform a lookups via fetch queries, you need to import the Fetch trait. This can be done using musicbrainz_rs::prelude
use musicbrainz_rs::entity::artist;
use musicbrainz_rs::entity::artist::*;
use musicbrainz_rs::prelude::*;
fn main() { let nirvana = Artist::fetch() .id("5b11f4ce-a62d-471e-81fc-a69a8278c7da") .execute();
asserteq!(nirvana.unwrap().name, "Nirvana".tostring()); }
Include parameters
You can also use includes to get more detail about a resource :
Every Musicbrainz resource has allowed include parameters.
use musicbrainz_rs::entity::label::*;
use musicbrainz_rs::prelude::*;
fn main() { let ninja_tune = Label::fetch() .id("dc940013-b8a8-4362-a465-291026c04b42") .with_tags() .with_ratings() .execute() .unwrap();
assert!(ninja_tune .tags .unwrap() .iter() .any(|tag| tag.name == "independent"));
assert!(ninjatune.rating.issome()); }
CoverArt query
Release and ReleaseGroup entities in MusicBrainz also allow you to make CoverArt queries on them:
use musicbrainz_rs::entity::release::*;
use musicbrainz_rs::entity::CoverartResponse;
use musicbrainz_rs::prelude::*;
use musicbrainz_rs::FetchCoverart;
fn main() { // CoverArt Query for a Release. let inuterocoverart = Release::fetch_coverart() .id("76df3287-6cda-33eb-8e9a-044b5e15ffdd") .execute() .expect("Unable to get cover art");
if let CoverartResponse::Json(coverart) = inuterocoverart { assert!(!coverart.images[0].back); assert_eq!( coverart.images[0].image, "http://coverartarchive.org/release/76df3287-6cda-33eb-8e9a-044b5e15ffdd/829521842.jpg" ); } else { assert!(false); }
let in_utero = Release::fetch() .id("76df3287-6cda-33eb-8e9a-044b5e15ffdd") .execute() .expect("Unable to get release");
// Calling get_coverart() method on an already fetched Release entity. let inuterocoverart = in_utero .get_coverart() .execute() .expect("Unable to get coverart");
if let CoverartResponse::Json(coverart) = inuterocoverart { assert!(!coverart.images[0].back); assert_eq!( coverart.images[0].image, "http://coverartarchive.org/release/76df3287-6cda-33eb-8e9a-044b5e15ffdd/829521842.jpg" ); } else { assert!(false); }
// CoverArt Query Builder to fetch a specific resource. let inutero500pxfrontcoverart = Release::fetch_coverart() .id("76df3287-6cda-33eb-8e9a-044b5e15ffdd") .res_500() .back() .execute() .expect("Unable to get cover art");
if let CoverartResponse::Url(coverarturl) = inutero500pxfront_coverart { println!("{}", coverart_url); } else { assert!(false); } }
Browse query
Use musicbrainzrs::Browse or bring it in scope using musicbrainzrs::prelude to perform a browse query. Just like Include every muscibrainz resource has allowable linked entities for such queries.
use musicbrainz_rs::entity::artist;
use musicbrainz_rs::entity::artist::Artist;
use musicbrainz_rs::prelude::*;
fn main() { let artistsoninuterorelease = Artist::browse() .by_release("18d4e9b4-9247-4b44-914a-8ddec3502103") .execute();
let artistsoninuterorelease = artistsoninuterorelease.unwrap();
artistsoninuterorelease .entities .iter() .for_each(|artist| println!("{:?}", artist.name)); }
Search query
Use musicbrainzrs::Search to perform a search query.
use musicbrainz_rs::entity::artist::Artist;
use musicbrainz_rs::prelude::*;
fn main() { musicbrainzrs::config::setuseragent("myawesome_app/1.0");
let query = Artist::query_builder() .artist("Miles Davis") .and() .country("US") .build();
let query_result = Artist::search(query).execute().unwrap(); let queryresult: Vec<String> = queryresult.entities .iter() .map(|artist| artist.name.clone()).collect();
assert!(queryresult.contains(&"Miles Davis".tostring())); assert!(queryresult.contains(&"Miles Davis Quintet".tostring())); }
Custom user agent
By default, the user agent will be set to musicbrainz_rs/<version>. To comply with MB's API rules, you should set this to a custom string that identifies your application.
You can see how here
Rate limit
By default, a rate limiter of 1req/sec is implemented according to MB's policy. This allows to fearlessly send heaps of requests without worrying about DOS'ing MusicBrainz. This feature is only available bundled with the async feature, as it require an async runtime.
Examples
To see what is currently implemented in the crate you can look at the tests directory.
You can run examples with cargo run --example example_name
Cargo Features
Async:
sync: Enable the sync apiasync: Enable the async api (Sync and Async aren't mutually exclusive)
native_tls: Use the system's native TLS. By default, Rustls is used to not have to depend on the system's tlsrustls(default): Use rustls as tls provider.rate_limit: Add a rate limiter to the requests, using thegovernorcrate. Please note that it only affectasyncvariants of functions, asgovernoris made to work in async functions only. If you know a ratelimit crate that does both sync and async, feel free to submit an issue
backtrace: Enable error backtracestracing: Enable tracinghotpath,hotpath-alloc,hotpath-off: Enablehotpathdebuging / perf analysis.
extras: Extra non api related utilities that still fits musicbrainzlegacyserialize: Enable legacy model serialization. Use an old version of the serializer for compatibility with musicbrainzrs < 0.8.0.
API changes and versioning
Versioning is based on rust poilicy, and independant of api changes. This means if the bindings need a breaking changes, the major version will be bumped. Otherwise, the patch version will be bumped
MSRV
The Minimum Supported Rust Version for the crate is 1.85.0. Bumps to the msrv are not considered breaking as cargo won't pull the new version (thanks resolver v3).
Contributing
All contributions are welcome, if find a bug or have a feature request don't hesitate to open an issue! You can check the documentation folder for more information if needed
Credits
Most of this crate documentation is taken from the official MusicBrainz doc, thanks to the MetaBrainz Foundation and its sponsors and supporters. Cover Art provided by the Cover Art Archive.