Skip to main content

wekan_cli/client/attachments/
raw_upload.rs

1use super::{
2    AttachmentUploadResponse, BackgroundUploadResponse, POST_TIMEOUT, UploadAttachmentRequest,
3    UploadBackgroundRequest, decode_attachment, require_success,
4};
5use crate::client::{ClientError, WekanClient};
6use reqwest::header::{ACCEPT, CONTENT_TYPE};
7use secrecy::{ExposeSecret, SecretString};
8use serde::de::DeserializeOwned;
9
10impl WekanClient {
11    async fn raw_attachment_upload<T: DeserializeOwned>(
12        &self,
13        operation: &str,
14        query: &[(&str, &str)],
15        bytes: Vec<u8>,
16        token: &SecretString,
17    ) -> Result<T, ClientError> {
18        let mut endpoint = self.attachment_endpoint(&[operation])?;
19        endpoint
20            .query_pairs_mut()
21            .extend_pairs(query.iter().copied());
22        // The raw route selects its transport by Content-Type. File MIME metadata
23        // belongs in fileType so JSON files also use the raw byte transport.
24        let body = self
25            .execute_success_request(
26                self.http
27                    .post(endpoint)
28                    .timeout(POST_TIMEOUT)
29                    .header(ACCEPT, "application/json")
30                    .header(CONTENT_TYPE, "application/octet-stream")
31                    .bearer_auth(token.expose_secret())
32                    .body(bytes),
33            )
34            .await?;
35        decode_attachment(&body)
36    }
37    pub async fn upload_attachment_raw(
38        &self,
39        request: UploadAttachmentRequest,
40        token: &SecretString,
41    ) -> Result<AttachmentUploadResponse, ClientError> {
42        let mut query = vec![
43            ("boardId", request.board_id.as_str()),
44            ("swimlaneId", request.swimlane_id.as_str()),
45            ("listId", request.list_id.as_str()),
46            ("cardId", request.card_id.as_str()),
47            ("fileName", request.file_name.as_str()),
48        ];
49        if let Some(file_type) = &request.file_type {
50            query.push(("fileType", file_type));
51        }
52        let response: AttachmentUploadResponse = self
53            .raw_attachment_upload("upload", &query, request.file_data, token)
54            .await?;
55        require_success(response.success)?;
56        Ok(response)
57    }
58    pub async fn upload_background_raw(
59        &self,
60        request: UploadBackgroundRequest,
61        token: &SecretString,
62    ) -> Result<BackgroundUploadResponse, ClientError> {
63        let query = vec![
64            ("boardId", request.board_id.as_str()),
65            ("fileName", request.file_name.as_str()),
66            (
67                "fileType",
68                request.file_type.as_deref().unwrap_or("image/png"),
69            ),
70        ];
71        let response: BackgroundUploadResponse = self
72            .raw_attachment_upload("upload-background", &query, request.file_data, token)
73            .await?;
74        require_success(response.success)?;
75        Ok(response)
76    }
77}