1use 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 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 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 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 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 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 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 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 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 pub async fn chat_unfurl_v3(
148 &self,
149 req: &SlackApiChatUnfurlRequestV3,
150 ) -> ClientResult<SlackApiChatUnfurlResponse> {
151 self.http_session_api
152 .http_post("chat.unfurl", req, Some(&SLACK_TIER3_METHOD_CONFIG))
153 .await
154 }
155
156 pub async fn chat_update(
160 &self,
161 req: &SlackApiChatUpdateRequest,
162 ) -> ClientResult<SlackApiChatUpdateResponse> {
163 self.http_session_api
164 .http_post("chat.update", req, Some(&SLACK_TIER3_METHOD_CONFIG))
165 .await
166 }
167
168 pub async fn chat_scheduled_messages_list(
172 &self,
173 req: &SlackApiChatScheduledMessagesListRequest,
174 ) -> ClientResult<SlackApiChatScheduledMessagesListResponse> {
175 self.http_session_api
176 .http_post(
177 "chat.scheduledMessages.list",
178 req,
179 Some(&SLACK_TIER3_METHOD_CONFIG),
180 )
181 .await
182 }
183}
184
185#[skip_serializing_none]
186#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
187pub struct SlackApiChatDeleteRequest {
188 pub channel: SlackChannelId,
189 pub ts: SlackTs,
190 pub as_user: Option<bool>,
191}
192
193#[skip_serializing_none]
194#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
195pub struct SlackApiChatDeleteResponse {
196 pub channel: SlackChannelId,
197 pub ts: SlackTs,
198}
199
200#[skip_serializing_none]
201#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
202pub struct SlackApiChatDeleteScheduledMessageRequest {
203 pub channel: SlackChannelId,
204 pub scheduled_message: SlackScheduledMid,
205 pub as_user: Option<bool>,
206}
207
208#[skip_serializing_none]
209#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
210pub struct SlackApiChatDeleteScheduledMessageResponse {}
211
212#[skip_serializing_none]
213#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
214pub struct SlackApiChatGetPermalinkRequest {
215 pub channel: SlackChannelId,
216 pub message_ts: SlackTs,
217}
218
219#[skip_serializing_none]
220#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
221pub struct SlackApiChatGetPermalinkResponse {
222 pub channel: SlackChannelId,
223 pub permalink: Url,
224}
225
226#[skip_serializing_none]
227#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
228pub struct SlackApiChatPostEphemeralRequest {
229 pub channel: SlackChannelId,
230 pub user: SlackUserId,
231 #[serde(flatten)]
232 pub content: SlackMessageContent,
233 pub as_user: Option<bool>,
234 pub icon_emoji: Option<String>,
235 pub icon_url: Option<String>,
236 pub link_names: Option<bool>,
237 pub parse: Option<String>,
238 pub thread_ts: Option<SlackTs>,
239 pub username: Option<String>,
240}
241
242#[skip_serializing_none]
243#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
244pub struct SlackApiChatPostEphemeralResponse {}
245
246#[skip_serializing_none]
247#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
248pub struct SlackApiChatPostMessageRequest {
249 pub channel: SlackChannelId,
250 #[serde(flatten)]
251 pub content: SlackMessageContent,
252 pub as_user: Option<bool>,
253 pub icon_emoji: Option<String>,
254 pub icon_url: Option<String>,
255 pub link_names: Option<bool>,
256 pub parse: Option<String>,
257 pub thread_ts: Option<SlackTs>,
258 pub username: Option<String>,
259 pub reply_broadcast: Option<bool>,
260 pub unfurl_links: Option<bool>,
261 pub unfurl_media: Option<bool>,
262}
263
264#[skip_serializing_none]
265#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
266pub struct SlackApiChatPostMessageResponse {
267 pub channel: SlackChannelId,
268 pub ts: SlackTs,
269 pub message: SlackMessage,
270}
271
272#[skip_serializing_none]
273#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
274pub struct SlackApiChatScheduleMessageRequest {
275 pub channel: SlackChannelId,
276 #[serde(flatten)]
277 pub content: SlackMessageContent,
278 pub post_at: SlackDateTime,
279 pub as_user: Option<bool>,
280 pub icon_emoji: Option<String>,
281 pub icon_url: Option<String>,
282 pub link_names: Option<bool>,
283 pub parse: Option<String>,
284 pub thread_ts: Option<SlackTs>,
285 pub username: Option<String>,
286 pub reply_broadcast: Option<bool>,
287 pub unfurl_links: Option<bool>,
288 pub unfurl_media: Option<bool>,
289}
290
291#[skip_serializing_none]
292#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
293pub struct SlackApiChatScheduleMessageResponse {
294 pub channel: SlackChannelId,
295 pub scheduled_message_id: SlackScheduledMid,
296 pub post_at: SlackDateTime,
297}
298
299#[skip_serializing_none]
300#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
301pub struct SlackApiChatUnfurlRequest {
302 pub channel: SlackChannelId,
303 pub ts: SlackTs,
304 pub unfurls: HashMap<String, SlackApiChatUnfurlMapItem>,
305 pub user_auth_message: Option<String>,
306 pub user_auth_required: Option<bool>,
307 pub user_auth_url: Option<Url>,
308}
309
310#[skip_serializing_none]
311#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
312pub struct SlackApiChatUnfurlRequestV2 {
313 pub source: SlackApiChatUnfurlSource,
314 pub unfurl_id: SlackUnfurlId,
315 pub unfurls: HashMap<String, SlackApiChatUnfurlMapItemV2>,
316 pub user_auth_message: Option<String>,
317 pub user_auth_required: Option<bool>,
318 pub user_auth_url: Option<Url>,
319}
320
321#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
322pub struct SlackChannelTs {
323 pub channel: SlackChannelId,
324 pub ts: SlackTs,
325}
326
327#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
328pub struct SlackUnfurlIdSource {
329 pub source: String,
330 pub unfurl_id: SlackUnfurlId,
331}
332
333#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
334#[serde(untagged)]
335pub enum SlackUnfurlRequestId {
336 ChannelTs(SlackChannelTs),
337 UnfurlIdSource(SlackUnfurlIdSource),
338}
339
340#[skip_serializing_none]
341#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
342pub struct SlackApiChatUnfurlRequestV3 {
343 #[serde(flatten)]
344 pub id: SlackUnfurlRequestId,
345 pub unfurls: HashMap<String, SlackApiChatUnfurlMapItemV2>,
346 pub user_auth_message: Option<String>,
347 pub user_auth_required: Option<bool>,
348 pub user_auth_url: Option<Url>,
349}
350
351#[skip_serializing_none]
352#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
353pub enum SlackApiChatUnfurlSource {
354 #[serde(rename = "composer")]
355 Composer,
356 #[serde(rename = "conversations_history")]
357 ConversationsHistory,
358}
359
360#[skip_serializing_none]
361#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
362pub struct SlackApiChatUnfurlMapItem {
363 pub text: String,
364}
365
366#[skip_serializing_none]
367#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
368pub struct SlackApiChatUnfurlMapItemV2 {
369 pub blocks: Vec<SlackBlock>,
370 pub preview: Option<SlackApiChatUnfurlPreview>,
371}
372
373#[skip_serializing_none]
374#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
375pub struct SlackApiChatUnfurlPreview {
376 pub title: SlackBlockText,
377 pub icon_url: Option<Url>,
378}
379
380#[skip_serializing_none]
381#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
382pub struct SlackApiChatUnfurlResponse {}
383
384#[skip_serializing_none]
385#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
386pub struct SlackApiChatUpdateRequest {
387 pub channel: SlackChannelId,
388 #[serde(flatten)]
389 pub content: SlackMessageContent,
390 pub ts: SlackTs,
391 pub as_user: Option<bool>,
392 pub link_names: Option<bool>,
393 pub parse: Option<String>,
394 pub reply_broadcast: Option<bool>,
395}
396
397#[skip_serializing_none]
398#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
399pub struct SlackApiChatUpdateResponse {
400 pub channel: SlackChannelId,
401 pub ts: SlackTs,
402 pub thread_ts: Option<SlackTs>,
403 pub message: SlackUpdatedMessage,
404}
405
406#[skip_serializing_none]
407#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
408pub struct SlackApiChatScheduledMessagesListRequest {
409 pub channel: Option<SlackChannelId>,
410 pub cursor: Option<SlackCursorId>,
411 pub latest: Option<SlackTs>,
412 pub limit: Option<u16>,
413 pub oldest: Option<SlackTs>,
414}
415
416#[skip_serializing_none]
417#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
418pub struct SlackApiChatScheduledMessagesListResponse {
419 pub scheduled_messages: Vec<SlackApiChatScheduledMessageInfo>,
420 pub response_metadata: Option<SlackResponseMetadata>,
421}
422
423#[skip_serializing_none]
424#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
425pub struct SlackApiChatScheduledMessageInfo {
426 pub id: SlackScheduledMid,
427 pub channel_id: SlackChannelId,
428 pub post_at: SlackDateTime,
429 pub date_created: SlackDateTime,
430}
431
432impl<SCHC> SlackApiScrollableRequest<SCHC> for SlackApiChatScheduledMessagesListRequest
433where
434 SCHC: SlackClientHttpConnector + Send + Sync + Clone + 'static,
435{
436 type ResponseType = SlackApiChatScheduledMessagesListResponse;
437 type CursorType = SlackCursorId;
438 type ResponseItemType = SlackApiChatScheduledMessageInfo;
439
440 fn with_new_cursor(&self, new_cursor: Option<&Self::CursorType>) -> Self {
441 self.clone().opt_cursor(new_cursor.cloned())
442 }
443
444 fn scroll<'a, 's>(
445 &'a self,
446 session: &'a SlackClientSession<'s, SCHC>,
447 ) -> BoxFuture<'a, ClientResult<Self::ResponseType>> {
448 async move { session.chat_scheduled_messages_list(self).await }.boxed()
449 }
450}
451
452impl SlackApiScrollableResponse for SlackApiChatScheduledMessagesListResponse {
453 type CursorType = SlackCursorId;
454 type ResponseItemType = SlackApiChatScheduledMessageInfo;
455
456 fn next_cursor(&self) -> Option<&Self::CursorType> {
457 self.response_metadata
458 .as_ref()
459 .and_then(|rm| rm.next_cursor.as_ref())
460 }
461
462 fn scrollable_items<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Self::ResponseItemType> + 'a> {
463 Box::new(self.scheduled_messages.iter())
464 }
465}
466
467lazy_static! {
468 pub static ref CHAT_GET_PERMLINK_SPECIAL_LIMIT_RATE_CTL: SlackApiMethodRateControlConfig =
469 SlackApiMethodRateControlConfig::new().with_special_rate_limit(
470 SlackApiRateControlSpecialLimit::new(
471 "chat.getPermalink".into(),
472 SlackApiRateControlLimit::new(100, std::time::Duration::from_secs(1))
473 )
474 );
475 pub static ref CHAT_POST_MESSAGE_SPECIAL_LIMIT_RATE_CTL: SlackApiMethodRateControlConfig =
476 SlackApiMethodRateControlConfig::new().with_special_rate_limit(
477 SlackApiRateControlSpecialLimit::new(
478 "chat.postMessage".into(),
479 SlackApiRateControlLimit::new(1, std::time::Duration::from_secs(1))
480 )
481 );
482}