slack_morphism/api/
chat.rs

1//!
2//! Support for Slack Chat API methods
3//!
4
5use rsb_derive::Builder;
6use rvstruct::*;
7use serde::{Deserialize, Serialize};
8use serde_with::skip_serializing_none;
9
10use crate::models::blocks::{SlackBlock, SlackBlockText};
11use crate::models::*;
12use crate::ratectl::*;
13use crate::scroller::*;
14use crate::SlackClientSession;
15use crate::{ClientResult, SlackClientHttpConnector};
16use futures::future::{BoxFuture, FutureExt};
17use lazy_static::lazy_static;
18use std::collections::HashMap;
19use url::Url;
20
21impl<'a, SCHC> SlackClientSession<'a, SCHC>
22where
23    SCHC: SlackClientHttpConnector + Send,
24{
25    ///
26    /// https://api.slack.com/methods/chat.delete
27    ///
28    pub async fn chat_delete(
29        &self,
30        req: &SlackApiChatDeleteRequest,
31    ) -> ClientResult<SlackApiChatDeleteResponse> {
32        self.http_session_api
33            .http_post("chat.delete", req, Some(&SLACK_TIER3_METHOD_CONFIG))
34            .await
35    }
36
37    ///
38    /// https://api.slack.com/methods/chat.deleteScheduledMessage
39    ///
40    pub async fn chat_delete_scheduled_message(
41        &self,
42        req: &SlackApiChatDeleteScheduledMessageRequest,
43    ) -> ClientResult<SlackApiChatDeleteScheduledMessageResponse> {
44        self.http_session_api
45            .http_post(
46                "chat.deleteScheduledMessage",
47                req,
48                Some(&SLACK_TIER3_METHOD_CONFIG),
49            )
50            .await
51    }
52
53    ///
54    /// https://api.slack.com/methods/chat.getPermalink
55    ///
56    pub async fn chat_get_permalink(
57        &self,
58        req: &SlackApiChatGetPermalinkRequest,
59    ) -> ClientResult<SlackApiChatGetPermalinkResponse> {
60        self.http_session_api
61            .http_get(
62                "chat.getPermalink",
63                &vec![
64                    ("channel", Some(&req.channel.value())),
65                    ("message_ts", Some(&req.message_ts.value())),
66                ],
67                Some(&CHAT_GET_PERMLINK_SPECIAL_LIMIT_RATE_CTL),
68            )
69            .await
70    }
71
72    ///
73    /// https://api.slack.com/methods/chat.postEphemeral
74    ///
75    pub async fn chat_post_ephemeral(
76        &self,
77        req: &SlackApiChatPostEphemeralRequest,
78    ) -> ClientResult<SlackApiChatPostEphemeralResponse> {
79        self.http_session_api
80            .http_post("chat.postEphemeral", req, Some(&SLACK_TIER4_METHOD_CONFIG))
81            .await
82    }
83
84    ///
85    /// https://api.slack.com/methods/chat.postMessage
86    ///
87    pub async fn chat_post_message(
88        &self,
89        req: &SlackApiChatPostMessageRequest,
90    ) -> ClientResult<SlackApiChatPostMessageResponse> {
91        self.http_session_api
92            .http_post(
93                "chat.postMessage",
94                req,
95                Some(&CHAT_POST_MESSAGE_SPECIAL_LIMIT_RATE_CTL),
96            )
97            .await
98    }
99
100    ///
101    /// https://api.slack.com/methods/chat.scheduleMessage
102    ///
103    pub async fn chat_schedule_message(
104        &self,
105        req: &SlackApiChatScheduleMessageRequest,
106    ) -> ClientResult<SlackApiChatScheduleMessageResponse> {
107        self.http_session_api
108            .http_post(
109                "chat.scheduleMessage",
110                req,
111                Some(&SLACK_TIER3_METHOD_CONFIG),
112            )
113            .await
114    }
115
116    ///
117    /// The old/legacy version of unfurl with channel/ts
118    /// https://api.slack.com/methods/chat.unfurl
119    ///
120    pub async fn chat_unfurl(
121        &self,
122        req: &SlackApiChatUnfurlRequest,
123    ) -> ClientResult<SlackApiChatUnfurlResponse> {
124        self.http_session_api
125            .http_post("chat.unfurl", req, Some(&SLACK_TIER3_METHOD_CONFIG))
126            .await
127    }
128
129    ///
130    /// The version for unfurl with source/unfurl_id
131    /// https://api.slack.com/methods/chat.unfurl
132    ///
133    pub async fn chat_unfurl_v2(
134        &self,
135        req: &SlackApiChatUnfurlRequestV2,
136    ) -> ClientResult<SlackApiChatUnfurlResponse> {
137        self.http_session_api
138            .http_post("chat.unfurl", req, Some(&SLACK_TIER3_METHOD_CONFIG))
139            .await
140    }
141
142    ///
143    /// https://api.slack.com/methods/chat.update
144    ///
145    pub async fn chat_update(
146        &self,
147        req: &SlackApiChatUpdateRequest,
148    ) -> ClientResult<SlackApiChatUpdateResponse> {
149        self.http_session_api
150            .http_post("chat.update", req, Some(&SLACK_TIER3_METHOD_CONFIG))
151            .await
152    }
153
154    ///
155    /// https://api.slack.com/methods/chat.scheduledMessages.list
156    ///
157    pub async fn chat_scheduled_messages_list(
158        &self,
159        req: &SlackApiChatScheduledMessagesListRequest,
160    ) -> ClientResult<SlackApiChatScheduledMessagesListResponse> {
161        self.http_session_api
162            .http_post(
163                "chat.scheduledMessages.list",
164                req,
165                Some(&SLACK_TIER3_METHOD_CONFIG),
166            )
167            .await
168    }
169}
170
171#[skip_serializing_none]
172#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
173pub struct SlackApiChatDeleteRequest {
174    pub channel: SlackChannelId,
175    pub ts: SlackTs,
176    pub as_user: Option<bool>,
177}
178
179#[skip_serializing_none]
180#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
181pub struct SlackApiChatDeleteResponse {
182    pub channel: SlackChannelId,
183    pub ts: SlackTs,
184}
185
186#[skip_serializing_none]
187#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
188pub struct SlackApiChatDeleteScheduledMessageRequest {
189    pub channel: SlackChannelId,
190    pub scheduled_message: SlackScheduledMid,
191    pub as_user: Option<bool>,
192}
193
194#[skip_serializing_none]
195#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
196pub struct SlackApiChatDeleteScheduledMessageResponse {}
197
198#[skip_serializing_none]
199#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
200pub struct SlackApiChatGetPermalinkRequest {
201    pub channel: SlackChannelId,
202    pub message_ts: SlackTs,
203}
204
205#[skip_serializing_none]
206#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
207pub struct SlackApiChatGetPermalinkResponse {
208    pub channel: SlackChannelId,
209    pub permalink: Url,
210}
211
212#[skip_serializing_none]
213#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
214pub struct SlackApiChatPostEphemeralRequest {
215    pub channel: SlackChannelId,
216    pub user: SlackUserId,
217    #[serde(flatten)]
218    pub content: SlackMessageContent,
219    pub as_user: Option<bool>,
220    pub icon_emoji: Option<String>,
221    pub icon_url: Option<String>,
222    pub link_names: Option<bool>,
223    pub parse: Option<String>,
224    pub thread_ts: Option<SlackTs>,
225    pub username: Option<String>,
226}
227
228#[skip_serializing_none]
229#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
230pub struct SlackApiChatPostEphemeralResponse {}
231
232#[skip_serializing_none]
233#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
234pub struct SlackApiChatPostMessageRequest {
235    pub channel: SlackChannelId,
236    #[serde(flatten)]
237    pub content: SlackMessageContent,
238    pub as_user: Option<bool>,
239    pub icon_emoji: Option<String>,
240    pub icon_url: Option<String>,
241    pub link_names: Option<bool>,
242    pub parse: Option<String>,
243    pub thread_ts: Option<SlackTs>,
244    pub username: Option<String>,
245    pub reply_broadcast: Option<bool>,
246    pub unfurl_links: Option<bool>,
247    pub unfurl_media: Option<bool>,
248}
249
250#[skip_serializing_none]
251#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
252pub struct SlackApiChatPostMessageResponse {
253    pub channel: SlackChannelId,
254    pub ts: SlackTs,
255    pub message: SlackMessage,
256}
257
258#[skip_serializing_none]
259#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
260pub struct SlackApiChatScheduleMessageRequest {
261    pub channel: SlackChannelId,
262    #[serde(flatten)]
263    pub content: SlackMessageContent,
264    pub post_at: SlackDateTime,
265    pub as_user: Option<bool>,
266    pub icon_emoji: Option<String>,
267    pub icon_url: Option<String>,
268    pub link_names: Option<bool>,
269    pub parse: Option<String>,
270    pub thread_ts: Option<SlackTs>,
271    pub username: Option<String>,
272    pub reply_broadcast: Option<bool>,
273    pub unfurl_links: Option<bool>,
274    pub unfurl_media: Option<bool>,
275}
276
277#[skip_serializing_none]
278#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
279pub struct SlackApiChatScheduleMessageResponse {
280    pub channel: SlackChannelId,
281    pub scheduled_message_id: SlackScheduledMid,
282    pub post_at: SlackDateTime,
283}
284
285#[skip_serializing_none]
286#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
287pub struct SlackApiChatUnfurlRequest {
288    pub channel: SlackChannelId,
289    pub ts: SlackTs,
290    pub unfurls: HashMap<String, SlackApiChatUnfurlMapItem>,
291    pub user_auth_message: Option<String>,
292    pub user_auth_required: Option<bool>,
293    pub user_auth_url: Option<Url>,
294}
295
296#[skip_serializing_none]
297#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
298pub struct SlackApiChatUnfurlRequestV2 {
299    pub source: SlackApiChatUnfurlSource,
300    pub unfurl_id: SlackUnfurlId,
301    pub unfurls: HashMap<String, SlackApiChatUnfurlMapItemV2>,
302    pub user_auth_message: Option<String>,
303    pub user_auth_required: Option<bool>,
304    pub user_auth_url: Option<Url>,
305}
306
307#[skip_serializing_none]
308#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
309pub enum SlackApiChatUnfurlSource {
310    #[serde(rename = "composer")]
311    Composer,
312    #[serde(rename = "conversations_history")]
313    ConversationsHistory,
314}
315
316#[skip_serializing_none]
317#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
318pub struct SlackApiChatUnfurlMapItem {
319    pub text: String,
320}
321
322#[skip_serializing_none]
323#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
324pub struct SlackApiChatUnfurlMapItemV2 {
325    pub blocks: Vec<SlackBlock>,
326    pub preview: Option<SlackApiChatUnfurlPreview>,
327}
328
329#[skip_serializing_none]
330#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
331pub struct SlackApiChatUnfurlPreview {
332    pub title: SlackBlockText,
333    pub icon_url: Option<Url>,
334}
335
336#[skip_serializing_none]
337#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
338pub struct SlackApiChatUnfurlResponse {}
339
340#[skip_serializing_none]
341#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
342pub struct SlackApiChatUpdateRequest {
343    pub channel: SlackChannelId,
344    #[serde(flatten)]
345    pub content: SlackMessageContent,
346    pub ts: SlackTs,
347    pub as_user: Option<bool>,
348    pub link_names: Option<bool>,
349    pub parse: Option<String>,
350    pub reply_broadcast: Option<bool>,
351}
352
353#[skip_serializing_none]
354#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
355pub struct SlackApiChatUpdateResponse {
356    pub channel: SlackChannelId,
357    pub ts: SlackTs,
358    pub thread_ts: Option<SlackTs>,
359    pub message: SlackUpdatedMessage,
360}
361
362#[skip_serializing_none]
363#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
364pub struct SlackApiChatScheduledMessagesListRequest {
365    pub channel: Option<SlackChannelId>,
366    pub cursor: Option<SlackCursorId>,
367    pub latest: Option<SlackTs>,
368    pub limit: Option<u16>,
369    pub oldest: Option<SlackTs>,
370}
371
372#[skip_serializing_none]
373#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
374pub struct SlackApiChatScheduledMessagesListResponse {
375    pub scheduled_messages: Vec<SlackApiChatScheduledMessageInfo>,
376    pub response_metadata: Option<SlackResponseMetadata>,
377}
378
379#[skip_serializing_none]
380#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
381pub struct SlackApiChatScheduledMessageInfo {
382    pub id: SlackScheduledMid,
383    pub channel_id: SlackChannelId,
384    pub post_at: SlackDateTime,
385    pub date_created: SlackDateTime,
386}
387
388impl<SCHC> SlackApiScrollableRequest<SCHC> for SlackApiChatScheduledMessagesListRequest
389where
390    SCHC: SlackClientHttpConnector + Send + Sync + Clone + 'static,
391{
392    type ResponseType = SlackApiChatScheduledMessagesListResponse;
393    type CursorType = SlackCursorId;
394    type ResponseItemType = SlackApiChatScheduledMessageInfo;
395
396    fn with_new_cursor(&self, new_cursor: Option<&Self::CursorType>) -> Self {
397        self.clone().opt_cursor(new_cursor.cloned())
398    }
399
400    fn scroll<'a, 's>(
401        &'a self,
402        session: &'a SlackClientSession<'s, SCHC>,
403    ) -> BoxFuture<'a, ClientResult<Self::ResponseType>> {
404        async move { session.chat_scheduled_messages_list(self).await }.boxed()
405    }
406}
407
408impl SlackApiScrollableResponse for SlackApiChatScheduledMessagesListResponse {
409    type CursorType = SlackCursorId;
410    type ResponseItemType = SlackApiChatScheduledMessageInfo;
411
412    fn next_cursor(&self) -> Option<&Self::CursorType> {
413        self.response_metadata
414            .as_ref()
415            .and_then(|rm| rm.next_cursor.as_ref())
416    }
417
418    fn scrollable_items<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::ResponseItemType> + 'a> {
419        Box::new(self.scheduled_messages.iter())
420    }
421}
422
423lazy_static! {
424    pub static ref CHAT_GET_PERMLINK_SPECIAL_LIMIT_RATE_CTL: SlackApiMethodRateControlConfig =
425        SlackApiMethodRateControlConfig::new().with_special_rate_limit(
426            SlackApiRateControlSpecialLimit::new(
427                "chat.getPermalink".into(),
428                SlackApiRateControlLimit::new(100, std::time::Duration::from_secs(1))
429            )
430        );
431    pub static ref CHAT_POST_MESSAGE_SPECIAL_LIMIT_RATE_CTL: SlackApiMethodRateControlConfig =
432        SlackApiMethodRateControlConfig::new().with_special_rate_limit(
433            SlackApiRateControlSpecialLimit::new(
434                "chat.postMessage".into(),
435                SlackApiRateControlLimit::new(1, std::time::Duration::from_secs(1))
436            )
437        );
438}