capmonstercloud_client/requests/
yidun.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, Serialize)]
10pub struct YidunRequest {
11 #[serde(rename = "websiteURL")]
13 pub website_url: String,
14 #[serde(rename = "websiteKey")]
16 pub website_key: String,
17 #[serde(flatten, skip_serializing_if = "Option::is_none")]
18 pub proxy: Option<ProxyInfo>,
19 #[serde(rename = "userAgent", skip_serializing_if = "Option::is_none")]
21 pub user_agent: Option<String>,
22 #[serde(rename = "yidunGetLib", skip_serializing_if = "Option::is_none")]
25 pub yidun_get_lib: Option<String>,
26 #[serde(
29 rename = "yidunApiServerSubdomain",
30 skip_serializing_if = "Option::is_none"
31 )]
32 pub yidun_api_server_subdomain: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub challenge: Option<String>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub hcg: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub hct: Option<i64>,
42}
43
44impl YidunRequest {
45 pub fn new(website_url: impl Into<String>, website_key: impl Into<String>) -> Self {
46 Self {
47 website_url: website_url.into(),
48 website_key: website_key.into(),
49 proxy: None,
50 user_agent: None,
51 yidun_get_lib: None,
52 yidun_api_server_subdomain: None,
53 challenge: None,
54 hcg: None,
55 hct: None,
56 }
57 }
58
59 pub fn with_proxy(mut self, proxy: ProxyInfo) -> Self {
60 self.proxy = Some(proxy);
61 self
62 }
63
64 pub fn with_user_agent(mut self, value: impl Into<String>) -> Self {
65 self.user_agent = Some(value.into());
66 self
67 }
68
69 pub fn with_yidun_get_lib(mut self, value: impl Into<String>) -> Self {
70 self.yidun_get_lib = Some(value.into());
71 self
72 }
73
74 pub fn with_yidun_api_server_subdomain(mut self, value: impl Into<String>) -> Self {
75 self.yidun_api_server_subdomain = Some(value.into());
76 self
77 }
78
79 pub fn with_challenge(mut self, value: impl Into<String>) -> Self {
80 self.challenge = Some(value.into());
81 self
82 }
83
84 pub fn with_hcg(mut self, value: impl Into<String>) -> Self {
85 self.hcg = Some(value.into());
86 self
87 }
88
89 pub fn with_hct(mut self, value: i64) -> Self {
90 self.hct = Some(value);
91 self
92 }
93}
94
95impl CaptchaRequest for YidunRequest {
96 const TASK_TYPE: &'static str = "YidunTask";
97
98 fn timeouts(&self) -> GetResultTimeouts {
99 GetResultTimeouts::secs(1.0, 10.0, 3.0, 180.0)
100 }
101
102 fn validate(&self) -> Result<()> {
103 require_non_empty("websiteURL", &self.website_url)?;
104 require_non_empty("websiteKey", &self.website_key)?;
105 Ok(())
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112 use crate::proxy::ProxyType;
113 use serde_json::json;
114
115 #[test]
116 fn minimal_task() {
117 let task = YidunRequest::new("https://example.com", "KEY")
118 .to_task()
119 .unwrap();
120 assert_eq!(
121 task,
122 json!({"type": "YidunTask", "websiteURL": "https://example.com", "websiteKey": "KEY"})
123 );
124 }
125
126 #[test]
127 fn full_task() {
128 let task = YidunRequest::new("https://example.com", "KEY")
129 .with_proxy(ProxyInfo::new(ProxyType::Http, "1.2.3.4", 80))
130 .with_user_agent("UA")
131 .with_yidun_get_lib("https://cstaticdun.126.net/load.min.js")
132 .with_yidun_api_server_subdomain("c.example.com")
133 .with_challenge("ch")
134 .with_hcg("hcg")
135 .with_hct(1700000000000)
136 .to_task()
137 .unwrap();
138 assert_eq!(
139 task,
140 json!({"type": "YidunTask", "websiteURL": "https://example.com", "websiteKey": "KEY",
141 "userAgent": "UA", "yidunGetLib": "https://cstaticdun.126.net/load.min.js",
142 "yidunApiServerSubdomain": "c.example.com", "challenge": "ch", "hcg": "hcg",
143 "hct": 1700000000000i64,
144 "proxyType": "http", "proxyAddress": "1.2.3.4", "proxyPort": 80})
145 );
146 }
147
148 #[test]
149 fn empty_required_strings_are_rejected() {
150 let err = YidunRequest::new("", "KEY").to_task().unwrap_err();
151 assert!(matches!(err, crate::error::Error::Validation(ref m) if m.contains("websiteURL")));
152 let err = YidunRequest::new("https://example.com", "")
153 .to_task()
154 .unwrap_err();
155 assert!(matches!(err, crate::error::Error::Validation(ref m) if m.contains("websiteKey")));
156 }
157}