MCPcopy Index your code
hub / github.com/RustyNova016/musicbrainz_rs

github.com/RustyNova016/musicbrainz_rs @v0.13.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.13.0 ↗ · + Follow
567 symbols 1,561 edges 175 files 28 documented · 5%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

MusicBrainz Rust  

Latest Version Build Status codecov GitHub tag (latest by date) Conventional Commits License

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();

    assert_eq!(nirvana.unwrap().name, "Nirvana".to_string());
}

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!(ninja_tune.rating.is_some());
}

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 in_utero_coverart = Release::fetch_coverart()
        .id("76df3287-6cda-33eb-8e9a-044b5e15ffdd")
        .execute()
        .expect("Unable to get cover art");

    if let CoverartResponse::Json(coverart) = in_utero_coverart {
        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 in_utero_coverart = in_utero
        .get_coverart()
        .execute()
        .expect("Unable to get coverart");

    if let CoverartResponse::Json(coverart) = in_utero_coverart {
        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 in_utero_500px_front_coverart = Release::fetch_coverart()
        .id("76df3287-6cda-33eb-8e9a-044b5e15ffdd")
        .res_500()
        .back()
        .execute()
        .expect("Unable to get cover art");

    if let CoverartResponse::Url(coverart_url) = in_utero_500px_front_coverart {
        println!("{}", coverart_url);
    } else {
        assert!(false);
    }
}

Browse query

Use musicbrainz_rs::Browse or bring it in scope using musicbrainz_rs::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 artists_on_in_utero_release = Artist::browse()
        .by_release("18d4e9b4-9247-4b44-914a-8ddec3502103")
        .execute();

    let artists_on_in_utero_release = artists_on_in_utero_release.unwrap();

    artists_on_in_utero_release
        .entities
        .iter()
        .for_each(|artist| println!("{:?}", artist.name));
}

Search query

Use musicbrainz_rs::Search to perform a search query.

use musicbrainz_rs::entity::artist::Artist;
use musicbrainz_rs::prelude::*;

fn main() {
    musicbrainz_rs::config::set_user_agent("my_awesome_app/1.0");

    let query = Artist::query_builder()
        .artist("Miles Davis")
        .and()
        .country("US")
        .build();

    let query_result = Artist::search(query).execute().unwrap();
    let query_result: Vec<String> = query_result.entities
        .iter()
        .map(|artist| artist.name.clone()).collect();

    assert!(query_result.contains(&"Miles Davis".to_string()));
    assert!(query_result.contains(&"Miles Davis Quintet".to_string()));
}

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 api - async: Enable the async api (Sync and Async aren't mutually exclusive)

Fetching: - native_tls: Use the system's native TLS. By default, Rustls is used to not have to depend on the system's tls - rustls (default): Use rustls as tls provider. - rate_limit: Add a rate limiter to the requests, using the governor crate. Please note that it only affect async variants of functions, as governor is 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

Debuging: - backtrace: Enable error backtraces - tracing: Enable tracing - hotpath, hotpath-alloc, hotpath-off: Enable hotpath debuging / perf analysis.

Others: - extras: Extra non api related utilities that still fits musicbrainz - legacy_serialize: Enable legacy model serialization. Use an old version of the serializer for compatibility with musicbrainz_rs < 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.

Extension points exported contracts — how you extend this code

APIPath (Interface)
Provide the entity HTTP api path, do not use this trait directly [15 implementers]
src/lib.rs
Fetch (Interface)
Implemented by all fetchable entities (see [`FetchQuery`]) [13 implementers]
src/api/fetch_query.rs
Browsable (Interface)
(no doc) [11 implementers]
src/entity/mod.rs
NullEq (Interface)
(no doc) [3 implementers]
tests/test_framework/null_eq.rs
Search (Interface)
Implemented by all searchable entities (see [`SearchQuery`]) [12 implementers]
src/api/search_query.rs
Searchable (Interface)
(no doc) [15 implementers]
src/entity/search.rs
Browse (Interface)
Implemented by all browsable entities (see [`BrowseQuery`]) [11 implementers]
src/api/browse_query.rs
FetchCoverart (Interface)
Implemented by all fetchable coverart entities (see [`FetchCoverartQuery`])
src/api/coverart_query.rs

Core symbols most depended-on inside this repo

id
called by 253
src/api/fetch_query.rs
execute
called by 171
src/api/fetch_query.rs
execute_async
called by 168
src/api/fetch_query.rs
as_api_request
called by 13
src/api/fetch_query.rs
parse
called by 11
src/api/parser/mod.rs
check_fetch_query
called by 11
tests/test_framework/mod.rs
compare_dates
called by 8
src/entity/date_string.rs
as_str
called by 8
src/entity/mod.rs

Shape

Function 360
Method 94
Class 69
Enum 36
Interface 8

Languages

Rust100%

Modules by API surface

tests/async_tests/artist/artist_includes.rs18 symbols
tests/blocking_tests/artist/artist_includes.rs17 symbols
src/api/coverart_query.rs17 symbols
src/entity/release.rs14 symbols
tests/blocking_tests/release/release_includes.rs13 symbols
tests/blocking_tests/api/fetch.rs13 symbols
tests/async_tests/release/release_includes.rs13 symbols
src/entity/mod.rs13 symbols
tests/async_tests/recording/recording_includes.rs12 symbols
tests/async_tests/api/fetch.rs12 symbols
tests/blocking_tests/recording/recording_includes.rs11 symbols
tests/blocking_tests/label/label_includes.rs11 symbols

For agents

$ claude mcp add musicbrainz_rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page