forked from Keelrleek/SoulStream
The previous .git directory was found gutted (only info/ remained), so history is unrecoverable locally. This commit restores version control with the tree exactly as it stands: the working app, the preview-tracks launcher on the artist hero, the scrollable-track-previews design bundle (docs + approved mockups), and the Phase 0 validation artifacts.
87 lines
3.0 KiB
Rust
87 lines
3.0 KiB
Rust
//! Live citizenship test: share our downloaded albums, join the distributed
|
|
//! network, and report every search we answer for real peers.
|
|
//!
|
|
//! cargo run -p soulseek-client --example citizen
|
|
|
|
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 suffix = std::time::SystemTime::now()
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
.unwrap()
|
|
.subsec_nanos()
|
|
% 100_000;
|
|
let username = format!("ssplusshare{suffix}");
|
|
|
|
let music = dirs_music().join("SoulSeek+");
|
|
let mut config = Config::default();
|
|
config.shared_folders = vec![music.clone()];
|
|
config.upload_slots = 4;
|
|
config.description = "SoulSeek+ dev share".into();
|
|
|
|
println!("sharing {}…", music.display());
|
|
let (client, mut events) = Client::connect(config).await.expect("connect");
|
|
let (dirs, files) = client.share_counts();
|
|
println!("indexed {files} files in {dirs} folders");
|
|
|
|
client
|
|
.login(&username, "ssplusdev-throwaway")
|
|
.await
|
|
.expect("login");
|
|
println!("logged in as {username}; joining network, waiting for searches to answer…\n");
|
|
|
|
let mut answered = 0usize;
|
|
let mut uploads = 0usize;
|
|
let start = tokio::time::Instant::now();
|
|
let deadline = start + std::time::Duration::from_secs(180);
|
|
let mut next_tick = start + std::time::Duration::from_secs(20);
|
|
loop {
|
|
let ev = tokio::select! {
|
|
ev = events.recv() => ev,
|
|
_ = tokio::time::sleep_until(next_tick) => {
|
|
next_tick += std::time::Duration::from_secs(20);
|
|
println!(
|
|
" … {}s: parent={}, {} searches seen, {answered} answered",
|
|
start.elapsed().as_secs(),
|
|
client.has_parent(),
|
|
client.searches_seen(),
|
|
);
|
|
if tokio::time::Instant::now() >= deadline { break; }
|
|
continue;
|
|
}
|
|
};
|
|
match ev {
|
|
Some(Event::RespondedToSearch { username, files }) => {
|
|
answered += 1;
|
|
if answered <= 25 {
|
|
println!(" ✓ answered {username} with {files} file(s)");
|
|
}
|
|
}
|
|
Some(Event::Upload(u)) => {
|
|
uploads += 1;
|
|
println!(" ⬆ upload to {}: {:?} {}", u.username, u.state, u.filename);
|
|
}
|
|
Some(Event::Disconnected { reason }) => {
|
|
println!("disconnected: {reason}");
|
|
break;
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
println!(
|
|
"\nRESULT: {} searches seen, {answered} answered, {uploads} upload events",
|
|
client.searches_seen(),
|
|
);
|
|
client.shutdown();
|
|
}
|
|
|
|
fn dirs_music() -> std::path::PathBuf {
|
|
// %USERPROFILE%\Music
|
|
let profile = std::env::var("USERPROFILE").unwrap_or_else(|_| ".".into());
|
|
std::path::PathBuf::from(profile).join("Music")
|
|
}
|