Merge pull request #892 from teloxide/type_update_id

Add `UpdateId`
This commit is contained in:
Sima Kinsart 2023-06-15 14:30:07 +00:00 committed by GitHub
commit 7e1c1c3e4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 87 deletions

View file

@ -60,11 +60,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `PollAnswer::option_ids` now use `u8` instead of `i32` ([#887][pr887]) - `PollAnswer::option_ids` now use `u8` instead of `i32` ([#887][pr887])
- Use `u32` for sizes and `Seconds` for timespans in `InlineQueryResult*` ([#887][pr887]) - Use `u32` for sizes and `Seconds` for timespans in `InlineQueryResult*` ([#887][pr887])
- `SendGame::reply_to_message_id`, `SendSticker::reply_to_message_id` and `SendInvoice::reply_to_message_id` now use `MessageId` instead of `i32` ([#887][pr887]) - `SendGame::reply_to_message_id`, `SendSticker::reply_to_message_id` and `SendInvoice::reply_to_message_id` now use `MessageId` instead of `i32` ([#887][pr887])
- Use `UpdateId` for `Update::id` ([#892][pr892])
[pr852]: https://github.com/teloxide/teloxide/pull/853 [pr852]: https://github.com/teloxide/teloxide/pull/853
[pr859]: https://github.com/teloxide/teloxide/pull/859 [pr859]: https://github.com/teloxide/teloxide/pull/859
[pr876]: https://github.com/teloxide/teloxide/pull/876 [pr876]: https://github.com/teloxide/teloxide/pull/876
[pr885]: https://github.com/teloxide/teloxide/pull/885 [pr885]: https://github.com/teloxide/teloxide/pull/885
[pr892]: https://github.com/teloxide/teloxide/pull/892
### Deprecated ### Deprecated

View file

@ -162,13 +162,11 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::types::{ChatId, Seconds};
use cool_asserts::assert_matches; use cool_asserts::assert_matches;
use crate::{ use crate::{
net::request::deserialize_response, net::request::deserialize_response,
types::{True, Update, UpdateKind}, types::{ChatId, Seconds, True, Update, UpdateId, UpdateKind},
ApiError, RequestError, ApiError, RequestError,
}; };
@ -223,7 +221,7 @@ mod tests {
.to_owned(); .to_owned();
let res = deserialize_response::<Vec<Update>>(json).unwrap(); let res = deserialize_response::<Vec<Update>>(json).unwrap();
assert_matches!(res, [Update { id: 0, kind: UpdateKind::PollAnswer(_) }]); assert_matches!(res, [Update { id: UpdateId(0), kind: UpdateKind::PollAnswer(_) }]);
} }
/// Check that `get_updates` can work with malformed updates. /// Check that `get_updates` can work with malformed updates.
@ -264,10 +262,10 @@ mod tests {
assert_matches!( assert_matches!(
res, res,
[ [
Update { id: 0, kind: UpdateKind::PollAnswer(_) }, Update { id: UpdateId(0), kind: UpdateKind::PollAnswer(_) },
Update { id: 1, kind: UpdateKind::Error(v) } if v.is_object(), Update { id: UpdateId(1), kind: UpdateKind::Error(v) } if v.is_object(),
Update { id: 2, kind: UpdateKind::PollAnswer(_) }, Update { id: UpdateId(2), kind: UpdateKind::PollAnswer(_) },
Update { id: 3, kind: UpdateKind::Error(v) } if v.is_object(), Update { id: UpdateId(3), kind: UpdateKind::Error(v) } if v.is_object(),
] ]
); );
} }

View file

@ -22,12 +22,101 @@ pub struct Update {
/// week, then identifier of the next update will be chosen randomly /// week, then identifier of the next update will be chosen randomly
/// instead of sequentially. /// instead of sequentially.
#[serde(rename = "update_id")] #[serde(rename = "update_id")]
pub id: i32, pub id: UpdateId,
#[serde(flatten)] #[serde(flatten)]
pub kind: UpdateKind, pub kind: UpdateKind,
} }
/// An identifier of a telegram update.
///
/// See [`Update::id`] for more information.
#[derive(Clone, Copy)]
#[derive(Debug)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct UpdateId(pub u32);
#[derive(Clone, Debug, PartialEq)]
pub enum UpdateKind {
// NB: When adding new variants, don't forget to update
// - `AllowedUpdate`
// - `Update::user`
// - `Update::chat`
// - `DpHandlerDescription::full_set`
// - `dispatching/filter_ext.rs`
/// New incoming message of any kind — text, photo, sticker, etc.
Message(Message),
/// New version of a message that is known to the bot and was edited.
EditedMessage(Message),
/// New incoming channel post of any kind — text, photo, sticker, etc.
ChannelPost(Message),
/// New version of a channel post that is known to the bot and was edited.
EditedChannelPost(Message),
/// New incoming [inline] query.
///
/// [inline]: https://core.telegram.org/bots/api#inline-mode
InlineQuery(InlineQuery),
/// The result of an [inline] query that was chosen by a user and sent to
/// their chat partner. Please see our documentation on the [feedback
/// collecting] for details on how to enable these updates for your bot.
///
/// [inline]: https://core.telegram.org/bots/api#inline-mode
/// [feedback collecting]: https://core.telegram.org/bots/inline#collecting-feedback
ChosenInlineResult(ChosenInlineResult),
/// New incoming callback query.
CallbackQuery(CallbackQuery),
/// New incoming shipping query. Only for invoices with flexible price.
ShippingQuery(ShippingQuery),
/// New incoming pre-checkout query. Contains full information about
/// checkout.
PreCheckoutQuery(PreCheckoutQuery),
/// New poll state. Bots receive only updates about stopped polls and
/// polls, which are sent by the bot.
Poll(Poll),
/// A user changed their answer in a non-anonymous poll. Bots receive new
/// votes only in polls that were sent by the bot itself.
PollAnswer(PollAnswer),
/// The bot's chat member status was updated in a chat. For private chats,
/// this update is received only when the bot is blocked or unblocked by the
/// user.
MyChatMember(ChatMemberUpdated),
/// A chat member's status was updated in a chat. The bot must be an
/// administrator in the chat and must explicitly specify
/// [`AllowedUpdate::ChatMember`] in the list of `allowed_updates` to
/// receive these updates.
///
/// [`AllowedUpdate::ChatMember`]: crate::types::AllowedUpdate::ChatMember
ChatMember(ChatMemberUpdated),
/// A request to join the chat has been sent. The bot must have the
/// can_invite_users administrator right in the chat to receive these
/// updates.
ChatJoinRequest(ChatJoinRequest),
/// An error that happened during deserialization.
///
/// This allows `teloxide` to continue working even if telegram adds a new
/// kinds of updates.
///
/// **Note that deserialize implementation always returns an empty value**,
/// teloxide fills in the data when doing deserialization.
Error(Value),
}
impl Update { impl Update {
/// Returns the user that performed the action that caused this update, if /// Returns the user that performed the action that caused this update, if
/// known. /// known.
@ -129,83 +218,16 @@ impl Update {
} }
} }
#[derive(Clone, Debug, PartialEq)] impl UpdateId {
pub enum UpdateKind { /// Returns the offset for the **next** update that can be used for polling.
// NB: When adding new variants, don't forget to update
// - `AllowedUpdate`
// - `Update::user`
// - `Update::chat`
// - `DpHandlerDescription::full_set`
// - `dispatching/filter_ext.rs`
/// New incoming message of any kind — text, photo, sticker, etc.
Message(Message),
/// New version of a message that is known to the bot and was edited.
EditedMessage(Message),
/// New incoming channel post of any kind — text, photo, sticker, etc.
ChannelPost(Message),
/// New version of a channel post that is known to the bot and was edited.
EditedChannelPost(Message),
/// New incoming [inline] query.
/// ///
/// [inline]: https://core.telegram.org/bots/api#inline-mode /// I.e. `self.0 + 1`.
InlineQuery(InlineQuery), #[must_use]
pub fn as_offset(self) -> i32 {
debug_assert!(self.0 < i32::MAX as u32);
/// The result of an [inline] query that was chosen by a user and sent to self.0 as i32 + 1
/// their chat partner. Please see our documentation on the [feedback }
/// collecting] for details on how to enable these updates for your bot.
///
/// [inline]: https://core.telegram.org/bots/api#inline-mode
/// [feedback collecting]: https://core.telegram.org/bots/inline#collecting-feedback
ChosenInlineResult(ChosenInlineResult),
/// New incoming callback query.
CallbackQuery(CallbackQuery),
/// New incoming shipping query. Only for invoices with flexible price.
ShippingQuery(ShippingQuery),
/// New incoming pre-checkout query. Contains full information about
/// checkout.
PreCheckoutQuery(PreCheckoutQuery),
/// New poll state. Bots receive only updates about stopped polls and
/// polls, which are sent by the bot.
Poll(Poll),
/// A user changed their answer in a non-anonymous poll. Bots receive new
/// votes only in polls that were sent by the bot itself.
PollAnswer(PollAnswer),
/// The bot's chat member status was updated in a chat. For private chats,
/// this update is received only when the bot is blocked or unblocked by the
/// user.
MyChatMember(ChatMemberUpdated),
/// A chat member's status was updated in a chat. The bot must be an
/// administrator in the chat and must explicitly specify
/// [`AllowedUpdate::ChatMember`] in the list of `allowed_updates` to
/// receive these updates.
///
/// [`AllowedUpdate::ChatMember`]: crate::types::AllowedUpdate::ChatMember
ChatMember(ChatMemberUpdated),
/// A request to join the chat has been sent. The bot must have the
/// can_invite_users administrator right in the chat to receive these
/// updates.
ChatJoinRequest(ChatJoinRequest),
/// An error that happened during deserialization.
///
/// This allows `teloxide` to continue working even if telegram adds a new
/// kinds of updates.
///
/// **Note that deserialize implementation always returns an empty value**,
/// teloxide fills in the data when doing deserialization.
Error(Value),
} }
impl<'de> Deserialize<'de> for UpdateKind { impl<'de> Deserialize<'de> for UpdateKind {
@ -344,7 +366,7 @@ fn empty_error() -> UpdateKind {
mod test { mod test {
use crate::types::{ use crate::types::{
Chat, ChatId, ChatKind, ChatPrivate, MediaKind, MediaText, Message, MessageCommon, Chat, ChatId, ChatKind, ChatPrivate, MediaKind, MediaText, Message, MessageCommon,
MessageId, MessageKind, Update, UpdateKind, User, UserId, MessageId, MessageKind, Update, UpdateId, UpdateKind, User, UserId,
}; };
use chrono::{DateTime, NaiveDateTime, Utc}; use chrono::{DateTime, NaiveDateTime, Utc};
@ -379,7 +401,7 @@ mod test {
}"#; }"#;
let expected = Update { let expected = Update {
id: 892_252_934, id: UpdateId(892_252_934),
kind: UpdateKind::Message(Message { kind: UpdateKind::Message(Message {
via_bot: None, via_bot: None,
id: MessageId(6557), id: MessageId(6557),

View file

@ -354,7 +354,7 @@ impl<B: Requester> Stream for PollingStream<'_, B> {
} }
Ok(updates) => { Ok(updates) => {
if let Some(upd) = updates.last() { if let Some(upd) = updates.last() {
*this.offset = upd.id + 1; *this.offset = upd.id.as_offset();
} }
match *this.drop_pending_updates { match *this.drop_pending_updates {