async_dingtalk/
contact.rs

1use crate::DingTalk;
2use log::info;
3use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Debug)]
7pub struct UserInfo {
8    pub email: Option<String>,
9    pub mobile: Option<String>,
10    #[serde(rename = "nick")]
11    pub username: String,
12    #[serde(default, rename = "openId")]
13    pub open_id: Option<String>,
14    #[serde(rename = "unionId")]
15    pub union_id: String,
16    #[serde(rename = "stateCode")]
17    pub state_code: String,
18    pub visitor: Option<bool>,
19}
20
21impl DingTalk {
22    /// Get the user info of the given union ID.
23    ///
24    /// [Documents](https://open.dingtalk.com/document/isvapp/get-user-info)
25    ///
26    /// # Arguments
27    ///
28    /// * `union_id` - The union ID of the DingTalk user.
29    ///
30    /// # Returns
31    ///
32    /// A `Result` containing the user info if successful, otherwise an error string.
33    pub async fn get_contact_userinfo(
34        &self,
35        union_id: String,
36    ) -> Result<UserInfo, Box<dyn std::error::Error>> {
37        let mut headers = HeaderMap::new();
38        match self.get_app_access_token().await {
39            Ok(at) => headers.insert(
40                HeaderName::from_static("x-acs-dingtalk-access-token"),
41                HeaderValue::from_str(&at).unwrap(),
42            ),
43            Err(e) => return Err(e),
44        };
45
46        let url: String = format!("https://api.dingtalk.com/v1.0/contact/users/{}", union_id);
47        let response = self.client.get(&url).headers(headers).send().await?;
48
49        if !response.status().is_success() {
50            return Err(format!("Failed to get user info: {}", response.status()).into());
51        }
52
53        let result = response.json::<UserInfo>().await?;
54
55        info!("union_id: {union_id}, fetch user info: {:#?}", &result);
56
57        Ok(result)
58    }
59}