#![cfg(feature = "browser")]
use crate::Error;
use crate::scraper::CloudScraper;
use headless_chrome::Tab;
use std::sync::Arc;
use std::time::Duration;
pub struct GenericSolver;
impl GenericSolver {
pub fn solve_cloudflare_turnstile(tab: &Arc<Tab>) -> Result<(), Error> {
let challenge_selectors = vec![
".cf-turnstile",
"#challenge-stage",
"input[type='checkbox']",
];
for selector in challenge_selectors {
if let Ok(element) = tab.wait_for_element(selector) {
let box_model = element
.get_box_model()
.map_err(|e| Error::BrowserError(format!("Box model failed: {}", e)))?;
let center_x = box_model.content.most_left();
let center_y = box_model.content.most_top();
CloudScraper::human_move_mouse(tab, center_x, center_y)?;
std::thread::sleep(Duration::from_millis(150));
tab.click_point(headless_chrome::browser::tab::point::Point {
x: center_x,
y: center_y,
})
.map_err(|e| Error::InteractionError(format!("Click failed: {}", e)))?;
std::thread::sleep(Duration::from_secs(3));
return Ok(());
}
}
Err(Error::InteractionError(
"Could not find a challenge element to solve".to_string(),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use headless_chrome::Browser;
#[cfg(feature = "browser")]
#[test]
fn test_solve_cloudflare_turnstile_not_found() {
let browser = Browser::default().expect("Expected to get a browser");
let tab = browser.new_tab().expect("Expected to get a tab");
let result = GenericSolver::solve_cloudflare_turnstile(&tab);
assert!(result.is_err());
}
#[cfg(feature = "browser")]
#[test]
fn test_solve_cloudflare_turnstile_success() {
let browser = Browser::default().expect("Failed to launch");
let tab = browser.new_tab().expect("Failed to create tab");
let html_content = "<html><body><div class='cf-turnstile' style='width: 300px; height: 65px;'></div></body></html>";
let file_path = std::env::temp_dir().join("test_solver.html");
std::fs::write(&file_path, html_content).expect("Failed to write mock HTML");
let file_url = format!("file://{}", file_path.display());
tab.navigate_to(&file_url).expect("Failed to navigate");
tab.wait_until_navigated().expect("Failed to wait");
let result = GenericSolver::solve_cloudflare_turnstile(&tab);
assert!(result.is_ok());
}
}