mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 06:25:10 +01:00
Add MaybeInaccessibleMessage
to the Message
and CallbackQuery
This commit is contained in:
parent
6c967231ef
commit
c8f7bd745c
8 changed files with 145 additions and 23 deletions
|
@ -41,6 +41,7 @@ pub use game::*;
|
|||
pub use game_high_score::*;
|
||||
pub use general_forum_topic_hidden::*;
|
||||
pub use general_forum_topic_unhidden::*;
|
||||
pub use inaccessible_message::*;
|
||||
pub use inline_keyboard_button::*;
|
||||
pub use inline_keyboard_markup::*;
|
||||
pub use inline_query::*;
|
||||
|
@ -79,6 +80,7 @@ pub use label_price::*;
|
|||
pub use location::*;
|
||||
pub use login_url::*;
|
||||
pub use mask_position::*;
|
||||
pub use maybe_inaccessible_message::*;
|
||||
pub use me::*;
|
||||
pub use menu_button::*;
|
||||
pub use message::*;
|
||||
|
@ -170,6 +172,7 @@ mod game;
|
|||
mod game_high_score;
|
||||
mod general_forum_topic_hidden;
|
||||
mod general_forum_topic_unhidden;
|
||||
mod inaccessible_message;
|
||||
mod inline_keyboard_button;
|
||||
mod inline_keyboard_markup;
|
||||
mod inline_query_results_button;
|
||||
|
@ -186,6 +189,7 @@ mod label_price;
|
|||
mod location;
|
||||
mod login_url;
|
||||
mod mask_position;
|
||||
mod maybe_inaccessible_message;
|
||||
mod me;
|
||||
mod menu_button;
|
||||
mod message;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Message, User};
|
||||
use crate::types::{MaybeInaccessibleMessage, Message, User};
|
||||
|
||||
/// This object represents an incoming callback query from a callback button in
|
||||
/// an [inline keyboard].
|
||||
|
@ -24,10 +24,9 @@ pub struct CallbackQuery {
|
|||
/// A sender.
|
||||
pub from: User,
|
||||
|
||||
/// A message with the callback button that originated the query. Note that
|
||||
/// message content and message date will not be available if the message
|
||||
/// is too old.
|
||||
pub message: Option<Message>,
|
||||
/// Message sent by the bot with the callback button that originated the
|
||||
/// query
|
||||
pub message: Option<MaybeInaccessibleMessage>,
|
||||
|
||||
/// An identifier of the message sent via the bot in inline mode, that
|
||||
/// originated the query.
|
||||
|
@ -58,7 +57,13 @@ impl CallbackQuery {
|
|||
use crate::util::flatten;
|
||||
use std::iter::once;
|
||||
|
||||
once(&self.from).chain(flatten(self.message.as_ref().map(Message::mentioned_users)))
|
||||
once(&self.from).chain(flatten(
|
||||
self.message
|
||||
.as_ref()
|
||||
// If we can access the message
|
||||
.and_then(|maybe| maybe.message())
|
||||
.map(Message::mentioned_users),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
13
crates/teloxide-core/src/types/inaccessible_message.rs
Normal file
13
crates/teloxide-core/src/types/inaccessible_message.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, MessageId};
|
||||
|
||||
/// This object describes a message that was deleted or is otherwise
|
||||
/// inaccessible to the bot.
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct InaccessibleMessage {
|
||||
/// Chat the message belonged to
|
||||
pub chat: Chat,
|
||||
/// Unique message identifier inside the chat
|
||||
pub message_id: MessageId,
|
||||
}
|
98
crates/teloxide-core/src/types/maybe_inaccessible_message.rs
Normal file
98
crates/teloxide-core/src/types/maybe_inaccessible_message.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Chat, InaccessibleMessage, Message, MessageId};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum MaybeInaccessibleMessage {
|
||||
Inaccessible(InaccessibleMessage),
|
||||
Regular(Message),
|
||||
}
|
||||
|
||||
impl MaybeInaccessibleMessage {
|
||||
pub fn id(&self) -> MessageId {
|
||||
match self {
|
||||
Self::Inaccessible(i_message) => i_message.message_id,
|
||||
Self::Regular(message) => message.id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn message(&self) -> Option<&Message> {
|
||||
match self {
|
||||
Self::Regular(message) => Some(message),
|
||||
Self::Inaccessible(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chat_and_id(&self) -> (&Chat, MessageId) {
|
||||
(self.chat(), self.id())
|
||||
}
|
||||
|
||||
pub fn chat(&self) -> &Chat {
|
||||
match self {
|
||||
Self::Regular(message) => &message.chat,
|
||||
Self::Inaccessible(i_message) => &i_message.chat,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MaybeInaccessibleMessage {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let message: Message = Message::deserialize(deserializer)?;
|
||||
|
||||
// Thank you, TBA 7.0 authors!
|
||||
if message.date.timestamp() == 0 {
|
||||
return Ok(MaybeInaccessibleMessage::Inaccessible(InaccessibleMessage {
|
||||
chat: message.chat,
|
||||
message_id: message.id,
|
||||
}));
|
||||
}
|
||||
Ok(MaybeInaccessibleMessage::Regular(message))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_inaccessible_message() {
|
||||
let json = r#"{
|
||||
"chat": {
|
||||
"id": 42,
|
||||
"first_name": "Вадим Игоревич",
|
||||
"last_name": "Сырцев",
|
||||
"username": "syrtcevvi",
|
||||
"type": "private"
|
||||
},
|
||||
"message_id": 4,
|
||||
"date": 0
|
||||
}"#;
|
||||
|
||||
let inaccessible_message = serde_json::from_str::<MaybeInaccessibleMessage>(json);
|
||||
assert!(inaccessible_message.is_ok());
|
||||
assert!(matches!(inaccessible_message.unwrap(), MaybeInaccessibleMessage::Inaccessible(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_regular_message() {
|
||||
let json = r#"{
|
||||
"chat": {
|
||||
"id": 42,
|
||||
"first_name": "Вадим Игоревич",
|
||||
"last_name": "Сырцев",
|
||||
"username": "syrtcevvi",
|
||||
"type": "private"
|
||||
},
|
||||
"message_id": 4,
|
||||
"date": 1
|
||||
}"#;
|
||||
|
||||
let regular_message = serde_json::from_str::<MaybeInaccessibleMessage>(json);
|
||||
assert!(regular_message.is_ok());
|
||||
assert!(matches!(regular_message.unwrap(), MaybeInaccessibleMessage::Regular(_)));
|
||||
}
|
||||
}
|
|
@ -8,10 +8,11 @@ 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, MessageOrigin,
|
||||
PassportData, PhotoSize, Poll, ProximityAlertTriggered, Sticker, Story, SuccessfulPayment,
|
||||
ThreadId, True, User, UsersShared, Venue, Video, VideoChatEnded, VideoChatParticipantsInvited,
|
||||
VideoChatScheduled, VideoChatStarted, VideoNote, Voice, WebAppData, WriteAccessAllowed,
|
||||
MaybeInaccessibleMessage, 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,
|
||||
};
|
||||
|
||||
/// This object represents a message.
|
||||
|
@ -245,7 +246,7 @@ pub struct MessagePinned {
|
|||
/// field will not contain further `reply_to_message` fields even if it
|
||||
/// is itself a reply.
|
||||
#[serde(rename = "pinned_message")]
|
||||
pub pinned: Box<Message>,
|
||||
pub pinned: Box<MaybeInaccessibleMessage>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -627,14 +628,14 @@ mod getters {
|
|||
use std::ops::Deref;
|
||||
|
||||
use crate::types::{
|
||||
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,
|
||||
self, message::MessageKind::*, Chat, ChatId, ChatMigration, MaybeInaccessibleMessage,
|
||||
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,
|
||||
};
|
||||
|
@ -1208,7 +1209,7 @@ mod getters {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn pinned_message(&self) -> Option<&Message> {
|
||||
pub fn pinned_message(&self) -> Option<&MaybeInaccessibleMessage> {
|
||||
match &self.kind {
|
||||
Pinned(MessagePinned { pinned }) => Some(pinned),
|
||||
_ => None,
|
||||
|
|
|
@ -220,7 +220,7 @@ impl Update {
|
|||
|
||||
let chat = match &self.kind {
|
||||
Message(m) | EditedMessage(m) | ChannelPost(m) | EditedChannelPost(m) => &m.chat,
|
||||
CallbackQuery(q) => &q.message.as_ref()?.chat,
|
||||
CallbackQuery(q) => q.message.as_ref()?.chat(),
|
||||
ChatMember(m) => &m.chat,
|
||||
MyChatMember(m) => &m.chat,
|
||||
ChatJoinRequest(c) => &c.chat,
|
||||
|
|
|
@ -116,7 +116,8 @@ async fn callback_handler(bot: Bot, q: CallbackQuery) -> Result<(), Box<dyn Erro
|
|||
bot.answer_callback_query(q.id).await?;
|
||||
|
||||
// Edit text of the message to which the buttons were attached
|
||||
if let Some(Message { id, chat, .. }) = q.message {
|
||||
if let Some(maybe_message) = q.message {
|
||||
let (chat, id) = maybe_message.chat_and_id();
|
||||
bot.edit_message_text(chat.id, id, text).await?;
|
||||
} else if let Some(id) = q.inline_message_id {
|
||||
bot.edit_message_text_inline(id, text).await?;
|
||||
|
|
|
@ -16,7 +16,7 @@ impl GetChatId for Message {
|
|||
|
||||
impl GetChatId for CallbackQuery {
|
||||
fn chat_id(&self) -> Option<ChatId> {
|
||||
self.message.as_ref().map(|mes| mes.chat.id)
|
||||
self.message.as_ref().map(|mes| mes.chat().id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue