From 4722bc3fecd0e208de1b588771c60e7481dd7914 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 1 Aug 2025 00:22:59 -0400 Subject: [PATCH] cleanup --- .../upload_image_media_file_from_bytes.rs | 23 +++++-------- .../enqueue_image_inpaint_command.rs | 15 ++++---- .../commands/enqueue/image_inpaint/errors.rs | 23 ++++++++++--- .../handle_flux_pro_1_inpaint_artcraft.rs | 34 ++++++++++--------- 4 files changed, 51 insertions(+), 44 deletions(-) diff --git a/crates/api_clients/storyteller_client/src/media_files/upload_image_media_file_from_bytes.rs b/crates/api_clients/storyteller_client/src/media_files/upload_image_media_file_from_bytes.rs index b86ada1ea3..045ba59f43 100644 --- a/crates/api_clients/storyteller_client/src/media_files/upload_image_media_file_from_bytes.rs +++ b/crates/api_clients/storyteller_client/src/media_files/upload_image_media_file_from_bytes.rs @@ -21,7 +21,7 @@ use enums::no_table::style_transfer::style_transfer_name::StyleTransferName; use enums_public::by_table::model_weights::public_weights_types::PublicWeightsType; use idempotency::uuid::generate_random_uuid; use log::debug; -use reqwest::multipart::Form; +use reqwest::multipart::{Form, Part}; use reqwest::Client; use serde_derive::{Deserialize, Serialize}; use std::fs::File; @@ -34,10 +34,11 @@ use tokens::tokens::prompts::PromptToken; use uuid::uuid; /// Upload an image media file from a file. +/// NB: We need owned bytes for the request. pub async fn upload_image_media_file_from_bytes( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, - bytes: &[u8], + bytes: Vec, ) -> Result { let url = get_route(api_host); @@ -49,22 +50,14 @@ pub async fn upload_image_media_file_from_bytes( .build() .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - // TODO TODO IN-MEMORY FORM-MULTIPOST WITH BYTES - - + let part = Part::bytes(bytes) + .file_name("image.png") + .mime_str("image/png") + .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; let form = Form::new() .text("uuid_idempotency_token", generate_random_uuid()) - .file("file", path) - .await - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; + .part("file", part); let mut request_builder = client.post(url) .header("User-Agent", USER_AGENT) diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/enqueue_image_inpaint_command.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/enqueue_image_inpaint_command.rs index 321b912f99..9a2bb4d0b2 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/enqueue_image_inpaint_command.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/enqueue_image_inpaint_command.rs @@ -94,20 +94,17 @@ pub enum EnqueueInpaintImageErrorType { /// No mask image was supplied. NoMaskImageSpecified, + /// Too many mask images were supplied. + MultipleMaskImagesSpecified, + + /// Bad mask image was supplied. + BadMaskImage, + /// Generic bad request error BadRequest, /// Generic server error ServerError, - - /// The user is sending too many requests - TooManyConcurrentTasks, - /// User is not logged into Sora! - SoraLoginRequired, - /// The user needs to create a Sora account - SoraUsernameNotYetCreated, - /// The Sora service is having problems. Try again soon. - SoraIsHavingProblems, } #[derive(Serialize)] diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/errors.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/errors.rs index 23a39dc01e..e11b65e5ce 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/errors.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/errors.rs @@ -20,13 +20,13 @@ pub enum InternalImageInpaintError { /// Both mask image media token and raw bytes were supplied. MaskMediaTokenAndBytesSupplied, - + /// Mask image has an unknown MIME type. CouldNotDetermineMaskMimeType, - + /// Could not encode the mask image to PNG. CouldNotEncodeMask, - + /// No storyteller credentials are set. NeedsStorytellerCredentials, @@ -85,7 +85,22 @@ impl InternalImageInpaintError { InternalImageInpaintError::NoMaskImageSpecified => { status = CommandErrorStatus::BadRequest; error_type = EnqueueInpaintImageErrorType::NoMaskImageSpecified; - error_message = "No source image was provided".to_string(); + error_message = "No mask image was provided".to_string(); + } + InternalImageInpaintError::MaskMediaTokenAndBytesSupplied => { + status = CommandErrorStatus::BadRequest; + error_type = EnqueueInpaintImageErrorType::MultipleMaskImagesSpecified; + error_message = "multiple mask images provided".to_string(); + } + InternalImageInpaintError::CouldNotDetermineMaskMimeType => { + status = CommandErrorStatus::BadRequest; + error_type = EnqueueInpaintImageErrorType::BadMaskImage; + error_message = "bad mask image (mime)".to_string(); + } + InternalImageInpaintError::CouldNotEncodeMask => { + status = CommandErrorStatus::BadRequest; + error_type = EnqueueInpaintImageErrorType::BadMaskImage; + error_message = "bad mask image (encode)".to_string(); } InternalImageInpaintError::InvalidNumberOfRequestedImages { min, max, requested } => { status = CommandErrorStatus::BadRequest; diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/flux_pro_1_inpaint/handle_flux_pro_1_inpaint_artcraft.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/flux_pro_1_inpaint/handle_flux_pro_1_inpaint_artcraft.rs index 3b8132a207..eb9417f28f 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/flux_pro_1_inpaint/handle_flux_pro_1_inpaint_artcraft.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_inpaint/flux_pro_1_inpaint/handle_flux_pro_1_inpaint_artcraft.rs @@ -1,5 +1,7 @@ use crate::core::commands::enqueue::image::enqueue_text_to_image_command::EnqueueTextToImageRequest; use crate::core::commands::enqueue::image::internal_image_error::InternalImageError; +use crate::core::commands::enqueue::image_bg_removal::enqueue_image_bg_removal_command::EnqueueImageBgRemovalCommand; +use crate::core::commands::enqueue::image_bg_removal::errors::InternalBgRemovalError; use crate::core::commands::enqueue::image_edit::enqueue_contextual_edit_image_command::{EditImageQuality, EditImageSize, EnqueueContextualEditImageCommand}; use crate::core::commands::enqueue::image_inpaint::enqueue_image_inpaint_command::EnqueueInpaintImageCommand; use crate::core::commands::enqueue::image_inpaint::errors::InternalImageInpaintError; @@ -12,6 +14,7 @@ use crate::core::model::image_models::ImageModel; use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; use crate::core::state::data_dir::app_data_root::AppDataRoot; use crate::core::state::provider_priority::ProviderPriorityStore; +use crate::core::utils::save_base64_image_to_temp_dir::save_base64_image_to_temp_dir; use crate::services::fal::state::fal_credential_manager::FalCredentialManager; use crate::services::fal::state::fal_task_queue::FalTaskQueue; use crate::services::sora::state::sora_credential_manager::SoraCredentialManager; @@ -29,23 +32,20 @@ use enums::tauri::tasks::task_type::TaskType; use fal_client::requests::queue::image_gen::enqueue_flux_pro_11_ultra_text_to_image::{enqueue_flux_pro_11_ultra_text_to_image, FluxPro11UltraTextToImageArgs}; use fal_client::requests::webhook::image::enqueue_gpt_image_1_edit_image_webhook::GptEditImageQuality; use idempotency::uuid::generate_random_uuid; +use images::encoding::image_bytes_to_png_bytes::image_bytes_to_png_bytes; use log::{error, info}; +use mimetypes::mimetype_info::mimetype_info::MimetypeInfo; +use storyteller_client::credentials::storyteller_credential_set::StorytellerCredentialSet; use storyteller_client::generate::image::edit::gpt_image_1_edit_image::gpt_image_1_edit_image; use storyteller_client::generate::image::generate_flux_1_dev_text_to_image::generate_flux_1_dev_text_to_image; use storyteller_client::generate::image::generate_flux_1_schnell_text_to_image::generate_flux_1_schnell_text_to_image; use storyteller_client::generate::image::generate_flux_pro_11_text_to_image::generate_flux_pro_11_text_to_image; use storyteller_client::generate::image::generate_flux_pro_11_ultra_text_to_image::generate_flux_pro_11_ultra_text_to_image; use storyteller_client::generate::image::inpaint::flux_pro_1_inpaint_image::flux_pro_1_inpaint_image; -use tauri::AppHandle; -use images::encoding::image_bytes_to_png_bytes::image_bytes_to_png_bytes; -use mimetypes::mimetype_info::mimetype_info::MimetypeInfo; -use storyteller_client::credentials::storyteller_credential_set::StorytellerCredentialSet; use storyteller_client::media_files::upload_image_media_file_from_bytes::upload_image_media_file_from_bytes; use storyteller_client::media_files::upload_image_media_file_from_file::upload_image_media_file_from_file; +use tauri::AppHandle; use tokens::tokens::media_files::MediaFileToken; -use crate::core::commands::enqueue::image_bg_removal::enqueue_image_bg_removal_command::EnqueueImageBgRemovalCommand; -use crate::core::commands::enqueue::image_bg_removal::errors::InternalBgRemovalError; -use crate::core::utils::save_base64_image_to_temp_dir::save_base64_image_to_temp_dir; pub async fn handle_flux_pro_1_inpaint_artcraft( request: &EnqueueInpaintImageCommand, @@ -65,7 +65,7 @@ pub async fn handle_flux_pro_1_inpaint_artcraft( info!("Calling Artcraft flux pro 1 inpaint ..."); let uuid_idempotency_token = generate_random_uuid(); - + let num_images = match request.image_count { None => None, Some(1) => Some(FluxPro1InpaintImageNumImages::One), @@ -80,7 +80,7 @@ pub async fn handle_flux_pro_1_inpaint_artcraft( }); }, }; - + let image_media_token = match &request.image_media_token { Some(token) => token.clone(), None => { @@ -159,13 +159,15 @@ async fn get_mask( info!("Uploading image media file from bytes..."); - let result = - upload_image_media_file_from_bytes(&app_env_configs.storyteller_host, Some(&storyteller_creds), &image_bytes) - .await - .map_err(|err| { - error!("Failed to upload image media file: {:?}", err); - InternalImageInpaintError::StorytellerError(err) - })?; + let result = upload_image_media_file_from_bytes( + &app_env_configs.storyteller_host, + Some(&storyteller_creds), + image_bytes + ).await + .map_err(|err| { + error!("Failed to upload image media file: {:?}", err); + InternalImageInpaintError::StorytellerError(err) + })?; Ok(result.media_file_token) }