1use crate::attachment::attachment::Attachment;
5use crate::block::blocks::Block;
6use crate::chat::message::Message;
7use crate::error::Error;
8use crate::http_client::{get_slack_url, ResponseMetadata, SlackWebAPIClient};
9use serde::{Deserialize, Serialize};
10use serde_with::skip_serializing_none;
11
12#[skip_serializing_none]
13#[derive(Deserialize, Serialize, Debug, Default, PartialEq)]
14pub struct UpdateRequest {
15 pub channel: String,
16 pub ts: String,
17 pub as_user: Option<bool>,
18 pub attachments: Option<Vec<Attachment>>,
19 pub blocks: Option<Vec<Block>>,
20 pub file_ids: Option<Vec<String>>,
21 pub link_names: Option<bool>,
22 pub parse: Option<String>,
23 pub reply_broadcast: Option<bool>,
24 pub text: Option<String>,
25}
26
27#[skip_serializing_none]
28#[derive(Deserialize, Serialize, Debug, Default, PartialEq)]
29pub struct UpdateResponse {
30 pub ok: bool,
31 pub error: Option<String>,
32 pub response_metadata: Option<ResponseMetadata>,
33 pub channel: Option<String>,
34 pub ts: Option<String>,
35 pub text: Option<String>,
36 pub message: Option<Message>,
37}
38
39pub async fn update<T>(
40 client: &T,
41 param: &UpdateRequest,
42 bot_token: &str,
43) -> Result<UpdateResponse, Error>
44where
45 T: SlackWebAPIClient,
46{
47 let url = get_slack_url("chat.update");
48 let json = serde_json::to_string(¶m)?;
49
50 client
51 .post_json(&url, &json, bot_token)
52 .await
53 .and_then(|result| {
54 serde_json::from_str::<UpdateResponse>(&result).map_err(Error::SerdeJsonError)
55 })
56}
57
58#[cfg(test)]
59mod test {
60 use super::*;
61 use crate::block::block_object::{TextBlockObject, TextBlockType};
62 use crate::block::block_section::SectionBlock;
63 use crate::http_client::MockSlackWebAPIClient;
64
65 #[test]
66 fn convert_request() {
67 let request = UpdateRequest {
68 channel: "C123456789".to_string(),
69 ts: "1405894322.002768".to_string(),
70 as_user: Some(true),
71 attachments: Some(vec![Attachment {
72 pretext: Some("pre-hello".to_string()),
73 text: Some("text-world".to_string()),
74 ..Default::default()
75 }]),
76 blocks: Some(vec![Block::SectionBlock(SectionBlock {
77 text: Some(TextBlockObject {
78 type_filed: TextBlockType::PlainText,
79 text: "text".to_string(),
80 ..Default::default()
81 }),
82 ..Default::default()
83 })]),
84 file_ids: Some(vec!["F013GKY52QK".to_string(), "F013GL22D0T".to_string()]),
85 link_names: Some(true),
86 parse: Some("none".to_string()),
87 reply_broadcast: Some(true),
88 text: Some("Hello world".to_string()),
89 };
90 let json = r##"{
91 "channel": "C123456789",
92 "ts": "1405894322.002768",
93 "as_user": true,
94 "attachments": [
95 {
96 "pretext": "pre-hello",
97 "text": "text-world"
98 }
99 ],
100 "blocks": [
101 {
102 "type": "section",
103 "text": {
104 "type": "plain_text",
105 "text": "text"
106 }
107 }
108 ],
109 "file_ids": [
110 "F013GKY52QK",
111 "F013GL22D0T"
112 ],
113 "link_names": true,
114 "parse": "none",
115 "reply_broadcast": true,
116 "text": "Hello world"
117}"##;
118
119 let j = serde_json::to_string_pretty(&request).unwrap();
120 assert_eq!(json, j);
121
122 let s = serde_json::from_str::<UpdateRequest>(json).unwrap();
123 assert_eq!(request, s);
124 }
125
126 #[test]
127 fn convert_response() {
128 let response = UpdateResponse {
129 ok: true,
130 channel: Some("C024BE91L".to_string()),
131 ts: Some("1401383885.000061".to_string()),
132 text: Some("Updated text you carefully authored".to_string()),
133 message: Some(Message {
134 text: Some("Updated text you carefully authored".to_string()),
135 user: Some("U34567890".to_string()),
136 ..Default::default()
137 }),
138 ..Default::default()
139 };
140 let json = r##"{
141 "ok": true,
142 "channel": "C024BE91L",
143 "ts": "1401383885.000061",
144 "text": "Updated text you carefully authored",
145 "message": {
146 "text": "Updated text you carefully authored",
147 "user": "U34567890"
148 }
149}"##;
150
151 let j = serde_json::to_string_pretty(&response).unwrap();
152 assert_eq!(json, j);
153
154 let s = serde_json::from_str::<UpdateResponse>(json).unwrap();
155 assert_eq!(response, s);
156 }
157
158 #[async_std::test]
159 async fn test_update() {
160 let param = UpdateRequest {
161 channel: "C123456789".to_string(),
162 ts: "1405894322.002768".to_string(),
163 as_user: Some(true),
164 attachments: Some(vec![Attachment {
165 pretext: Some("pre-hello".to_string()),
166 text: Some("text-world".to_string()),
167 ..Default::default()
168 }]),
169 blocks: Some(vec![Block::SectionBlock(SectionBlock {
170 text: Some(TextBlockObject {
171 type_filed: TextBlockType::PlainText,
172 text: "text".to_string(),
173 ..Default::default()
174 }),
175 ..Default::default()
176 })]),
177 file_ids: Some(vec!["F013GKY52QK".to_string(), "F013GL22D0T".to_string()]),
178 link_names: Some(true),
179 parse: Some("none".to_string()),
180 reply_broadcast: Some(true),
181 text: Some("Hello world".to_string()),
182 };
183
184 let mut mock = MockSlackWebAPIClient::new();
185 mock.expect_post_json().returning(|_, _, _| {
186 Ok(r##"{
187 "ok": true,
188 "channel": "C123456789",
189 "ts": "1401383885.000061",
190 "text": "Hello world",
191 "message": {
192 "text": "text",
193 "user": "U34567890"
194 }
195}"##
196 .to_string())
197 });
198
199 let response = update(&mock, ¶m, &"test_token".to_string())
200 .await
201 .unwrap();
202 let expect = UpdateResponse {
203 ok: true,
204 channel: Some("C123456789".to_string()),
205 ts: Some("1401383885.000061".to_string()),
206 text: Some("Hello world".to_string()),
207 message: Some(Message {
208 text: Some("text".to_string()),
209 user: Some("U34567890".to_string()),
210 ..Default::default()
211 }),
212 ..Default::default()
213 };
214
215 assert_eq!(expect, response);
216 }
217}