1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
7#[serde(rename_all = "camelCase")]
8pub enum ChallengeType {
9 RecaptchaV2Checkbox,
10 RecaptchaV3,
11 TextCaptcha,
12 ImageGridCaptcha,
13 MfaCodeEntry,
14}
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
18pub struct ChallengeDetection {
19 pub challenge_type: ChallengeType,
20 pub confidence: f32,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub region: Option<ChallengeRegion>,
23 #[serde(default)]
24 pub blocking: bool,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub hints: Option<ChallengeDetectionHints>,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
30#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
31pub struct ChallengeRegion {
32 pub x: f32,
33 pub y: f32,
34 pub width: f32,
35 pub height: f32,
36}
37
38#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
40pub struct ChallengeDetectionHints {
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub target_field_purpose: Option<String>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub instruction_text: Option<String>,
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
49pub struct DetectChallengeIntent {
50 pub purpose: String,
51 #[serde(default)]
52 pub hints: DetectChallengeHints,
53}
54
55#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
56#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
57#[serde(rename_all = "camelCase")]
58pub struct DetectChallengeHints {
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub region: Option<ChallengeRegion>,
62 #[serde(default = "default_detect_timeout_ms")]
64 pub timeout_ms: u64,
65}
66
67impl Default for DetectChallengeHints {
68 fn default() -> Self {
69 Self {
70 region: None,
71 timeout_ms: default_detect_timeout_ms(),
72 }
73 }
74}
75
76fn default_detect_timeout_ms() -> u64 {
77 15_000
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
81#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
82pub struct SolveChallengeIntent {
83 pub purpose: String,
84 #[serde(default)]
85 pub hints: SolveChallengeHints,
86}
87
88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
89#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
90#[serde(rename_all = "camelCase")]
91pub struct SolveChallengeHints {
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub region: Option<ChallengeRegion>,
94 #[serde(default = "default_solve_timeout_ms")]
95 pub timeout_ms: u64,
96}
97
98impl Default for SolveChallengeHints {
99 fn default() -> Self {
100 Self {
101 region: None,
102 timeout_ms: default_solve_timeout_ms(),
103 }
104 }
105}
106
107fn default_solve_timeout_ms() -> u64 {
108 30_000
109}
110
111#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
112#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
113#[serde(tag = "kind", rename_all = "camelCase")]
114pub enum SolveStep {
115 Click {
116 x: f32,
117 y: f32,
118 },
119 TypeText {
120 text: String,
121 target_field_purpose: String,
122 },
123 WaitAndReassess {
124 ms: u64,
125 },
126}