refactor(handlers): use teloxide's own chat-kind predicates

is_group hand-rolled what Chat::is_group/is_supergroup/is_private already
answer (verified in teloxide-core's chat.rs), and the private check was a
ChatKind pattern match. The unit test that exercised the helper asserted
teloxide's semantics; the channel case it guarded (a channel must not get the
group hint) is now asserted through handle_message instead, next to the group
case.
This commit is contained in:
2026-09-21 17:26:35 +08:00
parent d9f3ee99c1
commit 26581cfca1
+23 -50
View File
@@ -27,9 +27,7 @@ use crate::media_sender::MediaSender;
use commands::{Command, execute_command}; use commands::{Command, execute_command};
use teloxide::RequestError; use teloxide::RequestError;
use teloxide::prelude::*; use teloxide::prelude::*;
use teloxide::types::{ use teloxide::types::{ChatId, Message, MessageId, ParseMode, ReplyParameters};
ChatId, ChatKind, Message, MessageId, ParseMode, PublicChatKind, ReplyParameters,
};
use teloxide::utils::command::BotCommands; use teloxide::utils::command::BotCommands;
use urls::{URL_JOBS, extract_urls}; use urls::{URL_JOBS, extract_urls};
@@ -196,7 +194,7 @@ pub(crate) async fn handle_message(
bot: &Bot, bot: &Bot,
message: Message, message: Message,
) -> Result<(), RequestError> { ) -> Result<(), RequestError> {
let is_private = matches!(message.chat.kind, ChatKind::Private(_)); let is_private = message.chat.is_private();
let sender = message let sender = message
.from .from
.as_ref() .as_ref()
@@ -267,10 +265,11 @@ pub(crate) async fn handle_message(
break; break;
} }
} }
} else if is_group(&message.chat.kind) } else if message.chat.is_group()
&& extract_urls(&message) || message.chat.is_supergroup()
.iter() && extract_urls(&message)
.any(|url| x_media::site::cache_key(url).is_some()) .iter()
.any(|url| x_media::site::cache_key(url).is_some())
{ {
// A supported link in a group used to be dropped in silence, which // A supported link in a group used to be dropped in silence, which
// reads as a broken bot (the command menu is registered globally, so // reads as a broken bot (the command menu is registered globally, so
@@ -287,18 +286,6 @@ pub(crate) async fn handle_message(
const GROUP_LINK_HINT: &str = const GROUP_LINK_HINT: &str =
"Links are handled in private chat only — send me this link there, or use inline mode here."; "Links are handled in private chat only — send me this link there, or use inline mode here.";
/// Groups and supergroups, as opposed to private chats and channels.
fn is_group(kind: &ChatKind) -> bool {
matches!(
kind,
ChatKind::Public(chat)
if matches!(
chat.kind,
PublicChatKind::Group | PublicChatKind::Supergroup(_)
)
)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@@ -464,38 +451,24 @@ mod tests {
assert_eq!(api.methods(), vec!["EditMessageCaption", "SendMessage"]); assert_eq!(api.methods(), vec!["EditMessageCaption", "SendMessage"]);
assert_eq!(api.body("SendMessage")["text"], GROUP_LINK_HINT); assert_eq!(api.body("SendMessage")["text"], GROUP_LINK_HINT);
}
#[test] // A channel stays silent: the hint reply would be posted into the
fn the_link_hint_is_for_groups_only() { // channel itself, so the same link must produce no further call.
use teloxide::types::{ChatPrivate, ChatPublic, PublicChatChannel, PublicChatSupergroup}; let channel: Message = serde_json::from_value(serde_json::json!({
"message_id": 3,
"date": 0,
"chat": { "id": -1001234567890i64, "type": "channel", "title": "c" },
"text": "https://x.com/u/status/1",
"entities": [{ "type": "url", "offset": 0, "length": 24 }],
}))
.expect("a minimal channel message deserializes");
let group = ChatKind::Public(ChatPublic { handle_message(&ctx, &bot, channel).await.unwrap();
title: None,
kind: PublicChatKind::Group,
});
let supergroup = ChatKind::Public(ChatPublic {
title: None,
kind: PublicChatKind::Supergroup(PublicChatSupergroup {
username: None,
is_forum: false,
}),
});
// A channel must stay silent: the hint reply would be posted into the
// channel itself.
let channel = ChatKind::Public(ChatPublic {
title: None,
kind: PublicChatKind::Channel(PublicChatChannel { username: None }),
});
let private = ChatKind::Private(ChatPrivate {
username: None,
first_name: None,
last_name: None,
});
assert!(is_group(&group)); assert_eq!(
assert!(is_group(&supergroup)); api.methods(),
assert!(!is_group(&channel)); vec!["EditMessageCaption", "SendMessage"],
assert!(!is_group(&private)); "a channel must not get the group hint"
);
} }
} }