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 ---------- diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index f73380d3..732630c4 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -466,6 +466,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 + async def authorize_bot(self): try: r = await self.send( @@ -1376,6 +1382,8 @@ class Client(Methods, BaseClient): if progress: await 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: @@ -1584,7 +1592,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) diff --git a/pyrogram/client/ext/base_client.py b/pyrogram/client/ext/base_client.py index 7d5e7a4b..15d7637b 100644 --- a/pyrogram/client/ext/base_client.py +++ b/pyrogram/client/ext/base_client.py @@ -26,6 +26,9 @@ from ...session.internals import MsgId class BaseClient: + class StopTransmission(StopIteration): + pass + APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__) DEVICE_MODEL = "{} {}".format( diff --git a/pyrogram/client/methods/messages/download_media.py b/pyrogram/client/methods/messages/download_media.py index 66d6ca24..a3b1fe95 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. diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py index 74a41184..1bf0255b 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,55 +127,56 @@ 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 await self.save_file(thumb) - file = await 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. @@ -120,6 +120,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. @@ -127,53 +128,54 @@ 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 = await 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: @@ -106,6 +106,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. @@ -113,48 +114,49 @@ 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 await self.save_file(thumb) - file = await 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,45 +113,46 @@ class SendPhoto(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(photo): - file = await 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,52 +89,54 @@ 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 = await 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,54 +131,55 @@ 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 = await 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: @@ -104,55 +104,57 @@ 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 await self.save_file(thumb) - file = await 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,49 +112,50 @@ class SendVoice(BaseClient): file = None style = self.html if parse_mode.lower() == "html" else self.markdown - if os.path.exists(voice): - file = await 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 "`. Use as a shortcut for: