cloudscraper_rs/challenges/solvers/
mod.rs

1//! Challenge solver module registry.
2//!
3//! Each submodule implements a solver for a specific Cloudflare mitigation.
4
5pub mod access_denied;
6pub mod bot_management;
7pub mod javascript_v1;
8pub mod javascript_v2;
9pub mod managed_v3;
10pub mod rate_limit;
11pub mod turnstile;
12
13use std::collections::HashMap;
14use std::time::Duration;
15
16/// Common solver interface to be implemented once logic is ported.
17pub trait ChallengeSolver {
18    fn name(&self) -> &'static str;
19}
20
21/// Records domain-level mitigation failures without depending on the full state manager.
22pub trait FailureRecorder {
23    fn record_failure(&self, domain: &str, reason: &str);
24}
25
26/// Provides fingerprint invalidation semantics for mitigation strategies.
27pub trait FingerprintManager {
28    fn invalidate(&mut self, domain: &str);
29}
30
31/// Provides TLS profile rotation semantics for mitigation strategies.
32pub trait TlsProfileManager {
33    fn rotate_profile(&mut self, domain: &str);
34}
35
36/// Standardised mitigation instructions returned by non-form-based solvers.
37#[derive(Debug, Clone, PartialEq)]
38pub struct MitigationPlan {
39    pub should_retry: bool,
40    pub wait: Option<Duration>,
41    pub reason: String,
42    pub new_proxy: Option<String>,
43    pub headers: HashMap<String, String>,
44    pub metadata: HashMap<String, String>,
45}
46
47impl MitigationPlan {
48    pub fn retry_after(wait: Duration, reason: impl Into<String>) -> Self {
49        Self {
50            should_retry: true,
51            wait: Some(wait),
52            reason: reason.into(),
53            new_proxy: None,
54            headers: HashMap::new(),
55            metadata: HashMap::new(),
56        }
57    }
58
59    pub fn retry_immediately(reason: impl Into<String>) -> Self {
60        Self {
61            should_retry: true,
62            wait: None,
63            reason: reason.into(),
64            new_proxy: None,
65            headers: HashMap::new(),
66            metadata: HashMap::new(),
67        }
68    }
69
70    pub fn no_retry(reason: impl Into<String>) -> Self {
71        Self {
72            should_retry: false,
73            wait: None,
74            reason: reason.into(),
75            new_proxy: None,
76            headers: HashMap::new(),
77            metadata: HashMap::new(),
78        }
79    }
80
81    pub fn with_proxy(mut self, proxy: impl Into<String>) -> Self {
82        self.new_proxy = Some(proxy.into());
83        self
84    }
85
86    pub fn insert_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
87        self.metadata.insert(key.into(), value.into());
88        self
89    }
90}
91
92/// Helper enum referencing all solver variants.
93#[allow(dead_code)]
94pub enum SolverVariant {
95    JavascriptV1,
96    JavascriptV2,
97    ManagedV3,
98    Turnstile,
99    RateLimit,
100    AccessDenied,
101    BotManagement,
102}