open_lark/service/cloud_docs/bitable/v1/app/
get.rs

1use reqwest::Method;
2use serde::Deserialize;
3
4use crate::{
5    core::{
6        api_req::ApiRequest,
7        api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8        constants::AccessTokenType,
9        endpoints::cloud_docs::*,
10        http::Transport,
11        req_option::RequestOption,
12        SDKResult,
13    },
14    impl_executable_builder_owned,
15};
16
17use super::AppService;
18
19impl AppService {
20    /// 获取多维表格元数据
21    ///
22    /// <https://open.feishu.cn/document/server-docs/docs/bitable-v1/app/get>
23    pub async fn get(
24        &self,
25        request: GetAppRequest,
26        option: Option<RequestOption>,
27    ) -> SDKResult<BaseResponse<GetAppResponse>> {
28        let mut api_req = request.api_request;
29        api_req.http_method = Method::GET;
30        api_req.api_path = BITABLE_V1_APP_GET.replace("{app_token}", &request.app_token);
31        api_req.supported_access_token_types = vec![AccessTokenType::Tenant, AccessTokenType::User];
32
33        let api_resp = Transport::request(api_req, &self.config, option).await?;
34        Ok(api_resp)
35    }
36}
37
38/// 获取多维表格元数据请求
39#[derive(Debug, Default)]
40pub struct GetAppRequest {
41    api_request: ApiRequest,
42    /// 多维表格的唯一标识符
43    app_token: String,
44}
45
46impl GetAppRequest {
47    pub fn builder() -> GetAppRequestBuilder {
48        GetAppRequestBuilder::default()
49    }
50
51    /// 创建获取多维表格元数据请求
52    pub fn new(app_token: impl ToString) -> Self {
53        Self {
54            api_request: ApiRequest::default(),
55            app_token: app_token.to_string(),
56        }
57    }
58}
59
60#[derive(Default)]
61pub struct GetAppRequestBuilder {
62    request: GetAppRequest,
63}
64
65impl GetAppRequestBuilder {
66    /// 多维表格的唯一标识符
67    pub fn app_token(mut self, app_token: impl ToString) -> Self {
68        self.request.app_token = app_token.to_string();
69        self
70    }
71
72    pub fn build(self) -> GetAppRequest {
73        self.request
74    }
75}
76
77impl_executable_builder_owned!(
78    GetAppRequestBuilder,
79    AppService,
80    GetAppRequest,
81    BaseResponse<GetAppResponse>,
82    get
83);
84
85#[derive(Deserialize, Debug)]
86pub struct GetAppResponse {
87    /// 多维表格的 app 信息
88    pub app: GetAppResponseData,
89}
90
91#[derive(Deserialize, Debug)]
92pub struct GetAppResponseData {
93    /// 多维表格的 app_token
94    pub app_token: String,
95    /// 多维表格的名字
96    pub name: String,
97    /// 多维表格的版本号(对多维表格进行修改时更新,如新增、删除数据表,修改数据表名等,初始为1,
98    /// 每次更新+1)
99    pub revision: i32,
100    /// 多维表格是否开启了高级权限。取值包括:
101    ///
102    /// - true:表示开启了高级权限
103    /// - false:表示关闭了高级权限
104    pub is_advanced: bool,
105    /// 文档时区
106    pub time_zone: String,
107}
108
109impl ApiResponseTrait for GetAppResponse {
110    fn data_format() -> ResponseFormat {
111        ResponseFormat::Data
112    }
113}
114
115#[cfg(test)]
116#[allow(unused_variables, unused_unsafe)]
117mod tests {
118    use super::*;
119    use serde_json;
120
121    #[test]
122    fn test_get_app_request() {
123        let request = GetAppRequest::builder()
124            .app_token("bascnmBA*****yGehy8")
125            .build();
126
127        assert_eq!(request.app_token, "bascnmBA*****yGehy8");
128    }
129
130    #[test]
131    fn test_get_app_request_new() {
132        let request = GetAppRequest::new("bascnmBA*****yGehy8");
133        assert_eq!(request.app_token, "bascnmBA*****yGehy8");
134    }
135
136    #[test]
137    fn test_get_app_request_builder_default() {
138        let builder = GetAppRequestBuilder::default();
139        let request = builder.build();
140        assert_eq!(request.app_token, "");
141    }
142
143    #[test]
144    fn test_get_app_request_builder_multiple_calls() {
145        let request = GetAppRequest::builder()
146            .app_token("first_token")
147            .app_token("final_token")
148            .build();
149        assert_eq!(request.app_token, "final_token");
150    }
151
152    #[test]
153    fn test_get_app_request_default() {
154        let request = GetAppRequest::default();
155        assert_eq!(request.app_token, "");
156    }
157
158    #[test]
159    fn test_get_app_request_debug() {
160        let request = GetAppRequest::new("test_app_token");
161        let debug_str = format!("{:?}", request);
162        assert!(debug_str.contains("GetAppRequest"));
163        assert!(debug_str.contains("test_app_token"));
164    }
165
166    #[test]
167    fn test_get_app_request_with_string_types() {
168        let owned_string = String::from("owned_token");
169        let request1 = GetAppRequest::new(owned_string);
170        assert_eq!(request1.app_token, "owned_token");
171
172        let string_ref = "ref_token";
173        let request2 = GetAppRequest::new(string_ref);
174        assert_eq!(request2.app_token, "ref_token");
175
176        let request3 = GetAppRequest::builder()
177            .app_token(String::from("builder_token"))
178            .build();
179        assert_eq!(request3.app_token, "builder_token");
180    }
181
182    #[test]
183    fn test_get_app_request_with_special_characters() {
184        let special_token = "app_token_with_特殊字符_123";
185        let request = GetAppRequest::new(special_token);
186        assert_eq!(request.app_token, special_token);
187    }
188
189    #[test]
190    fn test_get_app_request_with_empty_token() {
191        let request = GetAppRequest::new("");
192        assert_eq!(request.app_token, "");
193    }
194
195    #[test]
196    fn test_get_app_response_deserialization() {
197        let json = r#"{
198            "app": {
199                "app_token": "bascnmBA*****yGehy8",
200                "name": "测试多维表格",
201                "revision": 5,
202                "is_advanced": true,
203                "time_zone": "Asia/Shanghai"
204            }
205        }"#;
206
207        let response: GetAppResponse = serde_json::from_str(json).unwrap();
208        assert_eq!(response.app.app_token, "bascnmBA*****yGehy8");
209        assert_eq!(response.app.name, "测试多维表格");
210        assert_eq!(response.app.revision, 5);
211        assert!(response.app.is_advanced);
212        assert_eq!(response.app.time_zone, "Asia/Shanghai");
213    }
214
215    #[test]
216    fn test_get_app_response_data_debug() {
217        let app_data = GetAppResponseData {
218            app_token: "test_token".to_string(),
219            name: "Test App".to_string(),
220            revision: 1,
221            is_advanced: false,
222            time_zone: "UTC".to_string(),
223        };
224
225        let debug_str = format!("{:?}", app_data);
226        assert!(debug_str.contains("GetAppResponseData"));
227        assert!(debug_str.contains("test_token"));
228        assert!(debug_str.contains("Test App"));
229        assert!(debug_str.contains("UTC"));
230    }
231
232    #[test]
233    fn test_get_app_response_debug() {
234        let response = GetAppResponse {
235            app: GetAppResponseData {
236                app_token: "debug_token".to_string(),
237                name: "Debug App".to_string(),
238                revision: 3,
239                is_advanced: true,
240                time_zone: "America/New_York".to_string(),
241            },
242        };
243
244        let debug_str = format!("{:?}", response);
245        assert!(debug_str.contains("GetAppResponse"));
246        assert!(debug_str.contains("debug_token"));
247        assert!(debug_str.contains("Debug App"));
248    }
249
250    #[test]
251    fn test_get_app_response_with_false_advanced() {
252        let json = r#"{
253            "app": {
254                "app_token": "basic_app_token",
255                "name": "Basic App",
256                "revision": 1,
257                "is_advanced": false,
258                "time_zone": "UTC"
259            }
260        }"#;
261
262        let response: GetAppResponse = serde_json::from_str(json).unwrap();
263        assert!(!response.app.is_advanced);
264        assert_eq!(response.app.revision, 1);
265    }
266
267    #[test]
268    fn test_get_app_response_with_different_timezones() {
269        let timezones = vec![
270            ("UTC", "UTC"),
271            ("Asia/Shanghai", "Asia/Shanghai"),
272            ("America/New_York", "America/New_York"),
273            ("Europe/London", "Europe/London"),
274        ];
275
276        for (tz_input, tz_expected) in timezones {
277            let json = format!(
278                r#"{{
279                    "app": {{
280                        "app_token": "test_token",
281                        "name": "Test",
282                        "revision": 1,
283                        "is_advanced": false,
284                        "time_zone": "{}"
285                    }}
286                }}"#,
287                tz_input
288            );
289
290            let response: GetAppResponse = serde_json::from_str(&json).unwrap();
291            assert_eq!(response.app.time_zone, tz_expected);
292        }
293    }
294
295    #[test]
296    fn test_get_app_response_data_format() {
297        let format = GetAppResponse::data_format();
298        assert!(matches!(format, ResponseFormat::Data));
299    }
300
301    #[test]
302    fn test_get_app_response_with_large_revision() {
303        let json = r#"{
304            "app": {
305                "app_token": "test",
306                "name": "Test",
307                "revision": 999999,
308                "is_advanced": true,
309                "time_zone": "UTC"
310            }
311        }"#;
312
313        let response: GetAppResponse = serde_json::from_str(json).unwrap();
314        assert_eq!(response.app.revision, 999999);
315    }
316
317    #[test]
318    fn test_get_app_response_with_unicode_name() {
319        let json = r#"{
320            "app": {
321                "app_token": "unicode_test",
322                "name": "测试应用📱💼",
323                "revision": 2,
324                "is_advanced": false,
325                "time_zone": "Asia/Tokyo"
326            }
327        }"#;
328
329        let response: GetAppResponse = serde_json::from_str(json).unwrap();
330        assert_eq!(response.app.name, "测试应用📱💼");
331        assert_eq!(response.app.time_zone, "Asia/Tokyo");
332    }
333
334    #[test]
335    fn test_get_app_response_with_zero_revision() {
336        let json = r#"{
337            "app": {
338                "app_token": "zero_rev",
339                "name": "Zero Revision App",
340                "revision": 0,
341                "is_advanced": false,
342                "time_zone": "UTC"
343            }
344        }"#;
345
346        let response: GetAppResponse = serde_json::from_str(json).unwrap();
347        assert_eq!(response.app.revision, 0);
348    }
349
350    #[test]
351    fn test_memory_efficiency() {
352        let request = GetAppRequest::new("test");
353        let size = std::mem::size_of_val(&request);
354        assert!(size > 0);
355        assert!(size < 1024);
356    }
357}