1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum RiskType {
9 Slide,
11 Gobang,
13 Icon,
15 Ai,
17 Svg,
19}
20
21impl RiskType {
22 pub fn as_str(&self) -> &'static str {
24 match self {
25 RiskType::Slide => "slide",
26 RiskType::Gobang => "gobang",
27 RiskType::Icon => "icon",
28 RiskType::Ai => "ai",
29 RiskType::Svg => "svg",
30 }
31 }
32}
33
34impl std::fmt::Display for RiskType {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{}", self.as_str())
37 }
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct SecCode {
43 pub captcha_id: String,
44 pub lot_number: String,
45 pub pass_token: String,
46 pub gen_time: String,
47 pub captcha_output: String,
48}
49
50#[derive(Debug, Deserialize)]
52pub struct GeetestResponse<T> {
53 pub status: String,
54 pub data: Option<T>,
56 #[serde(default)]
58 pub code: Option<String>,
59 #[serde(default)]
61 pub msg: Option<String>,
62}
63
64#[derive(Debug, Clone, Deserialize)]
66pub struct LoadResponse {
67 pub lot_number: String,
68 pub payload: String,
69 pub process_token: String,
70 pub pt: String,
71 pub pow_detail: PowDetail,
72 #[serde(default)]
74 pub slice: Option<String>,
75 #[serde(default)]
76 pub bg: Option<String>,
77 #[serde(default)]
79 pub ques: Option<serde_json::Value>,
80 #[serde(default)]
82 pub imgs: Option<String>,
83 #[serde(default)]
85 pub svg: Option<String>,
86 #[serde(default)]
87 pub prompt: Option<String>,
88}
89
90#[derive(Debug, Clone, Deserialize)]
92pub struct PowDetail {
93 pub hashfunc: String,
94 pub version: String,
95 pub bits: u32,
96 pub datetime: String,
97}
98
99#[derive(Debug, Clone, Serialize)]
101pub struct PowResult {
102 pub pow_msg: String,
103 pub pow_sign: String,
104}
105
106#[derive(Debug, Deserialize)]
108pub struct VerifyResponse {
109 pub seccode: Option<SecCode>,
110 #[serde(default)]
111 pub result: Option<String>,
112 #[serde(default, deserialize_with = "deserialize_optional_string_or_int")]
114 pub score: Option<String>,
115 #[serde(default)]
117 pub payload: Option<String>,
118 #[serde(default)]
120 pub process_token: Option<String>,
121 #[serde(default, deserialize_with = "deserialize_optional_string_or_int")]
123 pub payload_protocol: Option<String>,
124 #[serde(default)]
126 pub lot_number: Option<String>,
127}
128
129fn deserialize_optional_string_or_int<'de, D>(
131 deserializer: D,
132) -> std::result::Result<Option<String>, D::Error>
133where
134 D: serde::Deserializer<'de>,
135{
136 use serde::de::{self, Visitor};
137
138 struct StringOrIntVisitor;
139
140 impl<'de> Visitor<'de> for StringOrIntVisitor {
141 type Value = Option<String>;
142
143 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
144 formatter.write_str("a string, integer, or null")
145 }
146
147 fn visit_none<E>(self) -> std::result::Result<Self::Value, E>
148 where
149 E: de::Error,
150 {
151 Ok(None)
152 }
153
154 fn visit_unit<E>(self) -> std::result::Result<Self::Value, E>
155 where
156 E: de::Error,
157 {
158 Ok(None)
159 }
160
161 fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
162 where
163 E: de::Error,
164 {
165 Ok(Some(v.to_string()))
166 }
167
168 fn visit_string<E>(self, v: String) -> std::result::Result<Self::Value, E>
169 where
170 E: de::Error,
171 {
172 Ok(Some(v))
173 }
174
175 fn visit_i64<E>(self, v: i64) -> std::result::Result<Self::Value, E>
176 where
177 E: de::Error,
178 {
179 Ok(Some(v.to_string()))
180 }
181
182 fn visit_u64<E>(self, v: u64) -> std::result::Result<Self::Value, E>
183 where
184 E: de::Error,
185 {
186 Ok(Some(v.to_string()))
187 }
188 }
189
190 deserializer.deserialize_any(StringOrIntVisitor)
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct CachedConstants {
196 pub version: String,
198 pub fetched_at: chrono::DateTime<chrono::Utc>,
200 pub mapping: String,
202 pub abo: HashMap<String, String>,
204 pub device_id: String,
206}
207
208#[derive(Debug, Clone)]
210pub struct Constants {
211 pub mapping: String,
212 pub abo: HashMap<String, String>,
213 pub device_id: String,
214}
215
216impl From<CachedConstants> for Constants {
217 fn from(cached: CachedConstants) -> Self {
218 Self {
219 mapping: cached.mapping,
220 abo: cached.abo,
221 device_id: cached.device_id,
222 }
223 }
224}