diff --git a/compiler/error/source/400_BAD_REQUEST.tsv b/compiler/error/source/400_BAD_REQUEST.tsv index 01281830..7e930c8d 100644 --- a/compiler/error/source/400_BAD_REQUEST.tsv +++ b/compiler/error/source/400_BAD_REQUEST.tsv @@ -124,4 +124,5 @@ WEBDOCUMENT_URL_EMPTY The web document URL is empty WEBDOCUMENT_URL_INVALID The web document URL is invalid WEBDOCUMENT_MIME_INVALID The web document mime type is invalid BUTTON_URL_INVALID The button url is invalid -AUTH_BYTES_INVALID The authorization bytes are invalid \ No newline at end of file +AUTH_BYTES_INVALID The authorization bytes are invalid +CHANNELS_TOO_MUCH You have joined too many channels or supergroups \ No newline at end of file diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/client/ext/dispatcher.py index 744df2a8..a2fa472b 100644 --- a/pyrogram/client/ext/dispatcher.py +++ b/pyrogram/client/ext/dispatcher.py @@ -21,7 +21,13 @@ import logging from collections import OrderedDict import pyrogram -from pyrogram.api import types +from pyrogram.api.types import ( + UpdateNewMessage, UpdateNewChannelMessage, UpdateNewScheduledMessage, + UpdateEditMessage, UpdateEditChannelMessage, + UpdateDeleteMessages, UpdateDeleteChannelMessages, + UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, + UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll +) from . import utils from ..handlers import ( CallbackQueryHandler, MessageHandler, DeletedMessagesHandler, @@ -33,23 +39,24 @@ log = logging.getLogger(__name__) class Dispatcher: NEW_MESSAGE_UPDATES = ( - types.UpdateNewMessage, - types.UpdateNewChannelMessage + UpdateNewMessage, + UpdateNewChannelMessage, + UpdateNewScheduledMessage ) EDIT_MESSAGE_UPDATES = ( - types.UpdateEditMessage, - types.UpdateEditChannelMessage + UpdateEditMessage, + UpdateEditChannelMessage, ) DELETE_MESSAGES_UPDATES = ( - types.UpdateDeleteMessages, - types.UpdateDeleteChannelMessages + UpdateDeleteMessages, + UpdateDeleteChannelMessages ) CALLBACK_QUERY_UPDATES = ( - types.UpdateBotCallbackQuery, - types.UpdateInlineBotCallbackQuery + UpdateBotCallbackQuery, + UpdateInlineBotCallbackQuery ) MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES @@ -65,7 +72,10 @@ class Dispatcher: self.groups = OrderedDict() async def message_parser(update, users, chats): - return await pyrogram.Message._parse(self.client, update.message, users, chats), MessageHandler + return await pyrogram.Message._parse( + self.client, update.message, users, chats, + isinstance(update, UpdateNewScheduledMessage) + ), MessageHandler async def deleted_messages_parser(update, users, chats): return utils.parse_deleted_messages(self.client, update), DeletedMessagesHandler @@ -86,9 +96,9 @@ class Dispatcher: Dispatcher.MESSAGE_UPDATES: message_parser, Dispatcher.DELETE_MESSAGES_UPDATES: deleted_messages_parser, Dispatcher.CALLBACK_QUERY_UPDATES: callback_query_parser, - (types.UpdateUserStatus,): user_status_parser, - (types.UpdateBotInlineQuery,): inline_query_parser, - (types.UpdateMessagePoll,): poll_parser + (UpdateUserStatus,): user_status_parser, + (UpdateBotInlineQuery,): inline_query_parser, + (UpdateMessagePoll,): poll_parser } self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} diff --git a/pyrogram/client/filters/filters.py b/pyrogram/client/filters/filters.py index 5d892bbe..9d04c839 100644 --- a/pyrogram/client/filters/filters.py +++ b/pyrogram/client/filters/filters.py @@ -208,6 +208,12 @@ class Filters: *animation*, *voice*, *video_note*, *contact*, *location*, *venue*, *poll*. """ + scheduled = create(lambda _, m: bool(m.scheduled), "ScheduledFilter") + """Filter messages that have been scheduled (not yet sent).""" + + from_scheduled = create(lambda _, m: bool(m.from_scheduled), "FromScheduledFilter") + """Filter new automatically sent messages that were previously scheduled.""" + @staticmethod def command( commands: str or list, diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py index 22e349ff..6ff4453c 100644 --- a/pyrogram/client/methods/messages/send_animation.py +++ b/pyrogram/client/methods/messages/send_animation.py @@ -39,6 +39,7 @@ class SendAnimation(BaseClient): thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -98,6 +99,9 @@ class SendAnimation(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -183,6 +187,7 @@ class SendAnimation(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -191,11 +196,15 @@ class SendAnimation(BaseClient): await self.save_file(animation, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): message = await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) if unsave: diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/client/methods/messages/send_audio.py index 3d4d9689..ab416728 100644 --- a/pyrogram/client/methods/messages/send_audio.py +++ b/pyrogram/client/methods/messages/send_audio.py @@ -37,6 +37,7 @@ class SendAudio(BaseClient): title: str = None, thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -94,6 +95,9 @@ class SendAudio(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -180,6 +184,7 @@ class SendAudio(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -188,11 +193,15 @@ class SendAudio(BaseClient): await self.save_file(audio, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_cached_media.py b/pyrogram/client/methods/messages/send_cached_media.py index c95df576..46f81268 100644 --- a/pyrogram/client/methods/messages/send_cached_media.py +++ b/pyrogram/client/methods/messages/send_cached_media.py @@ -32,6 +32,7 @@ class SendCachedMedia(BaseClient): parse_mode: Union[str, None] = object, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -72,6 +73,9 @@ class SendCachedMedia(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -92,15 +96,17 @@ class SendCachedMedia(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_contact.py b/pyrogram/client/methods/messages/send_contact.py index 598d5ef2..a0317603 100644 --- a/pyrogram/client/methods/messages/send_contact.py +++ b/pyrogram/client/methods/messages/send_contact.py @@ -30,8 +30,10 @@ class SendContact(BaseClient): phone_number: str, first_name: str, last_name: str = None, - vcard: str = None, disable_notification: bool = None, + vcard: str = None, + disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -66,6 +68,9 @@ class SendContact(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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,14 +96,16 @@ class SendContact(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None ) ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py index b0810a0b..3143457d 100644 --- a/pyrogram/client/methods/messages/send_document.py +++ b/pyrogram/client/methods/messages/send_document.py @@ -30,10 +30,12 @@ class SendDocument(BaseClient): self, chat_id: Union[int, str], document: str, - thumb: str = None, caption: str = "", + thumb: str = None, + caption: str = "", parse_mode: Union[str, None] = object, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -80,6 +82,9 @@ class SendDocument(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -155,6 +160,7 @@ class SendDocument(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -163,11 +169,15 @@ class SendDocument(BaseClient): await self.save_file(document, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_location.py b/pyrogram/client/methods/messages/send_location.py index 977d4362..836a7ab7 100644 --- a/pyrogram/client/methods/messages/send_location.py +++ b/pyrogram/client/methods/messages/send_location.py @@ -31,6 +31,7 @@ class SendLocation(BaseClient): longitude: float, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -59,6 +60,9 @@ class SendLocation(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -84,14 +88,16 @@ class SendLocation(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None ) ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_message.py b/pyrogram/client/methods/messages/send_message.py index 3e790537..fadc4d61 100644 --- a/pyrogram/client/methods/messages/send_message.py +++ b/pyrogram/client/methods/messages/send_message.py @@ -32,6 +32,7 @@ class SendMessage(BaseClient): disable_web_page_preview: bool = None, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -67,6 +68,9 @@ class SendMessage(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -121,6 +125,7 @@ class SendMessage(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, message=message, entities=entities @@ -151,9 +156,10 @@ class SendMessage(BaseClient): ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_photo.py b/pyrogram/client/methods/messages/send_photo.py index 1e4a888d..3ec2f5b4 100644 --- a/pyrogram/client/methods/messages/send_photo.py +++ b/pyrogram/client/methods/messages/send_photo.py @@ -35,6 +35,7 @@ class SendPhoto(BaseClient): ttl_seconds: int = None, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -80,6 +81,9 @@ class SendPhoto(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -151,6 +155,7 @@ class SendPhoto(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -159,11 +164,15 @@ class SendPhoto(BaseClient): await self.save_file(photo, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_poll.py b/pyrogram/client/methods/messages/send_poll.py index 2fa008ab..a684dda9 100644 --- a/pyrogram/client/methods/messages/send_poll.py +++ b/pyrogram/client/methods/messages/send_poll.py @@ -31,6 +31,7 @@ class SendPoll(BaseClient): options: List[str], disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -59,6 +60,9 @@ class SendPoll(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -88,14 +92,16 @@ class SendPoll(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None ) ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_sticker.py b/pyrogram/client/methods/messages/send_sticker.py index 7cca77d5..5759fc18 100644 --- a/pyrogram/client/methods/messages/send_sticker.py +++ b/pyrogram/client/methods/messages/send_sticker.py @@ -32,6 +32,7 @@ class SendSticker(BaseClient): sticker: str, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -62,6 +63,9 @@ class SendSticker(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -129,6 +133,7 @@ class SendSticker(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, message="" ) @@ -137,11 +142,15 @@ class SendSticker(BaseClient): await self.save_file(sticker, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_venue.py b/pyrogram/client/methods/messages/send_venue.py index ba6b9bb7..b737d272 100644 --- a/pyrogram/client/methods/messages/send_venue.py +++ b/pyrogram/client/methods/messages/send_venue.py @@ -35,6 +35,7 @@ class SendVenue(BaseClient): foursquare_type: str = "", disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -76,6 +77,9 @@ class SendVenue(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -108,14 +112,16 @@ class SendVenue(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None ) ) for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage)): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/client/methods/messages/send_video.py index 46cdc995..57e32944 100644 --- a/pyrogram/client/methods/messages/send_video.py +++ b/pyrogram/client/methods/messages/send_video.py @@ -39,6 +39,7 @@ class SendVideo(BaseClient): supports_streaming: bool = True, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -98,6 +99,9 @@ class SendVideo(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message. + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -179,6 +183,7 @@ class SendVideo(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -187,11 +192,15 @@ class SendVideo(BaseClient): await self.save_file(video, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/client/methods/messages/send_video_note.py index 5ab00a9e..164b60b7 100644 --- a/pyrogram/client/methods/messages/send_video_note.py +++ b/pyrogram/client/methods/messages/send_video_note.py @@ -35,6 +35,7 @@ class SendVideoNote(BaseClient): thumb: str = None, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -77,6 +78,9 @@ class SendVideoNote(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -147,6 +151,7 @@ class SendVideoNote(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, message="" ) @@ -155,11 +160,15 @@ class SendVideoNote(BaseClient): await self.save_file(video_note, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/methods/messages/send_voice.py b/pyrogram/client/methods/messages/send_voice.py index 1577622d..e8326e8d 100644 --- a/pyrogram/client/methods/messages/send_voice.py +++ b/pyrogram/client/methods/messages/send_voice.py @@ -35,6 +35,7 @@ class SendVoice(BaseClient): duration: int = 0, disable_notification: bool = None, reply_to_message_id: int = None, + schedule_date: int = None, reply_markup: Union[ "pyrogram.InlineKeyboardMarkup", "pyrogram.ReplyKeyboardMarkup", @@ -78,6 +79,9 @@ class SendVoice(BaseClient): reply_to_message_id (``int``, *optional*): If the message is a reply, ID of the original message + schedule_date (``int``, *optional*): + Date when the message will be automatically sent. Unix time. + reply_markup (:obj:`InlineKeyboardMarkup` | :obj:`ReplyKeyboardMarkup` | :obj:`ReplyKeyboardRemove` | :obj:`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. @@ -151,6 +155,7 @@ class SendVoice(BaseClient): silent=disable_notification or None, reply_to_msg_id=reply_to_message_id, random_id=self.rnd_id(), + schedule_date=schedule_date, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) ) @@ -159,11 +164,15 @@ class SendVoice(BaseClient): await self.save_file(voice, file_id=file.id, file_part=e.x) else: for i in r.updates: - if isinstance(i, (types.UpdateNewMessage, types.UpdateNewChannelMessage)): + if isinstance( + i, + (types.UpdateNewMessage, types.UpdateNewChannelMessage, types.UpdateNewScheduledMessage) + ): return await pyrogram.Message._parse( self, i.message, {i.id: i for i in r.users}, - {i.id: i for i in r.chats} + {i.id: i for i in r.chats}, + is_scheduled=isinstance(i, types.UpdateNewScheduledMessage) ) except BaseClient.StopTransmission: return None diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index bc1ff186..0ae20d7f 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -282,6 +282,8 @@ class Message(Object, Update): mentioned: bool = None, empty: bool = None, service: bool = None, + scheduled: bool = None, + from_scheduled: bool = None, media: bool = None, edit_date: int = None, media_group_id: str = None, @@ -344,6 +346,8 @@ class Message(Object, Update): self.mentioned = mentioned self.empty = empty self.service = service + self.scheduled = scheduled + self.from_scheduled = from_scheduled self.media = media self.edit_date = edit_date self.media_group_id = media_group_id @@ -387,7 +391,7 @@ class Message(Object, Update): @staticmethod async def _parse(client, message: types.Message or types.MessageService or types.MessageEmpty, users: dict, - chats: dict, replies: int = 1): + chats: dict, is_scheduled: bool = False, replies: int = 1): if isinstance(message, types.MessageEmpty): return Message(message_id=message.id, empty=True, client=client) @@ -620,6 +624,8 @@ class Message(Object, Update): forward_signature=forward_signature, forward_date=forward_date, mentioned=message.mentioned, + scheduled=is_scheduled, + from_scheduled=message.from_scheduled, media=bool(media) or None, edit_date=message.edit_date, media_group_id=message.grouped_id, diff --git a/pyrogram/client/types/user_and_chats/chat_photo.py b/pyrogram/client/types/user_and_chats/chat_photo.py index 95160447..b19ea771 100644 --- a/pyrogram/client/types/user_and_chats/chat_photo.py +++ b/pyrogram/client/types/user_and_chats/chat_photo.py @@ -20,6 +20,7 @@ from struct import pack import pyrogram from pyrogram.api import types +from pyrogram.errors import PeerIdInvalid from ..object import Object from ...ext.utils import encode @@ -58,7 +59,10 @@ class ChatPhoto(Object): loc_small = chat_photo.photo_small loc_big = chat_photo.photo_big - peer = client.resolve_peer(peer_id) + try: + peer = client.resolve_peer(peer_id) + except PeerIdInvalid: + return None if isinstance(peer, types.InputPeerUser): peer_id = peer.user_id