mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 19:03:46 +03:00
Officially remove bot_file_id support
This commit is contained in:
parent
3d36bb7b93
commit
9af8ec8cce
|
@ -178,6 +178,23 @@ The following modules have been moved inside ``_misc``:
|
|||
// TODO review telethon/__init__.py isn't exposing more than it should
|
||||
|
||||
|
||||
Support for bot-API style file_id has been removed
|
||||
--------------------------------------------------
|
||||
|
||||
They have been half-broken for a while now, so this is just making an existing reality official.
|
||||
See `issue #1613 <https://github.com/LonamiWebs/Telethon/issues/1613>`__ for details.
|
||||
|
||||
An alternative solution to re-use files may be provided in the future. For the time being, you
|
||||
should either upload the file as needed, or keep a message with the media somewhere you can
|
||||
later fetch it (by storing the chat and message identifier).
|
||||
|
||||
Additionally, the ``custom.File.id`` property is gone (which used to provide access to this
|
||||
"bot-API style" file identifier.
|
||||
|
||||
// TODO could probably provide an in-memory cache for uploads to temporarily reuse old InputFile.
|
||||
// this should lessen the impact of the removal of this feature
|
||||
|
||||
|
||||
The custom.Message class and the way it is used has changed
|
||||
-----------------------------------------------------------
|
||||
|
||||
|
|
|
@ -282,9 +282,6 @@ async def download_media(
|
|||
date = datetime.datetime.now()
|
||||
media = message
|
||||
|
||||
if isinstance(media, str):
|
||||
media = utils.resolve_bot_file_id(media)
|
||||
|
||||
if isinstance(media, _tl.MessageService):
|
||||
if isinstance(message.action,
|
||||
_tl.MessageActionChatEditPhoto):
|
||||
|
|
|
@ -3147,10 +3147,6 @@ class TelegramClient:
|
|||
send the file as "external" media, and Telegram is the
|
||||
one that will fetch the media and send it.
|
||||
|
||||
* A Bot API-like ``file_id``. You can convert previously
|
||||
sent media to file IDs for later reusing with
|
||||
`telethon.utils.pack_bot_file_id`.
|
||||
|
||||
* A handle to an existing file (for example, if you sent a
|
||||
message with media before, you can use its ``message.media``
|
||||
as a file here).
|
||||
|
|
|
@ -425,17 +425,13 @@ async def _file_to_media(
|
|||
media = _tl.InputMediaPhotoExternal(file, ttl_seconds=ttl)
|
||||
else:
|
||||
media = _tl.InputMediaDocumentExternal(file, ttl_seconds=ttl)
|
||||
else:
|
||||
bot_file = utils.resolve_bot_file_id(file)
|
||||
if bot_file:
|
||||
media = utils.get_input_media(bot_file, ttl=ttl)
|
||||
|
||||
if media:
|
||||
pass # Already have media, don't check the rest
|
||||
elif not file_handle:
|
||||
raise ValueError(
|
||||
'Failed to convert {} to media. Not an existing file, '
|
||||
'an HTTP URL or a valid bot-API-like file ID'.format(file)
|
||||
'Failed to convert {} to media. Not an existing file or '
|
||||
'HTTP URL'.format(file)
|
||||
)
|
||||
elif as_image:
|
||||
media = _tl.InputMediaUploadedPhoto(file_handle, ttl_seconds=ttl)
|
||||
|
|
|
@ -856,11 +856,7 @@ def is_image(file):
|
|||
"""
|
||||
Returns `True` if the file extension looks like an image file to Telegram.
|
||||
"""
|
||||
match = re.match(r'\.(png|jpe?g)', _get_extension(file), re.IGNORECASE)
|
||||
if match:
|
||||
return True
|
||||
else:
|
||||
return isinstance(resolve_bot_file_id(file), _tl.Photo)
|
||||
return bool(re.match(r'\.(png|jpe?g)', _get_extension(file), re.IGNORECASE))
|
||||
|
||||
|
||||
def is_gif(file):
|
||||
|
@ -1119,161 +1115,6 @@ def _encode_telegram_base64(string):
|
|||
return None # not valid base64, not valid ascii, not a string
|
||||
|
||||
|
||||
def resolve_bot_file_id(file_id):
|
||||
"""
|
||||
Given a Bot API-style `file_id <telethon.tl.custom.file.File.id>`,
|
||||
returns the media it represents. If the `file_id <telethon.tl.custom.file.File.id>`
|
||||
is not valid, `None` is returned instead.
|
||||
|
||||
Note that the `file_id <telethon.tl.custom.file.File.id>` does not have information
|
||||
such as image dimensions or file size, so these will be zero if present.
|
||||
|
||||
For thumbnails, the photo ID and hash will always be zero.
|
||||
"""
|
||||
data = _rle_decode(_decode_telegram_base64(file_id))
|
||||
if not data:
|
||||
return None
|
||||
|
||||
# This isn't officially documented anywhere, but
|
||||
# we assume the last byte is some kind of "version".
|
||||
data, version = data[:-1], data[-1]
|
||||
if version not in (2, 4):
|
||||
return None
|
||||
|
||||
if (version == 2 and len(data) == 24) or (version == 4 and len(data) == 25):
|
||||
if version == 2:
|
||||
file_type, dc_id, media_id, access_hash = struct.unpack('<iiqq', data)
|
||||
# elif version == 4:
|
||||
else:
|
||||
# TODO Figure out what the extra byte means
|
||||
file_type, dc_id, media_id, access_hash, _ = struct.unpack('<iiqqb', data)
|
||||
|
||||
if not (1 <= dc_id <= 5):
|
||||
# Valid `file_id`'s must have valid DC IDs. Since this method is
|
||||
# called when sending a file and the user may have entered a path
|
||||
# they believe is correct but the file doesn't exist, this method
|
||||
# may detect a path as "valid" bot `file_id` even when it's not.
|
||||
# By checking the `dc_id`, we greatly reduce the chances of this
|
||||
# happening.
|
||||
return None
|
||||
|
||||
attributes = []
|
||||
if file_type == 3 or file_type == 9:
|
||||
attributes.append(_tl.DocumentAttributeAudio(
|
||||
duration=0,
|
||||
voice=file_type == 3
|
||||
))
|
||||
elif file_type == 4 or file_type == 13:
|
||||
attributes.append(_tl.DocumentAttributeVideo(
|
||||
duration=0,
|
||||
w=0,
|
||||
h=0,
|
||||
round_message=file_type == 13
|
||||
))
|
||||
# elif file_type == 5: # other, cannot know which
|
||||
elif file_type == 8:
|
||||
attributes.append(_tl.DocumentAttributeSticker(
|
||||
alt='',
|
||||
stickerset=_tl.InputStickerSetEmpty()
|
||||
))
|
||||
elif file_type == 10:
|
||||
attributes.append(_tl.DocumentAttributeAnimated())
|
||||
|
||||
return _tl.Document(
|
||||
id=media_id,
|
||||
access_hash=access_hash,
|
||||
date=None,
|
||||
mime_type='',
|
||||
size=0,
|
||||
thumbs=None,
|
||||
dc_id=dc_id,
|
||||
attributes=attributes,
|
||||
file_reference=b''
|
||||
)
|
||||
elif (version == 2 and len(data) == 44) or (version == 4 and len(data) in (49, 77)):
|
||||
if version == 2:
|
||||
(file_type, dc_id, media_id, access_hash,
|
||||
volume_id, secret, local_id) = struct.unpack('<iiqqqqi', data)
|
||||
# else version == 4:
|
||||
elif len(data) == 49:
|
||||
# TODO Figure out what the extra five bytes mean
|
||||
(file_type, dc_id, media_id, access_hash,
|
||||
volume_id, secret, local_id, _) = struct.unpack('<iiqqqqi5s', data)
|
||||
elif len(data) == 77:
|
||||
# See #1613.
|
||||
(file_type, dc_id, _, media_id, access_hash, volume_id, _, local_id, _) = struct.unpack('<ii28sqqq12sib', data)
|
||||
else:
|
||||
return None
|
||||
|
||||
if not (1 <= dc_id <= 5):
|
||||
return None
|
||||
|
||||
# Thumbnails (small) always have ID 0; otherwise size 'x'
|
||||
photo_size = 's' if media_id or access_hash else 'x'
|
||||
return _tl.Photo(
|
||||
id=media_id,
|
||||
access_hash=access_hash,
|
||||
file_reference=b'',
|
||||
date=None,
|
||||
sizes=[_tl.PhotoSize(
|
||||
type=photo_size,
|
||||
w=0,
|
||||
h=0,
|
||||
size=0
|
||||
)],
|
||||
dc_id=dc_id,
|
||||
has_stickers=None
|
||||
)
|
||||
|
||||
|
||||
def pack_bot_file_id(file):
|
||||
"""
|
||||
Inverse operation for `resolve_bot_file_id`.
|
||||
|
||||
The only parameters this method will accept are :tl:`Document` and
|
||||
:tl:`Photo`, and it will return a variable-length ``file_id`` string.
|
||||
|
||||
If an invalid parameter is given, it will ``return None``.
|
||||
"""
|
||||
if isinstance(file, _tl.MessageMediaDocument):
|
||||
file = file.document
|
||||
elif isinstance(file, _tl.MessageMediaPhoto):
|
||||
file = file.photo
|
||||
|
||||
if isinstance(file, _tl.Document):
|
||||
file_type = 5
|
||||
for attribute in file.attributes:
|
||||
if isinstance(attribute, _tl.DocumentAttributeAudio):
|
||||
file_type = 3 if attribute.voice else 9
|
||||
elif isinstance(attribute, _tl.DocumentAttributeVideo):
|
||||
file_type = 13 if attribute.round_message else 4
|
||||
elif isinstance(attribute, _tl.DocumentAttributeSticker):
|
||||
file_type = 8
|
||||
elif isinstance(attribute, _tl.DocumentAttributeAnimated):
|
||||
file_type = 10
|
||||
else:
|
||||
continue
|
||||
break
|
||||
|
||||
return _encode_telegram_base64(_rle_encode(struct.pack(
|
||||
'<iiqqb', file_type, file.dc_id, file.id, file.access_hash, 2)))
|
||||
|
||||
elif isinstance(file, _tl.Photo):
|
||||
size = next((x for x in reversed(file.sizes) if isinstance(
|
||||
x, (_tl.PhotoSize, _tl.PhotoCachedSize))), None)
|
||||
|
||||
if not size:
|
||||
return None
|
||||
|
||||
size = size.location
|
||||
return _encode_telegram_base64(_rle_encode(struct.pack(
|
||||
'<iiqqqqib', 2, file.dc_id, file.id, file.access_hash,
|
||||
size.volume_id, 0, size.local_id, 2 # 0 = old `secret`
|
||||
)))
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def resolve_invite_link(link):
|
||||
"""
|
||||
Resolves the given invite link. Returns a tuple of
|
||||
|
|
|
@ -18,21 +18,6 @@ class File:
|
|||
def __init__(self, media):
|
||||
self.media = media
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""
|
||||
The bot-API style ``file_id`` representing this file.
|
||||
|
||||
.. note::
|
||||
|
||||
This file ID may not work under user accounts,
|
||||
but should still be usable by bot accounts.
|
||||
|
||||
You can, however, still use it to identify
|
||||
a file in for example a database.
|
||||
"""
|
||||
return utils.pack_bot_file_id(self.media)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user