Add support for the new Bot API fields: file_id, file_unique_id

Remove file_ref from Pyrogram's API
This commit is contained in:
Dan 2020-11-27 22:09:17 +01:00
parent e0c3578fbb
commit a4566de2ef
34 changed files with 398 additions and 667 deletions

View File

@ -47,6 +47,7 @@ from pyrogram.storage import Storage, FileStorage, MemoryStorage
from pyrogram.types import User, TermsOfService
from pyrogram.utils import ainput
from .dispatcher import Dispatcher
from .file_id import FileId, FileType, ThumbnailSource
from .scaffold import Scaffold
log = logging.getLogger(__name__)
@ -493,22 +494,11 @@ class Client(Methods, Scaffold):
final_file_path = ""
try:
data, directory, file_name, progress, progress_args = packet
file_id, directory, file_name, file_size, progress, progress_args = packet
temp_file_path = await self.get_file(
media_type=data.media_type,
dc_id=data.dc_id,
document_id=data.document_id,
access_hash=data.access_hash,
thumb_size=data.thumb_size,
peer_id=data.peer_id,
peer_type=data.peer_type,
peer_access_hash=data.peer_access_hash,
volume_id=data.volume_id,
local_id=data.local_id,
file_ref=data.file_ref,
file_size=data.file_size,
is_big=data.is_big,
file_id=file_id,
file_size=file_size,
progress=progress,
progress_args=progress_args
)
@ -817,22 +807,13 @@ class Client(Methods, Scaffold):
async def get_file(
self,
media_type: int,
dc_id: int,
document_id: int,
access_hash: int,
thumb_size: str,
peer_id: int,
peer_type: str,
peer_access_hash: int,
volume_id: int,
local_id: int,
file_ref: str,
file_id: FileId,
file_size: int,
is_big: bool,
progress: callable,
progress_args: tuple = ()
) -> str:
dc_id = file_id.dc_id
async with self.media_sessions_lock:
session = self.media_sessions.get(dc_id, None)
@ -874,49 +855,43 @@ class Client(Methods, Scaffold):
self.media_sessions[dc_id] = session
file_ref = utils.decode_file_ref(file_ref)
file_type = file_id.file_type
if media_type == 1:
if peer_type == "user":
if file_type == FileType.CHAT_PHOTO:
if file_id.chat_id > 0:
peer = raw.types.InputPeerUser(
user_id=peer_id,
access_hash=peer_access_hash
)
elif peer_type == "chat":
peer = raw.types.InputPeerChat(
chat_id=peer_id
user_id=file_id.chat_id,
access_hash=file_id.chat_access_hash
)
else:
peer = raw.types.InputPeerChannel(
channel_id=peer_id,
access_hash=peer_access_hash
)
if file_id.chat_access_hash == 0:
peer = raw.types.InputPeerChat(
chat_id=file_id.chat_id
)
else:
peer = raw.types.InputPeerChannel(
channel_id=file_id.chat_id,
access_hash=file_id.chat_access_hash
)
location = raw.types.InputPeerPhotoFileLocation(
peer=peer,
volume_id=volume_id,
local_id=local_id,
big=is_big or None
volume_id=file_id.volume_id,
local_id=file_id.local_id,
big=file_id.thumbnail_source == ThumbnailSource.CHAT_PHOTO_BIG
)
elif media_type in (0, 2):
elif file_type in (FileType.THUMBNAIL, FileType.PHOTO):
location = raw.types.InputPhotoFileLocation(
id=document_id,
access_hash=access_hash,
file_reference=file_ref,
thumb_size=thumb_size
)
elif media_type == 14:
location = raw.types.InputDocumentFileLocation(
id=document_id,
access_hash=access_hash,
file_reference=file_ref,
thumb_size=thumb_size
id=file_id.media_id,
access_hash=file_id.access_hash,
file_reference=file_id.file_reference,
thumb_size=file_id.thumbnail_size
)
else:
location = raw.types.InputDocumentFileLocation(
id=document_id,
access_hash=access_hash,
file_reference=file_ref,
id=file_id.media_id,
access_hash=file_id.access_hash,
file_reference=file_id.file_reference,
thumb_size=""
)

View File

