tg_flows/types/
user_id.rs

1use serde::{Deserialize, Serialize};
2
3/// Identifier of a user.
4#[derive(Clone, Copy)]
5#[derive(Debug, derive_more::Display)]
6#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[derive(Serialize, Deserialize)]
8#[serde(transparent)]
9pub struct UserId(pub u64);
10
11impl UserId {
12    /// Returns an URL that links to the user with this id in the form of
13    /// `tg://user/?id=<...>`.
14    #[must_use]
15    pub fn url(self) -> url::Url {
16        url::Url::parse(&format!("tg://user/?id={self}")).unwrap()
17    }
18
19    /// Returns `true` if this is the id of the special user used by telegram
20    /// bot API to denote an anonymous user that sends messages on behalf of
21    /// a group.
22    #[must_use]
23    pub fn is_anonymous(self) -> bool {
24        // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4941-L4943
25        const ANON_ID: UserId = UserId(1087968824);
26
27        self == ANON_ID
28    }
29
30    /// Returns `true` if this is the id of the special user used by telegram
31    /// bot API to denote an anonymous user that sends messages on behalf of
32    /// a channel.
33    #[must_use]
34    pub fn is_channel(self) -> bool {
35        // https://github.com/tdlib/td/blob/4791fb6a2af0257f6cad8396e10424a79ee5f768/td/telegram/ContactsManager.cpp#L4945-L4947
36        const ANON_CHANNEL_ID: UserId = UserId(136817688);
37
38        self == ANON_CHANNEL_ID
39    }
40
41    /// Returns `true` if this is the id of the special user used by telegram
42    /// itself.
43    ///
44    /// It is sometimes also used as a fallback, for example when a channel post
45    /// is automatically forwarded to a group, bots in a group will get a
46    /// message where `from` is the Telegram user.
47    #[must_use]
48    pub fn is_telegram(self) -> bool {
49        const TELEGRAM_USER_ID: UserId = UserId(777000);
50
51        self == TELEGRAM_USER_ID
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use serde::{Deserialize, Serialize};
58
59    use crate::types::UserId;
60
61    /// Test that `UserId` is serialized as the underlying integer
62    #[test]
63    fn deser() {
64        let user_id = S { user_id: UserId(17) };
65        let json = r#"{"user_id":17}"#;
66
67        #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
68        struct S {
69            user_id: UserId,
70        }
71
72        assert_eq!(serde_json::to_string(&user_id).unwrap(), json);
73        assert_eq!(user_id, serde_json::from_str(json).unwrap());
74    }
75
76    #[test]
77    fn url_works() {
78        let id = UserId(17);
79
80        assert_eq!(id.url(), "tg://user/?id=17".parse().unwrap());
81    }
82}