capmonstercloud_client/requests/
datadome.rs1use serde::Serialize;
2
3use super::{require_non_empty, CaptchaRequest};
4use crate::error::Result;
5use crate::proxy::ProxyInfo;
6use crate::timeouts::GetResultTimeouts;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
10pub enum DataDomeVersion {
11 #[serde(rename = "new")]
13 New,
14}
15
16#[derive(Debug, Clone, Serialize)]
19pub struct DataDomeMetadata {
20 #[serde(rename = "captchaUrl")]
24 pub captcha_url: String,
25 #[serde(rename = "datadomeCookie")]
27 pub datadome_cookie: String,
28 #[serde(rename = "datadomeVersion", skip_serializing_if = "Option::is_none")]
30 pub datadome_version: Option<DataDomeVersion>,
31}
32
33impl DataDomeMetadata {
34 pub fn new(captcha_url: impl Into<String>, datadome_cookie: impl Into<String>) -> Self {
35 Self {
36 captcha_url: captcha_url.into(),
37 datadome_cookie: datadome_cookie.into(),
38 datadome_version: None,
39 }
40 }
41
42 pub fn with_datadome_version(mut self, value: DataDomeVersion) -> Self {
43 self.datadome_version = Some(value);
44 self
45 }
46}
47
48#[derive(Debug, Clone, Serialize)]
52pub struct DataDomeCustomTaskRequest {
53 #[serde(rename = "websiteURL")]
55 pub website_url: String,
56 pub metadata: DataDomeMetadata,
57 #[serde(flatten)]
59 pub proxy: ProxyInfo,
60 #[serde(rename = "userAgent", skip_serializing_if = "Option::is_none")]
62 pub user_agent: Option<String>,
63}
64
65impl DataDomeCustomTaskRequest {
66 pub fn new(
67 website_url: impl Into<String>,
68 metadata: DataDomeMetadata,
69 proxy: ProxyInfo,
70 ) -> Self {
71 Self {
72 website_url: website_url.into(),
73 metadata,
74 proxy,
75 user_agent: None,
76 }
77 }
78
79 pub fn with_user_agent(mut self, value: impl Into<String>) -> Self {
80 self.user_agent = Some(value.into());
81 self
82 }
83}
84
85impl CaptchaRequest for DataDomeCustomTaskRequest {
86 const TASK_TYPE: &'static str = "CustomTask";
87 const CLASS: Option<&'static str> = Some("DataDome");
88
89 fn timeouts(&self) -> GetResultTimeouts {
90 GetResultTimeouts::secs(1.0, 0.0, 3.0, 180.0)
91 }
92
93 fn validate(&self) -> Result<()> {
94 require_non_empty("websiteURL", &self.website_url)?;
95 require_non_empty("metadata.captchaUrl", &self.metadata.captcha_url)?;
96 require_non_empty("metadata.datadomeCookie", &self.metadata.datadome_cookie)?;
97 Ok(())
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::proxy::ProxyType;
105 use serde_json::json;
106
107 fn proxy() -> ProxyInfo {
108 ProxyInfo::new(ProxyType::Http, "1.2.3.4", 8080).with_auth("u", "p")
109 }
110
111 #[test]
112 fn minimal_task() {
113 let task = DataDomeCustomTaskRequest::new(
114 "https://example.com",
115 DataDomeMetadata::new(
116 "https://geo.captcha-delivery.com/captcha/?t=fe",
117 "datadome=abc",
118 ),
119 proxy(),
120 )
121 .to_task()
122 .unwrap();
123 assert_eq!(
124 task,
125 json!({
126 "type": "CustomTask", "class": "DataDome", "websiteURL": "https://example.com",
127 "metadata": {"captchaUrl": "https://geo.captcha-delivery.com/captcha/?t=fe", "datadomeCookie": "datadome=abc"},
128 "proxyType": "http", "proxyAddress": "1.2.3.4", "proxyPort": 8080,
129 "proxyLogin": "u", "proxyPassword": "p"
130 })
131 );
132 }
133
134 #[test]
135 fn full_task() {
136 let task = DataDomeCustomTaskRequest::new(
137 "https://example.com",
138 DataDomeMetadata::new("U", "C").with_datadome_version(DataDomeVersion::New),
139 proxy(),
140 )
141 .with_user_agent("UA")
142 .to_task()
143 .unwrap();
144 assert_eq!(
145 task,
146 json!({
147 "type": "CustomTask", "class": "DataDome", "websiteURL": "https://example.com",
148 "metadata": {"captchaUrl": "U", "datadomeCookie": "C", "datadomeVersion": "new"},
149 "proxyType": "http", "proxyAddress": "1.2.3.4", "proxyPort": 8080,
150 "proxyLogin": "u", "proxyPassword": "p", "userAgent": "UA"
151 })
152 );
153 }
154
155 #[test]
156 fn empty_required_strings_are_rejected() {
157 let err = DataDomeCustomTaskRequest::new(
158 "",
159 DataDomeMetadata::new("U", "C"),
160 ProxyInfo::new(ProxyType::Http, "1.2.3.4", 8080),
161 )
162 .to_task()
163 .unwrap_err();
164 assert!(matches!(err, crate::error::Error::Validation(ref m) if m.contains("websiteURL")));
165 let err = DataDomeCustomTaskRequest::new(
166 "https://example.com",
167 DataDomeMetadata::new("", "C"),
168 ProxyInfo::new(ProxyType::Http, "1.2.3.4", 8080),
169 )
170 .to_task()
171 .unwrap_err();
172 assert!(
173 matches!(err, crate::error::Error::Validation(ref m) if m.contains("metadata.captchaUrl"))
174 );
175 let err = DataDomeCustomTaskRequest::new(
176 "https://example.com",
177 DataDomeMetadata::new("U", ""),
178 ProxyInfo::new(ProxyType::Http, "1.2.3.4", 8080),
179 )
180 .to_task()
181 .unwrap_err();
182 assert!(
183 matches!(err, crate::error::Error::Validation(ref m) if m.contains("metadata.datadomeCookie"))
184 );
185 }
186}