open_lark/service/im/v1/image/
mod.rs

1use reqwest::Method;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5use crate::core::{
6    api_req::ApiRequest,
7    api_resp::{ApiResponseTrait, BaseResponse, ResponseFormat},
8    config::Config,
9    constants::AccessTokenType,
10    endpoints::EndpointBuilder,
11    http::Transport,
12    req_option::RequestOption,
13    standard_response::StandardResponse,
14    trait_system::executable_builder::ExecutableBuilder,
15    SDKResult,
16};
17use crate::impl_full_service;
18use async_trait::async_trait;
19
20/// 图片服务
21pub struct ImageService {
22    pub config: Config,
23}
24
25/// 上传图片响应
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct CreateImageResponse {
28    /// 图片的key
29    pub image_key: String,
30}
31
32impl ApiResponseTrait for CreateImageResponse {
33    fn data_format() -> ResponseFormat {
34        ResponseFormat::Data
35    }
36}
37
38/// 下载图片响应
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct GetImageResponse {
41    /// 图片数据
42    pub data: Vec<u8>,
43}
44
45impl ApiResponseTrait for GetImageResponse {
46    fn data_format() -> ResponseFormat {
47        ResponseFormat::Data
48    }
49}
50
51impl ImageService {
52    pub fn new(config: Config) -> Self {
53        Self { config }
54    }
55
56    /// 上传图片
57    pub async fn create(
58        &self,
59        image_type: &str,
60        image_data: Vec<u8>,
61        option: Option<RequestOption>,
62    ) -> SDKResult<CreateImageResponse> {
63        let api_req = ApiRequest {
64            http_method: Method::POST,
65            api_path: crate::core::endpoints::im::IM_V1_IMAGES.to_string(),
66            supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
67            query_params: HashMap::from([("image_type", image_type.to_string())]),
68            body: image_data,
69            ..Default::default()
70        };
71
72        let api_resp: BaseResponse<CreateImageResponse> =
73            Transport::request(api_req, &self.config, option).await?;
74        api_resp.into_result()
75    }
76
77    /// 下载图片  
78    pub async fn get(
79        &self,
80        image_key: &str,
81        option: Option<RequestOption>,
82    ) -> SDKResult<GetImageResponse> {
83        let api_req = ApiRequest {
84            http_method: Method::GET,
85            api_path: EndpointBuilder::replace_param(
86                crate::core::endpoints::im::IM_V1_DOWNLOAD_IMAGE,
87                "image_key",
88                image_key,
89            ),
90            supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
91            ..Default::default()
92        };
93
94        let api_resp: BaseResponse<GetImageResponse> =
95            Transport::request(api_req, &self.config, option).await?;
96        api_resp.into_result()
97    }
98
99    /// 创建图片上传Builder (推荐)
100    pub fn upload_builder(&self) -> ImageUploadBuilder {
101        ImageUploadBuilder::new()
102    }
103
104    /// 创建图片下载Builder (推荐)
105    pub fn download_builder(&self) -> ImageDownloadBuilder {
106        ImageDownloadBuilder::new()
107    }
108}
109
110// 接入统一 Service 抽象(IM v1 - ImageService)
111impl_full_service!(ImageService, "im.image", "v1");
112
113/// 图片上传Builder
114#[derive(Default)]
115pub struct ImageUploadBuilder {
116    image_type: Option<String>,
117    image_data: Option<Vec<u8>>,
118}
119
120impl ImageUploadBuilder {
121    pub fn new() -> Self {
122        Self::default()
123    }
124
125    /// 设置图片类型
126    pub fn image_type(mut self, image_type: impl ToString) -> Self {
127        self.image_type = Some(image_type.to_string());
128        self
129    }
130
131    /// 设置图片数据
132    pub fn image_data(mut self, image_data: Vec<u8>) -> Self {
133        self.image_data = Some(image_data);
134        self
135    }
136
137    pub fn build(self) -> (String, Vec<u8>) {
138        (
139            self.image_type.unwrap_or_default(),
140            self.image_data.unwrap_or_default(),
141        )
142    }
143}
144
145#[async_trait]
146impl ExecutableBuilder<ImageService, (String, Vec<u8>), CreateImageResponse>
147    for ImageUploadBuilder
148{
149    fn build(self) -> (String, Vec<u8>) {
150        self.build()
151    }
152
153    async fn execute(self, service: &ImageService) -> SDKResult<CreateImageResponse> {
154        let (image_type, image_data) = self.build();
155        service.create(&image_type, image_data, None).await
156    }
157
158    async fn execute_with_options(
159        self,
160        service: &ImageService,
161        option: RequestOption,
162    ) -> SDKResult<CreateImageResponse> {
163        let (image_type, image_data) = self.build();
164        service.create(&image_type, image_data, Some(option)).await
165    }
166}
167
168/// 图片下载Builder
169#[derive(Default)]
170pub struct ImageDownloadBuilder {
171    image_key: Option<String>,
172}
173
174impl ImageDownloadBuilder {
175    pub fn new() -> Self {
176        Self::default()
177    }
178
179    /// 设置图片key
180    pub fn image_key(mut self, image_key: impl ToString) -> Self {
181        self.image_key = Some(image_key.to_string());
182        self
183    }
184
185    pub fn build(self) -> String {
186        self.image_key.unwrap_or_default()
187    }
188}
189
190#[async_trait]
191impl ExecutableBuilder<ImageService, String, GetImageResponse> for ImageDownloadBuilder {
192    fn build(self) -> String {
193        self.build()
194    }
195
196    async fn execute(self, service: &ImageService) -> SDKResult<GetImageResponse> {
197        let image_key = self.build();
198        service.get(&image_key, None).await
199    }
200
201    async fn execute_with_options(
202        self,
203        service: &ImageService,
204        option: RequestOption,
205    ) -> SDKResult<GetImageResponse> {
206        let image_key = self.build();
207        service.get(&image_key, Some(option)).await
208    }
209}