2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-28 21:07:59 +00:00

Merge develop -> asyncio-dev

This commit is contained in:
Dan 2020-07-09 03:03:52 +02:00
commit f43165b211
14 changed files with 306 additions and 157 deletions

View File

@ -17,6 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import asyncio import asyncio
import io
import logging import logging
import math import math
import os import os
@ -28,7 +29,7 @@ from hashlib import sha256, md5
from importlib import import_module, reload from importlib import import_module, reload
from pathlib import Path from pathlib import Path
from signal import signal, SIGINT, SIGTERM, SIGABRT from signal import signal, SIGINT, SIGTERM, SIGABRT
from typing import Union, List from typing import Union, List, BinaryIO
from pyrogram.api import functions, types from pyrogram.api import functions, types
from pyrogram.api.core import TLObject from pyrogram.api.core import TLObject
@ -38,8 +39,9 @@ from pyrogram.client.methods.password.utils import compute_check
from pyrogram.crypto import AES from pyrogram.crypto import AES
from pyrogram.errors import ( from pyrogram.errors import (
PhoneMigrate, NetworkMigrate, SessionPasswordNeeded, PhoneMigrate, NetworkMigrate, SessionPasswordNeeded,
PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate, AuthBytesInvalid, PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate,
BadRequest) AuthBytesInvalid, BadRequest
)
from pyrogram.session import Auth, Session from pyrogram.session import Auth, Session
from .ext import utils, Syncer, BaseClient, Dispatcher from .ext import utils, Syncer, BaseClient, Dispatcher
from .ext.utils import ainput from .ext.utils import ainput
@ -1714,13 +1716,14 @@ class Client(Methods, BaseClient):
except KeyError: except KeyError:
raise PeerIdInvalid raise PeerIdInvalid
async def save_file(self, async def save_file(
path: str, self,
file_id: int = None, path: Union[str, BinaryIO],
file_part: int = 0, file_id: int = None,
progress: callable = None, file_part: int = 0,
progress_args: tuple = () progress: callable = None,
): progress_args: tuple = ()
):
"""Upload a file onto Telegram servers, without actually sending the message to anyone. """Upload a file onto Telegram servers, without actually sending the message to anyone.
Useful whenever an InputFile type is required. Useful whenever an InputFile type is required.
@ -1782,7 +1785,19 @@ class Client(Methods, BaseClient):
logging.error(e) logging.error(e)
part_size = 512 * 1024 part_size = 512 * 1024
file_size = os.path.getsize(path)
if isinstance(path, str):
fp = open(path, "rb")
elif isinstance(path, io.IOBase):
fp = path
else:
raise ValueError("Invalid file. Expected a file path as string or a binary (not text) file pointer")
file_name = fp.name
fp.seek(0, os.SEEK_END)
file_size = fp.tell()
fp.seek(0)
if file_size == 0: if file_size == 0:
raise ValueError("File size equals to 0 B") raise ValueError("File size equals to 0 B")
@ -1805,11 +1820,11 @@ class Client(Methods, BaseClient):
for session in pool: for session in pool:
await session.start() await session.start()
with open(path, "rb") as f: with fp:
f.seek(part_size * file_part) fp.seek(part_size * file_part)
while True: while True:
chunk = f.read(part_size) chunk = fp.read(part_size)
if not chunk: if not chunk:
if not is_big: if not is_big:
@ -1851,14 +1866,14 @@ class Client(Methods, BaseClient):
return types.InputFileBig( return types.InputFileBig(
id=file_id, id=file_id,
parts=file_total_parts, parts=file_total_parts,
name=os.path.basename(path), name=file_name,
) )
else: else:
return types.InputFile( return types.InputFile(
id=file_id, id=file_id,
parts=file_total_parts, parts=file_total_parts,
name=os.path.basename(path), name=file_name,
md5_checksum=md5_sum md5_checksum=md5_sum
) )
finally: finally:

View File

@ -63,7 +63,7 @@ class SetChatPhoto(BaseClient):
""" """
peer = await self.resolve_peer(chat_id) peer = await self.resolve_peer(chat_id)
if os.path.exists(photo): if os.path.isfile(photo):
photo = types.InputChatUploadedPhoto(file=await self.save_file(photo)) photo = types.InputChatUploadedPhoto(file=await self.save_file(photo))
else: else:
photo = utils.get_input_media_from_file_id(photo, file_ref, 2) photo = utils.get_input_media_from_file_id(photo, file_ref, 2)

