open_lark/service/cloud_docs/comments/
batch_query.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
17use super::list::Comment;
18
19/// 批量获取评论请求
20#[derive(Debug, Serialize, Default, Clone)]
21pub struct BatchQueryCommentsRequest {
22    #[serde(skip)]
23    api_request: ApiRequest,
24    /// 文档token
25    #[serde(skip)]
26    file_token: String,
27    /// 文档类型:doc、docx、sheet、bitable
28    #[serde(skip)]
29    file_type: String,
30    /// 评论ID列表
31    comment_ids: Vec<String>,
32    /// 用户ID类型
33    #[serde(skip_serializing_if = "Option::is_none")]
34    user_id_type: Option<String>,
35}
36
37impl BatchQueryCommentsRequest {
38    pub fn builder() -> BatchQueryCommentsRequestBuilder {
39        BatchQueryCommentsRequestBuilder::default()
40    }
41
42    pub fn new(
43        file_token: impl ToString,
44        file_type: impl ToString,
45        comment_ids: Vec<String>,
46    ) -> Self {
47        Self {
48            file_token: file_token.to_string(),
49            file_type: file_type.to_string(),
50            comment_ids,
51            ..Default::default()
52        }
53    }
54}
55
56#[derive(Default)]
57pub struct BatchQueryCommentsRequestBuilder {
58    request: BatchQueryCommentsRequest,
59}
60
61impl BatchQueryCommentsRequestBuilder {
62    /// 文档token
63    pub fn file_token(mut self, file_token: impl ToString) -> Self {
64        self.request.file_token = file_token.to_string();
65        self
66    }
67
68    /// 文档类型
69    pub fn file_type(mut self, file_type: impl ToString) -> Self {
70        self.request.file_type = file_type.to_string();
71        self
72    }
73
74    /// 设置为文档类型
75    pub fn with_doc_type(mut self) -> Self {
76        self.request.file_type = "doc".to_string();
77        self
78    }
79
80    /// 设置为docx类型
81    pub fn with_docx_type(mut self) -> Self {
82        self.request.file_type = "docx".to_string();
83        self
84    }
85
86    /// 设置为电子表格类型
87    pub fn with_sheet_type(mut self) -> Self {
88        self.request.file_type = "sheet".to_string();
89        self
90    }
91
92    /// 设置为多维表格类型
93    pub fn with_bitable_type(mut self) -> Self {
94        self.request.file_type = "bitable".to_string();
95        self
96    }
97
98    /// 评论ID列表
99    pub fn comment_ids(mut self, comment_ids: Vec<String>) -> Self {
100        self.request.comment_ids = comment_ids;
101        self
102    }
103
104    /// 添加单个评论ID
105    pub fn add_comment_id(mut self, comment_id: impl ToString) -> Self {
106        self.request.comment_ids.push(comment_id.to_string());
107        self
108    }
109
110    /// 批量添加评论ID
111    pub fn add_comment_ids(mut self, comment_ids: Vec<impl ToString>) -> Self {
112        for comment_id in comment_ids {
113            self.request.comment_ids.push(comment_id.to_string());
114        }
115        self
116    }
117
118    /// 用户ID类型
119    pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
120        self.request.user_id_type = Some(user_id_type.to_string());
121        self
122    }
123
124    /// 使用OpenID
125    pub fn with_open_id(mut self) -> Self {
126        self.request.user_id_type = Some("open_id".to_string());
127        self
128    }
129
130    /// 使用UserID
131    pub fn with_user_id(mut self) -> Self {
132        self.request.user_id_type = Some("user_id".to_string());
133        self
134    }
135
136    /// 使用UnionID
137    pub fn with_union_id(mut self) -> Self {
138        self.request.user_id_type = Some("union_id".to_string());
139        self
140    }
141
142    pub fn build(mut self) -> BatchQueryCommentsRequest {
143        self.request.api_request.body = serde_json::to_vec(&self.request).unwrap();
144        self.request
145    }
146}
147
148// 应用ExecutableBuilder trait到BatchQueryCommentsRequestBuilder
149impl_executable_builder_owned!(
150    BatchQueryCommentsRequestBuilder,
151    super::CommentsService,
152    BatchQueryCommentsRequest,
153    BaseResponse<BatchQueryCommentsResponse>,
154    batch_query
155);
156
157/// 批量获取评论响应
158#[derive(Debug, Deserialize)]
159pub struct BatchQueryCommentsResponse {
160    /// 评论列表
161    pub items: Vec<Comment>,
162}
163
164impl ApiResponseTrait for BatchQueryCommentsResponse {
165    fn data_format() -> ResponseFormat {
166        ResponseFormat::Data
167    }
168}
169
170/// 批量获取评论
171pub async fn batch_query_comments(
172    request: BatchQueryCommentsRequest,
173    config: &Config,
174    option: Option<RequestOption>,
175) -> SDKResult<BaseResponse<BatchQueryCommentsResponse>> {
176    let mut api_req = request.api_request;
177    api_req.http_method = Method::POST;
178    api_req.api_path = format!(
179        "/open-apis/comment/v1/comments/batch_query?file_type={}&file_token={}",
180        request.file_type, request.file_token
181    );
182
183    // 添加用户ID类型查询参数
184    if let Some(user_id_type) = request.user_id_type {
185        api_req.api_path = format!("{}&user_id_type={}", api_req.api_path, user_id_type);
186    }
187
188    api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
189
190    let api_resp = Transport::request(api_req, config, option).await?;
191    Ok(api_resp)
192}
193
194impl BatchQueryCommentsResponse {
195    /// 获取评论数量
196    pub fn count(&self) -> usize {
197        self.items.len()
198    }
199
200    /// 是否为空
201    pub fn is_empty(&self) -> bool {
202        self.items.is_empty()
203    }
204
205    /// 获取已解决的评论
206    pub fn solved_comments(&self) -> Vec<&Comment> {
207        self.items
208            .iter()
209            .filter(|comment| comment.is_solved)
210            .collect()
211    }
212
213    /// 获取未解决的评论
214    pub fn unsolved_comments(&self) -> Vec<&Comment> {
215        self.items
216            .iter()
217            .filter(|comment| !comment.is_solved)
218            .collect()
219    }
220
221    /// 获取全文评论
222    pub fn whole_comments(&self) -> Vec<&Comment> {
223        self.items
224            .iter()
225            .filter(|comment| comment.is_whole.unwrap_or(false))
226            .collect()
227    }
228
229    /// 获取非全文评论
230    pub fn non_whole_comments(&self) -> Vec<&Comment> {
231        self.items
232            .iter()
233            .filter(|comment| !comment.is_whole.unwrap_or(false))
234            .collect()
235    }
236
237    /// 根据用户ID筛选评论
238    pub fn comments_by_user(&self, user_id: &str) -> Vec<&Comment> {
239        self.items
240            .iter()
241            .filter(|comment| comment.user_id == user_id)
242            .collect()
243    }
244
245    /// 获取有回复的评论
246    pub fn comments_with_replies(&self) -> Vec<&Comment> {
247        self.items
248            .iter()
249            .filter(|comment| comment.has_replies())
250            .collect()
251    }
252}
253
254#[cfg(test)]
255mod tests {
256    use super::*;
257
258    #[test]
259    fn test_batch_query_comments_request_builder() {
260        let request = BatchQueryCommentsRequest::builder()
261            .file_token("doccnxxxxxx")
262            .with_doc_type()
263            .add_comment_id("comment1")
264            .add_comment_id("comment2")
265            .add_comment_ids(vec!["comment3", "comment4"])
266            .with_open_id()
267            .build();
268
269        assert_eq!(request.file_token, "doccnxxxxxx");
270        assert_eq!(request.file_type, "doc");
271        assert_eq!(request.comment_ids.len(), 4);
272        assert_eq!(request.comment_ids[0], "comment1");
273        assert_eq!(request.comment_ids[3], "comment4");
274        assert_eq!(request.user_id_type, Some("open_id".to_string()));
275    }
276}