@ -22,6 +22,7 @@ from typing import Union, BinaryIO
from pyrogram import raw
from pyrogram import utils
from pyrogram.scaffold import Scaffold
from pyrogram.file_id import FileType
class SetChatPhoto(Scaffold):
@ -30,8 +31,7 @@ class SetChatPhoto(Scaffold):
chat_id: Union[int, str],
*,
photo: Union[str, BinaryIO] = None,
video: Union[str, BinaryIO] = None,
file_ref: str = None
video: Union[str, BinaryIO] = None
) -> bool:
"""Set a new chat photo or video (H.264/MPEG-4 AVC video, max 5 seconds).
@ -45,19 +45,15 @@ class SetChatPhoto(Scaffold):
Unique identifier (int) or username (str) of the target chat.
photo (``str`` | ``BinaryIO``, *optional*):
New chat photo. You can pass a :obj:`~pyrogram.types.Photo` file_id (in pair with a valid file_ref), a
file path to upload a new photo from your local machine or a binary file-like object with its attribute
New chat photo. You can pass a :obj:`~pyrogram.types.Photo` file_id, a file path to upload a new photo
from your local machine or a binary file-like object with its attribute
".name" set for in-memory uploads.
video (``str`` | ``BinaryIO``, *optional*):
New chat video. You can pass a :obj:`~pyrogram.types.Video` file_id (in pair with a valid file_ref), a
file path to upload a new video from your local machine or a binary file-like object with its attribute
New chat video. You can pass a :obj:`~pyrogram.types.Video` file_id, a file path to upload a new video
from your local machine or 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.
Returns:
``bool``: True on success.
@ -71,14 +67,14 @@ class SetChatPhoto(Scaffold):
app.set_chat_photo(chat_id, photo="photo.jpg")
# Set chat photo using an exiting Photo file_id
app.set_chat_photo(chat_id, photo=photo.file_id, file_ref=photo.file_ref)
app.set_chat_photo(chat_id, photo=photo.file_id)
# Set chat video using a local file
app.set_chat_photo(chat_id, video="video.mp4")
# Set chat photo using an exiting Video file_id
app.set_chat_photo(chat_id, video=video.file_id, file_ref=video.file_ref)
app.set_chat_photo(chat_id, video=video.file_id)
"""
peer = await self.resolve_peer(chat_id)
@ -89,7 +85,7 @@ class SetChatPhoto(Scaffold):
video=await self.save_file(video)
)
else:
photo = utils.get_input_media_from_file_id(photo, file_ref, 2)
photo = utils.get_input_media_from_file_id(photo, FileType.PHOTO)
photo = raw.types.InputChatPhoto(id=photo.id)
else:
photo = raw.types.InputChatUploadedPhoto(

View File

@ -17,51 +17,22 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import asyncio
import binascii
import os
import struct
import time
from datetime import datetime
from typing import Union
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FileIdInvalid
from pyrogram.file_id import FileId, FileType, PHOTO_TYPES
from pyrogram.scaffold import Scaffold
DEFAULT_DOWNLOAD_DIR = "downloads/"
class FileData:
def __init__(
self, *, media_type: int = None, dc_id: int = None, document_id: int = None, access_hash: int = None,
thumb_size: str = None, peer_id: int = None, peer_type: str = None, peer_access_hash: int = None,
volume_id: int = None, local_id: int = None, is_big: bool = None, file_size: int = None, mime_type: str = None,
file_name: str = None, date: int = None, file_ref: str = None
):
self.media_type = media_type
self.dc_id = dc_id
self.document_id = document_id
self.access_hash = access_hash
self.thumb_size = thumb_size
self.peer_id = peer_id
self.peer_type = peer_type
self.peer_access_hash = peer_access_hash
self.volume_id = volume_id
self.local_id = local_id
self.is_big = is_big
self.file_size = file_size
self.mime_type = mime_type
self.file_name = file_name
self.date = date
self.file_ref = file_ref
class DownloadMedia(Scaffold):
async def download_media(
self,
message: Union["types.Message", str],
file_ref: str = None,
media: Union["types.Message", str],
file_name: str = DEFAULT_DOWNLOAD_DIR,
block: bool = True,
progress: callable = None,
@ -70,13 +41,9 @@ class DownloadMedia(Scaffold):
"""Download the media from a message.
Parameters:
message (:obj:`~pyrogram.types.Message` | ``str``):
Pass a Message containing the media, the media itself (message.audio, message.video, ...) or
the file id as string.
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.
media (:obj:`~pyrogram.types.Message` | ``str``):
Pass a Message containing the media, the media itself (message.audio, message.video, ...) or a file id
as string.
file_name (``str``, *optional*):
A custom *file_name* to be used instead of the one provided by Telegram.
@ -133,136 +100,63 @@ class DownloadMedia(Scaffold):
app.download_media(message, progress=progress)
"""
error_message = "This message doesn't contain any downloadable media"
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note", "new_chat_photo")
available_media = ("audio", "document", "photo", "sticker", "animation", "video", "voice", "video_note",
"new_chat_photo")
media_file_name = None
file_size = None
mime_type = None
date = None
if isinstance(message, types.Message):
if isinstance(media, types.Message):
for kind in available_media:
media = getattr(message, kind, None)
media = getattr(media, kind, None)
if media is not None:
break
else:
raise ValueError(error_message)
else:
media = message
raise ValueError("This message doesn't contain any downloadable media")
if isinstance(media, str):
file_id_str = media
else:
file_id_str = media.file_id
media_file_name = getattr(media, "file_name", "")
file_size = getattr(media, "file_size", None)
mime_type = getattr(media, "mime_type", None)
date = getattr(media, "date", None)
file_ref = getattr(media, "file_ref", None)
data = FileData(
file_name=media_file_name,
file_size=file_size,
mime_type=mime_type,
date=date,
file_ref=file_ref
)
file_id_obj = FileId.decode(file_id_str)
def get_existing_attributes() -> dict:
return dict(filter(lambda x: x[1] is not None, data.__dict__.items()))
try:
decoded = utils.decode_file_id(file_id_str)
media_type = decoded[0]
if media_type == 1:
unpacked = struct.unpack("<iiqqqiiiqi", decoded)
dc_id, photo_id, _, volume_id, size_type, peer_id, x, peer_access_hash, local_id = unpacked[1:]
if x == 0:
peer_type = "user"
elif x == -1:
peer_id = -peer_id
peer_type = "chat"
else:
peer_id = utils.get_channel_id(peer_id - 1000727379968)
peer_type = "channel"
data = FileData(
**get_existing_attributes(),
media_type=media_type,
dc_id=dc_id,
peer_id=peer_id,
peer_type=peer_type,
peer_access_hash=peer_access_hash,
volume_id=volume_id,
local_id=local_id,
is_big=size_type == 3
)
elif media_type in (0, 2, 14):
unpacked = struct.unpack("<iiqqqiiii", decoded)
dc_id, document_id, access_hash, volume_id, _, _, thumb_size, local_id = unpacked[1:]
data = FileData(
**get_existing_attributes(),
media_type=media_type,
dc_id=dc_id,
document_id=document_id,
access_hash=access_hash,
thumb_size=chr(thumb_size)
)
elif media_type in (3, 4, 5, 8, 9, 10, 13):
unpacked = struct.unpack("<iiqq", decoded)
dc_id, document_id, access_hash = unpacked[1:]
data = FileData(
**get_existing_attributes(),
media_type=media_type,
dc_id=dc_id,
document_id=document_id,
access_hash=access_hash
)
else:
raise ValueError(f"Unknown media type: {file_id_str}")
except (AssertionError, binascii.Error, struct.error):
raise FileIdInvalid from None
file_type = file_id_obj.file_type
media_file_name = getattr(media, "file_name", "")
file_size = getattr(media, "file_size", 0)
mime_type = getattr(media, "mime_type", None)
date = getattr(media, "date", 0)
directory, file_name = os.path.split(file_name)
file_name = file_name or data.file_name or ""
file_name = file_name or media_file_name or ""
if not os.path.isabs(file_name):
directory = self.PARENT_DIR / (directory or DEFAULT_DOWNLOAD_DIR)
media_type_str = self.MEDIA_TYPE_ID[data.media_type]
if not file_name:
guessed_extension = self.guess_extension(data.mime_type)
guessed_extension = self.guess_extension(mime_type)
if data.media_type in (0, 1, 2, 14):
if file_type in PHOTO_TYPES:
extension = ".jpg"
elif data.media_type == 3:
elif file_type == FileType.VOICE:
extension = guessed_extension or ".ogg"
elif data.media_type in (4, 10, 13):
elif file_type in (FileType.VIDEO, FileType.ANIMATION, FileType.VIDEO_NOTE):
extension = guessed_extension or ".mp4"
elif data.media_type == 5:
elif file_type == FileType.DOCUMENT:
extension = guessed_extension or ".zip"
elif data.media_type == 8:
elif file_type == FileType.STICKER:
extension = guessed_extension or ".webp"
elif data.media_type == 9:
elif file_type == FileType.AUDIO:
extension = guessed_extension or ".mp3"
else:
extension = ".unknown"
file_name = "{}_{}_{}{}".format(
media_type_str,
datetime.fromtimestamp(data.date or time.time()).strftime("%Y-%m-%d_%H-%M-%S"),
FileType(file_id_obj.file_type).name.lower(),
datetime.fromtimestamp(date or time.time()).strftime("%Y-%m-%d_%H-%M-%S"),
self.rnd_id(),
extension
)
downloader = self.handle_download((data, directory, file_name, progress, progress_args))
downloader = self.handle_download((file_id_obj, directory, file_name, file_size, progress, progress_args))
if block:
return await downloader

View File

@ -23,6 +23,7 @@ from pyrogram import types
from pyrogram import utils
from pyrogram.scaffold import Scaffold
from .inline_session import get_session
from pyrogram.file_id import FileType
class EditInlineMedia(Scaffold):
@ -76,35 +77,35 @@ class EditInlineMedia(Scaffold):
url=media.media
)
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, FileType.PHOTO)
elif isinstance(media, types.InputMediaVideo):
if re.match("^https?://", media.media):
media = raw.types.InputMediaDocumentExternal(
url=media.media
)
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, FileType.VIDEO)
elif isinstance(media, types.InputMediaAudio):
if re.match("^https?://", media.media):
media = raw.types.InputMediaDocumentExternal(
url=media.media
)
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, FileType.AUDIO)
elif isinstance(media, types.InputMediaAnimation):
if re.match("^https?://", media.media):
media = raw.types.InputMediaDocumentExternal(
url=media.media
)
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, FileType.ANIMATION)
elif isinstance(media, types.InputMediaDocument):
if re.match("^https?://", media.media):
media = raw.types.InputMediaDocumentExternal(
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)
media = utils.get_input_media_from_file_id(media.media, FileType.DOCUMENT)
unpacked = utils.unpack_inline_message_id(inline_message_id)
dc_id = unpacked.dc_id

