diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb8a266..fdedb554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [core] Add `login` (mobile) and `auth_token` retrieval via login5 +- [core] Add `OS` and `os_version` to `config.rs` ### Removed diff --git a/core/src/config.rs b/core/src/config.rs index 674c5020..1160c0f5 100644 --- a/core/src/config.rs +++ b/core/src/config.rs @@ -6,6 +6,20 @@ pub(crate) const KEYMASTER_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd"; pub(crate) const ANDROID_CLIENT_ID: &str = "9a8d2f0ce77a4e248bb71fefcb557637"; pub(crate) const IOS_CLIENT_ID: &str = "58bd3c95768941ea9eb4350aaa033eb3"; +// Easily adjust the current platform to mock the behavior on it. If for example +// android or ios needs to be mocked, the `os_version` has to be set to a valid version. +// Otherwise, client-token or login5 requests will fail with a generic invalid-credential error. +/// See [std::env::consts::OS] +pub const OS: &str = std::env::consts::OS; + +// valid versions for some os: +// 'android': 30 +// 'ios': 17 +/// See [sysinfo::System::os_version] +pub fn os_version() -> String { + sysinfo::System::os_version().unwrap_or("0".into()) +} + #[derive(Clone, Debug)] pub struct SessionConfig { pub client_id: String, @@ -39,7 +53,7 @@ impl SessionConfig { impl Default for SessionConfig { fn default() -> Self { - Self::default_for_os(std::env::consts::OS) + Self::default_for_os(OS) } } diff --git a/core/src/connection/handshake.rs b/core/src/connection/handshake.rs index d18f3df1..03b35598 100644 --- a/core/src/connection/handshake.rs +++ b/core/src/connection/handshake.rs @@ -110,7 +110,7 @@ where let mut client_nonce = vec![0; 0x10]; thread_rng().fill_bytes(&mut client_nonce); - let platform = match std::env::consts::OS { + let platform = match crate::config::OS { "android" => Platform::PLATFORM_ANDROID_ARM, "freebsd" | "netbsd" | "openbsd" => match ARCH { "x86_64" => Platform::PLATFORM_FREEBSD_X86_64, diff --git a/core/src/connection/mod.rs b/core/src/connection/mod.rs index c46e5ad8..2e9bbdb4 100644 --- a/core/src/connection/mod.rs +++ b/core/src/connection/mod.rs @@ -112,7 +112,7 @@ pub async fn authenticate( _ => CpuFamily::CPU_UNKNOWN, }; - let os = match std::env::consts::OS { + let os = match crate::config::OS { "android" => Os::OS_ANDROID, "freebsd" | "netbsd" | "openbsd" => Os::OS_FREEBSD, "ios" => Os::OS_IPHONE, diff --git a/core/src/http_client.rs b/core/src/http_client.rs index e7e25e92..8645d3a3 100644 --- a/core/src/http_client.rs +++ b/core/src/http_client.rs @@ -1,6 +1,5 @@ use std::{ collections::HashMap, - env::consts::OS, time::{Duration, Instant}, }; @@ -21,11 +20,11 @@ use hyper_util::{ use nonzero_ext::nonzero; use once_cell::sync::OnceCell; use parking_lot::Mutex; -use sysinfo::System; use thiserror::Error; use url::Url; use crate::{ + config::{os_version, OS}, date::Date, version::{spotify_version, FALLBACK_USER_AGENT, VERSION_STRING}, Error, @@ -106,12 +105,10 @@ pub struct HttpClient { impl HttpClient { pub fn new(proxy_url: Option<&Url>) -> Self { let zero_str = String::from("0"); - let os_version = System::os_version().unwrap_or_else(|| zero_str.clone()); + let os_version = os_version(); let (spotify_platform, os_version) = match OS { - // example os_version: 30 "android" => ("Android", os_version), - // example os_version: 17 "ios" => ("iOS", os_version), "macos" => ("OSX", zero_str), "windows" => ("Win32", zero_str), diff --git a/core/src/login5.rs b/core/src/login5.rs index b13ed985..dca8f27e 100644 --- a/core/src/login5.rs +++ b/core/src/login5.rs @@ -1,3 +1,4 @@ +use crate::config::OS; use crate::spclient::CLIENT_TOKEN; use crate::token::Token; use crate::{util, Error, SessionConfig}; @@ -15,7 +16,6 @@ use librespot_protocol::{ }; use protobuf::well_known_types::duration::Duration as ProtoDuration; use protobuf::{Message, MessageField}; -use std::env::consts::OS; use std::time::{Duration, Instant}; use thiserror::Error; use tokio::time::sleep; diff --git a/core/src/spclient.rs b/core/src/spclient.rs index 8725c45e..a23b52f0 100644 --- a/core/src/spclient.rs +++ b/core/src/spclient.rs @@ -1,5 +1,4 @@ use std::{ - env::consts::OS, fmt::Write, time::{Duration, Instant}, }; @@ -18,6 +17,7 @@ use rand::RngCore; use sysinfo::System; use thiserror::Error; +use crate::config::{os_version, OS}; use crate::{ apresolve::SocketAddress, cdn_url::CdnUrl, @@ -162,7 +162,7 @@ impl SpClient { .platform_specific_data .mut_or_insert_default(); - let os_version = System::os_version().unwrap_or_else(|| String::from("0")); + let os_version = os_version(); let kernel_version = System::kernel_version().unwrap_or_else(|| String::from("0")); match os { @@ -191,12 +191,10 @@ impl SpClient { ios_data.user_interface_idiom = 0; ios_data.target_iphone_simulator = false; ios_data.hw_machine = "iPhone14,5".to_string(); - // example system_version: 17 ios_data.system_version = os_version; } "android" => { let android_data = platform_data.mut_android(); - // example android_version: 30 android_data.android_version = os_version; android_data.api_version = 31; "Pixel".clone_into(&mut android_data.device_name); diff --git a/core/src/version.rs b/core/src/version.rs index d3870473..3439662c 100644 --- a/core/src/version.rs +++ b/core/src/version.rs @@ -29,14 +29,14 @@ pub const SPOTIFY_MOBILE_VERSION: &str = "8.6.84"; pub const FALLBACK_USER_AGENT: &str = "Spotify/117300517 Linux/0 (librespot)"; pub fn spotify_version() -> String { - match std::env::consts::OS { + match crate::config::OS { "android" | "ios" => SPOTIFY_MOBILE_VERSION.to_owned(), _ => SPOTIFY_VERSION.to_string(), } } pub fn spotify_semantic_version() -> String { - match std::env::consts::OS { + match crate::config::OS { "android" | "ios" => SPOTIFY_MOBILE_VERSION.to_owned(), _ => SPOTIFY_SEMANTIC_VERSION.to_string(), }