From 54bab306e1de37c67d2eefc43c6128f1f73cd45c Mon Sep 17 00:00:00 2001 From: xintaofei Date: Mon, 30 Mar 2026 23:28:00 +0800 Subject: [PATCH] =?UTF-8?q?tg=E9=80=9A=E9=81=93=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/chat_channel/backends/telegram.rs | 88 +++++++++++++------ .../src/chat_channel/command_dispatcher.rs | 8 +- 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src-tauri/src/chat_channel/backends/telegram.rs b/src-tauri/src/chat_channel/backends/telegram.rs index bf448a1..f1a3b97 100644 --- a/src-tauri/src/chat_channel/backends/telegram.rs +++ b/src-tauri/src/chat_channel/backends/telegram.rs @@ -34,6 +34,49 @@ impl TelegramBackend { self.bot_token, method ) } + + async fn send_text( + &self, + text: &str, + parse_mode: Option<&str>, + ) -> Result { + let mut body = serde_json::json!({ + "chat_id": self.chat_id, + "text": text, + }); + if let Some(mode) = parse_mode { + body["parse_mode"] = serde_json::Value::String(mode.to_string()); + } + + let resp = self + .client + .post(&self.api_url("sendMessage")) + .json(&body) + .send() + .await + .map_err(|e| ChatChannelError::SendFailed(e.to_string()))?; + + let result: serde_json::Value = resp + .json() + .await + .map_err(|e| ChatChannelError::SendFailed(e.to_string()))?; + + if result.get("ok").and_then(|v| v.as_bool()) != Some(true) { + let desc = result + .get("description") + .and_then(|v| v.as_str()) + .unwrap_or("unknown error"); + return Err(ChatChannelError::SendFailed(desc.to_string())); + } + + let message_id = result + .pointer("/result/message_id") + .and_then(|v| v.as_i64()) + .map(|id| id.to_string()) + .unwrap_or_default(); + + Ok(SentMessageId(message_id)) + } } #[async_trait] @@ -150,40 +193,25 @@ impl ChatChannelBackend for TelegramBackend { } async fn send_message(&self, text: &str) -> Result { - let body = serde_json::json!({ - "chat_id": self.chat_id, - "text": text, - "parse_mode": "Markdown", - }); - - let resp = self - .client - .post(&self.api_url("sendMessage")) - .json(&body) - .send() - .await - .map_err(|e| ChatChannelError::SendFailed(e.to_string()))?; - - let result: serde_json::Value = resp - .json() - .await - .map_err(|e| ChatChannelError::SendFailed(e.to_string()))?; - - let message_id = result - .pointer("/result/message_id") - .and_then(|v| v.as_i64()) - .map(|id| id.to_string()) - .unwrap_or_default(); - - Ok(SentMessageId(message_id)) + self.send_text(text, None).await } async fn send_rich_message( &self, message: &RichMessage, ) -> Result { - let text = format_telegram_markdown(message); - self.send_message(&text).await + let markdown_text = format_telegram_markdown(message); + let result = self.send_text(&markdown_text, Some("MarkdownV2")).await; + + match result { + Ok(id) => Ok(id), + Err(e) => { + // MarkdownV2 failed — fall back to plain text + eprintln!("[Telegram] MarkdownV2 send failed: {e}, retrying as plain text"); + let plain_text = message.to_plain_text(); + self.send_text(&plain_text, None).await + } + } } async fn test_connection(&self) -> Result<(), ChatChannelError> { @@ -234,7 +262,9 @@ fn format_telegram_markdown(msg: &RichMessage) -> String { } fn escape_markdown(text: &str) -> String { - text.replace('_', "\\_") + // Backslash must be escaped first to avoid double-escaping + text.replace('\\', "\\\\") + .replace('_', "\\_") .replace('*', "\\*") .replace('[', "\\[") .replace(']', "\\]") diff --git a/src-tauri/src/chat_channel/command_dispatcher.rs b/src-tauri/src/chat_channel/command_dispatcher.rs index 90ac44f..af3c80d 100644 --- a/src-tauri/src/chat_channel/command_dispatcher.rs +++ b/src-tauri/src/chat_channel/command_dispatcher.rs @@ -34,7 +34,13 @@ pub fn spawn_command_dispatcher( let send_result = manager.send_to_channel(cmd.channel_id, &response).await; let (status, error_detail) = match &send_result { Ok(_) => ("sent", None), - Err(e) => ("failed", Some(e.to_string())), + Err(e) => { + eprintln!( + "[ChatChannel] failed to send response for {:?} to channel {}: {e}", + text, cmd.channel_id + ); + ("failed", Some(e.to_string())) + } }; let _ = chat_channel_message_log_service::create_log(