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 http::Transport,
11 req_option::RequestOption,
12 SDKResult,
13 },
14 impl_executable_builder_owned,
15};
16
17use super::list::ReplyContent;
18
19#[derive(Debug, Serialize, Default, Clone)]
21pub struct UpdateReplyRequest {
22 #[serde(skip)]
23 api_request: ApiRequest,
24 #[serde(skip)]
26 file_token: String,
27 #[serde(skip)]
29 file_type: String,
30 #[serde(skip)]
32 comment_id: String,
33 #[serde(skip)]
35 reply_id: String,
36 content: ReplyContent,
38 #[serde(skip_serializing_if = "Option::is_none")]
40 user_id_type: Option<String>,
41}
42
43impl UpdateReplyRequest {
44 pub fn builder() -> UpdateReplyRequestBuilder {
45 UpdateReplyRequestBuilder::default()
46 }
47
48 pub fn new(
49 file_token: impl ToString,
50 file_type: impl ToString,
51 comment_id: impl ToString,
52 reply_id: impl ToString,
53 content: ReplyContent,
54 ) -> Self {
55 Self {
56 file_token: file_token.to_string(),
57 file_type: file_type.to_string(),
58 comment_id: comment_id.to_string(),
59 reply_id: reply_id.to_string(),
60 content,
61 ..Default::default()
62 }
63 }
64}
65
66#[derive(Default)]
67pub struct UpdateReplyRequestBuilder {
68 request: UpdateReplyRequest,
69}
70
71impl UpdateReplyRequestBuilder {
72 pub fn file_token(mut self, file_token: impl ToString) -> Self {
74 self.request.file_token = file_token.to_string();
75 self
76 }
77
78 pub fn file_type(mut self, file_type: impl ToString) -> Self {
80 self.request.file_type = file_type.to_string();
81 self
82 }
83
84 pub fn with_doc_type(mut self) -> Self {
86 self.request.file_type = "doc".to_string();
87 self
88 }
89
90 pub fn with_docx_type(mut self) -> Self {
92 self.request.file_type = "docx".to_string();
93 self
94 }
95
96 pub fn with_sheet_type(mut self) -> Self {
98 self.request.file_type = "sheet".to_string();
99 self
100 }
101
102 pub fn with_bitable_type(mut self) -> Self {
104 self.request.file_type = "bitable".to_string();
105 self
106 }
107
108 pub fn comment_id(mut self, comment_id: impl ToString) -> Self {
110 self.request.comment_id = comment_id.to_string();
111 self
112 }
113
114 pub fn reply_id(mut self, reply_id: impl ToString) -> Self {
116 self.request.reply_id = reply_id.to_string();
117 self
118 }
119
120 pub fn content(mut self, content: ReplyContent) -> Self {
122 self.request.content = content;
123 self
124 }
125
126 pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
128 self.request.user_id_type = Some(user_id_type.to_string());
129 self
130 }
131
132 pub fn with_open_id(mut self) -> Self {
134 self.request.user_id_type = Some("open_id".to_string());
135 self
136 }
137
138 pub fn with_user_id(mut self) -> Self {
140 self.request.user_id_type = Some("user_id".to_string());
141 self
142 }
143
144 pub fn with_union_id(mut self) -> Self {
146 self.request.user_id_type = Some("union_id".to_string());
147 self
148 }
149
150 pub fn build(mut self) -> UpdateReplyRequest {
151 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
152 self.request
153 }
154}
155
156#[derive(Debug, Deserialize)]
158pub struct UpdatedReply {
159 pub reply_id: String,
161 pub user_id: String,
163 pub create_time: i64,
165 pub update_time: i64,
167 pub content: ReplyContent,
169}
170
171impl_executable_builder_owned!(
173 UpdateReplyRequestBuilder,
174 super::CommentsService,
175 UpdateReplyRequest,
176 BaseResponse<UpdateReplyResponse>,
177 update_reply
178);
179
180#[derive(Debug, Deserialize)]
182pub struct UpdateReplyResponse {
183 pub reply: UpdatedReply,
185}
186
187impl ApiResponseTrait for UpdateReplyResponse {
188 fn data_format() -> ResponseFormat {
189 ResponseFormat::Data
190 }
191}
192
193pub async fn update_reply(
195 request: UpdateReplyRequest,
196 config: &Config,
197 option: Option<RequestOption>,
198) -> SDKResult<BaseResponse<UpdateReplyResponse>> {
199 let mut api_req = request.api_request;
200 api_req.http_method = Method::PUT;
201 api_req.api_path = format!(
202 "/open-apis/comment/v1/comments/{}/replies/{}?file_type={}&file_token={}",
203 request.comment_id, request.reply_id, request.file_type, request.file_token
204 );
205
206 if let Some(user_id_type) = request.user_id_type {
208 api_req.api_path = format!("{}&user_id_type={}", api_req.api_path, user_id_type);
209 }
210
211 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
212
213 let api_resp = Transport::request(api_req, config, option).await?;
214 Ok(api_resp)
215}
216
217impl UpdatedReply {
218 pub fn get_text_content(&self) -> String {
220 self.content
221 .elements
222 .iter()
223 .filter_map(|element| {
224 element
225 .text_run
226 .as_ref()
227 .map(|text_run| text_run.text.clone())
228 })
229 .collect::<Vec<_>>()
230 .join("")
231 }
232
233 pub fn is_updated(&self) -> bool {
235 self.update_time > self.create_time
236 }
237
238 pub fn time_since_creation(&self) -> i64 {
240 self.update_time - self.create_time
241 }
242
243 pub fn updated_at_formatted(&self) -> String {
245 format!("更新时间: {}", self.update_time)
246 }
247
248 pub fn summary(&self) -> String {
250 format!(
251 "回复ID: {}, 用户: {}, 内容: {}, 更新时间: {}",
252 self.reply_id,
253 self.user_id,
254 self.get_text_content(),
255 self.update_time
256 )
257 }
258}
259
260impl UpdateReplyResponse {
261 pub fn reply_id(&self) -> &str {
263 &self.reply.reply_id
264 }
265
266 pub fn user_id(&self) -> &str {
268 &self.reply.user_id
269 }
270
271 pub fn get_text_content(&self) -> String {
273 self.reply.get_text_content()
274 }
275
276 pub fn is_updated(&self) -> bool {
278 self.reply.is_updated()
279 }
280
281 pub fn create_time(&self) -> i64 {
283 self.reply.create_time
284 }
285
286 pub fn update_time(&self) -> i64 {
288 self.reply.update_time
289 }
290
291 pub fn update_summary(&self) -> String {
293 format!(
294 "回复更新成功 - ID: {}, 新内容: \"{}\"",
295 self.reply_id(),
296 self.get_text_content()
297 )
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304 use crate::service::comments::create::ContentBuilder;
305
306 #[test]
307 fn test_update_reply_request_builder() {
308 let content = ContentBuilder::new().add_text("更新后的回复内容").build();
309
310 let request = UpdateReplyRequest::builder()
311 .file_token("doccnxxxxxx")
312 .with_doc_type()
313 .comment_id("comment123")
314 .reply_id("reply456")
315 .content(content)
316 .with_open_id()
317 .build();
318
319 assert_eq!(request.file_token, "doccnxxxxxx");
320 assert_eq!(request.file_type, "doc");
321 assert_eq!(request.comment_id, "comment123");
322 assert_eq!(request.reply_id, "reply456");
323 assert_eq!(request.user_id_type, Some("open_id".to_string()));
324 }
325}