dingtalk_rs/client/
mod.rs1use crate::error::{new_api_error, Result};
2use http::{do_http, PostParameters};
3use reqwest::Method;
4use resp::{Responser, Token};
5use serde::{de::DeserializeOwned, ser::Serialize};
6use serde_json::{json, Value};
7
8const BASE_URL: &str = "https://oapi.dingtalk.com";
9const BASE_URL_NEW_VERSION: &str = "https://api.dingtalk.com";
10
11#[derive(Debug)]
12pub struct Client {
13 app_key: String,
14 app_secret: String,
15}
16
17impl Client {
18 pub fn new(app_key: String, app_secret: String) -> Self {
19 Self {
20 app_key,
21 app_secret,
22 }
23 }
24
25 pub fn new_from_env() -> Result<Self> {
26 use std::env;
27 Ok(Client::new(env::var("APP_KEY")?, env::var("APP_SECRET")?))
28 }
29
30 pub async fn access_token(&self) -> Result<String> {
33 let query_body = json!({
34 "appkey": self.app_key,
35 "appsecret": self.app_secret,
36 });
37
38 let resp = do_http(
39 Method::GET,
40 &format!("{BASE_URL}/gettoken"),
41 None,
42 Some(query_body),
43 None,
44 )
45 .await?;
46
47 let data = resp.json::<Token>().await?;
48
49 Ok(data.access_token)
50 }
51
52 async fn request<R: Responser + DeserializeOwned + Serialize + Default>(
54 &self,
55 method: Method,
56 url: &str,
57 body: Option<Value>,
58 ) -> Result<R> {
59 let body = if let Some(data) = body {
60 Some(PostParameters::json(data))
61 } else {
62 None
63 };
64
65 let resp = do_http(method, url, None, None, body)
66 .await?
67 .json::<R>()
68 .await?;
69
70 if resp.error_code() != 0 {
72 return Err(new_api_error(
73 resp.error_code(),
74 resp.error_message(),
75 resp.request_id(),
76 ));
77 }
78 Ok(resp)
79
80 }
85
86 async fn request_new_version<R: DeserializeOwned + Default>(
88 &self,
89 method: Method,
90 url: &str,
91 body: Option<Value>,
92 ) -> Result<R> {
93 let mut query = None;
94 let mut data = None;
95
96 match method {
97 Method::GET => query = body,
98 Method::POST => {
99 data = if let Some(data) = body {
100 Some(PostParameters::json(data))
101 } else {
102 None
103 };
104 }
105 _ => {}
106 }
107
108 let token = self.access_token().await?;
109
110 let headers = Some(std::collections::HashMap::from([(
111 reqwest::header::HeaderName::from_static("x-acs-dingtalk-access-token"),
112 token,
113 )]));
114
115 let resp = do_http(method, url, headers, query, data)
116 .await?
117 .json::<R>()
118 .await?;
119
120 Ok(resp)
121
122 }
127}
128
129mod http;
130mod resp;
131pub(crate) use resp::{Response, ResponseFlatten};
132
133mod contact_manager;
135pub use contact_manager::*;
136
137mod dto;
139pub use dto::*;
140mod model;
142pub use model::*;
143mod event_subscribe;
145pub use event_subscribe::*;
146
147mod message_notify;
149pub use message_notify::*;