1#!/usr/bin/env python
2# pylint: disable=R0902,R0913
3#
4# A library that provides a Python interface to the Telegram Bot API
5# Copyright (C) 2015-2020
6# Leandro Toledo de Souza <devs@python-telegram-bot.org>
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU Lesser Public License as published by
10# the Free Software Foundation, either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU Lesser Public License for more details.
17#
18# You should have received a copy of the GNU Lesser Public License
19# along with this program.  If not, see [http://www.gnu.org/licenses/].
20"""This module contains an object that represents a Telegram Message."""
21import datetime
22import sys
23from html import escape
24from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, ClassVar
25
26from telegram import (
27    Animation,
28    Audio,
29    Chat,
30    Contact,
31    Dice,
32    Document,
33    Game,
34    InlineKeyboardMarkup,
35    Invoice,
36    Location,
37    MessageEntity,
38    ParseMode,
39    PassportData,
40    PhotoSize,
41    Poll,
42    Sticker,
43    SuccessfulPayment,
44    TelegramObject,
45    User,
46    Venue,
47    Video,
48    VideoNote,
49    Voice,
50    ProximityAlertTriggered,
51)
52from telegram.utils.helpers import escape_markdown, from_timestamp, to_timestamp
53from telegram.utils.types import JSONDict
54
55if TYPE_CHECKING:
56    from telegram import Bot, GameHighScore, InputMedia, MessageId
57
58_UNDEFINED = object()
59
60
61class Message(TelegramObject):
62    # fmt: off
63    """This object represents a message.
64
65    Objects of this class are comparable in terms of equality. Two objects of this class are
66    considered equal, if their :attr:`message_id` and :attr:`chat` are equal.
67
68    Note:
69        * In Python `from` is a reserved word, use `from_user` instead.
70
71    Attributes:
72        message_id (:obj:`int`): Unique message identifier inside this chat.
73        from_user (:class:`telegram.User`): Optional. Sender.
74        sender_chat (:class:`telegram.Chat`): Optional. Sender of the message, sent on behalf of a
75            chat. The channel itself for channel messages. The supergroup itself for messages from
76            anonymous group administrators. The linked channel for messages automatically forwarded
77            to the discussion group.
78        date (:class:`datetime.datetime`): Date the message was sent.
79        chat (:class:`telegram.Chat`): Conversation the message belongs to.
80        forward_from (:class:`telegram.User`): Optional. Sender of the original message.
81        forward_from_chat (:class:`telegram.Chat`): Optional. For messages forwarded from channels
82            or from anonymous administrators, information about the original sender chat.
83        forward_from_message_id (:obj:`int`): Optional. Identifier of the original message in the
84            channel.
85        forward_date (:class:`datetime.datetime`): Optional. Date the original message was sent.
86        reply_to_message (:class:`telegram.Message`): Optional. For replies, the original message.
87            Note that the Message object in this field will not contain further
88            ``reply_to_message`` fields even if it itself is a reply.
89        edit_date (:class:`datetime.datetime`): Optional. Date the message was last edited.
90        media_group_id (:obj:`str`): Optional. The unique identifier of a media message group this
91            message belongs to.
92        text (:obj:`str`): Optional. The actual UTF-8 text of the message.
93        entities (List[:class:`telegram.MessageEntity`]): Optional. Special entities like
94            usernames, URLs, bot commands, etc. that appear in the text. See
95            :attr:`Message.parse_entity` and :attr:`parse_entities` methods for how to use
96            properly.
97        caption_entities (List[:class:`telegram.MessageEntity`]): Optional. Special entities like
98            usernames, URLs, bot commands, etc. that appear in the caption. See
99            :attr:`Message.parse_caption_entity` and :attr:`parse_caption_entities` methods for how
100            to use properly.
101        audio (:class:`telegram.Audio`): Optional. Information about the file.
102        document (:class:`telegram.Document`): Optional. Information about the file.
103        animation (:class:`telegram.Animation`) Optional. Information about the file.
104            For backward compatibility, when this field is set, the document field will also be
105            set.
106        game (:class:`telegram.Game`): Optional. Information about the game.
107        photo (List[:class:`telegram.PhotoSize`]): Optional. Available sizes of the photo.
108        sticker (:class:`telegram.Sticker`): Optional. Information about the sticker.
109        video (:class:`telegram.Video`): Optional. Information about the video.
110        voice (:class:`telegram.Voice`): Optional. Information about the file.
111        video_note (:class:`telegram.VideoNote`): Optional. Information about the video message.
112        new_chat_members (List[:class:`telegram.User`]): Optional. Information about new members to
113            the chat. (the bot itself may be one of these members).
114        caption (:obj:`str`): Optional. Caption for the document, photo or video, 0-1024
115            characters.
116        contact (:class:`telegram.Contact`): Optional. Information about the contact.
117        location (:class:`telegram.Location`): Optional. Information about the location.
118        venue (:class:`telegram.Venue`): Optional. Information about the venue.
119        left_chat_member (:class:`telegram.User`): Optional. Information about the user that left
120            the group. (this member may be the bot itself).
121        new_chat_title (:obj:`str`): Optional. A chat title was changed to this value.
122        new_chat_photo (List[:class:`telegram.PhotoSize`]): Optional. A chat photo was changed to
123            this value.
124        delete_chat_photo (:obj:`bool`): Optional. The chat photo was deleted.
125        group_chat_created (:obj:`bool`): Optional. The group has been created.
126        supergroup_chat_created (:obj:`bool`): Optional. The supergroup has been created.
127        channel_chat_created (:obj:`bool`): Optional. The channel has been created.
128        migrate_to_chat_id (:obj:`int`): Optional. The group has been migrated to a supergroup with
129            the specified identifier.
130        migrate_from_chat_id (:obj:`int`): Optional. The supergroup has been migrated from a group
131            with the specified identifier.
132        pinned_message (:class:`telegram.message`): Optional. Specified message was pinned.
133        invoice (:class:`telegram.Invoice`): Optional. Information about the invoice.
134        successful_payment (:class:`telegram.SuccessfulPayment`): Optional. Information about the
135            payment.
136        connected_website (:obj:`str`): Optional. The domain name of the website on which the user
137            has logged in.
138        forward_signature (:obj:`str`): Optional. Signature of the post author for messages
139            forwarded from channels.
140        forward_sender_name	(:obj:`str`): Optional. Sender's name for messages forwarded from users
141            who disallow adding a link to their account in forwarded messages.
142        author_signature (:obj:`str`): Optional. Signature of the post author for messages in
143            channels, or the custom title of an anonymous group administrator.
144        passport_data (:class:`telegram.PassportData`): Optional. Telegram Passport data.
145        poll (:class:`telegram.Poll`): Optional. Message is a native poll,
146            information about the poll.
147        dice (:class:`telegram.Dice`): Optional. Message is a dice.
148        via_bot (:class:`telegram.User`): Optional. Bot through which the message was sent.
149        proximity_alert_triggered (:class:`telegram.ProximityAlertTriggered`): Optional. Service
150            message. A user in the chat triggered another user's proximity alert while sharing
151            Live Location.
152        reply_markup (:class:`telegram.InlineKeyboardMarkup`): Optional. Inline keyboard attached
153            to the message.
154        bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
155
156    Args:
157        message_id (:obj:`int`): Unique message identifier inside this chat.
158        from_user (:class:`telegram.User`, optional): Sender, empty for messages sent
159            to channels.
160        sender_chat (:class:`telegram.Chat`, optional): Sender of the message, sent on behalf of a
161            chat. The channel itself for channel messages. The supergroup itself for messages from
162            anonymous group administrators. The linked channel for messages automatically forwarded
163            to the discussion group.
164        date (:class:`datetime.datetime`): Date the message was sent in Unix time. Converted to
165            :class:`datetime.datetime`.
166        chat (:class:`telegram.Chat`): Conversation the message belongs to.
167        forward_from (:class:`telegram.User`, optional): For forwarded messages, sender of
168            the original message.
169        forward_from_chat (:class:`telegram.Chat`, optional): For messages forwarded from channels
170            or from anonymous administrators, information about the original sender chat.
171        forward_from_message_id (:obj:`int`, optional): For forwarded channel posts, identifier of
172            the original message in the channel.
173        forward_sender_name	(:obj:`str`, optional): Sender's name for messages forwarded from users
174            who disallow adding a link to their account in forwarded messages.
175        forward_date (:class:`datetime.datetime`, optional): For forwarded messages, date the
176            original message was sent in Unix time. Converted to :class:`datetime.datetime`.
177        reply_to_message (:class:`telegram.Message`, optional): For replies, the original message.
178        edit_date (:class:`datetime.datetime`, optional): Date the message was last edited in Unix
179            time. Converted to :class:`datetime.datetime`.
180        media_group_id (:obj:`str`, optional): The unique identifier of a media message group this
181            message belongs to.
182        text (str, optional): For text messages, the actual UTF-8 text of the message, 0-4096
183            characters. Also found as :attr:`telegram.constants.MAX_MESSAGE_LENGTH`.
184        entities (List[:class:`telegram.MessageEntity`], optional): For text messages, special
185            entities like usernames, URLs, bot commands, etc. that appear in the text. See
186            :attr:`parse_entity` and :attr:`parse_entities` methods for how to use properly.
187        caption_entities (List[:class:`telegram.MessageEntity`]): Optional. For Messages with a
188            Caption. Special entities like usernames, URLs, bot commands, etc. that appear in the
189            caption. See :attr:`Message.parse_caption_entity` and :attr:`parse_caption_entities`
190            methods for how to use properly.
191        audio (:class:`telegram.Audio`, optional): Message is an audio file, information
192            about the file.
193        document (:class:`telegram.Document`, optional): Message is a general file, information
194            about the file.
195        animation (:class:`telegram.Animation`, optional): Message is an animation, information
196            about the animation. For backward compatibility, when this field is set, the document
197            field will also be set.
198        game (:class:`telegram.Game`, optional): Message is a game, information about the game.
199        photo (List[:class:`telegram.PhotoSize`], optional): Message is a photo, available
200            sizes of the photo.
201        sticker (:class:`telegram.Sticker`, optional): Message is a sticker, information
202            about the sticker.
203        video (:class:`telegram.Video`, optional): Message is a video, information about the video.
204        voice (:class:`telegram.Voice`, optional): Message is a voice message, information about
205            the file.
206        video_note (:class:`telegram.VideoNote`, optional): Message is a video note, information
207            about the video message.
208        new_chat_members (List[:class:`telegram.User`], optional): New members that were added to
209            the group or supergroup and information about them (the bot itself may be one of these
210            members).
211        caption (:obj:`str`, optional): Caption for the animation, audio, document, photo, video
212            or voice, 0-1024 characters.
213        contact (:class:`telegram.Contact`, optional): Message is a shared contact, information
214            about the contact.
215        location (:class:`telegram.Location`, optional): Message is a shared location, information
216            about the location.
217        venue (:class:`telegram.Venue`, optional): Message is a venue, information about the venue.
218            For backward compatibility, when this field is set, the location field will also be
219            set.
220        left_chat_member (:class:`telegram.User`, optional): A member was removed from the group,
221            information about them (this member may be the bot itself).
222        new_chat_title (:obj:`str`, optional): A chat title was changed to this value.
223        new_chat_photo (List[:class:`telegram.PhotoSize`], optional): A chat photo was changed to
224            this value.
225        delete_chat_photo (:obj:`bool`, optional): Service message: The chat photo was deleted.
226        group_chat_created (:obj:`bool`, optional): Service message: The group has been created.
227        supergroup_chat_created (:obj:`bool`, optional): Service message: The supergroup has been
228            created. This field can't be received in a message coming through updates, because bot
229            can't be a member of a supergroup when it is created. It can only be found in
230            :attr:`reply_to_message` if someone replies to a very first message in a directly
231            created supergroup.
232        channel_chat_created (:obj:`bool`, optional): Service message: The channel has been
233            created. This field can't be received in a message coming through updates, because bot
234            can't be a member of a channel when it is created. It can only be found in
235            :attr:`reply_to_message` if someone replies to a very first message in a channel.
236        migrate_to_chat_id (:obj:`int`, optional): The group has been migrated to a supergroup with
237            the specified identifier. This number may be greater than 32 bits and some programming
238            languages may have difficulty/silent defects in interpreting it. But it is smaller than
239            52 bits, so a signed 64 bit integer or double-precision float type are safe for storing
240            this identifier.
241        migrate_from_chat_id (:obj:`int`, optional): The supergroup has been migrated from a group
242            with the specified identifier. This number may be greater than 32 bits and some
243            programming languages may have difficulty/silent defects in interpreting it. But it is
244            smaller than 52 bits, so a signed 64 bit integer or double-precision float type are
245            safe for storing this identifier.
246        pinned_message (:class:`telegram.Message`, optional): Specified message was pinned. Note
247            that the Message object in this field will not contain further :attr:`reply_to_message`
248            fields even if it is itself a reply.
249        invoice (:class:`telegram.Invoice`, optional): Message is an invoice for a payment,
250            information about the invoice.
251        successful_payment (:class:`telegram.SuccessfulPayment`, optional): Message is a service
252            message about a successful payment, information about the payment.
253        connected_website (:obj:`str`, optional): The domain name of the website on which the user
254            has logged in.
255        forward_signature (:obj:`str`, optional): For messages forwarded from channels, signature
256            of the post author if present.
257        author_signature (:obj:`str`, optional):  Signature of the post author for messages in
258            channels, or the custom title of an anonymous group administrator.
259        passport_data (:class:`telegram.PassportData`, optional): Telegram Passport data.
260        poll (:class:`telegram.Poll`, optional): Message is a native poll,
261            information about the poll.
262        dice (:class:`telegram.Dice`, optional): Message is a dice with random value from 1 to 6.
263        via_bot (:class:`telegram.User`, optional): Message was sent through an inline bot.
264        proximity_alert_triggered (:class:`telegram.ProximityAlertTriggered`, optional): Service
265            message. A user in the chat triggered another user's proximity alert while sharing
266            Live Location.
267        reply_markup (:class:`telegram.InlineKeyboardMarkup`, optional): Inline keyboard attached
268            to the message. ``login_url`` buttons are represented as ordinary url buttons.
269        bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
270
271    """
272    # fmt: on
273
274    _effective_attachment = _UNDEFINED
275
276    ATTACHMENT_TYPES: ClassVar[List[str]] = [
277        'audio',
278        'game',
279        'animation',
280        'document',
281        'photo',
282        'sticker',
283        'video',
284        'voice',
285        'video_note',
286        'contact',
287        'location',
288        'venue',
289        'invoice',
290        'successful_payment',
291    ]
292    MESSAGE_TYPES: ClassVar[List[str]] = [
293        'text',
294        'new_chat_members',
295        'left_chat_member',
296        'new_chat_title',
297        'new_chat_photo',
298        'delete_chat_photo',
299        'group_chat_created',
300        'supergroup_chat_created',
301        'channel_chat_created',
302        'migrate_to_chat_id',
303        'migrate_from_chat_id',
304        'pinned_message',
305        'poll',
306        'dice',
307        'passport_data',
308        'proximity_alert_triggered',
309    ] + ATTACHMENT_TYPES
310
311    def __init__(
312        self,
313        message_id: int,
314        date: datetime.datetime,
315        chat: Chat,
316        from_user: User = None,
317        forward_from: User = None,
318        forward_from_chat: Chat = None,
319        forward_from_message_id: int = None,
320        forward_date: datetime.datetime = None,
321        reply_to_message: 'Message' = None,
322        edit_date: datetime.datetime = None,
323        text: str = None,
324        entities: List[MessageEntity] = None,
325        caption_entities: List[MessageEntity] = None,
326        audio: Audio = None,
327        document: Document = None,
328        game: Game = None,
329        photo: List[PhotoSize] = None,
330        sticker: Sticker = None,
331        video: Video = None,
332        voice: Voice = None,
333        video_note: VideoNote = None,
334        new_chat_members: List[User] = None,
335        caption: str = None,
336        contact: Contact = None,
337        location: Location = None,
338        venue: Venue = None,
339        left_chat_member: User = None,
340        new_chat_title: str = None,
341        new_chat_photo: List[PhotoSize] = None,
342        delete_chat_photo: bool = False,
343        group_chat_created: bool = False,
344        supergroup_chat_created: bool = False,
345        channel_chat_created: bool = False,
346        migrate_to_chat_id: int = None,
347        migrate_from_chat_id: int = None,
348        pinned_message: 'Message' = None,
349        invoice: Invoice = None,
350        successful_payment: SuccessfulPayment = None,
351        forward_signature: str = None,
352        author_signature: str = None,
353        media_group_id: str = None,
354        connected_website: str = None,
355        animation: Animation = None,
356        passport_data: PassportData = None,
357        poll: Poll = None,
358        forward_sender_name: str = None,
359        reply_markup: InlineKeyboardMarkup = None,
360        bot: 'Bot' = None,
361        dice: Dice = None,
362        via_bot: User = None,
363        proximity_alert_triggered: ProximityAlertTriggered = None,
364        sender_chat: Chat = None,
365        **_kwargs: Any,
366    ):
367        # Required
368        self.message_id = int(message_id)
369        # Optionals
370        self.from_user = from_user
371        self.sender_chat = sender_chat
372        self.date = date
373        self.chat = chat
374        self.forward_from = forward_from
375        self.forward_from_chat = forward_from_chat
376        self.forward_date = forward_date
377        self.reply_to_message = reply_to_message
378        self.edit_date = edit_date
379        self.text = text
380        self.entities = entities or list()
381        self.caption_entities = caption_entities or list()
382        self.audio = audio
383        self.game = game
384        self.document = document
385        self.photo = photo or list()
386        self.sticker = sticker
387        self.video = video
388        self.voice = voice
389        self.video_note = video_note
390        self.caption = caption
391        self.contact = contact
392        self.location = location
393        self.venue = venue
394        self.new_chat_members = new_chat_members or list()
395        self.left_chat_member = left_chat_member
396        self.new_chat_title = new_chat_title
397        self.new_chat_photo = new_chat_photo or list()
398        self.delete_chat_photo = bool(delete_chat_photo)
399        self.group_chat_created = bool(group_chat_created)
400        self.supergroup_chat_created = bool(supergroup_chat_created)
401        self.migrate_to_chat_id = migrate_to_chat_id
402        self.migrate_from_chat_id = migrate_from_chat_id
403        self.channel_chat_created = bool(channel_chat_created)
404        self.pinned_message = pinned_message
405        self.forward_from_message_id = forward_from_message_id
406        self.invoice = invoice
407        self.successful_payment = successful_payment
408        self.connected_website = connected_website
409        self.forward_signature = forward_signature
410        self.forward_sender_name = forward_sender_name
411        self.author_signature = author_signature
412        self.media_group_id = media_group_id
413        self.animation = animation
414        self.passport_data = passport_data
415        self.poll = poll
416        self.dice = dice
417        self.via_bot = via_bot
418        self.proximity_alert_triggered = proximity_alert_triggered
419        self.reply_markup = reply_markup
420        self.bot = bot
421
422        self._id_attrs = (self.message_id, self.chat)
423
424    @property
425    def chat_id(self) -> int:
426        """:obj:`int`: Shortcut for :attr:`telegram.Chat.id` for :attr:`chat`."""
427        return self.chat.id
428
429    @property
430    def link(self) -> Optional[str]:
431        """:obj:`str`: Convenience property. If the chat of the message is not
432        a private chat or normal group, returns a t.me link of the message."""
433        if self.chat.type not in [Chat.PRIVATE, Chat.GROUP]:
434            if self.chat.username:
435                to_link = self.chat.username
436            else:
437                # Get rid of leading -100 for supergroups
438                to_link = f"c/{str(self.chat.id)[4:]}"
439            return f"https://t.me/{to_link}/{self.message_id}"
440        return None
441
442    @classmethod
443    def de_json(cls, data: Optional[JSONDict], bot: 'Bot') -> 'Message':
444        data = cls.parse_data(data)
445
446        if not data:
447            return None
448
449        data['from_user'] = User.de_json(data.get('from'), bot)
450        data['sender_chat'] = Chat.de_json(data.get('sender_chat'), bot)
451        data['date'] = from_timestamp(data['date'])
452        data['chat'] = Chat.de_json(data.get('chat'), bot)
453        data['entities'] = MessageEntity.de_list(data.get('entities'), bot)
454        data['caption_entities'] = MessageEntity.de_list(data.get('caption_entities'), bot)
455        data['forward_from'] = User.de_json(data.get('forward_from'), bot)
456        data['forward_from_chat'] = Chat.de_json(data.get('forward_from_chat'), bot)
457        data['forward_date'] = from_timestamp(data.get('forward_date'))
458        data['reply_to_message'] = Message.de_json(data.get('reply_to_message'), bot)
459        data['edit_date'] = from_timestamp(data.get('edit_date'))
460        data['audio'] = Audio.de_json(data.get('audio'), bot)
461        data['document'] = Document.de_json(data.get('document'), bot)
462        data['animation'] = Animation.de_json(data.get('animation'), bot)
463        data['game'] = Game.de_json(data.get('game'), bot)
464        data['photo'] = PhotoSize.de_list(data.get('photo'), bot)
465        data['sticker'] = Sticker.de_json(data.get('sticker'), bot)
466        data['video'] = Video.de_json(data.get('video'), bot)
467        data['voice'] = Voice.de_json(data.get('voice'), bot)
468        data['video_note'] = VideoNote.de_json(data.get('video_note'), bot)
469        data['contact'] = Contact.de_json(data.get('contact'), bot)
470        data['location'] = Location.de_json(data.get('location'), bot)
471        data['venue'] = Venue.de_json(data.get('venue'), bot)
472        data['new_chat_members'] = User.de_list(data.get('new_chat_members'), bot)
473        data['left_chat_member'] = User.de_json(data.get('left_chat_member'), bot)
474        data['new_chat_photo'] = PhotoSize.de_list(data.get('new_chat_photo'), bot)
475        data['pinned_message'] = Message.de_json(data.get('pinned_message'), bot)
476        data['invoice'] = Invoice.de_json(data.get('invoice'), bot)
477        data['successful_payment'] = SuccessfulPayment.de_json(data.get('successful_payment'), bot)
478        data['passport_data'] = PassportData.de_json(data.get('passport_data'), bot)
479        data['poll'] = Poll.de_json(data.get('poll'), bot)
480        data['dice'] = Dice.de_json(data.get('dice'), bot)
481        data['via_bot'] = User.de_json(data.get('via_bot'), bot)
482        data['proximity_alert_triggered'] = ProximityAlertTriggered.de_json(
483            data.get('proximity_alert_triggered'), bot
484        )
485        data['reply_markup'] = InlineKeyboardMarkup.de_json(data.get('reply_markup'), bot)
486
487        return cls(bot=bot, **data)
488
489    @property
490    def effective_attachment(
491        self,
492    ) -> Union[
493        Contact,
494        Document,
495        Animation,
496        Game,
497        Invoice,
498        Location,
499        List[PhotoSize],
500        Sticker,
501        SuccessfulPayment,
502        Venue,
503        Video,
504        VideoNote,
505        Voice,
506        None,
507    ]:
508        """
509        :class:`telegram.Audio`
510            or :class:`telegram.Contact`
511            or :class:`telegram.Document`
512            or :class:`telegram.Animation`
513            or :class:`telegram.Game`
514            or :class:`telegram.Invoice`
515            or :class:`telegram.Location`
516            or List[:class:`telegram.PhotoSize`]
517            or :class:`telegram.Sticker`
518            or :class:`telegram.SuccessfulPayment`
519            or :class:`telegram.Venue`
520            or :class:`telegram.Video`
521            or :class:`telegram.VideoNote`
522            or :class:`telegram.Voice`: The attachment that this message was sent with. May be
523            :obj:`None` if no attachment was sent.
524
525        """
526        if self._effective_attachment is not _UNDEFINED:
527            return self._effective_attachment  # type: ignore
528
529        for i in Message.ATTACHMENT_TYPES:
530            if getattr(self, i, None):
531                self._effective_attachment = getattr(self, i)
532                break
533        else:
534            self._effective_attachment = None
535
536        return self._effective_attachment  # type: ignore
537
538    def __getitem__(self, item: str) -> Any:  # pylint: disable=R1710
539        if item in self.__dict__.keys():
540            return self.__dict__[item]
541        if item == 'chat_id':
542            return self.chat.id
543
544    def to_dict(self) -> JSONDict:
545        data = super().to_dict()
546
547        # Required
548        data['date'] = to_timestamp(self.date)
549        # Optionals
550        if self.forward_date:
551            data['forward_date'] = to_timestamp(self.forward_date)
552        if self.edit_date:
553            data['edit_date'] = to_timestamp(self.edit_date)
554        if self.photo:
555            data['photo'] = [p.to_dict() for p in self.photo]
556        if self.entities:
557            data['entities'] = [e.to_dict() for e in self.entities]
558        if self.caption_entities:
559            data['caption_entities'] = [e.to_dict() for e in self.caption_entities]
560        if self.new_chat_photo:
561            data['new_chat_photo'] = [p.to_dict() for p in self.new_chat_photo]
562        if self.new_chat_members:
563            data['new_chat_members'] = [u.to_dict() for u in self.new_chat_members]
564
565        return data
566
567    def _quote(self, kwargs: JSONDict) -> None:
568        """Modify kwargs for replying with or without quoting."""
569        if 'reply_to_message_id' in kwargs:
570            if 'quote' in kwargs:
571                del kwargs['quote']
572
573        elif 'quote' in kwargs:
574            if kwargs['quote']:
575                kwargs['reply_to_message_id'] = self.message_id
576
577            del kwargs['quote']
578
579        else:
580            if self.bot.defaults:
581                default_quote = self.bot.defaults.quote
582            else:
583                default_quote = None
584            if (default_quote is None and self.chat.type != Chat.PRIVATE) or default_quote:
585                kwargs['reply_to_message_id'] = self.message_id
586
587    def reply_text(self, *args: Any, **kwargs: Any) -> 'Message':
588        """Shortcut for::
589
590            bot.send_message(update.message.chat_id, *args, **kwargs)
591
592        Keyword Args:
593            quote (:obj:`bool`, optional): If set to :obj:`True`, the message is sent as an actual
594                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
595                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
596                private chats.
597
598        Returns:
599            :class:`telegram.Message`: On success, instance representing the message posted.
600
601        """
602        self._quote(kwargs)
603        return self.bot.send_message(self.chat_id, *args, **kwargs)
604
605    def reply_markdown(self, *args: Any, **kwargs: Any) -> 'Message':
606        """Shortcut for::
607
608            bot.send_message(update.message.chat_id, parse_mode=ParseMode.MARKDOWN, *args,
609            **kwargs)
610
611        Sends a message with Markdown version 1 formatting.
612
613        Note:
614            :attr:`telegram.ParseMode.MARKDOWN` is a legacy mode, retained by Telegram for
615            backward compatibility. You should use :meth:`reply_markdown_v2` instead.
616
617        Keyword Args:
618            quote (:obj:`bool`, optional): If set to :obj:`True`, the message is sent as an actual
619                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
620                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
621                private chats.
622
623        Returns:
624            :class:`telegram.Message`: On success, instance representing the message posted.
625        """
626
627        kwargs['parse_mode'] = ParseMode.MARKDOWN
628
629        self._quote(kwargs)
630
631        return self.bot.send_message(self.chat_id, *args, **kwargs)
632
633    def reply_markdown_v2(self, *args: Any, **kwargs: Any) -> 'Message':
634        """Shortcut for::
635
636            bot.send_message(update.message.chat_id, parse_mode=ParseMode.MARKDOWN_V2, *args,
637            **kwargs)
638
639        Sends a message with markdown version 2 formatting.
640
641        Keyword Args:
642            quote (:obj:`bool`, optional): If set to :obj:`True`, the message is sent as an actual
643                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
644                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
645                private chats.
646
647        Returns:
648            :class:`telegram.Message`: On success, instance representing the message posted.
649        """
650
651        kwargs['parse_mode'] = ParseMode.MARKDOWN_V2
652
653        self._quote(kwargs)
654
655        return self.bot.send_message(self.chat_id, *args, **kwargs)
656
657    def reply_html(self, *args: Any, **kwargs: Any) -> 'Message':
658        """Shortcut for::
659
660            bot.send_message(update.message.chat_id, parse_mode=ParseMode.HTML, *args, **kwargs)
661
662        Sends a message with HTML formatting.
663
664        Keyword Args:
665            quote (:obj:`bool`, optional): If set to :obj:`True`, the message is sent as an actual
666                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
667                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
668                private chats.
669
670        Returns:
671            :class:`telegram.Message`: On success, instance representing the message posted.
672        """
673
674        kwargs['parse_mode'] = ParseMode.HTML
675
676        self._quote(kwargs)
677
678        return self.bot.send_message(self.chat_id, *args, **kwargs)
679
680    def reply_media_group(self, *args: Any, **kwargs: Any) -> List[Optional['Message']]:
681        """Shortcut for::
682
683            bot.send_media_group(update.message.chat_id, *args, **kwargs)
684
685        Keyword Args:
686            quote (:obj:`bool`, optional): If set to :obj:`True`, the media group is sent as an
687                actual reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
688                this parameter will be ignored. Default: :obj:`True` in group chats and
689                :obj:`False` in private chats.
690
691        Returns:
692            List[:class:`telegram.Message`]: An array of the sent Messages.
693
694        Raises:
695            :class:`telegram.TelegramError`
696        """
697        self._quote(kwargs)
698        return self.bot.send_media_group(self.chat_id, *args, **kwargs)
699
700    def reply_photo(self, *args: Any, **kwargs: Any) -> 'Message':
701        """Shortcut for::
702
703            bot.send_photo(update.message.chat_id, *args, **kwargs)
704
705        Keyword Args:
706            quote (:obj:`bool`, optional): If set to :obj:`True`, the photo is sent as an actual
707                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
708                this parameter will be ignored. Default: :obj:`True` in group chats and
709                :obj:`False` in private chats.
710
711        Returns:
712            :class:`telegram.Message`: On success, instance representing the message posted.
713
714        """
715        self._quote(kwargs)
716        return self.bot.send_photo(self.chat_id, *args, **kwargs)
717
718    def reply_audio(self, *args: Any, **kwargs: Any) -> 'Message':
719        """Shortcut for::
720
721            bot.send_audio(update.message.chat_id, *args, **kwargs)
722
723        Keyword Args:
724            quote (:obj:`bool`, optional): If set to :obj:`True`, the audio is sent as an actual
725                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
726                this parameter will be ignored. Default: :obj:`True` in group chats and
727                :obj:`False` in private chats.
728
729        Returns:
730            :class:`telegram.Message`: On success, instance representing the message posted.
731
732        """
733        self._quote(kwargs)
734        return self.bot.send_audio(self.chat_id, *args, **kwargs)
735
736    def reply_document(self, *args: Any, **kwargs: Any) -> 'Message':
737        """Shortcut for::
738
739            bot.send_document(update.message.chat_id, *args, **kwargs)
740
741        Keyword Args:
742            quote (:obj:`bool`, optional): If set to :obj:`True`, the document is sent as an actual
743                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
744                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
745                private chats.
746
747        Returns:
748            :class:`telegram.Message`: On success, instance representing the message posted.
749
750        """
751        self._quote(kwargs)
752        return self.bot.send_document(self.chat_id, *args, **kwargs)
753
754    def reply_animation(self, *args: Any, **kwargs: Any) -> 'Message':
755        """Shortcut for::
756
757            bot.send_animation(update.message.chat_id, *args, **kwargs)
758
759        Keyword Args:
760            quote (:obj:`bool`, optional): If set to :obj:`True`, the animation is sent as an
761                actual reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
762                this parameter will be ignored. Default: :obj:`True` in group chats and
763                :obj:`False` in private chats.
764
765        Returns:
766            :class:`telegram.Message`: On success, instance representing the message posted.
767
768        """
769        self._quote(kwargs)
770        return self.bot.send_animation(self.chat_id, *args, **kwargs)
771
772    def reply_sticker(self, *args: Any, **kwargs: Any) -> 'Message':
773        """Shortcut for::
774
775            bot.send_sticker(update.message.chat_id, *args, **kwargs)
776
777        Keyword Args:
778            quote (:obj:`bool`, optional): If set to :obj:`True`, the sticker is sent as an actual
779                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
780                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
781                private chats.
782
783        Returns:
784            :class:`telegram.Message`: On success, instance representing the message posted.
785
786        """
787        self._quote(kwargs)
788        return self.bot.send_sticker(self.chat_id, *args, **kwargs)
789
790    def reply_video(self, *args: Any, **kwargs: Any) -> 'Message':
791        """Shortcut for::
792
793            bot.send_video(update.message.chat_id, *args, **kwargs)
794
795        Keyword Args:
796            quote (:obj:`bool`, optional): If set to :obj:`True`, the video is sent as an actual
797                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
798                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
799                private chats.
800
801        Returns:
802            :class:`telegram.Message`: On success, instance representing the message posted.
803
804        """
805        self._quote(kwargs)
806        return self.bot.send_video(self.chat_id, *args, **kwargs)
807
808    def reply_video_note(self, *args: Any, **kwargs: Any) -> 'Message':
809        """Shortcut for::
810
811            bot.send_video_note(update.message.chat_id, *args, **kwargs)
812
813        Keyword Args:
814            quote (:obj:`bool`, optional): If set to :obj:`True`, the video note is sent as an
815                actual reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
816                this parameter will be ignored. Default: :obj:`True` in group chats and
817                :obj:`False` in private chats.
818
819        Returns:
820            :class:`telegram.Message`: On success, instance representing the message posted.
821
822        """
823        self._quote(kwargs)
824        return self.bot.send_video_note(self.chat_id, *args, **kwargs)
825
826    def reply_voice(self, *args: Any, **kwargs: Any) -> 'Message':
827        """Shortcut for::
828
829            bot.send_voice(update.message.chat_id, *args, **kwargs)
830
831        Keyword Args:
832            quote (:obj:`bool`, optional): If set to :obj:`True`, the voice note is sent as an
833                actual reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
834                this parameter will be ignored. Default: :obj:`True` in group chats and
835                :obj:`False` in private chats.
836
837        Returns:
838            :class:`telegram.Message`: On success, instance representing the message posted.
839
840        """
841        self._quote(kwargs)
842        return self.bot.send_voice(self.chat_id, *args, **kwargs)
843
844    def reply_location(self, *args: Any, **kwargs: Any) -> 'Message':
845        """Shortcut for::
846
847            bot.send_location(update.message.chat_id, *args, **kwargs)
848
849        Keyword Args:
850            quote (:obj:`bool`, optional): If set to :obj:`True`, the location is sent as an actual
851                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
852                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
853                private chats.
854
855        Returns:
856            :class:`telegram.Message`: On success, instance representing the message posted.
857
858        """
859        self._quote(kwargs)
860        return self.bot.send_location(self.chat_id, *args, **kwargs)
861
862    def reply_venue(self, *args: Any, **kwargs: Any) -> 'Message':
863        """Shortcut for::
864
865            bot.send_venue(update.message.chat_id, *args, **kwargs)
866
867        Keyword Args:
868            quote (:obj:`bool`, optional): If set to :obj:`True`, the venue is sent as an actual
869                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
870                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
871                private chats.
872
873        Returns:
874            :class:`telegram.Message`: On success, instance representing the message posted.
875
876        """
877        self._quote(kwargs)
878        return self.bot.send_venue(self.chat_id, *args, **kwargs)
879
880    def reply_contact(self, *args: Any, **kwargs: Any) -> 'Message':
881        """Shortcut for::
882
883            bot.send_contact(update.message.chat_id, *args, **kwargs)
884
885        Keyword Args:
886            quote (:obj:`bool`, optional): If set to :obj:`True`, the contact is sent as an actual
887                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
888                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False` in
889                private chats.
890
891        Returns:
892            :class:`telegram.Message`: On success, instance representing the message posted.
893
894        """
895        self._quote(kwargs)
896        return self.bot.send_contact(self.chat_id, *args, **kwargs)
897
898    def reply_poll(self, *args: Any, **kwargs: Any) -> 'Message':
899        """Shortcut for::
900
901            bot.send_poll(update.message.chat_id, *args, **kwargs)
902
903        Keyword Args:
904            quote (:obj:`bool`, optional): If set to :obj:`True`, the poll is sent as an actual
905                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``,
906                this parameter will be ignored. Default: :obj:`True` in group chats and
907                :obj:`False` in private chats.
908
909        Returns:
910            :class:`telegram.Message`: On success, instance representing the message posted.
911
912        """
913        self._quote(kwargs)
914        return self.bot.send_poll(self.chat_id, *args, **kwargs)
915
916    def reply_dice(self, *args: Any, **kwargs: Any) -> 'Message':
917        """Shortcut for::
918
919            bot.send_dice(update.message.chat_id, *args, **kwargs)
920
921        Keyword Args:
922            quote (:obj:`bool`, optional): If set to :obj:`True`, the dice is sent as an actual
923                reply to this message. If ``reply_to_message_id`` is passed in ``kwargs``, this
924                parameter will be ignored. Default: :obj:`True` in group chats and :obj:`False`
925                in private chats.
926
927        Returns:
928            :class:`telegram.Message`: On success, instance representing the message posted.
929
930        """
931        self._quote(kwargs)
932        return self.bot.send_dice(self.chat_id, *args, **kwargs)
933
934    def forward(self, chat_id: int, *args: Any, **kwargs: Any) -> 'Message':
935        """Shortcut for::
936
937            bot.forward_message(chat_id=chat_id,
938                                from_chat_id=update.message.chat_id,
939                                message_id=update.message.message_id,
940                                *args,
941                                **kwargs)
942
943        Returns:
944            :class:`telegram.Message`: On success, instance representing the message forwarded.
945
946        """
947        return self.bot.forward_message(
948            chat_id=chat_id, from_chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
949        )
950
951    def copy(self, chat_id: int, *args: Any, **kwargs: Any) -> 'MessageId':
952        """Shortcut for::
953
954            bot.copy_message(chat_id=chat_id,
955                             from_chat_id=update.message.chat_id,
956                             message_id=update.message.message_id,
957                             *args,
958                             **kwargs)
959
960        Returns:
961            :class:`telegram.MessageId`: On success, returns the MessageId of the sent message.
962
963        """
964        return self.bot.copy_message(
965            chat_id=chat_id, from_chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
966        )
967
968    def reply_copy(
969        self, from_chat_id: int, message_id: int, *args: Any, **kwargs: Any
970    ) -> 'MessageId':
971        """Shortcut for::
972
973            bot.copy_message(chat_id=message.chat.id,
974                             from_chat_id=from_chat_id,
975                             message_id=message_id,
976                             *args,
977                             **kwargs)
978
979        Returns:
980            :class:`telegram.MessageId`: On success, returns the MessageId of the sent message.
981
982        """
983        return self.bot.copy_message(
984            chat_id=self.chat_id, from_chat_id=from_chat_id, message_id=message_id, *args, **kwargs
985        )
986
987    def edit_text(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
988        """Shortcut for::
989
990            bot.edit_message_text(chat_id=message.chat_id,
991                                  message_id=message.message_id,
992                                  *args,
993                                  **kwargs)
994
995        Note:
996            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
997            of methods) or channel posts, if the bot is an admin in that channel. However, this
998            behaviour is undocumented and might be changed by Telegram.
999
1000        Returns:
1001            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1002            edited Message is returned, otherwise ``True`` is returned.
1003
1004        """
1005        return self.bot.edit_message_text(
1006            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1007        )
1008
1009    def edit_caption(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
1010        """Shortcut for::
1011
1012            bot.edit_message_caption(chat_id=message.chat_id,
1013                                     message_id=message.message_id,
1014                                     *args,
1015                                     **kwargs)
1016
1017        Note:
1018            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1019            of methods) or channel posts, if the bot is an admin in that channel. However, this
1020            behaviour is undocumented and might be changed by Telegram.
1021
1022        Returns:
1023            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1024            edited Message is returned, otherwise ``True`` is returned.
1025
1026        """
1027        return self.bot.edit_message_caption(
1028            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1029        )
1030
1031    def edit_media(self, media: 'InputMedia', *args: Any, **kwargs: Any) -> Union['Message', bool]:
1032        """Shortcut for::
1033
1034            bot.edit_message_media(chat_id=message.chat_id,
1035                                   message_id=message.message_id,
1036                                   *args,
1037                                   **kwargs)
1038
1039        Note:
1040            You can only edit messages that the bot sent itself(i.e. of the ``bot.send_*`` family
1041            of methods) or channel posts, if the bot is an admin in that channel. However, this
1042            behaviour is undocumented and might be changed by Telegram.
1043
1044        Returns:
1045            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1046            edited Message is returned, otherwise ``True`` is returned.
1047
1048        """
1049        return self.bot.edit_message_media(
1050            chat_id=self.chat_id, message_id=self.message_id, media=media, *args, **kwargs
1051        )
1052
1053    def edit_reply_markup(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
1054        """Shortcut for::
1055
1056            bot.edit_message_reply_markup(chat_id=message.chat_id,
1057                                          message_id=message.message_id,
1058                                          *args,
1059                                          **kwargs)
1060
1061        Note:
1062            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1063            of methods) or channel posts, if the bot is an admin in that channel. However, this
1064            behaviour is undocumented and might be changed by Telegram.
1065
1066        Returns:
1067            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1068            edited Message is returned, otherwise ``True`` is returned.
1069        """
1070        return self.bot.edit_message_reply_markup(
1071            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1072        )
1073
1074    def edit_live_location(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
1075        """Shortcut for::
1076
1077            bot.edit_message_live_location(chat_id=message.chat_id,
1078                                           message_id=message.message_id,
1079                                           *args,
1080                                           **kwargs)
1081
1082        Note:
1083            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1084            of methods) or channel posts, if the bot is an admin in that channel. However, this
1085            behaviour is undocumented and might be changed by Telegram.
1086
1087        Returns:
1088            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1089            edited Message is returned, otherwise :obj:`True` is returned.
1090        """
1091        return self.bot.edit_message_live_location(
1092            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1093        )
1094
1095    def stop_live_location(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
1096        """Shortcut for::
1097
1098            bot.stop_message_live_location(chat_id=message.chat_id,
1099                                           message_id=message.message_id,
1100                                           *args,
1101                                           **kwargs)
1102
1103        Note:
1104            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1105            of methods) or channel posts, if the bot is an admin in that channel. However, this
1106            behaviour is undocumented and might be changed by Telegram.
1107
1108        Returns:
1109            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1110            edited Message is returned, otherwise :obj:`True` is returned.
1111        """
1112        return self.bot.stop_message_live_location(
1113            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1114        )
1115
1116    def set_game_score(self, *args: Any, **kwargs: Any) -> Union['Message', bool]:
1117        """Shortcut for::
1118
1119            bot.set_game_score(chat_id=message.chat_id,
1120                               message_id=message.message_id,
1121                               *args,
1122                               **kwargs)
1123
1124        Note:
1125            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1126            of methods) or channel posts, if the bot is an admin in that channel. However, this
1127            behaviour is undocumented and might be changed by Telegram.
1128
1129        Returns:
1130            :class:`telegram.Message`: On success, if edited message is sent by the bot, the
1131            edited Message is returned, otherwise :obj:`True` is returned.
1132        """
1133        return self.bot.set_game_score(
1134            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1135        )
1136
1137    def get_game_high_scores(self, *args: Any, **kwargs: Any) -> List['GameHighScore']:
1138        """Shortcut for::
1139
1140            bot.get_game_high_scores(chat_id=message.chat_id,
1141                                     message_id=message.message_id,
1142                                     *args,
1143                                     **kwargs)
1144
1145        Note:
1146            You can only edit messages that the bot sent itself (i.e. of the ``bot.send_*`` family
1147            of methods) or channel posts, if the bot is an admin in that channel. However, this
1148            behaviour is undocumented and might be changed by Telegram.
1149
1150        Returns:
1151            List[:class:`telegram.GameHighScore`]
1152        """
1153        return self.bot.get_game_high_scores(
1154            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1155        )
1156
1157    def delete(self, *args: Any, **kwargs: Any) -> bool:
1158        """Shortcut for::
1159
1160             bot.delete_message(chat_id=message.chat_id,
1161                                message_id=message.message_id,
1162                                *args,
1163                                **kwargs)
1164
1165        Returns:
1166            :obj:`bool`: On success, :obj:`True` is returned.
1167
1168        """
1169        return self.bot.delete_message(
1170            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1171        )
1172
1173    def stop_poll(self, *args: Any, **kwargs: Any) -> Poll:
1174        """Shortcut for::
1175
1176             bot.stop_poll(chat_id=message.chat_id,
1177                           message_id=message.message_id,
1178                           *args,
1179                           **kwargs)
1180
1181        Returns:
1182            :class:`telegram.Poll`: On success, the stopped Poll with the final results is
1183            returned.
1184
1185        """
1186        return self.bot.stop_poll(
1187            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1188        )
1189
1190    def pin(self, *args: Any, **kwargs: Any) -> bool:
1191        """Shortcut for::
1192
1193             bot.pin_chat_message(chat_id=message.chat_id,
1194                                  message_id=message.message_id,
1195                                  *args,
1196                                  **kwargs)
1197
1198        Returns:
1199            :obj:`bool`: On success, :obj:`True` is returned.
1200
1201        """
1202        return self.bot.pin_chat_message(
1203            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1204        )
1205
1206    def unpin(self, *args: Any, **kwargs: Any) -> bool:
1207        """Shortcut for::
1208
1209             bot.unpin_chat_message(chat_id=message.chat_id,
1210                                    message_id=message.message_id,
1211                                    *args,
1212                                    **kwargs)
1213
1214        Returns:
1215            :obj:`bool`: On success, :obj:`True` is returned.
1216
1217        """
1218        return self.bot.unpin_chat_message(
1219            chat_id=self.chat_id, message_id=self.message_id, *args, **kwargs
1220        )
1221
1222    def parse_entity(self, entity: MessageEntity) -> str:
1223        """Returns the text from a given :class:`telegram.MessageEntity`.
1224
1225        Note:
1226            This method is present because Telegram calculates the offset and length in
1227            UTF-16 codepoint pairs, which some versions of Python don't handle automatically.
1228            (That is, you can't just slice ``Message.text`` with the offset and length.)
1229
1230        Args:
1231            entity (:class:`telegram.MessageEntity`): The entity to extract the text from. It must
1232                be an entity that belongs to this message.
1233
1234        Returns:
1235            :obj:`str`: The text of the given entity.
1236
1237        Raises:
1238            RuntimeError: If the message has no text.
1239
1240        """
1241        if not self.text:
1242            raise RuntimeError("This Message has no 'text'.")
1243
1244        # Is it a narrow build, if so we don't need to convert
1245        if sys.maxunicode == 0xFFFF:
1246            return self.text[entity.offset : entity.offset + entity.length]
1247
1248        entity_text = self.text.encode('utf-16-le')
1249        entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
1250        return entity_text.decode('utf-16-le')
1251
1252    def parse_caption_entity(self, entity: MessageEntity) -> str:
1253        """Returns the text from a given :class:`telegram.MessageEntity`.
1254
1255        Note:
1256            This method is present because Telegram calculates the offset and length in
1257            UTF-16 codepoint pairs, which some versions of Python don't handle automatically.
1258            (That is, you can't just slice ``Message.caption`` with the offset and length.)
1259
1260        Args:
1261            entity (:class:`telegram.MessageEntity`): The entity to extract the text from. It must
1262                be an entity that belongs to this message.
1263
1264        Returns:
1265            :obj:`str`: The text of the given entity.
1266
1267        Raises:
1268            RuntimeError: If the message has no caption.
1269
1270        """
1271        if not self.caption:
1272            raise RuntimeError("This Message has no 'caption'.")
1273
1274        # Is it a narrow build, if so we don't need to convert
1275        if sys.maxunicode == 0xFFFF:
1276            return self.caption[entity.offset : entity.offset + entity.length]
1277
1278        entity_text = self.caption.encode('utf-16-le')
1279        entity_text = entity_text[entity.offset * 2 : (entity.offset + entity.length) * 2]
1280        return entity_text.decode('utf-16-le')
1281
1282    def parse_entities(self, types: List[str] = None) -> Dict[MessageEntity, str]:
1283        """
1284        Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
1285        It contains entities from this message filtered by their
1286        :attr:`telegram.MessageEntity.type` attribute as the key, and the text that each entity
1287        belongs to as the value of the :obj:`dict`.
1288
1289        Note:
1290            This method should always be used instead of the :attr:`entities` attribute, since it
1291            calculates the correct substring from the message text based on UTF-16 codepoints.
1292            See :attr:`parse_entity` for more info.
1293
1294        Args:
1295            types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
1296                strings. If the ``type`` attribute of an entity is contained in this list, it will
1297                be returned. Defaults to a list of all types. All types can be found as constants
1298                in :class:`telegram.MessageEntity`.
1299
1300        Returns:
1301            Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
1302            the text that belongs to them, calculated based on UTF-16 codepoints.
1303
1304        """
1305        if types is None:
1306            types = MessageEntity.ALL_TYPES
1307
1308        return {
1309            entity: self.parse_entity(entity)
1310            for entity in (self.entities or [])
1311            if entity.type in types
1312        }
1313
1314    def parse_caption_entities(self, types: List[str] = None) -> Dict[MessageEntity, str]:
1315        """
1316        Returns a :obj:`dict` that maps :class:`telegram.MessageEntity` to :obj:`str`.
1317        It contains entities from this message's caption filtered by their
1318        :attr:`telegram.MessageEntity.type` attribute as the key, and the text that each entity
1319        belongs to as the value of the :obj:`dict`.
1320
1321        Note:
1322            This method should always be used instead of the :attr:`caption_entities` attribute,
1323            since it calculates the correct substring from the message text based on UTF-16
1324            codepoints. See :attr:`parse_entity` for more info.
1325
1326        Args:
1327            types (List[:obj:`str`], optional): List of :class:`telegram.MessageEntity` types as
1328                strings. If the ``type`` attribute of an entity is contained in this list, it will
1329                be returned. Defaults to a list of all types. All types can be found as constants
1330                in :class:`telegram.MessageEntity`.
1331
1332        Returns:
1333            Dict[:class:`telegram.MessageEntity`, :obj:`str`]: A dictionary of entities mapped to
1334            the text that belongs to them, calculated based on UTF-16 codepoints.
1335
1336        """
1337        if types is None:
1338            types = MessageEntity.ALL_TYPES
1339
1340        return {
1341            entity: self.parse_caption_entity(entity)
1342            for entity in (self.caption_entities or [])
1343            if entity.type in types
1344        }
1345
1346    @staticmethod
1347    def _parse_html(
1348        message_text: Optional[str],
1349        entities: Dict[MessageEntity, str],
1350        urled: bool = False,
1351        offset: int = 0,
1352    ) -> Optional[str]:
1353        if message_text is None:
1354            return None
1355
1356        if sys.maxunicode != 0xFFFF:
1357            message_text = message_text.encode('utf-16-le')  # type: ignore
1358
1359        html_text = ''
1360        last_offset = 0
1361
1362        sorted_entities = sorted(entities.items(), key=(lambda item: item[0].offset))
1363        parsed_entities = []
1364
1365        for (entity, text) in sorted_entities:
1366            if entity not in parsed_entities:
1367                nested_entities = {
1368                    e: t
1369                    for (e, t) in sorted_entities
1370                    if e.offset >= entity.offset
1371                    and e.offset + e.length <= entity.offset + entity.length
1372                    and e != entity
1373                }
1374                parsed_entities.extend(list(nested_entities.keys()))
1375
1376                text = escape(text)
1377
1378                if nested_entities:
1379                    text = Message._parse_html(
1380                        text, nested_entities, urled=urled, offset=entity.offset
1381                    )
1382
1383                if entity.type == MessageEntity.TEXT_LINK:
1384                    insert = f'<a href="{entity.url}">{text}</a>'
1385                elif entity.type == MessageEntity.TEXT_MENTION and entity.user:
1386                    insert = f'<a href="tg://user?id={entity.user.id}">{text}</a>'
1387                elif entity.type == MessageEntity.URL and urled:
1388                    insert = f'<a href="{text}">{text}</a>'
1389                elif entity.type == MessageEntity.BOLD:
1390                    insert = '<b>' + text + '</b>'
1391                elif entity.type == MessageEntity.ITALIC:
1392                    insert = '<i>' + text + '</i>'
1393                elif entity.type == MessageEntity.CODE:
1394                    insert = '<code>' + text + '</code>'
1395                elif entity.type == MessageEntity.PRE:
1396                    if entity.language:
1397                        insert = f'<pre><code class="{entity.language}">{text}</code></pre>'
1398                    else:
1399                        insert = '<pre>' + text + '</pre>'
1400                elif entity.type == MessageEntity.UNDERLINE:
1401                    insert = '<u>' + text + '</u>'
1402                elif entity.type == MessageEntity.STRIKETHROUGH:
1403                    insert = '<s>' + text + '</s>'
1404                else:
1405                    insert = text
1406
1407                if offset == 0:
1408                    if sys.maxunicode == 0xFFFF:
1409                        html_text += (
1410                            escape(message_text[last_offset : entity.offset - offset]) + insert
1411                        )
1412                    else:
1413                        html_text += (
1414                            escape(
1415                                message_text[  # type: ignore
1416                                    last_offset * 2 : (entity.offset - offset) * 2
1417                                ].decode('utf-16-le')
1418                            )
1419                            + insert
1420                        )
1421                else:
1422                    if sys.maxunicode == 0xFFFF:
1423                        html_text += message_text[last_offset : entity.offset - offset] + insert
1424                    else:
1425                        html_text += (
1426                            message_text[  # type: ignore
1427                                last_offset * 2 : (entity.offset - offset) * 2
1428                            ].decode('utf-16-le')
1429                            + insert
1430                        )
1431
1432                last_offset = entity.offset - offset + entity.length
1433
1434        if offset == 0:
1435            if sys.maxunicode == 0xFFFF:
1436                html_text += escape(message_text[last_offset:])
1437            else:
1438                html_text += escape(
1439                    message_text[last_offset * 2 :].decode('utf-16-le')  # type: ignore
1440                )
1441        else:
1442            if sys.maxunicode == 0xFFFF:
1443                html_text += message_text[last_offset:]
1444            else:
1445                html_text += message_text[last_offset * 2 :].decode('utf-16-le')  # type: ignore
1446
1447        return html_text
1448
1449    @property
1450    def text_html(self) -> str:
1451        """Creates an HTML-formatted string from the markup entities found in the message.
1452
1453        Use this if you want to retrieve the message text with the entities formatted as HTML in
1454        the same way the original message was formatted.
1455
1456        Returns:
1457            :obj:`str`: Message text with entities formatted as HTML.
1458
1459        """
1460        return self._parse_html(self.text, self.parse_entities(), urled=False)
1461
1462    @property
1463    def text_html_urled(self) -> str:
1464        """Creates an HTML-formatted string from the markup entities found in the message.
1465
1466        Use this if you want to retrieve the message text with the entities formatted as HTML.
1467        This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1468
1469        Returns:
1470            :obj:`str`: Message text with entities formatted as HTML.
1471
1472        """
1473        return self._parse_html(self.text, self.parse_entities(), urled=True)
1474
1475    @property
1476    def caption_html(self) -> str:
1477        """Creates an HTML-formatted string from the markup entities found in the message's
1478        caption.
1479
1480        Use this if you want to retrieve the message caption with the caption entities formatted as
1481        HTML in the same way the original message was formatted.
1482
1483        Returns:
1484            :obj:`str`: Message caption with caption entities formatted as HTML.
1485
1486        """
1487        return self._parse_html(self.caption, self.parse_caption_entities(), urled=False)
1488
1489    @property
1490    def caption_html_urled(self) -> str:
1491        """Creates an HTML-formatted string from the markup entities found in the message's
1492        caption.
1493
1494        Use this if you want to retrieve the message caption with the caption entities formatted as
1495        HTML. This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1496
1497        Returns:
1498            :obj:`str`: Message caption with caption entities formatted as HTML.
1499
1500        """
1501        return self._parse_html(self.caption, self.parse_caption_entities(), urled=True)
1502
1503    @staticmethod
1504    def _parse_markdown(
1505        message_text: Optional[str],
1506        entities: Dict[MessageEntity, str],
1507        urled: bool = False,
1508        version: int = 1,
1509        offset: int = 0,
1510    ) -> Optional[str]:
1511        version = int(version)
1512
1513        if message_text is None:
1514            return None
1515
1516        if sys.maxunicode != 0xFFFF:
1517            message_text = message_text.encode('utf-16-le')  # type: ignore
1518
1519        markdown_text = ''
1520        last_offset = 0
1521
1522        sorted_entities = sorted(entities.items(), key=(lambda item: item[0].offset))
1523        parsed_entities = []
1524
1525        for (entity, text) in sorted_entities:
1526            if entity not in parsed_entities:
1527                nested_entities = {
1528                    e: t
1529                    for (e, t) in sorted_entities
1530                    if e.offset >= entity.offset
1531                    and e.offset + e.length <= entity.offset + entity.length
1532                    and e != entity
1533                }
1534                parsed_entities.extend(list(nested_entities.keys()))
1535
1536                orig_text = text
1537                text = escape_markdown(text, version=version)
1538
1539                if nested_entities:
1540                    if version < 2:
1541                        raise ValueError(
1542                            'Nested entities are not supported for Markdown ' 'version 1'
1543                        )
1544
1545                    text = Message._parse_markdown(
1546                        text, nested_entities, urled=urled, offset=entity.offset, version=version
1547                    )
1548
1549                if entity.type == MessageEntity.TEXT_LINK:
1550                    if version == 1:
1551                        url = entity.url
1552                    else:
1553                        # Links need special escaping. Also can't have entities nested within
1554                        url = escape_markdown(
1555                            entity.url, version=version, entity_type=MessageEntity.TEXT_LINK
1556                        )
1557                    insert = f'[{text}]({url})'
1558                elif entity.type == MessageEntity.TEXT_MENTION and entity.user:
1559                    insert = f'[{text}](tg://user?id={entity.user.id})'
1560                elif entity.type == MessageEntity.URL and urled:
1561                    if version == 1:
1562                        link = orig_text
1563                    else:
1564                        link = text
1565                    insert = f'[{link}]({orig_text})'
1566                elif entity.type == MessageEntity.BOLD:
1567                    insert = '*' + text + '*'
1568                elif entity.type == MessageEntity.ITALIC:
1569                    insert = '_' + text + '_'
1570                elif entity.type == MessageEntity.CODE:
1571                    # Monospace needs special escaping. Also can't have entities nested within
1572                    insert = (
1573                        '`'
1574                        + escape_markdown(
1575                            orig_text, version=version, entity_type=MessageEntity.CODE
1576                        )
1577                        + '`'
1578                    )
1579                elif entity.type == MessageEntity.PRE:
1580                    # Monospace needs special escaping. Also can't have entities nested within
1581                    code = escape_markdown(
1582                        orig_text, version=version, entity_type=MessageEntity.PRE
1583                    )
1584                    if entity.language:
1585                        prefix = '```' + entity.language + '\n'
1586                    else:
1587                        if code.startswith('\\'):
1588                            prefix = '```'
1589                        else:
1590                            prefix = '```\n'
1591                    insert = prefix + code + '```'
1592                elif entity.type == MessageEntity.UNDERLINE:
1593                    if version == 1:
1594                        raise ValueError(
1595                            'Underline entities are not supported for Markdown ' 'version 1'
1596                        )
1597                    insert = '__' + text + '__'
1598                elif entity.type == MessageEntity.STRIKETHROUGH:
1599                    if version == 1:
1600                        raise ValueError(
1601                            'Strikethrough entities are not supported for Markdown ' 'version 1'
1602                        )
1603                    insert = '~' + text + '~'
1604                else:
1605                    insert = text
1606
1607                if offset == 0:
1608                    if sys.maxunicode == 0xFFFF:
1609                        markdown_text += (
1610                            escape_markdown(
1611                                message_text[last_offset : entity.offset - offset], version=version
1612                            )
1613                            + insert
1614                        )
1615                    else:
1616                        markdown_text += (
1617                            escape_markdown(
1618                                message_text[  # type: ignore
1619                                    last_offset * 2 : (entity.offset - offset) * 2
1620                                ].decode('utf-16-le'),
1621                                version=version,
1622                            )
1623                            + insert
1624                        )
1625                else:
1626                    if sys.maxunicode == 0xFFFF:
1627                        markdown_text += (
1628                            message_text[last_offset : entity.offset - offset] + insert
1629                        )
1630                    else:
1631                        markdown_text += (
1632                            message_text[  # type: ignore
1633                                last_offset * 2 : (entity.offset - offset) * 2
1634                            ].decode('utf-16-le')
1635                            + insert
1636                        )
1637
1638                last_offset = entity.offset - offset + entity.length
1639
1640        if offset == 0:
1641            if sys.maxunicode == 0xFFFF:
1642                markdown_text += escape_markdown(message_text[last_offset:], version=version)
1643            else:
1644                markdown_text += escape_markdown(
1645                    message_text[last_offset * 2 :].decode('utf-16-le'),  # type: ignore
1646                    version=version,
1647                )
1648        else:
1649            if sys.maxunicode == 0xFFFF:
1650                markdown_text += message_text[last_offset:]
1651            else:
1652                markdown_text += message_text[last_offset * 2 :].decode(  # type: ignore
1653                    'utf-16-le'
1654                )
1655
1656        return markdown_text
1657
1658    @property
1659    def text_markdown(self) -> str:
1660        """Creates an Markdown-formatted string from the markup entities found in the message
1661        using :class:`telegram.ParseMode.MARKDOWN`.
1662
1663        Use this if you want to retrieve the message text with the entities formatted as Markdown
1664        in the same way the original message was formatted.
1665
1666        Note:
1667            :attr:`telegram.ParseMode.MARKDOWN` is is a legacy mode, retained by Telegram for
1668            backward compatibility. You should use :meth:`text_markdown_v2` instead.
1669
1670        Returns:
1671            :obj:`str`: Message text with entities formatted as Markdown.
1672
1673        """
1674        return self._parse_markdown(self.text, self.parse_entities(), urled=False)
1675
1676    @property
1677    def text_markdown_v2(self) -> str:
1678        """Creates an Markdown-formatted string from the markup entities found in the message
1679        using :class:`telegram.ParseMode.MARKDOWN_V2`.
1680
1681        Use this if you want to retrieve the message text with the entities formatted as Markdown
1682        in the same way the original message was formatted.
1683
1684        Returns:
1685            :obj:`str`: Message text with entities formatted as Markdown.
1686
1687        """
1688        return self._parse_markdown(self.text, self.parse_entities(), urled=False, version=2)
1689
1690    @property
1691    def text_markdown_urled(self) -> str:
1692        """Creates an Markdown-formatted string from the markup entities found in the message
1693        using :class:`telegram.ParseMode.MARKDOWN`.
1694
1695        Use this if you want to retrieve the message text with the entities formatted as Markdown.
1696        This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1697
1698        Note:
1699            :attr:`telegram.ParseMode.MARKDOWN` is is a legacy mode, retained by Telegram for
1700            backward compatibility. You should use :meth:`text_markdown_v2_urled` instead.
1701
1702        Returns:
1703            :obj:`str`: Message text with entities formatted as Markdown.
1704
1705        """
1706        return self._parse_markdown(self.text, self.parse_entities(), urled=True)
1707
1708    @property
1709    def text_markdown_v2_urled(self) -> str:
1710        """Creates an Markdown-formatted string from the markup entities found in the message
1711        using :class:`telegram.ParseMode.MARKDOWN_V2`.
1712
1713        Use this if you want to retrieve the message text with the entities formatted as Markdown.
1714        This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1715
1716        Returns:
1717            :obj:`str`: Message text with entities formatted as Markdown.
1718
1719        """
1720        return self._parse_markdown(self.text, self.parse_entities(), urled=True, version=2)
1721
1722    @property
1723    def caption_markdown(self) -> str:
1724        """Creates an Markdown-formatted string from the markup entities found in the message's
1725        caption using :class:`telegram.ParseMode.MARKDOWN`.
1726
1727        Use this if you want to retrieve the message caption with the caption entities formatted as
1728        Markdown in the same way the original message was formatted.
1729
1730        Note:
1731            :attr:`telegram.ParseMode.MARKDOWN` is is a legacy mode, retained by Telegram for
1732            backward compatibility. You should use :meth:`caption_markdown_v2` instead.
1733
1734        Returns:
1735            :obj:`str`: Message caption with caption entities formatted as Markdown.
1736
1737        """
1738        return self._parse_markdown(self.caption, self.parse_caption_entities(), urled=False)
1739
1740    @property
1741    def caption_markdown_v2(self) -> str:
1742        """Creates an Markdown-formatted string from the markup entities found in the message's
1743        caption using :class:`telegram.ParseMode.MARKDOWN_V2`.
1744
1745        Use this if you want to retrieve the message caption with the caption entities formatted as
1746        Markdown in the same way the original message was formatted.
1747
1748        Returns:
1749            :obj:`str`: Message caption with caption entities formatted as Markdown.
1750
1751        """
1752        return self._parse_markdown(
1753            self.caption, self.parse_caption_entities(), urled=False, version=2
1754        )
1755
1756    @property
1757    def caption_markdown_urled(self) -> str:
1758        """Creates an Markdown-formatted string from the markup entities found in the message's
1759        caption using :class:`telegram.ParseMode.MARKDOWN`.
1760
1761        Use this if you want to retrieve the message caption with the caption entities formatted as
1762        Markdown. This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1763
1764        Note:
1765            :attr:`telegram.ParseMode.MARKDOWN` is is a legacy mode, retained by Telegram for
1766            backward compatibility. You should use :meth:`caption_markdown_v2_urled` instead.
1767
1768        Returns:
1769            :obj:`str`: Message caption with caption entities formatted as Markdown.
1770
1771        """
1772        return self._parse_markdown(self.caption, self.parse_caption_entities(), urled=True)
1773
1774    @property
1775    def caption_markdown_v2_urled(self) -> str:
1776        """Creates an Markdown-formatted string from the markup entities found in the message's
1777        caption using :class:`telegram.ParseMode.MARKDOWN_V2`.
1778
1779        Use this if you want to retrieve the message caption with the caption entities formatted as
1780        Markdown. This also formats :attr:`telegram.MessageEntity.URL` as a hyperlink.
1781
1782        Returns:
1783            :obj:`str`: Message caption with caption entities formatted as Markdown.
1784
1785        """
1786        return self._parse_markdown(
1787            self.caption, self.parse_caption_entities(), urled=True, version=2
1788        )
1789