From 705083c2d92a2e94b96f2e052d76fae2f35d2993 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 2 Apr 2022 20:59:41 +0400 Subject: [PATCH] Add `UserId::{url, is_anonymous, is_channel, is_telegram}` functions --- CHANGELOG.md | 6 ++++++ src/types/user.rs | 30 +++++++++++------------------- src/types/user_id.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6408f44..7d6b229c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## unreleased +### Added + +- `UserId::{url, is_anonymous, is_channel, is_telegram}` convenience functions ([#197][pr197]) + +[pr197]: https://github.com/teloxide/teloxide-core/pull/197 + ### Changed - `user.id` now uses `UserId` type, `ChatId` now represents only _chat id_, not channel username, all `chat_id` function parameters now accept `Recipient` [**BC**] diff --git a/src/types/user.rs b/src/types/user.rs index 978ddfa0..f43b06c6 100644 --- a/src/types/user.rs +++ b/src/types/user.rs @@ -46,65 +46,57 @@ impl User { } /// Returns an URL that links to this user in the form of - /// `tg://user/?id=<...>` + /// `tg://user/?id=<...>`. pub fn url(&self) -> reqwest::Url { - reqwest::Url::parse(&format!("tg://user/?id={}", self.id)).unwrap() + self.id.url() } - /// Returns `true` if this is special user used by telegram bot API to + /// Returns `true` if this is the special user used by telegram bot API to /// denote an anonymous user that sends messages on behalf of a group. pub fn is_anonymous(&self) -> bool { - // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4941-L4943 - const ANON_ID: UserId = UserId(1087968824); - // Sanity check debug_assert!( - (self.id != ANON_ID) + !self.id.is_anonymous() || (self.is_bot && self.first_name == "Group" && self.last_name.is_none() && self.username.as_deref() == Some("GroupAnonymousBot")) ); - self.id == ANON_ID + self.id.is_anonymous() } - /// Returns `true` if this is special user used by telegram bot API to + /// Returns `true` if this is the special user used by telegram bot API to /// denote an anonymous user that sends messages on behalf of a channel. pub fn is_channel(&self) -> bool { - // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4945-L4947 - const ANON_CHANNEL_ID: UserId = UserId(136817688); - // Sanity check debug_assert!( - (self.id != ANON_CHANNEL_ID) + !self.id.is_channel() || (self.is_bot && self.first_name == "Group" && self.last_name.is_none() && self.username.as_deref() == Some("GroupAnonymousBot")) ); - self.id == ANON_CHANNEL_ID + self.id.is_channel() } - /// Returns `true` if this is special user used by telegram itself. + /// Returns `true` if this is the special user used by telegram itself. /// /// It is sometimes also used as a fallback, for example when a channel post /// is automatically forwarded to a group, bots in a group will get a /// message where `from` is the Telegram user. pub fn is_telegram(&self) -> bool { - const TELEGRAM_USER_ID: UserId = UserId(777000); - // Sanity check debug_assert!( - (self.id != TELEGRAM_USER_ID) + !self.id.is_telegram() || (!self.is_bot && self.first_name == "Telegram" && self.last_name.is_none() && self.username.is_none()) ); - self.id == TELEGRAM_USER_ID + self.id.is_telegram() } } diff --git a/src/types/user_id.rs b/src/types/user_id.rs index bfee58bf..20198f76 100644 --- a/src/types/user_id.rs +++ b/src/types/user_id.rs @@ -8,6 +8,46 @@ use serde::{Deserialize, Serialize}; #[serde(transparent)] pub struct UserId(pub u64); +impl UserId { + /// Returns an URL that links to the user with this id in the form of + /// `tg://user/?id=<...>`. + pub fn url(self) -> reqwest::Url { + reqwest::Url::parse(&format!("tg://user/?id={}", self)).unwrap() + } + + /// Returns `true` if this is the id of the special user used by telegram + /// bot API to denote an anonymous user that sends messages on behalf of + /// a group. + pub fn is_anonymous(self) -> bool { + // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4941-L4943 + const ANON_ID: UserId = UserId(1087968824); + + self == ANON_ID + } + + /// Returns `true` if this is the id of the special user used by telegram + /// bot API to denote an anonymous user that sends messages on behalf of + /// a channel. + pub fn is_channel(self) -> bool { + // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4945-L4947 + const ANON_CHANNEL_ID: UserId = UserId(136817688); + + self == ANON_CHANNEL_ID + } + + /// Returns `true` if this is the id of the special user used by telegram + /// itself. + /// + /// It is sometimes also used as a fallback, for example when a channel post + /// is automatically forwarded to a group, bots in a group will get a + /// message where `from` is the Telegram user. + pub fn is_telegram(self) -> bool { + const TELEGRAM_USER_ID: UserId = UserId(777000); + + self == TELEGRAM_USER_ID + } +} + #[cfg(test)] mod tests { use serde::{Deserialize, Serialize};