gyazo_api/
upload.rs

1use super::access_policy::AccessPolicy;
2use super::Gyazo;
3use reqwest::multipart;
4use std::fs;
5use std::path::Path;
6
7/// Gyazo API upload response structure.
8#[derive(serde::Deserialize, Debug)]
9pub struct UploadResponse {
10    /// Timestamp when the image was created.
11    pub created_at: String,
12    /// Unique identifier of the uploaded image.
13    pub image_id: String,
14    /// Permalink URL of the image.
15    pub permalink_url: String,
16    /// URL of the thumbnail.
17    pub thumb_url: String,
18    /// Type of the response.
19    pub r#type: String,
20    /// Direct URL to the uploaded image.
21    pub url: String,
22}
23
24/// Options for uploading images to Gyazo.
25///
26/// This struct contains optional parameters for configuring image uploads to the Gyazo API.
27/// Fields correspond to the API's query parameters, and all fields are optional.
28#[derive(Default)]
29pub struct GyazoUploadOptions {
30    /// Specifies the visibility of the uploaded image.
31    /// - `anyone`: The image is visible to anyone with the link. (default)
32    /// - `only_me`: The image is visible only to the uploader.
33    pub access_policy: Option<AccessPolicy>,
34
35    /// Specifies whether metadata like URL and title is public.
36    /// - `"true"`: Metadata is public.
37    /// - `"false"`: Metadata is private.
38    pub metadata_is_public: Option<bool>,
39
40    /// The URL of the website captured in the image.
41    pub referer_url: Option<String>,
42
43    /// The name of the application used to capture the image.
44    pub app: Option<String>,
45
46    /// The title of the website captured in the image.
47    pub title: Option<String>,
48
49    /// A comment or description for the uploaded image.
50    pub desc: Option<String>,
51
52    /// The creation date and time of the image, in Unix time (seconds since the epoch).
53    pub created_at: Option<f64>,
54
55    /// The ID of the collection to which the image should be added.
56    /// The collection must be owned by or shared with the uploader.
57    pub collection_id: Option<String>,
58}
59
60impl Gyazo {
61    /// Uploads an image to Gyazo.
62    ///
63    /// # Arguments
64    ///
65    /// * `image_path` - Path to the image file to upload.
66    /// * `options` - Optional upload configuration.
67    ///
68    /// # Returns
69    ///
70    /// A `Result` containing `UploadResponse` on success or a `reqwest::Error` on failure.
71    // TODO: test
72    pub async fn upload<P: AsRef<Path>>(
73        &self,
74        image_path: P,
75        options: Option<&GyazoUploadOptions>,
76    ) -> Result<UploadResponse, reqwest::Error> {
77        let file_content = fs::read(&image_path).expect("Failed to read the file");
78
79        let mut form = multipart::Form::new()
80            .text("access_token", self.access_token.clone())
81            .part(
82                "imagedata",
83                multipart::Part::bytes(file_content)
84                    .file_name(image_path.as_ref().to_str().unwrap().to_string()),
85            );
86
87        if let Some(opts) = options {
88            if let Some(access_policy) = &opts.access_policy {
89                form = form.text("access_policy", access_policy.as_str().to_string());
90            }
91            if let Some(metadata_is_public) = &opts.metadata_is_public {
92                form = form.text("metadata_is_public", metadata_is_public.to_string());
93            }
94            if let Some(referer_url) = &opts.referer_url {
95                form = form.text("referer_url", referer_url.clone());
96            }
97            if let Some(app) = &opts.app {
98                form = form.text("app", app.clone());
99            }
100            if let Some(title) = &opts.title {
101                form = form.text("title", title.clone());
102            }
103            if let Some(desc) = &opts.desc {
104                form = form.text("desc", desc.clone());
105            }
106            if let Some(created_at) = opts.created_at {
107                form = form.text("created_at", created_at.to_string());
108            }
109            if let Some(collection_id) = &opts.collection_id {
110                form = form.text("collection_id", collection_id.clone());
111            }
112        }
113
114        let response = self
115            .client
116            .post("https://upload.gyazo.com/api/upload")
117            .multipart(form)
118            .send()
119            .await?
120            .error_for_status()?
121            .json::<UploadResponse>()
122            .await?;
123
124        Ok(response)
125    }
126}