use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::error::Result;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CaptchaKind {
ReCaptcha,
HCaptcha,
Turnstile,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CaptchaConfig {
pub provider: String,
pub api_key: Option<String>,
pub client_key: Option<String>,
pub proxy: Option<String>,
pub no_proxy: bool,
}
#[async_trait]
pub trait CaptchaSolver: Send + Sync {
async fn solve(
&self,
kind: CaptchaKind,
page_url: &str,
site_key: &str,
config: &CaptchaConfig,
) -> Result<String>;
}
pub mod anticaptcha;
pub mod capsolver;
pub mod twocaptcha;
pub use anticaptcha::AntiCaptchaSolver;
pub use capsolver::CapsolverSolver;
pub use twocaptcha::TwoCaptchaSolver;
pub fn make_solver(config: &CaptchaConfig) -> Option<Box<dyn CaptchaSolver>> {
match config.provider.to_lowercase().as_str() {
"2captcha" => Some(Box::new(TwoCaptchaSolver::new())),
"anticaptcha" => Some(Box::new(AntiCaptchaSolver::new())),
"capsolver" => Some(Box::new(CapsolverSolver::new())),
_ => None,
}
}