eoka-server 0.2.0

Shared browser runtime and sidecar process for eoka browser automation
Documentation
#[derive(Debug, Clone)]
pub struct CaptchaInfo {
    pub captcha_type: String,
    pub sitekey: String,
}

pub async fn detect_captcha_on_page(page: &crate::eoka::Page) -> Option<CaptchaInfo> {
    let hcaptcha_script = r#"
        (() => document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey') || null)()
    "#;
    if let Ok(result) = page.evaluate::<serde_json::Value>(hcaptcha_script).await {
        if let Some(sitekey) = result.as_str().filter(|key| !key.is_empty()) {
            return Some(CaptchaInfo {
                captcha_type: "hcaptcha".into(),
                sitekey: sitekey.into(),
            });
        }
    }

    let recaptcha_script = r#"
        (() => {
            if (![...document.scripts].some(s => s.src.includes('recaptcha'))) return null;
            return document.documentElement.innerHTML.match(/"sitekey"\s*:\s*"([^"]+)"/)?.[1] || null;
        })()
    "#;
    if let Ok(result) = page.evaluate::<serde_json::Value>(recaptcha_script).await {
        if let Some(sitekey) = result.as_str().filter(|key| !key.is_empty()) {
            return Some(CaptchaInfo {
                captcha_type: "recaptcha".into(),
                sitekey: sitekey.into(),
            });
        }
    }
    None
}