mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
fix: prevent Telegram 409 Conflict on webhook re-registration (#447)
* fix: prevent Telegram 409 Conflict on webhook re-registration Delete any existing webhook before calling setWebhook in on_start(), matching the defensive cleanup that polling mode already does. As a safety net, register_webhook() now retries once on 409 after calling delete_webhook(). Closes #440 Co-Authored-By: Claude Opus 4.6 <[email protected]> * refactor: deduplicate 409 retry logic in register_webhook Restructure the match block so the initial request and retry share a single response-handling code path. Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
7481aea083
commit
293a700b69
@@ -376,6 +376,9 @@ impl Guest for TelegramChannel {
|
||||
// Register webhook with Telegram API — propagate errors so a bad token
|
||||
// causes activation to fail rather than silently succeeding.
|
||||
if let Some(ref tunnel_url) = config.tunnel_url {
|
||||
// Clear any stale webhook first to avoid 409 Conflict
|
||||
let _ = delete_webhook();
|
||||
|
||||
channel_host::log(
|
||||
channel_host::LogLevel::Info,
|
||||
&format!("Registering webhook: {}/webhook/telegram", tunnel_url),
|
||||
@@ -894,36 +897,61 @@ fn register_webhook(tunnel_url: &str, webhook_secret: Option<&str>) -> Result<()
|
||||
None,
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(response) => {
|
||||
if response.status != 200 {
|
||||
let body_str = String::from_utf8_lossy(&response.body);
|
||||
return Err(format!("HTTP {}: {}", response.status, body_str));
|
||||
}
|
||||
let mut response = match result {
|
||||
Ok(response) => response,
|
||||
Err(e) => return Err(format!("HTTP request failed: {}", e)),
|
||||
};
|
||||
|
||||
// Parse Telegram API response
|
||||
let api_response: TelegramApiResponse<serde_json::Value> =
|
||||
serde_json::from_slice(&response.body)
|
||||
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
||||
let mut retried = false;
|
||||
if response.status == 409 {
|
||||
channel_host::log(
|
||||
channel_host::LogLevel::Warn,
|
||||
"409 Conflict -- deleting existing webhook and retrying",
|
||||
);
|
||||
let _ = delete_webhook();
|
||||
retried = true;
|
||||
|
||||
if !api_response.ok {
|
||||
return Err(format!(
|
||||
"Telegram API error: {}",
|
||||
api_response
|
||||
.description
|
||||
.unwrap_or_else(|| "unknown".to_string())
|
||||
));
|
||||
}
|
||||
|
||||
channel_host::log(
|
||||
channel_host::LogLevel::Info,
|
||||
&format!("Webhook registered successfully: {}", webhook_url),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(format!("HTTP request failed: {}", e)),
|
||||
response = match channel_host::http_request(
|
||||
"POST",
|
||||
"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/setWebhook",
|
||||
&headers.to_string(),
|
||||
Some(&body_bytes),
|
||||
None,
|
||||
) {
|
||||
Ok(resp) => resp,
|
||||
Err(e) => return Err(format!("HTTP request failed (after 409 retry): {}", e)),
|
||||
};
|
||||
}
|
||||
|
||||
if response.status != 200 {
|
||||
let body_str = String::from_utf8_lossy(&response.body);
|
||||
let context = if retried { " (after 409 retry)" } else { "" };
|
||||
return Err(format!("HTTP {}{}: {}", response.status, context, body_str));
|
||||
}
|
||||
|
||||
// Parse Telegram API response
|
||||
let api_response: TelegramApiResponse<serde_json::Value> =
|
||||
serde_json::from_slice(&response.body)
|
||||
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
||||
|
||||
if !api_response.ok {
|
||||
let context = if retried { " (after 409 retry)" } else { "" };
|
||||
return Err(format!(
|
||||
"Telegram API error{}: {}",
|
||||
context,
|
||||
api_response
|
||||
.description
|
||||
.unwrap_or_else(|| "unknown".to_string())
|
||||
));
|
||||
}
|
||||
|
||||
let context = if retried { " (after retry)" } else { "" };
|
||||
channel_host::log(
|
||||
channel_host::LogLevel::Info,
|
||||
&format!("Webhook registered successfully{}: {}", context, webhook_url),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user