diff --git a/compiler/api/source/main_api.tl b/compiler/api/source/main_api.tl index bc5b1bf3..3cfee8a5 100644 --- a/compiler/api/source/main_api.tl +++ b/compiler/api/source/main_api.tl @@ -106,8 +106,8 @@ chatForbidden#6592a1a7 id:long title:string = Chat; channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat; channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; -chatFull#46a6ffb4 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector = ChatFull; -channelFull#56662e2e flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer = ChatFull; +chatFull#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?Vector = ChatFull; +channelFull#e13c3d20 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?Vector = ChatFull; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; @@ -120,7 +120,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto; messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message; -message#85d6cbe2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector ttl_period:flags.25?int = Message; +message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector ttl_period:flags.25?int = Message; messageService#2b085862 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -359,6 +359,7 @@ updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJ updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector = Update; updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector = Update; updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update; +updateMessageReactions#154798c3 peer:Peer msg_id:int reactions:MessageReactions = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -592,6 +593,7 @@ messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity; messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity; messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity; messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity; +messageEntitySpoiler#32ca960f offset:int length:int = MessageEntity; inputChannelEmpty#ee8c1e86 = InputChannel; inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel; @@ -897,6 +899,7 @@ channelAdminLogEventActionChangeHistoryTTL#6e941a38 prev_value:int new_value:int channelAdminLogEventActionParticipantJoinByRequest#afb6144a invite:ExportedChatInvite approved_by:long = ChannelAdminLogEventAction; channelAdminLogEventActionToggleNoForwards#cb2ac766 new_value:Bool = ChannelAdminLogEventAction; channelAdminLogEventActionSendMessage#278f2868 message:Message = ChannelAdminLogEventAction; +channelAdminLogEventActionChangeAvailableReactions#9cf7f76a prev_value:Vector new_value:Vector = ChannelAdminLogEventAction; channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent; @@ -1260,7 +1263,7 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult; account.resetPasswordOk#e926d63e = account.ResetPasswordResult; -sponsoredMessage#d151e19a flags:# random_id:bytes from_id:Peer channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector = SponsoredMessage; +sponsoredMessage#3a836df8 flags:# random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector = SponsoredMessage; messages.sponsoredMessages#65a4c7d5 messages:Vector chats:Vector users:Vector = messages.SponsoredMessages; @@ -1280,6 +1283,19 @@ messages.peerSettings#6880b94d settings:PeerSettings chats:Vector users:Ve auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut; +reactionCount#6fb250d1 flags:# chosen:flags.0?true reaction:string count:int = ReactionCount; + +messageReactions#87b6e36 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector recent_reactons:flags.1?Vector = MessageReactions; + +messageUserReaction#932844fa user_id:long reaction:string = MessageUserReaction; + +messages.messageReactionsList#a366923c flags:# count:int reactions:Vector users:Vector next_offset:flags.0?string = messages.MessageReactionsList; + +availableReaction#21d7c4b flags:# inactive:flags.0?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document = AvailableReaction; + +messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions; +messages.availableReactions#768e3aad hash:int reactions:Vector = messages.AvailableReactions; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -1418,9 +1434,9 @@ messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?t messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector = messages.AffectedMessages; messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool; -messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; -messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; -messages.forwardMessages#cc30290b flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.forwardMessages#cc30290b flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings; messages.report#8953ab4e peer:InputPeer id:Vector reason:ReportReason message:string = Bool; @@ -1499,7 +1515,7 @@ messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool; messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages; messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory; messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages; -messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; +messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates; messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile; messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets; messages.getSplitRanges#1cff7e08 = Vector; @@ -1558,6 +1574,12 @@ messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPe messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates; messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates; messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool; +messages.sendReaction#25690ce4 flags:# peer:InputPeer msg_id:int reaction:flags.0?string = Updates; +messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector = Updates; +messages.getMessageReactionsList#e0ee6b77 flags:# peer:InputPeer id:int reaction:flags.0?string offset:flags.1?string limit:int = messages.MessageReactionsList; +messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector = Updates; +messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions; +messages.setDefaultReaction#d960c4d4 reaction:string = Bool; updates.getState#edd4882a = updates.State; updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference; @@ -1706,4 +1728,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages; stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats; -// LAYER 135 \ No newline at end of file +// LAYER 136 \ No newline at end of file diff --git a/compiler/errors/source/400_BAD_REQUEST.tsv b/compiler/errors/source/400_BAD_REQUEST.tsv index e1d29f38..1b12472c 100644 --- a/compiler/errors/source/400_BAD_REQUEST.tsv +++ b/compiler/errors/source/400_BAD_REQUEST.tsv @@ -249,7 +249,7 @@ RANDOM_ID_INVALID The provided random ID is invalid RANDOM_LENGTH_INVALID The random length is invalid RANGES_INVALID Invalid range provided REACTION_EMPTY The reaction provided is empty -REACTION_INVALID Invalid reaction provided (only emoji are allowed) +REACTION_INVALID Invalid reaction provided (only valid emoji are allowed) REFLECTOR_NOT_AVAILABLE The call reflector is not available REPLY_MARKUP_BUY_EMPTY Reply markup for buy button empty REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty diff --git a/docs/source/topics/text-formatting.rst b/docs/source/topics/text-formatting.rst index 5d9a9376..e3b730e5 100644 --- a/docs/source/topics/text-formatting.rst +++ b/docs/source/topics/text-formatting.rst @@ -34,6 +34,7 @@ list of the basic styles currently supported by Pyrogram. - *italic* - :strike:`strike` - :underline:`underline` +- spoiler - `text URL `_ - `user text mention `_ - ``inline fixed-width code`` @@ -63,6 +64,8 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us ~~strike~~ + ||spoiler|| + [text URL](https://docs.pyrogram.org/) [text user mention](tg://user?id=23122162) @@ -86,6 +89,7 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us "__italic__, " "--underline--, " "~~strike~~, " + "||spoiler||, " "[mention](tg://user?id=23122162), " "[URL](https://pyrogram.org), " "`code`, " @@ -113,6 +117,8 @@ The following tags are currently supported: strike, strike, strike + spoiler + text URL inline mention @@ -136,6 +142,7 @@ The following tags are currently supported: "italic, " "underline, " "strike, " + "spoiler, " "mention, " "URL, " "code\n\n" diff --git a/pyrogram/methods/bots/send_game.py b/pyrogram/methods/bots/send_game.py index 8f6d10ab..f6e6a340 100644 --- a/pyrogram/methods/bots/send_game.py +++ b/pyrogram/methods/bots/send_game.py @@ -30,6 +30,7 @@ class SendGame(Scaffold): game_short_name: str, disable_notification: bool = None, reply_to_message_id: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -55,6 +56,9 @@ class SendGame(Scaffold): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup`, *optional*): An object for an inline keyboard. If empty, one ‘Play game_title’ button will be shown automatically. If not empty, the first button must launch the game. @@ -80,6 +84,7 @@ class SendGame(Scaffold): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) ) diff --git a/pyrogram/methods/messages/__init__.py b/pyrogram/methods/messages/__init__.py index 8dee8402..84cc143d 100644 --- a/pyrogram/methods/messages/__init__.py +++ b/pyrogram/methods/messages/__init__.py @@ -53,6 +53,7 @@ from .send_media_group import SendMediaGroup from .send_message import SendMessage from .send_photo import SendPhoto from .send_poll import SendPoll +from .send_reaction import SendReaction from .send_sticker import SendSticker from .send_venue import SendVenue from .send_video import SendVideo @@ -106,6 +107,7 @@ class Messages( CopyMediaGroup, SearchMessagesCount, SearchGlobalCount, - GetDiscussionMessage + GetDiscussionMessage, + SendReaction ): pass diff --git a/pyrogram/methods/messages/copy_message.py b/pyrogram/methods/messages/copy_message.py index 3250ac89..5e886949 100644 --- a/pyrogram/methods/messages/copy_message.py +++ b/pyrogram/methods/messages/copy_message.py @@ -37,6 +37,7 @@ class CopyMessage(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -88,6 +89,9 @@ class CopyMessage(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -112,5 +116,6 @@ class CopyMessage(Scaffold): disable_notification=disable_notification, reply_to_message_id=reply_to_message_id, schedule_date=schedule_date, + protect_content=protect_content, reply_markup=reply_markup ) diff --git a/pyrogram/methods/messages/forward_messages.py b/pyrogram/methods/messages/forward_messages.py index b67e50ec..9218bf6e 100644 --- a/pyrogram/methods/messages/forward_messages.py +++ b/pyrogram/methods/messages/forward_messages.py @@ -30,7 +30,8 @@ class ForwardMessages(Scaffold): from_chat_id: Union[int, str], message_ids: Union[int, Iterable[int]], disable_notification: bool = None, - schedule_date: int = None + schedule_date: int = None, + protect_content: bool = None ) -> Union["types.Message", List["types.Message"]]: """Forward messages of any kind. @@ -56,6 +57,9 @@ class ForwardMessages(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + Returns: :obj:`~pyrogram.types.Message` | List of :obj:`~pyrogram.types.Message`: In case *message_ids* was an integer, the single forwarded message is returned, otherwise, in case *message_ids* was an iterable, @@ -82,7 +86,8 @@ class ForwardMessages(Scaffold): id=message_ids, silent=disable_notification or None, random_id=[self.rnd_id() for _ in message_ids], - schedule_date=schedule_date + schedule_date=schedule_date, + noforwards=protect_content ) ) diff --git a/pyrogram/methods/messages/send_animation.py b/pyrogram/methods/messages/send_animation.py index d365ae56..d1ee9585 100644 --- a/pyrogram/methods/messages/send_animation.py +++ b/pyrogram/methods/messages/send_animation.py @@ -46,6 +46,7 @@ class SendAnimation(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -116,6 +117,9 @@ class SendAnimation(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -222,6 +226,7 @@ class SendAnimation(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/methods/messages/send_audio.py b/pyrogram/methods/messages/send_audio.py index 4fa683a9..eeb45f65 100644 --- a/pyrogram/methods/messages/send_audio.py +++ b/pyrogram/methods/messages/send_audio.py @@ -45,6 +45,7 @@ class SendAudio(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -113,6 +114,9 @@ class SendAudio(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -217,6 +221,7 @@ class SendAudio(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/methods/messages/send_contact.py b/pyrogram/methods/messages/send_contact.py index 6317a829..f744fab0 100644 --- a/pyrogram/methods/messages/send_contact.py +++ b/pyrogram/methods/messages/send_contact.py @@ -34,6 +34,7 @@ class SendContact(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -71,6 +72,9 @@ class SendContact(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -97,6 +101,7 @@ class SendContact(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) ) diff --git a/pyrogram/methods/messages/send_dice.py b/pyrogram/methods/messages/send_dice.py index 4b7422b3..6c7f70cd 100644 --- a/pyrogram/methods/messages/send_dice.py +++ b/pyrogram/methods/messages/send_dice.py @@ -31,6 +31,7 @@ class SendDice(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -63,6 +64,9 @@ class SendDice(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -91,6 +95,7 @@ class SendDice(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" ) diff --git a/pyrogram/methods/messages/send_document.py b/pyrogram/methods/messages/send_document.py index a7e34285..3661b255 100644 --- a/pyrogram/methods/messages/send_document.py +++ b/pyrogram/methods/messages/send_document.py @@ -43,6 +43,7 @@ class SendDocument(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -105,6 +106,9 @@ class SendDocument(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -194,6 +198,7 @@ class SendDocument(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/methods/messages/send_location.py b/pyrogram/methods/messages/send_location.py index e70d9661..1bc3b032 100644 --- a/pyrogram/methods/messages/send_location.py +++ b/pyrogram/methods/messages/send_location.py @@ -32,6 +32,7 @@ class SendLocation(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -63,6 +64,9 @@ class SendLocation(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -89,6 +93,7 @@ class SendLocation(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) ) diff --git a/pyrogram/methods/messages/send_media_group.py b/pyrogram/methods/messages/send_media_group.py index 4073ddec..dc8ca7f0 100644 --- a/pyrogram/methods/messages/send_media_group.py +++ b/pyrogram/methods/messages/send_media_group.py @@ -44,6 +44,7 @@ class SendMediaGroup(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, ) -> List["types.Message"]: """Send a group of photos or videos as an album. @@ -66,6 +67,9 @@ class SendMediaGroup(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + Returns: List of :obj:`~pyrogram.types.Message`: On success, a list of the sent messages is returned. @@ -377,7 +381,8 @@ class SendMediaGroup(Scaffold): multi_media=multi_media, silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, - schedule_date=schedule_date + schedule_date=schedule_date, + noforwards=protect_content ), sleep_threshold=60 ) diff --git a/pyrogram/methods/messages/send_message.py b/pyrogram/methods/messages/send_message.py index 552a233b..54fcfe48 100644 --- a/pyrogram/methods/messages/send_message.py +++ b/pyrogram/methods/messages/send_message.py @@ -34,6 +34,7 @@ class SendMessage(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -75,6 +76,9 @@ class SendMessage(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -132,7 +136,8 @@ class SendMessage(Scaffold): schedule_date=schedule_date, reply_markup=await reply_markup.write(self) if reply_markup else None, message=message, - entities=entities + entities=entities, + noforwards=protect_content ) ) diff --git a/pyrogram/methods/messages/send_photo.py b/pyrogram/methods/messages/send_photo.py index fcc3c04c..ff695589 100644 --- a/pyrogram/methods/messages/send_photo.py +++ b/pyrogram/methods/messages/send_photo.py @@ -41,6 +41,7 @@ class SendPhoto(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -93,6 +94,9 @@ class SendPhoto(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -172,6 +176,7 @@ class SendPhoto(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/methods/messages/send_poll.py b/pyrogram/methods/messages/send_poll.py index dc0ccf17..6fbb0aab 100644 --- a/pyrogram/methods/messages/send_poll.py +++ b/pyrogram/methods/messages/send_poll.py @@ -36,6 +36,7 @@ class SendPoll(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -83,6 +84,9 @@ class SendPoll(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -117,6 +121,7 @@ class SendPoll(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) ) diff --git a/pyrogram/methods/messages/send_reaction.py b/pyrogram/methods/messages/send_reaction.py new file mode 100644 index 00000000..a65cb5bc --- /dev/null +++ b/pyrogram/methods/messages/send_reaction.py @@ -0,0 +1,65 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2021 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from typing import Union + +from pyrogram import raw +from pyrogram.scaffold import Scaffold + + +class SendReaction(Scaffold): + async def send_reaction( + self, + chat_id: Union[int, str], + message_id: int, + emoji: str = "" + ) -> bool: + """Send a reaction to a message. + + Parameters: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + + message_id (``int``): + Identifier of the message. + + emoji (``str``, *optional*): + Reaction emoji. + Pass "" as emoji (default) to retract the reaction. + + Returns: + ``bool``: On success, True is returned. + + Example: + .. code-block:: python + + # Send a reaction + app.send_reaction(chat_id, message_id, "🔥") + + # Retract a reaction + app.send_reaction(chat_id, message_id) + """ + await self.send( + raw.functions.messages.SendReaction( + peer=await self.resolve_peer(chat_id), + msg_id=message_id, + reaction=emoji + ) + ) + + return True diff --git a/pyrogram/methods/messages/send_sticker.py b/pyrogram/methods/messages/send_sticker.py index c7ae122a..144bba37 100644 --- a/pyrogram/methods/messages/send_sticker.py +++ b/pyrogram/methods/messages/send_sticker.py @@ -37,6 +37,7 @@ class SendSticker(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -71,6 +72,9 @@ class SendSticker(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -150,6 +154,7 @@ class SendSticker(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" ) diff --git a/pyrogram/methods/messages/send_venue.py b/pyrogram/methods/messages/send_venue.py index 7dbae7a0..557aa673 100644 --- a/pyrogram/methods/messages/send_venue.py +++ b/pyrogram/methods/messages/send_venue.py @@ -36,6 +36,7 @@ class SendVenue(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -80,6 +81,9 @@ class SendVenue(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -113,6 +117,7 @@ class SendVenue(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None ) ) diff --git a/pyrogram/methods/messages/send_video.py b/pyrogram/methods/messages/send_video.py index d42846ed..23563175 100644 --- a/pyrogram/methods/messages/send_video.py +++ b/pyrogram/methods/messages/send_video.py @@ -47,6 +47,7 @@ class SendVideo(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -122,6 +123,9 @@ class SendVideo(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -228,6 +232,7 @@ class SendVideo(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/methods/messages/send_video_note.py b/pyrogram/methods/messages/send_video_note.py index 91ba93fe..231e1498 100644 --- a/pyrogram/methods/messages/send_video_note.py +++ b/pyrogram/methods/messages/send_video_note.py @@ -39,6 +39,7 @@ class SendVideoNote(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -85,6 +86,9 @@ class SendVideoNote(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -174,6 +178,7 @@ class SendVideoNote(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, message="" ) diff --git a/pyrogram/methods/messages/send_voice.py b/pyrogram/methods/messages/send_voice.py index c534767b..9828ccf8 100644 --- a/pyrogram/methods/messages/send_voice.py +++ b/pyrogram/methods/messages/send_voice.py @@ -41,6 +41,7 @@ class SendVoice(Scaffold): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -91,6 +92,9 @@ class SendVoice(Scaffold): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -178,6 +182,7 @@ class SendVoice(Scaffold): reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), schedule_date=schedule_date, + noforwards=protect_content, reply_markup=await reply_markup.write(self) if reply_markup else None, **await utils.parse_text_entities(self, caption, parse_mode, caption_entities) ) diff --git a/pyrogram/parser/html.py b/pyrogram/parser/html.py index f3f55195..805ca021 100644 --- a/pyrogram/parser/html.py +++ b/pyrogram/parser/html.py @@ -61,6 +61,8 @@ class Parser(HTMLParser): elif tag == "pre": entity = raw.types.MessageEntityPre extra["language"] = "" + elif tag == "spoiler": + entity = raw.types.MessageEntitySpoiler elif tag == "a": url = attrs.get("href", "") @@ -153,7 +155,7 @@ class HTML: start = entity.offset end = start + entity.length - if entity_type in ("bold", "italic", "underline", "strikethrough"): + if entity_type in ("bold", "italic", "underline", "strikethrough", "spoiler"): start_tag = f"<{entity_type[0]}>" end_tag = f"" elif entity_type in ("code", "pre", "blockquote"): diff --git a/pyrogram/parser/markdown.py b/pyrogram/parser/markdown.py index f71503d8..5d14f8e8 100644 --- a/pyrogram/parser/markdown.py +++ b/pyrogram/parser/markdown.py @@ -28,6 +28,7 @@ BOLD_DELIM = "**" ITALIC_DELIM = "__" UNDERLINE_DELIM = "--" STRIKE_DELIM = "~~" +SPOILER_DELIM = "||" CODE_DELIM = "`" PRE_DELIM = "```" @@ -41,7 +42,8 @@ MARKDOWN_RE = re.compile(r"({d})|\[(.+?)\]\((.+?)\)".format( STRIKE_DELIM, UNDERLINE_DELIM, ITALIC_DELIM, - BOLD_DELIM + BOLD_DELIM, + SPOILER_DELIM ] ]] ))) @@ -90,6 +92,8 @@ class Markdown: tag = "code" elif delim == PRE_DELIM: tag = "pre" + elif delim == SPOILER_DELIM: + tag = "spoiler" else: continue @@ -127,6 +131,8 @@ class Markdown: start_tag = end_tag = CODE_DELIM elif entity_type in ("pre", "blockquote"): start_tag = end_tag = PRE_DELIM + elif entity_type == "spoiler": + start_tag = end_tag = SPOILER_DELIM elif entity_type == "text_link": url = entity.url start_tag = "[" diff --git a/pyrogram/types/messages_and_media/__init__.py b/pyrogram/types/messages_and_media/__init__.py index 864019fe..9f31dde0 100644 --- a/pyrogram/types/messages_and_media/__init__.py +++ b/pyrogram/types/messages_and_media/__init__.py @@ -36,8 +36,10 @@ from .video import Video from .video_note import VideoNote from .voice import Voice from .webpage import WebPage +from .reaction import Reaction __all__ = [ "Animation", "Audio", "Contact", "Document", "Game", "Location", "Message", "MessageEntity", "Photo", "Thumbnail", - "StrippedThumbnail", "Poll", "PollOption", "Sticker", "Venue", "Video", "VideoNote", "Voice", "WebPage", "Dice" + "StrippedThumbnail", "Poll", "PollOption", "Sticker", "Venue", "Video", "VideoNote", "Voice", "WebPage", "Dice", + "Reaction" ] diff --git a/pyrogram/types/messages_and_media/message.py b/pyrogram/types/messages_and_media/message.py index 9e1c7e1a..9690baf9 100644 --- a/pyrogram/types/messages_and_media/message.py +++ b/pyrogram/types/messages_and_media/message.py @@ -284,6 +284,9 @@ class Message(Object, Update): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. + reactions (List of :obj:`~pyrogram.types.Reaction`): + List of the reactions to this message. + link (``str``, *property*): Generate a link to this message, only for groups and channels. """ @@ -361,7 +364,8 @@ class Message(Object, Update): "types.ReplyKeyboardMarkup", "types.ReplyKeyboardRemove", "types.ForceReply" - ] = None + ] = None, + reactions: List["types.Reaction"] = None ): super().__init__(client) @@ -428,6 +432,7 @@ class Message(Object, Update): self.voice_chat_started = voice_chat_started self.voice_chat_ended = voice_chat_ended self.voice_chat_members_invited = voice_chat_members_invited + self.reactions = reactions @staticmethod async def _parse( @@ -721,6 +726,9 @@ class Message(Object, Update): from_user = types.User._parse(client, users.get(user_id, None)) sender_chat = types.Chat._parse(client, message, users, chats, is_chat=False) if not from_user else None + reactions = [types.Reaction(emoji=r.reaction, count=r.count, chosen=r.chosen) + for r in message.reactions.results] if message.reactions else None + parsed_message = Message( message_id=message.id, date=message.date, @@ -780,6 +788,7 @@ class Message(Object, Update): via_bot=types.User._parse(client, users.get(message.via_bot_id, None)), outgoing=message.out, reply_markup=reply_markup, + reactions=reactions, client=client ) @@ -2915,6 +2924,7 @@ class Message(Object, Update): disable_notification: bool = None, reply_to_message_id: int = None, schedule_date: int = None, + protect_content: bool = None, reply_markup: Union[ "types.InlineKeyboardMarkup", "types.ReplyKeyboardMarkup", @@ -2970,6 +2980,9 @@ class Message(Object, Update): schedule_date (``int``, *optional*): Date when the message will be automatically sent. Unix time. + protect_content (``bool``, *optional*): + Protects the contents of the sent message from forwarding and saving. + reply_markup (:obj:`~pyrogram.types.InlineKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardMarkup` | :obj:`~pyrogram.types.ReplyKeyboardRemove` | :obj:`~pyrogram.types.ForceReply`, *optional*): Additional interface options. An object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. @@ -2999,6 +3012,7 @@ class Message(Object, Update): disable_notification=disable_notification, reply_to_message_id=reply_to_message_id, schedule_date=schedule_date, + protect_content=protect_content, reply_markup=self.reply_markup if reply_markup is object else reply_markup ) elif self.media: @@ -3008,6 +3022,7 @@ class Message(Object, Update): disable_notification=disable_notification, reply_to_message_id=reply_to_message_id, schedule_date=schedule_date, + protect_content=protect_content, reply_markup=self.reply_markup if reply_markup is object else reply_markup ) diff --git a/pyrogram/types/messages_and_media/message_entity.py b/pyrogram/types/messages_and_media/message_entity.py index a0fc86a9..9a211fde 100644 --- a/pyrogram/types/messages_and_media/message_entity.py +++ b/pyrogram/types/messages_and_media/message_entity.py @@ -42,6 +42,7 @@ class MessageEntityType(AutoName): ITALIC = auto() UNDERLINE = auto() STRIKETHROUGH = auto() + SPOILER = auto() CODE = auto() PRE = auto() TEXT_LINK = auto() @@ -62,6 +63,7 @@ RAW_ENTITIES_TO_TYPE = { raw.types.MessageEntityPre: MessageEntityType.PRE, raw.types.MessageEntityUnderline: MessageEntityType.UNDERLINE, raw.types.MessageEntityStrike: MessageEntityType.STRIKETHROUGH, + raw.types.MessageEntitySpoiler: MessageEntityType.SPOILER, raw.types.MessageEntityBlockquote: MessageEntityType.BLOCKQUOTE, raw.types.MessageEntityTextUrl: MessageEntityType.TEXT_LINK, raw.types.MessageEntityMentionName: MessageEntityType.TEXT_MENTION, @@ -90,6 +92,7 @@ class MessageEntity(Object): - "italic": *italic text*. - "underline": underlined text. - "strikethrough": strikethrough text. + - "spoiler": spoiler text. - "code": monowidth string. - "pre": monowidth block (see *language* below). - "text_link": for clickable text URLs. diff --git a/pyrogram/types/messages_and_media/reaction.py b/pyrogram/types/messages_and_media/reaction.py new file mode 100644 index 00000000..9d4baa54 --- /dev/null +++ b/pyrogram/types/messages_and_media/reaction.py @@ -0,0 +1,49 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2021 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import pyrogram +from ..object import Object + + +class Reaction(Object): + """Contains information about a reaction. + + Parameters: + emoji (``str``): + Reaction emoji. + + count (``int``): + Reaction count. + + chosen (``bool``): + Whether this is the chosen reaction. + """ + + def __init__( + self, + *, + client: "pyrogram.Client" = None, + emoji: str, + count: int, + chosen: bool + ): + super().__init__(client) + + self.emoji = emoji + self.count = count + self.chosen = chosen diff --git a/pyrogram/types/user_and_chats/chat.py b/pyrogram/types/user_and_chats/chat.py index 898a4325..c49afb5a 100644 --- a/pyrogram/types/user_and_chats/chat.py +++ b/pyrogram/types/user_and_chats/chat.py @@ -124,6 +124,10 @@ class Chat(Object): send_as_chat (:obj:`~pyrogram.types.Chat`, *optional*): The default "send_as" chat. Returned only in :meth:`~pyrogram.Client.get_chat`. + + available_reactions (List of ``str``, *optional*): + Available reactions in the chat. + Returned only in :meth:`~pyrogram.Client.get_chat`. """ def __init__( @@ -156,7 +160,8 @@ class Chat(Object): permissions: "types.ChatPermissions" = None, distance: int = None, linked_chat: "types.Chat" = None, - send_as_chat: "types.Chat" = None + send_as_chat: "types.Chat" = None, + available_reactions: List[str] = None ): super().__init__(client) @@ -187,6 +192,7 @@ class Chat(Object): self.distance = distance self.linked_chat = linked_chat self.send_as_chat = send_as_chat + self.available_reactions = available_reactions @staticmethod def _parse_user_chat(client, user: raw.types.User) -> "Chat": @@ -337,6 +343,8 @@ class Chat(Object): if isinstance(full_chat.exported_invite, raw.types.ChatInviteExported): parsed_chat.invite_link = full_chat.exported_invite.link + parsed_chat.available_reactions = full_chat.available_reactions or None + return parsed_chat @staticmethod