diff --git a/crates/comfyui-api/Cargo.toml b/crates/comfyui-api/Cargo.toml index 55a00c9..03e2c47 100644 --- a/crates/comfyui-api/Cargo.toml +++ b/crates/comfyui-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "comfyui-api" version = "0.2.1" -edition = "2021" +edition = "2024" description = "Stable Diffusion ComfyUI API wrapper" readme = "README.md" license = "MIT" diff --git a/crates/comfyui-api/src/api/mod.rs b/crates/comfyui-api/src/api/mod.rs index 0b6f070..9928088 100644 --- a/crates/comfyui-api/src/api/mod.rs +++ b/crates/comfyui-api/src/api/mod.rs @@ -84,6 +84,11 @@ impl Api { }) } + /// Returns the client id. + pub fn client_id(&self) -> uuid::Uuid { + self.client_id + } + /// Returns a new `Api` instance with the given `reqwest::Client` and URL as a string value. /// /// # Arguments diff --git a/crates/comfyui-api/src/api/websocket.rs b/crates/comfyui-api/src/api/websocket.rs index 23e67e6..a52b622 100644 --- a/crates/comfyui-api/src/api/websocket.rs +++ b/crates/comfyui-api/src/api/websocket.rs @@ -14,13 +14,13 @@ pub enum WebSocketApiError { ParseError(#[from] url::ParseError), /// Error parsing endpoint URL #[error("Failed to parse endpoint URL")] - ConnectFailed(#[from] tokio_tungstenite::tungstenite::Error), + ConnectFailed(#[from] Box), /// An error occurred while parsing the response from the API. #[error("Parsing response failed")] InvalidResponse(#[from] serde_json::Error), /// An error occurred while reading websocket message. #[error("Error occurred while reading websocket message")] - ReadFailed(#[source] tokio_tungstenite::tungstenite::Error), + ReadFailed(#[source] Box), } type Result = std::result::Result; @@ -65,7 +65,7 @@ impl WebsocketApi { &self, endpoint: &Url, ) -> Result>> { - let (connection, _) = connect_async(endpoint).await?; + let (connection, _) = connect_async(endpoint).await.map_err(Box::new)?; Ok(connection.filter_map(|m| async { match m { Ok(m) => match m { @@ -82,7 +82,7 @@ impl WebsocketApi { None } }, - Err(e) => Some(Err(WebSocketApiError::ReadFailed(e))), + Err(e) => Some(Err(WebSocketApiError::ReadFailed(Box::new(e)))), } })) } @@ -106,7 +106,7 @@ impl WebsocketApi { /// # Returns /// /// A `Stream` of `Update` values. These contain progress updates for a task. - pub async fn updates(&self) -> Result>> { + pub async fn updates(&self) -> Result> + use<'_>> { Ok(self.connect_impl().await?.filter_map(|m| async { match m { Ok(PreviewOrUpdate::Update(u)) => Some(Ok(u)), diff --git a/crates/comfyui-api/src/comfy/mod.rs b/crates/comfyui-api/src/comfy/mod.rs index 3173776..4d02eac 100644 --- a/crates/comfyui-api/src/comfy/mod.rs +++ b/crates/comfyui-api/src/comfy/mod.rs @@ -49,7 +49,9 @@ pub enum ComfyApiError { CreateApiFailed(#[from] api::ApiError), /// Execution was interrupted #[error("Execution was interrupted: node {} ({})", response.node_id, response.node_type)] - ExecutionInterrupted { response: ExecutionInterrupted }, + ExecutionInterrupted { + response: Box, + }, /// Error occurred during execution #[error("Error occurred during execution: {exception_type}: {exception_message}")] ExecutionError { @@ -82,15 +84,20 @@ pub struct Comfy { history: HistoryApi, upload: UploadApi, view: ViewApi, + websocket: WebsocketApi, } impl Default for Comfy { fn default() -> Self { + let client_id = Uuid::new_v4(); let api = Api::default(); Self { history: api.history().expect("failed to create history api"), upload: api.upload().expect("failed to create upload api"), view: api.view().expect("failed to create view api"), + websocket: api + .websocket_with_client(client_id) + .expect("failed to create websocket api"), api, } } @@ -99,11 +106,13 @@ impl Default for Comfy { impl Comfy { /// Returns a new `Comfy` instance with default settings. pub fn new() -> Result { + let client_id = Uuid::new_v4(); let api = Api::default(); Ok(Self { history: api.history()?, upload: api.upload()?, view: api.view()?, + websocket: api.websocket_with_client(client_id)?, api, }) } @@ -121,11 +130,13 @@ impl Comfy { where S: AsRef, { + let client_id = Uuid::new_v4(); let api = Api::new_with_url(url.as_ref())?; Ok(Self { history: api.history()?, upload: api.upload()?, view: api.view()?, + websocket: api.websocket_with_client(client_id)?, api, }) } @@ -144,11 +155,13 @@ impl Comfy { where S: AsRef, { + let client_id = Uuid::new_v4(); let api = Api::new_with_client_and_url(client, url.as_ref())?; Ok(Self { history: api.history()?, upload: api.upload()?, view: api.view()?, + websocket: api.websocket_with_client(client_id)?, api, }) } @@ -193,7 +206,9 @@ impl Comfy { if data.prompt_id != target_prompt_id { return Ok(None); } - Err(ComfyApiError::ExecutionInterrupted { response: data }) + Err(ComfyApiError::ExecutionInterrupted { + response: Box::new(data), + }) } Update::ExecutionError(data) => { if data.execution_status.prompt_id != target_prompt_id { @@ -212,25 +227,24 @@ impl Comfy { &'a self, prompt: &Prompt, ) -> Result> + 'a> { - let client_id = Uuid::new_v4(); - let prompt_api = self.api.prompt_with_client(client_id)?; - let websocket_api = self.api.websocket_with_client(client_id)?; - let stream = websocket_api - .updates() - .await - .map_err(ComfyApiError::ReceiveUpdateFailure)?; + let prompt_api = self.api.prompt_with_client(self.api.client_id())?; let response = prompt_api.send(prompt).await?; let prompt_id = response.prompt_id; - Ok(stream.filter_map(move |msg| async move { - match msg { - Ok(msg) => match self.filter_update(msg, prompt_id).await { - Ok(Some(images)) => Some(Ok(images)), - Ok(None) => None, - Err(e) => Some(Err(e)), - }, - Err(e) => Some(Err(ComfyApiError::ReceiveUpdateFailure(e))), - } - })) + Ok(self + .websocket + .updates() + .await + .map_err(ComfyApiError::ReceiveUpdateFailure)? + .filter_map(move |msg| async move { + match msg { + Ok(msg) => match self.filter_update(msg, prompt_id).await { + Ok(Some(images)) => Some(Ok(images)), + Ok(None) => None, + Err(e) => Some(Err(e)), + }, + Err(e) => Some(Err(ComfyApiError::ReceiveUpdateFailure(e))), + } + })) } /// Executes a prompt and returns a stream of generated images. diff --git a/crates/sal-e-api/Cargo.toml b/crates/sal-e-api/Cargo.toml index 95cb0d4..a716e09 100644 --- a/crates/sal-e-api/Cargo.toml +++ b/crates/sal-e-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sal-e-api" version = "0.2.1" -edition = "2021" +edition = "2024" description = "Stable-Diffusion Abstraction Layer" readme = "README.md" license = "MIT" diff --git a/crates/sal-e-api/src/api.rs b/crates/sal-e-api/src/api.rs index 61223a8..2e9fb1d 100644 --- a/crates/sal-e-api/src/api.rs +++ b/crates/sal-e-api/src/api.rs @@ -22,7 +22,7 @@ pub struct Response { pub enum ComfyPromptApiError { /// Error creating a ComfyUI Client #[error("Error creating a ComfyUI Client")] - CreateClient(#[from] comfyui_api::comfy::ComfyApiError), + CreateClient(#[from] Box), } /// Struct wrapping a connection to the ComfyUI API. @@ -50,7 +50,7 @@ impl ComfyPromptApi { /// A new `ComfyPromptApi` instance on success, or an error if there was a failure in the ComfyUI API client. pub fn new(prompt: comfyui_api::models::Prompt) -> Result { Ok(Self { - client: comfyui_api::comfy::Comfy::new()?, + client: comfyui_api::comfy::Comfy::new().map_err(Box::new)?, params: crate::gen_params::ComfyParams { prompt: Some(prompt), count: 1, @@ -79,7 +79,7 @@ impl ComfyPromptApi { S: AsRef, { Ok(Self { - client: comfyui_api::comfy::Comfy::new_with_url(url)?, + client: comfyui_api::comfy::Comfy::new_with_url(url).map_err(Box::new)?, params: crate::gen_params::ComfyParams { prompt: Some(prompt), count: 1, diff --git a/crates/stable-diffusion-api/Cargo.toml b/crates/stable-diffusion-api/Cargo.toml index 5e8bbe0..c5b75e5 100644 --- a/crates/stable-diffusion-api/Cargo.toml +++ b/crates/stable-diffusion-api/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "stable-diffusion-api" version = "0.1.2" -edition = "2021" +edition = "2024" description = "Stable Diffusion WebUI API wrapper" readme = "README.md" license = "MIT" diff --git a/crates/stable-diffusion-api/src/img2img.rs b/crates/stable-diffusion-api/src/img2img.rs index 9a55123..f7d8e1e 100644 --- a/crates/stable-diffusion-api/src/img2img.rs +++ b/crates/stable-diffusion-api/src/img2img.rs @@ -240,7 +240,7 @@ impl Img2ImgRequest { /// # Arguments /// /// * `seed` - An i64 value representing the seed for random number generation. - /// Set to `-1` to randomize. + /// Set to `-1` to randomize. /// /// # Example /// @@ -258,7 +258,7 @@ impl Img2ImgRequest { /// # Arguments /// /// * `subseed` - An i64 value representing the subseed for random number generation. - /// Set to `-1` to randomize. + /// Set to `-1` to randomize. /// /// # Example /// diff --git a/crates/stable-diffusion-api/src/txt2img.rs b/crates/stable-diffusion-api/src/txt2img.rs index 770f6a6..784465f 100644 --- a/crates/stable-diffusion-api/src/txt2img.rs +++ b/crates/stable-diffusion-api/src/txt2img.rs @@ -156,7 +156,7 @@ impl Txt2ImgRequest { /// # Arguments /// /// * `seed` - An i64 value representing the seed for random number generation. - /// Set to `-1` to randomize. + /// Set to `-1` to randomize. /// /// # Example /// @@ -174,7 +174,7 @@ impl Txt2ImgRequest { /// # Arguments /// /// * `subseed` - An i64 value representing the subseed for random number generation. - /// Set to `-1` to randomize. + /// Set to `-1` to randomize. /// /// # Example /// diff --git a/crates/stable-diffusion-bot/Cargo.toml b/crates/stable-diffusion-bot/Cargo.toml index de3b932..8cb975d 100644 --- a/crates/stable-diffusion-bot/Cargo.toml +++ b/crates/stable-diffusion-bot/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "stable-diffusion-bot" version = "0.2.1" -edition = "2021" +edition = "2024" description = "Stable Diffusion Telegram Bot" readme = "README.md" license = "MIT" diff --git a/crates/stable-diffusion-bot/src/bot/handlers/settings.rs b/crates/stable-diffusion-bot/src/bot/handlers/settings.rs index 51bd190..8186ae4 100644 --- a/crates/stable-diffusion-bot/src/bot/handlers/settings.rs +++ b/crates/stable-diffusion-bot/src/bot/handlers/settings.rs @@ -388,13 +388,12 @@ pub(crate) async fn handle_txt2img_settings_value( text: String, (selection, mut txt2img, img2img): (Option, Box, Box), ) -> anyhow::Result<()> { - if let Some(ref setting) = selection { - if let Err(e) = update_txt2img_setting(txt2img.as_mut(), setting, text) { + if let Some(ref setting) = selection + && let Err(e) = update_txt2img_setting(txt2img.as_mut(), setting, text) { bot.send_message(msg.chat.id, format!("Please enter a valid value: {e:?}.")) .await?; return Ok(()); } - } let bot_state = BotState::SettingsTxt2Img { selection: None }; @@ -419,13 +418,12 @@ pub(crate) async fn handle_img2img_settings_value( text: String, (selection, txt2img, mut img2img): (Option, Box, Box), ) -> anyhow::Result<()> { - if let Some(ref setting) = selection { - if let Err(e) = update_img2img_setting(img2img.as_mut(), setting, text) { + if let Some(ref setting) = selection + && let Err(e) = update_img2img_setting(img2img.as_mut(), setting, text) { bot.send_message(msg.chat.id, format!("Please enter a valid value: {e:?}.")) .await?; return Ok(()); } - } let bot_state = BotState::SettingsImg2Img { selection: None };