From 4661fb035b3122e01522b0122ae994d9c5c91691 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:17:42 +0200 Subject: [PATCH 01/20] Refactor Poll types and methods to reflect Bot API 4.2 docs --- pyrogram/client/methods/messages/__init__.py | 4 +- .../client/methods/messages/retract_vote.py | 13 ++--- pyrogram/client/methods/messages/send_poll.py | 4 +- .../messages/{close_poll.py => stop_poll.py} | 28 ++++++---- pyrogram/client/methods/messages/vote_poll.py | 14 ++--- .../client/types/messages_and_media/poll.py | 54 ++++++++++--------- .../types/messages_and_media/poll_option.py | 21 ++++---- pyrogram/client/types/pyrogram_type.py | 2 +- 8 files changed, 74 insertions(+), 66 deletions(-) rename pyrogram/client/methods/messages/{close_poll.py => stop_poll.py} (71%) diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index dde50b7b..d26c51cc 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .close_poll import ClosePoll +from .stop_poll import StopPoll from .delete_messages import DeleteMessages from .download_media import DownloadMedia from .edit_message_caption import EditMessageCaption @@ -72,7 +72,7 @@ class Messages( SendVoice, SendPoll, VotePoll, - ClosePoll, + StopPoll, RetractVote, DownloadMedia, IterHistory, diff --git a/pyrogram/client/methods/messages/retract_vote.py b/pyrogram/client/methods/messages/retract_vote.py index 8fa8996c..ce8a0140 100644 --- a/pyrogram/client/methods/messages/retract_vote.py +++ b/pyrogram/client/methods/messages/retract_vote.py @@ -18,6 +18,7 @@ from typing import Union +import pyrogram from pyrogram.api import functions from pyrogram.client.ext import BaseClient @@ -26,8 +27,8 @@ class RetractVote(BaseClient): def retract_vote( self, chat_id: Union[int, str], - message_id: id - ) -> bool: + message_id: int + ) -> "pyrogram.Poll": """Use this method to retract your vote in a poll. Args: @@ -37,15 +38,15 @@ class RetractVote(BaseClient): For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): - Unique poll message identifier inside this chat. + Identifier of the original message with the poll. Returns: - On success, True is returned. + On success, the :obj:`Poll ` with the retracted vote is returned. Raises: :class:`RPCError ` in case of a Telegram RPC error. """ - self.send( + r = self.send( functions.messages.SendVote( peer=self.resolve_peer(chat_id), msg_id=message_id, @@ -53,4 +54,4 @@ class RetractVote(BaseClient): ) ) - return True + return pyrogram.Poll._parse(self, r.updates[0]) diff --git a/pyrogram/client/methods/messages/send_poll.py b/pyrogram/client/methods/messages/send_poll.py index 13e55b08..6b4e227a 100644 --- a/pyrogram/client/methods/messages/send_poll.py +++ b/pyrogram/client/methods/messages/send_poll.py @@ -47,10 +47,10 @@ class SendPoll(BaseClient): For a contact that exists in your Telegram address book you can use his phone number (str). question (``str``): - The poll question, as string. + Poll question, 1-255 characters. options (List of ``str``): - The poll options, as list of strings (2 to 10 options are allowed). + List of answer options, 2-10 strings 1-100 characters each. disable_notification (``bool``, *optional*): Sends the message silently. diff --git a/pyrogram/client/methods/messages/close_poll.py b/pyrogram/client/methods/messages/stop_poll.py similarity index 71% rename from pyrogram/client/methods/messages/close_poll.py rename to pyrogram/client/methods/messages/stop_poll.py index 1b1164c2..a5a4ecc8 100644 --- a/pyrogram/client/methods/messages/close_poll.py +++ b/pyrogram/client/methods/messages/stop_poll.py @@ -18,19 +18,21 @@ from typing import Union +import pyrogram from pyrogram.api import functions, types from pyrogram.client.ext import BaseClient -class ClosePoll(BaseClient): - def close_poll( +class StopPoll(BaseClient): + def stop_poll( self, chat_id: Union[int, str], - message_id: id - ) -> bool: - """Use this method to close (stop) a poll. + message_id: int, + reply_markup: "pyrogram.InlineKeyboardMarkup" = None + ) -> "pyrogram.Poll": + """Use this method to stop a poll which was sent by you. - Closed polls can't be reopened and nobody will be able to vote in it anymore. + Stopped polls can't be reopened and nobody will be able to vote in it anymore. Args: chat_id (``int`` | ``str``): @@ -39,17 +41,20 @@ class ClosePoll(BaseClient): For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): - Unique poll message identifier inside this chat. + Identifier of the original message with the poll. + + reply_markup (:obj:`InlineKeyboardMarkup`, *optional*): + An InlineKeyboardMarkup object. Returns: - On success, True is returned. + On success, the stopped :obj:`Poll ` with the final results is returned. Raises: :class:`RPCError ` in case of a Telegram RPC error. """ poll = self.get_messages(chat_id, message_id).poll - self.send( + r = self.send( functions.messages.EditMessage( peer=self.resolve_peer(chat_id), id=message_id, @@ -60,8 +65,9 @@ class ClosePoll(BaseClient): question="", answers=[] ) - ) + ), + reply_markup=reply_markup.write() if reply_markup else None ) ) - return True + return pyrogram.Poll._parse(self, r.updates[0]) diff --git a/pyrogram/client/methods/messages/vote_poll.py b/pyrogram/client/methods/messages/vote_poll.py index 2a9de874..58f21a6c 100644 --- a/pyrogram/client/methods/messages/vote_poll.py +++ b/pyrogram/client/methods/messages/vote_poll.py @@ -18,6 +18,7 @@ from typing import Union +import pyrogram from pyrogram.api import functions from pyrogram.client.ext import BaseClient @@ -28,7 +29,7 @@ class VotePoll(BaseClient): chat_id: Union[int, str], message_id: id, option: int - ) -> bool: + ) -> "pyrogram.Poll": """Use this method to vote a poll. Args: @@ -38,25 +39,26 @@ class VotePoll(BaseClient): For a contact that exists in your Telegram address book you can use his phone number (str). message_id (``int``): - Unique poll message identifier inside this chat. + Identifier of the original message with the poll. option (``int``): Index of the poll option you want to vote for (0 to 9). Returns: - On success, True is returned. + On success, the :obj:`Poll ` with the chosen option is returned. Raises: :class:`RPCError ` in case of a Telegram RPC error. """ + poll = self.get_messages(chat_id, message_id).poll - self.send( + r = self.send( functions.messages.SendVote( peer=self.resolve_peer(chat_id), msg_id=message_id, - options=[poll.options[option].data] + options=[poll.options[option]._data] ) ) - return True + return pyrogram.Poll._parse(self, r.updates[0]) diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/client/types/messages_and_media/poll.py index 68667334..dfe7daa9 100644 --- a/pyrogram/client/types/messages_and_media/poll.py +++ b/pyrogram/client/types/messages_and_media/poll.py @@ -29,78 +29,80 @@ class Poll(PyrogramType): Args: id (``int``): - The poll id in this chat. - - closed (``bool``): - Whether the poll is closed or not. + Unique poll identifier. question (``str``): - Poll question. + Poll question, 1-255 characters. options (List of :obj:`PollOption`): - The available poll options. + List of poll options. + + is_closed (``bool``): + True, if the poll is closed. total_voters (``int``): - Total amount of voters for this poll. + Total count of voters for this poll. - option_chosen (``int``, *optional*): - The index of your chosen option (in case you voted already), None otherwise. + chosen_option (``int``, *optional*): + Index of your chosen option (0-9), None in case you haven't voted yet. """ - __slots__ = ["id", "closed", "question", "options", "total_voters", "option_chosen"] + __slots__ = ["id", "question", "options", "is_closed", "total_voters", "chosen_option"] def __init__( self, *, client: "pyrogram.client.ext.BaseClient", id: int, - closed: bool, question: str, options: List[PollOption], + is_closed: bool, total_voters: int, - option_chosen: int = None + chosen_option: int = None ): super().__init__(client) self.id = id - self.closed = closed self.question = question self.options = options + self.is_closed = is_closed self.total_voters = total_voters - self.option_chosen = option_chosen + self.chosen_option = chosen_option @staticmethod def _parse(client, media_poll: types.MessageMediaPoll) -> "Poll": poll = media_poll.poll results = media_poll.results.results total_voters = media_poll.results.total_voters - option_chosen = None + chosen_option = None options = [] for i, answer in enumerate(poll.answers): - voters = 0 + voter_count = 0 if results: result = results[i] - voters = result.voters + voter_count = result.voters if result.chosen: - option_chosen = i + chosen_option = i - options.append(PollOption( - text=answer.text, - voters=voters, - data=answer.option, - client=client - )) + options.append( + PollOption( + text=answer.text, + voter_count=voter_count, + data=answer.option, + client=client + ) + ) return Poll( id=poll.id, - closed=poll.closed, question=poll.question, options=options, + is_closed=poll.closed, total_voters=total_voters, - option_chosen=option_chosen, + chosen_option=chosen_option, client=client ) diff --git a/pyrogram/client/types/messages_and_media/poll_option.py b/pyrogram/client/types/messages_and_media/poll_option.py index c45c1db2..4b32623a 100644 --- a/pyrogram/client/types/messages_and_media/poll_option.py +++ b/pyrogram/client/types/messages_and_media/poll_option.py @@ -21,32 +21,29 @@ from ..pyrogram_type import PyrogramType class PollOption(PyrogramType): - """This object represents a Poll Option. + """This object contains information about one answer option in a poll. Args: text (``str``): - Text of the poll option. + Option text, 1-100 characters. - voters (``int``): - The number of users who voted this option. - It will be 0 until you vote for the poll. - - data (``bytes``): - Unique data that identifies this option among all the other options in a poll. + voter_count (``int``): + Number of users that voted for this option. + Equals to 0 until you vote. """ - __slots__ = ["text", "voters", "data"] + __slots__ = ["text", "voter_count", "_data"] def __init__( self, *, client: "pyrogram.client.ext.BaseClient", text: str, - voters: int, + voter_count: int, data: bytes ): super().__init__(client) self.text = text - self.voters = voters - self.data = data + self.voter_count = voter_count + self._data = data # Hidden diff --git a/pyrogram/client/types/pyrogram_type.py b/pyrogram/client/types/pyrogram_type.py index af828926..5f757d43 100644 --- a/pyrogram/client/types/pyrogram_type.py +++ b/pyrogram/client/types/pyrogram_type.py @@ -51,7 +51,7 @@ def default(o: PyrogramType): return remove_none( OrderedDict( [("_", "pyrogram." + o.__class__.__name__)] - + [i for i in content.items()] + + [i for i in content.items() if not i[0].startswith("_")] ) ) except AttributeError: From 22a7e338ff418f57d12ace8ca4f650a2e02c8f4c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:18:44 +0200 Subject: [PATCH 02/20] Fetch the pinned message in own chat (saved messages) --- pyrogram/client/types/user_and_chats/chat.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyrogram/client/types/user_and_chats/chat.py b/pyrogram/client/types/user_and_chats/chat.py index a13f8a2b..1d4369d4 100644 --- a/pyrogram/client/types/user_and_chats/chat.py +++ b/pyrogram/client/types/user_and_chats/chat.py @@ -185,6 +185,12 @@ class Chat(PyrogramType): if isinstance(chat_full, types.UserFull): parsed_chat = Chat._parse_user_chat(client, chat_full.user) parsed_chat.description = chat_full.about + + if chat_full.pinned_msg_id: + parsed_chat.pinned_message = client.get_messages( + parsed_chat.id, + message_ids=chat_full.pinned_msg_id + ) else: full_chat = chat_full.full_chat chat = None From ebacefb6e039c4a16b0c2993c6cfb9da705328bf Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:33:45 +0200 Subject: [PATCH 03/20] Increase media thumbnail size limit --- pyrogram/client/methods/messages/send_animation.py | 2 +- pyrogram/client/methods/messages/send_audio.py | 2 +- pyrogram/client/methods/messages/send_document.py | 2 +- pyrogram/client/methods/messages/send_video.py | 2 +- pyrogram/client/methods/messages/send_video_note.py | 2 +- .../client/types/input_media/input_media_animation.py | 2 +- pyrogram/client/types/input_media/input_media_audio.py | 2 +- .../client/types/input_media/input_media_document.py | 2 +- pyrogram/client/types/input_media/input_media_video.py | 2 +- pyrogram/client/types/messages_and_media/message.py | 10 +++++----- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py index 798d236d..c8da7297 100644 --- a/pyrogram/client/methods/messages/send_animation.py +++ b/pyrogram/client/methods/messages/send_animation.py @@ -83,7 +83,7 @@ class SendAnimation(BaseClient): thumb (``str``, *optional*): Thumbnail of the animation file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/client/methods/messages/send_audio.py index d514b737..0ef2aef3 100644 --- a/pyrogram/client/methods/messages/send_audio.py +++ b/pyrogram/client/methods/messages/send_audio.py @@ -85,7 +85,7 @@ class SendAudio(BaseClient): thumb (``str``, *optional*): Thumbnail of the music file album cover. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py index a36a0fbb..ad47d38c 100644 --- a/pyrogram/client/methods/messages/send_document.py +++ b/pyrogram/client/methods/messages/send_document.py @@ -63,7 +63,7 @@ class SendDocument(BaseClient): thumb (``str``, *optional*): Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/client/methods/messages/send_video.py index 08d8b7ab..c9456858 100644 --- a/pyrogram/client/methods/messages/send_video.py +++ b/pyrogram/client/methods/messages/send_video.py @@ -84,7 +84,7 @@ class SendVideo(BaseClient): thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. supports_streaming (``bool``, *optional*): diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/client/methods/messages/send_video_note.py index 4844dd65..19b35256 100644 --- a/pyrogram/client/methods/messages/send_video_note.py +++ b/pyrogram/client/methods/messages/send_video_note.py @@ -69,7 +69,7 @@ class SendVideoNote(BaseClient): thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): diff --git a/pyrogram/client/types/input_media/input_media_animation.py b/pyrogram/client/types/input_media/input_media_animation.py index e77499b5..6c06df7b 100644 --- a/pyrogram/client/types/input_media/input_media_animation.py +++ b/pyrogram/client/types/input_media/input_media_animation.py @@ -31,7 +31,7 @@ class InputMediaAnimation(InputMedia): thumb (``str``, *optional*): Thumbnail of the animation file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): diff --git a/pyrogram/client/types/input_media/input_media_audio.py b/pyrogram/client/types/input_media/input_media_audio.py index e8f1c257..6b7659fe 100644 --- a/pyrogram/client/types/input_media/input_media_audio.py +++ b/pyrogram/client/types/input_media/input_media_audio.py @@ -32,7 +32,7 @@ class InputMediaAudio(InputMedia): thumb (``str``, *optional*): Thumbnail of the music file album cover. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): diff --git a/pyrogram/client/types/input_media/input_media_document.py b/pyrogram/client/types/input_media/input_media_document.py index 9391e7d8..a5d36261 100644 --- a/pyrogram/client/types/input_media/input_media_document.py +++ b/pyrogram/client/types/input_media/input_media_document.py @@ -31,7 +31,7 @@ class InputMediaDocument(InputMedia): thumb (``str``): Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): diff --git a/pyrogram/client/types/input_media/input_media_video.py b/pyrogram/client/types/input_media/input_media_video.py index 5c918f13..27d166bd 100644 --- a/pyrogram/client/types/input_media/input_media_video.py +++ b/pyrogram/client/types/input_media/input_media_video.py @@ -33,7 +33,7 @@ class InputMediaVideo(InputMedia): thumb (``str``): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index fc2cb8fb..1ad00a7f 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -795,7 +795,7 @@ class Message(PyrogramType, Update): thumb (``str``, *optional*): Thumbnail of the animation file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): @@ -930,7 +930,7 @@ class Message(PyrogramType, Update): thumb (``str``, *optional*): Thumbnail of the music file album cover. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): @@ -1257,7 +1257,7 @@ class Message(PyrogramType, Update): thumb (``str``, *optional*): Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. caption (``str``, *optional*): @@ -2064,7 +2064,7 @@ class Message(PyrogramType, Update): thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. supports_streaming (``bool``, *optional*): @@ -2189,7 +2189,7 @@ class Message(PyrogramType, Update): thumb (``str``, *optional*): Thumbnail of the video sent. The thumbnail should be in JPEG format and less than 200 KB in size. - A thumbnail's width and height should not exceed 90 pixels. + A thumbnail's width and height should not exceed 320 pixels. Thumbnails can't be reused and can be only uploaded as a new file. disable_notification (``bool``, *optional*): From cbc938931dbe222e3b46e1289b298b36f02e1e3e Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:34:46 +0200 Subject: [PATCH 04/20] Rename forward_from_name to forward_sender_name --- .../client/types/messages_and_media/message.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index 1ad00a7f..de2f51b1 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -79,7 +79,7 @@ class Message(PyrogramType, Update): forward_from (:obj:`User `, *optional*): For forwarded messages, sender of the original message. - forward_from_name (``str``, *optional*): + forward_sender_name (``str``, *optional*): For messages forwarded from users who have hidden their accounts, name of the user. forward_from_chat (:obj:`Chat `, *optional*): @@ -267,7 +267,7 @@ class Message(PyrogramType, Update): # TODO: Add game missing field. Also invoice, successful_payment, connected_website __slots__ = [ - "message_id", "date", "chat", "from_user", "forward_from", "forward_from_name", "forward_from_chat", + "message_id", "date", "chat", "from_user", "forward_from", "forward_sender_name", "forward_from_chat", "forward_from_message_id", "forward_signature", "forward_date", "reply_to_message", "mentioned", "empty", "service", "media", "edit_date", "media_group_id", "author_signature", "text", "entities", "caption_entities", "audio", "document", "photo", "sticker", "animation", "game", "video", "voice", "video_note", "caption", @@ -286,7 +286,7 @@ class Message(PyrogramType, Update): chat: Chat = None, from_user: User = None, forward_from: User = None, - forward_from_name: str = None, + forward_sender_name: str = None, forward_from_chat: Chat = None, forward_from_message_id: int = None, forward_signature: str = None, @@ -348,7 +348,7 @@ class Message(PyrogramType, Update): self.chat = chat self.from_user = from_user self.forward_from = forward_from - self.forward_from_name = forward_from_name + self.forward_sender_name = forward_sender_name self.forward_from_chat = forward_from_chat self.forward_from_message_id = forward_from_message_id self.forward_signature = forward_signature @@ -487,7 +487,7 @@ class Message(PyrogramType, Update): entities = list(filter(lambda x: x is not None, entities)) forward_from = None - forward_from_name = None + forward_sender_name = None forward_from_chat = None forward_from_message_id = None forward_signature = None @@ -501,7 +501,7 @@ class Message(PyrogramType, Update): if forward_header.from_id: forward_from = User._parse(client, users[forward_header.from_id]) elif forward_header.from_name: - forward_from_name = forward_header.from_name + forward_sender_name = forward_header.from_name else: forward_from_chat = Chat._parse_channel_chat(client, chats[forward_header.channel_id]) forward_from_message_id = forward_header.channel_post @@ -607,7 +607,7 @@ class Message(PyrogramType, Update): caption_entities=entities or None if media is not None else None, author_signature=message.post_author, forward_from=forward_from, - forward_from_name=forward_from_name, + forward_sender_name=forward_sender_name, forward_from_chat=forward_from_chat, forward_from_message_id=forward_from_message_id, forward_signature=forward_signature, From 5c638e707e0fe70e3b449ffdbdafd5be3ba8b36a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:48:25 +0200 Subject: [PATCH 05/20] Poll ids are now strings and not integers --- pyrogram/client/types/messages_and_media/poll.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/client/types/messages_and_media/poll.py index dfe7daa9..e0461bba 100644 --- a/pyrogram/client/types/messages_and_media/poll.py +++ b/pyrogram/client/types/messages_and_media/poll.py @@ -28,7 +28,7 @@ class Poll(PyrogramType): """This object represents a Poll. Args: - id (``int``): + id (``str``): Unique poll identifier. question (``str``): @@ -53,7 +53,7 @@ class Poll(PyrogramType): self, *, client: "pyrogram.client.ext.BaseClient", - id: int, + id: str, question: str, options: List[PollOption], is_closed: bool, @@ -98,7 +98,7 @@ class Poll(PyrogramType): ) return Poll( - id=poll.id, + id=str(poll.id), question=poll.question, options=options, is_closed=poll.closed, From 5905f761fa214a459aa66f63630c72b2cd408273 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:50:13 +0200 Subject: [PATCH 06/20] Add PollHandler type and on_poll decorator for handling Poll updates --- pyrogram/client/ext/dispatcher.py | 7 ++- pyrogram/client/handlers/__init__.py | 3 +- pyrogram/client/handlers/poll_handler.py | 48 +++++++++++++++ .../client/methods/decorators/__init__.py | 4 +- pyrogram/client/methods/decorators/on_poll.py | 59 +++++++++++++++++++ .../client/types/messages_and_media/poll.py | 3 +- 6 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 pyrogram/client/handlers/poll_handler.py create mode 100644 pyrogram/client/methods/decorators/on_poll.py diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/client/ext/dispatcher.py index 7552b034..46be47f7 100644 --- a/pyrogram/client/ext/dispatcher.py +++ b/pyrogram/client/ext/dispatcher.py @@ -26,7 +26,7 @@ import pyrogram from pyrogram.api import types from ..handlers import ( CallbackQueryHandler, MessageHandler, DeletedMessagesHandler, - UserStatusHandler, RawUpdateHandler, InlineQueryHandler + UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler ) log = logging.getLogger(__name__) @@ -79,7 +79,10 @@ class Dispatcher: ), (types.UpdateBotInlineQuery,): - lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler) + lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler), + + (types.UpdateMessagePoll,): + lambda upd, usr, cht: (pyrogram.Poll._parse(self.client, upd), PollHandler) } self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} diff --git a/pyrogram/client/handlers/__init__.py b/pyrogram/client/handlers/__init__.py index 5e392949..c88c12fe 100644 --- a/pyrogram/client/handlers/__init__.py +++ b/pyrogram/client/handlers/__init__.py @@ -21,10 +21,11 @@ from .deleted_messages_handler import DeletedMessagesHandler from .disconnect_handler import DisconnectHandler from .inline_query_handler import InlineQueryHandler from .message_handler import MessageHandler +from .poll_handler import PollHandler from .raw_update_handler import RawUpdateHandler from .user_status_handler import UserStatusHandler __all__ = [ "MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler", - "UserStatusHandler", "InlineQueryHandler" + "UserStatusHandler", "InlineQueryHandler", "PollHandler" ] diff --git a/pyrogram/client/handlers/poll_handler.py b/pyrogram/client/handlers/poll_handler.py new file mode 100644 index 00000000..567fcec0 --- /dev/null +++ b/pyrogram/client/handlers/poll_handler.py @@ -0,0 +1,48 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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 .handler import Handler + + +class PollHandler(Handler): + """The Poll handler class. Used to handle polls updates. + + It is intended to be used with :meth:`add_handler() ` + + For a nicer way to register this handler, have a look at the + :meth:`on_poll() ` decorator. + + Args: + callback (``callable``): + Pass a function that will be called when a new poll update arrives. It takes *(client, poll)* + as positional arguments (look at the section below for a detailed description). + + filters (:obj:`Filters `): + Pass one or more filters to allow only a subset of polls to be passed + in your callback function. + + Other parameters: + client (:obj:`Client `): + The Client itself, useful when you want to call other API methods inside the poll handler. + + poll (:obj:`Poll `): + The received poll. + """ + + def __init__(self, callback: callable, filters=None): + super().__init__(callback, filters) diff --git a/pyrogram/client/methods/decorators/__init__.py b/pyrogram/client/methods/decorators/__init__.py index 33f55a3d..2a2861ae 100644 --- a/pyrogram/client/methods/decorators/__init__.py +++ b/pyrogram/client/methods/decorators/__init__.py @@ -21,6 +21,7 @@ from .on_deleted_messages import OnDeletedMessages from .on_disconnect import OnDisconnect from .on_inline_query import OnInlineQuery from .on_message import OnMessage +from .on_poll import OnPoll from .on_raw_update import OnRawUpdate from .on_user_status import OnUserStatus @@ -32,6 +33,7 @@ class Decorators( OnRawUpdate, OnDisconnect, OnUserStatus, - OnInlineQuery + OnInlineQuery, + OnPoll ): pass diff --git a/pyrogram/client/methods/decorators/on_poll.py b/pyrogram/client/methods/decorators/on_poll.py new file mode 100644 index 00000000..56dcd757 --- /dev/null +++ b/pyrogram/client/methods/decorators/on_poll.py @@ -0,0 +1,59 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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 Tuple + +import pyrogram +from pyrogram.client.filters.filter import Filter +from pyrogram.client.handlers.handler import Handler +from ...ext import BaseClient + + +class OnPoll(BaseClient): + def on_poll( + self=None, + filters=None, + group: int = 0 + ) -> callable: + """Use this decorator to automatically register a function for handling poll updates. + This does the same thing as :meth:`add_handler` using the :class:`PollHandler`. + + Args: + filters (:obj:`Filters `): + Pass one or more filters to allow only a subset of polls to be passed + in your function. + + group (``int``, *optional*): + The group identifier, defaults to 0. + """ + + def decorator(func: callable) -> Tuple[Handler, int]: + if isinstance(func, tuple): + func = func[0].callback + + handler = pyrogram.PollHandler(func, filters) + + if isinstance(self, Filter): + return pyrogram.PollHandler(func, self), group if filters is None else filters + + if self is not None: + self.add_handler(handler, group) + + return handler, group + + return decorator diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/client/types/messages_and_media/poll.py index e0461bba..acaf8697 100644 --- a/pyrogram/client/types/messages_and_media/poll.py +++ b/pyrogram/client/types/messages_and_media/poll.py @@ -22,9 +22,10 @@ import pyrogram from pyrogram.api import types from .poll_option import PollOption from ..pyrogram_type import PyrogramType +from ..update import Update -class Poll(PyrogramType): +class Poll(PyrogramType, Update): """This object represents a Poll. Args: From d6d2923e34381a90e62a3779e82532fc7923ef21 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 20:52:00 +0200 Subject: [PATCH 07/20] Add missing Poll docstrings in Message --- pyrogram/client/types/messages_and_media/message.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index de2f51b1..8dc05661 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -186,6 +186,9 @@ class Message(PyrogramType, Update): web page preview. In future versions this property could turn into a full web page object that contains more details. + poll (:obj:`Poll `, *optional*): + Message is a native poll, information about the poll. + new_chat_members (List of :obj:`User `, *optional*): New members that were added to the group or supergroup and information about them (the bot itself may be one of these members). From bcef74c574d799aa07d75f39ece5d271b21c6477 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 21:00:19 +0200 Subject: [PATCH 08/20] Update .gitignore to ignore the generated RPC error classes The "errors" package has been moved to make it simpler to import --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bfc2fb83..0b1a0699 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ config.ini # Pyrogram generated code -pyrogram/api/errors/exceptions/ +pyrogram/errors/exceptions/ pyrogram/api/functions/ pyrogram/api/types/ pyrogram/api/all.py From b056aa8d7f1f484aaffffc966a52b48094f8cfbe Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 14 Apr 2019 21:04:34 +0200 Subject: [PATCH 09/20] Add the field is_member to the ChatMember type This can be used to find whether a restricted user is a member of the chat at the moment of the request. --- .../types/user_and_chats/chat_member.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pyrogram/client/types/user_and_chats/chat_member.py b/pyrogram/client/types/user_and_chats/chat_member.py index 35911210..9ccf9314 100644 --- a/pyrogram/client/types/user_and_chats/chat_member.py +++ b/pyrogram/client/types/user_and_chats/chat_member.py @@ -36,6 +36,9 @@ class ChatMember(PyrogramType): date (``int``, *optional*): Date when the user joined, unix time. Not available for creator. + is_member (``bool``, *optional*): + Restricted only. True, if the user is a member of the chat at the moment of the request. + invited_by (:obj:`User `, *optional*): Administrators and self member only. Information about the user who invited this member. In case the user joined by himself this will be the same as "user". @@ -51,7 +54,7 @@ class ChatMember(PyrogramType): Information about the member permissions. """ - __slots__ = ["user", "status", "date", "invited_by", "promoted_by", "restricted_by", "permissions"] + __slots__ = ["user", "status", "date", "is_member", "invited_by", "promoted_by", "restricted_by", "permissions"] def __init__( self, @@ -60,6 +63,7 @@ class ChatMember(PyrogramType): user: "pyrogram.User", status: str, date: int = None, + is_member: bool = None, invited_by: "pyrogram.User" = None, promoted_by: "pyrogram.User" = None, restricted_by: "pyrogram.User" = None, @@ -70,6 +74,7 @@ class ChatMember(PyrogramType): self.user = user self.status = status self.date = date + self.is_member = is_member self.invited_by = invited_by self.promoted_by = promoted_by self.restricted_by = restricted_by @@ -121,14 +126,17 @@ class ChatMember(PyrogramType): ) if isinstance(member, types.ChannelParticipantBanned): + status = ( + "kicked" if member.banned_rights.view_messages + else "left" if member.left + else "restricted" + ) + return ChatMember( user=user, - status=( - "kicked" if member.banned_rights.view_messages - else "left" if member.left - else "restricted" - ), + status=status, date=member.date, + is_member=not member.left if status == "restricted" else None, restricted_by=pyrogram.User._parse(client, users[member.kicked_by]), permissions=pyrogram.ChatPermissions._parse(member), client=client From 80081a29b48e24d3bf9dd261bc3594b931f513e6 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Tue, 30 Apr 2019 14:43:57 +0200 Subject: [PATCH 10/20] Add supports_streaming attribute to the Video type --- .../client/types/messages_and_media/video.py | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/pyrogram/client/types/messages_and_media/video.py b/pyrogram/client/types/messages_and_media/video.py index caf34ce9..a45a8f8d 100644 --- a/pyrogram/client/types/messages_and_media/video.py +++ b/pyrogram/client/types/messages_and_media/video.py @@ -50,6 +50,9 @@ class Video(PyrogramType): mime_type (``str``, *optional*): Mime type of a file as defined by sender. + supports_streaming (``bool``, *optional*): + True, if the video was uploaded with streaming support. + file_size (``int``, *optional*): File size. @@ -57,7 +60,10 @@ class Video(PyrogramType): Date the video was sent in Unix time. """ - __slots__ = ["file_id", "thumb", "file_name", "mime_type", "file_size", "date", "width", "height", "duration"] + __slots__ = [ + "file_id", "width", "height", "duration", "thumb", "file_name", "mime_type", "supports_streaming", "file_size", + "date" + ] def __init__( self, @@ -70,20 +76,22 @@ class Video(PyrogramType): thumb: PhotoSize = None, file_name: str = None, mime_type: str = None, + supports_streaming: bool = None, file_size: int = None, date: int = None ): super().__init__(client) self.file_id = file_id - self.thumb = thumb - self.file_name = file_name - self.mime_type = mime_type - self.file_size = file_size - self.date = date self.width = width self.height = height self.duration = duration + self.thumb = thumb + self.file_name = file_name + self.mime_type = mime_type + self.supports_streaming = supports_streaming + self.file_size = file_size + self.date = date @staticmethod def _parse(client, video: types.Document, video_attributes: types.DocumentAttributeVideo, @@ -102,9 +110,10 @@ class Video(PyrogramType): height=video_attributes.h, duration=video_attributes.duration, thumb=PhotoSize._parse(client, video.thumbs), - mime_type=video.mime_type, - file_size=video.size, file_name=file_name, + mime_type=video.mime_type, + supports_streaming=video_attributes.supports_streaming, + file_size=video.size, date=video.date, client=client ) From 58482919ba826b36d5e7b60e8e9203c4f715093a Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 5 May 2019 12:21:20 +0200 Subject: [PATCH 11/20] Make is_member field actually working --- pyrogram/client/types/user_and_chats/chat_member.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/pyrogram/client/types/user_and_chats/chat_member.py b/pyrogram/client/types/user_and_chats/chat_member.py index 9ccf9314..046d2ebc 100644 --- a/pyrogram/client/types/user_and_chats/chat_member.py +++ b/pyrogram/client/types/user_and_chats/chat_member.py @@ -126,17 +126,11 @@ class ChatMember(PyrogramType): ) if isinstance(member, types.ChannelParticipantBanned): - status = ( - "kicked" if member.banned_rights.view_messages - else "left" if member.left - else "restricted" - ) - return ChatMember( user=user, - status=status, + status="kicked" if member.banned_rights.view_messages else "restricted", date=member.date, - is_member=not member.left if status == "restricted" else None, + is_member=not member.left, restricted_by=pyrogram.User._parse(client, users[member.kicked_by]), permissions=pyrogram.ChatPermissions._parse(member), client=client From bfda5852b6ba587709b24c9b0423ec77cb498db3 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 5 May 2019 15:44:28 +0200 Subject: [PATCH 12/20] Hint the return type of get_history --- pyrogram/client/methods/messages/get_history.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/methods/messages/get_history.py b/pyrogram/client/methods/messages/get_history.py index fda8f11f..1953fabc 100644 --- a/pyrogram/client/methods/messages/get_history.py +++ b/pyrogram/client/methods/messages/get_history.py @@ -37,7 +37,7 @@ class GetHistory(BaseClient): offset_id: int = 0, offset_date: int = 0, reverse: bool = False - ): + ) -> "pyrogram.Messages": """Use this method to retrieve a chunk of the history of a chat. You can get up to 100 messages at once. From 6f2c625cd1c3c769b5db2b2af519e7515a8fd930 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 5 May 2019 15:44:53 +0200 Subject: [PATCH 13/20] Handle minified poll updates --- pyrogram/client/ext/dispatcher.py | 2 +- .../client/types/messages_and_media/poll.py | 37 +++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pyrogram/client/ext/dispatcher.py b/pyrogram/client/ext/dispatcher.py index 46be47f7..1004095b 100644 --- a/pyrogram/client/ext/dispatcher.py +++ b/pyrogram/client/ext/dispatcher.py @@ -82,7 +82,7 @@ class Dispatcher: lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler), (types.UpdateMessagePoll,): - lambda upd, usr, cht: (pyrogram.Poll._parse(self.client, upd), PollHandler) + lambda upd, usr, cht: (pyrogram.Poll._parse_update(self.client, upd), PollHandler) } self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple} diff --git a/pyrogram/client/types/messages_and_media/poll.py b/pyrogram/client/types/messages_and_media/poll.py index acaf8697..fa68f669 100644 --- a/pyrogram/client/types/messages_and_media/poll.py +++ b/pyrogram/client/types/messages_and_media/poll.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from typing import List +from typing import List, Union import pyrogram from pyrogram.api import types @@ -71,12 +71,11 @@ class Poll(PyrogramType, Update): self.chosen_option = chosen_option @staticmethod - def _parse(client, media_poll: types.MessageMediaPoll) -> "Poll": + def _parse(client, media_poll: Union[types.MessageMediaPoll, types.UpdateMessagePoll]) -> "Poll": poll = media_poll.poll results = media_poll.results.results total_voters = media_poll.results.total_voters chosen_option = None - options = [] for i, answer in enumerate(poll.answers): @@ -107,3 +106,35 @@ class Poll(PyrogramType, Update): chosen_option=chosen_option, client=client ) + + @staticmethod + def _parse_update(client, update: types.UpdateMessagePoll): + if update.poll is not None: + return Poll._parse(client, update) + + results = update.results.results + chosen_option = None + options = [] + + for i, result in enumerate(results): + if result.chosen: + chosen_option = i + + options.append( + PollOption( + text="", + voter_count=result.voters, + data=result.option, + client=client + ) + ) + + return Poll( + id=str(update.poll_id), + question="", + options=options, + is_closed=False, + total_voters=update.results.total_voters, + chosen_option=chosen_option, + client=client + ) From 01f0af6bb033fa8468bc495d5afb4b3009288037 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 16:36:57 +0200 Subject: [PATCH 14/20] Increase OFFLINE_SLEEP to 15 minutes This avoid frequent dialogs fetch while debugging with user accounts --- pyrogram/client/ext/base_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index b4bfbd6b..ee7b2c24 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -50,7 +50,7 @@ class BaseClient: DIALOGS_AT_ONCE = 100 UPDATES_WORKERS = 1 DOWNLOAD_WORKERS = 1 - OFFLINE_SLEEP = 300 + OFFLINE_SLEEP = 900 WORKERS = 4 WORKDIR = "." CONFIG_FILE = "./config.ini" From 95ef9a64deb01ea4ca523a42f9d674079387b96c Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 16:40:07 +0200 Subject: [PATCH 15/20] Fix small typos --- docs/source/pyrogram/Client.rst | 2 +- pyrogram/client/types/user_and_chats/dialog.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index dcf8bb79..3a7c231f 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -69,7 +69,7 @@ Messages iter_history send_poll vote_poll - close_poll + stop_poll retract_vote download_media diff --git a/pyrogram/client/types/user_and_chats/dialog.py b/pyrogram/client/types/user_and_chats/dialog.py index 1bbd3b4b..d406d783 100644 --- a/pyrogram/client/types/user_and_chats/dialog.py +++ b/pyrogram/client/types/user_and_chats/dialog.py @@ -34,7 +34,7 @@ class Dialog(PyrogramType): The last message sent in the dialog at this time. unread_messages_count (``int``): - Amount of unread messages in this dialogs. + Amount of unread messages in this dialog. unread_mentions_count (``int``): Amount of unread messages containing a mention in this dialog. From e80eebc23494ecd558a4067fd0b6e3176cbc0261 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 16:44:50 +0200 Subject: [PATCH 16/20] Add get_history_count method --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/messages/__init__.py | 6 +- .../methods/messages/get_history_count.py | 84 +++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 pyrogram/client/methods/messages/get_history_count.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 3a7c231f..59293273 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -66,6 +66,7 @@ Messages delete_messages get_messages get_history + get_history_count iter_history send_poll vote_poll diff --git a/pyrogram/client/methods/messages/__init__.py b/pyrogram/client/methods/messages/__init__.py index d26c51cc..e843aa7c 100644 --- a/pyrogram/client/methods/messages/__init__.py +++ b/pyrogram/client/methods/messages/__init__.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with Pyrogram. If not, see . -from .stop_poll import StopPoll from .delete_messages import DeleteMessages from .download_media import DownloadMedia from .edit_message_caption import EditMessageCaption @@ -25,6 +24,7 @@ from .edit_message_reply_markup import EditMessageReplyMarkup from .edit_message_text import EditMessageText from .forward_messages import ForwardMessages from .get_history import GetHistory +from .get_history_count import GetHistoryCount from .get_messages import GetMessages from .iter_history import IterHistory from .retract_vote import RetractVote @@ -44,6 +44,7 @@ from .send_venue import SendVenue from .send_video import SendVideo from .send_video_note import SendVideoNote from .send_voice import SendVoice +from .stop_poll import StopPoll from .vote_poll import VotePoll @@ -76,6 +77,7 @@ class Messages( RetractVote, DownloadMedia, IterHistory, - SendCachedMedia + SendCachedMedia, + GetHistoryCount ): pass diff --git a/pyrogram/client/methods/messages/get_history_count.py b/pyrogram/client/methods/messages/get_history_count.py new file mode 100644 index 00000000..046ec095 --- /dev/null +++ b/pyrogram/client/methods/messages/get_history_count.py @@ -0,0 +1,84 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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 logging +import time +from typing import Union + +from pyrogram.api import types, functions +from pyrogram.client.ext import BaseClient +from pyrogram.errors import FloodWait + +log = logging.getLogger(__name__) + + +class GetHistoryCount(BaseClient): + def get_history_count( + self, + chat_id: Union[int, str] + ) -> int: + """Use this method to get the total count of messages in a chat. + + .. note:: + + Due to Telegram latest internal changes, the server can't reliably find anymore the total count of messages + a **private** or a **basic group** chat has with a single method call. To overcome this limitation, Pyrogram + has to iterate over all the messages. Channels and supergroups are not affected by this limitation. + + Args: + chat_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + + Returns: + On success, an integer is returned. + + Raises: + :class:`RPCError ` in case of a Telegram RPC error. + """ + + peer = self.resolve_peer(chat_id) + + if not isinstance(peer, types.InputPeerChannel): + offset = 0 + limit = 100 + + while True: + try: + r = self.send( + functions.messages.GetHistory( + peer=peer, + offset_id=1, + offset_date=0, + add_offset=-offset - limit, + limit=limit, + max_id=0, + min_id=0, + hash=0 + ) + ) + except FloodWait as e: + log.warning("Sleeping for {}s".format(e.x)) + time.sleep(e.x) + continue + + if not r.messages: + return offset + + offset += len(r.messages) + + return self.get_history(chat_id=chat_id, limit=1).total_count From 4e77ead18171d6c692d57737c88dbf2f00ea007b Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 16:54:50 +0200 Subject: [PATCH 17/20] Add get_dialogs_count method --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/chats/__init__.py | 4 +- .../client/methods/chats/get_dialogs_count.py | 51 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 pyrogram/client/methods/chats/get_dialogs_count.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index 59293273..e704cc1e 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -101,6 +101,7 @@ Chats iter_chat_members get_dialogs iter_dialogs + get_dialogs_count restrict_chat update_chat_username diff --git a/pyrogram/client/methods/chats/__init__.py b/pyrogram/client/methods/chats/__init__.py index c708453f..8db44abe 100644 --- a/pyrogram/client/methods/chats/__init__.py +++ b/pyrogram/client/methods/chats/__init__.py @@ -39,6 +39,7 @@ from .set_chat_title import SetChatTitle from .unban_chat_member import UnbanChatMember from .unpin_chat_message import UnpinChatMessage from .update_chat_username import UpdateChatUsername +from .get_dialogs_count import GetDialogsCount class Chats( @@ -64,6 +65,7 @@ class Chats( IterDialogs, IterChatMembers, UpdateChatUsername, - RestrictChat + RestrictChat, + GetDialogsCount ): pass diff --git a/pyrogram/client/methods/chats/get_dialogs_count.py b/pyrogram/client/methods/chats/get_dialogs_count.py new file mode 100644 index 00000000..1ba6895f --- /dev/null +++ b/pyrogram/client/methods/chats/get_dialogs_count.py @@ -0,0 +1,51 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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 pyrogram.api import functions, types +from ...ext import BaseClient + + +class GetDialogsCount(BaseClient): + def get_dialogs_count(self, pinned_only: bool = False) -> int: + """Use this method to get the total count of your dialogs. + + pinned_only (``bool``, *optional*): + Pass True if you want to count only pinned dialogs. + Defaults to False. + + Returns: + On success, an integer is returned. + + Raises: + :class:`RPCError ` in case of a Telegram RPC error. + """ + + if pinned_only: + return len(self.send(functions.messages.GetPinnedDialogs()).dialogs) + else: + r = self.send( + functions.messages.GetDialogs( + offset_date=0, + offset_id=0, + offset_peer=types.InputPeerEmpty(), + limit=1, + hash=0 + ) + ) + + return r.count From e8e0c16daf1b4f30370b02969d6620d1e6a60317 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 17:00:09 +0200 Subject: [PATCH 18/20] Add get_contacts_count method --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/contacts/__init__.py | 4 ++- .../methods/contacts/get_contacts_count.py | 34 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 pyrogram/client/methods/contacts/get_contacts_count.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index e704cc1e..e3ef2d69 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -126,6 +126,7 @@ Contacts add_contacts get_contacts + get_contacts_count delete_contacts Password diff --git a/pyrogram/client/methods/contacts/__init__.py b/pyrogram/client/methods/contacts/__init__.py index ab9ae6ef..a966d10a 100644 --- a/pyrogram/client/methods/contacts/__init__.py +++ b/pyrogram/client/methods/contacts/__init__.py @@ -19,11 +19,13 @@ from .add_contacts import AddContacts from .delete_contacts import DeleteContacts from .get_contacts import GetContacts +from .get_contacts_count import GetContactsCount class Contacts( GetContacts, DeleteContacts, - AddContacts + AddContacts, + GetContactsCount ): pass diff --git a/pyrogram/client/methods/contacts/get_contacts_count.py b/pyrogram/client/methods/contacts/get_contacts_count.py new file mode 100644 index 00000000..b41b27b8 --- /dev/null +++ b/pyrogram/client/methods/contacts/get_contacts_count.py @@ -0,0 +1,34 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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 pyrogram.api import functions +from ...ext import BaseClient + + +class GetContactsCount(BaseClient): + def get_contacts_count(self) -> int: + """Use this method to get the total count of contacts from your Telegram address book. + + Returns: + On success, an integer is returned. + + Raises: + :class:`RPCError ` in case of a Telegram RPC error. + """ + + return len(self.send(functions.contacts.GetContacts(hash=0)).contacts) From 08554633ce90a01b29931156c555760bd3567a9b Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 17:07:41 +0200 Subject: [PATCH 19/20] Add get_user_profile_photos_count method --- docs/source/pyrogram/Client.rst | 1 + pyrogram/client/methods/users/__init__.py | 4 +- .../users/get_user_profile_photos_count.py | 54 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 pyrogram/client/methods/users/get_user_profile_photos_count.py diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index e3ef2d69..5adf4956 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -114,6 +114,7 @@ Users get_me get_users get_user_profile_photos + get_user_profile_photos_count set_user_profile_photo delete_user_profile_photos update_username diff --git a/pyrogram/client/methods/users/__init__.py b/pyrogram/client/methods/users/__init__.py index f8c39650..d67a18bd 100644 --- a/pyrogram/client/methods/users/__init__.py +++ b/pyrogram/client/methods/users/__init__.py @@ -19,6 +19,7 @@ from .delete_user_profile_photos import DeleteUserProfilePhotos from .get_me import GetMe from .get_user_profile_photos import GetUserProfilePhotos +from .get_user_profile_photos_count import GetUserProfilePhotosCount from .get_users import GetUsers from .set_user_profile_photo import SetUserProfilePhoto from .update_username import UpdateUsername @@ -30,6 +31,7 @@ class Users( DeleteUserProfilePhotos, GetUsers, GetMe, - UpdateUsername + UpdateUsername, + GetUserProfilePhotosCount ): pass diff --git a/pyrogram/client/methods/users/get_user_profile_photos_count.py b/pyrogram/client/methods/users/get_user_profile_photos_count.py new file mode 100644 index 00000000..fdb81790 --- /dev/null +++ b/pyrogram/client/methods/users/get_user_profile_photos_count.py @@ -0,0 +1,54 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan Tès +# +# 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.api import functions, types +from ...ext import BaseClient + + +class GetUserProfilePhotosCount(BaseClient): + def get_user_profile_photos_count(self, user_id: Union[int, str]) -> int: + """Use this method to get the total count of profile pictures for a user. + + Args: + user_id (``int`` | ``str``): + Unique identifier (int) or username (str) of the target chat. + For your personal cloud (Saved Messages) you can simply use "me" or "self". + For a contact that exists in your Telegram address book you can use his phone number (str). + + Returns: + On success, an integer is returned. + + Raises: + :class:`RPCError ` in case of a Telegram RPC error. + """ + + r = self.send( + functions.photos.GetUserPhotos( + user_id=self.resolve_peer(user_id), + offset=0, + max_id=0, + limit=1 + ) + ) + + if isinstance(r, types.photos.Photos): + return len(r.photos) + else: + return r.count From 692073c856837e1e5e71f174cd4b866d12dd0f90 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Mon, 6 May 2019 17:09:44 +0200 Subject: [PATCH 20/20] Fix get_dialogs_count breaking in case of less than 200 dialogs --- pyrogram/client/methods/chats/get_dialogs_count.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/methods/chats/get_dialogs_count.py b/pyrogram/client/methods/chats/get_dialogs_count.py index 1ba6895f..bf1754ee 100644 --- a/pyrogram/client/methods/chats/get_dialogs_count.py +++ b/pyrogram/client/methods/chats/get_dialogs_count.py @@ -48,4 +48,7 @@ class GetDialogsCount(BaseClient): ) ) - return r.count + if isinstance(r, types.messages.Dialogs): + return len(r.dialogs) + else: + return r.count