use crate::cli::Options;
use crate::detect::check::{CheckOptions, Evidence, check};
use crate::detect::report::Report;
use crate::fetch::{FetchError, RobotsCache, fetch_evidence};
pub(crate) enum CheckOutcome {
Report(Box<Report>),
Malformed(String),
}
pub(crate) fn check_url(
url: &str,
index: Option<usize>,
options: &Options,
robots: &RobotsCache,
) -> CheckOutcome {
let started = std::time::Instant::now();
let mut evidence: Evidence = match render_evidence(url, options, robots) {
Some(evidence) => evidence,
None => match fetch_evidence(url, robots) {
Ok(evidence) => evidence,
Err(FetchError::Malformed(reason)) => return CheckOutcome::Malformed(reason),
Err(FetchError::Blocked(reason)) => {
return CheckOutcome::Report(Box::new(crate::cli::blocked_report(
url, &reason, index,
)));
}
},
};
evidence.total_ms = u64::try_from(started.elapsed().as_millis()).unwrap_or(u64::MAX);
let report = check(
&evidence,
&CheckOptions {
agent: options.agent.clone(),
index,
},
);
CheckOutcome::Report(Box::new(report))
}
fn render_evidence(url: &str, options: &Options, robots: &RobotsCache) -> Option<Evidence> {
if options.no_render {
return None;
}
let browser = match crate::render::find_browser() {
Ok(browser) => browser,
Err(reason) => {
eprintln!("scrape-le: render unavailable — {reason}");
return None;
}
};
match crate::render::render(url, browser) {
Ok(render) => Some(Evidence::from_render(
url,
render,
crate::fetch::fetch_robots_only(url, robots),
)),
Err(reason) => {
eprintln!("scrape-le: render failed — {reason}; falling back to HTTP evidence");
None
}
}
}