telegram_bot_raw_ars/types/
message.rs

1use serde::de::{Deserialize, Deserializer, Error};
2
3use crate::types::*;
4use crate::url::*;
5
6/// This object represents a chat message or a channel post.
7#[derive(Debug, Clone, PartialEq, PartialOrd)]
8pub enum MessageOrChannelPost {
9    Message(Message),
10    ChannelPost(ChannelPost),
11}
12
13/// This object represents a chat message.
14#[derive(Debug, Clone, PartialEq, PartialOrd)]
15pub struct Message {
16    /// Unique message identifier inside this chat.
17    pub id: MessageId,
18    /// Sender, can be empty for messages sent to channels.
19    pub from: User,
20    /// Date the message was sent in Unix time.
21    pub date: Integer,
22    /// Conversation the message belongs to.
23    pub chat: MessageChat,
24    /// Information about the original message.
25    pub forward: Option<Forward>,
26    /// For replies, the original message. Note that the Message object in this field will not
27    /// contain further reply_to_message fields even if it itself is a reply.
28    pub reply_to_message: Option<Box<MessageOrChannelPost>>,
29    /// Date the message was last edited in Unix time.
30    pub edit_date: Option<Integer>,
31    /// Kind of the message.
32    pub kind: MessageKind,
33}
34
35/// This object represents a channel message.
36#[derive(Debug, Clone, PartialEq, PartialOrd)]
37pub struct ChannelPost {
38    /// Unique message identifier inside this chat.
39    pub id: MessageId,
40    /// Date the message was sent in Unix time.
41    pub date: Integer,
42    /// Conversation the message belongs to.
43    pub chat: Channel,
44    /// Information about the original message.
45    pub forward: Option<Forward>,
46    /// For replies, the original message. Note that the Message object in this field will not
47    /// contain further reply_to_message fields even if it itself is a reply.
48    pub reply_to_message: Option<Box<MessageOrChannelPost>>,
49    /// Date the message was last edited in Unix time.
50    pub edit_date: Option<Integer>,
51    /// Kind of the message.
52    pub kind: MessageKind,
53}
54
55/// Information about the original message.
56#[derive(Debug, Clone, PartialEq, PartialOrd)]
57pub struct Forward {
58    /// Date the original message was sent in Unix time
59    pub date: Integer,
60    /// Sender of the original message.
61    pub from: ForwardFrom,
62}
63
64/// Information about the source of the original message.
65#[derive(Debug, Clone, PartialEq, PartialOrd)]
66pub enum ForwardFrom {
67    /// Sender of the original message.
68    User {
69        /// Sender of the original message.
70        user: User,
71    },
72    /// For messages forwarded from a channel, information about the original channel.
73    Channel {
74        /// Original channel.
75        channel: Channel,
76        /// Identifier of the original message in the channel
77        message_id: Integer,
78    },
79    ChannelHiddenUser {
80        sender_name: String,
81    },
82    /// For messages forwarded from a hidden admin
83    HiddenGroupAdmin {
84        /// Original group
85        chat_id: SupergroupId,
86        /// Group title
87        title: String,
88    },
89}
90
91/// Kind of the message.
92#[derive(Debug, Clone, PartialEq, PartialOrd)]
93pub enum MessageKind {
94    /// Text message.
95    Text {
96        /// Actual UTF-8 text of the message, 0-4096 characters.
97        data: String,
98        /// Special entities like usernames, URLs, bot commands, etc. that appear in the text
99        entities: Vec<MessageEntity>,
100    },
101    /// Message is an audio file.
102    Audio {
103        /// Information about the file.
104        data: Audio,
105    },
106    /// Message is a general file.
107    Document {
108        /// Information about the file.
109        data: Document,
110        /// Caption for the document, 0-200 characters.
111        caption: Option<String>,
112    },
113    /// Message is a photo.
114    Photo {
115        /// Available sizes of the photo.
116        data: Vec<PhotoSize>,
117        /// Caption for the photo, 0-200 characters.
118        caption: Option<String>,
119        /// The unique identifier of a media message group this message belongs to.
120        media_group_id: Option<String>,
121    },
122    /// Message is a sticker.
123    Sticker {
124        /// Information about the sticker.
125        data: Sticker,
126    },
127    /// Message is a video.
128    Video {
129        /// Information about the video.
130        data: Video,
131        /// Caption for the video, 0-200 characters.
132        caption: Option<String>,
133        /// The unique identifier of a media message group this message belongs to.
134        media_group_id: Option<String>,
135    },
136    /// Message is a voice message.
137    Voice {
138        /// Information about the file.
139        data: Voice,
140    },
141    /// Message is a video note.
142    VideoNote {
143        /// Information about the file.
144        data: VideoNote,
145    },
146    /// Message is a shared contact.
147    Contact {
148        /// Information about the contact.
149        data: Contact,
150    },
151    /// Message is a shared location.
152    Location {
153        /// Information about the location.
154        data: Location,
155    },
156    /// Message is a poll.
157    Poll {
158        /// Information about the poll.
159        data: Poll,
160    },
161    /// Message is a venue.
162    Venue {
163        /// Information about the venue.
164        data: Venue,
165    },
166    /// New members that were added to the group or supergroup and
167    /// information about them (the bot itself may be one of these members)
168    NewChatMembers {
169        /// Information about user (this member may be the bot itself).
170        data: Vec<User>,
171    },
172    /// A member was removed from the group.
173    LeftChatMember {
174        /// Information about user (this member may be the bot itself).
175        data: User,
176    },
177    /// New chat title.
178    NewChatTitle {
179        /// A chat title was changed to this value.
180        data: String,
181    },
182    /// New chat photo.
183    NewChatPhoto {
184        /// A chat photo was change to this value.
185        data: Vec<PhotoSize>,
186    },
187    /// Service message: the chat photo was deleted.
188    DeleteChatPhoto,
189    /// Service message: the group has been created.
190    GroupChatCreated,
191    /// Service message: the supergroup has been created. This field can‘t be received in a
192    /// message coming through updates, because bot can’t be a member of a supergroup when
193    /// it is created. It can only be found in reply_to_message if someone replies to a very
194    /// first message in a directly created supergroup.
195    SupergroupChatCreated,
196    /// Service message: the channel has been created. This field can‘t be received in a message
197    /// coming through updates, because bot can’t be a member of a channel when it is created.
198    /// It can only be found in reply_to_message if someone replies
199    /// to a very first message in a channel.
200    ChannelChatCreated,
201    /// The group has been migrated to a supergroup.
202    MigrateToChatId {
203        /// Supergroup chat identifier.
204        data: Integer,
205    },
206    /// The supergroup has been migrated from a group.
207    MigrateFromChatId {
208        /// Group chat identifier.
209        data: Integer,
210    },
211    /// Specified message was pinned.
212    PinnedMessage {
213        // Specified message was pinned. Note that the Message object in this field will not
214        // contain further reply_to_message fields even if it is itself a reply.
215        data: Box<MessageOrChannelPost>,
216    },
217    #[doc(hidden)]
218    Unknown { raw: RawMessage },
219}
220
221impl Message {
222    fn from_raw_message(raw: RawMessage) -> Result<Self, String> {
223        let id = raw.message_id;
224        let from = match raw.from.clone() {
225            Some(from) => from,
226            None => return Err(format!("Missing `from` field for Message")),
227        };
228        let date = raw.date;
229        let chat = match raw.chat.clone() {
230            Chat::Private(x) => MessageChat::Private(x),
231            Chat::Group(x) => MessageChat::Group(x),
232            Chat::Supergroup(x) => MessageChat::Supergroup(x),
233            Chat::Unknown(x) => MessageChat::Unknown(x),
234            Chat::Channel(_) => return Err(format!("Channel chat in Message")),
235        };
236
237        let reply_to_message = raw.reply_to_message.clone();
238        let edit_date = raw.edit_date;
239
240        let forward = match (
241            raw.forward_date,
242            &raw.forward_from,
243            &raw.forward_from_chat,
244            raw.forward_from_message_id,
245            &raw.forward_sender_name,
246        ) {
247            (None, &None, &None, None, &None) => None,
248            (Some(date), &Some(ref from), &None, None, &None) => Some(Forward {
249                date: date,
250                from: ForwardFrom::User { user: from.clone() },
251            }),
252            (Some(date), &None, &Some(Chat::Channel(ref channel)), Some(message_id), &None) => {
253                Some(Forward {
254                    date: date,
255                    from: ForwardFrom::Channel {
256                        channel: channel.clone(),
257                        message_id: message_id,
258                    },
259                })
260            }
261            (Some(date), &None, &None, None, &Some(ref sender_name)) => Some(Forward {
262                date,
263                from: ForwardFrom::ChannelHiddenUser {
264                    sender_name: sender_name.clone(),
265                },
266            }),
267            (
268                Some(date),
269                None,
270                Some(Chat::Supergroup(Supergroup {
271                    id: chat_id, title, ..
272                })),
273                None,
274                None,
275            ) => Some(Forward {
276                date,
277                from: ForwardFrom::HiddenGroupAdmin {
278                    chat_id: chat_id.clone(),
279                    title: title.clone(),
280                },
281            }),
282            _ => return Err(format!("invalid forward fields combination")),
283        };
284
285        let make_message = |kind| {
286            Ok(Message {
287                id: id.into(),
288                from: from,
289                date: date,
290                chat: chat,
291                forward: forward,
292                reply_to_message: reply_to_message,
293                edit_date: edit_date,
294                kind: kind,
295            })
296        };
297
298        macro_rules! maybe_field {
299            ($name:ident, $variant:ident) => {{
300                if let Some(val) = raw.$name {
301                    return make_message(MessageKind::$variant { data: val });
302                }
303            }};
304        }
305
306        macro_rules! maybe_field_with_caption {
307            ($name:ident, $variant:ident) => {{
308                if let Some(val) = raw.$name {
309                    return make_message(MessageKind::$variant {
310                        data: val,
311                        caption: raw.caption,
312                    });
313                }
314            }};
315        }
316
317        macro_rules! maybe_field_with_caption_and_group {
318            ($name:ident, $variant:ident) => {{
319                if let Some(val) = raw.$name {
320                    return make_message(MessageKind::$variant {
321                        data: val,
322                        caption: raw.caption,
323                        media_group_id: raw.media_group_id,
324                    });
325                }
326            }};
327        }
328
329        macro_rules! maybe_true_field {
330            ($name:ident, $variant:ident) => {{
331                if let Some(True) = raw.$name {
332                    return make_message(MessageKind::$variant);
333                }
334            }};
335        }
336
337        if let Some(text) = raw.text {
338            let entities = raw.entities.unwrap_or_else(Vec::new);
339            return make_message(MessageKind::Text {
340                data: text,
341                entities: entities,
342            });
343        }
344
345        maybe_field!(audio, Audio);
346        maybe_field_with_caption!(document, Document);
347        maybe_field_with_caption_and_group!(photo, Photo);
348        maybe_field!(sticker, Sticker);
349        maybe_field_with_caption_and_group!(video, Video);
350        maybe_field!(voice, Voice);
351        maybe_field!(video_note, VideoNote);
352        maybe_field!(contact, Contact);
353        maybe_field!(location, Location);
354        maybe_field!(poll, Poll);
355        maybe_field!(venue, Venue);
356        maybe_field!(new_chat_members, NewChatMembers);
357        maybe_field!(left_chat_member, LeftChatMember);
358        maybe_field!(new_chat_title, NewChatTitle);
359        maybe_field!(new_chat_photo, NewChatPhoto);
360        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
361        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
362        maybe_true_field!(group_chat_created, GroupChatCreated);
363        maybe_true_field!(supergroup_chat_created, SupergroupChatCreated);
364        maybe_true_field!(channel_chat_created, ChannelChatCreated);
365        maybe_field!(migrate_to_chat_id, MigrateToChatId);
366        maybe_field!(migrate_from_chat_id, MigrateFromChatId);
367        maybe_field!(pinned_message, PinnedMessage);
368
369        make_message(MessageKind::Unknown { raw: raw })
370    }
371}
372
373impl<'de> Deserialize<'de> for Message {
374    fn deserialize<D>(deserializer: D) -> Result<Message, D::Error>
375    where
376        D: Deserializer<'de>,
377    {
378        let raw: RawMessage = Deserialize::deserialize(deserializer)?;
379
380        Self::from_raw_message(raw).map_err(|err| D::Error::custom(err))
381    }
382}
383
384impl ChannelPost {
385    fn from_raw_message(raw: RawMessage) -> Result<Self, String> {
386        let id = raw.message_id;
387        let date = raw.date;
388        let chat = match raw.chat.clone() {
389            Chat::Channel(channel) => channel,
390            _ => return Err(format!("Expected channel chat type for ChannelMessage")),
391        };
392        let reply_to_message = raw.reply_to_message.clone();
393        let edit_date = raw.edit_date;
394
395        let forward = match (
396            raw.forward_date,
397            &raw.forward_from,
398            &raw.forward_from_chat,
399            raw.forward_from_message_id,
400            &raw.forward_sender_name,
401        ) {
402            (None, &None, &None, None, &None) => None,
403            (Some(date), &Some(ref from), &None, None, &None) => Some(Forward {
404                date: date,
405                from: ForwardFrom::User { user: from.clone() },
406            }),
407            (Some(date), &None, &Some(Chat::Channel(ref channel)), Some(message_id), &None) => {
408                Some(Forward {
409                    date: date,
410                    from: ForwardFrom::Channel {
411                        channel: channel.clone(),
412                        message_id: message_id,
413                    },
414                })
415            }
416            (Some(date), &None, &None, None, &Some(ref sender_name)) => Some(Forward {
417                date,
418                from: ForwardFrom::ChannelHiddenUser {
419                    sender_name: sender_name.clone(),
420                },
421            }),
422            (
423                Some(date),
424                None,
425                Some(Chat::Supergroup(Supergroup {
426                    id: chat_id, title, ..
427                })),
428                None,
429                None,
430            ) => Some(Forward {
431                date,
432                from: ForwardFrom::HiddenGroupAdmin {
433                    chat_id: chat_id.clone(),
434                    title: title.clone(),
435                },
436            }),
437            _ => return Err(format!("invalid forward fields combination")),
438        };
439
440        let make_message = |kind| {
441            Ok(ChannelPost {
442                id: id.into(),
443                date: date,
444                chat: chat,
445                forward: forward,
446                reply_to_message: reply_to_message,
447                edit_date: edit_date,
448                kind: kind,
449            })
450        };
451
452        macro_rules! maybe_field {
453            ($name:ident, $variant:ident) => {{
454                if let Some(val) = raw.$name {
455                    return make_message(MessageKind::$variant { data: val });
456                }
457            }};
458        }
459
460        macro_rules! maybe_field_with_caption {
461            ($name:ident, $variant:ident) => {{
462                if let Some(val) = raw.$name {
463                    return make_message(MessageKind::$variant {
464                        data: val,
465                        caption: raw.caption,
466                    });
467                }
468            }};
469        }
470
471        macro_rules! maybe_field_with_caption_and_group {
472            ($name:ident, $variant:ident) => {{
473                if let Some(val) = raw.$name {
474                    return make_message(MessageKind::$variant {
475                        data: val,
476                        caption: raw.caption,
477                        media_group_id: raw.media_group_id,
478                    });
479                }
480            }};
481        }
482
483        macro_rules! maybe_true_field {
484            ($name:ident, $variant:ident) => {{
485                if let Some(True) = raw.$name {
486                    return make_message(MessageKind::$variant);
487                }
488            }};
489        }
490
491        if let Some(text) = raw.text {
492            let entities = raw.entities.unwrap_or_else(Vec::new);
493            return make_message(MessageKind::Text {
494                data: text,
495                entities: entities,
496            });
497        }
498
499        maybe_field!(audio, Audio);
500        maybe_field_with_caption!(document, Document);
501        maybe_field_with_caption_and_group!(photo, Photo);
502        maybe_field!(sticker, Sticker);
503        maybe_field_with_caption_and_group!(video, Video);
504        maybe_field!(voice, Voice);
505        maybe_field!(video_note, VideoNote);
506        maybe_field!(contact, Contact);
507        maybe_field!(location, Location);
508        maybe_field!(poll, Poll);
509        maybe_field!(venue, Venue);
510        maybe_field!(new_chat_members, NewChatMembers);
511        maybe_field!(left_chat_member, LeftChatMember);
512        maybe_field!(new_chat_title, NewChatTitle);
513        maybe_field!(new_chat_photo, NewChatPhoto);
514        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
515        maybe_true_field!(delete_chat_photo, DeleteChatPhoto);
516        maybe_true_field!(group_chat_created, GroupChatCreated);
517        maybe_true_field!(supergroup_chat_created, SupergroupChatCreated);
518        maybe_true_field!(channel_chat_created, ChannelChatCreated);
519        maybe_field!(migrate_to_chat_id, MigrateToChatId);
520        maybe_field!(migrate_from_chat_id, MigrateFromChatId);
521        maybe_field!(pinned_message, PinnedMessage);
522
523        make_message(MessageKind::Unknown { raw: raw })
524    }
525}
526
527impl<'de> Deserialize<'de> for ChannelPost {
528    // TODO(knsd): Remove .clone()
529    fn deserialize<D>(deserializer: D) -> Result<ChannelPost, D::Error>
530    where
531        D: Deserializer<'de>,
532    {
533        let raw: RawMessage = Deserialize::deserialize(deserializer)?;
534
535        Self::from_raw_message(raw).map_err(|err| D::Error::custom(err))
536    }
537}
538
539impl<'de> Deserialize<'de> for MessageOrChannelPost {
540    // TODO(knsd): Remove .clone()
541    fn deserialize<D>(deserializer: D) -> Result<MessageOrChannelPost, D::Error>
542    where
543        D: Deserializer<'de>,
544    {
545        let raw: RawMessage = Deserialize::deserialize(deserializer)?;
546        let is_channel = match raw.chat {
547            Chat::Channel(_) => true,
548            _ => false,
549        };
550
551        let res = if is_channel {
552            ChannelPost::from_raw_message(raw).map(MessageOrChannelPost::ChannelPost)
553        } else {
554            Message::from_raw_message(raw).map(MessageOrChannelPost::Message)
555        };
556
557        res.map_err(|err| D::Error::custom(err))
558    }
559}
560
561/// This object represents a message. Directly mapped.
562#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
563pub struct RawMessage {
564    /// Unique message identifier inside this chat.
565    pub message_id: Integer,
566    /// Sender, can be empty for messages sent to channels.
567    pub from: Option<User>,
568    /// Date the message was sent in Unix time.
569    pub date: Integer,
570    /// Conversation the message belongs to.
571    pub chat: Chat,
572    /// For forwarded messages, sender of the original message.
573    pub forward_from: Option<User>,
574    /// For messages forwarded from a channel, information about the original channel.
575    pub forward_from_chat: Option<Chat>,
576    /// For forwarded channel posts, identifier of the original message in the channel.
577    pub forward_from_message_id: Option<Integer>,
578    /// For forwarded messages, date the original message was sent in Unix time.
579    pub forward_date: Option<Integer>,
580    /// For replies, the original message. Note that the Message object in this field will not
581    /// contain further reply_to_message fields even if it itself is a reply.
582    pub reply_to_message: Option<Box<MessageOrChannelPost>>,
583    /// Date the message was last edited in Unix time.
584    pub edit_date: Option<Integer>,
585    /// The unique identifier of a media message group this message belongs to.
586    pub media_group_id: Option<String>,
587    /// For text messages, the actual UTF-8 text of the message, 0-4096 characters.
588    pub text: Option<String>,
589    /// For text messages, special entities like usernames, URLs, bot commands, etc.
590    /// that appear in the text.
591    pub entities: Option<Vec<MessageEntity>>,
592    /// Message is an audio file, information about the file.
593    pub audio: Option<Audio>,
594    /// Message is a general file, information about the file.
595    pub document: Option<Document>,
596    // pub game: Option<Game>,
597    /// Message is a photo, available sizes of the photo.
598    pub photo: Option<Vec<PhotoSize>>,
599    /// Message is a sticker, information about the sticker.
600    pub sticker: Option<Sticker>,
601    /// Message is a video, information about the video.
602    pub video: Option<Video>,
603    /// Message is a voice message, information about the file.
604    pub voice: Option<Voice>,
605    /// Message is a video note message, information about the file.
606    pub video_note: Option<VideoNote>,
607    /// Caption for the document, photo or video, 0-200 characters.
608    pub caption: Option<String>,
609    /// Message is a shared contact, information about the contact.
610    pub contact: Option<Contact>,
611    /// Message is a shared location, information about the location.
612    pub location: Option<Location>,
613    /// Message is a native poll, information about the poll.
614    pub poll: Option<Poll>,
615    /// Message is a venue, information about the venue.
616    pub venue: Option<Venue>,
617    /// New members that were added to the group or supergroup and information
618    /// about them (the bot itself may be one of these members)
619    pub new_chat_members: Option<Vec<User>>,
620    /// A member was removed from the group, information about
621    /// them (this member may be the bot itself)
622    pub left_chat_member: Option<User>,
623    /// A chat title was changed to this value.
624    pub new_chat_title: Option<String>,
625    /// A chat photo was change to this value.
626    pub new_chat_photo: Option<Vec<PhotoSize>>,
627    /// Service message: the chat photo was deleted.
628    pub delete_chat_photo: Option<True>,
629    /// Service message: the group has been created.
630    pub group_chat_created: Option<True>,
631    /// Service message: the supergroup has been created. This field can‘t be received in a
632    /// message coming through updates, because bot can’t be a member of a supergroup when
633    /// it is created. It can only be found in reply_to_message if someone replies to a very
634    /// first message in a directly created supergroup.
635    pub supergroup_chat_created: Option<True>,
636    /// Service message: the channel has been created. This field can‘t be received in a message
637    /// coming through updates, because bot can’t be a member of a channel when it is created.
638    /// It can only be found in reply_to_message if someone replies
639    /// to a very first message in a channel.
640    pub channel_chat_created: Option<True>,
641    /// The group has been migrated to a supergroup with the specified identifier.
642    pub migrate_to_chat_id: Option<Integer>,
643    /// The supergroup has been migrated from a group with the specified identifier.
644    pub migrate_from_chat_id: Option<Integer>,
645    /// Specified message was pinned. Note that the Message object in this field will not contain
646    /// further reply_to_message fields even if it is itself a reply.
647    pub pinned_message: Option<Box<MessageOrChannelPost>>,
648    /// Forward from channel by a hidden user.
649    pub forward_sender_name: Option<String>,
650}
651
652/// This object represents one special entity in a text message.
653/// For example, hashtags, usernames, URLs, etc.
654#[derive(Debug, Clone, PartialEq, PartialOrd)]
655pub struct MessageEntity {
656    /// Offset in UTF-16 code units to the start of the entity
657    pub offset: Integer,
658    /// Length of the entity in UTF-16 code units
659    pub length: Integer,
660    /// Kind of the entity.
661    pub kind: MessageEntityKind,
662}
663
664/// Kind of the entity.
665#[derive(Debug, Clone, PartialEq, PartialOrd)]
666pub enum MessageEntityKind {
667    Mention,
668    Hashtag,
669    BotCommand,
670    Url,
671    Email,
672    Bold,
673    Italic,
674    Code,
675    Pre,
676    TextLink(String), // TODO(knsd) URL?
677    TextMention(User),
678    #[doc(hidden)]
679    Unknown(RawMessageEntity),
680}
681
682impl<'de> Deserialize<'de> for MessageEntity {
683    fn deserialize<D>(deserializer: D) -> Result<MessageEntity, D::Error>
684    where
685        D: Deserializer<'de>,
686    {
687        use self::MessageEntityKind::*;
688
689        let raw: RawMessageEntity = Deserialize::deserialize(deserializer)?;
690
691        let offset = raw.offset;
692        let length = raw.length;
693
694        macro_rules! required_field {
695            ($name:ident) => {{
696                match raw.$name {
697                    Some(val) => val,
698                    None => return Err(D::Error::missing_field(stringify!($name))),
699                }
700            }};
701        }
702
703        let kind = match raw.type_.as_str() {
704            "mention" => Mention,
705            "hashtag" => Hashtag,
706            "bot_command" => BotCommand,
707            "url" => Url,
708            "email" => Email,
709            "bold" => Bold,
710            "italic" => Italic,
711            "code" => Code,
712            "pre" => Pre,
713            "text_link" => TextLink(required_field!(url)),
714            "text_mention" => TextMention(required_field!(user)),
715            _ => Unknown(raw),
716        };
717
718        Ok(MessageEntity {
719            offset: offset,
720            length: length,
721            kind: kind,
722        })
723    }
724}
725
726/// This object represents one special entity in a text message.
727/// For example, hashtags, usernames, URLs, etc. Directly mapped.
728#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
729pub struct RawMessageEntity {
730    /// Type of the entity. Can be mention (@username), hashtag, bot_command, url, email,
731    /// bold (bold text), italic (italic text), code (monowidth string), pre (monowidth block),
732    /// text_link (for clickable text URLs), text_mention (for users without usernames).
733    #[serde(rename = "type")]
734    pub type_: String,
735    /// Offset in UTF-16 code units to the start of the entity.
736    pub offset: Integer,
737    /// Length of the entity in UTF-16 code units.
738    pub length: Integer,
739    /// For “text_link” only, url that will be opened after user taps on the text.
740    pub url: Option<String>,
741    /// For “text_mention” only, the mentioned user.
742    pub user: Option<User>,
743}
744
745/// This object represents one size of a photo or a file / sticker thumbnail.
746#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
747pub struct PhotoSize {
748    /// Unique identifier for this file.
749    pub file_id: String,
750    /// Photo width.
751    pub width: Integer,
752    /// Photo height.
753    pub height: Integer,
754    /// File size.
755    pub file_size: Option<Integer>,
756}
757
758/// This object represents an audio file to be treated as music by the Telegram clients.
759#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
760pub struct Audio {
761    /// Unique identifier for this file.
762    pub file_id: String,
763    /// Duration of the audio in seconds as defined by sender.
764    pub duration: Integer,
765    /// Performer of the audio as defined by sender or by audio tags.
766    pub performer: Option<String>,
767    /// Title of the audio as defined by sender or by audio tags.
768    pub title: Option<String>,
769    /// MIME type of the file as defined by sender.
770    pub mime_type: Option<String>,
771    /// File size.
772    pub file_size: Option<Integer>,
773}
774
775/// This object represents a general file (as opposed to photos, voice messages and audio files).
776#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
777pub struct Document {
778    /// Unique file identifier for one bot
779    pub file_id: String,
780    /// Unique file identifier for all bots
781    pub file_unique_id: Option<String>,
782    /// Document thumbnail as defined by sender.
783    pub thumb: Option<PhotoSize>,
784    /// Original filename as defined by sender.
785    pub file_name: Option<String>,
786    /// MIME type of the file as defined by sender.
787    pub mime_type: Option<String>,
788    /// File size.
789    pub file_size: Option<Integer>,
790    /// Path for download
791    pub file_path: Option<String>,
792}
793
794/// This object represents a sticker.
795#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
796pub struct Sticker {
797    /// Identifier for this file, which can be used to download or reuse the file.
798    pub file_id: String,
799    /// Unique identifier for this file, which is supposed to be the same over time and for different bots.
800    /// Can't be used to download or reuse the file.
801    pub file_unique_id: String,
802    /// Sticker width.
803    pub width: Integer,
804    /// Sticker height.
805    pub height: Integer,
806    /// Sticker thumbnail in .webp or .jpg format.
807    pub thumb: Option<PhotoSize>,
808    /// Emoji associated with the sticker.
809    pub emoji: Option<String>,
810    /// The name of the sticker set this sticker belongs to.
811    pub set_name: Option<String>,
812    /// File size.
813    pub file_size: Option<Integer>,
814}
815
816/// This object represents a video file.
817#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
818pub struct Video {
819    /// Unique identifier for this file.
820    pub file_id: String,
821    /// Video width as defined by sender.
822    pub width: Integer,
823    /// Video height as defined by sender.
824    pub height: Integer,
825    /// Duration of the video in seconds as defined by sender.
826    pub duration: Integer,
827    /// Video thumbnail.
828    pub thumb: Option<PhotoSize>,
829    /// Mime type of a file as defined by sender.
830    pub mime_type: Option<String>,
831    /// File size.
832    pub file_size: Option<Integer>,
833}
834
835/// This object represents a voice note.
836#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
837pub struct Voice {
838    /// Unique identifier for this file.
839    pub file_id: String,
840    /// Duration of the audio in seconds as defined by sender.
841    pub duration: Integer,
842    /// MIME type of the file as defined by sender.
843    pub mime_type: Option<String>,
844    /// File size.
845    pub file_size: Option<Integer>,
846}
847
848/// This object represents a video message (available in Telegram apps as of v.4.0).
849#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
850pub struct VideoNote {
851    /// Unique identifier for this file.
852    pub file_id: String,
853    pub length: Integer,
854    /// Duration of the video in seconds as defined by sender.
855    pub duration: Integer,
856    /// Video thumbnail.
857    pub thumb: Option<PhotoSize>,
858    /// File size.
859    pub file_size: Option<Integer>,
860}
861
862/// This object represents a phone contact.
863#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
864pub struct Contact {
865    /// Contact's phone number.
866    pub phone_number: String,
867    /// Contact's first name.
868    pub first_name: String,
869    /// Contact's last name.
870    pub last_name: Option<String>,
871    /// Contact's user identifier in Telegram.
872    pub user_id: Option<Integer>,
873}
874
875/// This object represents a point on the map.
876#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
877pub struct Location {
878    /// Longitude as defined by sender.
879    pub longitude: Float,
880    /// Latitude as defined by sender.
881    pub latitude: Float,
882}
883
884/// This object represents a venue.
885#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
886pub struct Venue {
887    /// Venue location.
888    pub location: Location,
889    /// Name of the venue.
890    pub title: String,
891    /// Address of the venue.
892    pub address: String,
893    /// Foursquare identifier of the venue.
894    pub foursquare_id: Option<String>,
895}
896
897/// This object contains information about a poll.
898#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
899pub struct Poll {
900    /// Unique poll identifier.
901    pub id: String,
902    /// Poll question.
903    pub question: String,
904    /// List of poll options.
905    pub options: Vec<PollOption>,
906    /// Total number of users that voted in the poll.
907    pub total_voter_count: Integer,
908    /// True, if the poll is closed.
909    pub is_closed: bool,
910    /// True, if the poll is anonymous.
911    pub is_anonymous: bool,
912    /// Poll type.
913    #[serde(rename = "type")]
914    pub type_: PollType,
915    /// True, if the poll allows multiple answers.
916    pub allows_multiple_answers: bool,
917    /// 0-based identifier of the correct answer option. Available only for polls in the quiz mode,
918    /// which are closed, or was sent (not forwarded) by the bot or to the private chat with the bot.
919    pub correct_option_id: Option<Integer>,
920    /// Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll.
921    pub explanation: Option<String>,
922    /// Special entities like usernames, URLs, bot commands, etc. that appear in the explanation.
923    pub explanation_entities: Option<Vec<MessageEntity>>,
924    /// Amount of time in seconds the poll will be active after creation.
925    pub open_period: Option<Integer>,
926    /// Point in time (Unix timestamp) when the poll will be automatically closed.
927    pub close_date: Option<Integer>,
928}
929
930/// This object represents an answer of a user in a non-anonymous poll.
931#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
932pub struct PollAnswer {
933    /// Unique poll identifier.
934    pub poll_id: String,
935    /// The user, who changed the answer to the poll.
936    pub user: User,
937    /// 0-based identifiers of answer options, chosen by the user. May be empty if the user retracted their vote.
938    pub option_ids: Vec<Integer>,
939}
940
941/// This object contains information about one answer option in a poll.
942#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
943pub struct PollOption {
944    /// Option text.
945    pub text: String,
946    /// Number of users that voted for this option.
947    pub voter_count: Integer,
948}
949
950/// Type of a poll.
951#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
952pub enum PollType {
953    #[serde(rename = "regular")]
954    Regular,
955    #[serde(rename = "quiz")]
956    Quiz,
957}
958
959/// This object represent a user's profile pictures.
960#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
961pub struct UserProfilePhotos {
962    /// Total number of profile pictures the target user has.
963    pub total_count: Integer,
964    /// Requested profile pictures (in up to 4 sizes each).
965    pub photos: Vec<Vec<PhotoSize>>,
966}
967
968/// This object represents a file ready to be downloaded.
969/// The file can be downloaded via the link `https://api.telegram.org/file/bot<token>/<file_path>`.
970/// It is guaranteed that the link will be valid for at least 1 hour.
971#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
972pub struct File {
973    /// Unique identifier for this file.
974    pub file_id: String,
975    /// File size, if known.
976    pub file_size: Option<Integer>,
977    /// File path. Use `https://api.telegram.org/file/bot<token>/<file_path>` to get the file.
978    pub file_path: Option<String>,
979}
980
981impl File {
982    pub fn get_url(&self, token: &str) -> Option<String> {
983        self.file_path
984            .as_ref()
985            .map(|path| format!("{}file/bot{}/{}", telegram_api_url(), token, path))
986    }
987}
988
989/// Strongly typed ParseMode.
990/// See [documentation](https://core.telegram.org/bots/api#formatting-options) for details.
991#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize)]
992pub enum ParseMode {
993    /// Use legacy markdown formatting.
994    Markdown,
995    /// Use MarkdownV2 formatting.
996    MarkdownV2,
997    /// Use HTML formatting.
998    #[serde(rename = "HTML")]
999    Html,
1000}
1001
1002impl ::std::fmt::Display for ParseMode {
1003    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
1004        match *self {
1005            ParseMode::Markdown => write!(f, "Markdown"),
1006            ParseMode::MarkdownV2 => write!(f, "MarkdownV2"),
1007            ParseMode::Html => write!(f, "HTML"),
1008        }
1009    }
1010}