1use std::{collections::HashSet, time::Duration};
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value as JsonValue;
5
6use crate::{
7 api::{Method, Payload},
8 types::{
9 BusinessConnection,
10 BusinessMessagesDeleted,
11 CallbackQuery,
12 Chat,
13 ChatBoostRemoved,
14 ChatBoostUpdated,
15 ChatJoinRequest,
16 ChatMemberUpdated,
17 ChatPeerId,
18 ChatUsername,
19 ChosenInlineResult,
20 InlineQuery,
21 Integer,
22 MaybeInaccessibleMessage,
23 Message,
24 MessageReactionCountUpdated,
25 MessageReactionUpdated,
26 PaidMediaPurchased,
27 Poll,
28 PollAnswer,
29 PollAnswerVoter,
30 PreCheckoutQuery,
31 ShippingQuery,
32 User,
33 UserPeerId,
34 UserUsername,
35 },
36};
37
38#[cfg(test)]
39mod tests;
40
41#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
43pub struct Update {
44 #[serde(rename = "update_id")]
53 pub id: Integer,
54 #[serde(flatten)]
56 pub update_type: UpdateType,
57}
58
59impl Update {
60 pub fn new(id: Integer, update_type: UpdateType) -> Self {
67 Self { id, update_type }
68 }
69
70 pub fn get_chat(&self) -> Option<&Chat> {
72 self.get_message().map(|msg| &msg.chat).or(match self.update_type {
73 UpdateType::BotStatus(ref x) | UpdateType::UserStatus(ref x) => Some(&x.chat),
74 UpdateType::DeletedBusinessMessages(ref x) => Some(&x.chat),
75 UpdateType::ChatBoostRemoved(ref x) => Some(&x.chat),
76 UpdateType::ChatBoostUpdated(ref x) => Some(&x.chat),
77 UpdateType::ChatJoinRequest(ref x) => Some(&x.chat),
78 UpdateType::MessageReaction(ref x) => Some(&x.chat),
79 UpdateType::MessageReactionCount(ref x) => Some(&x.chat),
80 _ => None,
81 })
82 }
83
84 pub fn get_chat_id(&self) -> Option<ChatPeerId> {
86 self.get_chat().map(|chat| chat.get_id())
87 }
88
89 pub fn get_chat_username(&self) -> Option<&ChatUsername> {
91 self.get_chat().and_then(|chat| chat.get_username())
92 }
93
94 pub fn get_user(&self) -> Option<&User> {
96 Some(match self.update_type {
97 UpdateType::BotStatus(ref x) | UpdateType::UserStatus(ref x) => &x.from,
98 UpdateType::BusinessConnection(ref x) => &x.user,
99 UpdateType::CallbackQuery(ref x) => &x.from,
100 UpdateType::ChatBoostRemoved(_) => return None,
101 UpdateType::ChatBoostUpdated(_) => return None,
102 UpdateType::ChatJoinRequest(ref x) => &x.from,
103 UpdateType::ChosenInlineResult(ref x) => &x.from,
104 UpdateType::DeletedBusinessMessages(_) => return None,
105 UpdateType::InlineQuery(ref x) => &x.from,
106 UpdateType::Message(ref x)
107 | UpdateType::BusinessMessage(ref x)
108 | UpdateType::EditedBusinessMessage(ref x)
109 | UpdateType::EditedMessage(ref x)
110 | UpdateType::ChannelPost(ref x)
111 | UpdateType::EditedChannelPost(ref x) => return x.sender.get_user(),
112 UpdateType::MessageReaction(ref x) => return x.user.as_ref(),
113 UpdateType::MessageReactionCount(_) => return None,
114 UpdateType::Poll(_) => return None,
115 UpdateType::PollAnswer(ref x) => match &x.voter {
116 PollAnswerVoter::User(x) => x,
117 PollAnswerVoter::Chat(_) => return None,
118 },
119 UpdateType::PreCheckoutQuery(ref x) => &x.from,
120 UpdateType::PurchasedPaidMedia(ref x) => &x.from,
121 UpdateType::ShippingQuery(ref x) => &x.from,
122 UpdateType::Unknown(_) => return None,
123 })
124 }
125
126 pub fn get_user_id(&self) -> Option<UserPeerId> {
128 self.get_user().map(|user| user.id)
129 }
130
131 pub fn get_user_username(&self) -> Option<&UserUsername> {
133 self.get_user().and_then(|user| user.username.as_ref())
134 }
135
136 pub fn get_message(&self) -> Option<&Message> {
138 match self.update_type {
139 UpdateType::Message(ref msg)
140 | UpdateType::BusinessMessage(ref msg)
141 | UpdateType::EditedBusinessMessage(ref msg)
142 | UpdateType::EditedMessage(ref msg)
143 | UpdateType::ChannelPost(ref msg)
144 | UpdateType::EditedChannelPost(ref msg) => Some(msg),
145 UpdateType::CallbackQuery(ref query) => match query.message {
146 Some(MaybeInaccessibleMessage::Message(ref msg)) => Some(msg),
147 _ => None,
148 },
149 _ => None,
150 }
151 }
152}
153
154#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
156#[allow(clippy::large_enum_variant)]
157#[serde(rename_all = "snake_case")]
158pub enum UpdateType {
159 #[serde(rename = "my_chat_member")]
164 BotStatus(ChatMemberUpdated),
165 BusinessConnection(BusinessConnection),
168 BusinessMessage(Message),
170 CallbackQuery(CallbackQuery),
172 ChannelPost(Message),
174 #[serde(rename = "removed_chat_boost")]
178 ChatBoostRemoved(ChatBoostRemoved),
179 #[serde(rename = "chat_boost")]
183 ChatBoostUpdated(ChatBoostUpdated),
184 ChatJoinRequest(ChatJoinRequest),
189 ChosenInlineResult(ChosenInlineResult),
196 DeletedBusinessMessages(BusinessMessagesDeleted),
198 EditedBusinessMessage(Message),
200 EditedChannelPost(Message),
202 EditedMessage(Message),
204 InlineQuery(InlineQuery),
208 Message(Message),
210 MessageReaction(MessageReactionUpdated),
218 MessageReactionCount(MessageReactionCountUpdated),
224 Poll(Poll),
228 PollAnswer(PollAnswer),
232 PreCheckoutQuery(PreCheckoutQuery),
236 PurchasedPaidMedia(PaidMediaPurchased),
238 ShippingQuery(ShippingQuery),
242 #[serde(rename = "chat_member")]
248 UserStatus(ChatMemberUpdated),
249 #[serde(untagged)]
254 Unknown(JsonValue),
255}
256
257pub struct UnexpectedUpdate(Update);
261
262impl From<UnexpectedUpdate> for Update {
263 fn from(value: UnexpectedUpdate) -> Self {
264 value.0
265 }
266}
267
268impl TryFrom<Update> for BusinessConnection {
269 type Error = UnexpectedUpdate;
270
271 fn try_from(value: Update) -> Result<Self, Self::Error> {
272 use self::UpdateType::*;
273 match value.update_type {
274 BusinessConnection(x) => Ok(x),
275 _ => Err(UnexpectedUpdate(value)),
276 }
277 }
278}
279
280impl TryFrom<Update> for BusinessMessagesDeleted {
281 type Error = UnexpectedUpdate;
282
283 fn try_from(value: Update) -> Result<Self, Self::Error> {
284 use self::UpdateType::*;
285 match value.update_type {
286 DeletedBusinessMessages(x) => Ok(x),
287 _ => Err(UnexpectedUpdate(value)),
288 }
289 }
290}
291
292impl TryFrom<Update> for ChatMemberUpdated {
293 type Error = UnexpectedUpdate;
294
295 fn try_from(value: Update) -> Result<Self, Self::Error> {
296 use self::UpdateType::*;
297 match value.update_type {
298 BotStatus(x) | UserStatus(x) => Ok(x),
299 _ => Err(UnexpectedUpdate(value)),
300 }
301 }
302}
303
304impl TryFrom<Update> for CallbackQuery {
305 type Error = UnexpectedUpdate;
306
307 fn try_from(value: Update) -> Result<Self, Self::Error> {
308 use self::UpdateType::*;
309 match value.update_type {
310 CallbackQuery(x) => Ok(x),
311 _ => Err(UnexpectedUpdate(value)),
312 }
313 }
314}
315
316impl TryFrom<Update> for ChatJoinRequest {
317 type Error = UnexpectedUpdate;
318
319 fn try_from(value: Update) -> Result<Self, Self::Error> {
320 use self::UpdateType::*;
321 match value.update_type {
322 ChatJoinRequest(x) => Ok(x),
323 _ => Err(UnexpectedUpdate(value)),
324 }
325 }
326}
327
328impl TryFrom<Update> for ChosenInlineResult {
329 type Error = UnexpectedUpdate;
330
331 fn try_from(value: Update) -> Result<Self, Self::Error> {
332 use self::UpdateType::*;
333 match value.update_type {
334 ChosenInlineResult(x) => Ok(x),
335 _ => Err(UnexpectedUpdate(value)),
336 }
337 }
338}
339
340impl TryFrom<Update> for InlineQuery {
341 type Error = UnexpectedUpdate;
342
343 fn try_from(value: Update) -> Result<Self, Self::Error> {
344 use self::UpdateType::*;
345 match value.update_type {
346 InlineQuery(x) => Ok(x),
347 _ => Err(UnexpectedUpdate(value)),
348 }
349 }
350}
351
352impl TryFrom<Update> for Message {
353 type Error = UnexpectedUpdate;
354
355 fn try_from(value: Update) -> Result<Self, Self::Error> {
356 use self::UpdateType::*;
357 match value.update_type {
358 BusinessMessage(x)
359 | EditedBusinessMessage(x)
360 | EditedChannelPost(x)
361 | EditedMessage(x)
362 | ChannelPost(x)
363 | Message(x) => Ok(x),
364 _ => Err(UnexpectedUpdate(value)),
365 }
366 }
367}
368
369impl TryFrom<Update> for Poll {
370 type Error = UnexpectedUpdate;
371
372 fn try_from(value: Update) -> Result<Self, Self::Error> {
373 use self::UpdateType::*;
374 match value.update_type {
375 Poll(x) => Ok(x),
376 _ => Err(UnexpectedUpdate(value)),
377 }
378 }
379}
380
381impl TryFrom<Update> for PollAnswer {
382 type Error = UnexpectedUpdate;
383
384 fn try_from(value: Update) -> Result<Self, Self::Error> {
385 use self::UpdateType::*;
386 match value.update_type {
387 PollAnswer(x) => Ok(x),
388 _ => Err(UnexpectedUpdate(value)),
389 }
390 }
391}
392
393impl TryFrom<Update> for PreCheckoutQuery {
394 type Error = UnexpectedUpdate;
395
396 fn try_from(value: Update) -> Result<Self, Self::Error> {
397 use self::UpdateType::*;
398 match value.update_type {
399 PreCheckoutQuery(x) => Ok(x),
400 _ => Err(UnexpectedUpdate(value)),
401 }
402 }
403}
404
405impl TryFrom<Update> for PaidMediaPurchased {
406 type Error = UnexpectedUpdate;
407
408 fn try_from(value: Update) -> Result<Self, Self::Error> {
409 use self::UpdateType::*;
410 match value.update_type {
411 PurchasedPaidMedia(x) => Ok(x),
412 _ => Err(UnexpectedUpdate(value)),
413 }
414 }
415}
416
417impl TryFrom<Update> for ShippingQuery {
418 type Error = UnexpectedUpdate;
419
420 fn try_from(value: Update) -> Result<Self, Self::Error> {
421 use self::UpdateType::*;
422 match value.update_type {
423 ShippingQuery(x) => Ok(x),
424 _ => Err(UnexpectedUpdate(value)),
425 }
426 }
427}
428
429#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
431#[serde(rename_all = "snake_case")]
432pub enum AllowedUpdate {
433 #[serde(rename = "my_chat_member")]
435 BotStatus,
436 BusinessConnection,
438 BusinessMessage,
440 CallbackQuery,
442 ChannelPost,
444 #[serde(rename = "removed_chat_boost")]
446 ChatBoostRemoved,
447 #[serde(rename = "chat_boost")]
449 ChatBoostUpdated,
450 ChatJoinRequest,
452 ChosenInlineResult,
454 DeletedBusinessMessages,
456 EditedBusinessMessage,
458 EditedChannelPost,
460 EditedMessage,
462 InlineQuery,
464 Message,
466 MessageReaction,
468 MessageReactionCount,
470 Poll,
472 PollAnswer,
474 PreCheckoutQuery,
476 PurchasedPaidMedia,
478 ShippingQuery,
480 #[serde(rename = "chat_member")]
482 UserStatus,
483}
484
485#[serde_with::skip_serializing_none]
486#[derive(Clone, Debug, Default, Serialize)]
488pub struct GetUpdates {
489 allowed_updates: Option<HashSet<AllowedUpdate>>,
490 limit: Option<Integer>,
491 offset: Option<Integer>,
492 timeout: Option<Integer>,
493}
494
495impl Method for GetUpdates {
496 type Response = Vec<Update>;
497
498 fn into_payload(self) -> Payload {
499 Payload::json("getUpdates", self)
500 }
501}
502
503impl GetUpdates {
504 pub fn add_allowed_update(mut self, value: AllowedUpdate) -> Self {
510 match self.allowed_updates {
511 Some(ref mut updates) => {
512 updates.insert(value);
513 }
514 None => {
515 let mut updates = HashSet::new();
516 updates.insert(value);
517 self.allowed_updates = Some(updates);
518 }
519 };
520 self
521 }
522
523 pub fn with_allowed_updates<T>(mut self, value: T) -> Self
537 where
538 T: IntoIterator<Item = AllowedUpdate>,
539 {
540 self.allowed_updates = Some(value.into_iter().collect());
541 self
542 }
543
544 pub fn with_limit(mut self, value: Integer) -> Self {
550 self.limit = Some(value);
551 self
552 }
553
554 pub fn with_offset(mut self, value: Integer) -> Self {
569 self.offset = Some(value);
570 self
571 }
572
573 pub fn with_timeout(mut self, value: Duration) -> Self {
580 self.timeout = Some(value.as_secs() as i64);
581 self
582 }
583}