open_lark/service/cloud_docs/comments/
update_reply.rs1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5 core::{
6 api_req::ApiRequest,
7 api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8 config::Config,
9 constants::AccessTokenType,
10 endpoints::{cloud_docs::*, EndpointBuilder},
11 http::Transport,
12 req_option::RequestOption,
13 SDKResult,
14 },
15 impl_executable_builder_owned,
16};
17
18use super::list::ReplyContent;
19
20#[derive(Debug, Serialize, Default, Clone)]
22pub struct UpdateReplyRequest {
23 #[serde(skip)]
24 api_request: ApiRequest,
25 #[serde(skip)]
27 file_token: String,
28 #[serde(skip)]
30 file_type: String,
31 #[serde(skip)]
33 comment_id: String,
34 #[serde(skip)]
36 reply_id: String,
37 content: ReplyContent,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 user_id_type: Option<String>,
42}
43
44impl UpdateReplyRequest {
45 pub fn builder() -> UpdateReplyRequestBuilder {
46 UpdateReplyRequestBuilder::default()
47 }
48
49 pub fn new(
50 file_token: impl ToString,
51 file_type: impl ToString,
52 comment_id: impl ToString,
53 reply_id: impl ToString,
54 content: ReplyContent,
55 ) -> Self {
56 Self {
57 file_token: file_token.to_string(),
58 file_type: file_type.to_string(),
59 comment_id: comment_id.to_string(),
60 reply_id: reply_id.to_string(),
61 content,
62 ..Default::default()
63 }
64 }
65}
66
67#[derive(Default)]
68pub struct UpdateReplyRequestBuilder {
69 request: UpdateReplyRequest,
70}
71
72impl UpdateReplyRequestBuilder {
73 pub fn file_token(mut self, file_token: impl ToString) -> Self {
75 self.request.file_token = file_token.to_string();
76 self
77 }
78
79 pub fn file_type(mut self, file_type: impl ToString) -> Self {
81 self.request.file_type = file_type.to_string();
82 self
83 }
84
85 pub fn with_doc_type(mut self) -> Self {
87 self.request.file_type = "doc".to_string();
88 self
89 }
90
91 pub fn with_docx_type(mut self) -> Self {
93 self.request.file_type = "docx".to_string();
94 self
95 }
96
97 pub fn with_sheet_type(mut self) -> Self {
99 self.request.file_type = "sheet".to_string();
100 self
101 }
102
103 pub fn with_bitable_type(mut self) -> Self {
105 self.request.file_type = "bitable".to_string();
106 self
107 }
108
109 pub fn comment_id(mut self, comment_id: impl ToString) -> Self {
111 self.request.comment_id = comment_id.to_string();
112 self
113 }
114
115 pub fn reply_id(mut self, reply_id: impl ToString) -> Self {
117 self.request.reply_id = reply_id.to_string();
118 self
119 }
120
121 pub fn content(mut self, content: ReplyContent) -> Self {
123 self.request.content = content;
124 self
125 }
126
127 pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
129 self.request.user_id_type = Some(user_id_type.to_string());
130 self
131 }
132
133 pub fn with_open_id(mut self) -> Self {
135 self.request.user_id_type = Some("open_id".to_string());
136 self
137 }
138
139 pub fn with_user_id(mut self) -> Self {
141 self.request.user_id_type = Some("user_id".to_string());
142 self
143 }
144
145 pub fn with_union_id(mut self) -> Self {
147 self.request.user_id_type = Some("union_id".to_string());
148 self
149 }
150
151 pub fn build(mut self) -> UpdateReplyRequest {
152 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
153 self.request
154 }
155}
156
157#[derive(Debug, Deserialize)]
159pub struct UpdatedReply {
160 pub reply_id: String,
162 pub user_id: String,
164 pub create_time: i64,
166 pub update_time: i64,
168 pub content: ReplyContent,
170}
171
172impl_executable_builder_owned!(
174 UpdateReplyRequestBuilder,
175 super::CommentsService,
176 UpdateReplyRequest,
177 BaseResponse<UpdateReplyResponse>,
178 update_reply
179);
180
181#[derive(Debug, Deserialize)]
183pub struct UpdateReplyResponse {
184 pub reply: UpdatedReply,
186}
187
188impl ApiResponseTrait for UpdateReplyResponse {
189 fn data_format() -> ResponseFormat {
190 ResponseFormat::Data
191 }
192}
193
194pub async fn update_reply(
196 request: UpdateReplyRequest,
197 config: &Config,
198 option: Option<RequestOption>,
199) -> SDKResult<BaseResponse<UpdateReplyResponse>> {
200 let mut api_req = request.api_request;
201 api_req.http_method = Method::PUT;
202 api_req.api_path = format!(
203 "{}?file_type={}&file_token={}",
204 EndpointBuilder::replace_params_from_array(
205 COMMENT_V1_COMMENT_REPLY_UPDATE,
206 &[
207 ("comment_id", &request.comment_id),
208 ("reply_id", &request.reply_id)
209 ]
210 ),
211 request.file_type,
212 request.file_token
213 );
214
215 if let Some(user_id_type) = request.user_id_type {
217 api_req.api_path = format!("{}&user_id_type={}", api_req.api_path, user_id_type);
218 }
219
220 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
221
222 let api_resp = Transport::request(api_req, config, option).await?;
223 Ok(api_resp)
224}
225
226impl UpdatedReply {
227 pub fn get_text_content(&self) -> String {
229 self.content
230 .elements
231 .iter()
232 .filter_map(|element| {
233 element
234 .text_run
235 .as_ref()
236 .map(|text_run| text_run.text.clone())
237 })
238 .collect::<Vec<_>>()
239 .join("")
240 }
241
242 pub fn is_updated(&self) -> bool {
244 self.update_time > self.create_time
245 }
246
247 pub fn time_since_creation(&self) -> i64 {
249 self.update_time - self.create_time
250 }
251
252 pub fn updated_at_formatted(&self) -> String {
254 format!("更新时间: {}", self.update_time)
255 }
256
257 pub fn summary(&self) -> String {
259 format!(
260 "回复ID: {}, 用户: {}, 内容: {}, 更新时间: {}",
261 self.reply_id,
262 self.user_id,
263 self.get_text_content(),
264 self.update_time
265 )
266 }
267}
268
269impl UpdateReplyResponse {
270 pub fn reply_id(&self) -> &str {
272 &self.reply.reply_id
273 }
274
275 pub fn user_id(&self) -> &str {
277 &self.reply.user_id
278 }
279
280 pub fn get_text_content(&self) -> String {
282 self.reply.get_text_content()
283 }
284
285 pub fn is_updated(&self) -> bool {
287 self.reply.is_updated()
288 }
289
290 pub fn create_time(&self) -> i64 {
292 self.reply.create_time
293 }
294
295 pub fn update_time(&self) -> i64 {
297 self.reply.update_time
298 }
299
300 pub fn update_summary(&self) -> String {
302 format!(
303 "回复更新成功 - ID: {}, 新内容: \"{}\"",
304 self.reply_id(),
305 self.get_text_content()
306 )
307 }
308}
309
310#[cfg(test)]
311#[allow(unused_variables, unused_unsafe)]
312mod tests {
313 use super::*;
314 use crate::service::comments::create::ContentBuilder;
315
316 #[test]
317 fn test_update_reply_request_builder() {
318 let content = ContentBuilder::new().add_text("更新后的回复内容").build();
319
320 let request = UpdateReplyRequest::builder()
321 .file_token("doccnxxxxxx")
322 .with_doc_type()
323 .comment_id("comment123")
324 .reply_id("reply456")
325 .content(content)
326 .with_open_id()
327 .build();
328
329 assert_eq!(request.file_token, "doccnxxxxxx");
330 assert_eq!(request.file_type, "doc");
331 assert_eq!(request.comment_id, "comment123");
332 assert_eq!(request.reply_id, "reply456");
333 assert_eq!(request.user_id_type, Some("open_id".to_string()));
334 }
335}