View File

@ -23,6 +23,7 @@ from typing import Union
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -102,7 +103,7 @@ class EditMessageMedia(Scaffold):
url=media.media
)
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, FileType.PHOTO)
elif isinstance(media, types.InputMediaVideo):
if os.path.isfile(media.media):
media = await self.send(
@ -139,7 +140,7 @@ class EditMessageMedia(Scaffold):
url=media.media
)
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, FileType.VIDEO)
elif isinstance(media, types.InputMediaAudio):
if os.path.isfile(media.media):
media = await self.send(
@ -175,7 +176,7 @@ class EditMessageMedia(Scaffold):
url=media.media
)
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, FileType.AUDIO)
elif isinstance(media, types.InputMediaAnimation):
if os.path.isfile(media.media):
media = await self.send(
@ -213,7 +214,7 @@ class EditMessageMedia(Scaffold):
url=media.media
)
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, FileType.ANIMATION)
elif isinstance(media, types.InputMediaDocument):
if os.path.isfile(media.media):
media = await self.send(
@ -244,7 +245,7 @@ class EditMessageMedia(Scaffold):
url=media.media
)
else:
media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5)
media = utils.get_input_media_from_file_id(media.media, FileType.DOCUMENT)
r = await self.send(
raw.functions.messages.EditMessage(

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendAnimation(Scaffold):
self,
chat_id: Union[int, str],
animation: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
unsave: bool = False,
parse_mode: Union[str, None] = object,
@ -69,10 +69,6 @@ class SendAnimation(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
caption (``str``, *optional*):
Animation caption, 0-1024 characters.
@ -192,7 +188,7 @@ class SendAnimation(Scaffold):
url=animation
)
else:
media = utils.get_input_media_from_file_id(animation, file_ref, 10)
media = utils.get_input_media_from_file_id(animation, FileType.ANIMATION)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(animation, progress=progress, progress_args=progress_args)
@ -242,7 +238,9 @@ class SendAnimation(Scaffold):
if unsave:
document = message.animation or message.document
document_id = utils.get_input_media_from_file_id(document.file_id, document.file_ref).id
document_id = utils.get_input_media_from_file_id(
document.file_id, FileType.ANIMATION
).id
await self.send(
raw.functions.messages.SaveGif(

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendAudio(Scaffold):
self,
chat_id: Union[int, str],
audio: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
@ -69,10 +69,6 @@ class SendAudio(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
caption (``str``, *optional*):
Audio caption, 0-1024 characters.
@ -188,7 +184,7 @@ class SendAudio(Scaffold):
url=audio
)
else:
media = utils.get_input_media_from_file_id(audio, file_ref, 9)
media = utils.get_input_media_from_file_id(audio, FileType.AUDIO)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(audio, progress=progress, progress_args=progress_args)

View File

@ -29,7 +29,6 @@ class SendCachedMedia(Scaffold):
self,
chat_id: Union[int, str],
file_id: str,
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
disable_notification: bool = None,
@ -58,10 +57,6 @@ class SendCachedMedia(Scaffold):
Media to send.
Pass a file_id as string to send a media that exists on the Telegram servers.
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.
caption (``str``, *optional*):
Media caption, 0-1024 characters.
@ -98,7 +93,7 @@ class SendCachedMedia(Scaffold):
r = await self.send(
raw.functions.messages.SendMedia(
peer=await self.resolve_peer(chat_id),
media=utils.get_input_media_from_file_id(file_id, file_ref),
media=utils.get_input_media_from_file_id(file_id),
silent=disable_notification or None,
reply_to_msg_id=reply_to_message_id,
random_id=self.rnd_id(),

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendDocument(Scaffold):
self,
chat_id: Union[int, str],
document: Union[str, BinaryIO],
file_ref: str = None,
thumb: Union[str, BinaryIO] = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -66,10 +66,6 @@ class SendDocument(Scaffold):
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`` | ``BinaryIO``, *optional*):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
@ -171,7 +167,7 @@ class SendDocument(Scaffold):
url=document
)
else:
media = utils.get_input_media_from_file_id(document, file_ref, 5)
media = utils.get_input_media_from_file_id(document, FileType.DOCUMENT)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(document, progress=progress, progress_args=progress_args)

View File

@ -24,6 +24,7 @@ from typing import Union, List
from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
log = logging.getLogger(__name__)
@ -117,7 +118,7 @@ class SendMediaGroup(Scaffold):
)
)
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, FileType.PHOTO)
elif isinstance(i, types.InputMediaVideo):
if os.path.isfile(i.media):
media = await self.send(
@ -165,7 +166,7 @@ class SendMediaGroup(Scaffold):
)
)
else:
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 4)
media = utils.get_input_media_from_file_id(i.media, FileType.VIDEO)
elif isinstance(i, types.InputMediaAudio):
if os.path.isfile(i.media):
media = await self.send(
@ -212,7 +213,7 @@ class SendMediaGroup(Scaffold):
)
)
else:
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 9)
media = utils.get_input_media_from_file_id(i.media, FileType.AUDIO)
elif isinstance(i, types.InputMediaDocument):
if os.path.isfile(i.media):
media = await self.send(
@ -254,7 +255,7 @@ class SendMediaGroup(Scaffold):
)
)
else:
media = utils.get_input_media_from_file_id(i.media, i.file_ref, 5)
media = utils.get_input_media_from_file_id(i.media, FileType.DOCUMENT)
multi_media.append(
raw.types.InputSingleMedia(

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendPhoto(Scaffold):
self,
chat_id: Union[int, str],
photo: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
ttl_seconds: int = None,
@ -64,10 +64,6 @@ class SendPhoto(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
caption (``str``, *optional*):
Photo caption, 0-1024 characters.
@ -154,7 +150,7 @@ class SendPhoto(Scaffold):
ttl_seconds=ttl_seconds
)
else:
media = utils.get_input_media_from_file_id(photo, file_ref, 2)
media = utils.get_input_media_from_file_id(photo, FileType.PHOTO)
else:
file = await self.save_file(photo, progress=progress, progress_args=progress_args)
media = raw.types.InputMediaUploadedPhoto(

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendSticker(Scaffold):
self,
chat_id: Union[int, str],
sticker: Union[str, BinaryIO],
file_ref: str = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
schedule_date: int = None,
@ -61,10 +61,6 @@ class SendSticker(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
disable_notification (``bool``, *optional*):
Sends the message silently.
Users will receive a notification with no sound.
@ -133,7 +129,7 @@ class SendSticker(Scaffold):
url=sticker
)
else:
media = utils.get_input_media_from_file_id(sticker, file_ref, 8)
media = utils.get_input_media_from_file_id(sticker, FileType.STICKER)
else:
file = await self.save_file(sticker, progress=progress, progress_args=progress_args)
media = raw.types.InputMediaUploadedDocument(

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendVideo(Scaffold):
self,
chat_id: Union[int, str],
video: Union[str, BinaryIO],
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
@ -69,10 +69,6 @@ class SendVideo(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
caption (``str``, *optional*):
Video caption, 0-1024 characters.
@ -187,7 +183,7 @@ class SendVideo(Scaffold):
url=video
)
else:
media = utils.get_input_media_from_file_id(video, file_ref, 4)
media = utils.get_input_media_from_file_id(video, FileType.VIDEO)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(video, progress=progress, progress_args=progress_args)

View File

@ -24,6 +24,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -32,7 +33,6 @@ class SendVideoNote(Scaffold):
self,
chat_id: Union[int, str],
video_note: Union[str, BinaryIO],
file_ref: str = None,
duration: int = 0,
length: int = 1,
thumb: Union[str, BinaryIO] = None,
@ -63,10 +63,6 @@ class SendVideoNote(Scaffold):
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*):
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.
duration (``int``, *optional*):
Duration of sent video in seconds.
@ -150,7 +146,7 @@ class SendVideoNote(Scaffold):
]
)
else:
media = utils.get_input_media_from_file_id(video_note, file_ref, 13)
media = utils.get_input_media_from_file_id(video_note, FileType.VIDEO_NOTE)
else:
thumb = await self.save_file(thumb)
file = await self.save_file(video_note, progress=progress, progress_args=progress_args)

View File

@ -25,6 +25,7 @@ from pyrogram import raw
from pyrogram import types
from pyrogram import utils
from pyrogram.errors import FilePartMissing
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -33,7 +34,6 @@ class SendVoice(Scaffold):
self,
chat_id: Union[int, str],
voice: Union[str, BinaryIO],
file_ref=None,
caption: str = "",
parse_mode: Union[str, None] = object,
duration: int = 0,
@ -64,10 +64,6 @@ class SendVoice(Scaffold):
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.
To be used in combination with a file id in case a file reference is needed.
caption (``str``, *optional*):
Voice message caption, 0-1024 characters.
@ -154,7 +150,7 @@ class SendVoice(Scaffold):
url=voice
)
else:
media = utils.get_input_media_from_file_id(voice, file_ref, 3)
media = utils.get_input_media_from_file_id(voice, FileType.VOICE)
else:
file = await self.save_file(voice, progress=progress, progress_args=progress_args)
media = raw.types.InputMediaUploadedDocument(

View File

@ -20,6 +20,7 @@ from typing import List, Union
from pyrogram import raw
from pyrogram import utils
from pyrogram.file_id import FileType
from pyrogram.scaffold import Scaffold
@ -51,7 +52,7 @@ class DeleteProfilePhotos(Scaffold):
app.delete_profile_photos([p.file_id for p in photos[1:]])
"""
photo_ids = photo_ids if isinstance(photo_ids, list) else [photo_ids]
input_photos = [utils.get_input_media_from_file_id(i).id for i in photo_ids]
input_photos = [utils.get_input_media_from_file_id(i, FileType.PHOTO).id for i in photo_ids]
return bool(await self.send(
raw.functions.photos.DeletePhotos(

View File

@ -31,10 +31,9 @@ class InputMedia(Object):
- :obj:`~pyrogram.types.InputMediaVideo`
"""
def __init__(self, media: str, file_ref: str, caption: str, parse_mode: str):
def __init__(self, media: str, caption: str, parse_mode: str):
super().__init__()
self.media = media
self.file_ref = file_ref
self.caption = caption
self.parse_mode = parse_mode

View File

@ -30,10 +30,6 @@ class InputMediaAnimation(InputMedia):
Pass a file_id as string to send a file that exists on the Telegram servers or
pass a file path as string to upload a new file that exists on your local machine.
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*):
Thumbnail of the animation file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
@ -63,7 +59,6 @@ class InputMediaAnimation(InputMedia):
def __init__(
self,
media: str,
file_ref: str = None,
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -71,7 +66,7 @@ class InputMediaAnimation(InputMedia):
height: int = 0,
duration: int = 0
):
super().__init__(media, file_ref, caption, parse_mode)
super().__init__(media, caption, parse_mode)
self.thumb = thumb
self.width = width

