use std::sync::Arc;
use std::time::Duration;
use crate::chain::ProxyChain;
use crate::proxy::Proxy;
use crate::tools::{ping_proxy_chain_parallel, ping_proxy_parallel};
pub async fn compare_proxies(proxies: Vec<impl Into<Proxy>>, timeout: Option<u64>) -> Option<Proxy> {
let mut tasks = Vec::with_capacity(proxies.len());
for proxy_impl in proxies {
let proxy_arc = Arc::new(proxy_impl.into());
let task_proxy = proxy_arc.clone();
let task = tokio::spawn(ping_proxy_parallel(task_proxy, None));
tasks.push((proxy_arc, task));
}
let mut results = Vec::with_capacity(tasks.len());
for (proxy, task) in tasks {
let info;
if let Some(t) = timeout {
info = match tokio::time::timeout(Duration::from_millis(t), task).await {
Ok(r) => match r {
Ok(i) => i,
Err(_) => continue,
},
Err(_) => continue,
};
} else {
info = match task.await {
Ok(i) => i,
Err(_) => continue,
};
}
results.push((proxy, info));
}
let mut current_min_ping = None;
let mut best_proxy = None;
for (proxy, info) in results {
if let Some(min_ping) = current_min_ping {
if let Some(average_ping) = info.average_ping {
if min_ping > average_ping {
current_min_ping = Some(average_ping);
best_proxy = Some(Proxy::from(proxy));
}
}
} else {
current_min_ping = info.average_ping;
best_proxy = Some(Proxy::from(proxy));
}
}
best_proxy
}
pub async fn compare_proxy_chains(chains: Vec<impl Into<ProxyChain>>, timeout: Option<u64>) -> Option<ProxyChain> {
let mut tasks = Vec::with_capacity(chains.len());
for chain_impl in chains {
let chain_arc = Arc::new(chain_impl.into());
let task_chain = chain_arc.clone();
let task = tokio::spawn(ping_proxy_chain_parallel(task_chain, None));
tasks.push((chain_arc, task));
}
let mut results = Vec::with_capacity(tasks.len());
for (chain, task) in tasks {
let info;
if let Some(t) = timeout {
info = match tokio::time::timeout(Duration::from_millis(t), task).await {
Ok(r) => match r {
Ok(i) => i,
Err(_) => continue,
},
Err(_) => continue,
};
} else {
info = match task.await {
Ok(i) => i,
Err(_) => continue,
};
}
results.push((chain, info));
}
let mut current_min_ping = None;
let mut best_chain = None;
for (chain, info) in results {
if let Some(min_ping) = current_min_ping {
if let Some(average_ping) = info.average_ping {
if min_ping > average_ping {
current_min_ping = Some(average_ping);
best_chain = Some(ProxyChain::from(chain));
}
}
} else {
current_min_ping = info.average_ping;
best_chain = Some(ProxyChain::from(chain));
}
}
best_chain
}