From 5e7a87c0ddf81c5b87e6bcd8382a50d0538d7ff1 Mon Sep 17 00:00:00 2001 From: YoursFunny Date: Thu, 24 Sep 2026 20:29:04 +0800 Subject: [PATCH] fix: send text posts as HTML --- crates/xmedia-bot/src/media_sender/mod.rs | 26 +++++++++++++++++++ .../src/media_sender/test_support.rs | 16 ++++++++++++ crates/xmedia-bot/src/send/mod.rs | 11 +++----- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/crates/xmedia-bot/src/media_sender/mod.rs b/crates/xmedia-bot/src/media_sender/mod.rs index 1c36397..3d2c1e6 100644 --- a/crates/xmedia-bot/src/media_sender/mod.rs +++ b/crates/xmedia-bot/src/media_sender/mod.rs @@ -60,6 +60,14 @@ pub trait MediaSender: Send + Sync { reply_markup: Option, ) -> BoxFuture<'_, Result>; + /// Sends an HTML-formatted plain message. + fn send_html_message( + &self, + chat_id: ChatId, + text: String, + reply_to: Option, + ) -> BoxFuture<'_, Result>; + /// Answers an inline query with `results`, cached by Telegram for /// `cache_time` seconds. An empty `results` answers *empty*, which is a /// real answer: it stops the client spinning and lets Telegram serve a @@ -201,6 +209,24 @@ impl MediaSender for Bot { }) } + fn send_html_message( + &self, + chat_id: ChatId, + text: String, + reply_to: Option, + ) -> BoxFuture<'_, Result> { + Box::pin(async move { + crate::rate_limit::acquire_global(1.0).await; + let mut request = + ::send_message(self, chat_id, text).parse_mode(ParseMode::Html); + if let Some(reply_to) = reply_to { + request = request + .reply_parameters(ReplyParameters::new(reply_to).allow_sending_without_reply()); + } + request.await.map(|message| message.id.0 as i64) + }) + } + fn answer_inline_query( &self, id: InlineQueryId, diff --git a/crates/xmedia-bot/src/media_sender/test_support.rs b/crates/xmedia-bot/src/media_sender/test_support.rs index 0d2ce6b..19883b7 100644 --- a/crates/xmedia-bot/src/media_sender/test_support.rs +++ b/crates/xmedia-bot/src/media_sender/test_support.rs @@ -428,6 +428,22 @@ impl MediaSender for MockSender { }) } + fn send_html_message( + &self, + _chat_id: ChatId, + text: String, + _reply_to: Option, + ) -> BoxFuture<'_, Result> { + Box::pin(async move { + self.messages.lock().push(text); + match self.next("send_html_message") { + Outcome::MessageOk => Ok(MockSender::SENT_ID), + Outcome::MessageErr => Err(self.error()), + other => panic!("unexpected outcome {other:?} for send_html_message"), + } + }) + } + fn answer_inline_query( &self, _id: InlineQueryId, diff --git a/crates/xmedia-bot/src/send/mod.rs b/crates/xmedia-bot/src/send/mod.rs index 904fe49..a2609bd 100644 --- a/crates/xmedia-bot/src/send/mod.rs +++ b/crates/xmedia-bot/src/send/mod.rs @@ -681,12 +681,7 @@ pub(crate) async fn send_text_post( ) { match ctx .sender - .send_message( - ChatId(chat_id), - caption, - Some(MessageId(reply_to as i32)), - None, - ) + .send_html_message(ChatId(chat_id), caption, Some(MessageId(reply_to as i32))) .await { Ok(_) => log::info!("sent the post's text for chat={chat_id}"), @@ -847,7 +842,7 @@ mod tests { ) .await; - assert_eq!(sender.calls(), vec!["send_message"]); + assert_eq!(sender.calls(), vec!["send_html_message"]); assert_eq!( sender.messages(), vec!["https://x.com/u/status/1\nu: hello"] @@ -861,7 +856,7 @@ mod tests { send_text_post(&ctx, 1, 2, "text".into()).await; - assert_eq!(sender.calls(), vec!["send_message", "send_message"]); + assert_eq!(sender.calls(), vec!["send_html_message", "send_message"]); assert!(sender.messages()[1].contains("Could not send this post's text")); }