View File

@ -32,10 +32,6 @@ class InputMediaAudio(InputMedia):
Pass a file_id as string to send an audio that exists on the Telegram servers or
pass a file path as string to upload a new audio that exists on your local machine.
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*):
Thumbnail of the music file album cover.
The thumbnail should be in JPEG format and less than 200 KB in size.
@ -65,7 +61,6 @@ class InputMediaAudio(InputMedia):
def __init__(
self,
media: str,
file_ref: str = None,
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -73,7 +68,7 @@ class InputMediaAudio(InputMedia):
performer: str = "",
title: str = ""
):
super().__init__(media, file_ref, caption, parse_mode)
super().__init__(media, caption, parse_mode)
self.thumb = thumb
self.duration = duration

View File

@ -30,10 +30,6 @@ class InputMediaDocument(InputMedia):
Pass a file_id as string to send a file that exists on the Telegram servers or
pass a file path as string to upload a new file that exists on your local machine.
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``):
Thumbnail of the file sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
@ -54,11 +50,10 @@ class InputMediaDocument(InputMedia):
def __init__(
self,
media: str,
file_ref: str = None,
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object
):
super().__init__(media, file_ref, caption, parse_mode)
super().__init__(media, caption, parse_mode)
self.thumb = thumb

View File

@ -32,10 +32,6 @@ class InputMediaPhoto(InputMedia):
pass a file path as string to upload a new photo that exists on your local machine.
Sending photo by a URL is currently unsupported.
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.
caption (``str``, *optional*):
Caption of the photo to be sent, 0-1024 characters
@ -50,8 +46,7 @@ class InputMediaPhoto(InputMedia):
def __init__(
self,
media: str,
file_ref: str = None,
caption: str = "",
parse_mode: Union[str, None] = object
):
super().__init__(media, file_ref, caption, parse_mode)
super().__init__(media, caption, parse_mode)

