use crate::fetchers::response::Response;
pub fn is_duckduckgo_blocked(response: &Response) -> bool {
if !response.url().contains("duckduckgo.com") {
return false;
}
if response.status() == 202 {
return true;
}
response.is_success() && !response.text().contains("result__a")
}
pub fn decode_duckduckgo_href(href: &str) -> String {
let full = if let Some(stripped) = href.strip_prefix("//") {
format!("https://{}", stripped)
} else {
href.to_string()
};
if let Ok(parsed) = url::Url::parse(&full) {
let is_ddg_redirect = parsed
.host_str()
.map(|h| h.contains("duckduckgo.com"))
.unwrap_or(false)
&& parsed.path() == "/l/";
if is_ddg_redirect {
if let Some((_, target)) = parsed.query_pairs().find(|(k, _)| k == "uddg") {
return target.into_owned();
}
}
}
href.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
fn resp(status: u16, url: &str, body: &str) -> Response {
Response::new(
status,
"text/html".to_string(),
body.to_string(),
url.to_string(),
HashMap::new(),
)
}
#[test]
fn decodes_ddg_redirect_href() {
let href = "//duckduckgo.com/l/?uddg=https%3A%2F%2Fwww.andritz.com%2F&rut=abc";
assert_eq!(decode_duckduckgo_href(href), "https://www.andritz.com/");
}
#[test]
fn passes_through_non_ddg_href() {
assert_eq!(
decode_duckduckgo_href("https://example.com/page"),
"https://example.com/page"
);
}
#[test]
fn passes_through_ddg_non_redirect_path() {
let href = "//duckduckgo.com/about";
assert_eq!(decode_duckduckgo_href(href), href);
}
#[test]
fn detects_202_soft_block() {
let r = resp(
202,
"https://html.duckduckgo.com/html/?q=x",
"<html>home</html>",
);
assert!(is_duckduckgo_blocked(&r));
}
#[test]
fn detects_homepage_without_results() {
let r = resp(
200,
"https://html.duckduckgo.com/html/?q=x",
"<html>no results here</html>",
);
assert!(is_duckduckgo_blocked(&r));
}
#[test]
fn real_ddg_results_are_not_blocked() {
let r = resp(
200,
"https://html.duckduckgo.com/html/?q=x",
"<a class=\"result__a\" href=\"//duckduckgo.com/l/?uddg=https%3A%2F%2Fx\">X</a>",
);
assert!(!is_duckduckgo_blocked(&r));
}
#[test]
fn non_ddg_response_is_never_ddg_blocked() {
let r = resp(202, "https://example.com", "");
assert!(!is_duckduckgo_blocked(&r));
}
}