diff --git a/src/lib.rs b/src/lib.rs index 98deb38..efb0cbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ use sha1::{Digest, Sha1}; use std::path::PathBuf; use tokio::fs::File; use tokio_util::codec::{BytesCodec, FramedRead}; +use upload::resource_type::ResourceTypes; use upload::{result::UploadResult, UploadOptions}; pub struct Cloudinary { @@ -94,19 +95,21 @@ impl Cloudinary { } } - /// uploads an image + /// upload files of type `ResourceTypes` /// ```rust /// use cloudinary::{Source, Cloudinary}; - /// use cloudinary::upload::{UploadOptions}; - /// let options = UploadOptions::new().set_public_id("file.jpg".to_string()); - /// let cloudinary = Cloudinary::new("api_key".to_string(), "cloud_name".to_string(), "api_secret".to_string() ); - /// let result = cloudinary.upload_image(Source::Path("./image.jpg".into()), &options); + /// use cloudinary::upload::{resource_type::ResourceTypes, UploadOptions}; + /// let cloudinary = Cloudinary::new( + /// "api_key".to_string(), + /// "cloud_name".to_string(), + /// "api_secret".to_string() + /// ); + /// let options = UploadOptions::new() + /// .set_public_id("app_data.sql".to_string()) + /// .set_resource_type(ResourceTypes::Raw); + /// let result = cloudinary.upload(Source::Path("./data.sql".into()), &options); /// ``` - pub async fn upload_image( - &self, - src: Source, - options: &UploadOptions<'_>, - ) -> Result { + pub async fn upload(&self, src: Source, options: &UploadOptions<'_>) -> Result { let client = Client::new(); let file = match src { Source::Path(path) => prepare_file(&path).await?, @@ -114,8 +117,12 @@ impl Cloudinary { }; let multipart = self.build_form_data(options).part("file", file); let url = format!( - "https://api.cloudinary.com/v1_1/{}/image/upload", - self.cloud_name + "https://api.cloudinary.com/v1_1/{}/{}/upload", + self.cloud_name, + options + .get_resource_type() + .unwrap_or(ResourceTypes::Image) + .to_string() ); let response = client .post(&url) @@ -128,6 +135,24 @@ impl Cloudinary { Ok(json) } + /// uploads an image + /// ```rust + /// use cloudinary::{Source, Cloudinary}; + /// use cloudinary::upload::{UploadOptions}; + /// let options = UploadOptions::new().set_public_id("file.jpg".to_string()); + /// let cloudinary = Cloudinary::new("api_key".to_string(), "cloud_name".to_string(), "api_secret".to_string() ); + /// let result = cloudinary.upload_image(Source::Path("./image.jpg".into()), &options); + /// ``` + pub async fn upload_image( + &self, + src: Source, + options: &UploadOptions<'_>, + ) -> Result { + let new_opts = options.clone(); + let updated_options = new_opts.set_resource_type(ResourceTypes::Image); + self.upload(src, &updated_options).await + } + fn build_form_data(&self, options: &UploadOptions) -> Form { let mut map = options.get_map(); let resource_type = map.remove("resource_type"); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 18c991c..5df96cd 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -3,18 +3,55 @@ use std::env::var; use crate::{ upload::result::UploadResult::{Error, Success}, - upload::UploadOptions, + upload::{resource_type::ResourceTypes, UploadOptions}, Cloudinary, Source, }; -#[tokio::test] -async fn test_image_upload_from_url() { +struct CloudinaryVariable { + pub api_secret: String, + pub api_key: String, + pub cloud_name: String, +} + +fn load_env() -> CloudinaryVariable { dotenv().ok(); let api_secret = var("CLOUDINARY_API_SECRET").expect("enviroment variables not set"); let api_key = var("CLOUDINARY_API_KEY").expect("enviroment variables not set"); let cloud_name = var("CLOUDINARY_CLOUD_NAME").expect("enviroment variables not set"); + CloudinaryVariable { + api_secret, + api_key, + cloud_name, + } +} + +#[tokio::test] +async fn test_raw_upload() { + let env_vars = load_env(); + let cloudinary = Cloudinary::new(env_vars.api_key, env_vars.cloud_name, env_vars.api_secret); + + let audio_url = "https://commons.wikimedia.org/wiki/File:Panama_National_Anthem.ogg"; + let public_id = "audio_from_url.ogg"; + let options = UploadOptions::new() + .set_resource_type(ResourceTypes::Raw) + .set_public_id(String::from(public_id)) + .set_overwrite(true); + let res = cloudinary + .upload(Source::Url(audio_url.try_into().unwrap()), &options) + .await + .unwrap(); + + match res { + Success(audio) => assert_eq!(audio.public_id, public_id.to_string()), + Error(err) => panic!("{}", err.error.message), + } +} + +#[tokio::test] +async fn test_image_upload_from_url() { + let env_vars = load_env(); + let cloudinary = Cloudinary::new(env_vars.api_key, env_vars.cloud_name, env_vars.api_secret); - let cloudinary = Cloudinary::new(api_key, cloud_name, api_secret); let image_url = "https://upload.wikimedia.org/wikipedia/commons/c/ca/1x1.png"; let public_id = "image_upload_from_url"; @@ -34,12 +71,8 @@ async fn test_image_upload_from_url() { #[tokio::test] async fn test_image_upload_from_path() { - dotenv().ok(); - let api_secret = var("CLOUDINARY_API_SECRET").expect("enviroment variables not set"); - let api_key = var("CLOUDINARY_API_KEY").expect("enviroment variables not set"); - let cloud_name = var("CLOUDINARY_CLOUD_NAME").expect("enviroment variables not set"); - - let cloudinary = Cloudinary::new(api_key, cloud_name, api_secret); + let env_vars = load_env(); + let cloudinary = Cloudinary::new(env_vars.api_key, env_vars.cloud_name, env_vars.api_secret); let image_path = "./assets/1x1.png"; let public_id = "image_upload_from_path"; diff --git a/src/upload/mod.rs b/src/upload/mod.rs index bcc1d50..4ecd8e9 100644 --- a/src/upload/mod.rs +++ b/src/upload/mod.rs @@ -5,7 +5,7 @@ mod categorizations; mod data_types; mod delivery_type; mod raw_convert; -mod resource_type; +pub mod resource_type; mod responsive_breakpoints; pub mod result; @@ -19,7 +19,7 @@ use self::{ responsive_breakpoints::ResponsiveBreakpoints, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct UploadOptions<'entry_key_lifetime> { inner: BTreeMap<&'entry_key_lifetime str, DataType>, } diff --git a/src/upload/result.rs b/src/upload/result.rs index c736953..341692c 100644 --- a/src/upload/result.rs +++ b/src/upload/result.rs @@ -36,9 +36,9 @@ pub struct Response { pub version: usize, pub version_id: String, pub signature: String, - pub width: usize, - pub height: usize, - pub format: String, + pub width: Option, + pub height: Option, + pub format: Option, pub resource_type: String, #[serde(deserialize_with = "deserialize_from_str")] pub created_at: DateTime,