Skip to content

Commit

Permalink
Merge pull request #38 from Lurk/new-upload-result-type
Browse files Browse the repository at this point in the history
ResponseWithImageMetadata
  • Loading branch information
Lurk authored Oct 9, 2024
2 parents 39f3a86 + 9ddcbf8 commit 0d3745f
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 11 deletions.
23 changes: 19 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,19 @@ jobs:
CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
CLOUDINARY_API_KEY: ${{ secrets.CLOUDINARY_API_KEY }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_API_SECRET_1: ${{ secrets.CLOUDINARY_API_SECRET_1 }}
CLOUDINARY_API_KEY_1: ${{ secrets.CLOUDINARY_API_KEY_1 }}
CLOUDINARY_CLOUD_NAME_1: ${{ secrets.CLOUDINARY_CLOUD_NAME_1 }}
run: cargo test --locked --all-features --all-targets
# https://github.com/rust-lang/cargo/issues/6669
- name: cargo test --doc
env:
CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
CLOUDINARY_API_KEY: ${{ secrets.CLOUDINARY_API_KEY }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_API_SECRET_1: ${{ secrets.CLOUDINARY_API_SECRET_1 }}
CLOUDINARY_API_KEY_1: ${{ secrets.CLOUDINARY_API_KEY_1 }}
CLOUDINARY_CLOUD_NAME_1: ${{ secrets.CLOUDINARY_CLOUD_NAME_1 }}
run: cargo test --locked --all-features --doc
minimal:
runs-on: ubuntu-latest
Expand All @@ -60,7 +66,10 @@ jobs:
env:
CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
CLOUDINARY_API_KEY: ${{ secrets.CLOUDINARY_API_KEY }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_API_SECRET_1: ${{ secrets.CLOUDINARY_API_SECRET_1 }}
CLOUDINARY_API_KEY_1: ${{ secrets.CLOUDINARY_API_KEY_1 }}
CLOUDINARY_CLOUD_NAME_1: ${{ secrets.CLOUDINARY_CLOUD_NAME_1 }}
run: cargo test --locked --all-features --all-targets
os-check:
runs-on: ${{ matrix.os }}
Expand All @@ -82,7 +91,10 @@ jobs:
env:
CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
CLOUDINARY_API_KEY: ${{ secrets.CLOUDINARY_API_KEY }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_API_SECRET_1: ${{ secrets.CLOUDINARY_API_SECRET_1 }}
CLOUDINARY_API_KEY_1: ${{ secrets.CLOUDINARY_API_KEY_1 }}
CLOUDINARY_CLOUD_NAME_1: ${{ secrets.CLOUDINARY_CLOUD_NAME_1 }}
run: cargo test --locked --all-features --all-targets
coverage:
runs-on: ubuntu-latest
Expand All @@ -104,7 +116,10 @@ jobs:
env:
CLOUDINARY_API_SECRET: ${{ secrets.CLOUDINARY_API_SECRET }}
CLOUDINARY_API_KEY: ${{ secrets.CLOUDINARY_API_KEY }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_CLOUD_NAME: ${{ secrets.CLOUDINARY_CLOUD_NAME }}
CLOUDINARY_API_SECRET_1: ${{ secrets.CLOUDINARY_API_SECRET_1 }}
CLOUDINARY_API_KEY_1: ${{ secrets.CLOUDINARY_API_KEY_1 }}
CLOUDINARY_CLOUD_NAME_1: ${{ secrets.CLOUDINARY_CLOUD_NAME_1 }}
run: cargo llvm-cov --locked --all-features --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v4
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "cloudinary"
description = "A Rust library for the Cloudinary API"
license = "MIT OR Apache-2.0"
keywords = ["cloudinary", "api", "image", "video", "upload"]
version = "0.5.2"
version = "0.6.0"
edition = "2021"
rust-version = "1.65.0" # due to let-else

Expand Down
16 changes: 16 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ let tags = get_tags("cloud_name".into(), "tag_name".into()).await;

```


## Development

Due to differences in default upload result shape in different accounts, two sets
of credentials must be present in `.env` for tests to succeed.

```sh
CLOUDINARY_API_SECRET=***
CLOUDINARY_API_KEY=***
CLOUDINARY_CLOUD_NAME=***

CLOUDINARY_API_SECRET_1=***
CLOUDINARY_API_KEY_1=***
CLOUDINARY_CLOUD_NAME_1=***
```

## Minimum supported Rust version

The minimum supported Rust version for this crate is 1.65
Expand Down
16 changes: 16 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@
//!
//! ```
//!
//!
//! # Development
//!
//! Due to differences in default upload result shape in different accounts, two sets
//! of credentials must be present in `.env` for tests to succeed.
//!
//! ```sh
//! CLOUDINARY_API_SECRET=***
//! CLOUDINARY_API_KEY=***
//! CLOUDINARY_CLOUD_NAME=***
//!
//! CLOUDINARY_API_SECRET_1=***
//! CLOUDINARY_API_KEY_1=***
//! CLOUDINARY_CLOUD_NAME_1=***
//!```
//!
//! # Minimum supported Rust version
//!
//! The minimum supported Rust version for this crate is 1.65
Expand Down
49 changes: 44 additions & 5 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::env::var;
use crate::{
upload::UploadOptions,
upload::{
result::UploadResult::{Error, Success},
result::UploadResult::{Error, Response, ResponseWithImageMetadata},
Source, Upload,
},
};
Expand Down Expand Up @@ -35,8 +35,11 @@ async fn test_image_upload_from_base64() {
.unwrap();

match res {
Success(img) => assert_eq!(img.public_id, public_id),
Response(img) => assert_eq!(img.public_id, public_id),
Error(err) => panic!("{}", err.error.message),
_ => {
panic!("Since old account was used, only Response or Error variant is expected")
}
}
}

Expand All @@ -56,8 +59,11 @@ async fn test_image_upload_from_url() {
.unwrap();

match res {
Success(img) => assert_eq!(img.public_id, public_id),
Response(img) => assert_eq!(img.public_id, public_id),
Error(err) => panic!("{}", err.error.message),
_ => {
panic!("Since old account was used, only Response or Error variant is expected")
}
}
}

Expand All @@ -77,8 +83,11 @@ async fn test_image_upload_from_path() {
.unwrap();

match res {
Success(img) => assert_eq!(img.public_id, public_id),
Response(img) => assert_eq!(img.public_id, public_id),
Error(err) => panic!("{}", err.error.message),
_ => {
panic!("Since old account was used, only Response or Error variant is expected")
}
}
}

Expand Down Expand Up @@ -109,10 +118,40 @@ async fn test_destroy_existing_asset() {
.unwrap();

match res {
Success(_) => {
Response(_) => {
let res = cloudinary.destroy(public_id).await.unwrap();
assert_eq!(res.result, "ok")
}
Error(err) => panic!("{}", err.error.message),
_ => {
panic!("Since old account was used, only Response or Error variant is expected")
}
}
}

#[tokio::test]
async fn test_image_upload_from_new_acc() {
dotenv().ok();
let api_key = var("CLOUDINARY_API_KEY_1").expect("environment variables not set");
let cloud_name = var("CLOUDINARY_CLOUD_NAME_1").expect("environment variables not set");
let api_secret = var("CLOUDINARY_API_SECRET_1").expect("environment variables not set");

let cloudinary = Upload::new(api_key, cloud_name, api_secret);
let image_base64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
let public_id = "image_upload_from_base64";

let options = UploadOptions::new()
.set_image_metadata(true)
.set_public_id(public_id.into())
.set_overwrite(true);
let res = cloudinary
.image(Source::DataUrl(image_base64.into()), &options)
.await
.unwrap();

match res {
Error(err) => panic!("{}", err.error.message),
ResponseWithImageMetadata(img) => assert_eq!(img.public_id, public_id),
_ => panic!("Since new account was used, only ResponseWithImageMetadata or Error variant is expected"),
}
}
51 changes: 50 additions & 1 deletion src/upload/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ pub struct Message {
#[derive(Clone, Deserialize, Debug)]
#[serde(untagged)]
pub enum UploadResult {
Success(Box<Response>),
Response(Box<Response>),
/// New* accounts get response in this format by default
/// * unfortunately I was not able to find out what exactly "new" means
ResponseWithImageMetadata(Box<ResponseWithImageMetadata>),
Error(Box<Error>),
}

Expand Down Expand Up @@ -56,6 +59,52 @@ pub struct Response {
pub api_key: String,
}

#[derive(Clone, Deserialize, Debug)]
pub struct ImageMetadata {
#[serde(rename(serialize = "JFIFVersion", deserialize = "JFIFVersion"))]
pub jfif_version: Option<String>,
#[serde(rename(serialize = "ResolutionUnit", deserialize = "ResolutionUnit"))]
pub resolution_unit: Option<String>,
#[serde(rename(serialize = "XResolution", deserialize = "XResolution"))]
pub x_resolution: Option<String>,
#[serde(rename(serialize = "YResolution", deserialize = "YResolution"))]
pub y_resolution: Option<String>,
#[serde(rename(serialize = "Colorspace", deserialize = "Colorspace"))]
pub colorspace: Option<String>,
#[serde(rename(serialize = "DPI", deserialize = "DPI"))]
pub dpi: Option<String>,
}

/// https://cloudinary.com/documentation/image_upload_api_reference#upload_response
#[derive(Clone, Deserialize, Debug)]
pub struct ResponseWithImageMetadata {
pub asset_id: String,
pub public_id: String,
pub version: usize,
pub version_id: String,
pub signature: String,
pub width: usize,
pub height: usize,
pub format: String,
pub resource_type: String,
#[serde(deserialize_with = "deserialize_from_str")]
pub created_at: DateTime<Utc>,
pub tags: Vec<String>,
pub bytes: usize,
pub r#type: String,
pub etag: String,
pub placeholder: bool,
pub url: String,
pub secure_url: String,
pub asset_folder: String,
pub display_name: String,
pub image_metadata: ImageMetadata,
pub illustration_score: f64,
pub semi_transparent: bool,
pub grayscale: bool,
pub api_key: String,
}

#[derive(Clone, Deserialize, Debug)]
pub struct DestroyResult {
pub result: String,
Expand Down

0 comments on commit 0d3745f

Please sign in to comment.