diff --git a/crates/teloxide-core/src/types.rs b/crates/teloxide-core/src/types.rs index 50f7c9f6..3359badc 100644 --- a/crates/teloxide-core/src/types.rs +++ b/crates/teloxide-core/src/types.rs @@ -85,6 +85,7 @@ pub use message::*; pub use message_auto_delete_timer_changed::*; pub use message_entity::*; pub use message_id::*; +pub use message_origin::*; pub use order_info::*; pub use parse_mode::*; pub use passport_data::*; @@ -191,6 +192,7 @@ mod message; mod message_auto_delete_timer_changed; mod message_entity; mod message_id; +mod message_origin; mod order_info; mod parse_mode; mod photo_size; @@ -403,6 +405,7 @@ pub(crate) mod option_url_from_string { } } +#[allow(dead_code)] pub(crate) mod option_msg_id_as_int { use crate::types::MessageId; diff --git a/crates/teloxide-core/src/types/message.rs b/crates/teloxide-core/src/types/message.rs index eddd623e..575d2a82 100644 --- a/crates/teloxide-core/src/types/message.rs +++ b/crates/teloxide-core/src/types/message.rs @@ -8,9 +8,9 @@ use crate::types::{ Animation, Audio, BareChatId, Chat, ChatId, ChatShared, Contact, Dice, Document, ForumTopicClosed, ForumTopicCreated, ForumTopicEdited, ForumTopicReopened, Game, GeneralForumTopicHidden, GeneralForumTopicUnhidden, InlineKeyboardMarkup, Invoice, Location, - MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, PassportData, - PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, ThreadId, True, - User, UsersShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, + MessageAutoDeleteTimerChanged, MessageEntity, MessageEntityRef, MessageId, MessageOrigin, + PassportData, PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment, + ThreadId, True, User, UsersShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited, VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed, }; @@ -101,9 +101,8 @@ pub struct MessageCommon { /// title of an anonymous group administrator. pub author_signature: Option, - /// For forwarded messages, information about the forward - #[serde(flatten)] - pub forward: Option, + /// Information about the original message for forwarded messages + pub forward_origin: Option, /// For replies, the original message. Note that the Message object in this /// field will not contain further `reply_to_message` fields even if it @@ -299,52 +298,6 @@ pub struct MessagePassportData { pub passport_data: PassportData, } -/// Information about forwarded message. -#[serde_with::skip_serializing_none] -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Forward { - /// Date the original message was sent in Unix time. - #[serde(rename = "forward_date")] - #[serde(with = "crate::types::serde_date_from_unix_timestamp")] - pub date: DateTime, - - /// The entity that sent the original message. - #[serde(flatten)] - pub from: ForwardedFrom, - - /// For messages forwarded from channels, signature of the post author if - /// present. For messages forwarded from anonymous admins, authors title, if - /// present. - #[serde(rename = "forward_signature")] - pub signature: Option, - - /// For messages forwarded from channels, identifier of the original message - /// in the channel - #[serde( - rename = "forward_from_message_id", - with = "crate::types::option_msg_id_as_int", - default, - skip_serializing_if = "Option::is_none" - )] - pub message_id: Option, -} - -/// The entity that sent the original message that later was forwarded. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum ForwardedFrom { - /// The message was sent by a user. - #[serde(rename = "forward_from")] - User(User), - /// The message was sent by an anonymous user on behalf of a group or - /// channel. - #[serde(rename = "forward_from_chat")] - Chat(Chat), - /// The message was sent by a user who disallow adding a link to their - /// account in forwarded messages. - #[serde(rename = "forward_sender_name")] - SenderName(String), -} - #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(untagged)] pub enum MediaKind { @@ -674,13 +627,13 @@ mod getters { use std::ops::Deref; use crate::types::{ - self, message::MessageKind::*, Chat, ChatId, ChatMigration, Forward, ForwardedFrom, - MediaAnimation, MediaAudio, MediaContact, MediaDocument, MediaGame, MediaKind, - MediaLocation, MediaPhoto, MediaPoll, MediaSticker, MediaStory, MediaText, MediaVenue, - MediaVideo, MediaVideoNote, MediaVoice, Message, MessageChannelChatCreated, - MessageChatShared, MessageCommon, MessageConnectedWebsite, MessageDeleteChatPhoto, - MessageDice, MessageEntity, MessageGroupChatCreated, MessageId, MessageInvoice, - MessageLeftChatMember, MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle, + self, message::MessageKind::*, Chat, ChatId, ChatMigration, MediaAnimation, MediaAudio, + MediaContact, MediaDocument, MediaGame, MediaKind, MediaLocation, MediaPhoto, MediaPoll, + MediaSticker, MediaStory, MediaText, MediaVenue, MediaVideo, MediaVideoNote, MediaVoice, + Message, MessageChannelChatCreated, MessageChatShared, MessageCommon, + MessageConnectedWebsite, MessageDeleteChatPhoto, MessageDice, MessageEntity, + MessageGroupChatCreated, MessageId, MessageInvoice, MessageLeftChatMember, + MessageNewChatMembers, MessageNewChatPhoto, MessageNewChatTitle, MessageOrigin, MessagePassportData, MessagePinned, MessageProximityAlertTriggered, MessageSuccessfulPayment, MessageSupergroupChatCreated, MessageUsersShared, MessageVideoChatParticipantsInvited, PhotoSize, User, @@ -725,52 +678,63 @@ mod getters { } #[must_use] - pub fn forward(&self) -> Option<&Forward> { - self.common().and_then(|m| m.forward.as_ref()) + pub fn forward_origin(&self) -> Option<&MessageOrigin> { + match &self.kind { + Common(MessageCommon { forward_origin, .. }) => forward_origin.as_ref(), + _ => None, + } } #[must_use] pub fn forward_date(&self) -> Option> { - self.forward().map(|f| f.date) - } - - #[must_use] - pub fn forward_from(&self) -> Option<&ForwardedFrom> { - self.forward().map(|f| &f.from) + self.forward_origin().map(|f| f.date()) } #[must_use] pub fn forward_from_user(&self) -> Option<&User> { - self.forward_from().and_then(|from| match from { - ForwardedFrom::User(user) => Some(user), + self.forward_origin().and_then(|origin| match origin { + MessageOrigin::User { sender_user, .. } => Some(sender_user), _ => None, }) } #[must_use] pub fn forward_from_chat(&self) -> Option<&Chat> { - self.forward_from().and_then(|from| match from { - ForwardedFrom::Chat(chat) => Some(chat), + self.forward_origin().and_then(|origin| match origin { + MessageOrigin::Chat { sender_chat, .. } => Some(sender_chat), _ => None, }) } #[must_use] pub fn forward_from_sender_name(&self) -> Option<&str> { - self.forward_from().and_then(|from| match from { - ForwardedFrom::SenderName(sender_name) => Some(&**sender_name), + self.forward_origin().and_then(|origin| match origin { + MessageOrigin::HiddenUser { sender_user_name, .. } => { + Some(sender_user_name.as_str()) + } _ => None, }) } #[must_use] pub fn forward_from_message_id(&self) -> Option { - self.forward().and_then(|f| f.message_id) + self.forward_origin().and_then(|origin| match origin { + MessageOrigin::Channel { message_id, .. } => Some(*message_id), + _ => None, + }) } #[must_use] - pub fn forward_signature(&self) -> Option<&str> { - self.forward().and_then(|f| f.signature.as_deref()) + pub fn forward_author_signature(&self) -> Option<&str> { + self.forward_origin().and_then(|origin| match origin { + MessageOrigin::Chat { author_signature, .. } => { + author_signature.as_ref().map(|a| a.as_str()) + } + MessageOrigin::Channel { author_signature, .. } => { + author_signature.as_ref().map(|a| a.as_str()) + } + _ => None, + }) } #[must_use] @@ -1974,14 +1938,17 @@ mod tests { "title": "a", "type": "supergroup" }, - "date": 1640359576, - "forward_from_chat": { - "id": -1001160242915, - "title": "a", - "type": "supergroup" + "forward_origin": { + "type": "chat", + "date": 1640359544, + "sender_chat": { + "id": -1001160242915, + "title": "a", + "type": "supergroup" + }, + "author_signature": "TITLE" }, - "forward_signature": "TITLE", - "forward_date": 1640359544, + "date": 1640359576, "text": "text" }"#; @@ -2024,7 +1991,7 @@ mod tests { assert_eq!(message.sender_chat().unwrap(), &group); assert_eq!(&message.chat, &group); assert_eq!(message.forward_from_chat().unwrap(), &group); - assert_eq!(message.forward_signature().unwrap(), "TITLE"); + assert_eq!(message.forward_author_signature().unwrap(), "TITLE"); assert!(message.forward_date().is_some()); assert_eq!(message.text().unwrap(), "text"); } diff --git a/crates/teloxide-core/src/types/message_origin.rs b/crates/teloxide-core/src/types/message_origin.rs new file mode 100644 index 00000000..240539dd --- /dev/null +++ b/crates/teloxide-core/src/types/message_origin.rs @@ -0,0 +1,57 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; + +use crate::types::{Chat, MessageId, User}; + +/// This object describes the origin of a message +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +#[serde(tag = "type")] +pub enum MessageOrigin { + User { + /// Date the message was sent originally in Unix time + #[serde(default, with = "crate::types::serde_date_from_unix_timestamp")] + date: DateTime, + /// User that sent the message originally + sender_user: User, + }, + HiddenUser { + /// Date the message was sent originally in Unix time + #[serde(default, with = "crate::types::serde_date_from_unix_timestamp")] + date: DateTime, + /// Name of the user that sent the message originally + sender_user_name: String, + }, + Chat { + /// Date the message was sent originally in Unix time + #[serde(default, with = "crate::types::serde_date_from_unix_timestamp")] + date: DateTime, + /// Chat that sent the message originally + sender_chat: Chat, + /// For messages originally sent by an anonymous chat administrator, + /// original message author signature + author_signature: Option, + }, + Channel { + /// Date the message was sent originally in Unix time + #[serde(default, with = "crate::types::serde_date_from_unix_timestamp")] + date: DateTime, + /// Channel chat to which the message was originally sent + chat: Chat, + /// Unique message identifier inside the chat + message_id: MessageId, + /// Signature of the original post author + author_signature: Option, + }, +} + +impl MessageOrigin { + pub fn date(&self) -> DateTime { + *match self { + Self::User { date, .. } => date, + Self::HiddenUser { date, .. } => date, + Self::Chat { date, .. } => date, + Self::Channel { date, .. } => date, + } + } +} diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index a1d504ee..ed1b2cac 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -455,7 +455,7 @@ mod test { added_to_attachment_menu: false, }), reply_to_message: None, - forward: None, + forward_origin: None, edit_date: None, media_kind: MediaKind::Text(MediaText { text: String::from("hello there"), diff --git a/crates/teloxide/src/dispatching/filter_ext.rs b/crates/teloxide/src/dispatching/filter_ext.rs index 532f614f..08d0fba6 100644 --- a/crates/teloxide/src/dispatching/filter_ext.rs +++ b/crates/teloxide/src/dispatching/filter_ext.rs @@ -92,7 +92,6 @@ define_message_ext! { (filter_migration_from, Message::migrate_from_chat_id), (filter_migration_to, Message::migrate_to_chat_id), (filter_reply_to_message, Message::reply_to_message), - (filter_forward_from, Message::forward_from), // Rest variants of a MessageKind (filter_new_chat_members, Message::new_chat_members), (filter_left_chat_member, Message::left_chat_member),