dingtalk_stream/client/stream_/
send_message.rs1use crate::frames::up_message::robot_message::{RobotGroupMessage, RobotMessage, RobotPrivateMessage};
2use crate::frames::{SendMessageCallback, SendMessageCallbackData};
3use crate::{ROBOT_SEND_GROUP_MESSAGE, ROBOT_SEND_PRIVATE_MESSAGE};
4use anyhow::anyhow;
5use serde_json::json;
6use tracing::info;
7
8impl super::DingTalkStream {
9 pub async fn send_message<M: Into<RobotMessage>>(&self, message: M) -> crate::Result<()> {
10 let message = message.into();
11 let http_client = self.http_client.clone();
12 let credential = self.credential.clone();
13 let access_token = self.get_access_token().await?;
14 match message {
15 RobotMessage::Private {
16 message,
17 send_result_cb,
18 } => {
19 let _ = Self::send_private_message(
20 &http_client,
21 &access_token,
22 &credential.client_id,
23 &message,
24 send_result_cb.as_ref(),
25 )
26 .await?;
27 }
28 RobotMessage::Group {
29 message,
30 send_result_cb,
31 } => {
32 let _ = Self::send_group_message(
33 &http_client,
34 &access_token,
35 &credential.client_id,
36 &message,
37 send_result_cb.as_ref(),
38 )
39 .await?;
40 }
41 };
42 Ok(())
43 }
44}
45
46impl super::DingTalkStream {
47 async fn send_private_message(
48 http_client: &reqwest::Client,
49 access_token: &str,
50 client_id: &str,
51 RobotPrivateMessage { user_ids, content }: &RobotPrivateMessage,
52 send_result_cb: Option<&SendMessageCallback>,
53 ) -> crate::Result<()> {
54 let (msg_key, msg_param) = content.to_up_msg()?;
55 let msg_md5 = format!("{:x}", md5::compute(&msg_param));
56 info!("Sending private robot-message[{}]: {}", msg_md5, msg_param);
57 let response = http_client
58 .post(ROBOT_SEND_PRIVATE_MESSAGE)
59 .header("x-acs-dingtalk-access-token", access_token)
60 .header("Content-Type", "application/json")
61 .json(&json!({
62 "robotCode": client_id,
63 "userIds": user_ids,
64 "msgParam": msg_param,
65 "msgKey": msg_key
66 }))
67 .send()
68 .await;
69 if let Some(cb) = send_result_cb {
70 Self::exec_send_cb(response, cb).await;
71 }
72 info!("Send private robot-message[{}] ok", msg_md5);
73 Ok(())
74 }
75
76 async fn send_group_message(
77 http_client: &reqwest::Client,
78 access_token: &str,
79 client_id: &str,
80 RobotGroupMessage { group_id, content }: &RobotGroupMessage,
81 send_result_cb: Option<&SendMessageCallback>,
82 ) -> crate::Result<()> {
83 let (msg_key, msg_param) = content.to_up_msg()?;
84 let msg_md5 = format!("{:x}", md5::compute(&msg_param));
85 info!("Sending group robot-message[{}]: {}", msg_md5, msg_param);
86 let response = http_client
87 .post(ROBOT_SEND_GROUP_MESSAGE)
88 .header("x-acs-dingtalk-access-token", access_token)
89 .header("Content-Type", "application/json")
90 .json(&json!({
91 "robotCode": client_id,
92 "openConversationId": group_id,
93 "msgParam": msg_param,
94 "msgKey": msg_key
95 }))
96 .send()
97 .await;
98 if let Some(cb) = send_result_cb {
99 Self::exec_send_cb(response, cb).await;
100 }
101 info!("Send group robot-message[{}] ok", msg_md5);
102 Ok(())
103 }
104
105 async fn exec_send_cb(
106 response: Result<reqwest::Response, reqwest::Error>,
107 cb: &SendMessageCallback,
108 ) {
109 match response {
110 Ok(response) => {
111 let code = response.status();
112 match response.text().await {
113 Ok(text) => cb(Ok(SendMessageCallbackData {
114 http_status: code.as_u16(),
115 text,
116 })),
117 Err(err) => cb(Err(anyhow!("{err}"))),
118 }
119 }
120 Err(err) => cb(Err(anyhow!("{err}"))),
121 }
122 }
123}