diff --git a/Cargo.lock b/Cargo.lock index 65493a27..461095f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "addr2line" version = "0.14.1" @@ -1358,6 +1360,7 @@ dependencies = [ "tokio-stream", "tokio-util", "url", + "uuid", "vergen", ] @@ -2801,6 +2804,15 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", +] + [[package]] name = "vergen" version = "3.2.0" diff --git a/core/Cargo.toml b/core/Cargo.toml index 373e3088..9b2c6a52 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -40,6 +40,7 @@ tokio = { version = "1.0", features = ["io-util", "net", "rt", "sync"] } tokio-stream = "0.1" tokio-util = { version = "0.6", features = ["codec"] } url = "2.1" +uuid = { version = "0.8", default-features = false, features = ["v4"] } [build-dependencies] rand = "0.8" diff --git a/core/src/authentication.rs b/core/src/authentication.rs index 28393539..2992abcd 100644 --- a/core/src/authentication.rs +++ b/core/src/authentication.rs @@ -10,6 +10,7 @@ use sha1::{Digest, Sha1}; use crate::protocol::authentication::AuthenticationType; +/// The credentials are used to log into the Spotify API. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Credentials { pub username: String, @@ -25,11 +26,22 @@ pub struct Credentials { } impl Credentials { - pub fn with_password(username: String, password: String) -> Credentials { + /// Intialize these credentials from a username and a password. + /// + /// ### Example + /// ```rust + /// use librespot_core::authentication::Credentials; + /// + /// let creds = Credentials::with_password("my account", "my password"); + /// ``` + pub fn with_password( + username: impl Into, + password: impl Into, + ) -> Credentials { Credentials { - username, + username: username.into(), auth_type: AuthenticationType::AUTHENTICATION_USER_PASS, - auth_data: password.into_bytes(), + auth_data: password.into().into_bytes(), } } diff --git a/core/src/config.rs b/core/src/config.rs index 469b935a..26924640 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -10,6 +10,18 @@ pub struct SessionConfig { pub ap_port: Option, } +impl Default for SessionConfig { + fn default() -> SessionConfig { + let device_id = uuid::Uuid::new_v4().to_hyphenated().to_string(); + SessionConfig { + user_agent: crate::version::version_string(), + device_id, + proxy: None, + ap_port: None, + } + } +} + #[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] pub enum DeviceType { Unknown = 0, diff --git a/examples/get_token.rs b/examples/get_token.rs index d722e994..15b97bcb 100644 --- a/examples/get_token.rs +++ b/examples/get_token.rs @@ -1,5 +1,4 @@ use std::env; -use tokio_core::reactor::Core; use librespot::core::authentication::Credentials; use librespot::core::config::SessionConfig; @@ -9,29 +8,24 @@ use librespot::core::session::Session; const SCOPES: &str = "streaming,user-read-playback-state,user-modify-playback-state,user-read-currently-playing"; -fn main() { - let mut core = Core::new().unwrap(); - let handle = core.handle(); - +#[tokio::main] +async fn main() { let session_config = SessionConfig::default(); let args: Vec<_> = env::args().collect(); if args.len() != 4 { - println!("Usage: {} USERNAME PASSWORD CLIENT_ID", args[0]); + eprintln!("Usage: {} USERNAME PASSWORD CLIENT_ID", args[0]); + return; } - let username = args[1].to_owned(); - let password = args[2].to_owned(); - let client_id = &args[3]; println!("Connecting.."); - let credentials = Credentials::with_password(username, password); - let session = core - .run(Session::connect(session_config, credentials, None, handle)) - .unwrap(); + let credentials = Credentials::with_password(&args[1], &args[2]); + let session = Session::connect(session_config, credentials, None).await.unwrap(); println!( "Token: {:#?}", - core.run(keymaster::get_token(&session, &client_id, SCOPES)) + keymaster::get_token(&session, &args[3], SCOPES) + .await .unwrap() ); } diff --git a/examples/play.rs b/examples/play.rs index 4ba4c5b5..9b1988a6 100644 --- a/examples/play.rs +++ b/examples/play.rs @@ -1,47 +1,41 @@ use std::env; -use tokio_core::reactor::Core; use librespot::core::authentication::Credentials; use librespot::core::config::SessionConfig; use librespot::core::session::Session; use librespot::core::spotify_id::SpotifyId; use librespot::playback::config::PlayerConfig; - use librespot::playback::audio_backend; use librespot::playback::player::Player; -fn main() { - let mut core = Core::new().unwrap(); - let handle = core.handle(); - +#[tokio::main] +async fn main() { let session_config = SessionConfig::default(); let player_config = PlayerConfig::default(); let args: Vec<_> = env::args().collect(); if args.len() != 4 { - println!("Usage: {} USERNAME PASSWORD TRACK", args[0]); + eprintln!("Usage: {} USERNAME PASSWORD TRACK", args[0]); + return; } - let username = args[1].to_owned(); - let password = args[2].to_owned(); - let credentials = Credentials::with_password(username, password); + let credentials = Credentials::with_password(&args[1], &args[2]); let track = SpotifyId::from_base62(&args[3]).unwrap(); let backend = audio_backend::find(None).unwrap(); println!("Connecting .."); - let session = core - .run(Session::connect(session_config, credentials, None, handle)) - .unwrap(); + let session = Session::connect(session_config, credentials, None).await.unwrap(); - let (mut player, _) = Player::new(player_config, session.clone(), None, move || { - (backend)(None) + let (mut player, _) = Player::new(player_config, session, None, move || { + backend(None) }); player.load(track, true, 0); println!("Playing..."); - core.run(player.get_end_of_track_future()).unwrap(); + + player.await_end_of_track().await; println!("Done"); } diff --git a/examples/playlist_tracks.rs b/examples/playlist_tracks.rs index fc288d18..7bd95ae2 100644 --- a/examples/playlist_tracks.rs +++ b/examples/playlist_tracks.rs @@ -1,6 +1,5 @@ use env_logger; use std::env; -use tokio_core::reactor::Core; use librespot::core::authentication::Credentials; use librespot::core::config::SessionConfig; @@ -8,35 +7,30 @@ use librespot::core::session::Session; use librespot::core::spotify_id::SpotifyId; use librespot::metadata::{Metadata, Playlist, Track}; -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); - let mut core = Core::new().unwrap(); - let handle = core.handle(); - let session_config = SessionConfig::default(); let args: Vec<_> = env::args().collect(); if args.len() != 4 { - println!("Usage: {} USERNAME PASSWORD PLAYLIST", args[0]); + eprintln!("Usage: {} USERNAME PASSWORD PLAYLIST", args[0]); + return; } - let username = args[1].to_owned(); - let password = args[2].to_owned(); - let credentials = Credentials::with_password(username, password); + let credentials = Credentials::with_password(&args[1], &args[2]); - let uri_split = args[3].split(":"); + let uri_split = args[3].split(':'); let uri_parts: Vec<&str> = uri_split.collect(); println!("{}, {}, {}", uri_parts[0], uri_parts[1], uri_parts[2]); let plist_uri = SpotifyId::from_base62(uri_parts[2]).unwrap(); - let session = core - .run(Session::connect(session_config, credentials, None, handle)) - .unwrap(); + let session = Session::connect(session_config, credentials, None).await.unwrap(); - let plist = core.run(Playlist::get(&session, plist_uri)).unwrap(); + let plist = Playlist::get(&session, plist_uri).await.unwrap(); println!("{:?}", plist); for track_id in plist.tracks { - let plist_track = core.run(Track::get(&session, track_id)).unwrap(); + let plist_track = Track::get(&session, track_id).await.unwrap(); println!("track: {} ", plist_track.name); } }