View File

@ -26,7 +26,7 @@ class SetSlowMode(BaseClient):
async def set_slow_mode( async def set_slow_mode(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
seconds: int, seconds: Union[int, None]
) -> bool: ) -> bool:
"""Set the slow mode interval for a chat. """Set the slow mode interval for a chat.
@ -34,9 +34,9 @@ class SetSlowMode(BaseClient):
chat_id (``int`` | ``str``): chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat. Unique identifier (int) or username (str) of the target chat.
seconds (``int`` | ``str``): seconds (``int`` | ``None``):
Seconds in which members will be able to send only one message per this interval. Seconds in which members will be able to send only one message per this interval.
Valid values are: 0 (off), 10, 30, 60 (1m), 300 (5m), 900 (15m) or 3600 (1h). Valid values are: 0 or None (off), 10, 30, 60 (1m), 300 (5m), 900 (15m) or 3600 (1h).
Returns: Returns:
``bool``: True on success. ``bool``: True on success.
@ -44,13 +44,17 @@ class SetSlowMode(BaseClient):
Example: Example:
.. code-block:: python .. code-block:: python
# Set slow mode to 60 seconds
app.set_slow_mode("pyrogramchat", 60) app.set_slow_mode("pyrogramchat", 60)
# Disable slow mode
app.set_slow_mode("pyrogramchat", None)
""" """
await self.send( await self.send(
functions.channels.ToggleSlowMode( functions.channels.ToggleSlowMode(
channel=await self.resolve_peer(chat_id), channel=await self.resolve_peer(chat_id),
seconds=seconds seconds=0 if seconds is None else seconds
) )
) )

View File

@ -16,6 +16,8 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import re
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient, utils from pyrogram.client.ext import BaseClient, utils
@ -72,35 +74,35 @@ class EditInlineMedia(BaseClient):
parse_mode = media.parse_mode parse_mode = media.parse_mode
if isinstance(media, InputMediaPhoto): if isinstance(media, InputMediaPhoto):
if media.media.startswith("http"): if re.match("^https?://", media.media):
media = types.InputMediaPhotoExternal( media = types.InputMediaPhotoExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2)
elif isinstance(media, InputMediaVideo): elif isinstance(media, InputMediaVideo):
if media.media.startswith("http"): if re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4)
elif isinstance(media, InputMediaAudio): elif isinstance(media, InputMediaAudio):
if media.media.startswith("http"): if re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9)
elif isinstance(media, InputMediaAnimation): elif isinstance(media, InputMediaAnimation):
if media.media.startswith("http"): if re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10)
elif isinstance(media, InputMediaDocument): elif isinstance(media, InputMediaDocument):
if media.media.startswith("http"): if re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )

View File

