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        http::Transport,
11        req_option::RequestOption,
12        SDKResult,
13    },
14    impl_executable_builder_owned,
15};
16
17/// 删除回复请求
18#[derive(Debug, Serialize, Default, Clone)]
19pub struct DeleteReplyRequest {
20    #[serde(skip)]
21    api_request: ApiRequest,
22    /// 文档token
23    #[serde(skip)]
24    file_token: String,
25    /// 文档类型:doc、docx、sheet、bitable
26    #[serde(skip)]
27    file_type: String,
28    /// 评论ID
29    #[serde(skip)]
30    comment_id: String,
31    /// 回复ID
32    #[serde(skip)]
33    reply_id: String,
34    /// 用户ID类型
35    #[serde(skip_serializing_if = "Option::is_none")]
36    user_id_type: Option<String>,
37}
38
39impl DeleteReplyRequest {
40    pub fn builder() -> DeleteReplyRequestBuilder {
41        DeleteReplyRequestBuilder::default()
42    }
43
44    pub fn new(
45        file_token: impl ToString,
46        file_type: impl ToString,
47        comment_id: impl ToString,
48        reply_id: impl ToString,
49    ) -> Self {
50        Self {
51            file_token: file_token.to_string(),
52            file_type: file_type.to_string(),
53            comment_id: comment_id.to_string(),
54            reply_id: reply_id.to_string(),
55            ..Default::default()
56        }
57    }
58}
59
60#[derive(Default)]
61pub struct DeleteReplyRequestBuilder {
62    request: DeleteReplyRequest,
63}
64
65impl DeleteReplyRequestBuilder {
66    /// 文档token
67    pub fn file_token(mut self, file_token: impl ToString) -> Self {
68        self.request.file_token = file_token.to_string();
69        self
70    }
71
72    /// 文档类型
73    pub fn file_type(mut self, file_type: impl ToString) -> Self {
74        self.request.file_type = file_type.to_string();
75        self
76    }
77
78    /// 设置为文档类型
79    pub fn with_doc_type(mut self) -> Self {
80        self.request.file_type = "doc".to_string();
81        self
82    }
83
84    /// 设置为docx类型
85    pub fn with_docx_type(mut self) -> Self {
86        self.request.file_type = "docx".to_string();
87        self
88    }
89
90    /// 设置为电子表格类型
91    pub fn with_sheet_type(mut self) -> Self {
92        self.request.file_type = "sheet".to_string();
93        self
94    }
95
96    /// 设置为多维表格类型
97    pub fn with_bitable_type(mut self) -> Self {
98        self.request.file_type = "bitable".to_string();
99        self
100    }
101
102    /// 评论ID
103    pub fn comment_id(mut self, comment_id: impl ToString) -> Self {
104        self.request.comment_id = comment_id.to_string();
105        self
106    }
107
108    /// 回复ID
109    pub fn reply_id(mut self, reply_id: impl ToString) -> Self {
110        self.request.reply_id = reply_id.to_string();
111        self
112    }
113
114    /// 用户ID类型
115    pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
116        self.request.user_id_type = Some(user_id_type.to_string());
117        self
118    }
119
120    /// 使用OpenID
121    pub fn with_open_id(mut self) -> Self {
122        self.request.user_id_type = Some("open_id".to_string());
123        self
124    }
125
126    /// 使用UserID
127    pub fn with_user_id(mut self) -> Self {
128        self.request.user_id_type = Some("user_id".to_string());
129        self
130    }
131
132    /// 使用UnionID
133    pub fn with_union_id(mut self) -> Self {
134        self.request.user_id_type = Some("union_id".to_string());
135        self
136    }
137
138    pub fn build(mut self) -> DeleteReplyRequest {
139        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
140        self.request
141    }
142}
143
144/// 删除的回复信息
145#[derive(Debug, Deserialize)]
146pub struct DeletedReply {
147    /// 回复ID
148    pub reply_id: String,
149    /// 评论ID
150    pub comment_id: String,
151    /// 删除时间(毫秒时间戳)
152    pub delete_time: Option<i64>,
153    /// 删除者用户ID
154    pub deleter_user_id: Option<String>,
155}
156
157// 应用ExecutableBuilder trait到DeleteReplyRequestBuilder
158impl_executable_builder_owned!(
159    DeleteReplyRequestBuilder,
160    super::CommentsService,
161    DeleteReplyRequest,
162    BaseResponse<DeleteReplyResponse>,
163    delete_reply
164);
165
166/// 删除回复响应
167#[derive(Debug, Deserialize)]
168pub struct DeleteReplyResponse {
169    /// 删除的回复信息
170    pub reply: DeletedReply,
171}
172
173impl ApiResponseTrait for DeleteReplyResponse {
174    fn data_format() -> ResponseFormat {
175        ResponseFormat::Data
176    }
177}
178
179/// 删除回复
180pub async fn delete_reply(
181    request: DeleteReplyRequest,
182    config: &Config,
183    option: Option<RequestOption>,
184) -> SDKResult<BaseResponse<DeleteReplyResponse>> {
185    let mut api_req = request.api_request;
186    api_req.http_method = Method::DELETE;
187    api_req.api_path = format!(
188        "/open-apis/comment/v1/comments/{}/replies/{}?file_type={}&file_token={}",
189        request.comment_id, request.reply_id, request.file_type, request.file_token
190    );
191
192    // 添加用户ID类型查询参数
193    if let Some(user_id_type) = request.user_id_type {
194        api_req.api_path = format!("{}&user_id_type={}", api_req.api_path, user_id_type);
195    }
196
197    api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
198
199    let api_resp = Transport::request(api_req, config, option).await?;
200    Ok(api_resp)
201}
202
203impl DeletedReply {
204    /// 是否有删除时间
205    pub fn has_delete_time(&self) -> bool {
206        self.delete_time.is_some()
207    }
208
209    /// 是否有删除者信息
210    pub fn has_deleter(&self) -> bool {
211        self.deleter_user_id.is_some()
212    }
213
214    /// 获取删除时间的格式化字符串
215    pub fn delete_time_formatted(&self) -> Option<String> {
216        self.delete_time
217            .map(|timestamp| format!("删除时间: {timestamp}"))
218    }
219
220    /// 获取删除摘要信息
221    pub fn summary(&self) -> String {
222        let delete_info = if let Some(time) = self.delete_time {
223            format!("删除时间: {time}")
224        } else {
225            "删除时间: 未知".to_string()
226        };
227
228        let deleter_info = if let Some(deleter) = &self.deleter_user_id {
229            format!("删除者: {deleter}")
230        } else {
231            "删除者: 未知".to_string()
232        };
233
234        format!(
235            "回复ID: {}, 评论ID: {}, {}, {}",
236            self.reply_id, self.comment_id, delete_info, deleter_info
237        )
238    }
239}
240
241impl DeleteReplyResponse {
242    /// 获取回复ID
243    pub fn reply_id(&self) -> &str {
244        &self.reply.reply_id
245    }
246
247    /// 获取评论ID
248    pub fn comment_id(&self) -> &str {
249        &self.reply.comment_id
250    }
251
252    /// 获取删除时间
253    pub fn delete_time(&self) -> Option<i64> {
254        self.reply.delete_time
255    }
256
257    /// 获取删除者用户ID
258    pub fn deleter_user_id(&self) -> Option<&str> {
259        self.reply.deleter_user_id.as_deref()
260    }
261
262    /// 是否成功删除
263    pub fn is_deleted(&self) -> bool {
264        // 如果有回复信息返回,说明删除操作已执行
265        true
266    }
267
268    /// 获取删除成功的摘要信息
269    pub fn success_summary(&self) -> String {
270        format!(
271            "回复删除成功 - 回复ID: {}, 评论ID: {}",
272            self.reply_id(),
273            self.comment_id()
274        )
275    }
276
277    /// 获取详细的删除信息
278    pub fn detailed_info(&self) -> String {
279        self.reply.summary()
280    }
281}
282
283#[cfg(test)]
284mod tests {
285    use super::*;
286
287    #[test]
288    fn test_delete_reply_request_builder() {
289        let request = DeleteReplyRequest::builder()
290            .file_token("doccnxxxxxx")
291            .with_doc_type()
292            .comment_id("comment123")
293            .reply_id("reply456")
294            .with_open_id()
295            .build();
296
297        assert_eq!(request.file_token, "doccnxxxxxx");
298        assert_eq!(request.file_type, "doc");
299        assert_eq!(request.comment_id, "comment123");
300        assert_eq!(request.reply_id, "reply456");
301        assert_eq!(request.user_id_type, Some("open_id".to_string()));
302    }
303
304    #[test]
305    fn test_delete_reply_new() {
306        let request = DeleteReplyRequest::new("doccnxxxxxx", "doc", "comment123", "reply456");
307        assert_eq!(request.file_token, "doccnxxxxxx");
308        assert_eq!(request.file_type, "doc");
309        assert_eq!(request.comment_id, "comment123");
310        assert_eq!(request.reply_id, "reply456");
311    }
312}