Skip to main content

rustigram_types/
user.rs

1use serde::{Deserialize, Serialize};
2
3/// Represents a Telegram user or bot.
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5pub struct User {
6    /// Unique identifier for this user or bot.
7    pub id: i64,
8
9    /// `true` if this user is a bot.
10    pub is_bot: bool,
11
12    /// User's or bot's first name.
13    pub first_name: String,
14
15    /// User's or bot's last name.
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub last_name: Option<String>,
18
19    /// User's or bot's username.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub username: Option<String>,
22
23    /// IETF language tag of the user's language.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub language_code: Option<String>,
26
27    /// `true` if this user is a Telegram Premium user.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub is_premium: Option<bool>,
30
31    /// `true` if this user added the bot to the attachment menu.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub added_to_attachment_menu: Option<bool>,
34
35    /// Bots only — `true` if the bot can be invited to groups.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub can_join_groups: Option<bool>,
38
39    /// Bots only — `true` if privacy mode is disabled for the bot.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub can_read_all_group_messages: Option<bool>,
42
43    /// Bots only — `true` if the bot supports inline queries.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub supports_inline_queries: Option<bool>,
46
47    /// Bots only — `true` if the bot can be connected to a Telegram Business account.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub can_connect_to_business: Option<bool>,
50
51    /// Bots only — `true` if the bot has a main Web App.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub has_main_web_app: Option<bool>,
54
55    /// Bots only — `true` if the bot can manage other bots.
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub can_manage_bots: Option<bool>,
58}
59
60impl User {
61    /// Returns a human-readable display name, preferring `first_name + last_name`,
62    /// falling back to `username`, then `id`.
63    #[must_use]
64    pub fn full_name(&self) -> String {
65        match &self.last_name {
66            Some(last) => format!("{} {}", self.first_name, last),
67            None => self.first_name.clone(),
68        }
69    }
70
71    /// Returns a `@username` mention string if available.
72    #[must_use]
73    pub fn mention(&self) -> Option<String> {
74        self.username.as_ref().map(|u| format!("@{u}"))
75    }
76}
77
78/// Container for a user's profile photos.
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct UserProfilePhotos {
81    /// Total number of profile pictures the target user has.
82    pub total_count: u32,
83
84    /// Requested profile pictures (in up to 4 sizes each).
85    pub photos: Vec<Vec<crate::file::PhotoSize>>,
86}
87
88/// Container for a user's profile audios.
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct UserProfileAudios {
91    /// Total number of profile audios.
92    pub total_count: u32,
93
94    /// Requested profile audios.
95    pub audios: Vec<crate::file::Audio>,
96}
97
98/// Bot command scope — defines where a specific list of commands applies.
99#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
100#[serde(tag = "type", rename_all = "snake_case")]
101pub enum BotCommandScope {
102    /// Default scope — used when no more specific scope is applicable.
103    Default,
104    /// Covers all private chats.
105    AllPrivateChats,
106    /// Covers all group and supergroup chats.
107    AllGroupChats,
108    /// Covers all group and supergroup chat administrators.
109    AllChatAdministrators,
110    /// Covers a specific chat.
111    Chat {
112        /// Unique identifier or username of the target chat.
113        chat_id: ChatId,
114    },
115    /// Covers all administrators of a specific group or supergroup.
116    ChatAdministrators {
117        /// Unique identifier or username of the target chat.
118        chat_id: ChatId,
119    },
120    /// Covers a specific member of a group or supergroup.
121    ChatMember {
122        /// Unique identifier or username of the target chat.
123        chat_id: ChatId,
124        /// Unique identifier of the target user.
125        user_id: i64,
126    },
127}
128
129/// Represents a bot command.
130#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
131pub struct BotCommand {
132    /// Text of the command (1–32 characters, lowercase, alphanumeric + underscore).
133    pub command: String,
134    /// Description of the command (3–256 characters).
135    pub description: String,
136}
137
138/// Flexible chat identifier — either a numeric ID or a `@username`.
139#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
140#[serde(untagged)]
141pub enum ChatId {
142    /// Numeric chat ID (can be negative for groups/channels).
143    Id(i64),
144    /// Chat `@username`.
145    Username(String),
146}
147
148impl From<i64> for ChatId {
149    fn from(id: i64) -> Self {
150        Self::Id(id)
151    }
152}
153
154impl From<&str> for ChatId {
155    fn from(username: &str) -> Self {
156        Self::Username(username.to_owned())
157    }
158}
159
160impl From<String> for ChatId {
161    fn from(username: String) -> Self {
162        Self::Username(username)
163    }
164}
165
166impl std::fmt::Display for ChatId {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        match self {
169            Self::Id(id) => write!(f, "{id}"),
170            Self::Username(u) => write!(f, "{u}"),
171        }
172    }
173}