From 851d9879d380774bce1c7f3095cfecffb05972aa Mon Sep 17 00:00:00 2001 From: jellejurre Date: Mon, 11 Nov 2024 23:50:17 +0100 Subject: [PATCH 1/4] Add multipart content type --- generate.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generate.sh b/generate.sh index d0c6acf..86ccf3d 100755 --- a/generate.sh +++ b/generate.sh @@ -42,6 +42,8 @@ sed -i 's/Result>/Result Date: Tue, 12 Nov 2024 12:54:47 +0100 Subject: [PATCH 2/4] Regenerate with https://github.com/vrchatapi/specification/pull/408 Signed-off-by: C0D3 M4513R <28912031+C0D3-M4513R@users.noreply.github.com> --- .openapi-generator/FILES | 2 + docs/Avatar.md | 1 + docs/AvatarStyles.md | 13 +++ docs/File.md | 2 + docs/FilesApi.md | 96 +++++++++++++++++ docs/GroupsApi.md | 2 +- src/apis/files_api.rs | 199 ++++++++++++++++++++++++++++++++++++ src/apis/groups_api.rs | 2 +- src/models/avatar.rs | 4 + src/models/avatar_styles.rs | 40 ++++++++ src/models/file.rs | 6 ++ src/models/mod.rs | 2 + 12 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 docs/AvatarStyles.md create mode 100644 src/models/avatar_styles.rs diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index bf8ce19..d247a38 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -23,6 +23,7 @@ docs/ApiConfigReportReasons.md docs/ApiHealth.md docs/AuthenticationApi.md docs/Avatar.md +docs/AvatarStyles.md docs/AvatarUnityPackageUrlObject.md docs/AvatarsApi.md docs/Badge.md @@ -220,6 +221,7 @@ src/models/api_config_report_categories.rs src/models/api_config_report_reasons.rs src/models/api_health.rs src/models/avatar.rs +src/models/avatar_styles.rs src/models/avatar_unity_package_url_object.rs src/models/badge.rs src/models/ban_group_member_request.rs diff --git a/docs/Avatar.md b/docs/Avatar.md index efcc27f..5b8600c 100644 --- a/docs/Avatar.md +++ b/docs/Avatar.md @@ -15,6 +15,7 @@ Name | Type | Description | Notes **image_url** | **String** | | **name** | **String** | | **release_status** | [**models::ReleaseStatus**](ReleaseStatus.md) | | +**styles** | [**models::AvatarStyles**](Avatar_styles.md) | | **tags** | **Vec** | | **thumbnail_image_url** | **String** | | **unity_package_url** | **String** | | diff --git a/docs/AvatarStyles.md b/docs/AvatarStyles.md new file mode 100644 index 0000000..089ebfd --- /dev/null +++ b/docs/AvatarStyles.md @@ -0,0 +1,13 @@ +# AvatarStyles + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**primary** | Option<**String**> | | [optional] +**secondary** | Option<**String**> | | [optional] +**supplementary** | Option<**Vec**> | | [optional] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/docs/File.md b/docs/File.md index 0711a2c..fd0dba1 100644 --- a/docs/File.md +++ b/docs/File.md @@ -4,6 +4,8 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +**animation_style** | Option<**String**> | | [optional] +**mask_tag** | Option<**String**> | | [optional] **extension** | **String** | | **id** | **String** | | **mime_type** | [**models::MimeType**](MIMEType.md) | | diff --git a/docs/FilesApi.md b/docs/FilesApi.md index b0761c8..b5d0ffc 100644 --- a/docs/FilesApi.md +++ b/docs/FilesApi.md @@ -14,6 +14,9 @@ Method | HTTP request | Description [**get_file_data_upload_status**](FilesApi.md#get_file_data_upload_status) | **GET** /file/{fileId}/{versionId}/{fileType}/status | Check FileData Upload Status [**get_files**](FilesApi.md#get_files) | **GET** /files | List Files [**start_file_data_upload**](FilesApi.md#start_file_data_upload) | **PUT** /file/{fileId}/{versionId}/{fileType}/start | Start FileData Upload +[**upload_gallery_image**](FilesApi.md#upload_gallery_image) | **POST** /gallery | Upload gallery image +[**upload_icon**](FilesApi.md#upload_icon) | **POST** /icon | Upload icon +[**upload_image**](FilesApi.md#upload_image) | **POST** /file/image | Upload gallery image, icon, emoji or sticker @@ -330,3 +333,96 @@ Name | Type | Description | Required | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +## upload_gallery_image + +> models::File upload_gallery_image(file) +Upload gallery image + +Upload a gallery image + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**file** | **std::path::PathBuf** | The binary blob of the png file. | [required] | + +### Return type + +[**models::File**](File.md) + +### Authorization + +[authCookie](../README.md#authCookie) + +### HTTP request headers + +- **Content-Type**: multipart/form-data +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + +## upload_icon + +> models::File upload_icon(file) +Upload icon + +Upload an icon + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**file** | **std::path::PathBuf** | The binary blob of the png file. | [required] | + +### Return type + +[**models::File**](File.md) + +### Authorization + +[authCookie](../README.md#authCookie) + +### HTTP request headers + +- **Content-Type**: multipart/form-data +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + +## upload_image + +> models::File upload_image(file, tag, animation_style, mask_tag) +Upload gallery image, icon, emoji or sticker + +Upload an image, which can be an icon, gallery image, sticker or emoji + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**file** | **std::path::PathBuf** | The binary blob of the png file. | [required] | +**tag** | **String** | Needs to be either icon, gallery, sticker or emoji | [required] | +**animation_style** | Option<**String**> | Animation style for sticker, required for sticker. | | +**mask_tag** | Option<**String**> | Mask of the sticker, optional for sticker. | | + +### Return type + +[**models::File**](File.md) + +### Authorization + +[authCookie](../README.md#authCookie) + +### HTTP request headers + +- **Content-Type**: multipart/form-data +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/docs/GroupsApi.md b/docs/GroupsApi.md index b4e08e9..d6b225d 100644 --- a/docs/GroupsApi.md +++ b/docs/GroupsApi.md @@ -240,7 +240,7 @@ Name | Type | Description | Required | Notes > models::GroupAnnouncement create_group_announcement(group_id, create_group_announcement_request) Create Group Announcement -Creates an Announcement for a Group. +Creates an Announcement for a Group. Warning: This will also remove all announcements. To make proper announcements, use the posts endpoint instead ### Parameters diff --git a/src/apis/files_api.rs b/src/apis/files_api.rs index 7648f3d..8574ae4 100644 --- a/src/apis/files_api.rs +++ b/src/apis/files_api.rs @@ -87,6 +87,27 @@ pub enum StartFileDataUploadError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`upload_gallery_image`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UploadGalleryImageError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`upload_icon`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UploadIconError { + UnknownValue(serde_json::Value), +} + +/// struct for typed errors of method [`upload_image`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UploadImageError { + UnknownValue(serde_json::Value), +} + /// Creates a new File object pub async fn create_file( configuration: &configuration::Configuration, @@ -545,3 +566,181 @@ pub async fn start_file_data_upload( Err(Error::ResponseError(local_var_error)) } } + +/// Upload a gallery image +pub async fn upload_gallery_image( + configuration: &configuration::Configuration, + file: std::path::PathBuf, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/gallery", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + let mut local_var_form = reqwest::multipart::Form::new(); + let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) + .file_name(file.file_name().unwrap().to_string_lossy().to_string()) + .mime_str( + if file + .file_name() + .unwrap() + .to_string_lossy() + .to_string() + .ends_with("png") + { + "image/png" + } else { + "application/octet-stream" + }, + )?; + local_var_form = local_var_form.part("file", part); + local_var_req_builder = local_var_req_builder.multipart(local_var_form); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +/// Upload an icon +pub async fn upload_icon( + configuration: &configuration::Configuration, + file: std::path::PathBuf, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/icon", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + let mut local_var_form = reqwest::multipart::Form::new(); + let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) + .file_name(file.file_name().unwrap().to_string_lossy().to_string()) + .mime_str( + if file + .file_name() + .unwrap() + .to_string_lossy() + .to_string() + .ends_with("png") + { + "image/png" + } else { + "application/octet-stream" + }, + )?; + local_var_form = local_var_form.part("file", part); + local_var_req_builder = local_var_req_builder.multipart(local_var_form); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + +/// Upload an image, which can be an icon, gallery image, sticker or emoji +pub async fn upload_image( + configuration: &configuration::Configuration, + file: std::path::PathBuf, + tag: &str, + animation_style: Option<&str>, + mask_tag: Option<&str>, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!("{}/file/image", local_var_configuration.base_path); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::POST, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + let mut local_var_form = reqwest::multipart::Form::new(); + let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) + .file_name(file.file_name().unwrap().to_string_lossy().to_string()) + .mime_str( + if file + .file_name() + .unwrap() + .to_string_lossy() + .to_string() + .ends_with("png") + { + "image/png" + } else { + "application/octet-stream" + }, + )?; + local_var_form = local_var_form.part("file", part); + local_var_form = local_var_form.text("tag", tag.to_string()); + if let Some(local_var_param_value) = animation_style { + local_var_form = local_var_form.text("animationStyle", local_var_param_value.to_string()); + } + if let Some(local_var_param_value) = mask_tag { + local_var_form = local_var_form.text("maskTag", local_var_param_value.to_string()); + } + local_var_req_builder = local_var_req_builder.multipart(local_var_form); + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} diff --git a/src/apis/groups_api.rs b/src/apis/groups_api.rs index 312a40a..c7725ac 100644 --- a/src/apis/groups_api.rs +++ b/src/apis/groups_api.rs @@ -658,7 +658,7 @@ pub async fn create_group( } } -/// Creates an Announcement for a Group. +/// Creates an Announcement for a Group. Warning: This will also remove all announcements. To make proper announcements, use the posts endpoint instead pub async fn create_group_announcement( configuration: &configuration::Configuration, group_id: &str, diff --git a/src/models/avatar.rs b/src/models/avatar.rs index c8e4a8d..d1fa3a6 100644 --- a/src/models/avatar.rs +++ b/src/models/avatar.rs @@ -37,6 +37,8 @@ pub struct Avatar { pub name: String, #[serde(rename = "releaseStatus")] pub release_status: models::ReleaseStatus, + #[serde(rename = "styles")] + pub styles: models::AvatarStyles, #[serde(rename = "tags")] pub tags: Vec, #[serde(rename = "thumbnailImageUrl")] @@ -64,6 +66,7 @@ impl Avatar { image_url: String, name: String, release_status: models::ReleaseStatus, + styles: models::AvatarStyles, tags: Vec, thumbnail_image_url: String, unity_package_url: String, @@ -84,6 +87,7 @@ impl Avatar { image_url, name, release_status, + styles, tags, thumbnail_image_url, unity_package_url, diff --git a/src/models/avatar_styles.rs b/src/models/avatar_styles.rs new file mode 100644 index 0000000..464a437 --- /dev/null +++ b/src/models/avatar_styles.rs @@ -0,0 +1,40 @@ +/* + * VRChat API Documentation + * + * + * Contact: vrchatapi.lpv0t@aries.fyi + * Generated by: https://openapi-generator.tech + */ + +use crate::models; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct AvatarStyles { + #[serde( + rename = "primary", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub primary: Option>, + #[serde( + rename = "secondary", + default, + with = "::serde_with::rust::double_option", + skip_serializing_if = "Option::is_none" + )] + pub secondary: Option>, + #[serde(rename = "supplementary", skip_serializing_if = "Option::is_none")] + pub supplementary: Option>, +} + +impl AvatarStyles { + pub fn new() -> AvatarStyles { + AvatarStyles { + primary: None, + secondary: None, + supplementary: None, + } + } +} diff --git a/src/models/file.rs b/src/models/file.rs index f34119f..6dd4da9 100644 --- a/src/models/file.rs +++ b/src/models/file.rs @@ -12,6 +12,10 @@ use serde::{Deserialize, Serialize}; /// File : #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] pub struct File { + #[serde(rename = "animationStyle", skip_serializing_if = "Option::is_none")] + pub animation_style: Option, + #[serde(rename = "maskTag", skip_serializing_if = "Option::is_none")] + pub mask_tag: Option, #[serde(rename = "extension")] pub extension: String, #[serde(rename = "id")] @@ -40,6 +44,8 @@ impl File { versions: Vec, ) -> File { File { + animation_style: None, + mask_tag: None, extension, id, mime_type, diff --git a/src/models/mod.rs b/src/models/mod.rs index c1e7f4d..17c3d42 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -42,6 +42,8 @@ pub mod api_health; pub use self::api_health::ApiHealth; pub mod avatar; pub use self::avatar::Avatar; +pub mod avatar_styles; +pub use self::avatar_styles::AvatarStyles; pub mod avatar_unity_package_url_object; pub use self::avatar_unity_package_url_object::AvatarUnityPackageUrlObject; pub mod badge; From fa7b449cb280b5725d4d66816102788f6e31dffd Mon Sep 17 00:00:00 2001 From: C0D3 M4513R <28912031+C0D3-M4513R@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:39:27 +0100 Subject: [PATCH 3/4] Use async file io and don't `unwrap` --- Cargo.toml | 1 + generate.sh | 10 ++++- src/apis/files_api.rs | 90 +++++++++++++++++++++---------------------- src/apis/mod.rs | 3 ++ 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0d5be42..c4922f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT" edition = "2021" [dependencies] +async-std = "1" serde = { version = "^1.0", features = ["derive"] } serde_with = { version = "^3.8", default-features = false, features = ["base64", "std", "macros"] } serde_json = "^1.0" diff --git a/generate.sh b/generate.sh index 86ccf3d..db31f51 100755 --- a/generate.sh +++ b/generate.sh @@ -42,7 +42,15 @@ sed -i 's/Result>/Result\s\+{/\0\nAsyncStdIo(::async_std::io::Error),/" src/apis/mod.rs +sed -E -i 's/Error::Reqwest\(e\)\s+=>\s+\("reqwest", e\.to_string\(\)\),/Error::AsyncStdIo(e) => ("async_std", e.to_string()),\0/' src/apis/mod.rs #Fix Debug +sed -E -i 's/Error::Reqwest\(e\)\s+=>\s+\e,/Error::AsyncStdIo(e) => e,\n\0/' src/apis/mod.rs #Fix Error +sed -i "s/impl From for Error/impl From<::async_std::io::Error> for Error {\nfn from(val: ::async_std::io::Error) -> Self {\n Error::AsyncStdIo(val)\n}\n\}\n\0/" src/apis/mod.rs #Add From impl +#Use the async file io +sed -i 's|// TODO: support file upload for '\''file'\'' parameter|let part = {let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(\&file).await?);\nif let Some(filename) = file.file_name() { \npart = part.file_name(filename.to_string_lossy().to_string()).mime_str(if filename.to_string_lossy().ends_with("png") { "image/png" } else { "application/octet-stream" })?;} \n else { part = part.mime_str("application/octet-stream")?; }\n part };\n\tlocal_var_form = local_var_form.part("file", part);|' src/apis/files_api.rs cargo fmt cargo build diff --git a/src/apis/files_api.rs b/src/apis/files_api.rs index 8574ae4..704a7a0 100644 --- a/src/apis/files_api.rs +++ b/src/apis/files_api.rs @@ -585,21 +585,21 @@ pub async fn upload_gallery_image( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) - .file_name(file.file_name().unwrap().to_string_lossy().to_string()) - .mime_str( - if file - .file_name() - .unwrap() - .to_string_lossy() - .to_string() - .ends_with("png") - { - "image/png" - } else { - "application/octet-stream" - }, - )?; + let part = { + let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); + if let Some(filename) = file.file_name() { + part = part + .file_name(filename.to_string_lossy().to_string()) + .mime_str(if filename.to_string_lossy().ends_with("png") { + "image/png" + } else { + "application/octet-stream" + })?; + } else { + part = part.mime_str("application/octet-stream")?; + } + part + }; local_var_form = local_var_form.part("file", part); local_var_req_builder = local_var_req_builder.multipart(local_var_form); @@ -641,21 +641,21 @@ pub async fn upload_icon( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) - .file_name(file.file_name().unwrap().to_string_lossy().to_string()) - .mime_str( - if file - .file_name() - .unwrap() - .to_string_lossy() - .to_string() - .ends_with("png") - { - "image/png" - } else { - "application/octet-stream" - }, - )?; + let part = { + let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); + if let Some(filename) = file.file_name() { + part = part + .file_name(filename.to_string_lossy().to_string()) + .mime_str(if filename.to_string_lossy().ends_with("png") { + "image/png" + } else { + "application/octet-stream" + })?; + } else { + part = part.mime_str("application/octet-stream")?; + } + part + }; local_var_form = local_var_form.part("file", part); local_var_req_builder = local_var_req_builder.multipart(local_var_form); @@ -700,21 +700,21 @@ pub async fn upload_image( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = reqwest::multipart::Part::bytes(std::fs::read(&file).unwrap()) - .file_name(file.file_name().unwrap().to_string_lossy().to_string()) - .mime_str( - if file - .file_name() - .unwrap() - .to_string_lossy() - .to_string() - .ends_with("png") - { - "image/png" - } else { - "application/octet-stream" - }, - )?; + let part = { + let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); + if let Some(filename) = file.file_name() { + part = part + .file_name(filename.to_string_lossy().to_string()) + .mime_str(if filename.to_string_lossy().ends_with("png") { + "image/png" + } else { + "application/octet-stream" + })?; + } else { + part = part.mime_str("application/octet-stream")?; + } + part + }; local_var_form = local_var_form.part("file", part); local_var_form = local_var_form.text("tag", tag.to_string()); if let Some(local_var_param_value) = animation_style { diff --git a/src/apis/mod.rs b/src/apis/mod.rs index b87bc7d..4e32afe 100644 --- a/src/apis/mod.rs +++ b/src/apis/mod.rs @@ -10,6 +10,7 @@ pub struct ResponseContent { #[derive(Debug)] pub enum Error { + AsyncStdIo(::async_std::io::Error), Reqwest(reqwest::Error), Serde(serde_json::Error), Io(std::io::Error), @@ -19,6 +20,7 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (module, e) = match self { + Error::AsyncStdIo(e) => ("async_std", e.to_string()), Error::Reqwest(e) => ("reqwest", e.to_string()), Error::Serde(e) => ("serde", e.to_string()), Error::Io(e) => ("IO", e.to_string()), @@ -31,6 +33,7 @@ impl fmt::Display for Error { impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(match self { + Error::AsyncStdIo(e) => e, Error::Reqwest(e) => e, Error::Serde(e) => e, Error::Io(e) => e, From e918baacc78c868ab0f9a790a8b62c24566d9275 Mon Sep 17 00:00:00 2001 From: C0D3 M4513R <28912031+C0D3-M4513R@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:18:53 +0100 Subject: [PATCH 4/4] Don't use file-io for multipart uploads/image endpoints --- Cargo.toml | 1 - generate.sh | 9 +----- src/apis/files_api.rs | 66 ++++++++++++------------------------------- src/apis/mod.rs | 3 -- 4 files changed, 19 insertions(+), 60 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c4922f6..0d5be42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ license = "MIT" edition = "2021" [dependencies] -async-std = "1" serde = { version = "^1.0", features = ["derive"] } serde_with = { version = "^3.8", default-features = false, features = ["base64", "std", "macros"] } serde_json = "^1.0" diff --git a/generate.sh b/generate.sh index db31f51..70f02d3 100755 --- a/generate.sh +++ b/generate.sh @@ -43,14 +43,7 @@ sed -i 's/Result>/Result\s\+{/\0\nAsyncStdIo(::async_std::io::Error),/" src/apis/mod.rs -sed -E -i 's/Error::Reqwest\(e\)\s+=>\s+\("reqwest", e\.to_string\(\)\),/Error::AsyncStdIo(e) => ("async_std", e.to_string()),\0/' src/apis/mod.rs #Fix Debug -sed -E -i 's/Error::Reqwest\(e\)\s+=>\s+\e,/Error::AsyncStdIo(e) => e,\n\0/' src/apis/mod.rs #Fix Error -sed -i "s/impl From for Error/impl From<::async_std::io::Error> for Error {\nfn from(val: ::async_std::io::Error) -> Self {\n Error::AsyncStdIo(val)\n}\n\}\n\0/" src/apis/mod.rs #Add From impl -#Use the async file io -sed -i 's|// TODO: support file upload for '\''file'\'' parameter|let part = {let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(\&file).await?);\nif let Some(filename) = file.file_name() { \npart = part.file_name(filename.to_string_lossy().to_string()).mime_str(if filename.to_string_lossy().ends_with("png") { "image/png" } else { "application/octet-stream" })?;} \n else { part = part.mime_str("application/octet-stream")?; }\n part };\n\tlocal_var_form = local_var_form.part("file", part);|' src/apis/files_api.rs +perl -0pi -e 's|(fn\s+[^(]*\([^)]*)file:\s+:?:?std::path::PathBuf,?([^)]*)((?:(?!\/\/ TODO: support file upload for '\''file'\'' parameter)[\s\S])*)\/\/ TODO: support file upload for '\''file'\'' parameter|\1file: impl Into<::std::borrow::Cow<'\''static, [u8]>>,\n\tfilename: impl Into<::std::borrow::Cow<'\''static, str>>,\n\tmime_type: &str,\2\3let part = reqwest::multipart::Part::bytes(file).file_name(filename).mime_str(mime_type)?;\n\tlocal_var_form = local_var_form.part("file", part);|g' src/apis/files_api.rs cargo fmt cargo build diff --git a/src/apis/files_api.rs b/src/apis/files_api.rs index 704a7a0..1716b29 100644 --- a/src/apis/files_api.rs +++ b/src/apis/files_api.rs @@ -570,7 +570,9 @@ pub async fn start_file_data_upload( /// Upload a gallery image pub async fn upload_gallery_image( configuration: &configuration::Configuration, - file: std::path::PathBuf, + file: impl Into<::std::borrow::Cow<'static, [u8]>>, + filename: impl Into<::std::borrow::Cow<'static, str>>, + mime_type: &str, ) -> Result> { let local_var_configuration = configuration; @@ -585,21 +587,9 @@ pub async fn upload_gallery_image( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = { - let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); - if let Some(filename) = file.file_name() { - part = part - .file_name(filename.to_string_lossy().to_string()) - .mime_str(if filename.to_string_lossy().ends_with("png") { - "image/png" - } else { - "application/octet-stream" - })?; - } else { - part = part.mime_str("application/octet-stream")?; - } - part - }; + let part = reqwest::multipart::Part::bytes(file) + .file_name(filename) + .mime_str(mime_type)?; local_var_form = local_var_form.part("file", part); local_var_req_builder = local_var_req_builder.multipart(local_var_form); @@ -626,7 +616,9 @@ pub async fn upload_gallery_image( /// Upload an icon pub async fn upload_icon( configuration: &configuration::Configuration, - file: std::path::PathBuf, + file: impl Into<::std::borrow::Cow<'static, [u8]>>, + filename: impl Into<::std::borrow::Cow<'static, str>>, + mime_type: &str, ) -> Result> { let local_var_configuration = configuration; @@ -641,21 +633,9 @@ pub async fn upload_icon( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = { - let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); - if let Some(filename) = file.file_name() { - part = part - .file_name(filename.to_string_lossy().to_string()) - .mime_str(if filename.to_string_lossy().ends_with("png") { - "image/png" - } else { - "application/octet-stream" - })?; - } else { - part = part.mime_str("application/octet-stream")?; - } - part - }; + let part = reqwest::multipart::Part::bytes(file) + .file_name(filename) + .mime_str(mime_type)?; local_var_form = local_var_form.part("file", part); local_var_req_builder = local_var_req_builder.multipart(local_var_form); @@ -682,7 +662,9 @@ pub async fn upload_icon( /// Upload an image, which can be an icon, gallery image, sticker or emoji pub async fn upload_image( configuration: &configuration::Configuration, - file: std::path::PathBuf, + file: impl Into<::std::borrow::Cow<'static, [u8]>>, + filename: impl Into<::std::borrow::Cow<'static, str>>, + mime_type: &str, tag: &str, animation_style: Option<&str>, mask_tag: Option<&str>, @@ -700,21 +682,9 @@ pub async fn upload_image( local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); } let mut local_var_form = reqwest::multipart::Form::new(); - let part = { - let mut part = reqwest::multipart::Part::bytes(::async_std::fs::read(&file).await?); - if let Some(filename) = file.file_name() { - part = part - .file_name(filename.to_string_lossy().to_string()) - .mime_str(if filename.to_string_lossy().ends_with("png") { - "image/png" - } else { - "application/octet-stream" - })?; - } else { - part = part.mime_str("application/octet-stream")?; - } - part - }; + let part = reqwest::multipart::Part::bytes(file) + .file_name(filename) + .mime_str(mime_type)?; local_var_form = local_var_form.part("file", part); local_var_form = local_var_form.text("tag", tag.to_string()); if let Some(local_var_param_value) = animation_style { diff --git a/src/apis/mod.rs b/src/apis/mod.rs index 4e32afe..b87bc7d 100644 --- a/src/apis/mod.rs +++ b/src/apis/mod.rs @@ -10,7 +10,6 @@ pub struct ResponseContent { #[derive(Debug)] pub enum Error { - AsyncStdIo(::async_std::io::Error), Reqwest(reqwest::Error), Serde(serde_json::Error), Io(std::io::Error), @@ -20,7 +19,6 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (module, e) = match self { - Error::AsyncStdIo(e) => ("async_std", e.to_string()), Error::Reqwest(e) => ("reqwest", e.to_string()), Error::Serde(e) => ("serde", e.to_string()), Error::Io(e) => ("IO", e.to_string()), @@ -33,7 +31,6 @@ impl fmt::Display for Error { impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(match self { - Error::AsyncStdIo(e) => e, Error::Reqwest(e) => e, Error::Serde(e) => e, Error::Io(e) => e,