Fix issue #945 (PR 946 originally)

This commit is contained in:
Сырцев Вадим Игоревич 2024-07-20 08:39:27 +03:00 committed by Andrey Brusnik
parent 664717e07d
commit b625e813cc
No known key found for this signature in database
GPG key ID: D33232F28CFF442C
5 changed files with 77 additions and 51 deletions

View file

@ -31,6 +31,15 @@ pub struct Message {
#[serde(rename = "message_thread_id")]
pub thread_id: Option<ThreadId>,
/// Sender, empty for messages sent to channels.
pub from: Option<User>,
/// Sender of the message, sent on behalf of a chat. The channel itself for
/// channel messages. The supergroup itself for messages from anonymous
/// group administrators. The linked channel for messages automatically
/// forwarded to the discussion group
pub sender_chat: Option<Chat>,
/// Date the message was sent in Unix time.
#[serde(with = "crate::types::serde_date_from_unix_timestamp")]
pub date: DateTime<Utc>,
@ -38,6 +47,10 @@ pub struct Message {
/// Conversation the message belongs to.
pub chat: Chat,
/// `true`, if the message is sent to a forum topic.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub is_topic_message: bool,
/// Bot through which the message was sent.
pub via_bot: Option<User>,
@ -94,15 +107,6 @@ pub enum MessageKind {
#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MessageCommon {
/// Sender, empty for messages sent to channels.
pub from: Option<User>,
/// Sender of the message, sent on behalf of a chat. The channel itself for
/// channel messages. The supergroup itself for messages from anonymous
/// group administrators. The linked channel for messages automatically
/// forwarded to the discussion group
pub sender_chat: Option<Chat>,
/// Signature of the post author for messages in channels, or the custom
/// title of an anonymous group administrator.
pub author_signature: Option<String>,
@ -130,12 +134,6 @@ pub struct MessageCommon {
/// represented as ordinary `url` buttons.
pub reply_markup: Option<InlineKeyboardMarkup>,
/// `true`, if the message is sent to a forum topic.
// FIXME: `is_topic_message` is included even in service messages, like ForumTopicCreated.
// more this to `Message`
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub is_topic_message: bool,
/// `true`, if the message is a channel post that was automatically
/// forwarded to the connected discussion group.
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
@ -708,12 +706,10 @@ mod getters {
/// [telegram docs]: https://core.telegram.org/bots/api#message
impl Message {
/// Returns the user who sent the message.
#[deprecated(since = "0.13.0", note = "use `.from` field instead")]
#[must_use]
pub fn from(&self) -> Option<&User> {
match &self.kind {
Common(MessageCommon { from, .. }) => from.as_ref(),
_ => None,
}
self.from.as_ref()
}
#[must_use]
@ -724,12 +720,10 @@ mod getters {
}
}
#[deprecated(since = "0.13.0", note = "use `.sender_chat` field instead")]
#[must_use]
pub fn sender_chat(&self) -> Option<&Chat> {
match &self.kind {
Common(MessageCommon { sender_chat, .. }) => sender_chat.as_ref(),
_ => None,
}
self.sender_chat.as_ref()
}
#[must_use]
@ -1746,8 +1740,8 @@ impl Message {
// Lets just hope we didn't forget something here...
self.from()
.into_iter()
self.from
.iter()
.chain(self.via_bot.as_ref())
.chain(self.chat.mentioned_users_rec())
.chain(flatten(self.reply_to_message().map(Self::mentioned_users_rec)))
@ -1844,7 +1838,10 @@ mod tests {
Message {
id: MessageId(198283),
thread_id: None,
from: None,
sender_chat: None,
date: chrono::DateTime::from_timestamp(1567927221, 0).unwrap(),
is_topic_message: false,
chat: Chat {
id: ChatId(250918540),
kind: ChatKind::Private(ChatPrivate {
@ -2101,9 +2098,9 @@ mod tests {
chat_full_info: ChatFullInfo::default(),
};
assert!(message.from().unwrap().is_anonymous());
assert!(message.from.as_ref().unwrap().is_anonymous());
assert_eq!(message.author_signature().unwrap(), "TITLE2");
assert_eq!(message.sender_chat().unwrap(), &group);
assert_eq!(message.sender_chat.as_ref().unwrap(), &group);
assert_eq!(&message.chat, &group);
assert_eq!(message.forward_from_chat().unwrap(), &group);
assert_eq!(message.forward_author_signature().unwrap(), "TITLE");
@ -2126,7 +2123,7 @@ mod tests {
assert_eq!(message.migrate_to_chat_id(), Some(&new));
// The user who initialized the migration
assert!(message.from().is_some());
assert!(message.from.is_some());
// Migration from a common group
let json = r#"{"chat":{"id":-1001555296434,"title":"test","type":"supergroup"},"date":1629404938,"from":{"first_name":"Group","id":1087968824,"is_bot":true,"username":"GroupAnonymousBot"},"message_id":1,"migrate_from_chat_id":-599075523,"sender_chat":{"id":-1001555296434,"title":"test","type":"supergroup"}}"#;
@ -2137,10 +2134,10 @@ mod tests {
assert_eq!(message.migrate_from_chat_id(), Some(&old));
// Anonymous bot
assert!(message.from().is_some());
assert!(message.from.is_some());
// The chat to which the group migrated
assert!(message.sender_chat().is_some());
assert!(message.sender_chat.is_some());
}
/// Regression test for <https://github.com/teloxide/teloxide/issues/481>
@ -2296,7 +2293,9 @@ mod tests {
"message_thread_id":4
}"#;
let _: Message = serde_json::from_str(json).unwrap();
let message: Message = serde_json::from_str(json).unwrap();
// https://github.com/teloxide/teloxide/issues/945
assert!(message.from.is_some());
}
#[test]
@ -2480,6 +2479,28 @@ mod tests {
giveaway_message: Some(Box::new(Message {
id: MessageId(24),
thread_id: None,
from: None,
sender_chat: Some(Chat {
id: ChatId(-1002236736395),
kind: ChatKind::Public(ChatPublic {
title: Some("Test".to_owned()),
kind: PublicChatKind::Channel(PublicChatChannel {
linked_chat_id: None,
username: None
}),
description: None,
invite_link: None,
has_protected_content: None
}),
chat_full_info: ChatFullInfo::default(),
available_reactions: None,
photo: None,
has_aggressive_anti_spam_enabled: false,
has_hidden_members: false,
message_auto_delete_time: None,
pinned_message: None
}),
is_topic_message: false,
date: DateTime::from_timestamp(1721161230, 0).unwrap(),
chat: Chat {
id: ChatId(-1002236736395),

View file

@ -156,7 +156,9 @@ impl Update {
use UpdateKind::*;
let from = match &self.kind {
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => m.from()?,
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => {
m.from.as_ref()?
}
CallbackQuery(query) => &query.from,
ChosenInlineResult(chosen) => &chosen.from,
@ -510,6 +512,18 @@ mod test {
via_bot: None,
id: MessageId(6557),
thread_id: None,
from: Some(User {
id: UserId(218_485_655),
is_bot: false,
first_name: String::from("Waffle"),
last_name: None,
username: Some(String::from("WaffleLapkin")),
language_code: Some(String::from("en")),
is_premium: false,
added_to_attachment_menu: false,
}),
sender_chat: None,
is_topic_message: false,
date,
chat: Chat {
id: ChatId(218_485_655),
@ -530,16 +544,6 @@ mod test {
chat_full_info: ChatFullInfo::default(),
},
kind: MessageKind::Common(MessageCommon {
from: Some(User {
id: UserId(218_485_655),
is_bot: false,
first_name: String::from("Waffle"),
last_name: None,
username: Some(String::from("WaffleLapkin")),
language_code: Some(String::from("en")),
is_premium: false,
added_to_attachment_menu: false,
}),
reply_to_message: None,
forward_origin: None,
quote: None,
@ -556,9 +560,7 @@ mod test {
}),
}),
reply_markup: None,
sender_chat: None,
author_signature: None,
is_topic_message: false,
is_automatic_forward: false,
has_protected_content: false,
}),

View file

@ -79,7 +79,7 @@ async fn kick_user(bot: Bot, msg: Message) -> ResponseResult<()> {
match msg.reply_to_message() {
Some(replied) => {
// bot.unban_chat_member can also kicks a user from a group chat.
bot.unban_chat_member(msg.chat.id, replied.from().unwrap().id).await?;
bot.unban_chat_member(msg.chat.id, replied.from.as_ref().unwrap().id).await?;
}
None => {
bot.send_message(msg.chat.id, "Use this command in reply to another message").await?;
@ -94,7 +94,7 @@ async fn ban_user(bot: Bot, msg: Message, time: Duration) -> ResponseResult<()>
Some(replied) => {
bot.kick_chat_member(
msg.chat.id,
replied.from().expect("Must be MessageKind::Common").id,
replied.from.as_ref().expect("Must be MessageKind::Common").id,
)
.until_date(msg.date + time)
.await?;
@ -113,7 +113,7 @@ async fn mute_user(bot: Bot, msg: Message, time: Duration) -> ResponseResult<()>
Some(replied) => {
bot.restrict_chat_member(
msg.chat.id,
replied.from().expect("Must be MessageKind::Common").id,
replied.from.as_ref().expect("Must be MessageKind::Common").id,
ChatPermissions::empty(),
)
.until_date(msg.date + time)

View file

@ -34,7 +34,7 @@ async fn main() {
.branch(
// Filter a maintainer by a user ID.
dptree::filter(|cfg: ConfigParameters, msg: Message| {
msg.from().map(|user| user.id == cfg.bot_maintainer).unwrap_or_default()
msg.from.map(|user| user.id == cfg.bot_maintainer).unwrap_or_default()
})
.filter_command::<MaintainerCommands>()
.endpoint(|msg: Message, bot: Bot, cmd: MaintainerCommands| async move {
@ -125,7 +125,7 @@ async fn simple_commands_handler(
) -> Result<(), teloxide::RequestError> {
let text = match cmd {
SimpleCommand::Help => {
if msg.from().unwrap().id == cfg.bot_maintainer {
if msg.from.unwrap().id == cfg.bot_maintainer {
format!(
"{}\n\n{}",
SimpleCommand::descriptions(),
@ -138,7 +138,7 @@ async fn simple_commands_handler(
}
}
SimpleCommand::Maintainer => {
if msg.from().unwrap().id == cfg.bot_maintainer {
if msg.from.as_ref().unwrap().id == cfg.bot_maintainer {
"Maintainer is you!".into()
} else if let Some(username) = cfg.maintainer_username {
format!("Maintainer is @{username}")
@ -147,7 +147,7 @@ async fn simple_commands_handler(
}
}
SimpleCommand::MyId => {
format!("{}", msg.from().unwrap().id)
format!("{}", msg.from.unwrap().id)
}
};

View file

@ -1,4 +1,6 @@
#![allow(clippy::redundant_closure_call)]
// Required for the `filter_from` currently
#![allow(deprecated)]
use dptree::{di::DependencyMap, Handler};
@ -68,6 +70,7 @@ macro_rules! define_message_ext {
}
}
// FIXME: change macro so that we can filter things without getters
// May be expanded in the future.
define_message_ext! {
// MessageCommon