//! Smoke test against the live Soulseek network: //! login with a throwaway account, run one search, print results. //! //! cargo run -p soulseek-client --example probe -- "search terms" use soulseek_client::{Client, Config, Event}; #[tokio::main] async fn main() { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let query = std::env::args() .nth(1) .unwrap_or_else(|| "daft punk discovery".into()); let suffix = std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .subsec_nanos() % 100_000; let username = format!("ssplusdev{suffix}"); println!("connecting…"); let (client, mut events) = Client::connect(Config::default()).await.expect("connect"); println!("listener on port {}", client.listen_port()); match client.login(&username, "ssplusdev-throwaway").await { Ok(greeting) => println!("logged in as {username}: {}", greeting.trim()), Err(e) => { eprintln!("login failed: {e}"); return; } } let token = client.search(&query).expect("search"); println!("searching for {query:?} (token {token}) — collecting for 25s…\n"); let mut responses = 0usize; let mut files = 0usize; let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(25); loop { let ev = tokio::select! { ev = events.recv() => ev, _ = tokio::time::sleep_until(deadline) => break, }; match ev { Some(Event::SearchResult { response, .. }) => { responses += 1; files += response.files.len(); if responses <= 5 { let f = &response.files[0]; println!( " [{}] {} files, e.g. {} ({} MB{}) slots={} speed={}", response.username, response.files.len(), f.filename.rsplit('\\').next().unwrap_or(&f.filename), f.size / 1_000_000, f.bitrate() .map(|b| format!(", {b} kbps")) .unwrap_or_default(), response.has_free_upload_slot, response.upload_speed, ); } } Some(Event::Disconnected { reason }) => { println!("disconnected: {reason}"); break; } Some(_) => {} None => break, } } println!("\nRESULT: {responses} responses, {files} files"); client.shutdown(); }