1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
use serde::{Deserialize, Serialize};
use crate::chat::ChatJoinRequest;
use crate::inline::{ChosenInlineResult, InlineQuery};
use crate::message::Message;
use crate::payments::{BotSubscriptionUpdated, PreCheckoutQuery, ShippingQuery};
use crate::poll::{Poll, PollAnswer};
use crate::user::User;
/// An incoming update from Telegram.
///
/// Only one of the optional fields will be `Some` per update.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Update {
/// Unique sequential identifier.
pub update_id: i64,
/// The kind of update and its payload.
#[serde(flatten)]
pub kind: UpdateKind,
}
/// The specific kind of an incoming update.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum UpdateKind {
/// New incoming message.
Message(Message),
/// New version of a message.
EditedMessage(Message),
/// New incoming channel post.
ChannelPost(Message),
/// New version of a channel post.
EditedChannelPost(Message),
/// A message from a business account.
BusinessMessage(Message),
/// Edited message from a business account.
EditedBusinessMessage(Message),
/// New incoming inline query.
InlineQuery(InlineQuery),
/// The result of an inline query that was chosen.
ChosenInlineResult(ChosenInlineResult),
/// New incoming callback query.
CallbackQuery(Box<CallbackQuery>),
/// New incoming shipping query (only for invoices with flexible price).
ShippingQuery(ShippingQuery),
/// New incoming pre-checkout query.
PreCheckoutQuery(PreCheckoutQuery),
/// New poll state.
Poll(Poll),
/// A user changed their answer in a non-anonymous poll.
PollAnswer(PollAnswer),
/// Bot's chat member status was updated in a chat.
MyChatMember(ChatMemberUpdated),
/// A chat member's status was updated in a chat.
ChatMember(ChatMemberUpdated),
/// A request to join the chat has been sent.
ChatJoinRequest(ChatJoinRequest),
/// A reaction to a message was changed by a user.
MessageReaction(MessageReactionUpdated),
/// Reactions to a message with anonymous reactions were changed.
MessageReactionCount(MessageReactionCountUpdated),
/// A chat boost was added or changed.
ChatBoost(ChatBoostUpdated),
/// A boost was removed from a chat.
RemovedChatBoost(ChatBoostRemoved),
/// A managed bot was connected or disconnected.
ManagedBot(ManagedBotUpdated),
/// A business connection was established or removed.
BusinessConnection(BusinessConnection),
/// Messages were deleted from a connected business account.
DeletedBusinessMessages(BusinessMessagesDeleted),
/// Purchased paid media.
PurchasedPaidMedia(PaidMediaPurchased),
/// New guest message — the bot can reply using [`answerGuestQuery`](https://core.telegram.org/bots/api#answerguestquery).
GuestMessage(Message),
/// User payment subscription toward the bot has changed.
Subscription(BotSubscriptionUpdated),
}
impl Update {
/// Returns the `chat_id` if the update contains a message or callback query.
#[must_use]
pub fn chat_id(&self) -> Option<i64> {
match &self.kind {
UpdateKind::Message(m)
| UpdateKind::EditedMessage(m)
| UpdateKind::ChannelPost(m)
| UpdateKind::EditedChannelPost(m)
| UpdateKind::BusinessMessage(m)
| UpdateKind::EditedBusinessMessage(m)
| UpdateKind::GuestMessage(m) => Some(m.chat.id),
UpdateKind::CallbackQuery(q) => q.message.as_ref().map(|m| m.chat.id),
_ => None,
}
}
/// Returns the `from` user if available.
#[must_use]
pub fn from(&self) -> Option<&User> {
match &self.kind {
UpdateKind::Message(m)
| UpdateKind::EditedMessage(m)
| UpdateKind::ChannelPost(m)
| UpdateKind::EditedChannelPost(m)
| UpdateKind::BusinessMessage(m)
| UpdateKind::EditedBusinessMessage(m)
| UpdateKind::GuestMessage(m) => m.from.as_ref(),
UpdateKind::CallbackQuery(q) => Some(&q.from),
UpdateKind::InlineQuery(q) => Some(&q.from),
UpdateKind::ShippingQuery(q) => Some(&q.from),
UpdateKind::PreCheckoutQuery(q) => Some(&q.from),
UpdateKind::PollAnswer(a) => a.user.as_ref(),
UpdateKind::Subscription(s) => Some(&s.user),
_ => None,
}
}
}
/// Incoming callback query from a callback button in an inline keyboard.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CallbackQuery {
/// Unique identifier for this query.
pub id: String,
/// User who sent the query.
pub from: User,
/// Message sent by the bot with the button that originated the query.
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<Message>,
/// Identifier of the message sent via the bot in inline mode.
#[serde(skip_serializing_if = "Option::is_none")]
pub inline_message_id: Option<String>,
/// Global identifier, uniquely corresponding to the chat where the query originated.
pub chat_instance: String,
/// Data associated with the callback button.
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<String>,
/// Short name of a Game to be returned.
#[serde(skip_serializing_if = "Option::is_none")]
pub game_short_name: Option<String>,
}
/// A chat member's status change.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatMemberUpdated {
/// The chat where the change occurred.
pub chat: crate::chat::Chat,
/// The user who triggered the change.
pub from: User,
/// Date of the change, as a Unix timestamp.
pub date: i64,
/// Previous chat member status.
pub old_chat_member: crate::chat_member::ChatMember,
/// New chat member status.
pub new_chat_member: crate::chat_member::ChatMember,
/// Invite link used to join the chat, if any.
#[serde(skip_serializing_if = "Option::is_none")]
pub invite_link: Option<crate::chat::ChatInviteLink>,
/// `true` if the user joined via a join request.
#[serde(skip_serializing_if = "Option::is_none")]
pub via_join_request: Option<bool>,
/// `true` if the user joined via a folder invite link.
#[serde(skip_serializing_if = "Option::is_none")]
pub via_chat_folder_invite_link: Option<bool>,
}
/// A reaction to a message changed by a user.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageReactionUpdated {
/// The chat containing the message.
pub chat: crate::chat::Chat,
/// Identifier of the message that was reacted to.
pub message_id: i64,
/// The user who changed the reaction (non-anonymous reactions only).
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<User>,
/// The chat that changed the reaction (anonymous reactions in groups).
#[serde(skip_serializing_if = "Option::is_none")]
pub actor_chat: Option<crate::chat::Chat>,
/// Date of the change, as a Unix timestamp.
pub date: i64,
/// Previous list of reactions.
pub old_reaction: Vec<crate::message::ReactionType>,
/// New list of reactions.
pub new_reaction: Vec<crate::message::ReactionType>,
}
/// Anonymous reactions to a message were changed.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageReactionCountUpdated {
/// The chat containing the message.
pub chat: crate::chat::Chat,
/// Identifier of the message.
pub message_id: i64,
/// Date of the change, as a Unix timestamp.
pub date: i64,
/// Updated list of reactions with counts.
pub reactions: Vec<ReactionCount>,
}
/// Count of a specific reaction type.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReactionCount {
/// The reaction type.
#[serde(rename = "type")]
pub kind: crate::message::ReactionType,
/// Total number of reactions of this type.
pub total_count: u32,
}
/// A boost was added or changed in a chat.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatBoostUpdated {
/// The chat that was boosted.
pub chat: crate::chat::Chat,
/// Information about the boost.
pub boost: ChatBoost,
}
/// Information about a chat boost.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatBoost {
/// Unique identifier of the boost.
pub boost_id: String,
/// Unix timestamp when the boost was added.
pub add_date: i64,
/// Unix timestamp when the boost expires.
pub expiration_date: i64,
/// Source of the boost.
pub source: ChatBoostSource,
}
/// How a chat boost was obtained.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "source", rename_all = "snake_case")]
pub enum ChatBoostSource {
/// The boost was obtained by subscribing to Telegram Premium or gifting it.
Premium(ChatBoostSourcePremium),
/// The boost was obtained by the creation of Telegram Premium gift codes.
GiftCode(ChatBoostSourceGiftCode),
/// The boost was obtained by the creation of a Telegram Premium or Star giveaway.
Giveaway(ChatBoostSourceGiveaway),
}
/// A boost obtained by subscribing to Telegram Premium or gifting it.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ChatBoostSourcePremium {
/// User that boosted the chat.
pub user: User,
}
/// A boost obtained by the creation of Telegram Premium gift codes.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ChatBoostSourceGiftCode {
/// User for which the gift code was created.
pub user: User,
}
/// A boost obtained by the creation of a giveaway.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ChatBoostSourceGiveaway {
/// Identifier of the message with the giveaway in the chat.
pub giveaway_message_id: i64,
/// User that won the prize in the giveaway, if any.
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<User>,
/// Number of Telegram Stars to be split among winners; Star giveaways only.
#[serde(skip_serializing_if = "Option::is_none")]
pub prize_star_count: Option<i64>,
/// `true` if the giveaway was completed but no user won the prize.
#[serde(skip_serializing_if = "Option::is_none")]
pub is_unclaimed: Option<bool>,
}
/// Service message: the chat was boosted.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ChatBoostAdded {
/// Number of boosts added by the user.
pub boost_count: u32,
}
/// A boost was removed from a chat.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatBoostRemoved {
/// The chat that lost the boost.
pub chat: crate::chat::Chat,
/// Unique identifier of the boost.
pub boost_id: String,
/// Unix timestamp when the boost was removed.
pub remove_date: i64,
/// Source of the removed boost.
pub source: ChatBoostSource,
}
/// A managed bot was connected or disconnected.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManagedBotUpdated {
/// The user who connected or disconnected the managed bot.
pub user: User,
/// The managed bot.
pub bot: User,
}
/// Represents the rights of a business bot.
///
/// All fields are optional — a missing field means the right is not granted.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct BusinessBotRights {
/// `true` if the bot can send and edit messages in private chats that had
/// incoming messages in the last 24 hours.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_reply: Option<bool>,
/// `true` if the bot can mark incoming private messages as read.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_read_messages: Option<bool>,
/// `true` if the bot can delete messages sent by the bot.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_delete_sent_messages: Option<bool>,
/// `true` if the bot can delete all private messages in managed chats.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_delete_all_messages: Option<bool>,
/// `true` if the bot can edit the first and last name of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_edit_name: Option<bool>,
/// `true` if the bot can edit the bio of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_edit_bio: Option<bool>,
/// `true` if the bot can edit the profile photo of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_edit_profile_photo: Option<bool>,
/// `true` if the bot can edit the username of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_edit_username: Option<bool>,
/// `true` if the bot can change gift privacy settings for the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_change_gift_settings: Option<bool>,
/// `true` if the bot can view gifts and the Telegram Stars balance of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_view_gifts_and_stars: Option<bool>,
/// `true` if the bot can convert regular gifts owned by the business account to Telegram Stars.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_convert_gifts_to_stars: Option<bool>,
/// `true` if the bot can transfer and upgrade gifts owned by the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_transfer_and_upgrade_gifts: Option<bool>,
/// `true` if the bot can transfer Telegram Stars received by the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_transfer_stars: Option<bool>,
/// `true` if the bot can post, edit, and delete stories on behalf of the business account.
#[serde(skip_serializing_if = "Option::is_none")]
pub can_manage_stories: Option<bool>,
}
/// A business connection was established or removed.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BusinessConnection {
/// Unique identifier of the business connection.
pub id: String,
/// The business account user.
pub user: User,
/// Identifier of the private chat with the user.
pub user_chat_id: i64,
/// Date the connection was established as a Unix timestamp.
pub date: i64,
/// `true` if the connection is active.
pub is_enabled: bool,
/// Rights granted to the bot within this business connection.
#[serde(skip_serializing_if = "Option::is_none")]
pub rights: Option<BusinessBotRights>,
}
/// A list of boosts added to a chat by a user.
///
/// Returned by [`getUserChatBoosts`](https://core.telegram.org/bots/api#getuserchatboosts).
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserChatBoosts {
/// The list of boosts added to the chat by the user.
pub boosts: Vec<ChatBoost>,
}
/// Business messages that were deleted.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BusinessMessagesDeleted {
/// Unique identifier of the business connection.
pub business_connection_id: String,
/// The chat in which the messages were deleted.
pub chat: crate::chat::Chat,
/// Identifiers of the deleted messages.
pub message_ids: Vec<i64>,
}
/// Purchased paid media.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaidMediaPurchased {
/// The user who purchased the media.
pub from: User,
/// Bot-specified paid media payload.
pub paid_media_payload: String,
}