use lastfm_edit::{LastFmEditClient, LastFmEditClientImpl, LastFmEditSession, Result};
use std::env;
use std::fs;
use std::io::{self, Write};
use std::path::Path;
const SESSION_FILE: &str = "session.json";
#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();
println!("🎵 Last.fm Session Management Example");
println!("=====================================\n");
if Path::new(SESSION_FILE).exists() {
println!("📁 Found existing session file, attempting to restore...");
match restore_from_session().await {
Ok(client) => {
println!("✅ Session restored successfully!");
println!("👤 Logged in as: {}", client.username());
println!("🎧 Testing session by fetching recent tracks...");
let tracks = client.get_recent_scrobbles(1).await?;
let recent_tracks: Vec<_> = tracks.into_iter().take(3).collect();
println!("📊 Found {} recent tracks:", recent_tracks.len());
for track in recent_tracks {
println!(" 🎵 {} - {}", track.artist, track.name);
}
return Ok(());
}
Err(e) => {
println!("❌ Failed to restore session: {e}");
println!("🔄 Falling back to fresh login...\n");
let _ = fs::remove_file(SESSION_FILE);
}
}
}
println!("🔑 No valid session found, performing fresh login...");
let client = login_with_credentials().await?;
println!("✅ Login successful!");
println!("👤 Logged in as: {}", client.username());
println!("💾 Saving session to {SESSION_FILE}...");
save_session(&client)?;
println!("✅ Session saved!");
println!("🎧 Testing session by fetching recent tracks...");
let tracks = client.get_recent_scrobbles(1).await?;
let recent_tracks: Vec<_> = tracks.into_iter().take(3).collect();
println!("📊 Found {} recent tracks:", recent_tracks.len());
for track in recent_tracks {
println!(" 🎵 {} - {}", track.artist, track.name);
}
println!("\n🎉 Example completed!");
println!("💡 Next time you run this example, it will use the saved session automatically.");
Ok(())
}
async fn restore_from_session() -> Result<LastFmEditClientImpl> {
let session_json = fs::read_to_string(SESSION_FILE)
.map_err(|e| lastfm_edit::LastFmError::Http(format!("Failed to read session file: {e}")))?;
let session = LastFmEditSession::from_json(&session_json)
.map_err(|e| lastfm_edit::LastFmError::Http(format!("Failed to parse session: {e}")))?;
if !session.is_valid() {
return Err(lastfm_edit::LastFmError::Auth(
"Invalid session data".to_string(),
));
}
let http_client = http_client::native::NativeClient::new();
Ok(LastFmEditClientImpl::from_session(
Box::new(http_client),
session,
))
}
async fn login_with_credentials() -> Result<LastFmEditClientImpl> {
println!("🔧 Using login with credentials pattern...");
let username = get_username();
let password = get_password();
let http_client = http_client::native::NativeClient::new();
LastFmEditClientImpl::login_with_credentials(Box::new(http_client), &username, &password).await
}
fn save_session(client: &dyn LastFmEditClient) -> Result<()> {
let session = client.get_session();
let session_json = session
.to_json()
.map_err(|e| lastfm_edit::LastFmError::Http(format!("Failed to serialize session: {e}")))?;
fs::write(SESSION_FILE, session_json).map_err(|e| {
lastfm_edit::LastFmError::Http(format!("Failed to write session file: {e}"))
})?;
Ok(())
}
fn get_username() -> String {
env::var("LASTFM_EDIT_USERNAME").unwrap_or_else(|_| {
print!("Last.fm username: ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
input.trim().to_string()
})
}
fn get_password() -> String {
env::var("LASTFM_EDIT_PASSWORD").unwrap_or_else(|_| {
print!("Last.fm password: ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
input.trim().to_string()
})
}