| Crates.io | moosicbox_music_api |
| lib.rs | moosicbox_music_api |
| version | 0.1.4 |
| created_at | 2024-10-04 15:12:04.301137+00 |
| updated_at | 2025-07-21 19:21:49.099+00 |
| description | MoosicBox music API package |
| homepage | |
| repository | https://github.com/MoosicBox/MoosicBox |
| max_upload_size | |
| id | 1396684 |
| size | 144,494 |
A unified API abstraction layer for music services in the MoosicBox ecosystem. This package provides standardized interfaces and implementations for accessing music metadata, search functionality, and authentication across different music streaming services.
Add this to your Cargo.toml:
[dependencies]
moosicbox_music_api = "0.1.1"
use moosicbox_music_api::{MusicApi, SearchQuery, SearchResults};
use async_trait::async_trait;
#[async_trait]
impl MusicApi for MyMusicService {
async fn search(&self, query: &SearchQuery) -> Result<SearchResults, ApiError> {
// Implement search functionality
let results = self.perform_search(query).await?;
Ok(SearchResults::from(results))
}
async fn get_artist(&self, id: &str) -> Result<Artist, ApiError> {
// Fetch artist by ID
self.fetch_artist(id).await
}
async fn get_album(&self, id: &str) -> Result<Album, ApiError> {
// Fetch album by ID
self.fetch_album(id).await
}
}
use moosicbox_music_api::{SearchQuery, SearchType, SearchResults};
// Create search query
let query = SearchQuery::new("Pink Floyd")
.with_types(vec![SearchType::Artist, SearchType::Album])
.with_limit(20)
.with_offset(0);
// Execute search
let results = music_api.search(&query).await?;
// Process results
for artist in results.artists {
println!("Artist: {} ({})", artist.name, artist.id);
}
for album in results.albums {
println!("Album: {} by {} ({})", album.title, album.artist, album.id);
}
use moosicbox_music_api::auth::{AuthMethod, AuthResult};
// Username/password authentication
let auth = AuthMethod::UsernamePassword {
username: "user@example.com".to_string(),
password: "password".to_string(),
};
let result = music_api.authenticate(auth).await?;
match result {
AuthResult::Success(token) => {
println!("Authenticated with token: {}", token);
}
AuthResult::RequiresPolling(poll_info) => {
// Handle polling-based auth (e.g., OAuth device flow)
let token = music_api.poll_for_token(poll_info).await?;
}
AuthResult::Failed(error) => {
eprintln!("Authentication failed: {}", error);
}
}
use moosicbox_music_api::{PagingRequest, PagingResponse};
let mut page_request = PagingRequest::new().with_limit(50);
let mut all_tracks = Vec::new();
loop {
let response: PagingResponse<Track> = music_api
.get_album_tracks("album_id", &page_request)
.await?;
all_tracks.extend(response.items);
if let Some(next_cursor) = response.next_cursor {
page_request = page_request.with_cursor(next_cursor);
} else {
break;
}
}
#[async_trait]
pub trait MusicApi: Send + Sync {
async fn search(&self, query: &SearchQuery) -> Result<SearchResults, ApiError>;
async fn get_artist(&self, id: &str) -> Result<Artist, ApiError>;
async fn get_album(&self, id: &str) -> Result<Album, ApiError>;
async fn get_track(&self, id: &str) -> Result<Track, ApiError>;
async fn get_playlist(&self, id: &str) -> Result<Playlist, ApiError>;
async fn authenticate(&self, method: AuthMethod) -> Result<AuthResult, ApiError>;
}
#[async_trait]
pub trait SearchableApi: MusicApi {
async fn search_artists(&self, query: &str, limit: Option<u32>) -> Result<Vec<Artist>, ApiError>;
async fn search_albums(&self, query: &str, limit: Option<u32>) -> Result<Vec<Album>, ApiError>;
async fn search_tracks(&self, query: &str, limit: Option<u32>) -> Result<Vec<Track>, ApiError>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchQuery {
pub query: String,
pub types: Vec<SearchType>,
pub limit: Option<u32>,
pub offset: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResults {
pub artists: Vec<Artist>,
pub albums: Vec<Album>,
pub tracks: Vec<Track>,
pub playlists: Vec<Playlist>,
pub total_count: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AuthMethod {
UsernamePassword { username: String, password: String },
Token(String),
OAuth { client_id: String, redirect_uri: String },
}
MUSIC_API_TIMEOUT: Request timeout in seconds (default: 30)MUSIC_API_RETRY_COUNT: Number of retry attempts (default: 3)MUSIC_API_CACHE_TTL: Cache time-to-live in seconds (default: 300)api: Enable Actix Web API endpointsauth-poll: Enable polling-based authenticationauth-username-password: Enable username/password authenticationmodels-api-search: Enable search API modelsopenapi: Enable OpenAPI documentation generationWhen the api feature is enabled, the following endpoints are available:
GET /search?q={query}&types={types}&limit={limit}
GET /artists/{id}
GET /albums/{id}
GET /tracks/{id}
GET /playlists/{id}
POST /auth
GET /auth/poll/{poll_id}
use moosicbox_music_api::ApiError;
match music_api.get_artist("invalid_id").await {
Ok(artist) => println!("Found artist: {}", artist.name),
Err(ApiError::NotFound) => println!("Artist not found"),
Err(ApiError::Unauthorized) => println!("Authentication required"),
Err(ApiError::RateLimited) => println!("Rate limit exceeded"),
Err(ApiError::ServiceUnavailable) => println!("Service temporarily unavailable"),
Err(e) => eprintln!("Unexpected error: {}", e),
}
use moosicbox_music_api::MusicApi;
use moosicbox_tidal::TidalApi;
let tidal = TidalApi::new("client_id", "client_secret")?;
let results = tidal.search(&SearchQuery::new("Daft Punk")).await?;
use moosicbox_music_api::MusicApi;
use moosicbox_library::LocalLibraryApi;
let library = LocalLibraryApi::new("/path/to/music")?;
let results = library.search(&SearchQuery::new("Beatles")).await?;
# Run all tests
cargo test
# Run with specific features
cargo test --features "api,auth-poll"
# Run integration tests
cargo test --test integration
Authentication Failures
Search Returns No Results
Rate Limiting
Performance Issues
moosicbox_tidal - Tidal streaming service integrationmoosicbox_qobuz - Qobuz Hi-Res streaming integrationmoosicbox_library - Local music library managementmoosicbox_search - Full-text search functionalitymoosicbox_auth - Authentication and authorizationmoosicbox_paging - Pagination utilities