diff --git a/src/checker.rs b/src/checker.rs index 6bc184c..fa530f2 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -2,25 +2,25 @@ use std::sync::Arc; use color_eyre::eyre::WrapErr as _; -use crate::{ - config::Config, - event::{AppEvent, Event}, - proxy::Proxy, - storage::ProxyStorage, -}; +use crate::{config::Config, proxy::Proxy, storage::ProxyStorage}; + +#[cfg(feature = "tui")] +use crate::event::{AppEvent, Event}; async fn check_one( config: Arc, mut proxy: Proxy, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result { let check_result = proxy .check(Arc::clone(&config)) .await .wrap_err("proxy did not pass checking"); + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::ProxyChecked(proxy.protocol.clone())))?; match check_result { Ok(()) => { + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::ProxyWorking( proxy.protocol.clone(), )))?; @@ -45,20 +45,27 @@ async fn check_one( pub async fn check_all( config: Arc, storage: ProxyStorage, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result { let semaphore = Arc::new(tokio::sync::Semaphore::new(config.max_concurrent_checks)); let mut join_set = tokio::task::JoinSet::new(); for proxy in storage { let config = Arc::clone(&config); + #[cfg(feature = "tui")] let tx = tx.clone(); let permit = Arc::clone(&semaphore) .acquire_owned() .await .wrap_err("failed to acquire semaphore")?; join_set.spawn(async move { - let result = check_one(config, proxy, tx).await; + let result = check_one( + config, + proxy, + #[cfg(feature = "tui")] + tx, + ) + .await; drop(permit); result }); diff --git a/src/event.rs b/src/event.rs index 2648f93..e5ed136 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,15 +1,22 @@ +#[cfg(feature = "tui")] use crate::proxy::ProxyType; -#[cfg_attr(not(feature = "tui"), expect(dead_code))] pub enum AppEvent { + #[cfg(feature = "tui")] GeoDbTotal(Option), + #[cfg(feature = "tui")] GeoDbDownloaded(usize), + #[cfg(feature = "tui")] SourcesTotal(ProxyType, usize), + #[cfg(feature = "tui")] SourceScraped(ProxyType), + #[cfg(feature = "tui")] TotalProxies(ProxyType, usize), + #[cfg(feature = "tui")] ProxyChecked(ProxyType), + #[cfg(feature = "tui")] ProxyWorking(ProxyType), Done, diff --git a/src/geodb.rs b/src/geodb.rs index 8ef6aec..76c49fd 100644 --- a/src/geodb.rs +++ b/src/geodb.rs @@ -3,11 +3,10 @@ use std::{io, path::PathBuf}; use color_eyre::eyre::WrapErr as _; use tokio::io::AsyncWriteExt as _; -use crate::{ - event::{AppEvent, Event}, - fs::get_cache_path, - utils::is_docker, -}; +use crate::{fs::get_cache_path, utils::is_docker}; + +#[cfg(feature = "tui")] +use crate::event::{AppEvent, Event}; const GEODB_URL: &str = "https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-City.mmdb"; @@ -65,8 +64,9 @@ async fn save_etag( async fn save_geodb( mut response: reqwest::Response, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result<()> { + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::GeoDbTotal(response.content_length())))?; let geodb_file = get_geodb_path().await.wrap_err("failed to get GeoDB path")?; @@ -82,6 +82,7 @@ async fn save_geodb( file.write_all(&chunk).await.wrap_err_with(|| { format!("failed to write to file {}", geodb_file.display()) })?; + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::GeoDbDownloaded(chunk.len())))?; } Ok(()) @@ -89,7 +90,7 @@ async fn save_geodb( pub async fn download_geodb( http_client: reqwest::Client, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result<()> { let geodb_file = get_geodb_path().await.wrap_err("failed to get GeoDB path")?; @@ -120,7 +121,13 @@ pub async fn download_geodb( let etag = response.headers().get(reqwest::header::ETAG).cloned(); - save_geodb(response, tx.clone()).await.wrap_err("failed to save GeoDB")?; + save_geodb( + response, + #[cfg(feature = "tui")] + tx.clone(), + ) + .await + .wrap_err("failed to save GeoDB")?; if is_docker().await { log::info!( diff --git a/src/main.rs b/src/main.rs index 8589221..c9e9415 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,15 +87,22 @@ async fn main() -> color_eyre::Result<()> { let maybe_geodb_task = config.enable_geolocation.then(|| { let http_client = http_client.clone(); + #[cfg(feature = "tui")] let tx = tx.clone(); - tokio::spawn( - async move { geodb::download_geodb(http_client, tx).await }, - ) + tokio::spawn(async move { + geodb::download_geodb( + http_client, + #[cfg(feature = "tui")] + tx, + ) + .await + }) }); let mut storage = scraper::scrape_all( Arc::clone(&config), http_client.clone(), + #[cfg(feature = "tui")] tx.clone(), ) .await?; @@ -110,9 +117,14 @@ async fn main() -> color_eyre::Result<()> { } if !config.check_website.is_empty() { - storage = checker::check_all(Arc::clone(&config), storage, tx.clone()) - .await - .wrap_err("failed to check proxies")?; + storage = checker::check_all( + Arc::clone(&config), + storage, + #[cfg(feature = "tui")] + tx.clone(), + ) + .await + .wrap_err("failed to check proxies")?; } output::save_proxies(config, storage).await?; diff --git a/src/scraper.rs b/src/scraper.rs index d759eaf..03cb01c 100644 --- a/src/scraper.rs +++ b/src/scraper.rs @@ -4,13 +4,15 @@ use color_eyre::eyre::WrapErr as _; use crate::{ config::Config, - event::{AppEvent, Event}, parsers::PROXY_REGEX, proxy::{Proxy, ProxyType}, storage::ProxyStorage, utils::is_http_url, }; +#[cfg(feature = "tui")] +use crate::event::{AppEvent, Event}; + async fn fetch_text( config: Arc, http_client: reqwest::Client, @@ -48,11 +50,12 @@ async fn scrape_one( http_client: reqwest::Client, proto: ProxyType, source: &str, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result> { let text_result = fetch_text(Arc::clone(&config), http_client.clone(), source).await; + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::SourceScraped(proto.clone())))?; let text = match text_result { @@ -111,10 +114,11 @@ async fn scrape_one( pub async fn scrape_all( config: Arc, http_client: reqwest::Client, - tx: tokio::sync::mpsc::UnboundedSender, + #[cfg(feature = "tui")] tx: tokio::sync::mpsc::UnboundedSender, ) -> color_eyre::Result { let mut join_set = tokio::task::JoinSet::new(); for (proto, sources) in config.sources.clone() { + #[cfg(feature = "tui")] tx.send(Event::App(AppEvent::SourcesTotal( proto.clone(), sources.len(), @@ -123,9 +127,18 @@ pub async fn scrape_all( let config = Arc::clone(&config); let http_client = http_client.clone(); let proto = proto.clone(); + #[cfg(feature = "tui")] let tx = tx.clone(); join_set.spawn(async move { - scrape_one(config, http_client, proto, &source, tx).await + scrape_one( + config, + http_client, + proto, + &source, + #[cfg(feature = "tui")] + tx, + ) + .await }); } } @@ -133,11 +146,14 @@ pub async fn scrape_all( let mut storage = ProxyStorage::new(config.sources.keys().cloned().collect()); while let Some(res) = join_set.join_next().await { + #[cfg(feature = "tui")] let mut seen_protocols = HashSet::new(); for proxy in res.wrap_err("failed to join proxy scrape task")?? { + #[cfg(feature = "tui")] seen_protocols.insert(proxy.protocol.clone()); storage.insert(proxy); } + #[cfg(feature = "tui")] for proto in seen_protocols { let count = storage.iter().filter(|p| p.protocol == proto).count(); tx.send(Event::App(AppEvent::TotalProxies(proto, count)))?;