mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 17:38:10 +00:00
enqueuing to webhook works
This commit is contained in:
1 parent
d730ffb7bd
commit
3f85ef0884
12 files changed
+151
-7
No files matched your search
Generated
+7
@@ -3567,6 +3567,7 @@ dependencies = [
|
||||
"fal-derive",
|
||||
"futures 0.3.31",
|
||||
"image",
|
||||
"percent-encoding-rfc3986",
|
||||
"reqwest 0.12.15",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -7243,6 +7244,12 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding-rfc3986"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3637c05577168127568a64e9dc5a6887da720efef07b3d9472d45f63ab191166"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -15,6 +15,8 @@ pub enum FalErrorPlus {
|
||||
UrlParseError(url::ParseError),
|
||||
/// An endpoint we don't support yet.
|
||||
UnhandledEndpoint(String),
|
||||
/// Error from the `reqwest` crate.
|
||||
ReqwestError(reqwest::Error),
|
||||
}
|
||||
|
||||
impl Display for FalErrorPlus {
|
||||
@@ -25,6 +27,7 @@ impl Display for FalErrorPlus {
|
||||
Self::AnyhowError(err) => write!(f, "FalErrorPlus::AnyhowError: {:?}", err),
|
||||
Self::UrlParseError(err) => write!(f, "FalErrorPlus::UrlParseError: {:?}", err),
|
||||
Self::UnhandledEndpoint(endpoint) => write!(f, "FalErrorPlus::UnhandledEndpoint: {:?}", endpoint),
|
||||
Self::ReqwestError(err) => write!(f, "FalErrorPlus::ReqwestError: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,3 +51,9 @@ impl From<url::ParseError> for FalErrorPlus {
|
||||
FalErrorPlus::UrlParseError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<reqwest::Error> for FalErrorPlus {
|
||||
fn from(err: reqwest::Error) -> Self {
|
||||
FalErrorPlus::ReqwestError(err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod enqueue_hunyuan2_image_to_3d;
|
||||
pub mod image_gen;
|
||||
pub mod remove_background_rembg;
|
||||
pub mod video_gen;
|
||||
pub mod video_gen;
|
||||
pub mod webhook;
|
||||
+1
@@ -4,6 +4,7 @@ use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::imageutils::rembg::{rembg, RemoveBackgroundInput};
|
||||
use fal::prelude::Status;
|
||||
use fal_client::file_to_base64_url::file_to_base64_url;
|
||||
use futures::StreamExt;
|
||||
use std::path::Path;
|
||||
use url::Url;
|
||||
|
||||
|
||||
+27
-5
@@ -2,8 +2,9 @@ use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::imageutils::rembg::{rembg, RemoveBackgroundInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
|
||||
pub (super) async fn rembg_request(image_url: String, api_key: &FalApiKey) -> Result<(), FalErrorPlus> {
|
||||
pub async fn rembg_request(image_url: String, api_key: &FalApiKey) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
let request = RemoveBackgroundInput {
|
||||
image_url,
|
||||
@@ -12,9 +13,8 @@ pub (super) async fn rembg_request(image_url: String, api_key: &FalApiKey) -> Re
|
||||
};
|
||||
|
||||
let result = rembg(request)
|
||||
.with_client()
|
||||
.with_api_key(&api_key.0)
|
||||
.queue()
|
||||
.queue_webhook("https://api.storyteller.ai/webhook")
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
@@ -22,7 +22,29 @@ pub (super) async fn rembg_request(image_url: String, api_key: &FalApiKey) -> Re
|
||||
Err(err) => return Err(classify_fal_error(err)),
|
||||
};
|
||||
|
||||
println!("{:?}", result.payload);
|
||||
println!("{:?}", result);
|
||||
|
||||
Ok(())
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::remove_background_rembg::rembg_request::rembg_request;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // NB: Manually test, don't run in CI!
|
||||
async fn test_rembg_request() -> anyhow::Result<()> {
|
||||
// XXX: Don't commit secrets!
|
||||
let api_key = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
|
||||
let api_key = FalApiKey::from_str(&api_key);
|
||||
|
||||
let response = rembg_request("test_data/juno.jpg".into(), &api_key).await?;
|
||||
|
||||
|
||||
assert_eq!(1, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod remove_background_rembg_webhook;
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::error::classify_fal_error::classify_fal_error;
|
||||
use crate::error::fal_error_plus::FalErrorPlus;
|
||||
use fal::endpoints::fal_ai::imageutils::rembg::{rembg, RemoveBackgroundInput};
|
||||
use fal::webhook::WebhookResponse;
|
||||
use reqwest::IntoUrl;
|
||||
|
||||
pub struct RemoveBackgroundRembgWebhookArgs<'a, U: IntoUrl, V: IntoUrl> {
|
||||
pub image_url: U,
|
||||
pub webhook_url: V,
|
||||
pub api_key: &'a FalApiKey
|
||||
}
|
||||
|
||||
pub async fn remove_background_rembg_webhook<U: IntoUrl, V: IntoUrl>(
|
||||
args: RemoveBackgroundRembgWebhookArgs<'_, U, V>
|
||||
) -> Result<WebhookResponse, FalErrorPlus> {
|
||||
|
||||
let image_url = args.image_url.into_url()?;
|
||||
|
||||
let request = RemoveBackgroundInput {
|
||||
image_url: image_url.to_string(),
|
||||
crop_to_bbox: None,
|
||||
sync_mode: None
|
||||
};
|
||||
|
||||
let result = rembg(request)
|
||||
.with_api_key(&args.api_key.0)
|
||||
.queue_webhook(args.webhook_url)
|
||||
.await;
|
||||
|
||||
result.map_err(|err| classify_fal_error(err))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::creds::fal_api_key::FalApiKey;
|
||||
use crate::requests::webhook::image::remove_background_rembg_webhook::remove_background_rembg_webhook;
|
||||
use crate::requests::webhook::image::remove_background_rembg_webhook::RemoveBackgroundRembgWebhookArgs;
|
||||
use std::fs::read_to_string;
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore] // NB: Manually test, don't run in CI!
|
||||
async fn test_rembg_request() -> anyhow::Result<()> {
|
||||
// XXX: Don't commit secrets!
|
||||
let api_key = read_to_string("/Users/bt/Artcraft/credentials/fal_api_key.txt")?;
|
||||
let api_key = FalApiKey::from_str(&api_key);
|
||||
|
||||
let args = RemoveBackgroundRembgWebhookArgs {
|
||||
image_url: "https://cdn-2.fakeyou.com/media/b/2/p/b/0/b2pb09bcbxdqjzgbnsapvfs1t897wdnx/image_b2pb09bcbxdqjzgbnsapvfs1t897wdnx.png",
|
||||
webhook_url: "https://api.storyteller.ai/webhook",
|
||||
api_key: &api_key,
|
||||
};
|
||||
|
||||
let response = remove_background_rembg_webhook(args).await?;
|
||||
|
||||
println!("{:?}", response);
|
||||
|
||||
assert_eq!(1, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod image;
|
||||
Vendored
+1
@@ -33,6 +33,7 @@ all-features = true
|
||||
eventsource-stream = "0.2"
|
||||
smart-default = "0.7"
|
||||
thiserror = "1"
|
||||
percent-encoding-rfc3986 = "0.1.3"
|
||||
|
||||
[dependencies.base64]
|
||||
version = "0.22"
|
||||
|
||||
Vendored
+1
@@ -7,6 +7,7 @@ pub mod endpoints;
|
||||
pub mod image;
|
||||
pub mod queue;
|
||||
pub mod request;
|
||||
pub mod webhook;
|
||||
|
||||
use eventsource_stream::EventStreamError;
|
||||
pub use fal_derive::endpoint;
|
||||
|
||||
Vendored
+30
-1
@@ -1,11 +1,13 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use percent_encoding_rfc3986::{utf8_percent_encode, NON_ALPHANUMERIC};
|
||||
use reqwest::IntoUrl;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
use crate::{
|
||||
queue::{Queue, QueueResponse},
|
||||
FalError,
|
||||
};
|
||||
use crate::webhook::WebhookResponse;
|
||||
|
||||
/// A request to the FAL API
|
||||
///
|
||||
@@ -129,4 +131,31 @@ impl<Params: Serialize, Response: DeserializeOwned> FalRequest<Params, Response>
|
||||
|
||||
Ok(Queue::new(self.client, self.endpoint, key, payload))
|
||||
}
|
||||
|
||||
pub async fn queue_webhook<U: IntoUrl>(self, url: U) -> Result<WebhookResponse, FalError> {
|
||||
let key = self
|
||||
.api_key
|
||||
.expect("No fal API key provided, and FAL_API_KEY environment variable is not set");
|
||||
|
||||
let url_encoded = url.into_url()?;
|
||||
let url_encoded = utf8_percent_encode(url_encoded.as_str(), NON_ALPHANUMERIC).to_string();
|
||||
|
||||
let response = self
|
||||
.client
|
||||
.post(format!("https://queue.fal.run/{}?fal_webhook={}", self.endpoint, url_encoded))
|
||||
.json(&self.params)
|
||||
.header("Authorization", format!("Key {}", &key))
|
||||
.header("Content-Type", "application/json")
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if response.status() != 200 {
|
||||
let error = response.text().await?;
|
||||
return Err(error.into());
|
||||
}
|
||||
|
||||
let payload: WebhookResponse = response.error_for_status()?.json().await?;
|
||||
|
||||
Ok(payload)
|
||||
}
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
use crate::prelude::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct WebhookResponse {
|
||||
pub status: Option<String>,
|
||||
pub request_id: Option<String>,
|
||||
pub gateway_request_id: Option<String>,
|
||||
}
|
||||
Reference in new issue
Block a user