From b3faf21c95533232a71bbb7049d316ab18725c28 Mon Sep 17 00:00:00 2001
From: Dan <14043624+delivrance@users.noreply.github.com>
Date: Thu, 9 Jul 2020 02:56:09 +0200
Subject: [PATCH] Rework in-memory uploads
---
pyrogram/client/client.py | 35 +++++++++----
.../client/methods/messages/send_animation.py | 52 +++++++++++++------
.../client/methods/messages/send_audio.py | 50 ++++++++++++------
.../client/methods/messages/send_document.py | 45 ++++++++++------
.../client/methods/messages/send_photo.py | 34 +++++++-----
.../client/methods/messages/send_sticker.py | 39 +++++++++-----
.../client/methods/messages/send_video.py | 51 ++++++++++++------
.../methods/messages/send_video_note.py | 40 ++++++++++----
.../client/methods/messages/send_voice.py | 40 +++++++++-----
9 files changed, 260 insertions(+), 126 deletions(-)
diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py
index 0e186d85..c46f119a 100644
--- a/pyrogram/client/client.py
+++ b/pyrogram/client/client.py
@@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see .
+import io
import logging
import math
import os
@@ -30,7 +31,7 @@ from importlib import import_module, reload
from pathlib import Path
from signal import signal, SIGINT, SIGTERM, SIGABRT
from threading import Thread
-from typing import Union, List
+from typing import Union, List, BinaryIO
from pyrogram.api import functions, types
from pyrogram.api.core import TLObject
@@ -39,9 +40,9 @@ from pyrogram.client.handlers.handler import Handler
from pyrogram.client.methods.password.utils import compute_check
from pyrogram.crypto import AES
from pyrogram.errors import (
- PhoneMigrate, NetworkMigrate, SessionPasswordNeeded,
- FloodWait, PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate, AuthBytesInvalid,
- BadRequest)
+ PhoneMigrate, NetworkMigrate, SessionPasswordNeeded, PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate,
+ AuthBytesInvalid, BadRequest
+)
from pyrogram.session import Auth, Session
from .ext import utils, Syncer, BaseClient, Dispatcher
from .methods import Methods
@@ -1713,7 +1714,7 @@ class Client(Methods, BaseClient):
def save_file(
self,
- path: str,
+ path: Union[str, BinaryIO],
file_id: int = None,
file_part: int = 0,
progress: callable = None,
@@ -1767,7 +1768,19 @@ class Client(Methods, BaseClient):
RPCError: In case of a Telegram RPC error.
"""
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:
raise ValueError("File size equals to 0 B")
@@ -1785,11 +1798,11 @@ class Client(Methods, BaseClient):
session.start()
try:
- with open(path, "rb") as f:
- f.seek(part_size * file_part)
+ with fp:
+ fp.seek(part_size * file_part)
while True:
- chunk = f.read(part_size)
+ chunk = fp.read(part_size)
if not chunk:
if not is_big:
@@ -1835,14 +1848,14 @@ class Client(Methods, BaseClient):
return types.InputFileBig(
id=file_id,
parts=file_total_parts,
- name=os.path.basename(path),
+ name=file_name,
)
else:
return types.InputFile(
id=file_id,
parts=file_total_parts,
- name=os.path.basename(path),
+ name=file_name,
md5_checksum=md5_sum
)
finally:
diff --git a/pyrogram/client/methods/messages/send_animation.py b/pyrogram/client/methods/messages/send_animation.py
index c84e0503..a38856a0 100644
--- a/pyrogram/client/methods/messages/send_animation.py
+++ b/pyrogram/client/methods/messages/send_animation.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,7 +30,7 @@ class SendAnimation(BaseClient):
def send_animation(
self,
chat_id: Union[int, str],
- animation: str,
+ animation: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
unsave: bool = False,
@@ -38,7 +38,7 @@ class SendAnimation(BaseClient):
duration: int = 0,
width: int = 0,
height: int = 0,
- thumb: str = None,
+ thumb: Union[str, BinaryIO] = None,
file_name: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -60,11 +60,12 @@ class SendAnimation(BaseClient):
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).
- animation (``str``):
+ animation (``str`` | ``BinaryIO``):
Animation to send.
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 a file path as string to upload a new animation that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -93,7 +94,7 @@ class SendAnimation(BaseClient):
height (``int``, *optional*):
Animation height.
- thumb (``str``, *optional*):
+ thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
@@ -164,11 +165,36 @@ class SendAnimation(BaseClient):
file = None
try:
- if os.path.isfile(animation):
+ if isinstance(animation, str):
+ if os.path.isfile(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=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 self.save_file(thumb)
file = self.save_file(animation, progress=progress, progress_args=progress_args)
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,
thumb=thumb,
attributes=[
@@ -178,16 +204,10 @@ class SendAnimation(BaseClient):
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(animation)),
+ types.DocumentAttributeFilename(file_name=animation.name),
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)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_audio.py b/pyrogram/client/methods/messages/send_audio.py
index 49fd0e09..08c03d07 100644
--- a/pyrogram/client/methods/messages/send_audio.py
+++ b/pyrogram/client/methods/messages/send_audio.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,14 +30,14 @@ class SendAudio(BaseClient):
def send_audio(
self,
chat_id: Union[int, str],
- audio: str,
+ audio: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
performer: str = None,
title: str = None,
- thumb: str = None,
+ thumb: Union[str, BinaryIO] = None,
file_name: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -61,11 +61,12 @@ class SendAudio(BaseClient):
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).
- audio (``str``):
+ audio (``str`` | ``BinaryIO``):
Audio file to send.
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 a file path as string to upload a new audio file that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -90,7 +91,7 @@ class SendAudio(BaseClient):
title (``str``, *optional*):
Track name.
- thumb (``str``, *optional*):
+ thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
@@ -164,11 +165,34 @@ class SendAudio(BaseClient):
file = None
try:
- if os.path.isfile(audio):
+ if isinstance(audio, str):
+ if os.path.isfile(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=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 self.save_file(thumb)
file = self.save_file(audio, progress=progress, progress_args=progress_args)
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,
thumb=thumb,
attributes=[
@@ -177,15 +201,9 @@ class SendAudio(BaseClient):
performer=performer,
title=title
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(audio))
+ types.DocumentAttributeFilename(file_name=audio.name)
]
)
- elif re.match("^https?://", audio):
- media = types.InputMediaDocumentExternal(
- url=audio
- )
- else:
- media = utils.get_input_media_from_file_id(audio, file_ref, 9)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_document.py b/pyrogram/client/methods/messages/send_document.py
index 8f15c5ee..2241754b 100644
--- a/pyrogram/client/methods/messages/send_document.py
+++ b/pyrogram/client/methods/messages/send_document.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,9 +30,9 @@ class SendDocument(BaseClient):
def send_document(
self,
chat_id: Union[int, str],
- document: str,
+ document: Union[str, BinaryIO],
file_ref: str = None,
- thumb: str = None,
+ thumb: Union[str, BinaryIO] = None,
caption: str = "",
parse_mode: Union[str, None] = object,
file_name: str = None,
@@ -56,17 +56,18 @@ class SendDocument(BaseClient):
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).
- document (``str``):
+ document (``str`` | ``BinaryIO``):
File to send.
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 a file path as string to upload a new file that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
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.
- thumb (``str``, *optional*):
+ thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
@@ -144,23 +145,35 @@ class SendDocument(BaseClient):
file = None
try:
- if os.path.isfile(document):
+ if isinstance(document, str):
+ if os.path.isfile(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=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 self.save_file(thumb)
file = self.save_file(document, progress=progress, progress_args=progress_args)
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,
thumb=thumb,
attributes=[
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(document))
+ types.DocumentAttributeFilename(file_name=document.name)
]
)
- elif re.match("^https?://", document):
- media = types.InputMediaDocumentExternal(
- url=document
- )
- else:
- media = utils.get_input_media_from_file_id(document, file_ref, 5)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_photo.py b/pyrogram/client/methods/messages/send_photo.py
index c21bb487..63101685 100644
--- a/pyrogram/client/methods/messages/send_photo.py
+++ b/pyrogram/client/methods/messages/send_photo.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,7 +30,7 @@ class SendPhoto(BaseClient):
def send_photo(
self,
chat_id: Union[int, str],
- photo: str,
+ photo: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@@ -55,11 +55,12 @@ class SendPhoto(BaseClient):
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).
- photo (``str``):
+ photo (``str`` | ``BinaryIO``):
Photo to send.
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 a file path as string to upload a new photo that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -138,19 +139,26 @@ class SendPhoto(BaseClient):
file = None
try:
- if os.path.isfile(photo):
+ if isinstance(photo, str):
+ if os.path.isfile(photo):
+ file = 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 = 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)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_sticker.py b/pyrogram/client/methods/messages/send_sticker.py
index d9575885..0de47d64 100644
--- a/pyrogram/client/methods/messages/send_sticker.py
+++ b/pyrogram/client/methods/messages/send_sticker.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,7 +30,7 @@ class SendSticker(BaseClient):
def send_sticker(
self,
chat_id: Union[int, str],
- sticker: str,
+ sticker: Union[str, BinaryIO],
file_ref: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@@ -52,11 +52,12 @@ class SendSticker(BaseClient):
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).
- sticker (``str``):
+ sticker (``str`` | ``BinaryIO``):
Sticker to send.
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 a file path as string to upload a new sticker that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -114,21 +115,31 @@ class SendSticker(BaseClient):
file = None
try:
- if os.path.isfile(sticker):
+ if isinstance(sticker, str):
+ if os.path.isfile(sticker):
+ file = 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 = self.save_file(sticker, progress=progress, progress_args=progress_args)
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,
attributes=[
- types.DocumentAttributeFilename(file_name=os.path.basename(sticker))
+ types.DocumentAttributeFilename(file_name=sticker.name)
]
)
- elif re.match("^https?://", sticker):
- media = types.InputMediaDocumentExternal(
- url=sticker
- )
- else:
- media = utils.get_input_media_from_file_id(sticker, file_ref, 8)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_video.py b/pyrogram/client/methods/messages/send_video.py
index 9a67bbbb..1f46252f 100644
--- a/pyrogram/client/methods/messages/send_video.py
+++ b/pyrogram/client/methods/messages/send_video.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,14 +30,14 @@ class SendVideo(BaseClient):
def send_video(
self,
chat_id: Union[int, str],
- video: str,
+ video: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
width: int = 0,
height: int = 0,
- thumb: str = None,
+ thumb: Union[str, BinaryIO] = None,
file_name: str = None,
supports_streaming: bool = True,
disable_notification: bool = None,
@@ -60,11 +60,12 @@ class SendVideo(BaseClient):
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).
- video (``str``):
+ video (``str`` | ``BinaryIO``):
Video to send.
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 a file path as string to upload a new video that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -89,7 +90,7 @@ class SendVideo(BaseClient):
height (``int``, *optional*):
Video height.
- thumb (``str``, *optional*):
+ thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
@@ -161,11 +162,35 @@ class SendVideo(BaseClient):
file = None
try:
- if os.path.isfile(video):
+ if isinstance(video, str):
+ if os.path.isfile(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=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 self.save_file(thumb)
file = self.save_file(video, progress=progress, progress_args=progress_args)
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,
thumb=thumb,
attributes=[
@@ -175,15 +200,9 @@ class SendVideo(BaseClient):
w=width,
h=height
),
- types.DocumentAttributeFilename(file_name=file_name or os.path.basename(video))
+ types.DocumentAttributeFilename(file_name=video.name)
]
)
- elif re.match("^https?://", video):
- media = types.InputMediaDocumentExternal(
- url=video
- )
- else:
- media = utils.get_input_media_from_file_id(video, file_ref, 4)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_video_note.py b/pyrogram/client/methods/messages/send_video_note.py
index b7acdc01..829f1459 100644
--- a/pyrogram/client/methods/messages/send_video_note.py
+++ b/pyrogram/client/methods/messages/send_video_note.py
@@ -17,7 +17,7 @@
# along with Pyrogram. If not, see .
import os
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -29,11 +29,11 @@ class SendVideoNote(BaseClient):
def send_video_note(
self,
chat_id: Union[int, str],
- video_note: str,
+ video_note: Union[str, BinaryIO],
file_ref: str = None,
duration: int = 0,
length: int = 1,
- thumb: str = None,
+ thumb: Union[str, BinaryIO] = None,
disable_notification: bool = None,
reply_to_message_id: 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 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.
- Pass a file_id as string to send a video note that exists on the Telegram servers, or
- pass a file path as string to upload a new video note that exists on your local machine.
+ 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, 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.
file_ref (``str``, *optional*):
@@ -70,7 +71,7 @@ class SendVideoNote(BaseClient):
length (``int``, *optional*):
Video width and height.
- thumb (``str``, *optional*):
+ thumb (``str`` | ``BinaryIO``, *optional*):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
A thumbnail's width and height should not exceed 320 pixels.
@@ -128,11 +129,30 @@ class SendVideoNote(BaseClient):
file = None
try:
- if os.path.isfile(video_note):
+ if isinstance(video_note, str):
+ if os.path.isfile(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=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 self.save_file(thumb)
file = 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",
+ mime_type=self.guess_mime_type(video_note.name) or "video/mp4",
file=file,
thumb=thumb,
attributes=[
@@ -144,8 +164,6 @@ class SendVideoNote(BaseClient):
)
]
)
- else:
- media = utils.get_input_media_from_file_id(video_note, file_ref, 13)
while True:
try:
diff --git a/pyrogram/client/methods/messages/send_voice.py b/pyrogram/client/methods/messages/send_voice.py
index 23492f53..f99b4236 100644
--- a/pyrogram/client/methods/messages/send_voice.py
+++ b/pyrogram/client/methods/messages/send_voice.py
@@ -18,7 +18,7 @@
import os
import re
-from typing import Union
+from typing import Union, BinaryIO
import pyrogram
from pyrogram.api import functions, types
@@ -30,7 +30,7 @@ class SendVoice(BaseClient):
def send_voice(
self,
chat_id: Union[int, str],
- voice: str,
+ voice: Union[str, BinaryIO],
file_ref=None,
caption: str = "",
parse_mode: Union[str, None] = object,
@@ -55,11 +55,12 @@ class SendVoice(BaseClient):
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).
- voice (``str``):
+ voice (``str`` | ``BinaryIO``):
Audio file to send.
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 a file path as string to upload a new audio that exists on your local machine.
+ 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, or
+ pass a binary file-like object with its attribute ".name" set for in-memory uploads.
file_ref (``str``, *optional*):
A valid file reference obtained by a recently fetched media message.
@@ -133,10 +134,29 @@ class SendVoice(BaseClient):
file = None
try:
- if os.path.isfile(voice):
+ if isinstance(voice, str):
+ if os.path.isfile(voice):
+ file = 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 = self.save_file(voice, progress=progress, progress_args=progress_args)
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,
attributes=[
types.DocumentAttributeAudio(
@@ -145,12 +165,6 @@ class SendVoice(BaseClient):
)
]
)
- elif re.match("^https?://", voice):
- media = types.InputMediaDocumentExternal(
- url=voice
- )
- else:
- media = utils.get_input_media_from_file_id(voice, file_ref, 3)
while True:
try: