Skip to main content

dingtalk_sdk/api/
async_webhook.rs

1use crate::{
2    client::async_client::Client,
3    error::Result,
4    transport::{build_webhook_url, parse_standard_api_text_response},
5    types::{
6        ActionCardButton, FeedCardLink,
7        internal::{
8            ActionCardContent, FeedCardContent, LinkContent, MarkdownContent, TextContent,
9            WebhookMessage, build_at,
10        },
11    },
12};
13
14/// Async webhook robot service.
15#[derive(Clone)]
16pub struct WebhookService {
17    client: Client,
18    token: String,
19    secret: Option<String>,
20}
21
22impl WebhookService {
23    pub(crate) fn new(client: Client, token: impl Into<String>, secret: Option<String>) -> Self {
24        Self {
25            client,
26            token: token.into(),
27            secret,
28        }
29    }
30
31    async fn send_message(&self, message: &WebhookMessage) -> Result<String> {
32        let url = build_webhook_url(
33            self.client.webhook_base_url(),
34            &self.token,
35            self.secret.as_deref(),
36        )?;
37        let response = self
38            .client
39            .webhook_http()
40            .post(url.as_str())
41            .json(message)?
42            .send_response()
43            .await?;
44        parse_standard_api_text_response(response, self.client.body_snippet())
45    }
46
47    /// Sends a text webhook message.
48    pub async fn send_text_message(
49        &self,
50        content: &str,
51        at_mobiles: Option<Vec<String>>,
52        at_user_ids: Option<Vec<String>>,
53        is_at_all: Option<bool>,
54    ) -> Result<String> {
55        let message = WebhookMessage::Text {
56            text: TextContent {
57                content: content.to_string(),
58            },
59            at: build_at(at_mobiles, at_user_ids, is_at_all),
60        };
61        self.send_message(&message).await
62    }
63
64    /// Sends a link webhook message.
65    pub async fn send_link_message(
66        &self,
67        title: &str,
68        text: &str,
69        message_url: &str,
70        pic_url: Option<&str>,
71    ) -> Result<String> {
72        let message = WebhookMessage::Link {
73            link: LinkContent {
74                title: title.to_string(),
75                text: text.to_string(),
76                message_url: message_url.to_string(),
77                pic_url: pic_url.map(ToOwned::to_owned),
78            },
79            at: None,
80        };
81        self.send_message(&message).await
82    }
83
84    /// Sends a markdown webhook message.
85    pub async fn send_markdown_message(
86        &self,
87        title: &str,
88        text: &str,
89        at_mobiles: Option<Vec<String>>,
90        at_user_ids: Option<Vec<String>>,
91        is_at_all: Option<bool>,
92    ) -> Result<String> {
93        let message = WebhookMessage::Markdown {
94            markdown: MarkdownContent {
95                title: title.to_string(),
96                text: text.to_string(),
97            },
98            at: build_at(at_mobiles, at_user_ids, is_at_all),
99        };
100        self.send_message(&message).await
101    }
102
103    /// Sends a single-button action-card webhook message.
104    pub async fn send_action_card_message_single(
105        &self,
106        title: &str,
107        text: &str,
108        single_title: &str,
109        single_url: &str,
110        btn_orientation: Option<&str>,
111    ) -> Result<String> {
112        let message = WebhookMessage::ActionCard {
113            action_card: ActionCardContent {
114                title: title.to_string(),
115                text: text.to_string(),
116                btn_orientation: btn_orientation.map(ToOwned::to_owned),
117                single_title: Some(single_title.to_string()),
118                single_url: Some(single_url.to_string()),
119                btns: None,
120            },
121        };
122        self.send_message(&message).await
123    }
124
125    /// Sends a multi-button action-card webhook message.
126    pub async fn send_action_card_message_multi(
127        &self,
128        title: &str,
129        text: &str,
130        btns: Vec<ActionCardButton>,
131        btn_orientation: Option<&str>,
132    ) -> Result<String> {
133        let message = WebhookMessage::ActionCard {
134            action_card: ActionCardContent {
135                title: title.to_string(),
136                text: text.to_string(),
137                btn_orientation: btn_orientation.map(ToOwned::to_owned),
138                single_title: None,
139                single_url: None,
140                btns: Some(btns),
141            },
142        };
143        self.send_message(&message).await
144    }
145
146    /// Sends a feed-card webhook message.
147    pub async fn send_feed_card_message(&self, links: Vec<FeedCardLink>) -> Result<String> {
148        let message = WebhookMessage::FeedCard {
149            feed_card: FeedCardContent { links },
150        };
151        self.send_message(&message).await
152    }
153}