Skip to main content

antibot_rs/
types.rs

1use crate::cookie::Cookie;
2use serde::Deserialize;
3use std::time::{Duration, SystemTime};
4
5/// Where this solution came from.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum SolutionSource {
8    /// A fresh solve was performed by the underlying provider.
9    Fresh,
10    /// Returned from the in-process session cache.
11    Cached { age: Duration },
12}
13
14impl SolutionSource {
15    pub fn is_cached(&self) -> bool {
16        matches!(self, SolutionSource::Cached { .. })
17    }
18}
19
20/// Result of a solve. `response` is `None` for cache hits when only the
21/// cookies/user-agent were preserved; check [`SolutionSource`] to disambiguate.
22#[derive(Debug, Clone)]
23pub struct Solution {
24    pub url: String,
25    pub status: u16,
26    pub cookies: Vec<Cookie>,
27    pub user_agent: String,
28    /// Fully rendered HTML of the page. `None` on session-cache hits.
29    pub response: Option<String>,
30    pub solved_at: SystemTime,
31    pub source: SolutionSource,
32}
33
34impl Solution {
35    /// Format cookies as a `Cookie` header value.
36    pub fn cookie_header(&self) -> String {
37        self.cookies
38            .iter()
39            .map(|c| format!("{}={}", c.name, c.value))
40            .collect::<Vec<_>>()
41            .join("; ")
42    }
43
44    /// HTML body, or empty string if absent.
45    pub fn html(&self) -> &str {
46        self.response.as_deref().unwrap_or("")
47    }
48
49    pub(crate) fn from_wire(s: WireSolution) -> Self {
50        Self {
51            url: s.url,
52            status: s.status,
53            cookies: s.cookies,
54            user_agent: s.user_agent,
55            response: Some(s.response),
56            solved_at: SystemTime::now(),
57            source: SolutionSource::Fresh,
58        }
59    }
60}
61
62/// Wire-format solution as returned by FlareSolverr/Byparr `/v1`.
63#[derive(Debug, Clone, Deserialize)]
64pub(crate) struct WireSolution {
65    pub url: String,
66    pub status: u16,
67    pub cookies: Vec<Cookie>,
68    #[serde(rename = "userAgent")]
69    pub user_agent: String,
70    pub response: String,
71}
72
73/// Full response from the `/v1` endpoint.
74#[derive(Debug, Deserialize)]
75pub(crate) struct ApiResponse {
76    pub status: String,
77    #[serde(default)]
78    pub message: String,
79    pub solution: Option<WireSolution>,
80    /// Returned for session.create (and similar lifecycle calls).
81    #[serde(default)]
82    pub session: Option<String>,
83}