open_lark/service/cloud_docs/comments/
delete_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
18#[derive(Debug, Serialize, Default, Clone)]
20pub struct DeleteReplyRequest {
21 #[serde(skip)]
22 api_request: ApiRequest,
23 #[serde(skip)]
25 file_token: String,
26 #[serde(skip)]
28 file_type: String,
29 #[serde(skip)]
31 comment_id: String,
32 #[serde(skip)]
34 reply_id: String,
35 #[serde(skip_serializing_if = "Option::is_none")]
37 user_id_type: Option<String>,
38}
39
40impl DeleteReplyRequest {
41 pub fn builder() -> DeleteReplyRequestBuilder {
42 DeleteReplyRequestBuilder::default()
43 }
44
45 pub fn new(
46 file_token: impl ToString,
47 file_type: impl ToString,
48 comment_id: impl ToString,
49 reply_id: impl ToString,
50 ) -> Self {
51 Self {
52 file_token: file_token.to_string(),
53 file_type: file_type.to_string(),
54 comment_id: comment_id.to_string(),
55 reply_id: reply_id.to_string(),
56 ..Default::default()
57 }
58 }
59}
60
61#[derive(Default)]
62pub struct DeleteReplyRequestBuilder {
63 request: DeleteReplyRequest,
64}
65
66impl DeleteReplyRequestBuilder {
67 pub fn file_token(mut self, file_token: impl ToString) -> Self {
69 self.request.file_token = file_token.to_string();
70 self
71 }
72
73 pub fn file_type(mut self, file_type: impl ToString) -> Self {
75 self.request.file_type = file_type.to_string();
76 self
77 }
78
79 pub fn with_doc_type(mut self) -> Self {
81 self.request.file_type = "doc".to_string();
82 self
83 }
84
85 pub fn with_docx_type(mut self) -> Self {
87 self.request.file_type = "docx".to_string();
88 self
89 }
90
91 pub fn with_sheet_type(mut self) -> Self {
93 self.request.file_type = "sheet".to_string();
94 self
95 }
96
97 pub fn with_bitable_type(mut self) -> Self {
99 self.request.file_type = "bitable".to_string();
100 self
101 }
102
103 pub fn comment_id(mut self, comment_id: impl ToString) -> Self {
105 self.request.comment_id = comment_id.to_string();
106 self
107 }
108
109 pub fn reply_id(mut self, reply_id: impl ToString) -> Self {
111 self.request.reply_id = reply_id.to_string();
112 self
113 }
114
115 pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
117 self.request.user_id_type = Some(user_id_type.to_string());
118 self
119 }
120
121 pub fn with_open_id(mut self) -> Self {
123 self.request.user_id_type = Some("open_id".to_string());
124 self
125 }
126
127 pub fn with_user_id(mut self) -> Self {
129 self.request.user_id_type = Some("user_id".to_string());
130 self
131 }
132
133 pub fn with_union_id(mut self) -> Self {
135 self.request.user_id_type = Some("union_id".to_string());
136 self
137 }
138
139 pub fn build(mut self) -> DeleteReplyRequest {
140 self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
141 self.request
142 }
143}
144
145#[derive(Debug, Deserialize)]
147pub struct DeletedReply {
148 pub reply_id: String,
150 pub comment_id: String,
152 pub delete_time: Option<i64>,
154 pub deleter_user_id: Option<String>,
156}
157
158impl_executable_builder_owned!(
160 DeleteReplyRequestBuilder,
161 super::CommentsService,
162 DeleteReplyRequest,
163 BaseResponse<DeleteReplyResponse>,
164 delete_reply
165);
166
167#[derive(Debug, Deserialize)]
169pub struct DeleteReplyResponse {
170 pub reply: DeletedReply,
172}
173
174impl ApiResponseTrait for DeleteReplyResponse {
175 fn data_format() -> ResponseFormat {
176 ResponseFormat::Data
177 }
178}
179
180pub async fn delete_reply(
182 request: DeleteReplyRequest,
183 config: &Config,
184 option: Option<RequestOption>,
185) -> SDKResult<BaseResponse<DeleteReplyResponse>> {
186 let mut api_req = request.api_request;
187 api_req.http_method = Method::DELETE;
188 use std::collections::HashMap;
189 let mut params = HashMap::new();
190 params.insert("comment_id".to_string(), request.comment_id.clone());
191 params.insert("reply_id".to_string(), request.reply_id.clone());
192 let endpoint = EndpointBuilder::replace_params(COMMENT_V1_COMMENT_REPLY_DELETE, ¶ms);
193 api_req.api_path = format!(
194 "{}?file_type={}&file_token={}",
195 endpoint, request.file_type, request.file_token
196 );
197
198 if let Some(user_id_type) = request.user_id_type {
200 api_req.api_path = format!("{}&user_id_type={}", api_req.api_path, user_id_type);
201 }
202
203 api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
204
205 let api_resp = Transport::request(api_req, config, option).await?;
206 Ok(api_resp)
207}
208
209impl DeletedReply {
210 pub fn has_delete_time(&self) -> bool {
212 self.delete_time.is_some()
213 }
214
215 pub fn has_deleter(&self) -> bool {
217 self.deleter_user_id.is_some()
218 }
219
220 pub fn delete_time_formatted(&self) -> Option<String> {
222 self.delete_time
223 .map(|timestamp| format!("删除时间: {timestamp}"))
224 }
225
226 pub fn summary(&self) -> String {
228 let delete_info = if let Some(time) = self.delete_time {
229 format!("删除时间: {time}")
230 } else {
231 "删除时间: 未知".to_string()
232 };
233
234 let deleter_info = if let Some(deleter) = &self.deleter_user_id {
235 format!("删除者: {deleter}")
236 } else {
237 "删除者: 未知".to_string()
238 };
239
240 format!(
241 "回复ID: {}, 评论ID: {}, {}, {}",
242 self.reply_id, self.comment_id, delete_info, deleter_info
243 )
244 }
245}
246
247impl DeleteReplyResponse {
248 pub fn reply_id(&self) -> &str {
250 &self.reply.reply_id
251 }
252
253 pub fn comment_id(&self) -> &str {
255 &self.reply.comment_id
256 }
257
258 pub fn delete_time(&self) -> Option<i64> {
260 self.reply.delete_time
261 }
262
263 pub fn deleter_user_id(&self) -> Option<&str> {
265 self.reply.deleter_user_id.as_deref()
266 }
267
268 pub fn is_deleted(&self) -> bool {
270 true
272 }
273
274 pub fn success_summary(&self) -> String {
276 format!(
277 "回复删除成功 - 回复ID: {}, 评论ID: {}",
278 self.reply_id(),
279 self.comment_id()
280 )
281 }
282
283 pub fn detailed_info(&self) -> String {
285 self.reply.summary()
286 }
287}
288
289#[cfg(test)]
290#[allow(unused_variables, unused_unsafe)]
291mod tests {
292 use super::*;
293
294 #[test]
295 fn test_delete_reply_request_builder() {
296 let request = DeleteReplyRequest::builder()
297 .file_token("doccnxxxxxx")
298 .with_doc_type()
299 .comment_id("comment123")
300 .reply_id("reply456")
301 .with_open_id()
302 .build();
303
304 assert_eq!(request.file_token, "doccnxxxxxx");
305 assert_eq!(request.file_type, "doc");
306 assert_eq!(request.comment_id, "comment123");
307 assert_eq!(request.reply_id, "reply456");
308 assert_eq!(request.user_id_type, Some("open_id".to_string()));
309 }
310
311 #[test]
312 fn test_delete_reply_new() {
313 let request = DeleteReplyRequest::new("doccnxxxxxx", "doc", "comment123", "reply456");
314 assert_eq!(request.file_token, "doccnxxxxxx");
315 assert_eq!(request.file_type, "doc");
316 assert_eq!(request.comment_id, "comment123");
317 assert_eq!(request.reply_id, "reply456");
318 }
319}