mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 19:03:46 +03:00
parent
100cd807f6
commit
b66c1e6084
|
@ -690,6 +690,7 @@ class MessageMethods(UploadMethods, ButtonMethods, MessageParseMethods):
|
|||
reply_markup=self.build_reply_markup(buttons)
|
||||
)
|
||||
msg = self._get_response_message(request, await self(request), entity)
|
||||
await self._cache_media(msg, file, file_handle)
|
||||
return msg
|
||||
|
||||
async def delete_messages(self, entity, message_ids, *, revoke=True):
|
||||
|
|
|
@ -22,7 +22,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
async def send_file(
|
||||
self, entity, file, *, caption=None, force_document=False,
|
||||
progress_callback=None, reply_to=None, attributes=None,
|
||||
thumb=None, parse_mode=(),
|
||||
thumb=None, allow_cache=True, parse_mode=(),
|
||||
voice_note=False, video_note=False, buttons=None, silent=None,
|
||||
**kwargs):
|
||||
"""
|
||||
|
@ -74,6 +74,12 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
Successful thumbnails were files below 20kb and 200x200px.
|
||||
Width/height and dimensions/size ratios may be important.
|
||||
|
||||
allow_cache (`bool`, optional):
|
||||
Whether to allow using the cached version stored in the
|
||||
database or not. Defaults to ``True`` to avoid re-uploads.
|
||||
Must be ``False`` if you wish to use different attributes
|
||||
or thumb than those that were used when the file was cached.
|
||||
|
||||
parse_mode (`object`, optional):
|
||||
See the `TelegramClient.parse_mode` property for allowed
|
||||
values. Markdown parsing will be used by default.
|
||||
|
@ -81,10 +87,16 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
voice_note (`bool`, optional):
|
||||
If ``True`` the audio will be sent as a voice note.
|
||||
|
||||
Set `allow_cache` to ``False`` if you sent the same file
|
||||
without this setting before for it to work.
|
||||
|
||||
video_note (`bool`, optional):
|
||||
If ``True`` the video will be sent as a video note,
|
||||
also known as a round video message.
|
||||
|
||||
Set `allow_cache` to ``False`` if you sent the same file
|
||||
without this setting before for it to work.
|
||||
|
||||
buttons (`list`, `custom.Button <telethon.tl.custom.button.Button>`, :tl:`KeyboardButton`):
|
||||
The matrix (list of lists), row list or button to be shown
|
||||
after sending the message. This parameter will only work if
|
||||
|
@ -133,7 +145,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
|
||||
for x in documents:
|
||||
result.append(await self.send_file(
|
||||
entity, x,
|
||||
entity, x, allow_cache=allow_cache,
|
||||
caption=caption, force_document=force_document,
|
||||
progress_callback=progress_callback, reply_to=reply_to,
|
||||
attributes=attributes, thumb=thumb, voice_note=voice_note,
|
||||
|
@ -157,7 +169,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
file_handle, media = await self._file_to_media(
|
||||
file, force_document=force_document,
|
||||
progress_callback=progress_callback,
|
||||
attributes=attributes, thumb=thumb,
|
||||
attributes=attributes, allow_cache=allow_cache, thumb=thumb,
|
||||
voice_note=voice_note, video_note=video_note
|
||||
)
|
||||
|
||||
|
@ -167,6 +179,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
entities=msg_entities, reply_markup=markup, silent=silent
|
||||
)
|
||||
msg = self._get_response_message(request, await self(request), entity)
|
||||
await self._cache_media(msg, file, file_handle, force_document=force_document)
|
||||
|
||||
return msg
|
||||
|
||||
|
@ -174,6 +187,15 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
progress_callback=None, reply_to=None,
|
||||
parse_mode=(), silent=None):
|
||||
"""Specialized version of .send_file for albums"""
|
||||
# We don't care if the user wants to avoid cache, we will use it
|
||||
# anyway. Why? The cached version will be exactly the same thing
|
||||
# we need to produce right now to send albums (uploadMedia), and
|
||||
# cache only makes a difference for documents where the user may
|
||||
# want the attributes used on them to change.
|
||||
#
|
||||
# In theory documents can be sent inside the albums but they appear
|
||||
# as different messages (not inside the album), and the logic to set
|
||||
# the attributes/avoid cache is already written in .send_file().
|
||||
entity = await self.get_input_entity(entity)
|
||||
if not utils.is_list_like(caption):
|
||||
caption = (caption,)
|
||||
|
@ -184,15 +206,17 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
|
||||
reply_to = utils.get_message_id(reply_to)
|
||||
|
||||
# Need to upload the media first, but only if they're not cached yet
|
||||
media = []
|
||||
for file in files:
|
||||
# fh will either be InputPhoto or a modified InputFile
|
||||
fh = await self.upload_file(file)
|
||||
fh = await self.upload_file(file, use_cache=types.InputPhoto)
|
||||
if not isinstance(fh, types.InputPhoto):
|
||||
r = await self(functions.messages.UploadMediaRequest(
|
||||
entity, media=types.InputMediaUploadedPhoto(fh)
|
||||
))
|
||||
input_photo = utils.get_input_photo(r.photo)
|
||||
self.session.cache_file(fh.md5, fh.size, input_photo)
|
||||
fh = input_photo
|
||||
|
||||
if captions:
|
||||
|
@ -216,7 +240,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
]
|
||||
|
||||
async def upload_file(
|
||||
self, file, *, part_size_kb=None, file_name=None,
|
||||
self, file, *, part_size_kb=None, file_name=None, use_cache=None,
|
||||
progress_callback=None):
|
||||
"""
|
||||
Uploads the specified file and returns a handle (an instance of
|
||||
|
@ -243,6 +267,13 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
If not specified, the name will be taken from the ``file``
|
||||
and if this is not a ``str``, it will be ``"unnamed"``.
|
||||
|
||||
use_cache (`type`, optional):
|
||||
The type of cache to use (currently either :tl:`InputDocument`
|
||||
or :tl:`InputPhoto`). If present and the file is small enough
|
||||
to need the MD5, it will be checked against the database,
|
||||
and if a match is found, the upload won't be made. Instead,
|
||||
an instance of type ``use_cache`` will be returned.
|
||||
|
||||
progress_callback (`callable`, optional):
|
||||
A callback function accepting two parameters:
|
||||
``(sent bytes, total)``.
|
||||
|
@ -291,10 +322,20 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
is_large = file_size > 10 * 1024 * 1024
|
||||
hash_md5 = hashlib.md5()
|
||||
if not is_large:
|
||||
# Calculate the MD5 hash before anything else.
|
||||
# As this needs to be done always for small files,
|
||||
# might as well do it before anything else and
|
||||
# check the cache.
|
||||
if isinstance(file, str):
|
||||
with open(file, 'rb') as stream:
|
||||
file = stream.read()
|
||||
hash_md5.update(file)
|
||||
if use_cache:
|
||||
cached = self.session.get_file(
|
||||
hash_md5.digest(), file_size, cls=use_cache
|
||||
)
|
||||
if cached:
|
||||
return cached
|
||||
|
||||
part_count = (file_size + part_size - 1) // part_size
|
||||
__log__.info('Uploading file of %d bytes in %d chunks of %d',
|
||||
|
@ -337,7 +378,7 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
async def _file_to_media(
|
||||
self, file, force_document=False,
|
||||
progress_callback=None, attributes=None, thumb=None,
|
||||
voice_note=False, video_note=False):
|
||||
allow_cache=True, voice_note=False, video_note=False):
|
||||
if not file:
|
||||
return None, None
|
||||
|
||||
|
@ -356,9 +397,11 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
media = None
|
||||
file_handle = None
|
||||
as_image = utils.is_image(file) and not force_document
|
||||
use_cache = types.InputPhoto if as_image else types.InputDocument
|
||||
if not isinstance(file, str) or os.path.isfile(file):
|
||||
file_handle = await self.upload_file(
|
||||
file, progress_callback=progress_callback
|
||||
file, progress_callback=progress_callback,
|
||||
use_cache=use_cache if allow_cache else None
|
||||
)
|
||||
elif re.match('https?://', file):
|
||||
if as_image:
|
||||
|
@ -379,6 +422,12 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
'Failed to convert {} to media. Not an existing file, '
|
||||
'an HTTP URL or a valid bot-API-like file ID'.format(file)
|
||||
)
|
||||
elif isinstance(file_handle, use_cache):
|
||||
# File was cached, so an instance of use_cache was returned
|
||||
if as_image:
|
||||
media = types.InputMediaPhoto(file_handle)
|
||||
else:
|
||||
media = types.InputMediaDocument(file_handle)
|
||||
elif as_image:
|
||||
media = types.InputMediaUploadedPhoto(file_handle)
|
||||
else:
|
||||
|
@ -402,4 +451,17 @@ class UploadMethods(ButtonMethods, MessageParseMethods, UserMethods):
|
|||
)
|
||||
return file_handle, media
|
||||
|
||||
async def _cache_media(self, msg, file, file_handle,
|
||||
force_document=False):
|
||||
if file and msg and isinstance(file_handle,
|
||||
custom.InputSizedFile):
|
||||
# There was a response message and we didn't use cached
|
||||
# version, so cache whatever we just sent to the database.
|
||||
md5, size = file_handle.md5, file_handle.size
|
||||
if utils.is_image(file) and not force_document:
|
||||
to_cache = utils.get_input_photo(msg.media.photo)
|
||||
else:
|
||||
to_cache = utils.get_input_document(msg.media.document)
|
||||
self.session.cache_file(md5, size, to_cache)
|
||||
|
||||
# endregion
|
||||
|
|
|
@ -120,8 +120,6 @@ class Session(ABC):
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
# TODO get rid of now useless cache
|
||||
|
||||
@abstractmethod
|
||||
def cache_file(self, md5_digest, file_size, instance):
|
||||
"""
|
||||
|
|
|
@ -113,7 +113,7 @@ class InlineBuilder:
|
|||
Same as ``file`` for `client.send_file
|
||||
<telethon.client.uploads.UploadMethods.send_file>`.
|
||||
"""
|
||||
fh = await self._client.upload_file(file)
|
||||
fh = await self._client.upload_file(file, use_cache=types.InputPhoto)
|
||||
if not isinstance(fh, types.InputPhoto):
|
||||
r = await self._client(functions.messages.UploadMediaRequest(
|
||||
types.InputPeerSelf(), media=types.InputMediaUploadedPhoto(fh)
|
||||
|
@ -140,14 +140,14 @@ class InlineBuilder:
|
|||
async def document(
|
||||
self, file, title=None, *, description=None, type=None,
|
||||
mime_type=None, attributes=None, force_document=False,
|
||||
voice_note=False, video_note=False, id=None,
|
||||
voice_note=False, video_note=False, use_cache=True, id=None,
|
||||
text=None, parse_mode=(), link_preview=True,
|
||||
geo=None, period=60, contact=None, game=False, buttons=None
|
||||
):
|
||||
"""
|
||||
Creates a new inline result of document type.
|
||||
|
||||
`mime_type`, `attributes`, `force_document`,
|
||||
`use_cache`, `mime_type`, `attributes`, `force_document`,
|
||||
`voice_note` and `video_note` are described in `client.send_file
|
||||
<telethon.client.uploads.UploadMethods.send_file>`.
|
||||
|
||||
|
@ -174,7 +174,8 @@ class InlineBuilder:
|
|||
else:
|
||||
type = 'document'
|
||||
|
||||
fh = await self._client.upload_file(file)
|
||||
use_cache = types.InputDocument if use_cache else None
|
||||
fh = await self._client.upload_file(file, use_cache=use_cache)
|
||||
if not isinstance(fh, types.InputDocument):
|
||||
attributes, mime_type = utils.get_attributes(
|
||||
file,
|
||||
|
|
Loading…
Reference in New Issue
Block a user