use super::User;
use super::credential::Credential;
use crate::utils::{RequestBuilder, ResponseExt};
use crate::{Result, constants};
use http::Method;
use serde::{Deserialize, Serialize};
use tracing::{debug, instrument};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UserInfo {
nickname: String,
gender: u8,
country: String,
province: String,
city: String,
avatar: String,
watermark: Watermark,
}
impl UserInfo {
pub fn nickname(&self) -> &str {
&self.nickname
}
pub fn gender(&self) -> u8 {
self.gender
}
pub fn country(&self) -> &str {
&self.country
}
pub fn province(&self) -> &str {
&self.province
}
pub fn city(&self) -> &str {
&self.city
}
pub fn avatar(&self) -> &str {
&self.avatar
}
pub fn app_id(&self) -> &str {
&self.watermark.app_id
}
pub fn timestamp(&self) -> u64 {
self.watermark.timestamp
}
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct UserBuilder {
#[serde(rename = "nickName")]
nickname: String,
gender: u8,
country: String,
province: String,
city: String,
#[serde(rename = "avatarUrl")]
avatar: String,
watermark: WatermarkBuilder,
}
impl UserBuilder {
pub(crate) fn build(self) -> UserInfo {
UserInfo {
nickname: self.nickname,
gender: self.gender,
country: self.country,
province: self.province,
city: self.city,
avatar: self.avatar,
watermark: self.watermark.build(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Contact {
phone_number: String,
pure_phone_number: String,
country_code: String,
watermark: Watermark,
}
impl Contact {
pub fn phone_number(&self) -> &str {
&self.phone_number
}
pub fn pure_phone_number(&self) -> &str {
&self.pure_phone_number
}
pub fn country_code(&self) -> &str {
&self.country_code
}
pub fn app_id(&self) -> &str {
&self.watermark.app_id
}
pub fn timestamp(&self) -> u64 {
self.watermark.timestamp
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Watermark {
app_id: String,
timestamp: u64,
}
#[derive(Debug, Deserialize, Clone)]
struct WatermarkBuilder {
#[serde(rename = "appid")]
app_id: String,
timestamp: u64,
}
impl WatermarkBuilder {
fn build(self) -> Watermark {
Watermark {
app_id: self.app_id,
timestamp: self.timestamp,
}
}
}
impl User {
#[instrument(skip(self, code))]
pub async fn login(&self, code: &str) -> Result<Credential> {
debug!("code: {}", code);
let config = self.client.app_config();
let query = serde_json::json!({
"appid": &config.app_id,
"secret":&config.secret,
"js_code": code,
"grant_type": "authorization_code"
});
let request = RequestBuilder::new(constants::AUTHENTICATION_END_POINT)
.method(Method::GET)
.query(query)
.build()?;
let client = &self.client.client;
let response = client.execute(request).await?;
debug!("authentication response: {:#?}", &response);
response.to_json::<Credential>()
}
pub async fn get_contact(&self, code: &str, open_id: Option<&str>) -> Result<Contact> {
debug!("code: {}, open_id: {:?}", code, open_id);
let query = serde_json::json!({
"access_token":self.client.token().await?
});
let mut body = serde_json::json!({
"code":code
});
if let Some(open_id) = open_id {
body.as_object_mut()
.unwrap()
.insert("openid".to_string(), serde_json::json!(open_id));
}
let request = RequestBuilder::new(constants::PHONE_END_POINT)
.query(query)
.body(body)
.build()?;
let client = &self.client.client;
let response = client.execute(request).await?;
debug!("authentication response: {:#?}", &response);
response.to_json::<Contact>()
}
}