This commit is contained in:
Brandon Thomas committed 2026-05-07 15:18:16 -04:00
1 parent a499bf44d3
commit e047736100
9 files changed
+265 -195

No files matched your search

@@ -6,15 +6,18 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct Flux1DevEditImageArgs<'a, U: IntoUrl> {
pub prompt: &'a str,
pub image_url: String,
pub num_images: Flux1DevEditImageNumImages,
// Fulfillment
pub request: Flux1DevEditImageRequest,
pub webhook_url: U,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct Flux1DevEditImageRequest {
pub prompt: String,
pub image_url: String,
pub num_images: Flux1DevEditImageNumImages,
}
#[derive(Copy, Clone, Debug)]
pub enum Flux1DevEditImageNumImages {
One,
@@ -26,7 +29,9 @@ pub enum Flux1DevEditImageNumImages {
pub async fn enqueue_flux_1_dev_edit_image_webhook<U: IntoUrl>(
args: Flux1DevEditImageArgs<'_, U>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = match args.num_images {
let req = args.request;
let num_images = match req.num_images {
Flux1DevEditImageNumImages::One => 1,
Flux1DevEditImageNumImages::Two => 2,
Flux1DevEditImageNumImages::Three => 3,
@@ -34,8 +39,8 @@ pub async fn enqueue_flux_1_dev_edit_image_webhook<U: IntoUrl>(
};
let request = Flux1DevEditImageInput {
prompt: args.prompt.to_string(),
image_url: args.image_url,
prompt: req.prompt,
image_url: req.image_url,
num_images: Some(num_images),
enable_safety_checker: Some(false),
output_format: Some("png".to_string()),
@@ -55,6 +60,7 @@ mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_flux_1_dev_edit_image_webhook::{
enqueue_flux_1_dev_edit_image_webhook, Flux1DevEditImageArgs, Flux1DevEditImageNumImages,
Flux1DevEditImageRequest,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
@@ -67,9 +73,11 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = Flux1DevEditImageArgs {
prompt: "make this image look like a watercolor painting",
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1DevEditImageNumImages::One,
request: Flux1DevEditImageRequest {
prompt: "make this image look like a watercolor painting".to_string(),
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1DevEditImageNumImages::One,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -86,9 +94,11 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = Flux1DevEditImageArgs {
prompt: "turn this into a cyberpunk scene with neon lights",
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1DevEditImageNumImages::Two,
request: Flux1DevEditImageRequest {
prompt: "turn this into a cyberpunk scene with neon lights".to_string(),
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1DevEditImageNumImages::Two,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -6,13 +6,16 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct Flux1SchnellEditImageArgs<'a, U: IntoUrl> {
pub request: Flux1SchnellEditImageRequest,
pub webhook_url: U,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct Flux1SchnellEditImageRequest {
pub image_url: String,
pub num_images: Flux1SchnellEditImageNumImages,
pub image_size: Option<Flux1SchnellEditImageSize>,
// Fulfillment
pub webhook_url: U,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
@@ -36,14 +39,16 @@ pub enum Flux1SchnellEditImageSize {
pub async fn enqueue_flux_1_schnell_edit_image_webhook<U: IntoUrl>(
args: Flux1SchnellEditImageArgs<'_, U>
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images = match args.num_images {
let req = args.request;
let num_images = match req.num_images {
Flux1SchnellEditImageNumImages::One => 1,
Flux1SchnellEditImageNumImages::Two => 2,
Flux1SchnellEditImageNumImages::Three => 3,
Flux1SchnellEditImageNumImages::Four => 4,
};
let image_size = args.image_size.map(|s| match s {
let image_size = req.image_size.map(|s| match s {
Flux1SchnellEditImageSize::Square => "square",
Flux1SchnellEditImageSize::SquareHd => "square_hd",
Flux1SchnellEditImageSize::LandscapeFourByThree => "landscape_4_3",
@@ -53,7 +58,7 @@ pub async fn enqueue_flux_1_schnell_edit_image_webhook<U: IntoUrl>(
}.to_string());
let request = Flux1SchnellEditImageInput {
image_url: args.image_url,
image_url: req.image_url,
num_images: Some(num_images),
image_size,
enable_safety_checker: Some(false),
@@ -74,7 +79,7 @@ mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_flux_1_schnell_edit_image_webhook::{
enqueue_flux_1_schnell_edit_image_webhook, Flux1SchnellEditImageArgs,
Flux1SchnellEditImageNumImages, Flux1SchnellEditImageSize,
Flux1SchnellEditImageNumImages, Flux1SchnellEditImageRequest, Flux1SchnellEditImageSize,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
@@ -87,9 +92,11 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = Flux1SchnellEditImageArgs {
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1SchnellEditImageNumImages::One,
image_size: None,
request: Flux1SchnellEditImageRequest {
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1SchnellEditImageNumImages::One,
image_size: None,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -106,9 +113,11 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = Flux1SchnellEditImageArgs {
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1SchnellEditImageNumImages::Two,
image_size: Some(Flux1SchnellEditImageSize::LandscapeSixteenByNine),
request: Flux1SchnellEditImageRequest {
image_url: GHOST_IMAGE_URL.to_string(),
num_images: Flux1SchnellEditImageNumImages::Two,
image_size: Some(Flux1SchnellEditImageSize::LandscapeSixteenByNine),
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -6,16 +6,20 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct FluxProKontextMaxArgs<'a, U: IntoUrl, R: IntoUrl> {
// Request
pub prompt: &'a str,
pub request: FluxProKontextMaxRequest,
pub image_url: U,
pub num_images: FluxProKontextMaxNumImages,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct FluxProKontextMaxRequest {
pub prompt: String,
pub num_images: FluxProKontextMaxNumImages,
}
#[derive(Copy, Clone, Debug)]
pub enum FluxProKontextMaxNumImages {
One, // Default
@@ -27,8 +31,9 @@ pub enum FluxProKontextMaxNumImages {
pub async fn enqueue_flux_pro_kontext_max_edit_webhook<U: IntoUrl, R: IntoUrl>(
args: FluxProKontextMaxArgs<'_, U, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let num_images = match args.num_images {
let num_images = match req.num_images {
FluxProKontextMaxNumImages::One => 1,
FluxProKontextMaxNumImages::Two => 2,
FluxProKontextMaxNumImages::Three => 3,
@@ -36,7 +41,7 @@ pub async fn enqueue_flux_pro_kontext_max_edit_webhook<U: IntoUrl, R: IntoUrl>(
};
let request = FluxProKontextMaxEditInput {
prompt: args.prompt.to_string(),
prompt: req.prompt,
image_url: args.image_url.as_str().to_string(),
num_images: Some(num_images),
@@ -61,7 +66,7 @@ pub async fn enqueue_flux_pro_kontext_max_edit_webhook<U: IntoUrl, R: IntoUrl>(
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_flux_pro_kontext_max_edit_webhook::{enqueue_flux_pro_kontext_max_edit_webhook, FluxProKontextMaxArgs, FluxProKontextMaxNumImages};
use crate::requests::webhook::image::edit::enqueue_flux_pro_kontext_max_edit_webhook::{enqueue_flux_pro_kontext_max_edit_webhook, FluxProKontextMaxArgs, FluxProKontextMaxNumImages, FluxProKontextMaxRequest};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::TALL_MOCHI_WITH_GLASSES_IMAGE_URL;
@@ -75,11 +80,13 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = FluxProKontextMaxArgs {
request: FluxProKontextMaxRequest {
prompt: "turn the glasses into sunglasses, make them sleek sunglasses with black rims, square shaped".to_string(),
num_images: FluxProKontextMaxNumImages::One,
},
image_url: TALL_MOCHI_WITH_GLASSES_IMAGE_URL,
prompt: "turn the glasses into sunglasses, make them sleek sunglasses with black rims, square shaped",
api_key: &api_key,
webhook_url: "https://example.com/webhook",
num_images: FluxProKontextMaxNumImages::One,
};
let result = enqueue_flux_pro_kontext_max_edit_webhook(args).await?;
@@ -7,19 +7,23 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct Gemini25FlashEditArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
pub num_images: Gemini25FlashEditNumImages,
// Optional
pub aspect_ratio: Option<Gemini25FlashEditAspectRatio>,
pub request: Gemini25FlashEditRequest,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct Gemini25FlashEditRequest {
pub prompt: String,
pub image_urls: Vec<String>,
pub num_images: Gemini25FlashEditNumImages,
// Optional
pub aspect_ratio: Option<Gemini25FlashEditAspectRatio>,
}
#[derive(Copy, Clone, Debug)]
pub enum Gemini25FlashEditNumImages {
One,
@@ -50,7 +54,7 @@ pub enum Gemini25FlashEditAspectRatio {
}
impl <U: IntoUrl> FalRequestCostCalculator for Gemini25FlashEditArgs<'_, U> {
impl FalRequestCostCalculator for Gemini25FlashEditRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
// Your request will cost $0.039 per image. For $1.00, you can run this model 25 times.
match self.num_images {
@@ -66,15 +70,16 @@ impl <U: IntoUrl> FalRequestCostCalculator for Gemini25FlashEditArgs<'_, U> {
pub async fn enqueue_gemini_25_flash_edit_webhook<R: IntoUrl>(
args: Gemini25FlashEditArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let num_images = match args.num_images {
let num_images = match req.num_images {
Gemini25FlashEditNumImages::One => 1,
Gemini25FlashEditNumImages::Two => 2,
Gemini25FlashEditNumImages::Three => 3,
Gemini25FlashEditNumImages::Four => 4,
};
let aspect_ratio = args.aspect_ratio
let aspect_ratio = req.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
// Auto
Gemini25FlashEditAspectRatio::Auto => "auto",
@@ -95,8 +100,8 @@ pub async fn enqueue_gemini_25_flash_edit_webhook<R: IntoUrl>(
.map(|aspect_ratio| aspect_ratio.to_string());
let request = Gemini25FlashEditInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
prompt: req.prompt,
image_urls: req.image_urls,
aspect_ratio,
// Constants
num_images: Some(num_images),
@@ -114,7 +119,7 @@ pub async fn enqueue_gemini_25_flash_edit_webhook<R: IntoUrl>(
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_gemini_25_flash_edit_webhook::{enqueue_gemini_25_flash_edit_webhook, Gemini25FlashEditArgs, Gemini25FlashEditNumImages};
use crate::requests::webhook::image::edit::enqueue_gemini_25_flash_edit_webhook::{enqueue_gemini_25_flash_edit_webhook, Gemini25FlashEditArgs, Gemini25FlashEditNumImages, Gemini25FlashEditRequest};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
@@ -128,13 +133,15 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = Gemini25FlashEditArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
],
num_images: Gemini25FlashEditNumImages::Two,
aspect_ratio: None,
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly",
request: Gemini25FlashEditRequest {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
],
num_images: Gemini25FlashEditNumImages::Two,
aspect_ratio: None,
prompt: "add the ghost to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -13,12 +13,7 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct GptEditImageByokArgs<'a, V: IntoUrl> {
// Request
pub image_urls: Vec<String>,
pub prompt: &'a str,
pub image_size: GptEditImageSize,
pub num_images: GptEditImageNumImages,
pub quality: GptEditImageQuality,
pub request: GptEditImageByokRequest,
// Fulfillment
pub api_key: &'a FalApiKey,
@@ -26,6 +21,15 @@ pub struct GptEditImageByokArgs<'a, V: IntoUrl> {
pub webhook_url: V,
}
#[derive(Clone, Debug)]
pub struct GptEditImageByokRequest {
pub image_urls: Vec<String>,
pub prompt: String,
pub image_size: GptEditImageSize,
pub num_images: GptEditImageNumImages,
pub quality: GptEditImageQuality,
}
#[derive(Copy, Clone, Debug)]
pub enum GptEditImageSize {
Auto,
@@ -52,7 +56,7 @@ pub enum GptEditImageNumImages{
// NB: These are BYOK, so they're not Fal's prices
impl <U: IntoUrl> FalRequestCostCalculator for GptEditImageByokArgs<'_, U> {
impl FalRequestCostCalculator for GptEditImageByokRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
let base_cost = match self.quality {
GptEditImageQuality::Auto => 17,
@@ -74,22 +78,23 @@ impl <U: IntoUrl> FalRequestCostCalculator for GptEditImageByokArgs<'_, U> {
pub async fn enqueue_gpt_image_1_byok_edit_image_webhook<V: IntoUrl>(
args: GptEditImageByokArgs<'_, V>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let image_size = match args.image_size {
let image_size = match req.image_size {
GptEditImageSize::Auto => "auto",
GptEditImageSize::Square => "1024x1024",
GptEditImageSize::Horizontal => "1536x1024",
GptEditImageSize::Vertical => "1024x1536",
};
let quality = match args.quality {
let quality = match req.quality {
GptEditImageQuality::Auto => "auto",
GptEditImageQuality::Low => "low",
GptEditImageQuality::Medium => "medium",
GptEditImageQuality::High => "high",
};
let num_images = match args.num_images {
let num_images = match req.num_images {
GptEditImageNumImages::One => 1,
GptEditImageNumImages::Two => 2,
GptEditImageNumImages::Three => 3,
@@ -97,8 +102,8 @@ pub async fn enqueue_gpt_image_1_byok_edit_image_webhook<V: IntoUrl>(
};
let request = GptImage1EditImageInput {
image_urls: args.image_urls,
prompt: args.prompt.to_string(),
image_urls: req.image_urls,
prompt: req.prompt,
image_size: image_size.to_string(),
num_images,
quality: quality.to_string(),
@@ -118,8 +123,8 @@ mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::creds::open_ai_api_key::OpenAiApiKey;
use crate::requests::webhook::image::edit::enqueue_gpt_image_1_byok_edit_image_webhook::{
enqueue_gpt_image_1_byok_edit_image_webhook, GptEditImageByokArgs, GptEditImageNumImages,
GptEditImageQuality, GptEditImageSize,
enqueue_gpt_image_1_byok_edit_image_webhook, GptEditImageByokArgs, GptEditImageByokRequest,
GptEditImageNumImages, GptEditImageQuality, GptEditImageSize,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
@@ -138,15 +143,17 @@ mod tests {
let openai_api_key = OpenAiApiKey::from_str(&openai_secret);
let args = GptEditImageByokArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
image_size: GptEditImageSize::Horizontal,
num_images: GptEditImageNumImages::One,
quality: GptEditImageQuality::High,
request: GptEditImageByokRequest {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
image_size: GptEditImageSize::Horizontal,
num_images: GptEditImageNumImages::One,
quality: GptEditImageQuality::High,
},
api_key: &fal_api_key,
openai_api_key: &openai_api_key,
webhook_url: "https://example.com/webhook",
@@ -15,8 +15,15 @@ use reqwest::IntoUrl;
/// (The BYOK variant lives in `enqueue_gpt_image_1_byok_edit_image_webhook.rs`
/// and is deprecated.)
pub struct EnqueueGptImage1EditImageArgs<'a, R: IntoUrl> {
pub request: EnqueueGptImage1EditImageRequest,
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct EnqueueGptImage1EditImageRequest {
// Required
pub prompt: &'a str,
pub prompt: String,
pub image_urls: Vec<String>,
pub num_images: EnqueueGptImage1EditImageNumImages,
@@ -27,10 +34,6 @@ pub struct EnqueueGptImage1EditImageArgs<'a, R: IntoUrl> {
pub input_fidelity: Option<EnqueueGptImage1EditImageInputFidelity>,
pub background: Option<EnqueueGptImage1EditImageBackground>,
pub output_format: Option<EnqueueGptImage1EditImageOutputFormat>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
@@ -79,7 +82,7 @@ pub enum EnqueueGptImage1EditImageOutputFormat {
Webp,
}
impl<U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1EditImageArgs<'_, U> {
impl FalRequestCostCalculator for EnqueueGptImage1EditImageRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
// Per fal docs (fal-ai/gpt-image-1/edit-image), pricing matches
// text-to-image (input image tokens are billed separately and not included
@@ -115,14 +118,16 @@ impl<U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1EditImageArgs<'_,
pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
args: EnqueueGptImage1EditImageArgs<'_, R>,
) -> Result<WebhookResponse, FalErrorPlus> {
let num_images: u8 = match args.num_images {
let req = args.request;
let num_images: u8 = match req.num_images {
EnqueueGptImage1EditImageNumImages::One => 1,
EnqueueGptImage1EditImageNumImages::Two => 2,
EnqueueGptImage1EditImageNumImages::Three => 3,
EnqueueGptImage1EditImageNumImages::Four => 4,
};
let image_size = args.image_size.map(|s| {
let image_size = req.image_size.map(|s| {
match s {
EnqueueGptImage1EditImageSize::Auto => "auto",
EnqueueGptImage1EditImageSize::Square => "1024x1024",
@@ -132,7 +137,7 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
.to_string()
});
let quality = args.quality.map(|q| {
let quality = req.quality.map(|q| {
match q {
EnqueueGptImage1EditImageQuality::Low => "low",
EnqueueGptImage1EditImageQuality::Medium => "medium",
@@ -141,7 +146,7 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
.to_string()
});
let input_fidelity = args.input_fidelity.map(|f| {
let input_fidelity = req.input_fidelity.map(|f| {
match f {
EnqueueGptImage1EditImageInputFidelity::Low => "low",
EnqueueGptImage1EditImageInputFidelity::High => "high",
@@ -149,7 +154,7 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
.to_string()
});
let background = args.background.map(|b| {
let background = req.background.map(|b| {
match b {
EnqueueGptImage1EditImageBackground::Auto => "auto",
EnqueueGptImage1EditImageBackground::Transparent => "transparent",
@@ -158,7 +163,7 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
.to_string()
});
let output_format = args.output_format.map(|f| {
let output_format = req.output_format.map(|f| {
match f {
EnqueueGptImage1EditImageOutputFormat::Jpeg => "jpeg",
EnqueueGptImage1EditImageOutputFormat::Png => "png",
@@ -168,9 +173,9 @@ pub async fn enqueue_gpt_image_1_edit_image_webhook<R: IntoUrl>(
});
let request = GptImage1NonByokEditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
mask_image_url: args.mask_image_url,
prompt: req.prompt,
image_urls: req.image_urls,
mask_image_url: req.mask_image_url,
num_images: Some(num_images),
image_size,
quality,
@@ -193,7 +198,7 @@ mod tests {
use crate::requests::webhook::image::edit::enqueue_gpt_image_1_edit_image_webhook::{
enqueue_gpt_image_1_edit_image_webhook, EnqueueGptImage1EditImageArgs,
EnqueueGptImage1EditImageNumImages, EnqueueGptImage1EditImageQuality,
EnqueueGptImage1EditImageSize,
EnqueueGptImage1EditImageRequest, EnqueueGptImage1EditImageSize,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
@@ -209,19 +214,21 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueGptImage1EditImageArgs {
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
num_images: EnqueueGptImage1EditImageNumImages::One,
mask_image_url: None,
image_size: Some(EnqueueGptImage1EditImageSize::Horizontal),
quality: Some(EnqueueGptImage1EditImageQuality::Medium),
input_fidelity: None,
background: None,
output_format: None,
request: EnqueueGptImage1EditImageRequest {
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
num_images: EnqueueGptImage1EditImageNumImages::One,
mask_image_url: None,
image_size: Some(EnqueueGptImage1EditImageSize::Horizontal),
quality: Some(EnqueueGptImage1EditImageQuality::Medium),
input_fidelity: None,
background: None,
output_format: None,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};
@@ -7,22 +7,27 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueGptImage1p5EditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub request: EnqueueGptImage1p5EditImageRequest,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct EnqueueGptImage1p5EditImageRequest {
// Required
pub prompt: String,
pub image_urls: Vec<String>,
pub num_images: EnqueueGptImage1p5EditImageNumImages,
// Optional args
// Optional
pub mask_image_url: Option<String>,
pub image_size: Option<EnqueueGptImage1p5EditImageSize>,
pub background: Option<EnqueueGptImage1p5EditImageBackground>,
pub quality: Option<EnqueueGptImage1p5EditImageQuality>,
pub input_fidelity: Option<EnqueueGptImage1p5EditImageInputFidelity>,
pub output_format: Option<EnqueueGptImage1p5EditImageOutputFormat>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
@@ -70,8 +75,7 @@ pub enum EnqueueGptImage1p5EditImageOutputFormat {
Webp,
}
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1p5EditImageArgs<'_, U> {
impl FalRequestCostCalculator for EnqueueGptImage1p5EditImageRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
// Your request will cost different amounts based on the number of images, quality, and size.
// For low quality, you will be charged $0.009 for 1024x1024 or $0.013 for any other size per image.
@@ -97,19 +101,19 @@ impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1p5EditImageArgs<'
}
}
pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
args: EnqueueGptImage1p5EditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let num_images = match args.num_images {
let num_images = match req.num_images {
EnqueueGptImage1p5EditImageNumImages::One => 1,
EnqueueGptImage1p5EditImageNumImages::Two => 2,
EnqueueGptImage1p5EditImageNumImages::Three => 3,
EnqueueGptImage1p5EditImageNumImages::Four => 4,
};
let image_size = args.image_size
let image_size = req.image_size
.map(|s| match s {
EnqueueGptImage1p5EditImageSize::Square => "1024x1024",
EnqueueGptImage1p5EditImageSize::Wide => "1536x1024",
@@ -117,7 +121,7 @@ pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
})
.map(|resolution| resolution.to_string());
let background = args.background
let background = req.background
.map(|s| match s {
EnqueueGptImage1p5EditImageBackground::Auto => "auto",
EnqueueGptImage1p5EditImageBackground::Transparent => "transparent",
@@ -125,7 +129,7 @@ pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
})
.map(|aspect_ratio| aspect_ratio.to_string());
let quality = args.quality
let quality = req.quality
.map(|s| match s {
EnqueueGptImage1p5EditImageQuality::Low => "low",
EnqueueGptImage1p5EditImageQuality::Medium => "medium",
@@ -133,14 +137,14 @@ pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
})
.map(|aspect_ratio| aspect_ratio.to_string());
let input_fidelity = args.input_fidelity
let input_fidelity = req.input_fidelity
.map(|s| match s {
EnqueueGptImage1p5EditImageInputFidelity::Low => "low",
EnqueueGptImage1p5EditImageInputFidelity::High => "high",
})
.map(|aspect_ratio| aspect_ratio.to_string());
let output_format = args.output_format
let output_format = req.output_format
.map(|s| match s {
EnqueueGptImage1p5EditImageOutputFormat::Jpeg => "jpeg",
EnqueueGptImage1p5EditImageOutputFormat::Png => "png",
@@ -150,12 +154,12 @@ pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
.unwrap_or_else(|| "png".to_string());
let request = GptImage1p5EditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
prompt: req.prompt,
image_urls: req.image_urls,
num_images: Some(num_images),
output_format: Some(output_format),
// Optionals
mask_image_url: args.mask_image_url,
mask_image_url: req.mask_image_url,
image_size,
background,
quality,
@@ -173,7 +177,10 @@ pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_gpt_image_1p5_edit_image_webhook::{enqueue_gpt_image_1p5_image_edit_webhook, EnqueueGptImage1p5EditImageArgs, EnqueueGptImage1p5EditImageNumImages};
use crate::requests::webhook::image::edit::enqueue_gpt_image_1p5_edit_image_webhook::{
enqueue_gpt_image_1p5_image_edit_webhook, EnqueueGptImage1p5EditImageArgs,
EnqueueGptImage1p5EditImageNumImages, EnqueueGptImage1p5EditImageRequest,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
@@ -187,21 +194,23 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueGptImage1p5EditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: EnqueueGptImage1p5EditImageNumImages::Two,
mask_image_url: None,
image_size: None,
background: None,
quality: None,
input_fidelity: None,
request: EnqueueGptImage1p5EditImageRequest {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
num_images: EnqueueGptImage1p5EditImageNumImages::Two,
mask_image_url: None,
image_size: None,
background: None,
quality: None,
input_fidelity: None,
output_format: None,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
output_format: None,
};
let result = enqueue_gpt_image_1p5_image_edit_webhook(args).await?;
@@ -9,22 +9,27 @@ use crate::requests::webhook::image::edit::enqueue_gpt_image_2_edit_image_webhoo
use crate::requests::webhook::image::edit::enqueue_gpt_image_2_edit_image_webhook::EnqueueGptImage2EditImageSize::SquareHd;
pub struct EnqueueGptImage2EditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub image_urls: Vec<String>,
pub num_images: EnqueueGptImage2EditImageNumImages,
// Optional args
pub mask_url: Option<String>,
pub image_size: Option<EnqueueGptImage2EditImageSize>,
pub quality: Option<EnqueueGptImage2EditImageQuality>,
pub output_format: Option<EnqueueGptImage2EditImageOutputFormat>,
pub request: EnqueueGptImage2EditImageRequest,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct EnqueueGptImage2EditImageRequest {
// Required
pub prompt: String,
pub image_urls: Vec<String>,
pub num_images: EnqueueGptImage2EditImageNumImages,
// Optional
pub mask_url: Option<String>,
pub image_size: Option<EnqueueGptImage2EditImageSize>,
pub quality: Option<EnqueueGptImage2EditImageQuality>,
pub output_format: Option<EnqueueGptImage2EditImageOutputFormat>,
}
#[derive(Copy, Clone, Debug)]
pub enum EnqueueGptImage2EditImageNumImages {
One,
@@ -58,8 +63,7 @@ pub enum EnqueueGptImage2EditImageOutputFormat {
Webp,
}
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage2EditImageArgs<'_, U> {
impl FalRequestCostCalculator for EnqueueGptImage2EditImageRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
// Cost table (per image) by approximate pixel dimensions:
//
@@ -99,19 +103,19 @@ impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage2EditImageArgs<'_,
}
}
pub async fn enqueue_gpt_image_2_edit_image_webhook<R: IntoUrl>(
args: EnqueueGptImage2EditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let num_images = match args.num_images {
let num_images = match req.num_images {
EnqueueGptImage2EditImageNumImages::One => 1,
EnqueueGptImage2EditImageNumImages::Two => 2,
EnqueueGptImage2EditImageNumImages::Three => 3,
EnqueueGptImage2EditImageNumImages::Four => 4,
};
let image_size = args.image_size
let image_size = req.image_size
.map(|s| match s {
EnqueueGptImage2EditImageSize::SquareHd => "square_hd",
EnqueueGptImage2EditImageSize::Square => "square",
@@ -123,7 +127,7 @@ pub async fn enqueue_gpt_image_2_edit_image_webhook<R: IntoUrl>(
})
.map(|size| size.to_string());
let quality = args.quality
let quality = req.quality
.map(|s| match s {
EnqueueGptImage2EditImageQuality::Low => "low",
EnqueueGptImage2EditImageQuality::Medium => "medium",
@@ -131,7 +135,7 @@ pub async fn enqueue_gpt_image_2_edit_image_webhook<R: IntoUrl>(
})
.map(|quality| quality.to_string());
let output_format = args.output_format
let output_format = req.output_format
.map(|s| match s {
EnqueueGptImage2EditImageOutputFormat::Jpeg => "jpeg",
EnqueueGptImage2EditImageOutputFormat::Png => "png",
@@ -141,12 +145,12 @@ pub async fn enqueue_gpt_image_2_edit_image_webhook<R: IntoUrl>(
.unwrap_or_else(|| "png".to_string());
let request = GptImage2EditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
prompt: req.prompt,
image_urls: req.image_urls,
num_images: Some(num_images),
output_format: Some(output_format),
// Optionals
mask_url: args.mask_url,
mask_url: req.mask_url,
image_size,
quality,
};
@@ -162,7 +166,10 @@ pub async fn enqueue_gpt_image_2_edit_image_webhook<R: IntoUrl>(
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_gpt_image_2_edit_image_webhook::{enqueue_gpt_image_2_edit_image_webhook, EnqueueGptImage2EditImageArgs, EnqueueGptImage2EditImageNumImages};
use crate::requests::webhook::image::edit::enqueue_gpt_image_2_edit_image_webhook::{
enqueue_gpt_image_2_edit_image_webhook, EnqueueGptImage2EditImageArgs,
EnqueueGptImage2EditImageNumImages, EnqueueGptImage2EditImageRequest,
};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
@@ -176,19 +183,21 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueGptImage2EditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: EnqueueGptImage2EditImageNumImages::Two,
mask_url: None,
image_size: None,
quality: None,
request: EnqueueGptImage2EditImageRequest {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
num_images: EnqueueGptImage2EditImageNumImages::Two,
mask_url: None,
image_size: None,
quality: None,
output_format: None,
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
output_format: None,
};
let result = enqueue_gpt_image_2_edit_image_webhook(args).await?;
@@ -7,18 +7,20 @@ use crate::requests::api::webhook_response::WebhookResponse;
use reqwest::IntoUrl;
pub struct EnqueueNanoBananaProEditImageArgs<'a, R: IntoUrl> {
// Request required
pub prompt: &'a str,
pub request: EnqueueNanoBananaProEditImageRequest,
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Clone, Debug)]
pub struct EnqueueNanoBananaProEditImageRequest {
pub prompt: String,
pub image_urls: Vec<String>,
pub num_images: EnqueueNanoBananaProEditImageNumImages,
// Optional args
pub resolution: Option<EnqueueNanoBananaProEditImageResolution>,
pub aspect_ratio: Option<EnqueueNanoBananaProEditImageAspectRatio>,
// Fulfillment
pub webhook_url: R,
pub api_key: &'a FalApiKey,
}
#[derive(Copy, Clone, Debug)]
@@ -58,7 +60,7 @@ pub enum EnqueueNanoBananaProEditImageAspectRatio {
}
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueNanoBananaProEditImageArgs<'_, U> {
impl FalRequestCostCalculator for EnqueueNanoBananaProEditImageRequest {
fn calculate_cost_in_cents(&self) -> UsdCents {
// Your request will cost $0.15 per image.
// For $1.00, you can run this model 7 times.
@@ -84,15 +86,16 @@ impl <U: IntoUrl> FalRequestCostCalculator for EnqueueNanoBananaProEditImageArgs
pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
args: EnqueueNanoBananaProEditImageArgs<'_, R>
) -> Result<WebhookResponse, FalErrorPlus> {
let req = args.request;
let num_images = match args.num_images {
let num_images = match req.num_images {
EnqueueNanoBananaProEditImageNumImages::One => 1,
EnqueueNanoBananaProEditImageNumImages::Two => 2,
EnqueueNanoBananaProEditImageNumImages::Three => 3,
EnqueueNanoBananaProEditImageNumImages::Four => 4,
};
let resolution = args.resolution
let resolution = req.resolution
.map(|resolution| match resolution {
EnqueueNanoBananaProEditImageResolution::OneK => "1K",
EnqueueNanoBananaProEditImageResolution::TwoK => "2K",
@@ -100,7 +103,7 @@ pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
})
.map(|resolution| resolution.to_string());
let aspect_ratio = args.aspect_ratio
let aspect_ratio = req.aspect_ratio
.map(|aspect_ratio| match aspect_ratio {
// Auto
EnqueueNanoBananaProEditImageAspectRatio::Auto => "auto",
@@ -121,8 +124,8 @@ pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
.map(|aspect_ratio| aspect_ratio.to_string());
let request = NanoBananaProEditImageInput {
prompt: args.prompt.to_string(),
image_urls: args.image_urls,
prompt: req.prompt,
image_urls: req.image_urls,
num_images: Some(num_images),
// Optionals
aspect_ratio,
@@ -142,7 +145,7 @@ pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
#[cfg(test)]
mod tests {
use crate::creds::fal_api_key::FalApiKey;
use crate::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{enqueue_nano_banana_pro_image_edit_webhook, EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageAspectRatio, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageResolution};
use crate::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{enqueue_nano_banana_pro_image_edit_webhook, EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageAspectRatio, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageRequest, EnqueueNanoBananaProEditImageResolution};
use errors::AnyhowResult;
use std::fs::read_to_string;
use test_data::web::image_urls::{ERNEST_SCARED_STUPID_IMAGE_URL, GHOST_IMAGE_URL, TREX_SKELETON_IMAGE_URL};
@@ -156,15 +159,17 @@ mod tests {
let api_key = FalApiKey::from_str(&secret);
let args = EnqueueNanoBananaProEditImageArgs {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly",
num_images: EnqueueNanoBananaProEditImageNumImages::Two,
aspect_ratio: Some(EnqueueNanoBananaProEditImageAspectRatio::SixteenByNine),
resolution: Some(EnqueueNanoBananaProEditImageResolution::TwoK),
request: EnqueueNanoBananaProEditImageRequest {
image_urls: vec![
GHOST_IMAGE_URL.to_string(),
TREX_SKELETON_IMAGE_URL.to_string(),
ERNEST_SCARED_STUPID_IMAGE_URL.to_string(),
],
prompt: "add the ghost and scared man to the image of the t-rex skeleton, make it look spooky but friendly".to_string(),
num_images: EnqueueNanoBananaProEditImageNumImages::Two,
aspect_ratio: Some(EnqueueNanoBananaProEditImageAspectRatio::SixteenByNine),
resolution: Some(EnqueueNanoBananaProEditImageResolution::TwoK),
},
api_key: &api_key,
webhook_url: "https://example.com/webhook",
};