diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index 72b70c74..6cfbee78 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -16,9 +16,13 @@ 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]) +- 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 +[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..336d3f91 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. @@ -73,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)] @@ -92,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 { @@ -143,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..4c102a36 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, MAX_USER_ID, MIN_USER_ID}; + /// Identifier of a user. #[derive(Clone, Copy)] #[derive(Debug, derive_more::Display)] @@ -50,6 +52,19 @@ 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 { + fn eq(&self, other: &ChatId) -> bool { + // Reuse `PartialEq for ChatId` impl + other == self + } } #[cfg(test)]