@ -17,6 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
import re
from typing import Union from typing import Union
import pyrogram import pyrogram
@ -78,7 +79,7 @@ class EditMessageMedia(BaseClient):
parse_mode = media.parse_mode parse_mode = media.parse_mode
if isinstance(media, InputMediaPhoto): if isinstance(media, InputMediaPhoto):
if os.path.exists(media.media): if os.path.isfile(media.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -95,14 +96,14 @@ class EditMessageMedia(BaseClient):
file_reference=media.photo.file_reference file_reference=media.photo.file_reference
) )
) )
elif media.media.startswith("http"): elif re.match("^https?://", media.media):
media = types.InputMediaPhotoExternal( media = types.InputMediaPhotoExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 2)
elif isinstance(media, InputMediaVideo): elif isinstance(media, InputMediaVideo):
if os.path.exists(media.media): if os.path.isfile(media.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -132,14 +133,14 @@ class EditMessageMedia(BaseClient):
file_reference=media.document.file_reference file_reference=media.document.file_reference
) )
) )
elif media.media.startswith("http"): elif re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 4)
elif isinstance(media, InputMediaAudio): elif isinstance(media, InputMediaAudio):
if os.path.exists(media.media): if os.path.isfile(media.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -168,14 +169,14 @@ class EditMessageMedia(BaseClient):
file_reference=media.document.file_reference file_reference=media.document.file_reference
) )
) )
elif media.media.startswith("http"): elif re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 9)
elif isinstance(media, InputMediaAnimation): elif isinstance(media, InputMediaAnimation):
if os.path.exists(media.media): if os.path.isfile(media.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -206,14 +207,14 @@ class EditMessageMedia(BaseClient):
file_reference=media.document.file_reference file_reference=media.document.file_reference
) )
) )
elif media.media.startswith("http"): elif re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )
else: else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10) media = utils.get_input_media_from_file_id(media.media, media.file_ref, 10)
elif isinstance(media, InputMediaDocument): elif isinstance(media, InputMediaDocument):
if os.path.exists(media.media): if os.path.isfile(media.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -237,7 +238,7 @@ class EditMessageMedia(BaseClient):
file_reference=media.document.file_reference file_reference=media.document.file_reference
) )
) )
elif media.media.startswith("http"): elif re.match("^https?://", media.media):
media = types.InputMediaDocumentExternal( media = types.InputMediaDocumentExternal(
url=media.media url=media.media
) )

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,7 +30,7 @@ class SendAnimation(BaseClient):
async def send_animation( async def send_animation(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
animation: str, animation: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
caption: str = "", caption: str = "",
unsave: bool = False, unsave: bool = False,
@ -37,7 +38,7 @@ class SendAnimation(BaseClient):
duration: int = 0, duration: int = 0,
width: int = 0, width: int = 0,
height: int = 0, height: int = 0,
thumb: str = None, thumb: Union[str, BinaryIO] = None,
file_name: str = None, file_name: str = None,
disable_notification: bool = None, disable_notification: bool = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
@ -59,11 +60,12 @@ class SendAnimation(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
animation (``str``): animation (``str`` | ``BinaryIO``):
Animation to send. Animation to send.
Pass a file_id as string to send an animation that exists on the Telegram servers, Pass a file_id as string to send an animation that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get an animation from the Internet, or pass an HTTP URL as a string for Telegram to get an animation from the Internet,
pass a file path as string to upload a new animation that exists on your local machine. pass a file path as string to upload a new animation that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -92,7 +94,7 @@ class SendAnimation(BaseClient):
height (``int``, *optional*): height (``int``, *optional*):
Animation height. Animation height.
thumb (``str``, *optional*): thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the animation file sent. Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels. A thumbnail's width and height should not exceed 320 pixels.
@ -163,11 +165,36 @@ class SendAnimation(BaseClient):
file = None file = None
try: try:
if os.path.exists(animation): if isinstance(animation, str):
if os.path.isfile(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=self.guess_mime_type(animation) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=True,
duration=duration,
w=width,
h=height
),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(animation)),
types.DocumentAttributeAnimated()
]
)
elif re.match("^https?://", animation):
media = types.InputMediaDocumentExternal(
url=animation
)
else:
media = utils.get_input_media_from_file_id(animation, file_ref, 10)
else:
thumb = None if thumb is None else await self.save_file(thumb) thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(animation, progress=progress, progress_args=progress_args) file = await self.save_file(animation, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(animation) or "video/mp4", mime_type=self.guess_mime_type(animation.name) or "video/mp4",
file=file, file=file,
thumb=thumb, thumb=thumb,
attributes=[ attributes=[
@ -177,16 +204,10 @@ class SendAnimation(BaseClient):
w=width, w=width,
h=height h=height
), ),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(animation)), types.DocumentAttributeFilename(file_name=animation.name),
types.DocumentAttributeAnimated() types.DocumentAttributeAnimated()
] ]
) )
elif animation.startswith("http"):
media = types.InputMediaDocumentExternal(
url=animation
)
else:
media = utils.get_input_media_from_file_id(animation, file_ref, 10)
while True: while True:
try: try:

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,14 +30,14 @@ class SendAudio(BaseClient):
async def send_audio( async def send_audio(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
audio: str, audio: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
caption: str = "", caption: str = "",
parse_mode: Union[str, None] = object, parse_mode: Union[str, None] = object,
duration: int = 0, duration: int = 0,
performer: str = None, performer: str = None,
title: str = None, title: str = None,
thumb: str = None,file_name: str = None, thumb: Union[str, BinaryIO] = None,file_name: str = None,
disable_notification: bool = None, disable_notification: bool = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: int = None, schedule_date: int = None,
@ -59,11 +60,12 @@ class SendAudio(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
audio (``str``): audio (``str`` | ``BinaryIO``):
Audio file to send. Audio file to send.
Pass a file_id as string to send an audio file that exists on the Telegram servers, Pass a file_id as string to send an audio file that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get an audio file from the Internet, or pass an HTTP URL as a string for Telegram to get an audio file from the Internet,
pass a file path as string to upload a new audio file that exists on your local machine. pass a file path as string to upload a new audio file that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -88,7 +90,7 @@ class SendAudio(BaseClient):
title (``str``, *optional*): title (``str``, *optional*):
Track name. Track name.
thumb (``str``, *optional*): thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the music file album cover. Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size. The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels. A thumbnail's width and height should not exceed 320 pixels.
@ -162,11 +164,34 @@ class SendAudio(BaseClient):
file = None file = None
try: try:
if os.path.exists(audio): if isinstance(audio, str):
if os.path.isfile(audio):
thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(audio, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(audio) or "audio/mpeg",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeAudio(
duration=duration,
performer=performer,
title=title
),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(audio))
]
)
elif re.match("^https?://", audio):
media = types.InputMediaDocumentExternal(
url=audio
)
else:
media = utils.get_input_media_from_file_id(audio, file_ref, 9)
else:
thumb = None if thumb is None else await self.save_file(thumb) thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(audio, progress=progress, progress_args=progress_args) file = await self.save_file(audio, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(audio) or "audio/mpeg", mime_type=self.guess_mime_type(audio.name) or "audio/mpeg",
file=file, file=file,
thumb=thumb, thumb=thumb,
attributes=[ attributes=[
@ -175,15 +200,9 @@ class SendAudio(BaseClient):
performer=performer, performer=performer,
title=title title=title
), ),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(audio)) types.DocumentAttributeFilename(file_name=audio.name)
] ]
) )
elif audio.startswith("http"):
media = types.InputMediaDocumentExternal(
url=audio
)
else:
media = utils.get_input_media_from_file_id(audio, file_ref, 9)
while True: while True:
try: try:

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,9 +30,9 @@ class SendDocument(BaseClient):
async def send_document( async def send_document(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
document: str, document: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
thumb: str = None, thumb: Union[str, BinaryIO] = None,
caption: str = "", caption: str = "",
parse_mode: Union[str, None] = object, parse_mode: Union[str, None] = object,
file_name: str = None, file_name: str = None,
@ -55,17 +56,18 @@ class SendDocument(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
document (``str``): document (``str`` | ``BinaryIO``):
File to send. File to send.
Pass a file_id as string to send a file that exists on the Telegram servers, Pass a file_id as string to send a file that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a file from the Internet, or pass an HTTP URL as a string for Telegram to get a file from the Internet,
pass a file path as string to upload a new file that exists on your local machine. pass a file path as string to upload a new file that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
To be used in combination with a file id in case a file reference is needed. To be used in combination with a file id in case a file reference is needed.
thumb (``str``, *optional*): thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the file sent. Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size. The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels. A thumbnail's width and height should not exceed 320 pixels.
@ -143,23 +145,35 @@ class SendDocument(BaseClient):
file = None file = None
try: try:
if os.path.exists(document): if isinstance(document, str):
if os.path.isfile(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=self.guess_mime_type(document) or "application/zip",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document))
]
)
elif re.match("^https?://", document):
media = types.InputMediaDocumentExternal(
url=document
)
else:
media = utils.get_input_media_from_file_id(document, file_ref, 5)
else:
thumb = None if thumb is None else await self.save_file(thumb) thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(document, progress=progress, progress_args=progress_args) file = await self.save_file(document, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(document) or "application/zip", mime_type=self.guess_mime_type(document.name) or "application/zip",
file=file, file=file,
thumb=thumb, thumb=thumb,
attributes=[ attributes=[
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document)) types.DocumentAttributeFilename(file_name=document.name)
] ]
) )
elif document.startswith("http"):
media = types.InputMediaDocumentExternal(
url=document
)
else:
media = utils.get_input_media_from_file_id(document, file_ref, 5)
while True: while True:
try: try:

