From 529b38afee20bf855cbd48d566149b015f840f72 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 29 Jul 2023 14:03:10 +0400 Subject: [PATCH 1/6] Add a way to go `ChatId` -> `UserId` --- crates/teloxide-core/CHANGELOG.md | 2 ++ crates/teloxide-core/src/types/chat_id.rs | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index 72b70c74..b6160207 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -16,9 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Seconds` type, which represents a duration is seconds ([#859][pr859]) - `VideoChatEnded::duration` field that was previously missed ([#859][pr859]) - `ThreadId` newtype over `MessageId`, used for identifying reply threads ([#887][pr887]) +- `ChatId::as_user` ([#905][pr905]) [pr851]: https://github.com/teloxide/teloxide/pull/851 [pr887]: https://github.com/teloxide/teloxide/pull/887 +[pr905]: https://github.com/teloxide/teloxide/pull/905 ### Fixed diff --git a/crates/teloxide-core/src/types/chat_id.rs b/crates/teloxide-core/src/types/chat_id.rs index cccbc4a3..71363115 100644 --- a/crates/teloxide-core/src/types/chat_id.rs +++ b/crates/teloxide-core/src/types/chat_id.rs @@ -50,6 +50,15 @@ impl ChatId { matches!(self.to_bare(), BareChatId::Channel(_)) } + /// Returns user id, if this is an id of a user. + #[must_use] + pub fn as_user(self) -> Option { + match self.to_bare() { + BareChatId::User(u) => Some(u), + BareChatId::Group(_) | BareChatId::Channel(_) => None, + } + } + /// Converts this id to "bare" MTProto peer id. /// /// See [`BareChatId`] for more. From 4ccf24c7ab7568d8969382ca283445ed1aa2a339 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 29 Jul 2023 14:07:19 +0400 Subject: [PATCH 2/6] Allow comparing `UserId`s and `ChatId`s --- crates/teloxide-core/CHANGELOG.md | 1 + crates/teloxide-core/src/types/chat_id.rs | 18 ++++++++++++++++++ crates/teloxide-core/src/types/user_id.rs | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index b6160207..48216103 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `VideoChatEnded::duration` field that was previously missed ([#859][pr859]) - `ThreadId` newtype over `MessageId`, used for identifying reply threads ([#887][pr887]) - `ChatId::as_user` ([#905][pr905]) +- Implement `PartialEq for UserId` and `PartialEq for ChatId` ([#905][pr905]) [pr851]: https://github.com/teloxide/teloxide/pull/851 [pr887]: https://github.com/teloxide/teloxide/pull/887 diff --git a/crates/teloxide-core/src/types/chat_id.rs b/crates/teloxide-core/src/types/chat_id.rs index 71363115..f9cdb32c 100644 --- a/crates/teloxide-core/src/types/chat_id.rs +++ b/crates/teloxide-core/src/types/chat_id.rs @@ -82,6 +82,12 @@ impl From for ChatId { } } +impl PartialEq for ChatId { + fn eq(&self, other: &UserId) -> bool { + self.is_user() && *self == ChatId::from(*other) + } +} + impl BareChatId { /// Converts bare chat id back to normal bot API [`ChatId`]. #[allow(unused)] @@ -152,4 +158,16 @@ mod tests { fn display() { assert_eq!(ChatId(1).to_string(), "1"); } + + #[test] + fn user_id_eq() { + assert_eq!(ChatId(12), UserId(12)); + assert_eq!(ChatId(4652762), UserId(4652762)); + assert_ne!(ChatId(17), UserId(42)); + + // The user id is not well formed, so even though `-1 == max` is true, + // we don't want user id to match + assert_eq!(-1i64, u64::MAX as i64); + assert_ne!(ChatId(-1), UserId(u64::MAX)); + } } diff --git a/crates/teloxide-core/src/types/user_id.rs b/crates/teloxide-core/src/types/user_id.rs index 57c95d13..625a1691 100644 --- a/crates/teloxide-core/src/types/user_id.rs +++ b/crates/teloxide-core/src/types/user_id.rs @@ -1,5 +1,7 @@ use serde::{Deserialize, Serialize}; +use crate::types::ChatId; + /// Identifier of a user. #[derive(Clone, Copy)] #[derive(Debug, derive_more::Display)] @@ -52,6 +54,13 @@ impl UserId { } } +impl PartialEq for UserId { + fn eq(&self, other: &ChatId) -> bool { + // Reuse `PartialEq for ChatId` impl + other == self + } +} + #[cfg(test)] mod tests { use serde::{Deserialize, Serialize}; From ae0451f7d72e78fdeb317db397fb602a29eda17a Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 29 Jul 2023 14:09:09 +0400 Subject: [PATCH 3/6] Add `UserId::{MIN, MAX}` constants --- crates/teloxide-core/CHANGELOG.md | 1 + crates/teloxide-core/src/types/chat_id.rs | 4 ++-- crates/teloxide-core/src/types/user_id.rs | 8 +++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index 48216103..6cfbee78 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ThreadId` newtype over `MessageId`, used for identifying reply threads ([#887][pr887]) - `ChatId::as_user` ([#905][pr905]) - Implement `PartialEq for UserId` and `PartialEq for ChatId` ([#905][pr905]) +- `ChatId::{MIN, MAX}` ([#905][pr905]) [pr851]: https://github.com/teloxide/teloxide/pull/851 [pr887]: https://github.com/teloxide/teloxide/pull/887 diff --git a/crates/teloxide-core/src/types/chat_id.rs b/crates/teloxide-core/src/types/chat_id.rs index f9cdb32c..336d3f91 100644 --- a/crates/teloxide-core/src/types/chat_id.rs +++ b/crates/teloxide-core/src/types/chat_id.rs @@ -107,8 +107,8 @@ const MIN_MARKED_CHANNEL_ID: i64 = -1997852516352; const MAX_MARKED_CHANNEL_ID: i64 = -1000000000000; const MIN_MARKED_CHAT_ID: i64 = MAX_MARKED_CHANNEL_ID + 1; const MAX_MARKED_CHAT_ID: i64 = MIN_USER_ID - 1; -const MIN_USER_ID: i64 = 0; -const MAX_USER_ID: i64 = (1 << 40) - 1; +pub(crate) const MIN_USER_ID: i64 = 0; +pub(crate) const MAX_USER_ID: i64 = (1 << 40) - 1; #[cfg(test)] mod tests { diff --git a/crates/teloxide-core/src/types/user_id.rs b/crates/teloxide-core/src/types/user_id.rs index 625a1691..4c102a36 100644 --- a/crates/teloxide-core/src/types/user_id.rs +++ b/crates/teloxide-core/src/types/user_id.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use crate::types::ChatId; +use crate::types::{ChatId, MAX_USER_ID, MIN_USER_ID}; /// Identifier of a user. #[derive(Clone, Copy)] @@ -52,6 +52,12 @@ impl UserId { self == TELEGRAM_USER_ID } + + /// The smallest user id that could possibly be returned by Telegram. + pub const MIN: Self = Self(MIN_USER_ID as u64); + + /// The largest user id that could possibly be returned by Telegram. + pub const MAX: Self = Self(MAX_USER_ID as u64); } impl PartialEq for UserId { From 86a145e805fd155541c1806ed753a099f5ac885d Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 29 Jul 2023 14:42:31 +0400 Subject: [PATCH 4/6] Make `mentioned_users` somewhat less terrible --- crates/teloxide-core/src/types/update.rs | 35 ++++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index 4c5ff6f4..3ccd8c3e 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -154,16 +154,35 @@ impl Update { /// replies, pinned messages, message entities, "via bot" fields and more. /// Also note that this function can return duplicate users. pub fn mentioned_users(&self) -> impl Iterator { - use either::Either::{Left, Right}; + use either::Either::{Left as L, Right as R}; use std::iter::{empty, once}; - let i0 = Left; - let i1 = |x| Right(Left(x)); - let i2 = |x| Right(Right(Left(x))); - let i3 = |x| Right(Right(Right(Left(x)))); - let i4 = |x| Right(Right(Right(Right(Left(x))))); - let i5 = |x| Right(Right(Right(Right(Right(Left(x)))))); - let i6 = |x| Right(Right(Right(Right(Right(Right(x)))))); + // [root] + // / \ + // left - / \ - right + // / \ + // /\ /\ + // / \ / \ + // / \ / \ + // 0 /\ /\ /\ + // / \ / \ / \ + // 1 2 3 4 5 6 + // + // 0 = LL + // 1 = LRL + // 2 = LRR + // 3 = RLL + // 4 = RLR + // 5 = RRL + // 6 = RRR + + let i0 = |x| L(L(x)); + let i1 = |x| L(R(L(x))); + let i2 = |x| L(R(R(x))); + let i3 = |x| R(L(L(x))); + let i4 = |x| R(L(R(x))); + let i5 = |x| R(R(L(x))); + let i6 = |x| R(R(R(x))); match &self.kind { UpdateKind::Message(message) From aca9f9583d9c63aa4d363a87e9a623c86347bba7 Mon Sep 17 00:00:00 2001 From: TheAwiteb Date: Thu, 7 Sep 2023 21:42:29 +0300 Subject: [PATCH 5/6] Bump `chrono` to `v0.4.30` --- crates/teloxide-core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/teloxide-core/Cargo.toml b/crates/teloxide-core/Cargo.toml index 4df1fc7b..0f67fddf 100644 --- a/crates/teloxide-core/Cargo.toml +++ b/crates/teloxide-core/Cargo.toml @@ -72,7 +72,7 @@ takecell = "0.1" take_mut = "0.2" rc-box = "1.1.1" never = "0.1.0" -chrono = { version = "0.4.19", default-features = false } +chrono = { version = "0.4.30", default-features = false } either = "1.6.1" bitflags = { version = "1.2" } From 82dbee4bbb495c7144ff6a0685bf049843699acf Mon Sep 17 00:00:00 2001 From: TheAwiteb Date: Thu, 7 Sep 2023 21:43:55 +0300 Subject: [PATCH 6/6] Fix deprecation error Use `DateTime::from_naive_utc_and_offset` instead of `DateTime::from_utc` --- crates/teloxide-core/src/types.rs | 8 +++++--- crates/teloxide-core/src/types/update.rs | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/teloxide-core/src/types.rs b/crates/teloxide-core/src/types.rs index 371ab4c4..890dfb1a 100644 --- a/crates/teloxide-core/src/types.rs +++ b/crates/teloxide-core/src/types.rs @@ -269,7 +269,7 @@ pub(crate) fn serde_timestamp( NaiveDateTime::from_timestamp_opt(timestamp, 0) .ok_or_else(|| E::custom("invalid timestump")) - .map(|naive| DateTime::from_utc(naive, Utc)) + .map(|naive| DateTime::from_naive_utc_and_offset(naive, Utc)) } pub(crate) mod serde_opt_date_from_unix_timestamp { @@ -305,8 +305,10 @@ pub(crate) mod serde_opt_date_from_unix_timestamp { { let json = r#"{"date":1}"#; - let expected = - DateTime::from_utc(chrono::NaiveDateTime::from_timestamp_opt(1, 0).unwrap(), Utc); + let expected = DateTime::from_naive_utc_and_offset( + chrono::NaiveDateTime::from_timestamp_opt(1, 0).unwrap(), + Utc, + ); let Struct { date } = serde_json::from_str(json).unwrap(); assert_eq!(date, Some(expected)); diff --git a/crates/teloxide-core/src/types/update.rs b/crates/teloxide-core/src/types/update.rs index 344ee63f..44a2eeeb 100644 --- a/crates/teloxide-core/src/types/update.rs +++ b/crates/teloxide-core/src/types/update.rs @@ -395,8 +395,10 @@ mod test { #[test] fn message() { let timestamp = 1_569_518_342; - let date = - DateTime::from_utc(NaiveDateTime::from_timestamp_opt(timestamp, 0).unwrap(), Utc); + let date = DateTime::from_naive_utc_and_offset( + NaiveDateTime::from_timestamp_opt(timestamp, 0).unwrap(), + Utc, + ); let json = r#"{ "update_id":892252934,