1use serde::{Deserialize, Serialize};
37use std::collections::HashMap;
38use tracing::debug;
39
40use crate::{Result, client::Client, constants, error::Error::InternalServer, response::Response};
41
42#[derive(Debug, Serialize, Deserialize, Clone)]
74pub struct User {
75 nickname: String,
76 gender: u8,
77 country: String,
78 province: String,
79 city: String,
80 avatar: String,
81 watermark: Watermark,
82}
83
84impl User {
85 pub fn nickname(&self) -> &str {
86 &self.nickname
87 }
88
89 pub fn gender(&self) -> u8 {
90 self.gender
91 }
92
93 pub fn country(&self) -> &str {
94 &self.country
95 }
96
97 pub fn province(&self) -> &str {
98 &self.province
99 }
100
101 pub fn city(&self) -> &str {
102 &self.city
103 }
104
105 pub fn avatar(&self) -> &str {
106 &self.avatar
107 }
108
109 pub fn app_id(&self) -> &str {
110 &self.watermark.app_id
111 }
112
113 pub fn timestamp(&self) -> u64 {
114 self.watermark.timestamp
115 }
116}
117
118#[derive(Debug, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub(crate) struct UserBuilder {
121 #[serde(rename = "nickName")]
122 nickname: String,
123 gender: u8,
124 country: String,
125 province: String,
126 city: String,
127 #[serde(rename = "avatarUrl")]
128 avatar: String,
129 watermark: WatermarkBuilder,
130}
131
132impl UserBuilder {
133 pub(crate) fn build(self) -> User {
134 User {
135 nickname: self.nickname,
136 gender: self.gender,
137 country: self.country,
138 province: self.province,
139 city: self.city,
140 avatar: self.avatar,
141 watermark: self.watermark.build(),
142 }
143 }
144}
145
146#[derive(Debug, Serialize, Deserialize, Clone)]
147pub struct Contact {
148 phone_number: String,
149 pure_phone_number: String,
150 country_code: String,
151 watermark: Watermark,
152}
153
154impl Contact {
155 pub fn phone_number(&self) -> &str {
156 &self.phone_number
157 }
158
159 pub fn pure_phone_number(&self) -> &str {
160 &self.pure_phone_number
161 }
162
163 pub fn country_code(&self) -> &str {
164 &self.country_code
165 }
166
167 pub fn app_id(&self) -> &str {
168 &self.watermark.app_id
169 }
170
171 pub fn timestamp(&self) -> u64 {
172 self.watermark.timestamp
173 }
174}
175
176#[derive(Debug, Deserialize, Clone)]
177pub(crate) struct ContactBuilder {
178 #[serde(rename = "phone_info")]
179 inner: PhoneInner,
180}
181
182impl ContactBuilder {
183 pub(crate) fn build(self) -> Contact {
184 Contact {
185 phone_number: self.inner.phone_number,
186 pure_phone_number: self.inner.pure_phone_number,
187 country_code: self.inner.country_code,
188 watermark: self.inner.watermark.build(),
189 }
190 }
191}
192
193#[derive(Debug, Deserialize, Clone)]
194#[serde(rename_all = "camelCase")]
195struct PhoneInner {
196 #[serde(rename = "phoneNumber")]
197 phone_number: String,
198 #[serde(rename = "purePhoneNumber")]
199 pure_phone_number: String,
200 country_code: String,
201 watermark: WatermarkBuilder,
202}
203
204#[derive(Debug, Serialize, Deserialize, Clone)]
205struct Watermark {
206 app_id: String,
207 timestamp: u64,
208}
209
210#[derive(Debug, Deserialize, Clone)]
211struct WatermarkBuilder {
212 #[serde(rename = "appid")]
213 app_id: String,
214 timestamp: u64,
215}
216
217impl WatermarkBuilder {
218 fn build(self) -> Watermark {
219 Watermark {
220 app_id: self.app_id,
221 timestamp: self.timestamp,
222 }
223 }
224}
225
226impl Client {
227 pub async fn get_contact(&self, code: &str, open_id: Option<&str>) -> Result<Contact> {
286 debug!("code: {}, open_id: {:?}", code, open_id);
287
288 let mut query = HashMap::new();
289 let mut body = HashMap::new();
290
291 query.insert("access_token", self.token().await?);
292 body.insert("code", code);
293
294 if let Some(open_id) = open_id {
295 body.insert("openid", open_id);
296 }
297
298 let response = self
299 .request()
300 .post(constants::PHONE_END_POINT)
301 .query(&query)
302 .json(&body)
303 .send()
304 .await?;
305
306 debug!("response: {:#?}", response);
307
308 if response.status().is_success() {
309 let response = response.json::<Response<ContactBuilder>>().await?;
310
311 let builder = response.extract()?;
312
313 debug!("contact builder: {:#?}", builder);
314
315 Ok(builder.build())
316 } else {
317 Err(InternalServer(response.text().await?))
318 }
319 }
320}