mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-23 10:09:29 -04:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49249d568f | ||
|
|
6839f18cd2 | ||
|
|
f20d62a4d2 | ||
|
|
dc5d13fe4f | ||
|
|
1b6cf5590e |
+18
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4_edit_image::{bytedance_seedream_v4_edit_image, BytedanceSeedreamV4EditImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -53,6 +54,23 @@ pub enum EnqueueBytedanceSeedreamV4EditImageSize {
|
||||
Auto4k,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueBytedanceSeedreamV4EditImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Your request will cost $0.03 per image.
|
||||
let unit_cost = 3;
|
||||
let cost = match self.num_images {
|
||||
None => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4EditImageNumImages::One) => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4EditImageNumImages::Two) => unit_cost * 2,
|
||||
Some(EnqueueBytedanceSeedreamV4EditImageNumImages::Three) => unit_cost * 3,
|
||||
Some(EnqueueBytedanceSeedreamV4EditImageNumImages::Four) => unit_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_bytedance_seedream_v4_edit_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueBytedanceSeedreamV4EditImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+18
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4p5_edit_image::{bytedance_seedream_v4p5_edit_image, BytedanceSeedreamV4p5EditImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -52,6 +53,23 @@ pub enum EnqueueBytedanceSeedreamV4p5EditImageSize {
|
||||
Auto4k,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueBytedanceSeedreamV4p5EditImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Your request will cost $0.04 per image.
|
||||
let unit_cost = 4;
|
||||
let cost = match self.num_images {
|
||||
None => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::One) => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::Two) => unit_cost * 2,
|
||||
Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::Three) => unit_cost * 3,
|
||||
Some(EnqueueBytedanceSeedreamV4p5EditImageNumImages::Four) => unit_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_bytedance_seedream_v4p5_edit_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueBytedanceSeedreamV4p5EditImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+15
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::gemini_25_flash_image::edit::gemini_25_flash_image_edit;
|
||||
use fal::prelude::fal_ai::gemini_25_flash_image::edit::Gemini25FlashImageEditInput;
|
||||
use fal::webhook::WebhookResponse;
|
||||
@@ -49,6 +50,20 @@ pub enum Gemini25FlashEditAspectRatio {
|
||||
NineBySixteen, // NB: No NineByTwentyOne ?
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for Gemini25FlashEditArgs<'_, U> {
|
||||
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 {
|
||||
Gemini25FlashEditNumImages::One => 4,
|
||||
Gemini25FlashEditNumImages::Two => 8,
|
||||
Gemini25FlashEditNumImages::Three => 12,
|
||||
Gemini25FlashEditNumImages::Four => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gemini_25_flash_edit_webhook<R: IntoUrl>(
|
||||
args: Gemini25FlashEditArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+26
@@ -2,6 +2,7 @@ use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::gpt_image_1::edit_image::byok::{gpt_edit_image, GptEditImageRequest};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -44,6 +45,31 @@ pub enum GptEditImageNumImages{
|
||||
Four,
|
||||
}
|
||||
|
||||
|
||||
// NB: These are BYOK, so they're not Fal's prices
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for GptEditImageByokArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Can't find details, so using this: https://www.reddit.com/r/OpenAI/comments/1krfwa1/pricing_gpt_image_1_model/
|
||||
// Prompts are billed similarly to other GPT models. Image outputs cost approximately $0.01 (low), $0.04 (medium),
|
||||
// and $0.17 (high) for square images.
|
||||
// We're likely losing money on this, but that's okay. Will adjust in the future to be fair to users and us.
|
||||
let base_cost = match self.quality {
|
||||
GptEditImageQuality::Auto => 17,
|
||||
GptEditImageQuality::Low => 1,
|
||||
GptEditImageQuality::Medium => 4,
|
||||
GptEditImageQuality::High => 17,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
GptEditImageNumImages::One => base_cost,
|
||||
GptEditImageNumImages::Two => base_cost * 2,
|
||||
GptEditImageNumImages::Three => base_cost * 3,
|
||||
GptEditImageNumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gpt_image_1_edit_image_webhook<V: IntoUrl>(
|
||||
args: GptEditImageByokArgs<'_, V>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+29
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::gpt_image::gpt_image_1p5_image_edit::{gpt_image_1p5_image_edit, GptImage1p5ImageEditInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -69,6 +70,34 @@ pub enum EnqueueGptImage1p5EditImageOutputFormat {
|
||||
Webp,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1p5EditImageArgs<'_, U> {
|
||||
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.
|
||||
// For medium quality, you will be charged $0.034 for 1024x1024, $0.051 for 1024x1536 and $0.050 for 1536x1024 per image.
|
||||
// For high quality, you will be charged $0.133 for 1024x1024, $0.200 for 1024x1536 or $0.199 for 1536x1024 per image.
|
||||
let use_quality = self.quality.unwrap_or(EnqueueGptImage1p5EditImageQuality::Medium);
|
||||
let use_size = self.image_size.unwrap_or(EnqueueGptImage1p5EditImageSize::Square);
|
||||
let base_cost = match (use_quality, use_size) {
|
||||
(EnqueueGptImage1p5EditImageQuality::Low, EnqueueGptImage1p5EditImageSize::Square) => 1,
|
||||
(EnqueueGptImage1p5EditImageQuality::Low, _) => 1,
|
||||
(EnqueueGptImage1p5EditImageQuality::Medium, EnqueueGptImage1p5EditImageSize::Square) => 3,
|
||||
(EnqueueGptImage1p5EditImageQuality::Medium, _) => 5,
|
||||
(EnqueueGptImage1p5EditImageQuality::High, EnqueueGptImage1p5EditImageSize::Square) => 13,
|
||||
(EnqueueGptImage1p5EditImageQuality::High, _) => 20,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
EnqueueGptImage1p5EditImageNumImages::One => base_cost,
|
||||
EnqueueGptImage1p5EditImageNumImages::Two => base_cost * 2,
|
||||
EnqueueGptImage1p5EditImageNumImages::Three => base_cost * 3,
|
||||
EnqueueGptImage1p5EditImageNumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gpt_image_1p5_image_edit_webhook<R: IntoUrl>(
|
||||
args: EnqueueGptImage1p5EditImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+25
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::nano_banana_pro::nano_banana_pro_image_edit::{nano_banana_pro_image_edit, NanoBananaProImageEditInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -56,6 +57,30 @@ pub enum EnqueueNanoBananaProEditImageAspectRatio {
|
||||
NineBySixteen, // NB: No NineByTwentyOne ?
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueNanoBananaProEditImageArgs<'_, U> {
|
||||
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.
|
||||
// 4K outputs will be charged at double the standard rate.
|
||||
// If web search is used, an additional $0.015 will be charged.
|
||||
// Note: Pricing may change in the future.
|
||||
let cost = match self.resolution {
|
||||
None => 15,
|
||||
Some(EnqueueNanoBananaProEditImageResolution::OneK) => 15,
|
||||
Some(EnqueueNanoBananaProEditImageResolution::TwoK) => 15,
|
||||
Some(EnqueueNanoBananaProEditImageResolution::FourK) => 30,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
EnqueueNanoBananaProEditImageNumImages::One => cost,
|
||||
EnqueueNanoBananaProEditImageNumImages::Two => cost * 2,
|
||||
EnqueueNanoBananaProEditImageNumImages::Three => cost * 3,
|
||||
EnqueueNanoBananaProEditImageNumImages::Four => cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn enqueue_nano_banana_pro_image_edit_webhook<R: IntoUrl>(
|
||||
args: EnqueueNanoBananaProEditImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+18
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::qwen_image_edit::{qwen_image_edit, QwenImageEditInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -45,6 +46,23 @@ pub enum QwenImageEditSize {
|
||||
//Custom { width: u32, height: u32 }, // TODO
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl, R: IntoUrl> FalRequestCostCalculator for QwenImageEditArgs<'_, U, R> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Your request will cost $0.03 per megapixel. -- Ugh, not calculating that
|
||||
let base_cost = 3;
|
||||
let cost = match self.num_images {
|
||||
None => base_cost,
|
||||
Some(QwenImageEditNumImages::One) => base_cost,
|
||||
Some(QwenImageEditNumImages::Two) => base_cost * 2,
|
||||
Some(QwenImageEditNumImages::Three) => base_cost * 3,
|
||||
Some(QwenImageEditNumImages::Four) => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_qwen_image_edit_webhook<U: IntoUrl, R: IntoUrl>(
|
||||
args: QwenImageEditArgs<'_, U, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+17
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::flux_pro::v1_1::{v1_1, FluxProPlusTextToImageInput, ImageSizeProperty};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -33,6 +34,22 @@ pub enum FluxPro11NumImages {
|
||||
Four,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for FluxPro11Args<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Your request will cost $0.04 per megapixel. -- NB: What? Not going to calculate that.
|
||||
let base_cost = 6;
|
||||
let cost = match self.num_images {
|
||||
FluxPro11NumImages::One => base_cost,
|
||||
FluxPro11NumImages::Two => base_cost * 2,
|
||||
FluxPro11NumImages::Three => base_cost * 3,
|
||||
FluxPro11NumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_flux_pro_11_text_to_image_webhook<U: IntoUrl>(
|
||||
args: FluxPro11Args<'_, U>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+17
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::flux_pro::v1_1_ultra::{v1_1_ultra, AspectRatioProperty, FluxProUltraTextToImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -35,6 +36,22 @@ pub enum FluxPro11UltraNumImages {
|
||||
Four,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for FluxPro11UltraArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Your request will cost $0.06 per image.
|
||||
let base_cost = 6;
|
||||
let cost = match self.num_images {
|
||||
FluxPro11UltraNumImages::One => base_cost,
|
||||
FluxPro11UltraNumImages::Two => base_cost * 2,
|
||||
FluxPro11UltraNumImages::Three => base_cost * 3,
|
||||
FluxPro11UltraNumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_flux_pro_11_ultra_text_to_image_webhook<U: IntoUrl>(
|
||||
args: FluxPro11UltraArgs<'_, U>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+26
@@ -2,6 +2,7 @@ use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::prelude::fal_ai::gpt_image_1::edit_image::byok::{gpt_text_to_image, GptTextToImageRequest};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -43,6 +44,31 @@ pub enum GptTextToImageNumImages{
|
||||
Four,
|
||||
}
|
||||
|
||||
|
||||
// NB: These are BYOK, so they're not Fal's prices
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for GptTextToImageByokArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Can't find details, so using this: https://www.reddit.com/r/OpenAI/comments/1krfwa1/pricing_gpt_image_1_model/
|
||||
// Prompts are billed similarly to other GPT models. Image outputs cost approximately $0.01 (low), $0.04 (medium),
|
||||
// and $0.17 (high) for square images.
|
||||
// We're likely losing money on this, but that's okay. Will adjust in the future to be fair to users and us.
|
||||
let base_cost = match self.quality {
|
||||
GptTextToImageQuality::Auto => 17,
|
||||
GptTextToImageQuality::Low => 1,
|
||||
GptTextToImageQuality::Medium => 4,
|
||||
GptTextToImageQuality::High => 17,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
GptTextToImageNumImages::One => base_cost,
|
||||
GptTextToImageNumImages::Two => base_cost * 2,
|
||||
GptTextToImageNumImages::Three => base_cost * 3,
|
||||
GptTextToImageNumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gpt_image_1_text_to_image_webhook<V: IntoUrl>(
|
||||
args: GptTextToImageByokArgs<'_, V>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+19
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4_text_to_image::BytedanceSeedreamV4TextToImageInput;
|
||||
use fal::prelude::fal_ai::bytedance::seedream::bytedance_seedream_v4_text_to_image::bytedance_seedream_v4_text_to_image;
|
||||
use fal::webhook::WebhookResponse;
|
||||
@@ -53,6 +54,24 @@ pub enum EnqueueBytedanceSeedreamV4TextToImageSize {
|
||||
Auto4k,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueBytedanceSeedreamV4TextToImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// Copied from edit image version
|
||||
// Your request will cost $0.03 per image.
|
||||
let unit_cost = 3;
|
||||
let cost = match self.num_images {
|
||||
None => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4TextToImageNumImages::One) => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4TextToImageNumImages::Two) => unit_cost * 2,
|
||||
Some(EnqueueBytedanceSeedreamV4TextToImageNumImages::Three) => unit_cost * 3,
|
||||
Some(EnqueueBytedanceSeedreamV4TextToImageNumImages::Four) => unit_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_bytedance_seedream_v4_text_to_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueBytedanceSeedreamV4TextToImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+20
@@ -4,6 +4,8 @@ use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::bytedance::seedream::bytedance_seedream_v4p5_text_to_image::{bytedance_seedream_v4p5_text_to_image, BytedanceSeedreamV4p5TextToImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use crate::requests::webhook::image::edit::enqueue_bytedance_seedream_v4p5_edit_image_webhook::{EnqueueBytedanceSeedreamV4p5EditImageArgs, EnqueueBytedanceSeedreamV4p5EditImageNumImages};
|
||||
|
||||
pub struct EnqueueBytedanceSeedreamV4p5TextToImageArgs<'a, R: IntoUrl> {
|
||||
// Request required
|
||||
@@ -51,6 +53,24 @@ pub enum EnqueueBytedanceSeedreamV4p5TextToImageSize {
|
||||
Auto4k,
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueBytedanceSeedreamV4p5TextToImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// NB: Copied from edit image costs
|
||||
// Your request will cost $0.04 per image.
|
||||
let unit_cost = 4;
|
||||
let cost = match self.num_images {
|
||||
None => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::One) => unit_cost,
|
||||
Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Two) => unit_cost * 2,
|
||||
Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Three) => unit_cost * 3,
|
||||
Some(EnqueueBytedanceSeedreamV4p5TextToImageNumImages::Four) => unit_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_bytedance_seedream_v4p5_text_to_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueBytedanceSeedreamV4p5TextToImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+17
@@ -5,6 +5,8 @@ use fal::prelude::fal_ai::gemini_25_flash_image::text_to_image::gemini_25_flash_
|
||||
use fal::prelude::fal_ai::gemini_25_flash_image::text_to_image::Gemini25FlashTextToImageInput;
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use crate::requests::webhook::image::edit::enqueue_gemini_25_flash_edit_webhook::{Gemini25FlashEditArgs, Gemini25FlashEditNumImages};
|
||||
|
||||
pub struct Gemini25FlashTextToImageArgs<'a, R: IntoUrl> {
|
||||
// Request required
|
||||
@@ -46,6 +48,21 @@ pub enum Gemini25FlashTextToImageAspectRatio {
|
||||
NineBySixteen, // NB: No NineByTwentyOne ?
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for Gemini25FlashTextToImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// NB: This was copied from the image-to-image case.
|
||||
// Your request will cost $0.039 per image. For $1.00, you can run this model 25 times.
|
||||
match self.num_images {
|
||||
Gemini25FlashTextToImageNumImages::One => 4,
|
||||
Gemini25FlashTextToImageNumImages::Two => 8,
|
||||
Gemini25FlashTextToImageNumImages::Three => 12,
|
||||
Gemini25FlashTextToImageNumImages::Four => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gemini_25_flash_text_to_image_webhook<R: IntoUrl>(
|
||||
args: Gemini25FlashTextToImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+29
@@ -1,6 +1,7 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use fal::endpoints::fal_ai::gpt_image::gpt_image_1p5_text_to_image::{gpt_image_1p5_text_to_image, GptImage1p5TextToImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
@@ -61,6 +62,34 @@ pub enum EnqueueGptImage1p5TextToImageOutputFormat {
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueGptImage1p5TextToImageArgs<'_, U> {
|
||||
fn calculate_cost_in_cents(&self) -> UsdCents {
|
||||
// NB: copied from edit image case - should be correct, but not verified.
|
||||
// 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.
|
||||
// For medium quality, you will be charged $0.034 for 1024x1024, $0.051 for 1024x1536 and $0.050 for 1536x1024 per image.
|
||||
// For high quality, you will be charged $0.133 for 1024x1024, $0.200 for 1024x1536 or $0.199 for 1536x1024 per image.
|
||||
let use_quality = self.quality.unwrap_or(EnqueueGptImage1p5TextToImageQuality::Medium);
|
||||
let use_size = self.image_size.unwrap_or(EnqueueGptImage1p5TextToImageSize::Square);
|
||||
let base_cost = match (use_quality, use_size) {
|
||||
(EnqueueGptImage1p5TextToImageQuality::Low, EnqueueGptImage1p5TextToImageSize::Square) => 1,
|
||||
(EnqueueGptImage1p5TextToImageQuality::Low, _) => 1,
|
||||
(EnqueueGptImage1p5TextToImageQuality::Medium, EnqueueGptImage1p5TextToImageSize::Square) => 3,
|
||||
(EnqueueGptImage1p5TextToImageQuality::Medium, _) => 5,
|
||||
(EnqueueGptImage1p5TextToImageQuality::High, EnqueueGptImage1p5TextToImageSize::Square) => 13,
|
||||
(EnqueueGptImage1p5TextToImageQuality::High, _) => 20,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
EnqueueGptImage1p5TextToImageNumImages::One => base_cost,
|
||||
EnqueueGptImage1p5TextToImageNumImages::Two => base_cost * 2,
|
||||
EnqueueGptImage1p5TextToImageNumImages::Three => base_cost * 3,
|
||||
EnqueueGptImage1p5TextToImageNumImages::Four => base_cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_gpt_image_1p5_text_to_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueGptImage1p5TextToImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+27
@@ -4,6 +4,8 @@ use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::nano_banana_pro::nano_banana_pro_text_to_image::{nano_banana_pro_text_to_image, NanoBananaProTextToImageInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
use crate::requests::traits::fal_request_cost_calculator_trait::{FalRequestCostCalculator, UsdCents};
|
||||
use crate::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageResolution};
|
||||
|
||||
pub struct EnqueueNanoBananaProTextToImageArgs<'a, R: IntoUrl> {
|
||||
// Request required
|
||||
@@ -53,6 +55,31 @@ pub enum EnqueueNanoBananaProTextToImageAspectRatio {
|
||||
NineBySixteen, // NB: No NineByTwentyOne ?
|
||||
}
|
||||
|
||||
|
||||
impl <U: IntoUrl> FalRequestCostCalculator for EnqueueNanoBananaProTextToImageArgs<'_, U> {
|
||||
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.
|
||||
// 4K outputs will be charged at double the standard rate.
|
||||
// If web search is used, an additional $0.015 will be charged.
|
||||
// Note: Pricing may change in the future.
|
||||
let cost = match self.resolution {
|
||||
None => 15,
|
||||
Some(EnqueueNanoBananaProTextToImageResolution::OneK) => 15,
|
||||
Some(EnqueueNanoBananaProTextToImageResolution::TwoK) => 15,
|
||||
Some(EnqueueNanoBananaProTextToImageResolution::FourK) => 30,
|
||||
};
|
||||
let cost = match self.num_images {
|
||||
EnqueueNanoBananaProTextToImageNumImages::One => cost,
|
||||
EnqueueNanoBananaProTextToImageNumImages::Two => cost * 2,
|
||||
EnqueueNanoBananaProTextToImageNumImages::Three => cost * 3,
|
||||
EnqueueNanoBananaProTextToImageNumImages::Four => cost * 4,
|
||||
};
|
||||
cost as UsdCents
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn enqueue_nano_banana_pro_text_to_image_webhook<R: IntoUrl>(
|
||||
args: EnqueueNanoBananaProTextToImageArgs<'_, R>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
+39
-32
@@ -34,6 +34,10 @@ use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPrompt
|
||||
use mysql_queries::queries::users::user_subscriptions::find_subscription_for_owner_user::find_subscription_for_owner_user_using_connection;
|
||||
use sqlx::Acquire;
|
||||
use utoipa::ToSchema;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
|
||||
/// Gemini 2.5 Flash Image Editing
|
||||
#[utoipa::path(
|
||||
@@ -73,43 +77,34 @@ pub async fn gemini_25_flash_edit_image_handler(
|
||||
CommonWebError::ServerError
|
||||
})?;
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
|
||||
let maybe_avt_token = server_state
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +189,17 @@ pub async fn gemini_25_flash_edit_image_handler(
|
||||
aspect_ratio: None, // TODO
|
||||
};
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
//let cost = args.calculate_cost_in_cents();
|
||||
//info!("Charging wallet: {}", cost);
|
||||
//attempt_wallet_deduction_else_common_web_error(
|
||||
// user_token,
|
||||
// Some(apriori_job_token.as_str()),
|
||||
// cost,
|
||||
// &mut mysql_connection,
|
||||
//).await?;
|
||||
|
||||
let fal_result = enqueue_gemini_25_flash_edit_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -223,7 +229,7 @@ pub async fn gemini_25_flash_edit_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::Gemini25Flash),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -260,13 +266,14 @@ pub async fn gemini_25_flash_edit_image_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+42
-32
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -18,6 +19,7 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use enums::common::stripe_subscription_status::StripeSubscriptionStatus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_gpt_image_1_edit_image_webhook::enqueue_gpt_image_1_edit_image_webhook;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_gpt_image_1_edit_image_webhook::GptEditImageNumImages;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_gpt_image_1_edit_image_webhook::{GptEditImageByokArgs, GptEditImageQuality, GptEditImageSize};
|
||||
@@ -32,7 +34,9 @@ use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_it
|
||||
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
|
||||
use mysql_queries::queries::users::user_subscriptions::find_subscription_for_owner_user::find_subscription_for_owner_user_using_connection;
|
||||
use sqlx::Acquire;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::ToSchema;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
|
||||
/// Gpt Image 1 Image Editing
|
||||
#[utoipa::path(
|
||||
@@ -75,39 +79,31 @@ pub async fn gpt_image_1_edit_image_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
&user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
&user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +209,19 @@ pub async fn gpt_image_1_edit_image_handler(
|
||||
openai_api_key: &openai_api_key,
|
||||
};
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
let fal_result = enqueue_gpt_image_1_edit_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -242,7 +251,7 @@ pub async fn gpt_image_1_edit_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::GptImage1),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -279,13 +288,14 @@ pub async fn gpt_image_1_edit_image_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+27
-14
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -16,17 +17,20 @@ use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_qwen_image_edit_webhook::{enqueue_qwen_image_edit_webhook, QwenImageEditArgs, QwenImageEditNumImages};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
|
||||
use sqlx::Acquire;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Qwen Image Editing
|
||||
@@ -66,15 +70,12 @@ pub async fn qwen_edit_image_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&request.uuid_idempotency_token) {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
@@ -135,6 +136,8 @@ pub async fn qwen_edit_image_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let num_images = match request.num_images {
|
||||
Some(QwenEditImageNumImages::One) => QwenImageEditNumImages::One,
|
||||
Some(QwenEditImageNumImages::Two) => QwenImageEditNumImages::Two,
|
||||
@@ -160,6 +163,17 @@ pub async fn qwen_edit_image_handler(
|
||||
acceleration: acceleration.map(|s| s.to_string()),
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
let fal_result = enqueue_qwen_image_edit_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -189,9 +203,7 @@ pub async fn qwen_edit_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::Qwen),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -228,13 +240,14 @@ pub async fn qwen_edit_image_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+22
-39
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::billing::wallets::temporary_test_wallet_deduction::temporary_test_wallet_deduction;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -14,6 +15,7 @@ use enums::by_table::prompts::prompt_type::PromptType;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::enqueue_flux_pro_11_text_to_image_webhook::FluxPro11Args;
|
||||
use fal_client::requests::webhook::image::enqueue_flux_pro_11_text_to_image_webhook::{enqueue_flux_pro_11_text_to_image_webhook, FluxPro11AspectRatio, FluxPro11NumImages};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -21,9 +23,11 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
|
||||
use sqlx::Acquire;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Flux Pro 1.1
|
||||
@@ -70,16 +74,6 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(GenerateFluxProUltraTextToImageError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&request.uuid_idempotency_token) {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
}
|
||||
@@ -91,33 +85,12 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
CommonWebError::BadInputWithSimpleMessage("invalid idempotency token".to_string())
|
||||
})?;
|
||||
|
||||
|
||||
//// TODO: This is test code
|
||||
//let credits = match request.num_images {
|
||||
// Some(GenerateFluxPro11TextToImageNumImages::One) => 25,
|
||||
// Some(GenerateFluxPro11TextToImageNumImages::Two) => 50,
|
||||
// Some(GenerateFluxPro11TextToImageNumImages::Three) => 75,
|
||||
// Some(GenerateFluxPro11TextToImageNumImages::Four) => 100,
|
||||
// None => 100,
|
||||
//};
|
||||
|
||||
//// TODO: This is test code
|
||||
//let result = temporary_test_wallet_deduction(
|
||||
// user_token,
|
||||
// Some("todo-reference-token"),
|
||||
// credits,
|
||||
// &mut mysql_connection,
|
||||
//).await;
|
||||
|
||||
//// TODO: This is test code
|
||||
//if let Err(err) = result {
|
||||
// warn!("Temporary wallet deduction failed: {:?}", err); // Infallible for now.
|
||||
//}
|
||||
|
||||
const IS_MOD : bool = false;
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let aspect_ratio = match request.aspect_ratio {
|
||||
Some(GenerateFluxPro11TextToImageAspectRatio::Square) => FluxPro11AspectRatio::Square,
|
||||
Some(GenerateFluxPro11TextToImageAspectRatio::LandscapeFourByThree) => FluxPro11AspectRatio::LandscapeFourByThree,
|
||||
@@ -143,6 +116,17 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
num_images,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
let fal_result = enqueue_flux_pro_11_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -172,9 +156,7 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::FluxPro11),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -193,13 +175,14 @@ pub async fn generate_flux_pro_11_text_to_image_handler(
|
||||
}
|
||||
};
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+22
-38
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::billing::wallets::temporary_test_wallet_deduction::temporary_test_wallet_deduction;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -14,6 +15,7 @@ use enums::by_table::prompts::prompt_type::PromptType;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::enqueue_flux_pro_11_ultra_text_to_image_webhook::FluxPro11UltraArgs;
|
||||
use fal_client::requests::webhook::image::enqueue_flux_pro_11_ultra_text_to_image_webhook::{enqueue_flux_pro_11_ultra_text_to_image_webhook, FluxPro11UltraAspectRatio, FluxPro11UltraNumImages};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -21,9 +23,11 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
|
||||
use sqlx::Acquire;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Flux Pro 1.1 Ultra
|
||||
@@ -70,16 +74,6 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(GenerateFluxProUltraTextToImageError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&request.uuid_idempotency_token) {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
}
|
||||
@@ -91,32 +85,12 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
CommonWebError::BadInputWithSimpleMessage("invalid idempotency token".to_string())
|
||||
})?;
|
||||
|
||||
// // TODO: This is test code
|
||||
// let credits = match request.num_images {
|
||||
// Some(GenerateFluxPro11UltraTextToImageNumImages::One) => 25,
|
||||
// Some(GenerateFluxPro11UltraTextToImageNumImages::Two) => 50,
|
||||
// Some(GenerateFluxPro11UltraTextToImageNumImages::Three) => 75,
|
||||
// Some(GenerateFluxPro11UltraTextToImageNumImages::Four) => 100,
|
||||
// None => 100,
|
||||
// };
|
||||
|
||||
// // TODO: This is test code
|
||||
// let result = temporary_test_wallet_deduction(
|
||||
// user_token,
|
||||
// Some("todo-reference-token"),
|
||||
// credits,
|
||||
// &mut mysql_connection,
|
||||
// ).await;
|
||||
|
||||
// // TODO: This is test code
|
||||
// if let Err(err) = result {
|
||||
// warn!("Temporary wallet deduction failed: {:?}", err); // Infallible for now.
|
||||
// }
|
||||
|
||||
const IS_MOD : bool = false;
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let aspect_ratio = match request.aspect_ratio {
|
||||
Some(GenerateFluxPro11UltraTextToImageAspectRatio::Square) => FluxPro11UltraAspectRatio::Square,
|
||||
Some(GenerateFluxPro11UltraTextToImageAspectRatio::LandscapeFourByThree) => FluxPro11UltraAspectRatio::LandscapeFourByThree,
|
||||
@@ -146,6 +120,17 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
num_images,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
let fal_result = enqueue_flux_pro_11_ultra_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -175,9 +160,7 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::FluxPro11Ultra),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -196,13 +179,14 @@ pub async fn generate_flux_pro_11_ultra_text_to_image_handler(
|
||||
}
|
||||
};
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+43
-33
@@ -1,5 +1,6 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -18,18 +19,21 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use enums::common::stripe_subscription_status::StripeSubscriptionStatus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::enqueue_gpt_image_1_text_to_image_webhook::{enqueue_gpt_image_1_text_to_image_webhook, GptTextToImageByokArgs, GptTextToImageNumImages, GptTextToImageQuality, GptTextToImageSize};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPromptArgs};
|
||||
use mysql_queries::queries::users::user_subscriptions::find_subscription_for_owner_user::find_subscription_for_owner_user_using_connection;
|
||||
use sqlx::Acquire;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Gpt Image 1
|
||||
@@ -73,39 +77,31 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
&user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
&user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +148,7 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
if downgrade_for_free_user {
|
||||
num_images = GptTextToImageNumImages::One;
|
||||
}
|
||||
|
||||
|
||||
let openai_api_key = OpenAiApiKey::from_str(&server_state.openai.api_key);
|
||||
|
||||
let args = GptTextToImageByokArgs {
|
||||
@@ -165,6 +161,19 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
openai_api_key: &openai_api_key,
|
||||
};
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
let fal_result = enqueue_gpt_image_1_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -194,7 +203,7 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::GptImage1),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -213,13 +222,14 @@ pub async fn generate_gpt_image_1_text_to_image_handler(
|
||||
}
|
||||
};
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+38
-14
@@ -2,6 +2,7 @@ use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -19,6 +20,7 @@ use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_bytedance_seedream_v4_edit_image_webhook::{enqueue_bytedance_seedream_v4_edit_image_webhook, EnqueueBytedanceSeedreamV4EditImageArgs, EnqueueBytedanceSeedreamV4EditImageNumImages, EnqueueBytedanceSeedreamV4EditImageSize};
|
||||
use fal_client::requests::webhook::image::text::enqueue_bytedance_seedream_v4_text_to_image_webhook::{enqueue_bytedance_seedream_v4_text_to_image_webhook, EnqueueBytedanceSeedreamV4TextToImageArgs, EnqueueBytedanceSeedreamV4TextToImageNumImages, EnqueueBytedanceSeedreamV4TextToImageSize};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -26,6 +28,7 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
@@ -33,6 +36,7 @@ use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPrompt
|
||||
use server_environment::ServerEnvironment;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{Acquire, MySql};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -73,15 +77,12 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&request.uuid_idempotency_token) {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
@@ -109,6 +110,8 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let fal_result;
|
||||
|
||||
if let Some(input_image_urls) = image_urls.as_deref() {
|
||||
@@ -149,6 +152,17 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_bytedance_seedream_v4_edit_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -193,6 +207,17 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_bytedance_seedream_v4_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -223,9 +248,7 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::Seedream4),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -264,13 +287,14 @@ pub async fn bytedance_seedream_v4_multi_function_image_gen_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+38
-14
@@ -2,6 +2,7 @@ use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -19,6 +20,7 @@ use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_bytedance_seedream_v4p5_edit_image_webhook::{enqueue_bytedance_seedream_v4p5_edit_image_webhook, EnqueueBytedanceSeedreamV4p5EditImageArgs, EnqueueBytedanceSeedreamV4p5EditImageNumImages, EnqueueBytedanceSeedreamV4p5EditImageSize};
|
||||
use fal_client::requests::webhook::image::text::enqueue_bytedance_seedream_v4p5_text_to_image_webhook::{enqueue_bytedance_seedream_v4p5_text_to_image_webhook, EnqueueBytedanceSeedreamV4p5TextToImageArgs, EnqueueBytedanceSeedreamV4p5TextToImageNumImages, EnqueueBytedanceSeedreamV4p5TextToImageSize};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -26,6 +28,7 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
@@ -33,6 +36,7 @@ use mysql_queries::queries::prompts::insert_prompt::{insert_prompt, InsertPrompt
|
||||
use server_environment::ServerEnvironment;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{Acquire, MySql};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -73,15 +77,12 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(reason) = validate_idempotency_token_format(&request.uuid_idempotency_token) {
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
@@ -109,6 +110,8 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let fal_result;
|
||||
|
||||
if let Some(input_image_urls) = image_urls.as_deref() {
|
||||
@@ -148,6 +151,17 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_bytedance_seedream_v4p5_edit_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -191,6 +205,17 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_bytedance_seedream_v4p5_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -221,9 +246,7 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::Seedream4p5),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -262,13 +285,14 @@ pub async fn bytedance_seedream_v4p5_multi_function_image_gen_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_session.as_ref().map(|s| &s.user_token),
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+53
-32
@@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -21,6 +22,7 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use enums::common::stripe_subscription_status::StripeSubscriptionStatus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_gpt_image_1p5_edit_image_webhook::{enqueue_gpt_image_1p5_image_edit_webhook, EnqueueGptImage1p5EditImageArgs, EnqueueGptImage1p5EditImageBackground, EnqueueGptImage1p5EditImageInputFidelity, EnqueueGptImage1p5EditImageNumImages, EnqueueGptImage1p5EditImageQuality, EnqueueGptImage1p5EditImageSize};
|
||||
use fal_client::requests::webhook::image::text::enqueue_gpt_image_1p5_text_to_image_webhook::{enqueue_gpt_image_1p5_text_to_image_webhook, EnqueueGptImage1p5TextToImageArgs, EnqueueGptImage1p5TextToImageBackground, EnqueueGptImage1p5TextToImageNumImages, EnqueueGptImage1p5TextToImageQuality, EnqueueGptImage1p5TextToImageSize};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -28,6 +30,7 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
@@ -36,6 +39,7 @@ use mysql_queries::queries::users::user_subscriptions::find_subscription_for_own
|
||||
use server_environment::ServerEnvironment;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{Acquire, MySql};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -80,39 +84,31 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +170,8 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let fal_result;
|
||||
|
||||
if let Some(input_image_urls) = maybe_image_urls.as_deref() {
|
||||
@@ -232,6 +230,17 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_gpt_image_1p5_image_edit_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -286,6 +295,17 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_gpt_image_1p5_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -316,7 +336,7 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::GptImage1p5),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -355,13 +375,14 @@ pub async fn gpt_image_1p5_multi_function_image_gen_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+53
-32
@@ -2,6 +2,7 @@ use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -22,6 +23,7 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use enums::common::stripe_subscription_status::StripeSubscriptionStatus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_gemini_25_flash_edit_webhook::{enqueue_gemini_25_flash_edit_webhook, Gemini25FlashEditArgs, Gemini25FlashEditAspectRatio, Gemini25FlashEditNumImages};
|
||||
use fal_client::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{enqueue_nano_banana_pro_image_edit_webhook, EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageAspectRatio, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageResolution};
|
||||
use fal_client::requests::webhook::image::text::enqueue_gemini_25_flash_text_to_image_webhook::{enqueue_gemini_25_flash_text_to_image_webhook, Gemini25FlashTextToImageArgs, Gemini25FlashTextToImageAspectRatio, Gemini25FlashTextToImageNumImages};
|
||||
@@ -31,6 +33,7 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
@@ -39,6 +42,7 @@ use mysql_queries::queries::users::user_subscriptions::find_subscription_for_own
|
||||
use server_environment::ServerEnvironment;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{Acquire, MySql};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -83,39 +87,31 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +139,8 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let fal_result;
|
||||
|
||||
if let Some(input_image_urls) = image_urls.as_deref() {
|
||||
@@ -184,6 +182,17 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_gemini_25_flash_edit_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -229,6 +238,17 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_gemini_25_flash_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -259,7 +279,7 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::NanoBanana),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -298,13 +318,14 @@ pub async fn nano_banana_multi_function_image_gen_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
+54
-33
@@ -2,6 +2,7 @@ use std::collections::HashSet;
|
||||
use std::iter::FromIterator;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::billing::wallets::attempt_wallet_deduction::attempt_wallet_deduction_else_common_web_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::endpoints::generate::common::payments_error_test::payments_error_test;
|
||||
@@ -21,6 +22,7 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use enums::common::stripe_subscription_status::StripeSubscriptionStatus;
|
||||
use enums::common::visibility::Visibility;
|
||||
use fal_client::creds::open_ai_api_key::OpenAiApiKey;
|
||||
use fal_client::requests::traits::fal_request_cost_calculator_trait::FalRequestCostCalculator;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::{enqueue_nano_banana_pro_image_edit_webhook, EnqueueNanoBananaProEditImageArgs, EnqueueNanoBananaProEditImageAspectRatio, EnqueueNanoBananaProEditImageNumImages, EnqueueNanoBananaProEditImageResolution};
|
||||
use fal_client::requests::webhook::image::text::enqueue_nano_banana_pro_text_to_image_webhook::{enqueue_nano_banana_pro_text_to_image_webhook, EnqueueNanoBananaProTextToImageArgs, EnqueueNanoBananaProTextToImageAspectRatio, EnqueueNanoBananaProTextToImageNumImages, EnqueueNanoBananaProTextToImageResolution};
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -28,6 +30,7 @@ use log::{error, info, warn};
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::insert_generic_inference_job_for_fal_queue;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::FalCategory;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue::InsertGenericInferenceForFalArgs;
|
||||
use mysql_queries::queries::generic_inference::fal::insert_generic_inference_job_for_fal_queue_with_apriori_job_token::{insert_generic_inference_job_for_fal_queue_with_apriori_job_token, InsertGenericInferenceForFalWithAprioriJobTokenArgs};
|
||||
use mysql_queries::queries::idepotency_tokens::insert_idempotency_token::insert_idempotency_token;
|
||||
use mysql_queries::queries::media_files::get::batch_get_media_files_by_tokens::{batch_get_media_files_by_tokens, batch_get_media_files_by_tokens_with_connection};
|
||||
use mysql_queries::queries::prompt_context_items::insert_batch_prompt_context_items::{insert_batch_prompt_context_items, InsertBatchArgs, PromptContextItem};
|
||||
@@ -36,6 +39,7 @@ use mysql_queries::queries::users::user_subscriptions::find_subscription_for_own
|
||||
use server_environment::ServerEnvironment;
|
||||
use sqlx::pool::PoolConnection;
|
||||
use sqlx::{Acquire, MySql};
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
@@ -80,42 +84,34 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
.avt_cookie_manager
|
||||
.get_avt_token_from_request(&http_request);
|
||||
|
||||
let maybe_user_token = maybe_user_session
|
||||
.as_ref()
|
||||
.map(|s| &s.user_token);
|
||||
|
||||
// TODO: Limit usage for new accounts. Billing, free credits metering, etc.
|
||||
|
||||
//let user_session = match maybe_user_session {
|
||||
// Some(session) => session,
|
||||
// None => {
|
||||
// warn!("not logged in");
|
||||
// return Err(CommonWebError::NotAuthorized);
|
||||
// }
|
||||
//};
|
||||
let user_token = match maybe_user_session.as_ref() {
|
||||
Some(session) => &session.user_token,
|
||||
None => {
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
let mut downgrade_for_free_user = true;
|
||||
|
||||
if let Some(user_token) = maybe_user_token.as_ref() {
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
let result = find_subscription_for_owner_user_using_connection(
|
||||
user_token,
|
||||
PaymentsNamespace::Artcraft,
|
||||
&mut mysql_connection,
|
||||
).await;
|
||||
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
if let Ok(Some(subscription)) = result {
|
||||
info!("User {:?} has subscription: {:?} (stripe customer: {:?}, status: {:?})",
|
||||
user_token,
|
||||
subscription.token,
|
||||
subscription.stripe_customer_id,
|
||||
subscription.stripe_subscription_status);
|
||||
|
||||
// NB: Failing open means subscribers might get fewer results, but they're free right now.
|
||||
if subscription.stripe_subscription_status == StripeSubscriptionStatus::Active {
|
||||
downgrade_for_free_user = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
info!("downgrade_for_free_user: {}", downgrade_for_free_user);
|
||||
|
||||
let image_urls = match request.image_media_tokens.as_ref() {
|
||||
@@ -140,6 +136,8 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
|
||||
info!("Fal webhook URL: {}", server_state.fal.webhook_url);
|
||||
|
||||
let apriori_job_token = InferenceJobToken::generate();
|
||||
|
||||
let fal_result;
|
||||
|
||||
if let Some(input_image_urls) = image_urls.as_deref() {
|
||||
@@ -190,6 +188,17 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_nano_banana_pro_image_edit_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -244,6 +253,17 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
api_key: &server_state.fal.api_key,
|
||||
};
|
||||
|
||||
let cost = args.calculate_cost_in_cents();
|
||||
|
||||
info!("Charging wallet: {}", cost);
|
||||
|
||||
attempt_wallet_deduction_else_common_web_error(
|
||||
user_token,
|
||||
Some(apriori_job_token.as_str()),
|
||||
cost,
|
||||
&mut mysql_connection,
|
||||
).await?;
|
||||
|
||||
fal_result = enqueue_nano_banana_pro_text_to_image_webhook(args)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
@@ -274,7 +294,7 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
let prompt_result = insert_prompt(InsertPromptArgs {
|
||||
maybe_apriori_prompt_token: None,
|
||||
prompt_type: PromptType::ArtcraftApp,
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_model_type: Some(ModelType::NanoBananaPro),
|
||||
maybe_generation_provider: Some(GenerationProvider::Artcraft),
|
||||
maybe_positive_prompt: request.prompt.as_deref(),
|
||||
@@ -313,13 +333,14 @@ pub async fn nano_banana_pro_multi_function_image_gen_handler(
|
||||
}
|
||||
}
|
||||
|
||||
let db_result = insert_generic_inference_job_for_fal_queue(InsertGenericInferenceForFalArgs {
|
||||
let db_result = insert_generic_inference_job_for_fal_queue_with_apriori_job_token(InsertGenericInferenceForFalWithAprioriJobTokenArgs {
|
||||
apriori_job_token: &apriori_job_token,
|
||||
uuid_idempotency_token: &request.uuid_idempotency_token,
|
||||
maybe_external_third_party_id: &external_job_id,
|
||||
fal_category: FalCategory::ImageGeneration,
|
||||
maybe_inference_args: None,
|
||||
maybe_prompt_token: prompt_token.as_ref(),
|
||||
maybe_creator_user_token: maybe_user_token,
|
||||
maybe_creator_user_token: Some(&user_token),
|
||||
maybe_avt_token: maybe_avt_token.as_ref(),
|
||||
creator_ip_address: &ip_address,
|
||||
creator_set_visibility: Visibility::Public,
|
||||
|
||||
Reference in New Issue
Block a user