### RSpotify: Client Credentials Flow Example Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates the Client Credentials Flow for server-to-server requests using RSpotify. This flow is suitable for accessing public Spotify data without user authorization. It requires client ID and client secret, which can be loaded from environment variables. ```rust use rspotify::{ model::AlbumId, prelude::*, ClientCredsSpotify, Credentials }; #[tokio::main] async fn main() { // Set credentials from environment variables (RSPOTIFY_CLIENT_ID, RSPOTIFY_CLIENT_SECRET) // or create them explicitly: // let creds = Credentials::new("client_id", "client_secret"); let creds = Credentials::from_env().unwrap(); // Create client and request token let spotify = ClientCredsSpotify::new(creds); spotify.request_token().await.unwrap(); // Fetch album information let album_id = AlbumId::from_uri("spotify:album:0sNOF9WDwhWunNAHPD3Baj").unwrap(); let album = spotify.album(album_id, None).await.unwrap(); println!("Album: {} by {:?}", album.name, album.artists); // Output: Album: Birdy by [SimplifiedArtist { name: "Birdy", ... }] } ``` -------------------------------- ### RSpotify: Authorization Code with PKCE Flow Example Source: https://context7.com/ramsayleung/rspotify/llms.txt Showcases the Authorization Code with PKCE flow, recommended for public clients like mobile apps and SPAs where client secrets cannot be securely stored. This flow enhances security by not requiring a client secret and uses a code verifier mechanism. ```rust use rspotify::{ prelude::*, scopes, AuthCodePkceSpotify, Credentials, OAuth }; #[tokio::main] async fn main() { // PKCE flow only requires client ID (no secret) let creds = Credentials::from_env().unwrap(); // Or: let creds = Credentials::new_pkce("your_client_id"); let oauth = OAuth::from_env(scopes!("user-read-playback-state")).unwrap(); let mut spotify = AuthCodePkceSpotify::new(creds.clone(), oauth.clone()); // Get authorization URL (second parameter is PKCE verifier storage) let url = spotify.get_authorize_url(None).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); // Get current playback state let playback = spotify.current_playback(None, None::>).await.unwrap(); println!("Playback: {:?}", playback); // Token refresh works with PKCE spotify.refresh_token().await.unwrap(); } ``` -------------------------------- ### Playback Control with rspotify Source: https://context7.com/ramsayleung/rspotify/llms.txt Provides examples for controlling Spotify playback, including device management, playback state retrieval, and media control actions like play, pause, skip, seek, volume adjustment, shuffle, repeat, and starting playback of tracks or albums. Requires specific OAuth scopes for reading and modifying playback state. ```rust use rspotify::{ model::{PlayableId, TrackId, AlbumId, RepeatState, PlayContextId}, prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth, }; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!( "user-read-playback-state", "user-modify-playback-state" )).unwrap(); let spotify = AuthCodeSpotify::new(creds, oauth); let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); // Get available devices let devices = spotify.device().await.unwrap(); for device in &devices { println!("Device: {} ({})", device.name, device.id.as_deref().unwrap_or("unknown")); } // Get current playback state let playback = spotify.current_playback(None, None::>).await.unwrap(); if let Some(pb) = playback { println!("Currently playing on: {:?}", pb.device.name); } // Pause playback spotify.pause_playback(None).await.unwrap(); // Resume playback spotify.resume_playback(None, None).await.unwrap(); // Skip to next track spotify.next_track(None).await.unwrap(); // Skip to previous track spotify.previous_track(None).await.unwrap(); // Seek to position (25 seconds) spotify.seek_track(chrono::Duration::try_seconds(25).unwrap(), None).await.unwrap(); // Set volume (0-100) spotify.volume(50, None).await.unwrap(); // Toggle shuffle spotify.shuffle(true, None).await.unwrap(); // Set repeat mode (Track, Context, or Off) spotify.repeat(RepeatState::Track, None).await.unwrap(); // Play specific tracks let track_ids = [ TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap(), TrackId::from_id("1301WleyT98MSxVHPZCA6M").unwrap(), ]; let playable_ids: Vec = track_ids.iter().map(|t| t.as_ref().into()).collect(); spotify.start_uris_playback(playable_ids, None, None, None).await.unwrap(); // Play an album let album_id = AlbumId::from_id("6IcGNaXFRf5Y1jc7QsE9O2").unwrap(); spotify.start_context_playback( PlayContextId::Album(album_id), None, // device_id None, // offset None, // position ).await.unwrap(); // Add track to queue let track = TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap(); spotify.add_item_to_queue(PlayableId::Track(track), None).await.unwrap(); } ``` -------------------------------- ### Search Spotify Catalog with RSpotify Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to search for albums, artists, and tracks using the RSpotify search API. It includes examples of using field filters and market-specific queries. ```rust use rspotify::{ model::{Country, Market, SearchType}, prelude::*, ClientCredsSpotify, Credentials, }; fn main() { let creds = Credentials::from_env().unwrap(); let spotify = ClientCredsSpotify::new(creds); spotify.request_token().unwrap(); let album_query = "album:arrival artist:abba"; let result = spotify.search( album_query, SearchType::Album, None, None, Some(10), None, ).unwrap(); if let rspotify::model::SearchResult::Albums(albums) = result { for album in albums.items { println!("Found album: {} ({})", album.name, album.release_date.unwrap_or_default()); } } let artist_result = spotify.search( "tania bowra", SearchType::Artist, Some(Market::Country(Country::UnitedStates)), None, Some(10), None, ).unwrap(); let track_result = spotify.search( "bohemian rhapsody", SearchType::Track, Some(Market::Country(Country::UnitedStates)), None, Some(5), None, ).unwrap(); } ``` -------------------------------- ### RSpotify: Authorization Code Flow Example Source: https://context7.com/ramsayleung/rspotify/llms.txt Illustrates the Authorization Code Flow for accessing user-specific data. This flow requires user interaction for OAuth consent and is suitable for applications needing to manage user playlists or playback. It uses scopes to define permissions and handles token retrieval via a redirect URI. ```rust use rspotify::{ model::{AdditionalType, Country, Market}, prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth, }; #[tokio::main] async fn main() { // Load credentials from environment let creds = Credentials::from_env().unwrap(); // Define OAuth with required scopes and redirect URI // Set RSPOTIFY_REDIRECT_URI env var or configure explicitly: let oauth = OAuth::from_env(scopes!("user-read-currently-playing")).unwrap(); // Or manually: // let oauth = OAuth { // redirect_uri: "http://localhost:8888/callback".to_string(), // scopes: scopes!("user-read-currently-playing", "user-library-read"), // ..Default::default(), // }; let spotify = AuthCodeSpotify::new(creds, oauth); // Generate authorization URL and prompt user let url = spotify.get_authorize_url(false).unwrap(); // This opens browser and handles callback (requires `cli` feature) spotify.prompt_for_token(&url).await.unwrap(); // Get currently playing track let market = Market::Country(Country::Spain); let additional_types = [AdditionalType::Episode]; let playing = spotify.current_playing(Some(market), Some(&additional_types)).await.unwrap(); if let Some(context) = playing { println!("Now playing: {:?}", context.item); } } ``` -------------------------------- ### Error Handling Example Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to handle various errors that can occur during Spotify API requests, including HTTP errors, JSON parsing errors, and invalid tokens. It also shows how to gracefully handle invalid track IDs. ```APIDOC ## Error Handling Example ### Description This example demonstrates how to handle different types of errors returned by the RSpotify library, including HTTP errors, JSON parsing errors, and invalid token errors. It also shows how to manage invalid input for Spotify IDs. ### Method N/A (Illustrative Example) ### Endpoint N/A (Illustrative Example) ### Parameters N/A ### Request Example N/A ### Response #### Success Response (N/A) N/A #### Error Response Examples - **HTTP Error**: `ClientError::Http(http_err)` - **JSON Parsing Error**: `ClientError::ParseJson(json_err)` - **Invalid Token**: `ClientError::InvalidToken` - **Invalid ID**: `IdError::InvalidId` ```rust use rspotify::{ model::TrackId, prelude::*, ClientCredsSpotify, ClientError, Credentials, }; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let spotify = ClientCredsSpotify::new(creds); if let Err(e) = spotify.request_token().await { match e { ClientError::Http(http_err) => { eprintln!("HTTP error: {:?}", http_err); } ClientError::ParseJson(json_err) => { eprintln!("JSON parsing error: {:?}", json_err); } ClientError::InvalidToken => { eprintln!("Invalid or expired token"); } _ => eprintln!("Other error: {:?}", e), } return; } // Handle invalid IDs gracefully match TrackId::from_id("invalid!@#") { Ok(id) => println!("Valid ID: {}", id.id()), Err(e) => eprintln!("Invalid ID: {:?}", e), // IdError::InvalidId } // Handle API errors match spotify.track(TrackId::from_id("nonexistent123456789012").unwrap(), None).await { Ok(track) => println!("Track: {}", track.name), Err(ClientError::Http(e)) => { eprintln!("API error: {:?}", e); // Usually 404 Not Found } Err(e) => eprintln!("Error: {:?}", e), } } ``` ``` -------------------------------- ### Manage User Library with RSpotify Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to manage the current user's library, including saving and removing tracks and albums, checking for item existence, and retrieving saved albums and followed artists. Requires 'user-library-read', 'user-library-modify', 'user-follow-read', and 'user-follow-modify' scopes. ```rust use rspotify::{ model::{TrackId, AlbumId, ArtistId, LibraryId}, prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth, }; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!( "user-library-read", "user-library-modify", "user-follow-read", "user-follow-modify" )).unwrap(); let spotify = AuthCodeSpotify::new(creds, oauth); let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); // Save tracks to library let track_ids = [ LibraryId::Track(TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap()), LibraryId::Track(TrackId::from_id("1301WleyT98MSxVHPZCA6M").unwrap()), ]; spotify.library_add(track_ids).await.unwrap(); // Check if items are in library let check_ids = [ LibraryId::Track(TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap()), ]; let in_library = spotify.library_contains(check_ids).await.unwrap(); println!("Track in library: {}", in_library[0]); // Remove items from library let remove_ids = [ LibraryId::Album(AlbumId::from_id("6IcGNaXFRf5Y1jc7QsE9O2").unwrap()), ]; spotify.library_remove(remove_ids).await.unwrap(); // Get saved albums with automatic pagination use futures::stream::TryStreamExt; use futures_util::pin_mut; let albums_stream = spotify.current_user_saved_albums(None); pin_mut!(albums_stream); while let Some(saved_album) = albums_stream.try_next().await.unwrap() { println!("Saved album: {}", saved_album.album.name); } // Get followed artists let followed = spotify.current_user_followed_artists(None, Some(20)).await.unwrap(); for artist in followed.items { println!("Following: {}", artist.name); } } ``` -------------------------------- ### Manual Pagination with rspotify Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to manually paginate through results, such as saved tracks, by controlling the offset and limit. This method provides more granular control over data fetching compared to automatic pagination. It requires the `rspotify` crate and `tokio` for asynchronous operations. ```rust use rspotify::{prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth}; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!("user-library-read")).unwrap(); let spotify = AuthCodeSpotify::new(creds, oauth); let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); // Manual pagination with explicit limit and offset let mut offset = 0; let limit = 20; loop { let page = spotify .current_user_saved_tracks_manual(None, Some(limit), Some(offset)) .await .unwrap(); for item in &page.items { println!("{}", item.track.name); } // Check if there are more pages if page.next.is_none() { break; } offset += limit; } } ``` -------------------------------- ### Manage Playlists with RSpotify Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates creating, modifying, and managing playlists, including adding and removing tracks, and changing playlist details. Requires 'playlist-read-private', 'playlist-modify-public', and 'playlist-modify-private' scopes. ```rust use rspotify::{ model::{PlaylistId, TrackId, UserId, PlayableId}, prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth, }; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!( "playlist-read-private", "playlist-modify-public", "playlist-modify-private" )).unwrap(); let spotify = AuthCodeSpotify::new(creds, oauth); let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); // Get current user for playlist creation let me = spotify.me().await.unwrap(); let user_id = UserId::from_id(&me.id).unwrap(); // Create a new playlist let playlist = spotify.user_playlist_create( user_id.as_ref(), "My New Playlist", Some(false), // public Some(false), // collaborative Some("A playlist created with RSpotify"), ).await.unwrap(); println!("Created playlist: {} ({})", playlist.name, playlist.id); // Add tracks to playlist let tracks: Vec = vec![ TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap().into(), TrackId::from_id("1301WleyT98MSxVHPZCA6M").unwrap().into(), ]; spotify.playlist_add_items( playlist.id.as_ref(), tracks.clone(), Some(0), // position at start ).await.unwrap(); // Get playlist items let playlist_id = PlaylistId::from_id("37i9dQZF1DXcBWIGoYBM5M").unwrap(); let items = spotify.playlist_items_manual( playlist_id.as_ref(), None, // fields filter None, // market Some(10), // limit Some(0), // offset ).await.unwrap(); for item in items.items { if let Some(playable) = item.track { match playable { rspotify::model::PlayableItem::Track(track) => { println!("Track: {}", track.name); } rspotify::model::PlayableItem::Episode(episode) => { println!("Episode: {}", episode.name); } } } } // Change playlist details spotify.playlist_change_detail( playlist.id.as_ref(), Some("Updated Playlist Name"), Some(true), // make public Some("Updated description"), None, // collaborative ).await.unwrap(); // Remove tracks from playlist spotify.playlist_remove_all_occurrences_of_items( playlist.id.as_ref(), tracks, None, // snapshot_id ).await.unwrap(); } ``` -------------------------------- ### Configure Token Caching and Refreshing Source: https://context7.com/ramsayleung/rspotify/llms.txt Shows how to initialize an AuthCodeSpotify client with custom configuration to enable persistent token caching and automatic token refreshing. ```rust use rspotify::{prelude::*, scopes, AuthCodeSpotify, Config, Credentials, OAuth}; use std::path::PathBuf; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!("user-read-private")).unwrap(); let config = Config { token_cached: true, token_refreshing: true, cache_path: PathBuf::from(".spotify_cache.json"), pagination_chunks: 50, ..Default::default() }; let spotify = AuthCodeSpotify::with_config(creds, oauth, config); match spotify.read_token_cache(true).await { Ok(Some(token)) => { *spotify.token.lock().await.unwrap() = Some(token); if spotify.token.lock().await.unwrap().as_ref().unwrap().is_expired() { spotify.refresh_token().await.unwrap(); } } _ => { let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); } } let user = spotify.me().await.unwrap(); println!("Logged in as: {}", user.display_name.unwrap_or_default()); } ``` -------------------------------- ### Build RSpotify with reqwest (default) Source: https://github.com/ramsayleung/rspotify/blob/master/README.md This command builds the RSpotify crate using the default 'client-reqwest' feature, which is the standard way to build the project for typical usage. ```sh cargo build ``` -------------------------------- ### Build RSpotify with ureq (blocking interface) Source: https://github.com/ramsayleung/rspotify/blob/master/README.md This command builds RSpotify with the 'client-ureq' and 'ureq-rustls-tls' features, enabling the blocking interface using the 'ureq' HTTP client and Rustls for TLS. This requires specifying a TLS implementation. ```sh cargo build --no-default-features --features client-ureq,ureq-rustls-tls ``` -------------------------------- ### RSpotify Integration Patterns Source: https://context7.com/ramsayleung/rspotify/llms.txt Overview of common integration patterns for RSpotify, highlighting the suitability of different Spotify client types for various application architectures. ```APIDOC ## RSpotify Integration Patterns ### Description RSpotify is versatile for building Spotify-integrated applications. This section outlines common integration patterns based on different authorization flows and client types. ### Patterns 1. **Client Credentials Flow (`ClientCredsSpotify`)**: * **Use Case**: Ideal for accessing read-only public data that does not require user authorization (e.g., artist information, album details, track metadata). * **Security**: Suitable for server-side applications where user context is not needed. 2. **Authorization Code Flow (`AuthCodeSpotify`)**: * **Use Case**: Designed for web applications where users log in via Spotify to grant your application access to their private data and control their playback. * **Security**: Requires a secure backend server to handle the redirect URI and exchange the authorization code for tokens. 3. **Authorization Code Flow with PKCE (`AuthCodePkceSpotify`)**: * **Use Case**: Suitable for public clients like CLI tools, desktop applications, and mobile apps where storing a client secret is not feasible or secure. * **Security**: PKCE (Proof Key for Code Exchange) enhances security for public clients. ### Key Features for Integration * **Automatic Pagination**: Simplifies fetching large datasets by automatically handling subsequent requests for paginated results. * **Synchronous Client (`ureq`)**: Provides a simpler programming model for scripts and tools that do not require asynchronous operations. ``` -------------------------------- ### Perform Synchronous API Requests with ureq Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to use RSpotify in a synchronous context with the ureq client. This is suitable for CLI tools where asynchronous runtimes are not required. ```rust use rspotify::{ model::{Country, Market, SearchType}, prelude::*, ClientCredsSpotify, Credentials, }; fn main() { let creds = Credentials::from_env().unwrap(); let spotify = ClientCredsSpotify::new(creds); spotify.request_token().unwrap(); let result = spotify.search( "Beatles", SearchType::Artist, Some(Market::Country(Country::UnitedStates)), None, Some(5), None, ); match result { Ok(search_result) => println!("Found: {:?}", search_result), Err(err) => eprintln!("Error: {:?}", err), } } ``` -------------------------------- ### Build RSpotify for WASM Source: https://github.com/ramsayleung/rspotify/blob/master/README.md This command builds the RSpotify crate for the 'wasm32-unknown-unknown' target, enabling WebAssembly support. Refer to the documentation for more details on WASM usage. ```sh cargo build --target wasm32-unknown-unknown ``` -------------------------------- ### OAuth Token Management Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to configure token caching and automatic refreshing for authenticated Spotify sessions. ```APIDOC ## POST /oauth/token ### Description Handles token retrieval, caching, and automatic refreshing for OAuth2 authentication flows. ### Method POST ### Endpoint /oauth/token ### Parameters #### Request Body - **token_cached** (boolean) - Optional - Whether to persist tokens to disk. - **token_refreshing** (boolean) - Optional - Whether to automatically refresh expired tokens. - **cache_path** (string) - Optional - File path for the token cache. ### Request Example let config = Config { token_cached: true, token_refreshing: true, cache_path: PathBuf::from(".spotify_cache.json"), ..Default::default() }; ### Response #### Success Response (200) - **access_token** (string) - The valid OAuth access token. - **expires_in** (integer) - Time in seconds until token expiration. ``` -------------------------------- ### Implement Automatic Pagination with Async Streams Source: https://context7.com/ramsayleung/rspotify/llms.txt Explains how to use async streams to iterate through paginated Spotify API results automatically. It covers both sequential iteration and concurrent processing of items. ```rust use futures::stream::TryStreamExt; use futures_util::pin_mut; use rspotify::{prelude::*, scopes, AuthCodeSpotify, Credentials, OAuth}; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let oauth = OAuth::from_env(scopes!("user-library-read")).unwrap(); let spotify = AuthCodeSpotify::new(creds, oauth); let url = spotify.get_authorize_url(false).unwrap(); spotify.prompt_for_token(&url).await.unwrap(); let stream = spotify.current_user_saved_tracks(None); pin_mut!(stream); println!("Your saved tracks:"); while let Some(item) = stream.try_next().await.unwrap() { println!(" - {} by {:?}", item.track.name, item.track.artists.iter().map(|a| &a.name).collect::>()); } let stream = spotify.current_user_saved_tracks(None); stream .try_for_each_concurrent(10, |item| async move { println!("Processing: {}", item.track.name); Ok(()) }) .await .unwrap(); } ``` -------------------------------- ### Define OAuth Scopes with Macros Source: https://context7.com/ramsayleung/rspotify/llms.txt Illustrates the use of the scopes! macro to define required OAuth permissions at compile time, returning a HashSet of strings. ```rust use rspotify::scopes; use std::collections::HashSet; fn main() { let scopes = scopes!( "user-read-private", "user-read-email", "playlist-read-private", "playlist-modify-public" ); let scopes_alt = scopes!("user-read-private user-read-email"); let scopes: HashSet = scopes; println!("Requested scopes: {:?}", scopes); } ``` -------------------------------- ### Manage Type-Safe Spotify Resource Identifiers Source: https://context7.com/ramsayleung/rspotify/llms.txt Shows how to instantiate and manipulate strongly-typed Spotify IDs (AlbumId, TrackId, etc.) from raw strings, URIs, or URLs to ensure type safety in API calls. ```rust use rspotify::model::{AlbumId, ArtistId, TrackId, PlaylistId, EpisodeId, PlayableId}; use rspotify::prelude::Id; fn main() { let track_id = TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap(); let album_id = AlbumId::from_uri("spotify:album:6IcGNaXFRf5Y1jc7QsE9O2").unwrap(); let artist_id = ArtistId::from_id_or_uri("spotify:artist:0OdUWJ0sBjDrqHygGUXeCF").unwrap(); println!("Track ID: {}", track_id.id()); println!("Track URI: {}", track_id.uri()); println!("Track URL: {}", track_id.url()); let playable_track: PlayableId = track_id.into(); let episode_id = EpisodeId::from_id("0lbiy3LKzIY2fnyjioC11p").unwrap(); let playable_episode: PlayableId = episode_id.into(); let queue: Vec = vec![playable_track, playable_episode]; } ``` -------------------------------- ### Handle RSpotify API and ID Errors in Rust Source: https://context7.com/ramsayleung/rspotify/llms.txt Demonstrates how to handle different types of errors that can occur when interacting with the Spotify API using RSpotify in Rust. This includes HTTP errors, JSON parsing errors, invalid tokens, invalid track IDs, and API-specific errors like 404 Not Found. ```rust use rspotify::{ model::TrackId, prelude::*, ClientCredsSpotify, ClientError, Credentials, }; #[tokio::main] async fn main() { let creds = Credentials::from_env().unwrap(); let spotify = ClientCredsSpotify::new(creds); if let Err(e) = spotify.request_token().await { match e { ClientError::Http(http_err) => { eprintln!("HTTP error: {:?}", http_err); } ClientError::ParseJson(json_err) => { eprintln!("JSON parsing error: {:?}", json_err); } ClientError::InvalidToken => { eprintln!("Invalid or expired token"); } _ => eprintln!("Other error: {:?}", e), } return; } // Handle invalid IDs gracefully match TrackId::from_id("invalid!@#") { Ok(id) => println!("Valid ID: {}", id.id()), Err(e) => eprintln!("Invalid ID: {:?}", e), // IdError::InvalidId } // Handle API errors match spotify.track(TrackId::from_id("nonexistent123456789012").unwrap(), None).await { Ok(track) => println!("Track: {}", track.name), Err(ClientError::Http(e)) => { eprintln!("API error: {:?}", e); // Usually 404 Not Found } Err(e) => eprintln!("Error: {:?}", e), } } ``` -------------------------------- ### Generate Spotify URI from Id Type (Rust) Source: https://github.com/ramsayleung/rspotify/wiki/The-design-behind-the-`Id`-type This function generates a Spotify URI string from an Id type. It formats the URI using the Id's type and its unique identifier. This is crucial for interacting with Spotify API endpoints that require a URI format. ```Rust /// Examples: `spotify:album:6IcGNaXFRf5Y1jc7QsE9O2`, /// `spotify:track:4y4VO05kYgUTo2bzbox1an`. fn uri(&self) -> String { format!("spotify:{}:{}", self._type(), self.id()) } ``` -------------------------------- ### Synchronous Search API Source: https://context7.com/ramsayleung/rspotify/llms.txt Performs a synchronous search for artists using the ureq client implementation. ```APIDOC ## GET /search ### Description Searches for items (artists, tracks, etc.) on Spotify using a synchronous client. ### Method GET ### Endpoint /search ### Parameters #### Query Parameters - **q** (string) - Required - The search query. - **type** (string) - Required - The type of item to search (e.g., artist). - **market** (string) - Optional - The country code for market-specific results. - **limit** (integer) - Optional - Maximum number of results to return. ### Request Example spotify.search("Beatles", SearchType::Artist, Some(Market::Country(Country::UnitedStates)), None, Some(5), None); ### Response #### Success Response (200) - **search_result** (object) - The search results object containing the requested items. #### Response Example { "artists": { "items": [{"name": "The Beatles", "id": "3WrFJ7ztbogyGnTHbHJFl2"}] } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.