fix(channels): check response status in send() for Telegram, Slack, and Discord

Reliability fix: check HTTP response status in channel send methods
This commit is contained in:
Argenis 2026-02-15 09:48:58 -05:00 committed by GitHub
parent 64a64ccd3a
commit ef00cc9a66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 5 deletions

View file

@ -87,13 +87,23 @@ impl Channel for DiscordChannel {
let url = format!("https://discord.com/api/v10/channels/{channel_id}/messages"); let url = format!("https://discord.com/api/v10/channels/{channel_id}/messages");
let body = json!({ "content": message }); let body = json!({ "content": message });
self.client let resp = self
.client
.post(&url) .post(&url)
.header("Authorization", format!("Bot {}", self.bot_token)) .header("Authorization", format!("Bot {}", self.bot_token))
.json(&body) .json(&body)
.send() .send()
.await?; .await?;
if !resp.status().is_success() {
let status = resp.status();
let err = resp
.text()
.await
.unwrap_or_else(|e| format!("<failed to read response body: {e}>"));
anyhow::bail!("Discord send message failed ({status}): {err}");
}
Ok(()) Ok(())
} }

View file

@ -58,13 +58,34 @@ impl Channel for SlackChannel {
"text": message "text": message
}); });
self.client let resp = self
.client
.post("https://slack.com/api/chat.postMessage") .post("https://slack.com/api/chat.postMessage")
.bearer_auth(&self.bot_token) .bearer_auth(&self.bot_token)
.json(&body) .json(&body)
.send() .send()
.await?; .await?;
let status = resp.status();
let body = resp
.text()
.await
.unwrap_or_else(|e| format!("<failed to read response body: {e}>"));
if !status.is_success() {
anyhow::bail!("Slack chat.postMessage failed ({status}): {body}");
}
// Slack returns 200 for most app-level errors; check JSON "ok" field
let parsed: serde_json::Value = serde_json::from_str(&body).unwrap_or_default();
if parsed.get("ok") == Some(&serde_json::Value::Bool(false)) {
let err = parsed
.get("error")
.and_then(|e| e.as_str())
.unwrap_or("unknown");
anyhow::bail!("Slack chat.postMessage failed: {err}");
}
Ok(()) Ok(())
} }

View file

@ -376,12 +376,22 @@ impl Channel for TelegramChannel {
"parse_mode": "Markdown" "parse_mode": "Markdown"
}); });
self.client let resp = self
.client
.post(self.api_url("sendMessage")) .post(self.api_url("sendMessage"))
.json(&body) .json(&body)
.send() .send()
.await?; .await?;
if !resp.status().is_success() {
let status = resp.status();
let err = resp
.text()
.await
.unwrap_or_else(|e| format!("<failed to read response body: {e}>"));
anyhow::bail!("Telegram sendMessage failed ({status}): {err}");
}
Ok(()) Ok(())
} }

View file

@ -1,4 +1,4 @@
//! Utility functions for ZeroClaw. //! Utility functions for `ZeroClaw`.
//! //!
//! This module contains reusable helper functions used across the codebase. //! This module contains reusable helper functions used across the codebase.
@ -58,7 +58,10 @@ mod tests {
fn test_truncate_ascii_with_truncation() { fn test_truncate_ascii_with_truncation() {
// ASCII string longer than limit - truncates // ASCII string longer than limit - truncates
assert_eq!(truncate_with_ellipsis("hello world", 5), "hello..."); assert_eq!(truncate_with_ellipsis("hello world", 5), "hello...");
assert_eq!(truncate_with_ellipsis("This is a long message", 10), "This is a..."); assert_eq!(
truncate_with_ellipsis("This is a long message", 10),
"This is a..."
);
} }
#[test] #[test]