use crate::config;
use anyhow::Result;
use librespot_core::{authentication::Credentials, cache::Cache, config::SessionConfig, Session};
use librespot_oauth::OAuthClientBuilder;
pub const SPOTIFY_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
pub const NCSPOT_CLIENT_ID: &str = "d420a117a32841c2b3474932e49fb54b";
pub const OAUTH_SCOPES: &[&str] = &[
"user-read-playback-state",
"user-modify-playback-state",
"user-read-currently-playing",
"app-remote-control",
"streaming",
"playlist-read-private",
"playlist-read-collaborative",
"playlist-modify-private",
"playlist-modify-public",
"user-follow-modify",
"user-follow-read",
"user-read-playback-position",
"user-top-read",
"user-read-recently-played",
"user-library-modify",
"user-library-read",
"user-personalized",
];
#[derive(Clone)]
pub struct AuthConfig {
pub cache: Cache,
pub session_config: SessionConfig,
pub login_redirect_uri: String,
}
impl Default for AuthConfig {
fn default() -> Self {
AuthConfig {
cache: Cache::new(None::<String>, None, None, None).unwrap(),
session_config: SessionConfig::default(),
login_redirect_uri: "http://127.0.0.1:8989/login".to_string(),
}
}
}
impl AuthConfig {
pub fn session(&self) -> Session {
Session::new(self.session_config.clone(), Some(self.cache.clone()))
}
pub fn new(configs: &config::Configs) -> Result<AuthConfig> {
let audio_cache_folder = if configs.app_config.device.audio_cache {
Some(configs.cache_folder.join("audio"))
} else {
None
};
let cache = Cache::new(
Some(configs.cache_folder.clone()),
None,
audio_cache_folder,
None,
)?;
Ok(AuthConfig {
cache,
session_config: configs.app_config.session_config(),
login_redirect_uri: configs.app_config.login_redirect_uri.clone(),
})
}
}
pub fn get_creds(auth_config: &AuthConfig, reauth: bool, use_cached: bool) -> Result<Credentials> {
let creds = if use_cached {
auth_config.cache.credentials()
} else {
None
};
Ok(match creds {
None => {
let msg = "No cached credentials found, please authenticate the application first.";
if reauth {
eprintln!("{msg}");
let client_builder = OAuthClientBuilder::new(
SPOTIFY_CLIENT_ID,
&auth_config.login_redirect_uri,
OAUTH_SCOPES.to_vec(),
)
.open_in_browser();
let oauth_client = client_builder.build()?;
oauth_client
.get_access_token()
.map(|t| Credentials::with_access_token(t.access_token))?
} else {
anyhow::bail!(msg);
}
}
Some(creds) => {
tracing::info!("Using cached credentials");
creds
}
})
}