diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/video/omni_gen_video_cost_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/video/omni_gen_video_cost_handler.rs index b9b697eb0c..cc5411ef6e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/video/omni_gen_video_cost_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/video/omni_gen_video_cost_handler.rs @@ -1,15 +1,15 @@ use std::sync::Arc; +use crate::http_server::common_responses::common_web_error::CommonWebError; +use crate::http_server::endpoints::omni_gen::generate::video::helpers::hydrate_router_request::hydrate_to_router_request; +use crate::http_server::endpoints::omni_gen::shared_utils::video::validate_video_request::validate_video_request; +use crate::state::server_state::ServerState; use actix_web::web::Json; use actix_web::{web, HttpRequest}; use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_video_cost_and_generate_request::OmniGenVideoCostAndGenerateRequest; use artcraft_api_defs::omni_gen::cost_response::omni_gen_video_cost_response::OmniGenVideoCostResponse; use artcraft_router::api::router_provider::RouterProvider; use log::warn; -use crate::http_server::common_responses::common_web_error::CommonWebError; -use crate::http_server::endpoints::omni_gen::generate::video::helpers::hydrate_router_request::hydrate_to_router_request; -use crate::http_server::endpoints::omni_gen::generate::video::helpers::validate_image_required::validate_image_required; -use crate::state::server_state::ServerState; /// Estimate the cost of a video generation. #[utoipa::path( @@ -28,7 +28,7 @@ pub async fn omni_gen_video_cost_handler( request: Json, _server_state: web::Data>, ) -> Result, CommonWebError> { - validate_image_required(&request)?; + validate_video_request(&request)?; let mut builder = hydrate_to_router_request(&request)?; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/mod.rs index 2c80241f67..7108f22a3b 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/mod.rs @@ -4,4 +4,3 @@ pub(crate) mod hydrate_router_request; pub mod pipeline_result; pub mod resolve_kinovi_character_ids; pub mod resolve_media_tokens_to_urls; -pub mod validate_image_required; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs index 96a6b6535b..faa2b2ccca 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs @@ -32,15 +32,15 @@ use tokens::tokens::non_unique::debug_logs_event_token::DebugLogEventToken; use crate::http_server::common_responses::common_web_error::CommonWebError; use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test; use crate::http_server::endpoints::omni_gen::generate::video::helpers::hydrate_router_request::hydrate_to_router_request; -use crate::http_server::endpoints::omni_gen::generate::video::helpers::validate_image_required::validate_image_required; +use crate::http_server::endpoints::omni_gen::generate::video::helpers::resolve_kinovi_character_ids::resolve_kinovi_character_ids; use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::insert_fal_job::{insert_fal_job, InsertFalJobArgs}; use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::insert_gmicloud_job::{insert_gmicloud_job, InsertGmiCloudJobArgs}; use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::insert_grok_api_job::{insert_grok_api_job, InsertGrokApiJobArgs}; use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::insert_seedance2pro_jobs::{insert_seedance2pro_jobs, InsertSeedance2proJobsArgs}; use crate::http_server::endpoints::omni_gen::generate::video::insert_db_job::shared_job_args::SharedJobArgs; -use crate::http_server::endpoints::omni_gen::generate::video::pipeline_v2::run_pipeline_v2::{run_pipeline_v2, RunPipelineV2Args}; -use crate::http_server::endpoints::omni_gen::generate::video::helpers::resolve_kinovi_character_ids::resolve_kinovi_character_ids; use crate::http_server::endpoints::omni_gen::generate::video::kinovi_account::KinoviAccount; +use crate::http_server::endpoints::omni_gen::generate::video::pipeline_v2::run_pipeline_v2::{run_pipeline_v2, RunPipelineV2Args}; +use crate::http_server::endpoints::omni_gen::shared_utils::video::validate_video_request::validate_video_request; use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags; use crate::http_server::validations::validate_idempotency_token_format::validate_idempotency_token_format; use crate::state::server_state::ServerState; @@ -70,7 +70,7 @@ pub async fn omni_gen_video_generate_handler( // Reject doomed combos (e.g. grok_imagine_video_1p5 without an image) // before any billable or DB-mutating work — see helper for the rules. - validate_image_required(&request)?; + validate_video_request(&request)?; payments_error_test(&request.prompt.as_deref().unwrap_or(""))?; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/mod.rs index b86ae0ed6b..fefa50b0dd 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/mod.rs @@ -1,3 +1,4 @@ pub mod cost; pub mod generate; pub mod models; +pub mod shared_utils; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/mod.rs new file mode 100644 index 0000000000..8e5d9b9132 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/mod.rs @@ -0,0 +1 @@ +pub mod video; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/mod.rs new file mode 100644 index 0000000000..bfdbcc2afa --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/mod.rs @@ -0,0 +1,2 @@ +pub mod validate_video_request; +mod validate_when_image_required; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_video_request.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_video_request.rs new file mode 100644 index 0000000000..be9e4c6e0d --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_video_request.rs @@ -0,0 +1,11 @@ +use crate::http_server::common_responses::common_web_error::CommonWebError; +use crate::http_server::endpoints::omni_gen::shared_utils::video::validate_when_image_required::validate_when_image_required; +use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_video_cost_and_generate_request::OmniGenVideoCostAndGenerateRequest; + +/// Validate requests before they incur user costs or send API requests +pub fn validate_video_request( + request: &OmniGenVideoCostAndGenerateRequest, +) -> Result<(), CommonWebError> { + validate_when_image_required(request)?; + Ok(()) +} diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/validate_image_required.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_when_image_required.rs similarity index 89% rename from crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/validate_image_required.rs rename to crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_when_image_required.rs index f56e4e1d7f..c94faa6e48 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/helpers/validate_image_required.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/shared_utils/video/validate_when_image_required.rs @@ -7,7 +7,7 @@ use crate::http_server::common_responses::common_web_error::CommonWebError; /// the upstream API. Reject the request at the handler layer so callers see /// a clean 400 with an actionable message and we don't charge their wallet /// for an inference job we know will fail. -pub fn validate_image_required( +pub (super) fn validate_when_image_required( request: &OmniGenVideoCostAndGenerateRequest, ) -> Result<(), CommonWebError> { match request.model { @@ -22,6 +22,7 @@ pub fn validate_image_required( } let has_start_frame = request.start_frame_image_media_token.is_some(); + let has_reference_images = request .reference_image_media_tokens .as_ref() @@ -69,7 +70,7 @@ mod tests { #[test] fn passes_when_model_is_none() { let req = base_request(); - assert!(validate_image_required(&req).is_ok()); + assert!(validate_when_image_required(&req).is_ok()); } #[test] @@ -79,7 +80,7 @@ mod tests { model: Some(CommonVideoModel::Seedance2p0), ..base_request() }; - assert!(validate_image_required(&req).is_ok()); + assert!(validate_when_image_required(&req).is_ok()); } #[test] @@ -88,7 +89,7 @@ mod tests { model: Some(CommonVideoModel::GrokImagineVideo1p5), ..base_request() }; - let err = validate_image_required(&req).expect_err("should reject"); + let err = validate_when_image_required(&req).expect_err("should reject"); match err { CommonWebError::BadInputWithSimpleMessage(msg) => { assert_eq!(msg, "Image is required"); @@ -105,7 +106,7 @@ mod tests { ..base_request() }; assert!(matches!( - validate_image_required(&req), + validate_when_image_required(&req), Err(CommonWebError::BadInputWithSimpleMessage(_)) )); } @@ -117,7 +118,7 @@ mod tests { start_frame_image_media_token: Some(token("mf_start")), ..base_request() }; - assert!(validate_image_required(&req).is_ok()); + assert!(validate_when_image_required(&req).is_ok()); } #[test] @@ -127,7 +128,7 @@ mod tests { reference_image_media_tokens: Some(vec![token("mf_a"), token("mf_b")]), ..base_request() }; - assert!(validate_image_required(&req).is_ok()); + assert!(validate_when_image_required(&req).is_ok()); } #[test] @@ -138,7 +139,7 @@ mod tests { reference_image_media_tokens: Some(vec![token("mf_a")]), ..base_request() }; - assert!(validate_image_required(&req).is_ok()); + assert!(validate_when_image_required(&req).is_ok()); } #[test] @@ -151,6 +152,6 @@ mod tests { end_frame_image_media_token: Some(token("mf_end")), ..base_request() }; - assert!(validate_image_required(&req).is_err()); + assert!(validate_when_image_required(&req).is_err()); } }