mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-26 11:23:46 +03:00
Make sending files a lot more friendly with a simple .send_file()
This commit is contained in:
parent
81ccd21cdb
commit
4234efcc86
|
@ -315,6 +315,10 @@ class TelegramBareClient:
|
||||||
"""Uploads the specified file_path and returns a handle (an instance
|
"""Uploads the specified file_path and returns a handle (an instance
|
||||||
of InputFile or InputFileBig, as required) which can be later used.
|
of InputFile or InputFileBig, as required) which can be later used.
|
||||||
|
|
||||||
|
Uploading a file will simply return a "handle" to the file stored
|
||||||
|
remotely in the Telegram servers, which can be later used on. This
|
||||||
|
will NOT upload the file to your own chat.
|
||||||
|
|
||||||
If 'progress_callback' is not None, it should be a function that
|
If 'progress_callback' is not None, it should be a function that
|
||||||
takes two parameters, (bytes_uploaded, total_bytes).
|
takes two parameters, (bytes_uploaded, total_bytes).
|
||||||
|
|
||||||
|
@ -322,6 +326,7 @@ class TelegramBareClient:
|
||||||
part_size_kb = get_appropriated_part_size(file_size)
|
part_size_kb = get_appropriated_part_size(file_size)
|
||||||
file_name = path.basename(file_path)
|
file_name = path.basename(file_path)
|
||||||
"""
|
"""
|
||||||
|
# TODO Support both streams and bytes instead just "file_path"
|
||||||
file_size = path.getsize(file_path)
|
file_size = path.getsize(file_path)
|
||||||
if not part_size_kb:
|
if not part_size_kb:
|
||||||
part_size_kb = get_appropriated_part_size(file_size)
|
part_size_kb = get_appropriated_part_size(file_size)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import errno
|
import os
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from mimetypes import guess_type
|
from mimetypes import guess_type
|
||||||
from threading import Event, RLock, Thread
|
from threading import Event, RLock, Thread
|
||||||
|
@ -126,6 +126,9 @@ class TelegramClient(TelegramBareClient):
|
||||||
self._updates_thread = None
|
self._updates_thread = None
|
||||||
self._phone_code_hashes = {}
|
self._phone_code_hashes = {}
|
||||||
|
|
||||||
|
# Uploaded files cache so subsequent calls are instant
|
||||||
|
self._upload_cache = {}
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Connecting
|
# region Connecting
|
||||||
|
@ -475,53 +478,86 @@ class TelegramClient(TelegramBareClient):
|
||||||
|
|
||||||
# region Uploading files
|
# region Uploading files
|
||||||
|
|
||||||
def send_photo_file(self, input_file, entity, caption=''):
|
def send_file(self, entity, file, caption='',
|
||||||
"""Sends a previously uploaded input_file
|
force_document=False, callback=None):
|
||||||
(which should be a photo) to the given entity (or input peer)"""
|
"""Sends a file to the specified entity.
|
||||||
self.send_media_file(
|
The file may either be a path, a byte array, or a stream.
|
||||||
InputMediaUploadedPhoto(input_file, caption), entity)
|
|
||||||
|
|
||||||
def send_document_file(self, input_file, entity, caption=''):
|
An optional caption can also be specified for said file.
|
||||||
"""Sends a previously uploaded input_file
|
|
||||||
(which should be a document) to the given entity.
|
If "force_document" is False, the file will be sent as a photo
|
||||||
|
if it's recognised to have a common image format (e.g. .png, .jpg).
|
||||||
|
|
||||||
|
Otherwise, the file will always be sent as an uncompressed document.
|
||||||
|
|
||||||
|
Subsequent calls with the very same file will result in
|
||||||
|
immediate uploads, unless .clear_file_cache() is called.
|
||||||
|
|
||||||
|
If "progress_callback" is not None, it should be a function that
|
||||||
|
takes two parameters, (bytes_uploaded, total_bytes).
|
||||||
|
|
||||||
The entity may be a phone or an username at the expense of
|
The entity may be a phone or an username at the expense of
|
||||||
some performance loss.
|
some performance loss.
|
||||||
"""
|
"""
|
||||||
|
as_photo = False
|
||||||
|
if isinstance(file, str):
|
||||||
|
lowercase_file = file.lower()
|
||||||
|
as_photo = any(
|
||||||
|
lowercase_file.endswith(ext)
|
||||||
|
for ext in ('.png', '.jpg', '.gif', '.jpeg')
|
||||||
|
)
|
||||||
|
|
||||||
# Determine mime-type and attributes
|
file_hash = hash(file)
|
||||||
# Take the first element by using [0] since it returns a tuple
|
if file_hash in self._upload_cache:
|
||||||
mime_type = guess_type(input_file.name)[0]
|
file_handle = self._upload_cache[file_hash]
|
||||||
attributes = [
|
else:
|
||||||
DocumentAttributeFilename(input_file.name)
|
file_handle = self.upload_file(file, progress_callback=callback)
|
||||||
# TODO If the input file is an audio, find out:
|
self._upload_cache[file_hash] = file_handle
|
||||||
# Performer and song title and add DocumentAttributeAudio
|
|
||||||
]
|
if as_photo and not force_document:
|
||||||
# Ensure we have a mime type, any; but it cannot be None
|
media = InputMediaUploadedPhoto(file_handle, caption)
|
||||||
# 'The "octet-stream" subtype is used to indicate that a body
|
else:
|
||||||
# contains arbitrary binary data.'
|
mime_type = None
|
||||||
if not mime_type:
|
if isinstance(file, str):
|
||||||
mime_type = 'application/octet-stream'
|
# Determine mime-type and attributes
|
||||||
self.send_media_file(
|
# Take the first element by using [0] since it returns a tuple
|
||||||
InputMediaUploadedDocument(
|
mime_type = guess_type(file)[0]
|
||||||
file=input_file,
|
attributes = [
|
||||||
|
DocumentAttributeFilename(os.path.abspath(file))
|
||||||
|
# TODO If the input file is an audio, find out:
|
||||||
|
# Performer and song title and add DocumentAttributeAudio
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
attributes = [DocumentAttributeFilename('unnamed')]
|
||||||
|
|
||||||
|
# Ensure we have a mime type, any; but it cannot be None
|
||||||
|
# 'The "octet-stream" subtype is used to indicate that a body
|
||||||
|
# contains arbitrary binary data.'
|
||||||
|
if not mime_type:
|
||||||
|
mime_type = 'application/octet-stream'
|
||||||
|
|
||||||
|
media = InputMediaUploadedDocument(
|
||||||
|
file=file_handle,
|
||||||
mime_type=mime_type,
|
mime_type=mime_type,
|
||||||
attributes=attributes,
|
attributes=attributes,
|
||||||
caption=caption),
|
caption=caption
|
||||||
entity)
|
)
|
||||||
|
|
||||||
def send_media_file(self, input_media, entity):
|
# Once the media type is properly specified and the file uploaded,
|
||||||
"""Sends any input_media (contact, document, photo...)
|
# send the media message to the desired entity.
|
||||||
to the given entity.
|
|
||||||
|
|
||||||
The entity may be a phone or an username at the expense of
|
|
||||||
some performance loss.
|
|
||||||
"""
|
|
||||||
self(SendMediaRequest(
|
self(SendMediaRequest(
|
||||||
peer=self._get_entity(entity),
|
peer=self._get_entity(entity),
|
||||||
media=input_media
|
media=media
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def clear_file_cache(self):
|
||||||
|
"""Calls to .send_file() will cache the remote location of the
|
||||||
|
uploaded files so that subsequent files can be immediate, so
|
||||||
|
uploading the same file path will result in using the cached
|
||||||
|
version. To avoid this a call to this method should be made.
|
||||||
|
"""
|
||||||
|
self._upload_cache.clear()
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
# region Downloading media requests
|
# region Downloading media requests
|
||||||
|
@ -723,6 +759,9 @@ class TelegramClient(TelegramBareClient):
|
||||||
If the entity is neither, and it's not a TLObject, an
|
If the entity is neither, and it's not a TLObject, an
|
||||||
error will be raised.
|
error will be raised.
|
||||||
"""
|
"""
|
||||||
|
# TODO Maybe cache both the contacts and the entities.
|
||||||
|
# If an user cannot be found, force a cache update through
|
||||||
|
# a public method (since users may change their username)
|
||||||
if isinstance(entity, TLObject):
|
if isinstance(entity, TLObject):
|
||||||
return entity
|
return entity
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user