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