diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image/enqueue_text_to_image_command.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image/enqueue_text_to_image_command.rs index 9ea18682a5..a89e5e507c 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image/enqueue_text_to_image_command.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image/enqueue_text_to_image_command.rs @@ -1,10 +1,13 @@ +use crate::core::commands::enqueue::image::handle_image_artcraft::handle_image_artcraft; use crate::core::commands::enqueue::image::handle_image_fal::handle_image_fal; use crate::core::commands::enqueue::image::handle_image_sora::handle_image_sora; use crate::core::commands::enqueue::image::internal_image_error::InternalImageError; +use crate::core::commands::enqueue::object::handle_object_artcraft::handle_object_artcraft; use crate::core::commands::response::failure_response_wrapper::{CommandErrorResponseWrapper, CommandErrorStatus}; use crate::core::commands::response::shorthand::Response; use crate::core::commands::response::success_response_wrapper::SerializeMarker; use crate::core::events::sendable_event_trait::SendableEvent; +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::data_dir::trait_data_subdir::DataSubdir; use crate::core::utils::download_media_file_to_temp_dir::download_media_file_to_temp_dir; @@ -55,8 +58,6 @@ use storyteller_client::media_files::upload_image_media_file_from_file::upload_i use storyteller_client::utils::api_host::ApiHost; use tauri::{AppHandle, Emitter, Manager, State}; use tempfile::NamedTempFile; -use crate::core::commands::enqueue::image::handle_image_artcraft::handle_image_artcraft; -use crate::core::commands::enqueue::object::handle_object_artcraft::handle_object_artcraft; #[derive(Deserialize)] pub struct EnqueueTextToImageRequest { @@ -114,6 +115,7 @@ pub async fn enqueue_text_to_image_command( app: AppHandle, request: EnqueueTextToImageRequest, app_data_root: State<'_, AppDataRoot>, + app_env_configs: State<'_, AppEnvConfigs>, fal_creds_manager: State<'_, FalCredentialManager>, storyteller_creds_manager: State<'_, StorytellerCredentialManager>, fal_task_queue: State<'_, FalTaskQueue>, @@ -129,6 +131,7 @@ pub async fn enqueue_text_to_image_command( &app_data_root, &fal_creds_manager, &storyteller_creds_manager, + &app_env_configs, &fal_task_queue, &sora_creds_manager, &sora_task_queue, @@ -176,6 +179,7 @@ pub async fn handle_request( app_data_root: &AppDataRoot, fal_creds_manager: &FalCredentialManager, storyteller_creds_manager: &StorytellerCredentialManager, + app_env_configs: &AppEnvConfigs, fal_task_queue: &FalTaskQueue, sora_creds_manager: &SoraCredentialManager, sora_task_queue: &SoraTaskQueue, @@ -197,7 +201,7 @@ pub async fn handle_request( if fal_creds_manager.has_apparent_api_token()? { handle_image_fal(&app, request, fal_creds_manager, fal_task_queue).await?; } else { - handle_image_artcraft(request, &app, app_data_root, storyteller_creds_manager).await?; + handle_image_artcraft(request, &app, app_env_configs, app_data_root, storyteller_creds_manager).await?; } Ok(()) diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs index 116621f899..a9569fe7b6 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image/handle_image_artcraft.rs @@ -4,6 +4,7 @@ use crate::core::events::basic_sendable_event_trait::BasicSendableEvent; use crate::core::events::generation_events::common::{GenerationAction, GenerationModel, GenerationServiceProvider}; use crate::core::events::generation_events::generation_enqueue_failure_event::GenerationEnqueueFailureEvent; use crate::core::events::generation_events::generation_enqueue_success_event::GenerationEnqueueSuccessEvent; +use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; use crate::core::state::data_dir::app_data_root::AppDataRoot; use crate::core::utils::download_media_file_to_temp_dir::download_media_file_to_temp_dir; use crate::core::utils::save_base64_image_to_temp_dir::save_base64_image_to_temp_dir; @@ -37,6 +38,7 @@ use tauri::{AppHandle, State}; pub async fn handle_image_artcraft( request: EnqueueTextToImageRequest, app: &AppHandle, + app_env_configs: &AppEnvConfigs, app_data_root: &AppDataRoot, storyteller_creds_manager: &StorytellerCredentialManager, ) -> Result<(), InternalImageError> { @@ -82,7 +84,7 @@ pub async fn handle_image_artcraft( num_images: None, }; let result = generate_flux_1_dev_text_to_image( - &ApiHost::Storyteller, + &app_env_configs.storyteller_host, Some(&creds), request, ).await; @@ -107,7 +109,7 @@ pub async fn handle_image_artcraft( num_images: None, }; let result = generate_flux_1_schnell_text_to_image( - &ApiHost::Storyteller, + &app_env_configs.storyteller_host, Some(&creds), request, ).await; @@ -132,7 +134,7 @@ pub async fn handle_image_artcraft( num_images: None, }; let result = generate_flux_pro_11_text_to_image( - &ApiHost::Storyteller, + &app_env_configs.storyteller_host, Some(&creds), request, ).await; @@ -160,7 +162,7 @@ pub async fn handle_image_artcraft( num_images: None, }; let result = generate_flux_pro_11_ultra_text_to_image( - &ApiHost::Storyteller, + &app_env_configs.storyteller_host, Some(&creds), request, ).await; diff --git a/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs.rs b/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs.rs new file mode 100644 index 0000000000..2e6b21a940 --- /dev/null +++ b/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs.rs @@ -0,0 +1,38 @@ +use log::info; +use errors::AnyhowResult; +use storyteller_client::utils::api_host::ApiHost; +use crate::core::state::app_env_configs::app_env_configs_serializeable::{AppEnvConfigsSerializable, StorytellerApiHost}; +use crate::core::state::data_dir::app_data_root::AppDataRoot; + +#[derive(Clone)] +pub struct AppEnvConfigs { + pub storyteller_host: ApiHost, +} + +impl AppEnvConfigs { + + pub fn load_from_filesystem(root: &AppDataRoot) -> AnyhowResult { + println!("Loading app environmental configs from filesystem..."); + let input = AppEnvConfigsSerializable::load_from_filesystem(root)?; + + let storyteller = input.as_ref() + .map(|i| i.storyteller_host) + .flatten(); + + let storyteller_api = match storyteller { + Some(StorytellerApiHost::Localhost) => ApiHost::Localhost { + port: input.as_ref() + .and_then(|i| i.storyteller_port) + .unwrap_or(12345) + }, + Some(StorytellerApiHost::Production) => ApiHost::Storyteller, + _ => ApiHost::Storyteller, + }; + + println!("Using storyteller API host: {:?}", storyteller_api); + + Ok(Self { + storyteller_host: storyteller_api, + }) + } +} diff --git a/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs_serializeable.rs b/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs_serializeable.rs new file mode 100644 index 0000000000..483003d9b5 --- /dev/null +++ b/crates/desktop/artcraft/src/core/state/app_env_configs/app_env_configs_serializeable.rs @@ -0,0 +1,34 @@ +use serde_derive::{Deserialize, Serialize}; +use errors::AnyhowResult; +use crate::core::state::data_dir::app_data_root::AppDataRoot; + +const CURRENT_VERSION: &str = "1"; + +#[derive(Debug, Copy, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum StorytellerApiHost { + Production, + Localhost, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub struct AppEnvConfigsSerializable { + /// Versioning string. + pub version: Option, + pub storyteller_port: Option, + pub storyteller_host: Option, +} + +impl AppEnvConfigsSerializable { + pub fn load_from_filesystem(app_data_root: &AppDataRoot) -> AnyhowResult> { + let filename = app_data_root.settings_dir().get_app_env_configs_path(); + if !filename.exists() { + return Ok(None); + } + + let contents = std::fs::read_to_string(filename)?; + let data: Self = serde_json::from_str(&contents)?; + Ok(Some(data)) + } +} diff --git a/crates/desktop/artcraft/src/core/state/app_env_configs/mod.rs b/crates/desktop/artcraft/src/core/state/app_env_configs/mod.rs new file mode 100644 index 0000000000..be171e276d --- /dev/null +++ b/crates/desktop/artcraft/src/core/state/app_env_configs/mod.rs @@ -0,0 +1,2 @@ +pub mod app_env_configs; +pub mod app_env_configs_serializeable; \ No newline at end of file diff --git a/crates/desktop/artcraft/src/core/state/data_dir/app_settings_dir.rs b/crates/desktop/artcraft/src/core/state/data_dir/app_settings_dir.rs index e3a48b21ef..59cc921555 100644 --- a/crates/desktop/artcraft/src/core/state/data_dir/app_settings_dir.rs +++ b/crates/desktop/artcraft/src/core/state/data_dir/app_settings_dir.rs @@ -31,7 +31,11 @@ impl AppSettingsDir { pub fn get_app_preferences_path(&self) -> PathBuf { self.path.join("app_preferences.json") } - + + pub fn get_app_env_configs_path(&self) -> PathBuf { + self.path.join("env_configs.json") + } + pub fn write_app_preferences(&self, prefs: &AppPreferences) -> AnyhowResult<()> { let serializable = prefs.to_serializable(); diff --git a/crates/desktop/artcraft/src/core/state/mod.rs b/crates/desktop/artcraft/src/core/state/mod.rs index beda27a3c3..9b2f65bd9b 100644 --- a/crates/desktop/artcraft/src/core/state/mod.rs +++ b/crates/desktop/artcraft/src/core/state/mod.rs @@ -1,3 +1,4 @@ +pub mod app_env_configs; pub mod app_preferences; pub mod app_startup_time; pub mod data_dir; diff --git a/crates/desktop/artcraft/src/lib.rs b/crates/desktop/artcraft/src/lib.rs index e7791f5ccf..88f4a593b7 100644 --- a/crates/desktop/artcraft/src/lib.rs +++ b/crates/desktop/artcraft/src/lib.rs @@ -11,6 +11,7 @@ use crate::core::commands::enqueue::video::enqueue_image_to_video_command::enque use crate::core::commands::flip_image::flip_image; use crate::core::commands::get_build_info_command::get_build_info_command; use crate::core::commands::platform_info_command::platform_info_command; +use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; use crate::core::state::app_preferences::app_preferences_manager::load_app_preferences_or_default; use crate::core::state::data_dir::app_data_root::AppDataRoot; use crate::core::state::main_window_position::MainWindowPosition; @@ -71,6 +72,9 @@ pub fn run() { let fal_task_queue = FalTaskQueue::new(); let fal_task_queue_2 = fal_task_queue.clone(); + + let app_env_configs = AppEnvConfigs::load_from_filesystem(&app_data_root) + .expect("AppEnvConfigs should be loaded from disk"); println!("Initializing backend runtime..."); @@ -155,6 +159,7 @@ pub fn run() { Ok(()) }) .manage(app_data_root) + .manage(app_env_configs) .manage(app_preferences) .manage(fal_creds_manager) .manage(fal_task_queue) diff --git a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_dev_text_to_image.rs b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_dev_text_to_image.rs index 0e8280983f..1019b1f667 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_dev_text_to_image.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_dev_text_to_image.rs @@ -1,68 +1,18 @@ use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; -use crate::error::api_error::ApiError; -use crate::error::client_error::ClientError; use crate::error::storyteller_error::StorytellerError; use crate::utils::api_host::ApiHost; -use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; -use crate::utils::filter_bad_response::filter_bad_response; +use crate::utils::basic_json_post_request::basic_json_post_request; use artcraft_api_defs::generate::image::generate_flux_1_dev_text_to_image::{GenerateFlux1DevTextToImageRequest, GenerateFlux1DevTextToImageResponse, GENERATE_FLUX_1_DEV_TEXT_TO_IMAGE_PATH}; -use log::{debug, info}; -use reqwest::Client; pub async fn generate_flux_1_dev_text_to_image( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, request: GenerateFlux1DevTextToImageRequest, ) -> Result { - - let url = get_route(api_host); - - info!("Requesting {:?}", &url); - - let client = Client::builder() - .gzip(true) - .build() - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - let mut request_builder = client.post(url) - .header("User-Agent", USER_AGENT) - .header("Accept", APPLICATION_JSON) - .header("Content-Type", APPLICATION_JSON); - - if let Some(creds) = maybe_creds { - if let Some(header) = &creds.maybe_as_cookie_header() { - request_builder = request_builder.header("Cookie", header); - } - } - - let request_body = serde_json::to_string(&request) - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - debug!("Request body: {:?}", request_body); - - let response = request_builder - .body(request_body) - .send() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response = filter_bad_response(response) - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response_body = &response.text() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - debug!("Response body: {:?}", response_body); - - let response = serde_json::from_str(&response_body) - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - Ok(response) -} - -fn get_route(api_host: &ApiHost) -> String { - let api_hostname = api_host.to_api_hostname(); - format!("https://{}{}", api_hostname, GENERATE_FLUX_1_DEV_TEXT_TO_IMAGE_PATH) + Ok(basic_json_post_request( + api_host, + GENERATE_FLUX_1_DEV_TEXT_TO_IMAGE_PATH, + maybe_creds, + request, + ).await?) } diff --git a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_schnell_text_to_image.rs b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_schnell_text_to_image.rs index 2b58b2b32a..3cc1681be7 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_schnell_text_to_image.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_1_schnell_text_to_image.rs @@ -1,68 +1,18 @@ use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; -use crate::error::api_error::ApiError; -use crate::error::client_error::ClientError; use crate::error::storyteller_error::StorytellerError; use crate::utils::api_host::ApiHost; -use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; -use crate::utils::filter_bad_response::filter_bad_response; +use crate::utils::basic_json_post_request::basic_json_post_request; use artcraft_api_defs::generate::image::generate_flux_1_schnell_text_to_image::{GenerateFlux1SchnellTextToImageRequest, GenerateFlux1SchnellTextToImageResponse, GENERATE_FLUX_1_SCHNELL_TEXT_TO_IMAGE_PATH}; -use log::{debug, info}; -use reqwest::Client; pub async fn generate_flux_1_schnell_text_to_image( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, request: GenerateFlux1SchnellTextToImageRequest, ) -> Result { - - let url = get_route(api_host); - - info!("Requesting {:?}", &url); - - let client = Client::builder() - .gzip(true) - .build() - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - let mut request_builder = client.post(url) - .header("User-Agent", USER_AGENT) - .header("Accept", APPLICATION_JSON) - .header("Content-Type", APPLICATION_JSON); - - if let Some(creds) = maybe_creds { - if let Some(header) = &creds.maybe_as_cookie_header() { - request_builder = request_builder.header("Cookie", header); - } - } - - let request_body = serde_json::to_string(&request) - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - debug!("Request body: {:?}", request_body); - - let response = request_builder - .body(request_body) - .send() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response = filter_bad_response(response) - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response_body = &response.text() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - debug!("Response body: {:?}", response_body); - - let response = serde_json::from_str(&response_body) - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - Ok(response) -} - -fn get_route(api_host: &ApiHost) -> String { - let api_hostname = api_host.to_api_hostname(); - format!("https://{}{}", api_hostname, GENERATE_FLUX_1_SCHNELL_TEXT_TO_IMAGE_PATH) + Ok(basic_json_post_request( + api_host, + GENERATE_FLUX_1_SCHNELL_TEXT_TO_IMAGE_PATH, + maybe_creds, + request, + ).await?) } diff --git a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_text_to_image.rs b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_text_to_image.rs index 250e7ab550..501a6087a6 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_text_to_image.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_text_to_image.rs @@ -1,68 +1,18 @@ use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; -use crate::error::api_error::ApiError; -use crate::error::client_error::ClientError; use crate::error::storyteller_error::StorytellerError; use crate::utils::api_host::ApiHost; -use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; -use crate::utils::filter_bad_response::filter_bad_response; +use crate::utils::basic_json_post_request::basic_json_post_request; use artcraft_api_defs::generate::image::generate_flux_pro_11_text_to_image::{GenerateFluxPro11TextToImageRequest, GenerateFluxPro11TextToImageResponse, GENERATE_FLUX_PRO_11_TEXT_TO_IMAGE_PATH}; -use log::{debug, info}; -use reqwest::Client; pub async fn generate_flux_pro_11_text_to_image( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, request: GenerateFluxPro11TextToImageRequest, ) -> Result { - - let url = get_route(api_host); - - info!("Requesting {:?}", &url); - - let client = Client::builder() - .gzip(true) - .build() - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - let mut request_builder = client.post(url) - .header("User-Agent", USER_AGENT) - .header("Accept", APPLICATION_JSON) - .header("Content-Type", APPLICATION_JSON); - - if let Some(creds) = maybe_creds { - if let Some(header) = &creds.maybe_as_cookie_header() { - request_builder = request_builder.header("Cookie", header); - } - } - - let request_body = serde_json::to_string(&request) - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - debug!("Request body: {:?}", request_body); - - let response = request_builder - .body(request_body) - .send() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response = filter_bad_response(response) - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response_body = &response.text() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - debug!("Response body: {:?}", response_body); - - let response = serde_json::from_str(&response_body) - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - Ok(response) -} - -fn get_route(api_host: &ApiHost) -> String { - let api_hostname = api_host.to_api_hostname(); - format!("https://{}{}", api_hostname, GENERATE_FLUX_PRO_11_TEXT_TO_IMAGE_PATH) + Ok(basic_json_post_request( + api_host, + GENERATE_FLUX_PRO_11_TEXT_TO_IMAGE_PATH, + maybe_creds, + request, + ).await?) } diff --git a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_ultra_text_to_image.rs b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_ultra_text_to_image.rs index dc8a25ad99..6ba10770be 100644 --- a/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_ultra_text_to_image.rs +++ b/crates/lib/api_clients/storyteller_client/src/generate/image/generate_flux_pro_11_ultra_text_to_image.rs @@ -1,68 +1,18 @@ use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; -use crate::error::api_error::ApiError; -use crate::error::client_error::ClientError; use crate::error::storyteller_error::StorytellerError; use crate::utils::api_host::ApiHost; -use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; -use crate::utils::filter_bad_response::filter_bad_response; +use crate::utils::basic_json_post_request::basic_json_post_request; use artcraft_api_defs::generate::image::generate_flux_pro_11_ultra_text_to_image::{GenerateFluxPro11UltraTextToImageRequest, GenerateFluxPro11UltraTextToImageResponse, GENERATE_FLUX_PRO_11_ULTRA_TEXT_TO_IMAGE_PATH}; -use log::{debug, info}; -use reqwest::Client; pub async fn generate_flux_pro_11_ultra_text_to_image( api_host: &ApiHost, maybe_creds: Option<&StorytellerCredentialSet>, request: GenerateFluxPro11UltraTextToImageRequest, ) -> Result { - - let url = get_route(api_host); - - info!("Requesting {:?}", &url); - - let client = Client::builder() - .gzip(true) - .build() - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - let mut request_builder = client.post(url) - .header("User-Agent", USER_AGENT) - .header("Accept", APPLICATION_JSON) - .header("Content-Type", APPLICATION_JSON); - - if let Some(creds) = maybe_creds { - if let Some(header) = &creds.maybe_as_cookie_header() { - request_builder = request_builder.header("Cookie", header); - } - } - - let request_body = serde_json::to_string(&request) - .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; - - debug!("Request body: {:?}", request_body); - - let response = request_builder - .body(request_body) - .send() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response = filter_bad_response(response) - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - let response_body = &response.text() - .await - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - debug!("Response body: {:?}", response_body); - - let response = serde_json::from_str(&response_body) - .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; - - Ok(response) -} - -fn get_route(api_host: &ApiHost) -> String { - let api_hostname = api_host.to_api_hostname(); - format!("https://{}{}", api_hostname, GENERATE_FLUX_PRO_11_ULTRA_TEXT_TO_IMAGE_PATH) + Ok(basic_json_post_request( + api_host, + GENERATE_FLUX_PRO_11_ULTRA_TEXT_TO_IMAGE_PATH, + maybe_creds, + request, + ).await?) } diff --git a/crates/lib/api_clients/storyteller_client/src/utils/api_host.rs b/crates/lib/api_clients/storyteller_client/src/utils/api_host.rs index cc75a97538..ea45493b82 100644 --- a/crates/lib/api_clients/storyteller_client/src/utils/api_host.rs +++ b/crates/lib/api_clients/storyteller_client/src/utils/api_host.rs @@ -1,5 +1,5 @@ -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum ApiHost { Storyteller, FakeYou, @@ -14,4 +14,12 @@ impl ApiHost { ApiHost::Localhost { port } => format!("localhost:{}", port), } } + + pub fn to_api_hostname_and_scheme(&self) -> String { + match self { + ApiHost::Storyteller => "https://api.storyteller.ai".to_string(), + ApiHost::FakeYou => "https://api.fakeyou.com".to_string(), + ApiHost::Localhost { port } => format!("http://localhost:{}", port), + } + } } diff --git a/crates/lib/api_clients/storyteller_client/src/utils/basic_json_post_request.rs b/crates/lib/api_clients/storyteller_client/src/utils/basic_json_post_request.rs new file mode 100644 index 0000000000..838e97b14c --- /dev/null +++ b/crates/lib/api_clients/storyteller_client/src/utils/basic_json_post_request.rs @@ -0,0 +1,71 @@ +use crate::credentials::storyteller_credential_set::StorytellerCredentialSet; +use crate::error::api_error::ApiError; +use crate::error::client_error::ClientError; +use crate::error::storyteller_error::StorytellerError; +use crate::utils::api_host::ApiHost; +use crate::utils::constants::{APPLICATION_JSON, USER_AGENT}; +use crate::utils::filter_bad_response::filter_bad_response; +use artcraft_api_defs::generate::image::generate_flux_1_schnell_text_to_image::{GenerateFlux1SchnellTextToImageRequest, GenerateFlux1SchnellTextToImageResponse, GENERATE_FLUX_1_SCHNELL_TEXT_TO_IMAGE_PATH}; +use log::{debug, info}; +use reqwest::Client; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; + +pub async fn basic_json_post_request( + api_host: &ApiHost, + route_path: &str, + maybe_creds: Option<&StorytellerCredentialSet>, + request: Req, +) -> Result { + + let url = get_route(api_host, route_path); + + info!("Requesting {:?}", &url); + + let client = Client::builder() + .gzip(true) + .build() + .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; + + let mut request_builder = client.post(url) + .header("User-Agent", USER_AGENT) + .header("Accept", APPLICATION_JSON) + .header("Content-Type", APPLICATION_JSON); + + if let Some(creds) = maybe_creds { + if let Some(header) = &creds.maybe_as_cookie_header() { + request_builder = request_builder.header("Cookie", header); + } + } + + let request_body = serde_json::to_string(&request) + .map_err(|err| StorytellerError::Client(ClientError::from(err)))?; + + debug!("Request body: {:?}", request_body); + + let response = request_builder + .body(request_body) + .send() + .await + .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; + + let response = filter_bad_response(response) + .await + .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; + + let response_body = &response.text() + .await + .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; + + debug!("Response body: {:?}", response_body); + + let response = serde_json::from_str(&response_body) + .map_err(|err| StorytellerError::Api(ApiError::from(err)))?; + + Ok(response) +} + +fn get_route(api_host: &ApiHost, route_path: &str) -> String { + let api_hostname = api_host.to_api_hostname_and_scheme(); + format!("{}{}", api_hostname, route_path) +} diff --git a/crates/lib/api_clients/storyteller_client/src/utils/mod.rs b/crates/lib/api_clients/storyteller_client/src/utils/mod.rs index a9fc1c4753..defbbbc4c5 100644 --- a/crates/lib/api_clients/storyteller_client/src/utils/mod.rs +++ b/crates/lib/api_clients/storyteller_client/src/utils/mod.rs @@ -1,4 +1,5 @@ pub mod api_host; +pub mod basic_json_post_request; pub mod constants; pub mod filter_bad_response; pub mod http_get_anonymous;