View File

@ -32,10 +32,6 @@ class InputMediaVideo(InputMedia):
pass a file path as string to upload a new video that exists on your local machine.
Sending video by a URL is currently unsupported.
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``):
Thumbnail of the video sent.
The thumbnail should be in JPEG format and less than 200 KB in size.
@ -68,7 +64,6 @@ class InputMediaVideo(InputMedia):
def __init__(
self,
media: str,
file_ref: str = None,
thumb: str = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -77,7 +72,7 @@ class InputMediaVideo(InputMedia):
duration: int = 0,
supports_streaming: bool = True
):
super().__init__(media, file_ref, caption, parse_mode)
super().__init__(media, caption, parse_mode)
self.thumb = thumb
self.width = width

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -31,10 +30,11 @@ class Animation(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
width (``int``):
Animation width as defined by sender.
@ -66,7 +66,7 @@ class Animation(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
width: int,
height: int,
duration: int,
@ -79,7 +79,7 @@ class Animation(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
@ -97,16 +97,17 @@ class Animation(Object):
file_name: str
) -> "Animation":
return Animation(
file_id=encode_file_id(
pack(
"<iiqq",
10,
animation.dc_id,
animation.id,
animation.access_hash
)
),
file_ref=encode_file_ref(animation.file_reference),
file_id=FileId(
file_type=FileType.ANIMATION,
dc_id=animation.dc_id,
media_id=animation.id,
access_hash=animation.access_hash,
file_reference=animation.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=animation.id
).encode(),
width=getattr(video_attributes, "w", 0),
height=getattr(video_attributes, "h", 0),
duration=getattr(video_attributes, "duration", 0),

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -31,14 +30,21 @@ class Audio(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
duration (``int``):
Duration of the audio in seconds as defined by sender.
performer (``str``, *optional*):
Performer of the audio as defined by sender or by audio tags.
title (``str``, *optional*):
Title of the audio as defined by sender or by audio tags.
file_name (``str``, *optional*):
Audio file name.
@ -49,13 +55,7 @@ class Audio(Object):
File size.
date (``int``, *optional*):
Date the audio was sent in Unix time.
performer (``str``, *optional*):
Performer of the audio as defined by sender or by audio tags.
title (``str``, *optional*):
Title of the audio as defined by sender or by audio tags.
Date the audio was originally sent, in Unix time.
thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Thumbnails of the music file album cover.
@ -66,27 +66,27 @@ class Audio(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
duration: int,
performer: str = None,
title: str = None,
file_name: str = None,
mime_type: str = None,
file_size: int = None,
date: int = None,
performer: str = None,
title: str = None,
thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.duration = duration
self.performer = performer
self.title = title
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
self.date = date
self.duration = duration
self.performer = performer
self.title = title
self.thumbs = thumbs
@staticmethod
@ -97,16 +97,17 @@ class Audio(Object):
file_name: str
) -> "Audio":
return Audio(
file_id=encode_file_id(
pack(
"<iiqq",
9,
audio.dc_id,
audio.id,
audio.access_hash
)
),
file_ref=encode_file_ref(audio.file_reference),
file_id=FileId(
file_type=FileType.AUDIO,
dc_id=audio.dc_id,
media_id=audio.id,
access_hash=audio.access_hash,
file_reference=audio.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=audio.id
).encode(),
duration=audio_attributes.duration,
performer=audio_attributes.performer,
title=audio_attributes.title,

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -31,10 +30,11 @@ class Document(Object):
Parameters:
file_id (``str``):
Unique file identifier.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
file_name (``str``, *optional*):
Original filename as defined by sender.
@ -57,7 +57,7 @@ class Document(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
file_name: str = None,
mime_type: str = None,
file_size: int = None,
@ -67,7 +67,7 @@ class Document(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
@ -77,16 +77,17 @@ class Document(Object):
@staticmethod
def _parse(client, document: "raw.types.Document", file_name: str) -> "Document":
return Document(
file_id=encode_file_id(
pack(
"<iiqq",
5,
document.dc_id,
document.id,
document.access_hash
)
),
file_ref=encode_file_ref(document.file_reference),
file_id=FileId(
file_type=FileType.DOCUMENT,
dc_id=document.dc_id,
media_id=document.id,
access_hash=document.access_hash,
file_reference=document.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=document.id
).encode(),
file_name=file_name,
mime_type=document.mime_type,
file_size=document.size,

View File

@ -790,7 +790,6 @@ class Message(Object, Update):
async def reply_animation(
self,
animation: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -832,10 +831,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -916,7 +911,6 @@ class Message(Object, Update):
return await self._client.send_animation(
chat_id=self.chat.id,
animation=animation,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
duration=duration,
@ -933,7 +927,6 @@ class Message(Object, Update):
async def reply_audio(
self,
audio: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -975,10 +968,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -1059,7 +1048,6 @@ class Message(Object, Update):
return await self._client.send_audio(
chat_id=self.chat.id,
audio=audio,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
duration=duration,
@ -1076,7 +1064,6 @@ class Message(Object, Update):
async def reply_cached_media(
self,
file_id: str,
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -1110,10 +1097,6 @@ class Message(Object, Update):
Media to send.
Pass a file_id as string to send a media that exists on the Telegram servers.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -1155,7 +1138,6 @@ class Message(Object, Update):
return await self._client.send_cached_media(
chat_id=self.chat.id,
file_id=file_id,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
disable_notification=disable_notification,
@ -1289,7 +1271,6 @@ class Message(Object, Update):
async def reply_document(
self,
document: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
thumb: str = None,
caption: str = "",
@ -1328,10 +1309,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -1403,7 +1380,6 @@ class Message(Object, Update):
return await self._client.send_document(
chat_id=self.chat.id,
document=document,
file_ref=file_ref,
thumb=thumb,
caption=caption,
parse_mode=parse_mode,
@ -1691,7 +1667,6 @@ class Message(Object, Update):
async def reply_photo(
self,
photo: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -1730,10 +1705,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -1804,7 +1775,6 @@ class Message(Object, Update):
return await self._client.send_photo(
chat_id=self.chat.id,
photo=photo,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
ttl_seconds=ttl_seconds,
@ -1922,7 +1892,6 @@ class Message(Object, Update):
async def reply_sticker(
self,
sticker: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
disable_notification: bool = None,
reply_to_message_id: int = None,
@ -1958,10 +1927,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -2017,7 +1982,6 @@ class Message(Object, Update):
return await self._client.send_sticker(
chat_id=self.chat.id,
sticker=sticker,
file_ref=file_ref,
disable_notification=disable_notification,
reply_to_message_id=reply_to_message_id,
reply_markup=reply_markup,
@ -2126,7 +2090,6 @@ class Message(Object, Update):
async def reply_video(
self,
video: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -2169,10 +2132,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -2256,7 +2215,6 @@ class Message(Object, Update):
return await self._client.send_video(
chat_id=self.chat.id,
video=video,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
duration=duration,
@ -2274,7 +2232,6 @@ class Message(Object, Update):
async def reply_video_note(
self,
video_note: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
duration: int = 0,
length: int = 1,
@ -2313,10 +2270,6 @@ class Message(Object, Update):
pass a file path as string to upload a new video note that exists on your local machine.
Sending video notes by a URL is currently unsupported.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -2384,7 +2337,6 @@ class Message(Object, Update):
return await self._client.send_video_note(
chat_id=self.chat.id,
video_note=video_note,
file_ref=file_ref,
duration=duration,
length=length,
thumb=thumb,
@ -2398,7 +2350,6 @@ class Message(Object, Update):
async def reply_voice(
self,
voice: Union[str, BinaryIO],
file_ref: str = None,
quote: bool = None,
caption: str = "",
parse_mode: Union[str, None] = object,
@ -2437,10 +2388,6 @@ class Message(Object, Update):
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.
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.
quote (``bool``, *optional*):
If ``True``, the message will be sent as a reply to this message.
If *reply_to_message_id* is passed, this parameter will be ignored.
@ -2509,7 +2456,6 @@ class Message(Object, Update):
return await self._client.send_voice(
chat_id=self.chat.id,
voice=voice,
file_ref=file_ref,
caption=caption,
parse_mode=parse_mode,
duration=duration,
@ -2787,28 +2733,20 @@ class Message(Object, Update):
if self.photo:
file_id = self.photo.file_id
file_ref = self.photo.file_ref
elif self.audio:
file_id = self.audio.file_id
file_ref = self.audio.file_ref
elif self.document:
file_id = self.document.file_id
file_ref = self.document.file_ref
elif self.video:
file_id = self.video.file_id
file_ref = self.video.file_ref
elif self.animation:
file_id = self.animation.file_id
file_ref = self.animation.file_ref
elif self.voice:
file_id = self.voice.file_id
file_ref = self.voice.file_ref
elif self.sticker:
file_id = self.sticker.file_id
file_ref = self.sticker.file_ref
elif self.video_note:
file_id = self.video_note.file_id
file_ref = self.video_note.file_ref
elif self.contact:
return await self._client.send_contact(
chat_id,
@ -2857,9 +2795,9 @@ class Message(Object, Update):
raise ValueError("Unknown media type")
if self.sticker or self.video_note: # Sticker and VideoNote should have no caption
return await send_media(file_id=file_id, file_ref=file_ref)
return await send_media(file_id=file_id)
else:
return await send_media(file_id=file_id, file_ref=file_ref, caption=caption, parse_mode="html")
return await send_media(file_id=file_id, caption=caption, parse_mode="html")
else:
raise ValueError("Can't copy this message")
else:

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
@ -31,10 +30,11 @@ class Photo(Object):
Parameters:
file_id (``str``):
Unique identifier for this photo.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
width (``int``):
Photo width.
@ -60,7 +60,7 @@ class Photo(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
width: int,
height: int,
file_size: int,
@ -71,7 +71,7 @@ class Photo(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.width = width
self.height = height
self.file_size = file_size
@ -82,18 +82,36 @@ class Photo(Object):
@staticmethod
def _parse(client, photo: "raw.types.Photo", ttl_seconds: int = None) -> "Photo":
if isinstance(photo, raw.types.Photo):
big = list(filter(lambda p: isinstance(p, raw.types.PhotoSize), photo.sizes))[-1]
big = photo.sizes[-1]
if isinstance(big, raw.types.PhotoSizeProgressive):
big = raw.types.PhotoSize(
type=big.type,
location=big.location,
w=big.w,
h=big.h,
size=big.sizes[-1]
)
return Photo(
file_id=encode_file_id(
pack(
"<iiqqqiiii",
2, photo.dc_id, photo.id, photo.access_hash,
big.location.volume_id, 1, 2, ord(big.type),
big.location.local_id
)
),
file_ref=encode_file_ref(photo.file_reference),
file_id=FileId(
file_type=FileType.PHOTO,
dc_id=photo.dc_id,
media_id=photo.id,
access_hash=photo.access_hash,
file_reference=photo.file_reference,
thumbnail_source=ThumbnailSource.THUMBNAIL,
thumbnail_file_type=FileType.PHOTO,
thumbnail_size=big.type,
volume_id=big.location.volume_id,
local_id=big.location.local_id
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.PHOTO,
media_id=photo.id,
volume_id=big.location.volume_id,
local_id=big.location.local_id
).encode(),
width=big.w,
height=big.h,
file_size=big.size,

View File

@ -16,7 +16,6 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
from async_lru import alru_cache
@ -25,7 +24,7 @@ import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.errors import StickersetInvalid
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -34,10 +33,11 @@ class Sticker(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
width (``int``):
Sticker width.
@ -77,7 +77,7 @@ class Sticker(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
width: int,
height: int,
is_animated: bool,
@ -92,7 +92,7 @@ class Sticker(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.file_name = file_name
self.mime_type = mime_type
self.file_size = file_size
@ -137,16 +137,17 @@ class Sticker(Object):
set_name = None
return Sticker(
file_id=encode_file_id(
pack(
"<iiqq",
8,
sticker.dc_id,
sticker.id,
sticker.access_hash
)
),
file_ref=encode_file_ref(sticker.file_reference),
file_id=FileId(
file_type=FileType.STICKER,
dc_id=sticker.dc_id,
media_id=sticker.id,
access_hash=sticker.access_hash,
file_reference=sticker.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=sticker.id
).encode(),
width=image_size_attributes.w if image_size_attributes else 512,
height=image_size_attributes.h if image_size_attributes else 512,
is_animated=sticker.mime_type == "application/x-tgsticker",

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import Union, List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
@ -31,7 +30,11 @@ class Thumbnail(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
width (``int``):
Photo width.
@ -48,6 +51,7 @@ class Thumbnail(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_unique_id: str,
width: int,
height: int,
file_size: int
@ -55,6 +59,7 @@ class Thumbnail(Object):
super().__init__(client)
self.file_id = file_id
self.file_unique_id = file_unique_id
self.width = width
self.height = height
self.file_size = file_size
@ -66,10 +71,8 @@ class Thumbnail(Object):
) -> Union[List[Union["types.StrippedThumbnail", "Thumbnail"]], None]:
if isinstance(media, raw.types.Photo):
raw_thumbnails = media.sizes[:-1]
media_type = 2
elif isinstance(media, raw.types.Document):
raw_thumbnails = media.thumbs
media_type = 14
if not raw_thumbnails:
return None
@ -78,6 +81,9 @@ class Thumbnail(Object):
thumbnails = []
file_type = FileType.PHOTO if isinstance(media, raw.types.Photo) else FileType.THUMBNAIL
thumbnail_file_type = file_type
for thumbnail in raw_thumbnails:
# TODO: Enable this
# if isinstance(thumbnail, types.PhotoStrippedSize):
@ -85,14 +91,24 @@ class Thumbnail(Object):
if isinstance(thumbnail, raw.types.PhotoSize):
thumbnails.append(
Thumbnail(
file_id=encode_file_id(
pack(
"<iiqqqiiii",
media_type, media.dc_id, media.id, media.access_hash,
thumbnail.location.volume_id, 1, 2, ord(thumbnail.type),
thumbnail.location.local_id
)
),
file_id=FileId(
file_type=file_type,
dc_id=media.dc_id,
media_id=media.id,
access_hash=media.access_hash,
file_reference=media.file_reference,
thumbnail_file_type=thumbnail_file_type,
thumbnail_source=ThumbnailSource.THUMBNAIL,
thumbnail_size=thumbnail.type,
volume_id=thumbnail.location.volume_id,
local_id=thumbnail.location.local_id
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.PHOTO,
media_id=media.id,
volume_id=thumbnail.location.volume_id,
local_id=thumbnail.location.local_id
).encode(),
width=thumbnail.w,
height=thumbnail.h,
file_size=thumbnail.size,

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -31,10 +30,11 @@ class Video(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
width (``int``):
Video width as defined by sender.
@ -51,18 +51,18 @@ class Video(Object):
mime_type (``str``, *optional*):
Mime type of a file as defined by sender.
supports_streaming (``bool``, *optional*):
True, if the video was uploaded with streaming support.
file_size (``int``, *optional*):
File size.
date (``int``, *optional*):
Date the video was sent in Unix time.
supports_streaming (``bool``, *optional*):
True, if the video was uploaded with streaming support.
ttl_seconds (``int``. *optional*):
Time-to-live seconds, for secret photos.
date (``int``, *optional*):
Date the video was sent in Unix time.
thumbs (List of :obj:`~pyrogram.types.Thumbnail`, *optional*):
Video thumbnails.
"""
@ -72,31 +72,31 @@ class Video(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
width: int,
height: int,
duration: int,
file_name: str = None,
mime_type: str = None,
supports_streaming: bool = None,
file_size: int = None,
date: int = None,
supports_streaming: bool = None,
ttl_seconds: int = None,
date: int = None,
thumbs: List["types.Thumbnail"] = None
):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.width = width
self.height = height
self.duration = duration
self.file_name = file_name
self.mime_type = mime_type
self.supports_streaming = supports_streaming
self.file_size = file_size
self.date = date
self.supports_streaming = supports_streaming
self.ttl_seconds = ttl_seconds
self.date = date
self.thumbs = thumbs
@staticmethod
@ -108,16 +108,17 @@ class Video(Object):
ttl_seconds: int = None
) -> "Video":
return Video(
file_id=encode_file_id(
pack(
"<iiqq",
4,
video.dc_id,
video.id,
video.access_hash
)
),
file_ref=encode_file_ref(video.file_reference),
file_id=FileId(
file_type=FileType.VIDEO,
dc_id=video.dc_id,
media_id=video.id,
access_hash=video.access_hash,
file_reference=video.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=video.id
).encode(),
width=video_attributes.w,
height=video_attributes.h,
duration=video_attributes.duration,

View File

@ -16,13 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List
import pyrogram
from pyrogram import raw
from pyrogram import types
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -31,10 +30,11 @@ class VideoNote(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
length (``int``):
Video width and height as defined by sender.
@ -60,7 +60,7 @@ class VideoNote(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
length: int,
duration: int,
thumbs: List["types.Thumbnail"] = None,
@ -71,7 +71,7 @@ class VideoNote(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.mime_type = mime_type
self.file_size = file_size
self.date = date
@ -86,16 +86,17 @@ class VideoNote(Object):
video_attributes: "raw.types.DocumentAttributeVideo"
) -> "VideoNote":
return VideoNote(
file_id=encode_file_id(
pack(
"<iiqq",
13,
video_note.dc_id,
video_note.id,
video_note.access_hash
)
),
file_ref=encode_file_ref(video_note.file_reference),
file_id=FileId(
file_type=FileType.VIDEO_NOTE,
dc_id=video_note.dc_id,
media_id=video_note.id,
access_hash=video_note.access_hash,
file_reference=video_note.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=video_note.id
).encode(),
length=video_attributes.w,
duration=video_attributes.duration,
file_size=video_note.size,

View File

@ -16,11 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
import pyrogram
from pyrogram import raw
from pyrogram.utils import encode_file_id, encode_file_ref
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType
from ..object import Object
@ -29,10 +27,11 @@ class Voice(Object):
Parameters:
file_id (``str``):
Unique identifier for this file.
Identifier for this file, which can be used to download or reuse the file.
file_ref (``str``):
Up to date file reference.
file_unique_id (``str``):
Unique identifier for this file, which is supposed to be the same over time and for different accounts.
Can't be used to download or reuse the file.
duration (``int``):
Duration of the audio in seconds as defined by sender.
@ -55,7 +54,7 @@ class Voice(Object):
*,
client: "pyrogram.Client" = None,
file_id: str,
file_ref: str,
file_unique_id: str,
duration: int,
waveform: bytes = None,
mime_type: str = None,
@ -65,7 +64,7 @@ class Voice(Object):
super().__init__(client)
self.file_id = file_id
self.file_ref = file_ref
self.file_unique_id = file_unique_id
self.duration = duration
self.waveform = waveform
self.mime_type = mime_type
@ -75,16 +74,17 @@ class Voice(Object):
@staticmethod
def _parse(client, voice: "raw.types.Document", attributes: "raw.types.DocumentAttributeAudio") -> "Voice":
return Voice(
file_id=encode_file_id(
pack(
"<iiqq",
3,
voice.dc_id,
voice.id,
voice.access_hash
)
),
file_ref=encode_file_ref(voice.file_reference),
file_id=FileId(
file_type=FileType.VOICE,
dc_id=voice.dc_id,
media_id=voice.id,
access_hash=voice.access_hash,
file_reference=voice.file_reference
).encode(),
file_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.DOCUMENT,
media_id=voice.id
).encode(),
duration=attributes.duration,
mime_type=voice.mime_type,
file_size=voice.size,

View File

@ -16,14 +16,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import Union
import pyrogram
from pyrogram import raw
from pyrogram.utils import encode_file_id
from pyrogram.file_id import FileId, FileType, FileUniqueId, FileUniqueType, ThumbnailSource
from ..object import Object
from ... import utils
class ChatPhoto(Object):
@ -34,9 +32,17 @@ class ChatPhoto(Object):
File identifier of small (160x160) chat photo.
This file_id can be used only for photo download and only for as long as the photo is not changed.
small_photo_unique_id (``str``):
Unique file identifier of small (160x160) chat photo, which is supposed to be the same over time and for
different accounts. Can't be used to download or reuse the file.
big_file_id (``str``):
File identifier of big (640x640) chat photo.
This file_id can be used only for photo download and only for as long as the photo is not changed.
big_photo_unique_id (``str``):
Unique file identifier of big (640x640) chat photo, which is supposed to be the same over time and for
different accounts. Can't be used to download or reuse the file.
"""
def __init__(
@ -44,12 +50,17 @@ class ChatPhoto(Object):
*,
client: "pyrogram.Client" = None,
small_file_id: str,
big_file_id: str
small_photo_unique_id: str,
big_file_id: str,
big_photo_unique_id: str
):
super().__init__(client)
self.small_file_id = small_file_id
self.small_photo_unique_id = small_photo_unique_id
self.big_file_id = big_file_id
self.big_photo_unique_id = big_photo_unique_id
@staticmethod
def _parse(
@ -61,39 +72,40 @@ class ChatPhoto(Object):
if not isinstance(chat_photo, (raw.types.UserProfilePhoto, raw.types.ChatPhoto)):
return None
if peer_access_hash is None:
return None
photo_id = getattr(chat_photo, "photo_id", 0)
loc_small = chat_photo.photo_small
loc_big = chat_photo.photo_big
peer_type = utils.get_peer_type(peer_id)
if peer_type == "user":
x = 0
elif peer_type == "chat":
x = -1
else:
peer_id += 1000727379968
x = -234
media_id = chat_photo.photo_id if isinstance(chat_photo, raw.types.UserProfilePhoto) else 0
return ChatPhoto(
small_file_id=encode_file_id(
pack(
"<iiqqqiiiqi",
1, chat_photo.dc_id, photo_id,
0, loc_small.volume_id,
2, peer_id, x, peer_access_hash, loc_small.local_id
)
),
big_file_id=encode_file_id(
pack(
"<iiqqqiiiqi",
1, chat_photo.dc_id, photo_id,
0, loc_big.volume_id,
3, peer_id, x, peer_access_hash, loc_big.local_id
)
),
small_file_id=FileId(
file_type=FileType.CHAT_PHOTO,
dc_id=chat_photo.dc_id,
media_id=media_id,
access_hash=0,
volume_id=chat_photo.photo_small.volume_id,
thumbnail_source=ThumbnailSource.CHAT_PHOTO_SMALL,
local_id=chat_photo.photo_small.local_id,
chat_id=peer_id,
chat_access_hash=peer_access_hash
).encode(),
small_photo_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.PHOTO,
volume_id=chat_photo.photo_small.volume_id,
local_id=chat_photo.photo_small.local_id
).encode(),
big_file_id=FileId(
file_type=FileType.CHAT_PHOTO,
dc_id=chat_photo.dc_id,
media_id=media_id,
access_hash=0,
volume_id=chat_photo.photo_big.volume_id,
thumbnail_source=ThumbnailSource.CHAT_PHOTO_BIG,
local_id=chat_photo.photo_big.local_id,
chat_id=peer_id,
chat_access_hash=peer_access_hash
).encode(),
big_photo_unique_id=FileUniqueId(
file_unique_type=FileUniqueType.PHOTO,
volume_id=chat_photo.photo_big.volume_id,
local_id=chat_photo.photo_big.local_id
).encode(),
client=client
)

View File

@ -29,60 +29,7 @@ from typing import Union
from pyrogram import raw
from pyrogram import types
from pyrogram.scaffold import Scaffold
def decode_file_id(s: str) -> bytes:
s = base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
r = b""
major = s[-1]
minor = s[-2] if major != 2 else 0
assert minor in (0, 22, 24)
skip = 2 if minor else 1
i = 0
while i < len(s) - skip:
if s[i] != 0:
r += bytes([s[i]])
else:
r += b"\x00" * s[i + 1]
i += 1
i += 1
return r
def encode_file_id(s: bytes) -> str:
r = b""
n = 0
for i in s + bytes([22]) + bytes([4]):
if i == 0:
n += 1
else:
if n:
r += b"\x00" + bytes([n])
n = 0
r += bytes([i])
return base64.urlsafe_b64encode(r).decode().rstrip("=")
def encode_file_ref(file_ref: bytes) -> str:
return base64.urlsafe_b64encode(file_ref).decode().rstrip("=")
def decode_file_ref(file_ref: str) -> bytes:
if file_ref is None:
return b""
return base64.urlsafe_b64decode(file_ref + "=" * (-len(file_ref) % 4))
from pyrogram.file_id import FileId, FileType, PHOTO_TYPES, DOCUMENT_TYPES
async def ainput(prompt: str = "", *, hide: bool = False):
@ -102,52 +49,38 @@ def get_offset_date(dialogs):
def get_input_media_from_file_id(
file_id_str: str,
file_ref: str = None,
expected_media_type: int = None
file_id: str,
expected_file_type: FileType = None
) -> Union["raw.types.InputMediaPhoto", "raw.types.InputMediaDocument"]:
try:
decoded = decode_file_id(file_id_str)
except Exception:
raise ValueError(f"Failed to decode file_id: {file_id_str}")
else:
media_type = decoded[0]
decoded = FileId.decode(file_id)
if expected_media_type is not None:
if media_type != expected_media_type:
media_type_str = Scaffold.MEDIA_TYPE_ID.get(media_type, None)
expected_media_type_str = Scaffold.MEDIA_TYPE_ID.get(expected_media_type, None)
file_type = decoded.file_type
raise ValueError(f'Expected: "{expected_media_type_str}", got "{media_type_str}" file_id instead')
if expected_file_type is not None and file_type != expected_file_type:
raise ValueError(f'Expected: "{expected_file_type}", got "{file_type}" file_id instead')
if media_type in (0, 1, 14):
raise ValueError(f"This file_id can only be used for download: {file_id_str}")
if file_type in (FileType.THUMBNAIL, FileType.CHAT_PHOTO):
raise ValueError(f"This file_id can only be used for download: {file_id}")
if media_type == 2:
unpacked = struct.unpack("<iiqqqiiii", decoded)
dc_id, file_id, access_hash, volume_id, _, _, type, local_id = unpacked[1:]
return raw.types.InputMediaPhoto(
id=raw.types.InputPhoto(
id=file_id,
access_hash=access_hash,
file_reference=decode_file_ref(file_ref)
)
if file_type in PHOTO_TYPES:
return raw.types.InputMediaPhoto(
id=raw.types.InputPhoto(
id=decoded.media_id,
access_hash=decoded.access_hash,
file_reference=decoded.file_reference
)
)
if media_type in (3, 4, 5, 8, 9, 10, 13):
unpacked = struct.unpack("<iiqq", decoded)
dc_id, file_id, access_hash = unpacked[1:]
return raw.types.InputMediaDocument(
id=raw.types.InputDocument(
id=file_id,
access_hash=access_hash,
file_reference=decode_file_ref(file_ref)
)
if file_type in DOCUMENT_TYPES:
return raw.types.InputMediaDocument(
id=raw.types.InputDocument(
id=decoded.media_id,
access_hash=decoded.access_hash,
file_reference=decoded.file_reference
)
)
raise ValueError(f"Unknown media type: {file_id_str}")
raise ValueError(f"Unknown file id: {file_id}")
async def parse_messages(client, messages: "raw.types.messages.Messages", replies: int = 1) -> List["types.Message"]: