Merge branch 'develop' into asyncio

# Conflicts:
#	pyrogram/client/client.py
#	pyrogram/client/methods/messages/send_animation.py
#	pyrogram/client/methods/messages/send_audio.py
#	pyrogram/client/methods/messages/send_document.py
#	pyrogram/client/methods/messages/send_photo.py
#	pyrogram/client/methods/messages/send_sticker.py
#	pyrogram/client/methods/messages/send_video.py
#	pyrogram/client/methods/messages/send_video_note.py
#	pyrogram/client/methods/messages/send_voice.py
#	pyrogram/client/types/messages_and_media/message.py
This commit is contained in:
Dan 2019-01-11 14:24:15 +01:00
commit 9999c77e95
13 changed files with 390 additions and 344 deletions

View File

@ -21,6 +21,7 @@ Utilities
send send
resolve_peer resolve_peer
save_file save_file
stop_transmission
Decorators Decorators
---------- ----------

View File

@ -466,6 +466,12 @@ class Client(Methods, BaseClient):
else: else:
self.dispatcher.remove_handler(handler, group) 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): async def authorize_bot(self):
try: try:
r = await self.send( r = await self.send(
@ -1376,6 +1382,8 @@ class Client(Methods, BaseClient):
if progress: if progress:
await progress(self, min(file_part * part_size, file_size), file_size, *progress_args) await progress(self, min(file_part * part_size, file_size), file_size, *progress_args)
except Client.StopTransmission:
raise
except Exception as e: except Exception as e:
log.error(e, exc_info=True) log.error(e, exc_info=True)
else: else:
@ -1584,7 +1592,8 @@ class Client(Methods, BaseClient):
except Exception as e: except Exception as e:
raise e raise e
except Exception as e: except Exception as e:
log.error(e, exc_info=True) if not isinstance(e, Client.StopTransmission):
log.error(e, exc_info=True)
try: try:
os.remove(file_name) os.remove(file_name)

View File

@ -26,6 +26,9 @@ from ...session.internals import MsgId
class BaseClient: class BaseClient:
class StopTransmission(StopIteration):
pass
APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__) APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__)
DEVICE_MODEL = "{} {}".format( DEVICE_MODEL = "{} {}".format(

View File

@ -72,6 +72,7 @@ class DownloadMedia(BaseClient):
Returns: Returns:
On success, the absolute path of the downloaded file as string is returned, None otherwise. 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: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.

View File

@ -45,7 +45,7 @@ class SendAnimation(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = 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). """Use this method to send animation files (animation or H.264/MPEG-4 AVC video without sound).
Args: Args:
@ -119,6 +119,7 @@ class SendAnimation(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -126,55 +127,56 @@ class SendAnimation(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(animation): try:
thumb = None if thumb is None else await self.save_file(thumb) if os.path.exists(animation):
file = await self.save_file(animation, progress=progress, progress_args=progress_args) thumb = None if thumb is None else await self.save_file(thumb)
media = types.InputMediaUploadedDocument( file = await self.save_file(animation, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map[".mp4"], media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map[".mp4"],
thumb=thumb, file=file,
attributes=[ thumb=thumb,
types.DocumentAttributeVideo( attributes=[
supports_streaming=True, types.DocumentAttributeVideo(
duration=duration, supports_streaming=True,
w=width, duration=duration,
h=height w=width,
), h=height
types.DocumentAttributeFilename(os.path.basename(animation)), ),
types.DocumentAttributeAnimated() types.DocumentAttributeFilename(os.path.basename(animation)),
] types.DocumentAttributeAnimated()
) ]
elif animation.startswith("http"):
media = types.InputMediaDocumentExternal(
url=animation
)
else:
try:
decoded = utils.decode(animation)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 10:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif animation.startswith("http"):
media = types.InputMediaDocumentExternal(
url=animation
)
else:
try:
decoded = utils.decode(animation)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 10:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -195,3 +197,5 @@ class SendAnimation(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -44,7 +44,7 @@ class SendAudio(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send audio files. """Use this method to send audio files.
For sending voice messages, use the :obj:`send_voice()` method instead. For sending voice messages, use the :obj:`send_voice()` method instead.
@ -120,6 +120,7 @@ class SendAudio(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -127,53 +128,54 @@ class SendAudio(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(audio): try:
thumb = None if thumb is None else self.save_file(thumb) if os.path.exists(audio):
file = await self.save_file(audio, progress=progress, progress_args=progress_args) thumb = None if thumb is None else self.save_file(thumb)
media = types.InputMediaUploadedDocument( file = await self.save_file(audio, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map.get("." + audio.split(".")[-1], "audio/mpeg"), media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map.get("." + audio.split(".")[-1], "audio/mpeg"),
thumb=thumb, file=file,
attributes=[ thumb=thumb,
types.DocumentAttributeAudio( attributes=[
duration=duration, types.DocumentAttributeAudio(
performer=performer, duration=duration,
title=title performer=performer,
), title=title
types.DocumentAttributeFilename(os.path.basename(audio)) ),
] types.DocumentAttributeFilename(os.path.basename(audio))
) ]
elif audio.startswith("http"):
media = types.InputMediaDocumentExternal(
url=audio
)
else:
try:
decoded = utils.decode(audio)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 9:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif audio.startswith("http"):
media = types.InputMediaDocumentExternal(
url=audio
)
else:
try:
decoded = utils.decode(audio)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 9:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -194,3 +196,5 @@ class SendAudio(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -41,7 +41,7 @@ class SendDocument(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send general files. """Use this method to send general files.
Args: Args:
@ -106,6 +106,7 @@ class SendDocument(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -113,48 +114,49 @@ class SendDocument(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(document): try:
thumb = None if thumb is None else await self.save_file(thumb) if os.path.exists(document):
file = await self.save_file(document, progress=progress, progress_args=progress_args) thumb = None if thumb is None else await self.save_file(thumb)
media = types.InputMediaUploadedDocument( file = await self.save_file(document, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map.get("." + document.split(".")[-1], "text/plain"), media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map.get("." + document.split(".")[-1], "text/plain"),
thumb=thumb, file=file,
attributes=[ thumb=thumb,
types.DocumentAttributeFilename(os.path.basename(document)) attributes=[
] types.DocumentAttributeFilename(os.path.basename(document))
) ]
elif document.startswith("http"):
media = types.InputMediaDocumentExternal(
url=document
)
else:
try:
decoded = utils.decode(document)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] not in (5, 10):
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif document.startswith("http"):
media = types.InputMediaDocumentExternal(
url=document
)
else:
try:
decoded = utils.decode(document)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] not in (5, 10):
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -175,3 +177,5 @@ class SendDocument(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -41,7 +41,7 @@ class SendPhoto(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send photos. """Use this method to send photos.
Args: Args:
@ -105,6 +105,7 @@ class SendPhoto(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -112,45 +113,46 @@ class SendPhoto(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(photo): try:
file = await self.save_file(photo, progress=progress, progress_args=progress_args) if os.path.exists(photo):
media = types.InputMediaUploadedPhoto( file = await self.save_file(photo, progress=progress, progress_args=progress_args)
file=file, media = types.InputMediaUploadedPhoto(
ttl_seconds=ttl_seconds file=file,
)
elif photo.startswith("http"):
media = types.InputMediaPhotoExternal(
url=photo,
ttl_seconds=ttl_seconds
)
else:
try:
decoded = utils.decode(photo)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 2:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaPhoto(
id=types.InputPhoto(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
),
ttl_seconds=ttl_seconds ttl_seconds=ttl_seconds
) )
elif photo.startswith("http"):
media = types.InputMediaPhotoExternal(
url=photo,
ttl_seconds=ttl_seconds
)
else:
try:
decoded = utils.decode(photo)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 2:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaPhoto(
id=types.InputPhoto(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
),
ttl_seconds=ttl_seconds
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -171,3 +173,5 @@ class SendPhoto(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -38,7 +38,7 @@ class SendSticker(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send .webp stickers. """Use this method to send .webp stickers.
Args: Args:
@ -89,52 +89,54 @@ class SendSticker(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
""" """
file = None file = None
if os.path.exists(sticker): try:
file = await self.save_file(sticker, progress=progress, progress_args=progress_args) if os.path.exists(sticker):
media = types.InputMediaUploadedDocument( file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
mime_type="image/webp", media = types.InputMediaUploadedDocument(
file=file, mime_type="image/webp",
attributes=[ file=file,
types.DocumentAttributeFilename(os.path.basename(sticker)) attributes=[
] types.DocumentAttributeFilename(os.path.basename(sticker))
) ]
elif sticker.startswith("http"):
media = types.InputMediaDocumentExternal(
url=sticker
)
else:
try:
decoded = utils.decode(sticker)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 8:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif sticker.startswith("http"):
media = types.InputMediaDocumentExternal(
url=sticker
)
else:
try:
decoded = utils.decode(sticker)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 8:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -155,3 +157,5 @@ class SendSticker(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -46,7 +46,7 @@ class SendVideo(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send video files. """Use this method to send video files.
Args: Args:
@ -123,6 +123,7 @@ class SendVideo(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -130,54 +131,55 @@ class SendVideo(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(video): try:
thumb = None if thumb is None else self.save_file(thumb) if os.path.exists(video):
file = await self.save_file(video, progress=progress, progress_args=progress_args) thumb = None if thumb is None else self.save_file(thumb)
media = types.InputMediaUploadedDocument( file = await self.save_file(video, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map[".mp4"], media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map[".mp4"],
thumb=thumb, file=file,
attributes=[ thumb=thumb,
types.DocumentAttributeVideo( attributes=[
supports_streaming=supports_streaming or None, types.DocumentAttributeVideo(
duration=duration, supports_streaming=supports_streaming or None,
w=width, duration=duration,
h=height w=width,
), h=height
types.DocumentAttributeFilename(os.path.basename(video)) ),
] types.DocumentAttributeFilename(os.path.basename(video))
) ]
elif video.startswith("http"):
media = types.InputMediaDocumentExternal(
url=video
)
else:
try:
decoded = utils.decode(video)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 4:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif video.startswith("http"):
media = types.InputMediaDocumentExternal(
url=video
)
else:
try:
decoded = utils.decode(video)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 4:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -198,3 +200,5 @@ class SendVideo(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -41,7 +41,7 @@ class SendVideoNote(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send video messages. """Use this method to send video messages.
Args: Args:
@ -104,55 +104,57 @@ class SendVideoNote(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
""" """
file = None file = None
if os.path.exists(video_note): try:
thumb = None if thumb is None else await self.save_file(thumb) if os.path.exists(video_note):
file = await self.save_file(video_note, progress=progress, progress_args=progress_args) thumb = None if thumb is None else await self.save_file(thumb)
media = types.InputMediaUploadedDocument( file = await self.save_file(video_note, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map[".mp4"], media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map[".mp4"],
thumb=thumb, file=file,
attributes=[ thumb=thumb,
types.DocumentAttributeVideo( attributes=[
round_message=True, types.DocumentAttributeVideo(
duration=duration, round_message=True,
w=length, duration=duration,
h=length w=length,
) h=length
] )
) ]
else:
try:
decoded = utils.decode(video_note)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 13:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
else:
try:
decoded = utils.decode(video_note)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 13:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -173,3 +175,5 @@ class SendVideoNote(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -42,7 +42,7 @@ class SendVoice(BaseClient):
"pyrogram.ReplyKeyboardRemove", "pyrogram.ReplyKeyboardRemove",
"pyrogram.ForceReply"] = None, "pyrogram.ForceReply"] = None,
progress: callable = None, progress: callable = None,
progress_args: tuple = ()) -> "pyrogram.Message": progress_args: tuple = ()) -> Union["pyrogram.Message", None]:
"""Use this method to send audio files. """Use this method to send audio files.
Args: Args:
@ -104,6 +104,7 @@ class SendVoice(BaseClient):
Returns: Returns:
On success, the sent :obj:`Message <pyrogram.Message>` is returned. On success, the sent :obj:`Message <pyrogram.Message>` is returned.
In case the upload is deliberately stopped with :meth:`stop_transmission`, None is returned instead.
Raises: Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error. :class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
@ -111,49 +112,50 @@ class SendVoice(BaseClient):
file = None file = None
style = self.html if parse_mode.lower() == "html" else self.markdown style = self.html if parse_mode.lower() == "html" else self.markdown
if os.path.exists(voice): try:
file = await self.save_file(voice, progress=progress, progress_args=progress_args) if os.path.exists(voice):
media = types.InputMediaUploadedDocument( file = await self.save_file(voice, progress=progress, progress_args=progress_args)
mime_type=mimetypes.types_map.get("." + voice.split(".")[-1], "audio/mpeg"), media = types.InputMediaUploadedDocument(
file=file, mime_type=mimetypes.types_map.get("." + voice.split(".")[-1], "audio/mpeg"),
attributes=[ file=file,
types.DocumentAttributeAudio( attributes=[
voice=True, types.DocumentAttributeAudio(
duration=duration voice=True,
) duration=duration
] )
) ]
elif voice.startswith("http"):
media = types.InputMediaDocumentExternal(
url=voice
)
else:
try:
decoded = utils.decode(voice)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 3:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
if media_type:
raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
) )
elif voice.startswith("http"):
media = types.InputMediaDocumentExternal(
url=voice
)
else:
try:
decoded = utils.decode(voice)
fmt = "<iiqqqqi" if len(decoded) > 24 else "<iiqq"
unpacked = struct.unpack(fmt, decoded)
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
else:
if unpacked[0] != 3:
media_type = BaseClient.MEDIA_TYPE_ID.get(unpacked[0], None)
while True: if media_type:
try: raise FileIdInvalid("The file_id belongs to a {}".format(media_type))
r = await self.send( else:
raise FileIdInvalid("Unknown media type: {}".format(unpacked[0]))
media = types.InputMediaDocument(
id=types.InputDocument(
id=unpacked[2],
access_hash=unpacked[3],
file_reference=b""
)
)
while True:
try:
r = await self.send(
functions.messages.SendMedia( functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
media=media, media=media,
@ -174,3 +176,5 @@ class SendVoice(BaseClient):
{i.id: i for i in r.users}, {i.id: i for i in r.users},
{i.id: i for i in r.chats} {i.id: i for i in r.chats}
) )
except BaseClient.StopTransmission:
return None

View File

@ -916,7 +916,7 @@ class Message(PyrogramType, Update):
file_name: str = "", file_name: str = "",
block: bool = True, block: bool = True,
progress: callable = None, progress: callable = None,
progress_args: tuple = None): progress_args: tuple = ()):
"""Bound method *download* of :obj:`Message <pyrogram.Message>`. """Bound method *download* of :obj:`Message <pyrogram.Message>`.
Use as a shortcut for: Use as a shortcut for: