From 183ee40b65b9348901ea4c5432268aeac7ba26bc Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 16 Mar 2026 21:41:04 -0400 Subject: [PATCH] refactor --- Cargo.lock | 1 + .../artcraft/artcraft_router/Cargo.toml | 1 + .../execute_seedance2pro_seedance2p0.rs | 59 ++++--------------- .../artcraft/artcraft_router/src/lib.rs | 1 + .../src/utils/download_file.rs | 19 ++++++ .../artcraft/artcraft_router/src/utils/mod.rs | 1 + .../extension/extract_extension_from_url.rs | 13 ++++ 7 files changed, 47 insertions(+), 48 deletions(-) create mode 100644 crates/api_clients/artcraft/artcraft_router/src/utils/download_file.rs create mode 100644 crates/api_clients/artcraft/artcraft_router/src/utils/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 7ade5a9a2a..a861579b9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -797,6 +797,7 @@ dependencies = [ "test_data", "tokens", "tokio", + "url_utils", "uuid 1.18.1", "workspace-build-acceleration", "world_labs_api", diff --git a/crates/api_clients/artcraft/artcraft_router/Cargo.toml b/crates/api_clients/artcraft/artcraft_router/Cargo.toml index cc509549b2..67ddad74c5 100644 --- a/crates/api_clients/artcraft/artcraft_router/Cargo.toml +++ b/crates/api_clients/artcraft/artcraft_router/Cargo.toml @@ -22,6 +22,7 @@ fal_client.workspace = true muapi_client.workspace = true seedance2pro.workspace = true tokens.workspace = true +url_utils.workspace = true world_labs_api.workspace = true # External diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/seedance2pro/execute_seedance2pro_seedance2p0.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/seedance2pro/execute_seedance2pro_seedance2p0.rs index cd7778c763..8f73777c25 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/seedance2pro/execute_seedance2pro_seedance2p0.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/seedance2pro/execute_seedance2pro_seedance2p0.rs @@ -5,14 +5,18 @@ use crate::generate::generate_video::generate_video_response::{ GenerateVideoResponse, Seedance2proVideoResponsePayload, }; use crate::generate::generate_video::plan::seedance2pro::plan_generate_video_seedance2pro_seedance2p0::PlanSeedance2proSeedance2p0; +use crate::utils::download_file::download_file; use seedance2pro::requests::generate_video::generate_video::{ - GenerateVideoArgs, generate_video, + generate_video, GenerateVideoArgs, }; use seedance2pro::requests::prepare_file_upload::prepare_file_upload::{ - PrepareFileUploadArgs, prepare_file_upload, + prepare_file_upload, PrepareFileUploadArgs, }; use seedance2pro::requests::upload_file::upload_file::{ - UploadFileArgs, upload_file, + upload_file, UploadFileArgs, +}; +use url_utils::extension::extract_extension_from_url::{ + extract_extension_from_url_str, ExtractExtensions, }; pub async fn execute_seedance2pro_seedance2p0( @@ -57,21 +61,19 @@ async fn upload_to_seedance2pro( session: &seedance2pro::creds::seedance2pro_session::Seedance2ProSession, source_url: &str, ) -> Result { - // Extract file extension from URL - let extension = extract_extension(source_url).unwrap_or("bin"); + let extension = extract_extension_from_url_str(source_url, &ExtractExtensions::All) + .map(|ext| ext.without_period().to_string()) + .unwrap_or_else(|| "jpg".to_string()); - // Download the file let file_bytes = download_file(source_url).await?; - // Prepare the upload (get a signed URL) let prepare_response = prepare_file_upload(PrepareFileUploadArgs { session, - extension: extension.to_string(), + extension, }) .await .map_err(|err| ArtcraftRouterError::Provider(ProviderError::Seedance2Pro(err)))?; - // Upload the file let upload_response = upload_file(UploadFileArgs { upload_url: prepare_response.upload_url, file_bytes, @@ -108,42 +110,3 @@ async fn upload_optional_url_list( } } } - -/// Download a file from a URL, returning its bytes. -async fn download_file(url: &str) -> Result, ArtcraftRouterError> { - let response = reqwest::get(url) - .await - .map_err(|err| ArtcraftRouterError::FileDownload(format!("Failed to download {}: {}", url, err)))?; - - if !response.status().is_success() { - return Err(ArtcraftRouterError::FileDownload( - format!("Download failed for {} with status {}", url, response.status()) - )); - } - - response.bytes() - .await - .map(|b| b.to_vec()) - .map_err(|err| ArtcraftRouterError::FileDownload(format!("Failed to read bytes from {}: {}", url, err))) -} - -/// Extract the file extension from a URL path, ignoring query parameters. -fn extract_extension(url: &str) -> Option<&str> { - let path = url.split('?').next().unwrap_or(url); - let filename = path.rsplit('/').next()?; - let dot_pos = filename.rfind('.')?; - Some(&filename[dot_pos + 1..]) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_extract_extension() { - assert_eq!(extract_extension("https://example.com/image.png"), Some("png")); - assert_eq!(extract_extension("https://example.com/video.mp4?token=abc"), Some("mp4")); - assert_eq!(extract_extension("https://example.com/path/to/file.jpg"), Some("jpg")); - assert_eq!(extract_extension("https://example.com/noext"), None); - } -} diff --git a/crates/api_clients/artcraft/artcraft_router/src/lib.rs b/crates/api_clients/artcraft/artcraft_router/src/lib.rs index 49dc9014a1..b7ace7c4b0 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/lib.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/lib.rs @@ -2,6 +2,7 @@ pub mod api; pub mod client; pub mod errors; pub mod generate; +pub mod utils; #[cfg(test)] pub mod test_helpers; diff --git a/crates/api_clients/artcraft/artcraft_router/src/utils/download_file.rs b/crates/api_clients/artcraft/artcraft_router/src/utils/download_file.rs new file mode 100644 index 0000000000..ec33419a5f --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_router/src/utils/download_file.rs @@ -0,0 +1,19 @@ +use crate::errors::artcraft_router_error::ArtcraftRouterError; + +/// Download a file from a URL, returning its bytes. +pub async fn download_file(url: &str) -> Result, ArtcraftRouterError> { + let response = reqwest::get(url) + .await + .map_err(|err| ArtcraftRouterError::FileDownload(format!("Failed to download {}: {}", url, err)))?; + + if !response.status().is_success() { + return Err(ArtcraftRouterError::FileDownload( + format!("Download failed for {} with status {}", url, response.status()) + )); + } + + response.bytes() + .await + .map(|b| b.to_vec()) + .map_err(|err| ArtcraftRouterError::FileDownload(format!("Failed to read bytes from {}: {}", url, err))) +} diff --git a/crates/api_clients/artcraft/artcraft_router/src/utils/mod.rs b/crates/api_clients/artcraft/artcraft_router/src/utils/mod.rs new file mode 100644 index 0000000000..db2beffde9 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_router/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod download_file; diff --git a/crates/lib/url_utils/src/extension/extract_extension_from_url.rs b/crates/lib/url_utils/src/extension/extract_extension_from_url.rs index f84f9d11f8..928aa583fe 100644 --- a/crates/lib/url_utils/src/extension/extract_extension_from_url.rs +++ b/crates/lib/url_utils/src/extension/extract_extension_from_url.rs @@ -228,4 +228,17 @@ mod tests { let ext = extract_extension_from_url_str(url, &ExtractExtensions::All); assert!(ext.is_none()); } + + fn extract_extension_all(url: &str) -> Option { + extract_extension_from_url_str(url, &ExtractExtensions::All) + .map(|ext| ext.without_period().to_string()) + } + + #[test] + fn test_extract_various_extensions() { + assert_eq!(extract_extension_all("https://example.com/image.png").as_deref(), Some("png")); + assert_eq!(extract_extension_all("https://example.com/video.mp4?token=abc").as_deref(), Some("mp4")); + assert_eq!(extract_extension_all("https://example.com/path/to/file.jpg").as_deref(), Some("jpg")); + assert_eq!(extract_extension_all("https://example.com/noext"), None); + } }