Skip to main content

rustigram_types/
chat.rs

1use serde::{Deserialize, Serialize};
2
3use crate::business::{
4    Birthdate, BusinessIntro, BusinessLocation, BusinessOpeningHours, UserRating,
5};
6use crate::community::Community;
7use crate::file::Audio;
8use crate::gifts::UniqueGiftColors;
9use crate::message::{Message, ReactionType};
10use crate::payments::AcceptedGiftTypes;
11use crate::user::User;
12
13#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
14/// Type of a Telegram chat.
15#[serde(rename_all = "snake_case")]
16pub enum ChatType {
17    /// One-on-one conversation.
18    ///
19    /// The default, so that [`Chat`] and [`ChatFullInfo`] can derive
20    /// [`Default`]. A private chat is the simplest case and the only variant
21    /// that needs no additional context to be coherent.
22    #[default]
23    Private,
24    /// Group chat.
25    Group,
26    /// Supergroup.
27    Supergroup,
28    /// Broadcast channel.
29    Channel,
30}
31
32#[derive(Debug, Clone, Default, Serialize, Deserialize)]
33/// Minimal chat descriptor — used in messages and updates.
34///
35/// Telegram adds fields to this object regularly, so it is `#[non_exhaustive]`:
36/// build one with [`Default::default`] and assign the fields you need, and
37/// future Bot API additions stay non-breaking.
38#[non_exhaustive]
39pub struct Chat {
40    /// Unique identifier for this chat.
41    pub id: i64,
42
43    /// Type of chat.
44    #[serde(rename = "type")]
45    pub kind: ChatType,
46
47    /// Title, for supergroups, channels and group chats.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub title: Option<String>,
50
51    /// Username, for private chats, supergroups and channels.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub username: Option<String>,
54
55    /// First name of the other party in a private chat.
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub first_name: Option<String>,
58
59    /// Last name of the other party in a private chat.
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub last_name: Option<String>,
62
63    /// `true` if the supergroup chat is a forum (has topics enabled).
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub is_forum: Option<bool>,
66    /// `true` if the chat is the direct messages chat of a channel.
67    #[serde(skip_serializing_if = "Option::is_none")]
68    pub is_direct_messages: Option<bool>,
69}
70
71impl Chat {
72    /// Returns the chat's display name.
73    #[must_use]
74    pub fn display_name(&self) -> String {
75        self.title
76            .clone()
77            .or_else(|| {
78                self.first_name.as_ref().map(|f| {
79                    self.last_name
80                        .as_ref()
81                        .map_or(f.clone(), |l| format!("{f} {l}"))
82                })
83            })
84            .or_else(|| self.username.clone())
85            .unwrap_or_else(|| self.id.to_string())
86    }
87}
88
89#[derive(Debug, Clone, Default, Serialize, Deserialize)]
90/// Full chat information — returned by `getChat`.
91///
92/// `#[non_exhaustive]` for the same reason as [`Chat`] — this is the
93/// fastest-growing object in the Bot API.
94#[non_exhaustive]
95pub struct ChatFullInfo {
96    /// Unique identifier for this chat.
97    pub id: i64,
98
99    /// Type of chat.
100    #[serde(rename = "type")]
101    pub kind: ChatType,
102
103    /// Title of the chat (groups, supergroups, and channels).
104    #[serde(skip_serializing_if = "Option::is_none")]
105    pub title: Option<String>,
106
107    /// Username of the chat.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub username: Option<String>,
110
111    /// First name of the other party in a private chat.
112    #[serde(skip_serializing_if = "Option::is_none")]
113    pub first_name: Option<String>,
114
115    /// Last name of the other party in a private chat.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub last_name: Option<String>,
118
119    /// `true` if the supergroup chat is a forum (has topics enabled).
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub is_forum: Option<bool>,
122    /// `true` if the chat is the direct messages chat of a channel.
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub is_direct_messages: Option<bool>,
125    /// Identifier of the accent color for the chat name and backgrounds.
126    ///
127    /// Required by the spec, but kept defaulted rather than bare so that a
128    /// response from an older Bot API server still decodes.
129    #[serde(default)]
130    pub accent_color_id: u32,
131
132    /// Maximum number of reactions that can be set on a message.
133    #[serde(default)]
134    pub max_reaction_count: u32,
135
136    /// The bot that processes join request queries in the chat.
137    ///
138    /// Only available to chat administrators.
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub guard_bot: Option<User>,
141    /// Birthdate of a private chat's user.
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub birthdate: Option<Birthdate>,
144    /// Intro of a private chat with a business account.
145    #[serde(skip_serializing_if = "Option::is_none")]
146    pub business_intro: Option<BusinessIntro>,
147    /// Location of a private chat with a business account.
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub business_location: Option<BusinessLocation>,
150    /// Opening hours of a private chat with a business account.
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub business_opening_hours: Option<BusinessOpeningHours>,
153    /// The personal channel of a private chat's user.
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub personal_chat: Option<Box<Chat>>,
156    /// The chat this direct messages chat belongs to.
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub parent_chat: Option<Box<Chat>>,
159    /// Reactions allowed in the chat. Absent means every emoji reaction is allowed.
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub available_reactions: Option<Vec<ReactionType>>,
162    /// Custom emoji identifier of the emoji chosen by the chat for its reply
163    /// header and link preview background.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub background_custom_emoji_id: Option<String>,
166    /// Identifier of the accent color for the chat's profile background.
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub profile_accent_color_id: Option<u32>,
169    /// Custom emoji identifier of the emoji chosen by the chat for its profile
170    /// background.
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub profile_background_custom_emoji_id: Option<String>,
173    /// Custom emoji identifier of the emoji status of the chat or the user.
174    #[serde(skip_serializing_if = "Option::is_none")]
175    pub emoji_status_custom_emoji_id: Option<String>,
176    /// Expiration date of the emoji status, as a Unix timestamp.
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub emoji_status_expiration_date: Option<i64>,
179    /// Types of gifts accepted by the chat.
180    #[serde(default)]
181    pub accepted_gift_types: AcceptedGiftTypes,
182    /// Rating of a private chat's user.
183    #[serde(skip_serializing_if = "Option::is_none")]
184    pub rating: Option<UserRating>,
185    /// The audio shown first on the user's profile.
186    #[serde(skip_serializing_if = "Option::is_none")]
187    pub first_profile_audio: Option<Audio>,
188    /// Colour scheme used for the chat's name, replies, and link previews,
189    /// taken from a unique gift.
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub unique_gift_colors: Option<UniqueGiftColors>,
192    /// Number of Telegram Stars a user must pay to send one message to the chat.
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub paid_message_star_count: Option<i64>,
195
196    /// Chat photo.
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub photo: Option<ChatPhoto>,
199
200    /// Active usernames of a channel, supergroup, or user.
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub active_usernames: Option<Vec<String>>,
203
204    /// Bio of the other party in a private chat.
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub bio: Option<String>,
207
208    /// `true` if privacy settings prevent viewing the other party's bio.
209    #[serde(skip_serializing_if = "Option::is_none")]
210    pub has_private_forwards: Option<bool>,
211
212    /// `true` if the privacy settings prevent sending voice and video note messages.
213    #[serde(skip_serializing_if = "Option::is_none")]
214    pub has_restricted_voice_and_video_messages: Option<bool>,
215
216    /// `true` if users need to join in order to send messages.
217    #[serde(skip_serializing_if = "Option::is_none")]
218    pub join_to_send_messages: Option<bool>,
219
220    /// `true` if all users directly joining the supergroup need to be approved.
221    #[serde(skip_serializing_if = "Option::is_none")]
222    pub join_by_request: Option<bool>,
223
224    /// Description, for groups, supergroups and channel chats.
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub description: Option<String>,
227
228    /// Primary invite link for the chat.
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub invite_link: Option<String>,
231
232    /// Latest pinned message.
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub pinned_message: Option<Box<Message>>,
235
236    /// Default chat member permissions, for groups and supergroups.
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub permissions: Option<ChatPermissions>,
239
240    /// `true` if paid media messages can be sent or forwarded to the channel chat.
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub can_send_paid_media: Option<bool>,
243
244    /// Delay in seconds between consecutive messages from a non-administrator.
245    #[serde(skip_serializing_if = "Option::is_none")]
246    pub slow_mode_delay: Option<u32>,
247
248    /// Delay in seconds after which all messages sent by the user will be automatically
249    /// deleted.
250    #[serde(skip_serializing_if = "Option::is_none")]
251    pub unrestrict_boost_count: Option<u32>,
252
253    /// Message auto-delete timer setting for new messages.
254    #[serde(skip_serializing_if = "Option::is_none")]
255    pub message_auto_delete_time: Option<u32>,
256
257    /// `true` if aggressive anti-spam checks are enabled in the supergroup.
258    #[serde(skip_serializing_if = "Option::is_none")]
259    pub has_aggressive_anti_spam_enabled: Option<bool>,
260
261    /// `true` if non-administrators can only get the list of bots and administrators.
262    #[serde(skip_serializing_if = "Option::is_none")]
263    pub has_hidden_members: Option<bool>,
264
265    /// `true` if messages from the chat can't be forwarded to other chats.
266    #[serde(skip_serializing_if = "Option::is_none")]
267    pub has_protected_content: Option<bool>,
268
269    /// `true` if new chat members will have access to old messages.
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub has_visible_history: Option<bool>,
272
273    /// Name of the group sticker set.
274    #[serde(skip_serializing_if = "Option::is_none")]
275    pub sticker_set_name: Option<String>,
276
277    /// `true` if the bot can change the group sticker set.
278    #[serde(skip_serializing_if = "Option::is_none")]
279    pub can_set_sticker_set: Option<bool>,
280
281    /// Custom emoji identifier of the emoji chosen by the chat for the reply header.
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub custom_emoji_sticker_set_name: Option<String>,
284
285    /// Unique identifier for the linked chat.
286    #[serde(skip_serializing_if = "Option::is_none")]
287    pub linked_chat_id: Option<i64>,
288
289    /// The location to which the supergroup is connected.
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub location: Option<ChatLocation>,
292
293    /// The Community to which the chat belongs.
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub community: Option<Community>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
299/// Chat photo information.
300pub struct ChatPhoto {
301    /// File identifier of small (160x160) chat photo.
302    pub small_file_id: String,
303    /// Unique file identifier of small chat photo.
304    pub small_file_unique_id: String,
305    /// File identifier of big (640x640) chat photo.
306    pub big_file_id: String,
307    /// Unique file identifier of big chat photo.
308    pub big_file_unique_id: String,
309}
310
311#[derive(Debug, Clone, Default, Serialize, Deserialize)]
312/// Defines chat permissions for regular members.
313pub struct ChatPermissions {
314    /// `true` if the user is allowed to send text messages, rich messages, contacts,
315    /// giveaways, giveaway winners, invoices, locations, and venues.
316    #[serde(skip_serializing_if = "Option::is_none")]
317    pub can_send_messages: Option<bool>,
318    /// Allows sending audio files.
319    #[serde(skip_serializing_if = "Option::is_none")]
320    pub can_send_audios: Option<bool>,
321    /// Allows sending documents.
322    #[serde(skip_serializing_if = "Option::is_none")]
323    pub can_send_documents: Option<bool>,
324    /// Allows sending photos.
325    #[serde(skip_serializing_if = "Option::is_none")]
326    pub can_send_photos: Option<bool>,
327    /// Allows sending videos.
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub can_send_videos: Option<bool>,
330    /// Allows sending video notes.
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub can_send_video_notes: Option<bool>,
333    /// Allows sending voice notes.
334    #[serde(skip_serializing_if = "Option::is_none")]
335    pub can_send_voice_notes: Option<bool>,
336    /// Allows sending polls.
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub can_send_polls: Option<bool>,
339    /// Allows sending other types of messages (stickers, GIFs, games, etc.).
340    #[serde(skip_serializing_if = "Option::is_none")]
341    pub can_send_other_messages: Option<bool>,
342    /// Allows adding web page previews to messages.
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub can_add_web_page_previews: Option<bool>,
345    /// Allows changing the chat title, photo, and other settings.
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub can_change_info: Option<bool>,
348    /// Allows inviting new users to the chat.
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub can_invite_users: Option<bool>,
351    /// Allows pinning messages.
352    #[serde(skip_serializing_if = "Option::is_none")]
353    pub can_pin_messages: Option<bool>,
354    /// Allows managing forum topics (supergroups only).
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub can_manage_topics: Option<bool>,
357    /// Allows editing the chat tag (supergroups only).
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub can_edit_tag: Option<bool>,
360    /// Allows reacting to messages.
361    ///
362    /// If omitted, defaults to the value of `can_send_messages`.
363    #[serde(skip_serializing_if = "Option::is_none")]
364    pub can_react_to_messages: Option<bool>,
365}
366
367/// Location to which the supergroup is connected.
368#[derive(Debug, Clone, Serialize, Deserialize)]
369pub struct ChatLocation {
370    /// The location to which the supergroup is connected.
371    pub location: Location,
372    /// Location address; 1-64 characters.
373    pub address: String,
374}
375
376/// Geographic point on the map.
377#[derive(Debug, Clone, Serialize, Deserialize)]
378pub struct Location {
379    /// Latitude as defined by the sender.
380    pub latitude: f64,
381    /// Longitude as defined by the sender.
382    pub longitude: f64,
383    /// Radius of uncertainty for the location, in metres (0–1500).
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub horizontal_accuracy: Option<f64>,
386    /// Time relative to the message sending date, during which the location can
387    /// be updated; in seconds.
388    #[serde(skip_serializing_if = "Option::is_none")]
389    pub live_period: Option<u32>,
390    /// Direction of movement in degrees (1–360).
391    #[serde(skip_serializing_if = "Option::is_none")]
392    pub heading: Option<u16>,
393    /// Maximum distance in metres for proximity alerts.
394    #[serde(skip_serializing_if = "Option::is_none")]
395    pub proximity_alert_radius: Option<u32>,
396}
397
398/// Represents a venue.
399#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct Venue {
401    /// Venue location.
402    pub location: Location,
403    /// Name of the venue.
404    pub title: String,
405    /// Address of the venue.
406    pub address: String,
407    /// Foursquare identifier of the venue.
408    #[serde(skip_serializing_if = "Option::is_none")]
409    pub foursquare_id: Option<String>,
410    /// Foursquare type of the venue.
411    #[serde(skip_serializing_if = "Option::is_none")]
412    pub foursquare_type: Option<String>,
413    /// Google Places identifier of the venue.
414    #[serde(skip_serializing_if = "Option::is_none")]
415    pub google_place_id: Option<String>,
416    /// Google Places type of the venue.
417    #[serde(skip_serializing_if = "Option::is_none")]
418    pub google_place_type: Option<String>,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
422/// Invite link for a chat.
423pub struct ChatInviteLink {
424    /// The invite link.
425    pub invite_link: String,
426    /// Creator of the link.
427    pub creator: User,
428    /// `true` if users joining the chat via the link need to be approved by chat admins.
429    pub creates_join_request: bool,
430    /// `true` if the link is primary.
431    pub is_primary: bool,
432    /// `true` if the link is revoked.
433    pub is_revoked: bool,
434    /// Invite link name.
435    #[serde(skip_serializing_if = "Option::is_none")]
436    pub name: Option<String>,
437    /// Point in time (Unix) when the link will expire or has been expired.
438    #[serde(skip_serializing_if = "Option::is_none")]
439    pub expire_date: Option<i64>,
440    /// Maximum number of users that can be members of the chat simultaneously.
441    #[serde(skip_serializing_if = "Option::is_none")]
442    pub member_limit: Option<u32>,
443    /// Number of pending join requests created using this link.
444    #[serde(skip_serializing_if = "Option::is_none")]
445    pub pending_join_request_count: Option<u32>,
446    /// Number of seconds the subscription created by this link will be active.
447    #[serde(skip_serializing_if = "Option::is_none")]
448    pub subscription_period: Option<u32>,
449    /// Number of Telegram Stars a user must pay for a subscription.
450    #[serde(skip_serializing_if = "Option::is_none")]
451    pub subscription_price: Option<u32>,
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
455/// Represents a join request sent to a chat.
456pub struct ChatJoinRequest {
457    /// The chat the join request was sent to.
458    pub chat: Chat,
459    /// The user that sent the join request.
460    pub from: User,
461    /// Identifier of a private chat with the user.
462    pub user_chat_id: i64,
463    /// Date the request was sent as Unix time.
464    pub date: i64,
465    /// Bio of the user, if available.
466    #[serde(skip_serializing_if = "Option::is_none")]
467    pub bio: Option<String>,
468    /// The invite link used to send the request, if any.
469    #[serde(skip_serializing_if = "Option::is_none")]
470    pub invite_link: Option<ChatInviteLink>,
471    /// Identifier of the join request query.
472    ///
473    /// When present, the bot must call `answerChatJoinRequestQuery` or
474    /// `sendChatJoinRequestWebApp` within 10 seconds.
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub query_id: Option<String>,
477}
478
479// ─── Link & InputMediaLink ────────────────────────────────────────────────────
480
481/// Represents an HTTP link.
482#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
483pub struct Link {
484    /// The HTTP(S) URL.
485    pub url: String,
486}
487
488/// An HTTP link to be used as [`InputPollOptionMedia`](crate::poll::InputPollOptionMedia).
489///
490/// The `type` discriminant belongs to the enclosing
491/// [`InputPollOptionMedia`](crate::poll::InputPollOptionMedia), which is
492/// internally tagged. Declaring it here as well made the value serialise
493/// correctly but never decode, since serde consumes the tag to select the
494/// variant and the inner struct then found no `type` field of its own.
495#[derive(Debug, Clone, Serialize, Deserialize)]
496pub struct InputMediaLink {
497    /// The HTTP(S) URL of the link.
498    pub url: String,
499}
500
501impl InputMediaLink {
502    /// Creates a new `InputMediaLink` from a URL.
503    pub fn new(url: impl Into<String>) -> Self {
504        Self { url: url.into() }
505    }
506}