mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-06-25 06:26:40 +00:00
Implement file-related methods
This commit is contained in:
parent
c44eb12c60
commit
938126691c
@ -41,7 +41,14 @@ from .chats import (
|
|||||||
kick_participant,
|
kick_participant,
|
||||||
)
|
)
|
||||||
from .dialogs import conversation, delete_dialog, edit_folder, iter_dialogs, iter_drafts
|
from .dialogs import conversation, delete_dialog, edit_folder, iter_dialogs, iter_drafts
|
||||||
from .downloads import download_media, download_profile_photo, iter_download
|
from .files import (
|
||||||
|
download,
|
||||||
|
iter_download,
|
||||||
|
send_audio,
|
||||||
|
send_file,
|
||||||
|
send_photo,
|
||||||
|
send_video,
|
||||||
|
)
|
||||||
from .messages import (
|
from .messages import (
|
||||||
MessageMap,
|
MessageMap,
|
||||||
build_message_map,
|
build_message_map,
|
||||||
@ -74,7 +81,6 @@ from .updates import (
|
|||||||
remove_event_handler,
|
remove_event_handler,
|
||||||
set_receive_updates,
|
set_receive_updates,
|
||||||
)
|
)
|
||||||
from .uploads import send_file, upload_file
|
|
||||||
from .users import (
|
from .users import (
|
||||||
get_entity,
|
get_entity,
|
||||||
get_input_entity,
|
get_input_entity,
|
||||||
@ -192,14 +198,71 @@ class Client:
|
|||||||
def conversation(self) -> None:
|
def conversation(self) -> None:
|
||||||
conversation(self)
|
conversation(self)
|
||||||
|
|
||||||
async def download_profile_photo(self) -> None:
|
async def send_photo(self, *args, **kwargs) -> None:
|
||||||
await download_profile_photo(self)
|
"""
|
||||||
|
Send a photo file.
|
||||||
|
|
||||||
async def download_media(self) -> None:
|
Exactly one of path, url or file must be specified.
|
||||||
await download_media(self)
|
A `File` can also be used as the second parameter.
|
||||||
|
|
||||||
def iter_download(self) -> None:
|
By default, the server will be allowed to `compress` the image.
|
||||||
iter_download(self)
|
Only compressed images can be displayed as photos in applications.
|
||||||
|
Images that cannot be compressed will be sent as file documents,
|
||||||
|
with a thumbnail if possible.
|
||||||
|
|
||||||
|
Unlike `send_file`, this method will attempt to guess the values for
|
||||||
|
width and height if they are not provided and the can't be compressed.
|
||||||
|
"""
|
||||||
|
return send_photo(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def send_audio(self, *args, **kwargs) -> None:
|
||||||
|
"""
|
||||||
|
Send an audio file.
|
||||||
|
|
||||||
|
Unlike `send_file`, this method will attempt to guess the values for
|
||||||
|
duration, title and performer if they are not provided.
|
||||||
|
"""
|
||||||
|
return send_audio(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def send_video(self, *args, **kwargs) -> None:
|
||||||
|
"""
|
||||||
|
Send a video file.
|
||||||
|
|
||||||
|
Unlike `send_file`, this method will attempt to guess the values for
|
||||||
|
duration, width and height if they are not provided.
|
||||||
|
"""
|
||||||
|
return send_video(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def send_file(self, *args, **kwargs) -> None:
|
||||||
|
"""
|
||||||
|
Send any type of file with any amount of attributes.
|
||||||
|
|
||||||
|
This method will not attempt to guess any of the file metadata such as
|
||||||
|
width, duration, title, etc. If you want to let the library attempt to
|
||||||
|
guess the file metadata, use the type-specific methods to send media:
|
||||||
|
`send_photo`, `send_audio` or `send_file`.
|
||||||
|
|
||||||
|
Unlike `send_photo`, image files will be sent as documents by default.
|
||||||
|
|
||||||
|
The parameters are used to construct a `File`. See the documentation
|
||||||
|
for `File.new` to learn what they do and when they are in effect.
|
||||||
|
"""
|
||||||
|
return send_file(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def iter_download(self, *args, **kwargs) -> None:
|
||||||
|
"""
|
||||||
|
Stream server media by iterating over its bytes in chunks.
|
||||||
|
"""
|
||||||
|
return iter_download(self, *args, **kwargs)
|
||||||
|
|
||||||
|
async def download(self, *args, **kwargs) -> None:
|
||||||
|
"""
|
||||||
|
Download a file.
|
||||||
|
|
||||||
|
This is simply a more convenient method to `iter_download`,
|
||||||
|
as it will handle dealing with the file chunks and writes by itself.
|
||||||
|
"""
|
||||||
|
return download(self, *args, **kwargs)
|
||||||
|
|
||||||
async def send_message(
|
async def send_message(
|
||||||
self,
|
self,
|
||||||
@ -326,12 +389,6 @@ class Client:
|
|||||||
async def catch_up(self) -> None:
|
async def catch_up(self) -> None:
|
||||||
await catch_up(self)
|
await catch_up(self)
|
||||||
|
|
||||||
async def send_file(self) -> None:
|
|
||||||
await send_file(self)
|
|
||||||
|
|
||||||
async def upload_file(self) -> None:
|
|
||||||
await upload_file(self)
|
|
||||||
|
|
||||||
async def get_me(self) -> None:
|
async def get_me(self) -> None:
|
||||||
await get_me(self)
|
await get_me(self)
|
||||||
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from .client import Client
|
|
||||||
|
|
||||||
|
|
||||||
async def download_profile_photo(self: Client) -> None:
|
|
||||||
self
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
async def download_media(self: Client) -> None:
|
|
||||||
self
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
def iter_download(self: Client) -> None:
|
|
||||||
self
|
|
||||||
raise NotImplementedError
|
|
499
client/src/telethon/_impl/client/client/files.py
Normal file
499
client/src/telethon/_impl/client/client/files.py
Normal file
@ -0,0 +1,499 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
from mimetypes import guess_type
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING, Any, Coroutine, List, Optional, Protocol, Self, Union
|
||||||
|
|
||||||
|
from ...tl import abcs, functions, types
|
||||||
|
from ..types.chat import ChatLike
|
||||||
|
from ..types.message import Message
|
||||||
|
from ..types.meta import NoPublicConstructor
|
||||||
|
from ..utils import generate_random_id
|
||||||
|
from .messages import parse_message
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .client import Client
|
||||||
|
|
||||||
|
|
||||||
|
MIN_CHUNK_SIZE = 4 * 1024
|
||||||
|
MAX_CHUNK_SIZE = 512 * 1024
|
||||||
|
FILE_MIGRATE_ERROR = 303
|
||||||
|
BIG_FILE_SIZE = 10 * 1024 * 1024
|
||||||
|
|
||||||
|
math_round = round
|
||||||
|
|
||||||
|
|
||||||
|
class InFileLike(Protocol):
|
||||||
|
"""
|
||||||
|
[File-like object](https://docs.python.org/3/glossary.html#term-file-like-object)
|
||||||
|
used for input only, where the `read` method can be `async`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def read(self, n: int) -> Union[bytes, Coroutine[Any, Any, bytes]]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OutFileLike(Protocol):
|
||||||
|
"""
|
||||||
|
[File-like object](https://docs.python.org/3/glossary.html#term-file-like-object)
|
||||||
|
used for output only, where the `write` method can be `async`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def write(self, data: bytes) -> Union[Any, Coroutine[Any, Any, Any]]:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
MediaLike = object
|
||||||
|
|
||||||
|
|
||||||
|
class File(metaclass=NoPublicConstructor):
|
||||||
|
"""
|
||||||
|
File information of uploaded media.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
path: Optional[Path],
|
||||||
|
file: Optional[InFileLike],
|
||||||
|
attributes: List[abcs.DocumentAttribute],
|
||||||
|
size: int,
|
||||||
|
name: str,
|
||||||
|
mime: str,
|
||||||
|
photo: bool,
|
||||||
|
muted: bool,
|
||||||
|
input_media: Optional[abcs.InputMedia],
|
||||||
|
):
|
||||||
|
self._path = path
|
||||||
|
self._file = file
|
||||||
|
self._attributes = attributes
|
||||||
|
self._size = size
|
||||||
|
self._name = name
|
||||||
|
self._mime = mime
|
||||||
|
self._photo = photo
|
||||||
|
self._muted = muted
|
||||||
|
self._input_file: Optional[abcs.InputFile] = None
|
||||||
|
self._input_media: Optional[abcs.InputMedia] = input_media
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def new(
|
||||||
|
cls,
|
||||||
|
path: Optional[Union[str, Path, File]] = None,
|
||||||
|
*,
|
||||||
|
url: Optional[str] = None,
|
||||||
|
file: Optional[InFileLike] = None,
|
||||||
|
size: Optional[int] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
mime_type: Optional[str] = None,
|
||||||
|
compress: bool = False,
|
||||||
|
animated: bool = False,
|
||||||
|
duration: Optional[float] = None,
|
||||||
|
voice: bool = False,
|
||||||
|
title: Optional[str] = None,
|
||||||
|
performer: Optional[str] = None,
|
||||||
|
emoji: Optional[str] = None,
|
||||||
|
emoji_sticker: Optional[str] = None,
|
||||||
|
width: Optional[int] = None,
|
||||||
|
height: Optional[int] = None,
|
||||||
|
round: bool = False,
|
||||||
|
supports_streaming: bool = False,
|
||||||
|
muted: bool = False,
|
||||||
|
) -> "File":
|
||||||
|
"""
|
||||||
|
Create file information that can later be sent as media.
|
||||||
|
|
||||||
|
If the path is a `File`, the rest of parameters are ignored, and
|
||||||
|
this existing instance is returned instead (the method is a no-op).
|
||||||
|
|
||||||
|
Only one of path, url or file must be specified.
|
||||||
|
|
||||||
|
If a local file path is not given, size and name must be specified.
|
||||||
|
|
||||||
|
The mime_type will be inferred from the name if it is omitted.
|
||||||
|
|
||||||
|
The rest of parameters are only used depending on the mime_type:
|
||||||
|
|
||||||
|
* For image/:
|
||||||
|
* width (required), in pixels, of the media.
|
||||||
|
* height (required), in pixels, of the media.
|
||||||
|
* For audio/:
|
||||||
|
* duration (required), in seconds, of the media. This will be rounded.
|
||||||
|
* voice, if it's a live recording.
|
||||||
|
* title, of the song.
|
||||||
|
* performer, with the name of the artist.
|
||||||
|
* For video/:
|
||||||
|
* duration (required), in seconds, of the media. This will be rounded.
|
||||||
|
* width (required), in pixels, of the media.
|
||||||
|
* height (required), in pixels, of the media.
|
||||||
|
* round, if it should be displayed as a round video.
|
||||||
|
* supports_streaming, if clients are able to stream the video.
|
||||||
|
* muted, if the sound from the video is or should be missing.
|
||||||
|
* For sticker:
|
||||||
|
* animated, if it's not a static image.
|
||||||
|
* emoji, as the alternative text for the sticker.
|
||||||
|
* stickerset, to which the sticker belongs.
|
||||||
|
|
||||||
|
If any of the required fields are missing, the attribute will not be sent.
|
||||||
|
"""
|
||||||
|
if isinstance(path, File):
|
||||||
|
return path
|
||||||
|
|
||||||
|
attributes: List[abcs.DocumentAttribute] = []
|
||||||
|
|
||||||
|
if sum((path is not None, url is not None, file is not None)) != 1:
|
||||||
|
raise ValueError("must specify exactly one of path, markdown or html")
|
||||||
|
|
||||||
|
if path is not None:
|
||||||
|
size = os.path.getsize(path)
|
||||||
|
name = os.path.basename(path)
|
||||||
|
|
||||||
|
if size is None:
|
||||||
|
raise ValueError("must specify size")
|
||||||
|
if name is None:
|
||||||
|
raise ValueError("must specify name")
|
||||||
|
|
||||||
|
if mime_type is None:
|
||||||
|
mime_type, _ = guess_type(name, strict=False)
|
||||||
|
if mime_type is None:
|
||||||
|
raise ValueError("must specify mime_type")
|
||||||
|
|
||||||
|
if sum((path is not None, url is not None, file is not None)) != 1:
|
||||||
|
raise ValueError("must specify exactly one of path, markdown or html")
|
||||||
|
|
||||||
|
attributes.append(types.DocumentAttributeFilename(file_name=name))
|
||||||
|
|
||||||
|
if mime_type.startswith("image/"):
|
||||||
|
if width is not None and height is not None:
|
||||||
|
attributes.append(types.DocumentAttributeImageSize(w=width, h=height))
|
||||||
|
elif mime_type.startswith("audio/"):
|
||||||
|
if duration is not None:
|
||||||
|
attributes.append(
|
||||||
|
types.DocumentAttributeAudio(
|
||||||
|
voice=voice,
|
||||||
|
duration=int(math_round(duration)),
|
||||||
|
title=title,
|
||||||
|
performer=performer,
|
||||||
|
waveform=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif mime_type.startswith("video/"):
|
||||||
|
if duration is not None and width is not None and height is not None:
|
||||||
|
attributes.append(
|
||||||
|
types.DocumentAttributeVideo(
|
||||||
|
round_message=round,
|
||||||
|
supports_streaming=supports_streaming,
|
||||||
|
duration=int(math_round(duration)),
|
||||||
|
w=width,
|
||||||
|
h=height,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("sticker")
|
||||||
|
|
||||||
|
photo = compress and mime_type.startswith("image/")
|
||||||
|
|
||||||
|
input_media: Optional[abcs.InputMedia]
|
||||||
|
if url is not None:
|
||||||
|
if photo:
|
||||||
|
input_media = types.InputMediaPhotoExternal(
|
||||||
|
spoiler=False, url=url, ttl_seconds=None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
input_media = types.InputMediaDocumentExternal(
|
||||||
|
spoiler=False, url=url, ttl_seconds=None
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
input_media = None
|
||||||
|
|
||||||
|
return cls(
|
||||||
|
path=Path(path) if path is not None else None,
|
||||||
|
file=file,
|
||||||
|
attributes=attributes,
|
||||||
|
size=size,
|
||||||
|
name=name,
|
||||||
|
mime=mime_type,
|
||||||
|
photo=photo,
|
||||||
|
muted=muted,
|
||||||
|
input_media=input_media,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _read(self, n: int) -> bytes:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
async def send_photo(
|
||||||
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
path: Optional[Union[str, Path, File]] = None,
|
||||||
|
*,
|
||||||
|
url: Optional[str] = None,
|
||||||
|
file: Optional[InFileLike] = None,
|
||||||
|
size: Optional[int] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
compress: bool = True,
|
||||||
|
width: Optional[int] = None,
|
||||||
|
height: Optional[int] = None,
|
||||||
|
) -> Message:
|
||||||
|
return await send_file(
|
||||||
|
self,
|
||||||
|
chat,
|
||||||
|
path,
|
||||||
|
url=url,
|
||||||
|
file=file,
|
||||||
|
size=size,
|
||||||
|
name=name,
|
||||||
|
compress=compress,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_audio(
|
||||||
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
path: Optional[Union[str, Path, File]] = None,
|
||||||
|
*,
|
||||||
|
url: Optional[str] = None,
|
||||||
|
file: Optional[InFileLike] = None,
|
||||||
|
size: Optional[int] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
duration: Optional[float] = None,
|
||||||
|
voice: bool = False,
|
||||||
|
title: Optional[str] = None,
|
||||||
|
performer: Optional[str] = None,
|
||||||
|
) -> Message:
|
||||||
|
return await send_file(
|
||||||
|
self,
|
||||||
|
chat,
|
||||||
|
path,
|
||||||
|
url=url,
|
||||||
|
file=file,
|
||||||
|
size=size,
|
||||||
|
name=name,
|
||||||
|
duration=duration,
|
||||||
|
voice=voice,
|
||||||
|
title=title,
|
||||||
|
performer=performer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_video(
|
||||||
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
path: Optional[Union[str, Path, File]] = None,
|
||||||
|
*,
|
||||||
|
url: Optional[str] = None,
|
||||||
|
file: Optional[InFileLike] = None,
|
||||||
|
size: Optional[int] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
duration: Optional[float] = None,
|
||||||
|
width: Optional[int] = None,
|
||||||
|
height: Optional[int] = None,
|
||||||
|
round: bool = False,
|
||||||
|
supports_streaming: bool = False,
|
||||||
|
) -> Message:
|
||||||
|
return await send_file(
|
||||||
|
self,
|
||||||
|
chat,
|
||||||
|
path,
|
||||||
|
url=url,
|
||||||
|
file=file,
|
||||||
|
size=size,
|
||||||
|
name=name,
|
||||||
|
duration=duration,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
round=round,
|
||||||
|
supports_streaming=supports_streaming,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def send_file(
|
||||||
|
self: Client,
|
||||||
|
chat: ChatLike,
|
||||||
|
path: Optional[Union[str, Path, File]] = None,
|
||||||
|
*,
|
||||||
|
url: Optional[str] = None,
|
||||||
|
file: Optional[InFileLike] = None,
|
||||||
|
size: Optional[int] = None,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
mime_type: Optional[str] = None,
|
||||||
|
compress: bool = False,
|
||||||
|
animated: bool = False,
|
||||||
|
duration: Optional[float] = None,
|
||||||
|
voice: bool = False,
|
||||||
|
title: Optional[str] = None,
|
||||||
|
performer: Optional[str] = None,
|
||||||
|
emoji: Optional[str] = None,
|
||||||
|
emoji_sticker: Optional[str] = None,
|
||||||
|
width: Optional[int] = None,
|
||||||
|
height: Optional[int] = None,
|
||||||
|
round: bool = False,
|
||||||
|
supports_streaming: bool = False,
|
||||||
|
muted: bool = False,
|
||||||
|
caption: Optional[str] = None,
|
||||||
|
caption_markdown: Optional[str] = None,
|
||||||
|
caption_html: Optional[str] = None,
|
||||||
|
) -> Message:
|
||||||
|
file_info = File.new(
|
||||||
|
path,
|
||||||
|
url=url,
|
||||||
|
file=file,
|
||||||
|
size=size,
|
||||||
|
name=name,
|
||||||
|
mime_type=mime_type,
|
||||||
|
compress=compress,
|
||||||
|
animated=animated,
|
||||||
|
duration=duration,
|
||||||
|
voice=voice,
|
||||||
|
title=title,
|
||||||
|
performer=performer,
|
||||||
|
emoji=emoji,
|
||||||
|
emoji_sticker=emoji_sticker,
|
||||||
|
width=width,
|
||||||
|
height=height,
|
||||||
|
round=round,
|
||||||
|
supports_streaming=supports_streaming,
|
||||||
|
muted=muted,
|
||||||
|
)
|
||||||
|
message, entities = parse_message(
|
||||||
|
text=caption, markdown=caption_markdown, html=caption_html
|
||||||
|
)
|
||||||
|
|
||||||
|
peer = (await self._resolve_to_packed(chat))._to_input_peer()
|
||||||
|
|
||||||
|
if file_info._input_media is None:
|
||||||
|
if file_info._input_file is None:
|
||||||
|
file_info._input_file = await upload(self, file_info)
|
||||||
|
file_info._input_media = (
|
||||||
|
types.InputMediaUploadedPhoto(
|
||||||
|
spoiler=False,
|
||||||
|
file=file_info._input_file,
|
||||||
|
stickers=None,
|
||||||
|
ttl_seconds=None,
|
||||||
|
)
|
||||||
|
if file_info._photo
|
||||||
|
else types.InputMediaUploadedDocument(
|
||||||
|
nosound_video=file_info._muted,
|
||||||
|
force_file=False,
|
||||||
|
spoiler=False,
|
||||||
|
file=file_info._input_file,
|
||||||
|
thumb=None,
|
||||||
|
mime_type=file_info._mime,
|
||||||
|
attributes=file_info._attributes,
|
||||||
|
stickers=None,
|
||||||
|
ttl_seconds=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
random_id = generate_random_id()
|
||||||
|
|
||||||
|
return self._build_message_map(
|
||||||
|
await self(
|
||||||
|
functions.messages.send_media(
|
||||||
|
silent=False,
|
||||||
|
background=False,
|
||||||
|
clear_draft=False,
|
||||||
|
noforwards=False,
|
||||||
|
update_stickersets_order=False,
|
||||||
|
peer=peer,
|
||||||
|
reply_to_msg_id=None,
|
||||||
|
top_msg_id=None,
|
||||||
|
media=file_info._input_media,
|
||||||
|
message=message,
|
||||||
|
random_id=random_id,
|
||||||
|
reply_markup=None,
|
||||||
|
entities=entities,
|
||||||
|
schedule_date=None,
|
||||||
|
send_as=None,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
peer,
|
||||||
|
).with_random_id(random_id)
|
||||||
|
|
||||||
|
|
||||||
|
async def upload(
|
||||||
|
self: Client,
|
||||||
|
file: File,
|
||||||
|
) -> abcs.InputFile:
|
||||||
|
file_id = generate_random_id()
|
||||||
|
|
||||||
|
uploaded = 0
|
||||||
|
part = 0
|
||||||
|
total_parts = (file._size + MAX_CHUNK_SIZE - 1) // MAX_CHUNK_SIZE
|
||||||
|
buffer = bytearray()
|
||||||
|
to_store: Union[bytearray, bytes] = b""
|
||||||
|
hash_md5 = hashlib.md5()
|
||||||
|
is_big = file._size > BIG_FILE_SIZE
|
||||||
|
|
||||||
|
while uploaded != file._size:
|
||||||
|
chunk = await file._read(MAX_CHUNK_SIZE - len(buffer))
|
||||||
|
if not chunk:
|
||||||
|
raise ValueError("unexpected end-of-file")
|
||||||
|
|
||||||
|
if len(chunk) == MAX_CHUNK_SIZE or uploaded + len(chunk) == file._size:
|
||||||
|
to_store = chunk
|
||||||
|
else:
|
||||||
|
buffer += chunk
|
||||||
|
if len(buffer) == MAX_CHUNK_SIZE:
|
||||||
|
to_store = buffer
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if is_big:
|
||||||
|
await self(
|
||||||
|
functions.upload.save_big_file_part(
|
||||||
|
file_id=file_id,
|
||||||
|
file_part=part,
|
||||||
|
file_total_parts=part,
|
||||||
|
bytes=to_store,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self(
|
||||||
|
functions.upload.save_file_part(
|
||||||
|
file_id=file_id, file_part=total_parts, bytes=to_store
|
||||||
|
)
|
||||||
|
)
|
||||||
|
hash_md5.update(to_store)
|
||||||
|
|
||||||
|
buffer.clear()
|
||||||
|
part += 1
|
||||||
|
|
||||||
|
if file._size > BIG_FILE_SIZE:
|
||||||
|
types.InputFileBig(
|
||||||
|
id=file_id,
|
||||||
|
parts=total_parts,
|
||||||
|
name=file._name,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
types.InputFile(
|
||||||
|
id=file_id,
|
||||||
|
parts=total_parts,
|
||||||
|
name=file._name,
|
||||||
|
md5_checksum=hash_md5.hexdigest(),
|
||||||
|
)
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
async def iter_download(self: Client) -> None:
|
||||||
|
pass
|
||||||
|
# result = self(
|
||||||
|
# functions.upload.get_file(
|
||||||
|
# precise=False,
|
||||||
|
# cdn_supported=False,
|
||||||
|
# location=types.InputFileLocation(),
|
||||||
|
# offset=0,
|
||||||
|
# limit=MAX_CHUNK_SIZE,
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# assert isinstance(result, types.upload.File)
|
||||||
|
# if len(result.bytes) < MAX_CHUNK_SIZE:
|
||||||
|
# done
|
||||||
|
# else:
|
||||||
|
# offset += MAX_CHUNK_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
async def download(self: Client, media: MediaLike, file: OutFileLike) -> None:
|
||||||
|
pass
|
@ -1,16 +0,0 @@
|
|||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from .client import Client
|
|
||||||
|
|
||||||
|
|
||||||
async def send_file(self: Client) -> None:
|
|
||||||
self
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
async def upload_file(self: Client) -> None:
|
|
||||||
self
|
|
||||||
raise NotImplementedError
|
|
0
client/src/telethon/_impl/client/types/__init__.py
Normal file
0
client/src/telethon/_impl/client/types/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user