From 200ed844fe24333a4ac21f2b98fa0a845a103d04 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 13:02:19 +0100 Subject: [PATCH 1/8] Fix first_name and last_name not being called if they are callable --- pyrogram/client/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 61a3775b..2a3a420d 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -578,13 +578,13 @@ class Client(Methods, BaseClient): if not phone_registered: self.first_name = ( input("First name: ") if self.first_name is None - else str(self.first_name) if callable(self.first_name) + else str(self.first_name()) if callable(self.first_name) else str(self.first_name) ) self.last_name = ( input("Last name: ") if self.last_name is None - else str(self.last_name) if callable(self.last_name) + else str(self.last_name()) if callable(self.last_name) else str(self.last_name) ) From d5ed47f4e963700bc2a9d425e31a86ecce57a1b7 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 13:59:18 +0100 Subject: [PATCH 2/8] Fix Message.download() not working when using the progress callback --- pyrogram/client/types/messages_and_media/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyrogram/client/types/messages_and_media/message.py b/pyrogram/client/types/messages_and_media/message.py index a323898c..badd3689 100644 --- a/pyrogram/client/types/messages_and_media/message.py +++ b/pyrogram/client/types/messages_and_media/message.py @@ -912,7 +912,7 @@ class Message(PyrogramType, Update): else: raise ValueError("The message doesn't contain any keyboard") - def download(self, file_name: str = "", block: bool = True, progress: callable = None, progress_args: tuple = None): + def download(self, file_name: str = "", block: bool = True, progress: callable = None, progress_args: tuple = ()): """Bound method *download* of :obj:`Message `. Use as a shortcut for: From c28b9f9a2cbb9db8602e798bc68cd725f0b9cfd7 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 14:00:03 +0100 Subject: [PATCH 3/8] Add StopTransmission custom exception Useful for stopping up/downloads after they started --- pyrogram/client/ext/base_client.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index aaed5786..7b94ae6e 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -27,6 +27,9 @@ from ...session.internals import MsgId class BaseClient: + class StopTransmission(StopIteration): + pass + APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__) DEVICE_MODEL = "{} {}".format( From 6b63e88de7e42ebfc1aa20433154750d82533ce5 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 14:02:40 +0100 Subject: [PATCH 4/8] Add Client.stop_transmission() method As a wrapper for raise StopTransmission --- pyrogram/client/client.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index 2a3a420d..b8e310a5 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -460,6 +460,12 @@ class Client(Methods, BaseClient): else: self.dispatcher.remove_handler(handler, group) + def stop_transmission(self): + """Use this method to stop downloading or uploading a file. + Must be called inside a progress callback function. + """ + raise Client.StopTransmission + def authorize_bot(self): try: r = self.send( From b37d4dc7ec78d0010c6ab35900244d40649a7299 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 14:03:16 +0100 Subject: [PATCH 5/8] Make get_file and save_file handle StopTransmission errors --- pyrogram/client/client.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index b8e310a5..2912072d 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -1368,6 +1368,8 @@ class Client(Methods, BaseClient): if progress: progress(self, min(file_part * part_size, file_size), file_size, *progress_args) + except Client.StopTransmission: + raise except Exception as e: log.error(e, exc_info=True) else: @@ -1569,7 +1571,8 @@ class Client(Methods, BaseClient): except Exception as e: raise e except Exception as e: - log.error(e, exc_info=True) + if not isinstance(e, Client.StopTransmission): + log.error(e, exc_info=True) try: os.remove(file_name) From 2791600926285043128729c9357473b780fab47e Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 14:12:53 +0100 Subject: [PATCH 6/8] Hint about the returned value in case of stopped downloads --- pyrogram/client/methods/messages/download_media.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyrogram/client/methods/messages/download_media.py b/pyrogram/client/methods/messages/download_media.py index cfdcfce7..181daa14 100644 --- a/pyrogram/client/methods/messages/download_media.py +++ b/pyrogram/client/methods/messages/download_media.py @@ -72,6 +72,7 @@ class DownloadMedia(BaseClient): Returns: On success, the absolute path of the downloaded file as string is returned, None otherwise. + In case the download is deliberately stopped with :meth:`stop_transmission`, None is returned as well. Raises: :class:`Error ` in case of a Telegram RPC error. From 4e02cd23a8564cb6ac8a112684561feaafc8a5ed Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Fri, 11 Jan 2019 14:13:23 +0100 Subject: [PATCH 7/8] Make all send_* methods dealing with files aware of StopTransmission --- .../client/methods/messages/send_animation.py | 136 +++++++++--------- .../client/methods/messages/send_audio.py | 132 ++++++++--------- .../client/methods/messages/send_document.py | 122 ++++++++-------- .../client/methods/messages/send_photo.py | 114 ++++++++------- .../client/methods/messages/send_sticker.py | 118 +++++++-------- .../client/methods/messages/send_video.py | 134 ++++++++--------- .../methods/messages/send_video_note.py | 130 +++++++++-------- .../client/methods/messages/send_voice.py | 130 +++++++++-------- 8 files changed, 524 insertions(+), 492 deletions(-) diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py index 08b69c17..5b27c914 100644 --- a/pyrogram/client/methods/messages/send_animation.py +++ b/pyrogram/client/methods/messages/send_animation.py @@ -45,7 +45,7 @@ class SendAnimation(BaseClient): "pyrogram.ReplyKeyboardRemove", "pyrogram.ForceReply"] = None, progress: callable = None, - progress_args: tuple = ()) -> "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send animation files (animation or H.264/MPEG-4 AVC video without sound). Args: @@ -119,6 +119,7 @@ class SendAnimation(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -126,72 +127,75 @@ class SendAnimation(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(animation): - thumb = None if thumb is None else self.save_file(thumb) - file = self.save_file(animation, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map[".mp4"], - file=file, - thumb=thumb, - attributes=[ - types.DocumentAttributeVideo( - supports_streaming=True, - duration=duration, - w=width, - h=height - ), - types.DocumentAttributeFilename(os.path.basename(animation)), - types.DocumentAttributeAnimated() - ] - ) - elif animation.startswith("http"): - media = types.InputMediaDocumentExternal( - url=animation - ) - else: - try: - decoded = utils.decode(animation) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send audio files. For sending voice messages, use the :obj:`send_voice()` method instead. @@ -121,6 +121,7 @@ class SendAudio(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -128,70 +129,73 @@ class SendAudio(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(audio): - thumb = None if thumb is None else self.save_file(thumb) - file = self.save_file(audio, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map.get("." + audio.split(".")[-1], "audio/mpeg"), - file=file, - thumb=thumb, - attributes=[ - types.DocumentAttributeAudio( - duration=duration, - performer=performer, - title=title - ), - types.DocumentAttributeFilename(os.path.basename(audio)) - ] - ) - elif audio.startswith("http"): - media = types.InputMediaDocumentExternal( - url=audio - ) - else: - try: - decoded = utils.decode(audio) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send general files. Args: @@ -107,6 +107,7 @@ class SendDocument(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -114,65 +115,68 @@ class SendDocument(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(document): - thumb = None if thumb is None else self.save_file(thumb) - file = self.save_file(document, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map.get("." + document.split(".")[-1], "text/plain"), - file=file, - thumb=thumb, - attributes=[ - types.DocumentAttributeFilename(os.path.basename(document)) - ] - ) - elif document.startswith("http"): - media = types.InputMediaDocumentExternal( - url=document - ) - else: - try: - decoded = utils.decode(document) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send photos. Args: @@ -105,6 +105,7 @@ class SendPhoto(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -112,62 +113,65 @@ class SendPhoto(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(photo): - file = self.save_file(photo, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedPhoto( - file=file, - ttl_seconds=ttl_seconds - ) - elif photo.startswith("http"): - media = types.InputMediaPhotoExternal( - url=photo, - ttl_seconds=ttl_seconds - ) - else: - try: - decoded = utils.decode(photo) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send .webp stickers. Args: @@ -89,69 +89,73 @@ class SendSticker(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. """ file = None - if os.path.exists(sticker): - file = self.save_file(sticker, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type="image/webp", - file=file, - attributes=[ - types.DocumentAttributeFilename(os.path.basename(sticker)) - ] - ) - elif sticker.startswith("http"): - media = types.InputMediaDocumentExternal( - url=sticker - ) - else: - try: - decoded = utils.decode(sticker) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send video files. Args: @@ -123,6 +123,7 @@ class SendVideo(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -130,71 +131,74 @@ class SendVideo(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(video): - thumb = None if thumb is None else self.save_file(thumb) - file = self.save_file(video, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map[".mp4"], - file=file, - thumb=thumb, - attributes=[ - types.DocumentAttributeVideo( - supports_streaming=supports_streaming or None, - duration=duration, - w=width, - h=height - ), - types.DocumentAttributeFilename(os.path.basename(video)) - ] - ) - elif video.startswith("http"): - media = types.InputMediaDocumentExternal( - url=video - ) - else: - try: - decoded = utils.decode(video) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send video messages. Args: @@ -105,72 +105,76 @@ class SendVideoNote(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. """ file = None - if os.path.exists(video_note): - thumb = None if thumb is None else self.save_file(thumb) - file = self.save_file(video_note, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map[".mp4"], - file=file, - thumb=thumb, - attributes=[ - types.DocumentAttributeVideo( - round_message=True, - duration=duration, - w=length, - h=length - ) - ] - ) - else: - try: - decoded = utils.decode(video_note) - fmt = " 24 else " 24 else " "pyrogram.Message": + progress_args: tuple = ()) -> Union["pyrogram.Message", None]: """Use this method to send audio files. Args: @@ -104,6 +104,7 @@ class SendVoice(BaseClient): Returns: On success, the sent :obj:`Message ` is returned. + In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead. Raises: :class:`Error ` in case of a Telegram RPC error. @@ -111,66 +112,69 @@ class SendVoice(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(voice): - file = self.save_file(voice, progress=progress, progress_args=progress_args) - media = types.InputMediaUploadedDocument( - mime_type=mimetypes.types_map.get("." + voice.split(".")[-1], "audio/mpeg"), - file=file, - attributes=[ - types.DocumentAttributeAudio( - voice=True, - duration=duration - ) - ] - ) - elif voice.startswith("http"): - media = types.InputMediaDocumentExternal( - url=voice - ) - else: - try: - decoded = utils.decode(voice) - fmt = " 24 else " 24 else " Date: Fri, 11 Jan 2019 14:20:01 +0100 Subject: [PATCH 8/8] Add stop_transmission to docs --- docs/source/pyrogram/Client.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/pyrogram/Client.rst b/docs/source/pyrogram/Client.rst index f9e50d3e..548f1c5b 100644 --- a/docs/source/pyrogram/Client.rst +++ b/docs/source/pyrogram/Client.rst @@ -21,6 +21,7 @@ Utilities send resolve_peer save_file + stop_transmission Decorators ----------