View File

@ -16,15 +16,14 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import asyncio
import logging import logging
import os import os
import re
from typing import Union, List from typing import Union, List
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
from pyrogram.client.ext import BaseClient, utils from pyrogram.client.ext import BaseClient, utils
from pyrogram.errors import FloodWait
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -77,7 +76,7 @@ class SendMediaGroup(BaseClient):
for i in media: for i in media:
if isinstance(i, pyrogram.InputMediaPhoto): if isinstance(i, pyrogram.InputMediaPhoto):
if os.path.exists(i.media): if os.path.isfile(i.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -94,7 +93,7 @@ class SendMediaGroup(BaseClient):
file_reference=media.photo.file_reference file_reference=media.photo.file_reference
) )
) )
elif i.media.startswith("http"): elif re.match("^https?://", i.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -114,7 +113,7 @@ class SendMediaGroup(BaseClient):
else: else:
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 2) media = utils.get_input_media_from_file_id(i.media, i.file_ref, 2)
elif isinstance(i, pyrogram.InputMediaVideo): elif isinstance(i, pyrogram.InputMediaVideo):
if os.path.exists(i.media): if os.path.isfile(i.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),
@ -142,7 +141,7 @@ class SendMediaGroup(BaseClient):
file_reference=media.document.file_reference file_reference=media.document.file_reference
) )
) )
elif i.media.startswith("http"): elif re.match("^https?://", i.media):
media = await self.send( media = await self.send(
functions.messages.UploadMedia( functions.messages.UploadMedia(
peer=await self.resolve_peer(chat_id), peer=await self.resolve_peer(chat_id),

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,7 +30,7 @@ class SendPhoto(BaseClient):
async def send_photo( async def send_photo(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
photo: str, photo: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
caption: str = "", caption: str = "",
parse_mode: Union[str, None] = object, parse_mode: Union[str, None] = object,
@ -54,11 +55,12 @@ class SendPhoto(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
photo (``str``): photo (``str`` | ``BinaryIO``):
Photo to send. Photo to send.
Pass a file_id as string to send a photo that exists on the Telegram servers, Pass a file_id as string to send a photo that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a photo from the Internet, or pass an HTTP URL as a string for Telegram to get a photo from the Internet,
pass a file path as string to upload a new photo that exists on your local machine. pass a file path as string to upload a new photo that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -137,19 +139,26 @@ class SendPhoto(BaseClient):
file = None file = None
try: try:
if os.path.exists(photo): if isinstance(photo, str):
if os.path.isfile(photo):
file = await self.save_file(photo, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedPhoto(
file=file,
ttl_seconds=ttl_seconds
)
elif re.match("^https?://", photo):
media = types.InputMediaPhotoExternal(
url=photo,
ttl_seconds=ttl_seconds
)
else:
media = utils.get_input_media_from_file_id(photo, file_ref, 2)
else:
file = await self.save_file(photo, progress=progress, progress_args=progress_args) file = await self.save_file(photo, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedPhoto( media = types.InputMediaUploadedPhoto(
file=file, file=file,
ttl_seconds=ttl_seconds ttl_seconds=ttl_seconds
) )
elif photo.startswith("http"):
media = types.InputMediaPhotoExternal(
url=photo,
ttl_seconds=ttl_seconds
)
else:
media = utils.get_input_media_from_file_id(photo, file_ref, 2)
while True: while True:
try: try:

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,7 +30,7 @@ class SendSticker(BaseClient):
async def send_sticker( async def send_sticker(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
sticker: str, sticker: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
disable_notification: bool = None, disable_notification: bool = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
@ -51,11 +52,12 @@ class SendSticker(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
sticker (``str``): sticker (``str`` | ``BinaryIO``):
Sticker to send. Sticker to send.
Pass a file_id as string to send a sticker that exists on the Telegram servers, Pass a file_id as string to send a sticker that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a .webp sticker file from the Internet, or pass an HTTP URL as a string for Telegram to get a .webp sticker file from the Internet,
pass a file path as string to upload a new sticker that exists on your local machine. pass a file path as string to upload a new sticker that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -113,21 +115,31 @@ class SendSticker(BaseClient):
file = None file = None
try: try:
if os.path.exists(sticker): if isinstance(sticker, str):
if os.path.isfile(sticker):
file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(sticker) or "image/webp",
file=file,
attributes=[
types.DocumentAttributeFilename(file_name=os.path.basename(sticker))
]
)
elif re.match("^https?://", sticker):
media = types.InputMediaDocumentExternal(
url=sticker
)
else:
media = utils.get_input_media_from_file_id(sticker, file_ref, 8)
else:
file = await self.save_file(sticker, progress=progress, progress_args=progress_args) file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(sticker) or "image/webp", mime_type=self.guess_mime_type(sticker.name) or "image/webp",
file=file, file=file,
attributes=[ attributes=[
types.DocumentAttributeFilename(file_name=os.path.basename(sticker)) types.DocumentAttributeFilename(file_name=sticker.name)
] ]
) )
elif sticker.startswith("http"):
media = types.InputMediaDocumentExternal(
url=sticker
)
else:
media = utils.get_input_media_from_file_id(sticker, file_ref, 8)
while True: while True:
try: try:

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,14 +30,14 @@ class SendVideo(BaseClient):
async def send_video( async def send_video(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
video: str, video: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
caption: str = "", caption: str = "",
parse_mode: Union[str, None] = object, parse_mode: Union[str, None] = object,
duration: int = 0, duration: int = 0,
width: int = 0, width: int = 0,
height: int = 0, height: int = 0,
thumb: str = None, thumb: Union[str, BinaryIO] = None,
file_name: str = None, file_name: str = None,
supports_streaming: bool = True, supports_streaming: bool = True,
disable_notification: bool = None, disable_notification: bool = None,
@ -59,11 +60,12 @@ class SendVideo(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
video (``str``): video (``str`` | ``BinaryIO``):
Video to send. Video to send.
Pass a file_id as string to send a video that exists on the Telegram servers, Pass a file_id as string to send a video that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get a video from the Internet, or pass an HTTP URL as a string for Telegram to get a video from the Internet,
pass a file path as string to upload a new video that exists on your local machine. pass a file path as string to upload a new video that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -88,7 +90,7 @@ class SendVideo(BaseClient):
height (``int``, *optional*): height (``int``, *optional*):
Video height. Video height.
thumb (``str``, *optional*): thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent. Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size. The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels. A thumbnail's width and height should not exceed 320 pixels.
@ -160,11 +162,35 @@ class SendVideo(BaseClient):
file = None file = None
try: try:
if os.path.exists(video): if isinstance(video, str):
if os.path.isfile(video):
thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(video, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeVideo(
supports_streaming=supports_streaming or None,
duration=duration,
w=width,
h=height
),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
]
)
elif re.match("^https?://", video):
media = types.InputMediaDocumentExternal(
url=video
)
else:
media = utils.get_input_media_from_file_id(video, file_ref, 4)
else:
thumb = None if thumb is None else await self.save_file(thumb) thumb = None if thumb is None else await self.save_file(thumb)
file = await self.save_file(video, progress=progress, progress_args=progress_args) file = await self.save_file(video, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video) or "video/mp4", mime_type=self.guess_mime_type(video.name) or "video/mp4",
file=file, file=file,
thumb=thumb, thumb=thumb,
attributes=[ attributes=[
@ -174,15 +200,9 @@ class SendVideo(BaseClient):
w=width, w=width,
h=height h=height
), ),
types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video)) types.DocumentAttributeFilename(file_name=video.name)
] ]
) )
elif video.startswith("http"):
media = types.InputMediaDocumentExternal(
url=video
)
else:
media = utils.get_input_media_from_file_id(video, file_ref, 4)
while True: while True:
try: try:

View File

@ -17,7 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,11 +29,11 @@ class SendVideoNote(BaseClient):
async def send_video_note( async def send_video_note(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
video_note: str, video_note: Union[str, BinaryIO],
file_ref: str = None, file_ref: str = None,
duration: int = 0, duration: int = 0,
length: int = 1, length: int = 1,
thumb: str = None, thumb: Union[str, BinaryIO] = None,
disable_notification: bool = None, disable_notification: bool = None,
reply_to_message_id: int = None, reply_to_message_id: int = None,
schedule_date: int = None, schedule_date: int = None,
@ -54,10 +54,11 @@ class SendVideoNote(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
video_note (``str``): video_note (``str`` | ``BinaryIO``):
Video note to send. Video note to send.
Pass a file_id as string to send a video note that exists on the Telegram servers, or Pass a file_id as string to send a video note that exists on the Telegram servers,
pass a file path as string to upload a new video note that exists on your local machine. pass a file path as string to upload a new video note that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
Sending video notes by a URL is currently unsupported. Sending video notes by a URL is currently unsupported.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
@ -70,7 +71,7 @@ class SendVideoNote(BaseClient):
length (``int``, *optional*): length (``int``, *optional*):
Video width and height. Video width and height.
thumb (``str``, *optional*): thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent. Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size. The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels. A thumbnail's width and height should not exceed 320 pixels.
@ -128,11 +129,30 @@ class SendVideoNote(BaseClient):
file = None file = None
try: try:
if os.path.exists(video_note): if isinstance(video_note, str):
if os.path.isfile(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=self.guess_mime_type(video_note) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
types.DocumentAttributeVideo(
round_message=True,
duration=duration,
w=length,
h=length
)
]
)
else:
media = utils.get_input_media_from_file_id(video_note, file_ref, 13)
else:
thumb = None if thumb is None else await self.save_file(thumb) 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) file = await self.save_file(video_note, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(video_note) or "video/mp4", mime_type=self.guess_mime_type(video_note.name) or "video/mp4",
file=file, file=file,
thumb=thumb, thumb=thumb,
attributes=[ attributes=[
@ -144,8 +164,6 @@ class SendVideoNote(BaseClient):
) )
] ]
) )
else:
media = utils.get_input_media_from_file_id(video_note, file_ref, 13)
while True: while True:
try: try:

View File

@ -17,7 +17,8 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>. # along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import os import os
from typing import Union import re
from typing import Union, BinaryIO
import pyrogram import pyrogram
from pyrogram.api import functions, types from pyrogram.api import functions, types
@ -29,7 +30,7 @@ class SendVoice(BaseClient):
async def send_voice( async def send_voice(
self, self,
chat_id: Union[int, str], chat_id: Union[int, str],
voice: str, voice: Union[str, BinaryIO],
file_ref=None, file_ref=None,
caption: str = "", caption: str = "",
parse_mode: Union[str, None] = object, parse_mode: Union[str, None] = object,
@ -54,11 +55,12 @@ class SendVoice(BaseClient):
For your personal cloud (Saved Messages) you can simply use "me" or "self". 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). For a contact that exists in your Telegram address book you can use his phone number (str).
voice (``str``): voice (``str`` | ``BinaryIO``):
Audio file to send. Audio file to send.
Pass a file_id as string to send an audio that exists on the Telegram servers, Pass a file_id as string to send an audio that exists on the Telegram servers,
pass an HTTP URL as a string for Telegram to get an audio from the Internet, or pass an HTTP URL as a string for Telegram to get an audio from the Internet,
pass a file path as string to upload a new audio that exists on your local machine. pass a file path as string to upload a new audio that exists on your local machine, or
pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*): file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message. A valid file reference obtained by a recently fetched media message.
@ -132,10 +134,29 @@ class SendVoice(BaseClient):
file = None file = None
try: try:
if os.path.exists(voice): if isinstance(voice, str):
if os.path.isfile(voice):
file = await self.save_file(voice, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(voice) or "audio/mpeg",
file=file,
attributes=[
types.DocumentAttributeAudio(
voice=True,
duration=duration
)
]
)
elif re.match("^https?://", voice):
media = types.InputMediaDocumentExternal(
url=voice
)
else:
media = utils.get_input_media_from_file_id(voice, file_ref, 3)
else:
file = await self.save_file(voice, progress=progress, progress_args=progress_args) file = await self.save_file(voice, progress=progress, progress_args=progress_args)
media = types.InputMediaUploadedDocument( media = types.InputMediaUploadedDocument(
mime_type=self.guess_mime_type(voice) or "audio/mpeg", mime_type=self.guess_mime_type(voice.name) or "audio/mpeg",
file=file, file=file,
attributes=[ attributes=[
types.DocumentAttributeAudio( types.DocumentAttributeAudio(
@ -144,12 +165,6 @@ class SendVoice(BaseClient):
) )
] ]
) )
elif voice.startswith("http"):
media = types.InputMediaDocumentExternal(
url=voice
)
else:
media = utils.get_input_media_from_file_id(voice, file_ref, 3)
while True: while True:
try: try: