1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use tracing::debug;
4
5use crate::{Result, client::Client, constants, error::Error::InternalServer, response::Response};
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8pub struct User {
9 nickname: String,
10 gender: u8,
11 country: String,
12 province: String,
13 city: String,
14 avatar: String,
15 watermark: Watermark,
16}
17
18impl User {
19 pub fn nickname(&self) -> &str {
20 &self.nickname
21 }
22
23 pub fn gender(&self) -> u8 {
24 self.gender
25 }
26
27 pub fn country(&self) -> &str {
28 &self.country
29 }
30
31 pub fn province(&self) -> &str {
32 &self.province
33 }
34
35 pub fn city(&self) -> &str {
36 &self.city
37 }
38
39 pub fn avatar(&self) -> &str {
40 &self.avatar
41 }
42
43 pub fn app_id(&self) -> &str {
44 &self.watermark.app_id
45 }
46
47 pub fn timestamp(&self) -> u64 {
48 self.watermark.timestamp
49 }
50}
51
52#[derive(Debug, Deserialize)]
53#[serde(rename_all = "camelCase")]
54pub(crate) struct UserBuilder {
55 #[serde(rename = "nickName")]
56 nickname: String,
57 gender: u8,
58 country: String,
59 province: String,
60 city: String,
61 #[serde(rename = "avatarUrl")]
62 avatar: String,
63 watermark: WatermarkBuilder,
64}
65
66impl UserBuilder {
67 pub(crate) fn build(self) -> User {
68 User {
69 nickname: self.nickname,
70 gender: self.gender,
71 country: self.country,
72 province: self.province,
73 city: self.city,
74 avatar: self.avatar,
75 watermark: self.watermark.build(),
76 }
77 }
78}
79
80#[derive(Debug, Serialize, Deserialize, Clone)]
81pub struct Contact {
82 phone_number: String,
83 pure_phone_number: String,
84 country_code: String,
85 watermark: Watermark,
86}
87
88impl Contact {
89 pub fn phone_number(&self) -> &str {
90 &self.phone_number
91 }
92
93 pub fn pure_phone_number(&self) -> &str {
94 &self.pure_phone_number
95 }
96
97 pub fn country_code(&self) -> &str {
98 &self.country_code
99 }
100
101 pub fn app_id(&self) -> &str {
102 &self.watermark.app_id
103 }
104
105 pub fn timestamp(&self) -> u64 {
106 self.watermark.timestamp
107 }
108}
109
110#[derive(Debug, Deserialize, Clone)]
111pub(crate) struct ContactBuilder {
112 #[serde(rename = "phone_info")]
113 inner: PhoneInner,
114}
115
116impl ContactBuilder {
117 pub(crate) fn build(self) -> Contact {
118 Contact {
119 phone_number: self.inner.phone_number,
120 pure_phone_number: self.inner.pure_phone_number,
121 country_code: self.inner.country_code,
122 watermark: self.inner.watermark.build(),
123 }
124 }
125}
126
127#[derive(Debug, Deserialize, Clone)]
128#[serde(rename_all = "camelCase")]
129struct PhoneInner {
130 #[serde(rename = "phoneNumber")]
131 phone_number: String,
132 #[serde(rename = "purePhoneNumber")]
133 pure_phone_number: String,
134 country_code: String,
135 watermark: WatermarkBuilder,
136}
137
138#[derive(Debug, Serialize, Deserialize, Clone)]
139struct Watermark {
140 app_id: String,
141 timestamp: u64,
142}
143
144#[derive(Debug, Deserialize, Clone)]
145struct WatermarkBuilder {
146 #[serde(rename = "appid")]
147 app_id: String,
148 timestamp: u64,
149}
150
151impl WatermarkBuilder {
152 fn build(self) -> Watermark {
153 Watermark {
154 app_id: self.app_id,
155 timestamp: self.timestamp,
156 }
157 }
158}
159
160impl Client {
161 pub async fn get_contact(&self, code: &str, open_id: Option<&str>) -> Result<Contact> {
177 debug!("code: {}, open_id: {:?}", code, open_id);
178
179 let mut query = HashMap::new();
180 let mut body = HashMap::new();
181
182 query.insert("access_token", self.access_token().await?);
183 body.insert("code", code);
184
185 if let Some(open_id) = open_id {
186 body.insert("openid", open_id);
187 }
188
189 let response = self
190 .request()
191 .post(constants::PHONE_END_POINT)
192 .query(&query)
193 .json(&body)
194 .send()
195 .await?;
196
197 debug!("response: {:#?}", response);
198
199 if response.status().is_success() {
200 let response = response.json::<Response<ContactBuilder>>().await?;
201
202 let builder = response.extract()?;
203
204 debug!("contact builder: {:#?}", builder);
205
206 Ok(builder.build())
207 } else {
208 Err(InternalServer(response.text().await?))
209 }
210 }
211}