From 10e0877d51a6631098a33aee7e15c05b13efe132 Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Mon, 14 Oct 2024 22:54:44 +0200 Subject: [PATCH] user detail loading --- src/api.rs | 48 +++++++++++++++++++++++++++++++++++++----------- src/auth.rs | 2 +- src/main.rs | 11 ++++++++++- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/api.rs b/src/api.rs index 5fd0415..ce27028 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,24 +1,27 @@ use std::future::Future; -use std::time::Duration; +use std::time::{Duration, Instant}; use chrono::TimeDelta; +use futures_util::lock::Mutex; use librespot_core::Session; use librespot_oauth::OAuthToken; use reqwest::StatusCode; +use rspotify::model::PrivateUser; +use rspotify::prelude::*; use rspotify::{AuthCodeSpotify, ClientError, ClientResult, Config, Token}; use rspotify::http::HttpError; -use crate::auth::{rspotify_scopes, SPOTIFY_REDIRECT_URI}; +use crate::auth::{get_access_token_from_refresh_token, rspotify_scopes, SPOTIFY_REDIRECT_URI}; -struct SpotifyContext { +pub struct SpotifyContext { session: Session, api: AuthCodeSpotify, - token: OAuthToken + token: Mutex } impl SpotifyContext { - fn new(session: Session, token: OAuthToken) -> SpotifyContext { + pub fn new(session: Session, token: OAuthToken) -> SpotifyContext { let config = Config { token_refreshing: false, ..Default::default() @@ -34,13 +37,28 @@ impl SpotifyContext { }, config, ); - SpotifyContext { session, api, token } + SpotifyContext { session, api, token: Mutex::new(token) } + } + + pub async fn update_token(&self) -> bool { + let expires_soon = Instant::now() + Duration::from_secs(10); + let token = self.token.lock().await; + if token.expires_at < expires_soon { + let refresh_token = token.refresh_token.clone(); + drop(token); + let token = get_access_token_from_refresh_token(&refresh_token).unwrap();; + *self.api.token.lock().await.unwrap() = Some(librespot_token_to_rspotify(&token)); + *self.token.lock().await = token; + true + } else { + false + } } /// Execute `api_call` and retry once if a rate limit occurs. - async fn api_with_retry>, R>(&self, api_call: F) -> Option + async fn api_with_retry<'a, F, T: Future>, R>(&'a self, api_call: F) -> Option where - F: Fn(&AuthCodeSpotify) -> T, + F: Fn(&'a AuthCodeSpotify) -> T, { let result = { api_call(&self.api).await }; match result { @@ -63,9 +81,12 @@ impl SpotifyContext { } StatusCode::UNAUTHORIZED => { dbg!("token unauthorized. trying refresh.."); - // self.update_token() - // .and_then(move |_| api_call(&self.api).await.ok()) - None + let updated = self.update_token().await; + if updated { + api_call(&self.api).await.ok() + } else { + None + } } _ => { eprintln!("unhandled api error: {:?}", response); @@ -82,6 +103,11 @@ impl SpotifyContext { } } } + + pub async fn current_user(&self) -> Result { + self.api_with_retry(|api| api.current_user()).await.ok_or(()) + } + } fn librespot_token_to_rspotify(token: &OAuthToken) -> Token { diff --git a/src/auth.rs b/src/auth.rs index e9c1451..1f4c0d0 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -69,7 +69,7 @@ fn oauth2_client() -> Result { Ok(client) } -fn get_access_token_from_refresh_token(refresh_token: &str) -> Result { +pub fn get_access_token_from_refresh_token(refresh_token: &str) -> Result { let client = oauth2_client()?; let token = client .exchange_refresh_token(&RefreshToken::new(refresh_token.to_string())) diff --git a/src/main.rs b/src/main.rs index 77abb05..1896739 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::thread; +use api::SpotifyContext; use auth::get_token; use clap::Parser; use cli::Args; @@ -53,9 +54,17 @@ fn main() -> cushy::Result { } }); + dbg!(session.user_data()); + + let context = SpotifyContext::new(session, token); + + tokio::spawn(async move { + let user = context.current_user().await.unwrap(); + dbg!(user); + }); + drop(guard); } - dbg!(session.user_data()); app.run() } \ No newline at end of file