rspotify

repository·master·Indexed 20 days ago

https://github.com/ramsayleung/rspotify

A Rust wrapper for the Spotify Web API (version 0.16.1) providing support for authorization flows and API endpoints. It supports both async (via reqwest) and blocking (via ureq) modes using the maybe_async pattern, and is compatible with the wasm32-unknown-unknown target. The library includes a model crate for Spotify data types and a macros crate featuring the scopes! macro for managing authentication scopes.

Tokens
26.4K
Snippets
107
Records
139
Agent score
64%

What's inside rspotify

  1. Build RSpotify with different HTTP clients

    master

    RSpotify uses the maybe_async crate to switch between async and blocking clients. You must choose one client implementation at a time; you cannot build with all features enabled simultaneously due to duplicate definition errors in the trait implementations.

    Default Client (Async)

    By default, client-reqwest is used. You can build it using standard commands:

    $ cargo build

    Blocking Client (ureq)

    To use the ureq client for blocking interfaces, you must disable default features and specify a TLS implementation (e.g., ureq-rustls-tls):

    $ cargo build --no-default-features --features client-ureq,ureq-rustls-tls
    $ cargo build --no-default-features --features client-ureq,ureq-rustls-tls
  2. Build RSpotify for WebAssembly (WASM)

    master

    RSpotify supports the wasm32-unknown-unknown target. To build for WebAssembly, use the --target flag with cargo build:

    $ cargo build --target wasm32-unknown-unknown

    For more specific details regarding WebAssembly integration, refer to the official documentation.

    $ cargo build --target wasm32-unknown-unknown
  3. Understand the OAuthClient trait

    master
    The OAuthClient trait defines methods available to clients that require user authorization. It extends BaseClient and includes endpoints that always require authorization, as well as parts of the authentication flow. If you are using a client that requires a user to log in via Spotify, it will implement this trait.
  4. Understand the BaseClient trait

    master
    The BaseClient trait defines the core functionality for all Spotify clients in rspotify. It provides access to basic endpoints that may not require full user authorization, handles authentication URL construction, and manages the underlying HTTP client and configuration. It also includes mechanisms for automatic token refreshing and token caching.
  5. Automatic token re-authentication

    master
    The BaseClient supports automatic re-authentication. If Config::token_refreshing is enabled, the client can automatically use a refresh token to obtain a new access token when the current one is expired. This is typically triggered during authenticated requests via the internal auth_headers method.
  6. Use AuthCodePkceSpotify for Spotify API authorization

    master

    The AuthCodePkceSpotify client implements the Authorization Code Flow with Proof Key for Code Exchange (PKCE). This flow is ideal when you want to avoid storing a client secret.

    Important Note: The refresh token obtained via PKCE will only work to request the next one, after which it becomes invalid. This makes it suitable for short-lived sessions or specific client-side implementations.

    use rspotify::{AuthCodePkceSpotify, Credentials, OAuth};
    
    // Example initialization
    let creds = Credentials { id: "CLIENT_ID".to_string(), ..Default::default() };
    let oauth = OAuth { redirect_uri: "REDIRECT_URI".to_string(), ..Default::default() };
    let client = AuthCodePkceSpotify::new(creds, oauth);
  7. Group multiple ID types using `PlayableId` or `LibraryId`

    master

    The library provides enum wrappers to treat different kinds of IDs generically when an endpoint accepts multiple types.

    PlayableId<'a>

    Used for items that can be played. It wraps:

    • TrackId<'a>
    • EpisodeId<'a>

    LibraryId<'a>

    A comprehensive wrapper for all major library items. It wraps:

    • TrackId<'a>, AlbumId<'a>, EpisodeId<'a>, ShowId<'a>, ArtistId<'a>, UserId<'a>, and PlaylistId<'a>.

    PlayContextId<'a>

    Used for context-based playback. It wraps:

    • ArtistId<'a>, AlbumId<'a>, PlaylistId<'a>, and ShowId<'a>.

    All these enums implement the Id trait and provide .as_ref(), .into_static(), and .clone_static() methods to manage lifetimes.

    use rspotify_model::{TrackId, EpisodeId, PlayableId};
    
    fn add_to_queue(id: &[PlayableId]) { /* ... */ }
    
    let tracks = [
        PlayableId::Track(TrackId::from_id("track_id_1").unwrap()),
        PlayableId::Track(TrackId::from_id("track_id_2").unwrap()),
    ];
    let episodes = [
        PlayableId::Episode(EpisodeId::from_id("ep_id_1").unwrap()),
    ];
    
    // Combine different types into a single vector of PlayableId
    let playable: Vec<PlayableId> = tracks.into_iter().chain(episodes.into_iter()).collect();
    
    add_to_queue(&playable);
  8. How the Authorization Code Flow works in AuthCodeSpotify

    master

    The AuthCodeSpotify client implements the Spotify Authorization Code Flow, which allows access to user private data. The flow follows these steps:

    1. Generate Authorization URL: Use get_authorize_url to create the URL where the user will log in.
    2. User Authorization: The user logs in via the generated URL and is redirected to your specified redirect_uri with a code parameter in the URL.
    3. Parse Code: Extract the code from the redirect URL (the client provides parse_response_code for this).
    4. Exchange Code for Token: Call request_token(code) to exchange the code for an access token. This token is stored internally.
    5. Refresh Token: When the access token expires, use refetch_token() to obtain a new one using the stored refresh_token without requiring user re-login.

    Note for CLI developers: If you enable the cli feature, you can use prompt_for_token to automate these steps via user interaction in the terminal.

    // Conceptual flow summary:
    // 1. let url = client.get_authorize_url(false)?;
    // 2. // User visits url, gets redirected to callback with ?code=...
    // 3. client.request_token("the_code_from_url").await?;
    // 4. // Later, when expired:
    // 5. client.refetch_token().await?;
  9. Choose the correct Spotify client for your authorization flow

    master

    RSpotify provides different client types depending on the Spotify authentication flow you are using. You should select the client that matches your requirements:

    • Client Credentials Flow: Use ClientCredsSpotify. Best for server-to-server interactions where user context is not needed.
    • Authorization Code Flow: Use AuthCodeSpotify. Standard flow for accessing user data.
    • Authorization Code Flow with PKCE: Use AuthCodePkceSpotify. Recommended for mobile or web applications (including WASM) to improve security.
  10. Use ClientCredsSpotify for basic Spotify API access

    master

    The ClientCredsSpotify client implements the Spotify Client Credentials Flow. This is the most basic authentication flow, suitable for accessing public data without user authorization.

    Important Limitations:

    • It cannot be used to access or manage user private data (use OAuthClient for that).
    • There is no refresh token available in this flow; refetching a token is equivalent to requesting a new one from scratch.

    To use this client, you must provide Credentials and then call request_token() to obtain an access token.

    use rspotify::{ClientCredsSpotify, Credentials};
    
    let creds = Credentials::new(client_id, Some(client_secret));
    let client = ClientCredsSpotify::new(creds);
    client.request_token().await?;
  11. How Spotify IDs and URIs work with type safety

    master

    The rspotify-model crate provides type-safe wrappers for various Spotify identifiers. Instead of using raw strings, you use specific types like TrackId, ArtistId, or AlbumId. This prevents logic errors, such as passing an EpisodeId to a function expecting a TrackId, which are caught at compile-time.

    Supported ID Types

    • ArtistId (Type::Artist)
    • AlbumId (Type::Album)
    • TrackId (Type::Track)
    • PlaylistId (Type::Playlist)
    • UserId (Type::User)
    • ShowId (Type::Show)
    • EpisodeId (Type::Episode)

    Key Concepts

    • The Id Trait: The central interface for all ID types. You must import this trait (e.g., use rspotify::prelude::*) to access methods like .id(), .uri(), and .url().
    • Ownership and Lifetimes: ID types are wrappers around Cow<str>. They can hold borrowed data (Id<'a>) or owned data (Id<'static>). Use .into_static() or .clone_static() to convert a borrowed ID into an owned one with a 'static lifetime.
    • Parsing: You can create IDs from raw strings (using .from_id()) or from full Spotify URIs (using .from_uri()).
    use rspotify_model::{TrackId, EpisodeId};
    
    fn pause_track(id: TrackId<'_>) { /* ... */ }
    
    // Success: Correct type
    let id = TrackId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap();
    pause_track(id);
    
    // Compile-time error: Wrong type
    // let id = EpisodeId::from_id("4iV5W9uYEdYUVa79Axb7Rh").unwrap();
    // pause_track(id); // This would fail to compile
    
    // Runtime panic: URI type mismatch
    // let id = TrackId::from_uri("spotify:album:6akEvsycLGftJxYudPjmqK").unwrap();
    // pause_track(id); // This would panic because the URI is an album, not a track