Skip to main content

tgbot/types/definitions/
update.rs

1use std::{collections::HashSet, time::Duration};
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value as JsonValue;
5
6use crate::{
7    api::{Method, Payload},
8    types::{
9        BusinessConnection,
10        BusinessMessagesDeleted,
11        CallbackQuery,
12        Chat,
13        ChatBoostRemoved,
14        ChatBoostUpdated,
15        ChatJoinRequest,
16        ChatMemberUpdated,
17        ChatPeerId,
18        ChatUsername,
19        ChosenInlineResult,
20        InlineQuery,
21        Integer,
22        ManagedBotUpdated,
23        MaybeInaccessibleMessage,
24        Message,
25        MessageReactionCountUpdated,
26        MessageReactionUpdated,
27        PaidMediaPurchased,
28        Poll,
29        PollAnswer,
30        PollAnswerVoter,
31        PreCheckoutQuery,
32        ShippingQuery,
33        User,
34        UserPeerId,
35        UserUsername,
36    },
37};
38
39/// Represents an incoming update.
40#[derive(Clone, Debug, Deserialize, Serialize)]
41pub struct Update {
42    /// Unique identifier of the update.
43    ///
44    /// Update identifiers start from a certain positive number and increase sequentially.
45    /// This ID becomes especially handy if you’re using Webhooks, since it allows you to
46    /// ignore repeated updates or to restore the correct update sequence,
47    /// should they get out of order.
48    /// If there are no new updates for at least a week, then identifier
49    /// of the next update will be chosen randomly instead of sequentially.
50    #[serde(rename = "update_id")]
51    pub id: Integer,
52    /// Type of the update.
53    #[serde(flatten)]
54    pub update_type: UpdateType,
55}
56
57impl Update {
58    /// Creates a new `Update`.
59    ///
60    /// # Arguments
61    ///
62    /// * `id` - Unique identifier of the update.
63    /// * `update_type` - Type of the update.
64    pub fn new(id: Integer, update_type: UpdateType) -> Self {
65        Self { id, update_type }
66    }
67
68    /// Returns the chat.
69    pub fn get_chat(&self) -> Option<&Chat> {
70        self.get_message().map(|msg| &msg.chat).or(match &self.update_type {
71            UpdateType::BotStatus(x) | UpdateType::UserStatus(x) => Some(&x.chat),
72            UpdateType::DeletedBusinessMessages(x) => Some(&x.chat),
73            UpdateType::ChatBoostRemoved(x) => Some(&x.chat),
74            UpdateType::ChatBoostUpdated(x) => Some(&x.chat),
75            UpdateType::ChatJoinRequest(x) => Some(&x.chat),
76            UpdateType::MessageReaction(x) => Some(&x.chat),
77            UpdateType::MessageReactionCount(x) => Some(&x.chat),
78            _ => None,
79        })
80    }
81
82    /// Returns the ID of the chat.
83    pub fn get_chat_id(&self) -> Option<ChatPeerId> {
84        self.get_chat().map(|chat| chat.get_id())
85    }
86
87    /// Returns the username of the chat.
88    pub fn get_chat_username(&self) -> Option<&ChatUsername> {
89        self.get_chat().and_then(|chat| chat.get_username())
90    }
91
92    /// Returns the user.
93    pub fn get_user(&self) -> Option<&User> {
94        Some(match &self.update_type {
95            UpdateType::BotStatus(x) | UpdateType::UserStatus(x) => &x.from,
96            UpdateType::BusinessConnection(x) => &x.user,
97            UpdateType::CallbackQuery(x) => &x.from,
98            UpdateType::ChatBoostRemoved(_) => return None,
99            UpdateType::ChatBoostUpdated(_) => return None,
100            UpdateType::ChatJoinRequest(x) => &x.from,
101            UpdateType::ChosenInlineResult(x) => &x.from,
102            UpdateType::DeletedBusinessMessages(_) => return None,
103            UpdateType::InlineQuery(x) => &x.from,
104            UpdateType::ManagedBot(x) => &x.user,
105            UpdateType::Message(x)
106            | UpdateType::BusinessMessage(x)
107            | UpdateType::ChannelPost(x)
108            | UpdateType::EditedBusinessMessage(x)
109            | UpdateType::EditedChannelPost(x)
110            | UpdateType::EditedMessage(x)
111            | UpdateType::GuestMessage(x) => return x.sender.get_user(),
112            UpdateType::MessageReaction(x) => return x.user.as_ref(),
113            UpdateType::MessageReactionCount(_) => return None,
114            UpdateType::Poll(_) => return None,
115            UpdateType::PollAnswer(x) => match &x.voter {
116                PollAnswerVoter::User(x) => x,
117                PollAnswerVoter::Chat(_) => return None,
118            },
119            UpdateType::PreCheckoutQuery(x) => &x.from,
120            UpdateType::PurchasedPaidMedia(x) => &x.from,
121            UpdateType::ShippingQuery(x) => &x.from,
122            UpdateType::Unknown(_) => return None,
123        })
124    }
125
126    /// Returns the ID of the user.
127    pub fn get_user_id(&self) -> Option<UserPeerId> {
128        self.get_user().map(|user| user.id)
129    }
130
131    /// Returns the username of the user.
132    pub fn get_user_username(&self) -> Option<&UserUsername> {
133        self.get_user().and_then(|user| user.username.as_ref())
134    }
135
136    /// Returns the message.
137    pub fn get_message(&self) -> Option<&Message> {
138        match &self.update_type {
139            UpdateType::Message(msg)
140            | UpdateType::BusinessMessage(msg)
141            | UpdateType::ChannelPost(msg)
142            | UpdateType::EditedBusinessMessage(msg)
143            | UpdateType::EditedChannelPost(msg)
144            | UpdateType::EditedMessage(msg)
145            | UpdateType::GuestMessage(msg) => Some(msg),
146            UpdateType::CallbackQuery(query) => match &query.message {
147                Some(MaybeInaccessibleMessage::Message(msg)) => Some(msg),
148                _ => None,
149            },
150            _ => None,
151        }
152    }
153}
154
155/// Represents a type of an update.
156#[derive(Clone, Debug, Deserialize, Serialize)]
157#[serde(rename_all = "snake_case")]
158pub enum UpdateType {
159    /// The bot chat member status was updated in a chat.
160    ///
161    /// For private chats, this update is received only
162    /// when the bot is blocked or unblocked by the user.
163    #[serde(rename = "my_chat_member")]
164    BotStatus(Box<ChatMemberUpdated>),
165    /// The bot was connected to or disconnected from a business account,
166    /// or a user edited an existing connection with the bot.
167    BusinessConnection(Box<BusinessConnection>),
168    /// New non-service message from a connected business account.
169    BusinessMessage(Box<Message>),
170    /// A new incoming callback query.
171    CallbackQuery(Box<CallbackQuery>),
172    /// A new incoming channel post.
173    ChannelPost(Box<Message>),
174    /// A boost was removed from a chat.
175    ///
176    /// The bot must be an administrator in the chat to receive these updates.
177    #[serde(rename = "removed_chat_boost")]
178    ChatBoostRemoved(Box<ChatBoostRemoved>),
179    /// A chat boost was added or changed.
180    ///
181    /// The bot must be an administrator in the chat to receive these updates.
182    #[serde(rename = "chat_boost")]
183    ChatBoostUpdated(Box<ChatBoostUpdated>),
184    /// A request to join the chat has been sent.
185    ///
186    /// The bot must have the `can_invite_users` administrator right
187    /// in the chat to receive these updates.
188    ChatJoinRequest(Box<ChatJoinRequest>),
189    /// The result of an inline query that was chosen by a user and sent to their chat partner.
190    ///
191    /// Please see our documentation on the [feedback collecting][1]
192    /// for details on how to enable these updates for your bot.
193    ///
194    /// [1]: https://core.telegram.org/bots/inline#collecting-feedback
195    ChosenInlineResult(Box<ChosenInlineResult>),
196    /// Messages were deleted from a connected business account.
197    DeletedBusinessMessages(Box<BusinessMessagesDeleted>),
198    /// New version of a message from a connected business account.
199    EditedBusinessMessage(Box<Message>),
200    /// A new version of a channel post that is known to the bot and was edited.
201    EditedChannelPost(Box<Message>),
202    /// A new version of a message that is known to the bot and was edited.
203    EditedMessage(Box<Message>),
204    /// A new guest message.
205    GuestMessage(Box<Message>),
206    /// A new incoming [inline][1] query.
207    ///
208    /// [1]: https://core.telegram.org/bots/api#inline-mode
209    InlineQuery(Box<InlineQuery>),
210    /// A new bot was created to be managed by the bot, or token or owner of a managed bot was changed.
211    ManagedBot(ManagedBotUpdated),
212    /// A new incoming message.
213    Message(Box<Message>),
214    /// A reaction to a message was changed by a user.
215    ///
216    /// The bot must be an administrator in the chat
217    /// and must explicitly specify [`AllowedUpdate::MessageReaction`]
218    /// in the list of allowed_updates to receive these updates.
219    ///
220    /// The update isn't received for reactions set by bots.
221    MessageReaction(Box<MessageReactionUpdated>),
222    /// Reactions to a message with anonymous reactions were changed.
223    ///
224    /// The bot must be an administrator in the chat
225    /// and must explicitly specify [`AllowedUpdate::MessageReactionCount`]
226    /// in the list of allowed_updates to receive these updates.
227    MessageReactionCount(Box<MessageReactionCountUpdated>),
228    /// A new poll state.
229    ///
230    /// Bots receive only updates about polls, which are sent or stopped by the bot.
231    Poll(Box<Poll>),
232    /// A user changed their answer in a non-anonymous poll
233    ///
234    /// Bots receive new votes only in polls that were sent by the bot itself.
235    PollAnswer(Box<PollAnswer>),
236    /// A new incoming pre-checkout query.
237    ///
238    /// Contains full information about checkout
239    PreCheckoutQuery(Box<PreCheckoutQuery>),
240    /// A user purchased paid media with a non-empty payload sent by the bot in a non-channel chat.
241    PurchasedPaidMedia(Box<PaidMediaPurchased>),
242    /// A new incoming shipping query.
243    ///
244    /// Only for invoices with flexible price.
245    ShippingQuery(Box<ShippingQuery>),
246    /// A chat member's status was updated in a chat.
247    ///
248    /// The bot must be an administrator in the chat
249    /// and must explicitly specify [`AllowedUpdate::UserStatus`] in the list
250    /// of `allowed_updates` to receive these updates.
251    #[serde(rename = "chat_member")]
252    UserStatus(Box<ChatMemberUpdated>),
253    /// Used for unknown update types.
254    ///
255    /// For example, Telegram introduced a new update type,
256    /// but tgbot does not support it.
257    #[serde(untagged)]
258    Unknown(JsonValue),
259}
260
261/// Conversion of an [`Update`] into `T` failed.
262///
263/// Use [`Update::from`] to get the original update.
264pub struct UnexpectedUpdate(Update);
265
266impl From<UnexpectedUpdate> for Update {
267    fn from(value: UnexpectedUpdate) -> Self {
268        value.0
269    }
270}
271
272impl TryFrom<Update> for BusinessConnection {
273    type Error = UnexpectedUpdate;
274
275    fn try_from(value: Update) -> Result<Self, Self::Error> {
276        use self::UpdateType::*;
277        match value.update_type {
278            BusinessConnection(x) => Ok(*x),
279            _ => Err(UnexpectedUpdate(value)),
280        }
281    }
282}
283
284impl TryFrom<Update> for BusinessMessagesDeleted {
285    type Error = UnexpectedUpdate;
286
287    fn try_from(value: Update) -> Result<Self, Self::Error> {
288        use self::UpdateType::*;
289        match value.update_type {
290            DeletedBusinessMessages(x) => Ok(*x),
291            _ => Err(UnexpectedUpdate(value)),
292        }
293    }
294}
295
296impl TryFrom<Update> for ChatMemberUpdated {
297    type Error = UnexpectedUpdate;
298
299    fn try_from(value: Update) -> Result<Self, Self::Error> {
300        use self::UpdateType::*;
301        match value.update_type {
302            BotStatus(x) | UserStatus(x) => Ok(*x),
303            _ => Err(UnexpectedUpdate(value)),
304        }
305    }
306}
307
308impl TryFrom<Update> for CallbackQuery {
309    type Error = UnexpectedUpdate;
310
311    fn try_from(value: Update) -> Result<Self, Self::Error> {
312        use self::UpdateType::*;
313        match value.update_type {
314            CallbackQuery(x) => Ok(*x),
315            _ => Err(UnexpectedUpdate(value)),
316        }
317    }
318}
319
320impl TryFrom<Update> for ChatJoinRequest {
321    type Error = UnexpectedUpdate;
322
323    fn try_from(value: Update) -> Result<Self, Self::Error> {
324        use self::UpdateType::*;
325        match value.update_type {
326            ChatJoinRequest(x) => Ok(*x),
327            _ => Err(UnexpectedUpdate(value)),
328        }
329    }
330}
331
332impl TryFrom<Update> for ChosenInlineResult {
333    type Error = UnexpectedUpdate;
334
335    fn try_from(value: Update) -> Result<Self, Self::Error> {
336        use self::UpdateType::*;
337        match value.update_type {
338            ChosenInlineResult(x) => Ok(*x),
339            _ => Err(UnexpectedUpdate(value)),
340        }
341    }
342}
343
344impl TryFrom<Update> for InlineQuery {
345    type Error = UnexpectedUpdate;
346
347    fn try_from(value: Update) -> Result<Self, Self::Error> {
348        use self::UpdateType::*;
349        match value.update_type {
350            InlineQuery(x) => Ok(*x),
351            _ => Err(UnexpectedUpdate(value)),
352        }
353    }
354}
355
356impl TryFrom<Update> for Message {
357    type Error = UnexpectedUpdate;
358
359    fn try_from(value: Update) -> Result<Self, Self::Error> {
360        use self::UpdateType::*;
361        match value.update_type {
362            BusinessMessage(x)
363            | EditedBusinessMessage(x)
364            | EditedChannelPost(x)
365            | EditedMessage(x)
366            | GuestMessage(x)
367            | ChannelPost(x)
368            | Message(x) => Ok(*x),
369            _ => Err(UnexpectedUpdate(value)),
370        }
371    }
372}
373
374impl TryFrom<Update> for Poll {
375    type Error = UnexpectedUpdate;
376
377    fn try_from(value: Update) -> Result<Self, Self::Error> {
378        use self::UpdateType::*;
379        match value.update_type {
380            Poll(x) => Ok(*x),
381            _ => Err(UnexpectedUpdate(value)),
382        }
383    }
384}
385
386impl TryFrom<Update> for PollAnswer {
387    type Error = UnexpectedUpdate;
388
389    fn try_from(value: Update) -> Result<Self, Self::Error> {
390        use self::UpdateType::*;
391        match value.update_type {
392            PollAnswer(x) => Ok(*x),
393            _ => Err(UnexpectedUpdate(value)),
394        }
395    }
396}
397
398impl TryFrom<Update> for PreCheckoutQuery {
399    type Error = UnexpectedUpdate;
400
401    fn try_from(value: Update) -> Result<Self, Self::Error> {
402        use self::UpdateType::*;
403        match value.update_type {
404            PreCheckoutQuery(x) => Ok(*x),
405            _ => Err(UnexpectedUpdate(value)),
406        }
407    }
408}
409
410impl TryFrom<Update> for PaidMediaPurchased {
411    type Error = UnexpectedUpdate;
412
413    fn try_from(value: Update) -> Result<Self, Self::Error> {
414        use self::UpdateType::*;
415        match value.update_type {
416            PurchasedPaidMedia(x) => Ok(*x),
417            _ => Err(UnexpectedUpdate(value)),
418        }
419    }
420}
421
422impl TryFrom<Update> for ShippingQuery {
423    type Error = UnexpectedUpdate;
424
425    fn try_from(value: Update) -> Result<Self, Self::Error> {
426        use self::UpdateType::*;
427        match value.update_type {
428            ShippingQuery(x) => Ok(*x),
429            _ => Err(UnexpectedUpdate(value)),
430        }
431    }
432}
433
434/// Represents a type of update to receive.
435#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
436#[serde(rename_all = "snake_case")]
437pub enum AllowedUpdate {
438    /// The bot chat member status.
439    #[serde(rename = "my_chat_member")]
440    BotStatus,
441    /// Business account connection changes.
442    BusinessConnection,
443    /// New non-service message from a connected business account.
444    BusinessMessage,
445    /// A callback query.
446    CallbackQuery,
447    /// A channel post.
448    ChannelPost,
449    /// A boost was removed from a chat.
450    #[serde(rename = "removed_chat_boost")]
451    ChatBoostRemoved,
452    /// A chat boost was added or changed.
453    #[serde(rename = "chat_boost")]
454    ChatBoostUpdated,
455    /// A request to join a chat.
456    ChatJoinRequest,
457    /// A chosen inline result.
458    ChosenInlineResult,
459    /// Messages were deleted from a connected business account.
460    DeletedBusinessMessages,
461    /// New version of a message from a connected business account.
462    EditedBusinessMessage,
463    /// An edited channel post.
464    EditedChannelPost,
465    /// An edited message.
466    EditedMessage,
467    /// A new guest message.
468    GuestMessage,
469    /// An inline query.
470    InlineQuery,
471    /// A message.
472    Message,
473    /// A reaction to a message.
474    MessageReaction,
475    /// An anonymous reaction to a message.
476    MessageReactionCount,
477    /// A poll.
478    Poll,
479    /// A poll answer.
480    PollAnswer,
481    /// A pre checkout query.
482    PreCheckoutQuery,
483    /// A user purchased paid media.
484    PurchasedPaidMedia,
485    /// A shipping query.
486    ShippingQuery,
487    /// A chat member status.
488    #[serde(rename = "chat_member")]
489    UserStatus,
490}
491
492#[serde_with::skip_serializing_none]
493/// Returns incoming updates using long polling.
494#[derive(Clone, Debug, Default, Serialize)]
495pub struct GetUpdates {
496    allowed_updates: Option<HashSet<AllowedUpdate>>,
497    limit: Option<Integer>,
498    offset: Option<Integer>,
499    timeout: Option<Integer>,
500}
501
502impl Method for GetUpdates {
503    type Response = Vec<Update>;
504
505    fn into_payload(self) -> Payload {
506        Payload::json("getUpdates", self)
507    }
508}
509
510impl GetUpdates {
511    /// Adds a type of an update you want your bot to receive.
512    ///
513    /// # Arguments
514    ///
515    /// * `value` - The type to add.
516    pub fn add_allowed_update(mut self, value: AllowedUpdate) -> Self {
517        match self.allowed_updates {
518            Some(ref mut updates) => {
519                updates.insert(value);
520            }
521            None => {
522                let mut updates = HashSet::new();
523                updates.insert(value);
524                self.allowed_updates = Some(updates);
525            }
526        };
527        self
528    }
529
530    /// Sets a new list of allowed updates.
531    ///
532    /// # Arguments
533    ///
534    /// * `value` - List of the types of updates you want your bot to receive.
535    ///
536    /// For example, specify `[AllowedUpdate::Message, AllowedUpdate::EditedChannelPost]`
537    /// to only receive updates of these types.
538    /// Specify an empty list to receive all updates regardless of type (default).
539    /// If not specified, the previous setting will be used.
540    /// Please note that this parameter doesn't affect updates
541    /// created before the call to the method,
542    /// so unwanted updates may be received for a short period of time.
543    pub fn with_allowed_updates<T>(mut self, value: T) -> Self
544    where
545        T: IntoIterator<Item = AllowedUpdate>,
546    {
547        self.allowed_updates = Some(value.into_iter().collect());
548        self
549    }
550
551    /// Sets a new limit.
552    ///
553    /// # Arguments
554    ///
555    /// * `value` - Limit of the number of updates to be retrieved; 1—100; default - 100.
556    pub fn with_limit(mut self, value: Integer) -> Self {
557        self.limit = Some(value);
558        self
559    }
560
561    /// Sets a new offset.
562    ///
563    /// # Arguments
564    ///
565    /// * `value` - Identifier of the first update to be returned.
566    ///
567    /// Must be greater by one than the highest
568    /// among the identifiers of previously received updates.
569    /// By default, updates starting with the earliest unconfirmed update are returned.
570    /// An update is considered confirmed as soon as the method is called with
571    /// an offset higher than its `update_id`.
572    /// The negative offset can be specified to retrieve updates starting
573    /// from `-offset` update from the end of the updates queue.
574    /// All previous updates will forgotten.
575    pub fn with_offset(mut self, value: Integer) -> Self {
576        self.offset = Some(value);
577        self
578    }
579
580    /// Sets a new timeout.
581    ///
582    /// # Arguments
583    ///
584    /// * `value` - Timeout for long polling; default - 0, i.e. usual short polling; should be positive;
585    ///   short polling should be used for testing purposes only.
586    pub fn with_timeout(mut self, value: Duration) -> Self {
587        self.timeout = Some(value.as_secs() as i64);
588        self
589    }
590}