open_lark/service/cloud_docs/comments/
delete_reply.rs

1use 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/// 删除回复请求
19#[derive(Debug, Serialize, Default, Clone)]
20pub struct DeleteReplyRequest {
21    #[serde(skip)]
22    api_request: ApiRequest,
23    /// 文档token
24    #[serde(skip)]
25    file_token: String,
26    /// 文档类型:doc、docx、sheet、bitable
27    #[serde(skip)]
28    file_type: String,
29    /// 评论ID
30    #[serde(skip)]
31    comment_id: String,
32    /// 回复ID
33    #[serde(skip)]
34    reply_id: String,
35    /// 用户ID类型
36    #[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    /// 文档token
68    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    /// 文档类型
74    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    /// 设置为文档类型
80    pub fn with_doc_type(mut self) -> Self {
81        self.request.file_type = "doc".to_string();
82        self
83    }
84
85    /// 设置为docx类型
86    pub fn with_docx_type(mut self) -> Self {
87        self.request.file_type = "docx".to_string();
88        self
89    }
90
91    /// 设置为电子表格类型
92    pub fn with_sheet_type(mut self) -> Self {
93        self.request.file_type = "sheet".to_string();
94        self
95    }
96
97    /// 设置为多维表格类型
98    pub fn with_bitable_type(mut self) -> Self {
99        self.request.file_type = "bitable".to_string();
100        self
101    }
102
103    /// 评论ID
104    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    /// 回复ID
110    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    /// 用户ID类型
116    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    /// 使用OpenID
122    pub fn with_open_id(mut self) -> Self {
123        self.request.user_id_type = Some("open_id".to_string());
124        self
125    }
126
127    /// 使用UserID
128    pub fn with_user_id(mut self) -> Self {
129        self.request.user_id_type = Some("user_id".to_string());
130        self
131    }
132
133    /// 使用UnionID
134    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/// 删除的回复信息
146#[derive(Debug, Deserialize)]
147pub struct DeletedReply {
148    /// 回复ID
149    pub reply_id: String,
150    /// 评论ID
151    pub comment_id: String,
152    /// 删除时间(毫秒时间戳)
153    pub delete_time: Option<i64>,
154    /// 删除者用户ID
155    pub deleter_user_id: Option<String>,
156}
157
158// 应用ExecutableBuilder trait到DeleteReplyRequestBuilder
159impl_executable_builder_owned!(
160    DeleteReplyRequestBuilder,
161    super::CommentsService,
162    DeleteReplyRequest,
163    BaseResponse<DeleteReplyResponse>,
164    delete_reply
165);
166
167/// 删除回复响应
168#[derive(Debug, Deserialize)]
169pub struct DeleteReplyResponse {
170    /// 删除的回复信息
171    pub reply: DeletedReply,
172}
173
174impl ApiResponseTrait for DeleteReplyResponse {
175    fn data_format() -> ResponseFormat {
176        ResponseFormat::Data
177    }
178}
179
180/// 删除回复
181pub 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, &params);
193    api_req.api_path = format!(
194        "{}?file_type={}&file_token={}",
195        endpoint, request.file_type, request.file_token
196    );
197
198    // 添加用户ID类型查询参数
199    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    /// 是否有删除时间
211    pub fn has_delete_time(&self) -> bool {
212        self.delete_time.is_some()
213    }
214
215    /// 是否有删除者信息
216    pub fn has_deleter(&self) -> bool {
217        self.deleter_user_id.is_some()
218    }
219
220    /// 获取删除时间的格式化字符串
221    pub fn delete_time_formatted(&self) -> Option<String> {
222        self.delete_time
223            .map(|timestamp| format!("删除时间: {timestamp}"))
224    }
225
226    /// 获取删除摘要信息
227    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    /// 获取回复ID
249    pub fn reply_id(&self) -> &str {
250        &self.reply.reply_id
251    }
252
253    /// 获取评论ID
254    pub fn comment_id(&self) -> &str {
255        &self.reply.comment_id
256    }
257
258    /// 获取删除时间
259    pub fn delete_time(&self) -> Option<i64> {
260        self.reply.delete_time
261    }
262
263    /// 获取删除者用户ID
264    pub fn deleter_user_id(&self) -> Option<&str> {
265        self.reply.deleter_user_id.as_deref()
266    }
267
268    /// 是否成功删除
269    pub fn is_deleted(&self) -> bool {
270        // 如果有回复信息返回,说明删除操作已执行
271        true
272    }
273
274    /// 获取删除成功的摘要信息
275    pub fn success_summary(&self) -> String {
276        format!(
277            "回复删除成功 - 回复ID: {}, 评论ID: {}",
278            self.reply_id(),
279            self.comment_id()
280        )
281    }
282
283    /// 获取详细的删除信息
284    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}