mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-02-10 00:21:02 +03:00
Change the way thumb size selection works
This commit is contained in:
parent
03de901b7f
commit
e2132d5f7c
|
@ -706,3 +706,9 @@ formatting_entities stays because otherwise it's the only feasible way to manual
|
||||||
todo update send_message and send_file docs (well review all functions)
|
todo update send_message and send_file docs (well review all functions)
|
||||||
|
|
||||||
album overhaul. use a list of Message instead.
|
album overhaul. use a list of Message instead.
|
||||||
|
|
||||||
|
size selector for download_profile_photo and download_media is now different
|
||||||
|
|
||||||
|
still thumb because otherwise documents are weird.
|
||||||
|
|
||||||
|
keep support for explicit size instance?
|
||||||
|
|
|
@ -7,7 +7,7 @@ import inspect
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from .._crypto import AES
|
from .._crypto import AES
|
||||||
from .._misc import utils, helpers, requestiter, tlobject, hints
|
from .._misc import utils, helpers, requestiter, tlobject, hints, enums
|
||||||
from .. import errors, _tl
|
from .. import errors, _tl
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -180,7 +180,7 @@ async def download_profile_photo(
|
||||||
entity: 'hints.EntityLike',
|
entity: 'hints.EntityLike',
|
||||||
file: 'hints.FileLike' = None,
|
file: 'hints.FileLike' = None,
|
||||||
*,
|
*,
|
||||||
download_big: bool = True) -> typing.Optional[str]:
|
thumb) -> typing.Optional[str]:
|
||||||
# hex(crc32(x.encode('ascii'))) for x in
|
# hex(crc32(x.encode('ascii'))) for x in
|
||||||
# ('User', 'Chat', 'UserFull', 'ChatFull')
|
# ('User', 'Chat', 'UserFull', 'ChatFull')
|
||||||
ENTITIES = (0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697)
|
ENTITIES = (0x2da17977, 0xc5af5d94, 0x1f4661b9, 0xd49a2697)
|
||||||
|
@ -189,8 +189,6 @@ async def download_profile_photo(
|
||||||
if not isinstance(entity, tlobject.TLObject) or entity.SUBCLASS_OF_ID in INPUTS:
|
if not isinstance(entity, tlobject.TLObject) or entity.SUBCLASS_OF_ID in INPUTS:
|
||||||
entity = await self.get_entity(entity)
|
entity = await self.get_entity(entity)
|
||||||
|
|
||||||
thumb = -1 if download_big else 0
|
|
||||||
|
|
||||||
possible_names = []
|
possible_names = []
|
||||||
if entity.SUBCLASS_OF_ID not in ENTITIES:
|
if entity.SUBCLASS_OF_ID not in ENTITIES:
|
||||||
photo = entity
|
photo = entity
|
||||||
|
@ -212,11 +210,13 @@ async def download_profile_photo(
|
||||||
photo = entity.photo
|
photo = entity.photo
|
||||||
|
|
||||||
if isinstance(photo, (_tl.UserProfilePhoto, _tl.ChatPhoto)):
|
if isinstance(photo, (_tl.UserProfilePhoto, _tl.ChatPhoto)):
|
||||||
|
thumb = enums.Size.ORIGINAL if thumb == () else enums.parse_photo_size(thumb)
|
||||||
|
|
||||||
dc_id = photo.dc_id
|
dc_id = photo.dc_id
|
||||||
loc = _tl.InputPeerPhotoFileLocation(
|
loc = _tl.InputPeerPhotoFileLocation(
|
||||||
peer=await self.get_input_entity(entity),
|
peer=await self.get_input_entity(entity),
|
||||||
photo_id=photo.photo_id,
|
photo_id=photo.photo_id,
|
||||||
big=download_big
|
big=thumb >= enums.Size.LARGE
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# It doesn't make any sense to check if `photo` can be used
|
# It doesn't make any sense to check if `photo` can be used
|
||||||
|
@ -259,7 +259,7 @@ async def download_media(
|
||||||
message: 'hints.MessageLike',
|
message: 'hints.MessageLike',
|
||||||
file: 'hints.FileLike' = None,
|
file: 'hints.FileLike' = None,
|
||||||
*,
|
*,
|
||||||
thumb: 'typing.Union[int, _tl.TypePhotoSize]' = None,
|
size = (),
|
||||||
progress_callback: 'hints.ProgressCallback' = None) -> typing.Optional[typing.Union[str, bytes]]:
|
progress_callback: 'hints.ProgressCallback' = None) -> typing.Optional[typing.Union[str, bytes]]:
|
||||||
# Downloading large documents may be slow enough to require a new file reference
|
# Downloading large documents may be slow enough to require a new file reference
|
||||||
# to be obtained mid-download. Store (input chat, message id) so that the message
|
# to be obtained mid-download. Store (input chat, message id) so that the message
|
||||||
|
@ -292,11 +292,11 @@ async def download_media(
|
||||||
return await _download_document(
|
return await _download_document(
|
||||||
self, media, file, date, thumb, progress_callback, msg_data
|
self, media, file, date, thumb, progress_callback, msg_data
|
||||||
)
|
)
|
||||||
elif isinstance(media, _tl.MessageMediaContact) and thumb is None:
|
elif isinstance(media, _tl.MessageMediaContact):
|
||||||
return _download_contact(
|
return _download_contact(
|
||||||
self, media, file
|
self, media, file
|
||||||
)
|
)
|
||||||
elif isinstance(media, (_tl.WebDocument, _tl.WebDocumentNoProxy)) and thumb is None:
|
elif isinstance(media, (_tl.WebDocument, _tl.WebDocumentNoProxy)):
|
||||||
return await _download_web_document(
|
return await _download_web_document(
|
||||||
self, media, file, progress_callback
|
self, media, file, progress_callback
|
||||||
)
|
)
|
||||||
|
@ -491,44 +491,15 @@ def _iter_download(
|
||||||
|
|
||||||
|
|
||||||
def _get_thumb(thumbs, thumb):
|
def _get_thumb(thumbs, thumb):
|
||||||
# Seems Telegram has changed the order and put `PhotoStrippedSize`
|
if isinstance(thumb, tlobject.TLObject):
|
||||||
# last while this is the smallest (layer 116). Ensure we have the
|
|
||||||
# sizes sorted correctly with a custom function.
|
|
||||||
def sort_thumbs(thumb):
|
|
||||||
if isinstance(thumb, _tl.PhotoStrippedSize):
|
|
||||||
return 1, len(thumb.bytes)
|
|
||||||
if isinstance(thumb, _tl.PhotoCachedSize):
|
|
||||||
return 1, len(thumb.bytes)
|
|
||||||
if isinstance(thumb, _tl.PhotoSize):
|
|
||||||
return 1, thumb.size
|
|
||||||
if isinstance(thumb, _tl.PhotoSizeProgressive):
|
|
||||||
return 1, max(thumb.sizes)
|
|
||||||
if isinstance(thumb, _tl.VideoSize):
|
|
||||||
return 2, thumb.size
|
|
||||||
|
|
||||||
# Empty size or invalid should go last
|
|
||||||
return 0, 0
|
|
||||||
|
|
||||||
thumbs = list(sorted(thumbs, key=sort_thumbs))
|
|
||||||
|
|
||||||
for i in reversed(range(len(thumbs))):
|
|
||||||
# :tl:`PhotoPathSize` is used for animated stickers preview, and the thumb is actually
|
|
||||||
# a SVG path of the outline. Users expect thumbnails to be JPEG files, so pretend this
|
|
||||||
# thumb size doesn't actually exist (#1655).
|
|
||||||
if isinstance(thumbs[i], _tl.PhotoPathSize):
|
|
||||||
thumbs.pop(i)
|
|
||||||
|
|
||||||
if thumb is None:
|
|
||||||
return thumbs[-1]
|
|
||||||
elif isinstance(thumb, int):
|
|
||||||
return thumbs[thumb]
|
|
||||||
elif isinstance(thumb, str):
|
|
||||||
return next((t for t in thumbs if t.type == thumb), None)
|
|
||||||
elif isinstance(thumb, (_tl.PhotoSize, _tl.PhotoCachedSize,
|
|
||||||
_tl.PhotoStrippedSize, _tl.VideoSize)):
|
|
||||||
return thumb
|
return thumb
|
||||||
else:
|
|
||||||
return None
|
thumb = enums.parse_photo_size(thumb)
|
||||||
|
return min(
|
||||||
|
thumbs,
|
||||||
|
default=None,
|
||||||
|
key=lambda t: abs(thumb - enums.parse_photo_size(t.type))
|
||||||
|
)
|
||||||
|
|
||||||
def _download_cached_photo_size(self: 'TelegramClient', size, file):
|
def _download_cached_photo_size(self: 'TelegramClient', size, file):
|
||||||
# No need to download anything, simply write the bytes
|
# No need to download anything, simply write the bytes
|
||||||
|
@ -623,7 +594,7 @@ async def _download_document(
|
||||||
if not isinstance(document, _tl.Document):
|
if not isinstance(document, _tl.Document):
|
||||||
return
|
return
|
||||||
|
|
||||||
if thumb is None:
|
if thumb == ():
|
||||||
kind, possible_names = _get_kind_and_names(document.attributes)
|
kind, possible_names = _get_kind_and_names(document.attributes)
|
||||||
file = _get_proper_filename(
|
file = _get_proper_filename(
|
||||||
file, kind, utils.get_extension(document),
|
file, kind, utils.get_extension(document),
|
||||||
|
|
|
@ -1610,7 +1610,7 @@ class TelegramClient:
|
||||||
entity: 'hints.EntityLike',
|
entity: 'hints.EntityLike',
|
||||||
file: 'hints.FileLike' = None,
|
file: 'hints.FileLike' = None,
|
||||||
*,
|
*,
|
||||||
download_big: bool = True) -> typing.Optional[str]:
|
thumb: typing.Union[str, enums.Size] = ()) -> typing.Optional[str]:
|
||||||
"""
|
"""
|
||||||
Downloads the profile photo from the given user, chat or channel.
|
Downloads the profile photo from the given user, chat or channel.
|
||||||
|
|
||||||
|
@ -1634,8 +1634,15 @@ class TelegramClient:
|
||||||
If file is the type `bytes`, it will be downloaded in-memory
|
If file is the type `bytes`, it will be downloaded in-memory
|
||||||
as a bytestring (e.g. ``file=bytes``).
|
as a bytestring (e.g. ``file=bytes``).
|
||||||
|
|
||||||
download_big (`bool`, optional):
|
thumb (optional):
|
||||||
Whether to use the big version of the available photos.
|
The thumbnail size to download. A different size may be chosen
|
||||||
|
if the specified size doesn't exist. The category of the size
|
||||||
|
you choose will be respected when possible (e.g. if you
|
||||||
|
specify a cropped size, a cropped variant of similar size will
|
||||||
|
be preferred over a boxed variant of similar size). Cropped
|
||||||
|
images are considered to be smaller than boxed images.
|
||||||
|
|
||||||
|
By default, the largest size (original) is downloaded.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
`None` if no photo was provided, or if it was Empty. On success
|
`None` if no photo was provided, or if it was Empty. On success
|
||||||
|
@ -1655,7 +1662,7 @@ class TelegramClient:
|
||||||
message: 'hints.MessageLike',
|
message: 'hints.MessageLike',
|
||||||
file: 'hints.FileLike' = None,
|
file: 'hints.FileLike' = None,
|
||||||
*,
|
*,
|
||||||
thumb: 'typing.Union[int, _tl.TypePhotoSize]' = None,
|
thumb: typing.Union[str, enums.Size] = (),
|
||||||
progress_callback: 'hints.ProgressCallback' = None) -> typing.Optional[typing.Union[str, bytes]]:
|
progress_callback: 'hints.ProgressCallback' = None) -> typing.Optional[typing.Union[str, bytes]]:
|
||||||
"""
|
"""
|
||||||
Downloads the given media from a message object.
|
Downloads the given media from a message object.
|
||||||
|
@ -1680,29 +1687,15 @@ class TelegramClient:
|
||||||
A callback function accepting two parameters:
|
A callback function accepting two parameters:
|
||||||
``(received bytes, total)``.
|
``(received bytes, total)``.
|
||||||
|
|
||||||
thumb (`int` | :tl:`PhotoSize`, optional):
|
thumb (optional):
|
||||||
Which thumbnail size from the document or photo to download,
|
The thumbnail size to download. A different size may be chosen
|
||||||
instead of downloading the document or photo itself.
|
if the specified size doesn't exist. The category of the size
|
||||||
|
you choose will be respected when possible (e.g. if you
|
||||||
|
specify a cropped size, a cropped variant of similar size will
|
||||||
|
be preferred over a boxed variant of similar size). Cropped
|
||||||
|
images are considered to be smaller than boxed images.
|
||||||
|
|
||||||
If it's specified but the file does not have a thumbnail,
|
By default, the original media is downloaded.
|
||||||
this method will return `None`.
|
|
||||||
|
|
||||||
The parameter should be an integer index between ``0`` and
|
|
||||||
``len(sizes)``. ``0`` will download the smallest thumbnail,
|
|
||||||
and ``len(sizes) - 1`` will download the largest thumbnail.
|
|
||||||
You can also use negative indices, which work the same as
|
|
||||||
they do in Python's `list`.
|
|
||||||
|
|
||||||
You can also pass the :tl:`PhotoSize` instance to use.
|
|
||||||
Alternatively, the thumb size type `str` may be used.
|
|
||||||
|
|
||||||
In short, use ``thumb=0`` if you want the smallest thumbnail
|
|
||||||
and ``thumb=-1`` if you want the largest thumbnail.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
The largest thumbnail may be a video instead of a photo,
|
|
||||||
as they are available since layer 116 and are bigger than
|
|
||||||
any of the photos.
|
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
`None` if no media was provided, or if it was Empty. On success
|
`None` if no media was provided, or if it was Empty. On success
|
||||||
|
|
|
@ -1,6 +1,16 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
def _impl_op(which):
|
||||||
|
def op(self, other):
|
||||||
|
if not isinstance(other, type(self)):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
return getattr(self._val(), which)(other._val())
|
||||||
|
|
||||||
|
return op
|
||||||
|
|
||||||
|
|
||||||
class ConnectionMode(Enum):
|
class ConnectionMode(Enum):
|
||||||
FULL = 'full'
|
FULL = 'full'
|
||||||
INTERMEDIATE = 'intermediate'
|
INTERMEDIATE = 'intermediate'
|
||||||
|
@ -38,6 +48,91 @@ class Action(Enum):
|
||||||
CANCEL = 'cancel'
|
CANCEL = 'cancel'
|
||||||
|
|
||||||
|
|
||||||
|
class Size(Enum):
|
||||||
|
"""
|
||||||
|
See https://core.telegram.org/api/files#image-thumbnail-types.
|
||||||
|
|
||||||
|
* ``'s'``. The image fits within a box of 100x100.
|
||||||
|
* ``'m'``. The image fits within a box of 320x320.
|
||||||
|
* ``'x'``. The image fits within a box of 800x800.
|
||||||
|
* ``'y'``. The image fits within a box of 1280x1280.
|
||||||
|
* ``'w'``. The image fits within a box of 2560x2560.
|
||||||
|
* ``'a'``. The image was cropped to be at most 160x160.
|
||||||
|
* ``'b'``. The image was cropped to be at most 320x320.
|
||||||
|
* ``'c'``. The image was cropped to be at most 640x640.
|
||||||
|
* ``'d'``. The image was cropped to be at most 1280x1280.
|
||||||
|
* ``'i'``. The image comes inline (no need to download anything).
|
||||||
|
* ``'j'``. Only the image outline is present (for stickers).
|
||||||
|
* ``'u'``. The image is actually a short MPEG4 animated video.
|
||||||
|
* ``'v'``. The image is actually a short MPEG4 video preview.
|
||||||
|
|
||||||
|
The sorting order is first dimensions, then ``cropped < boxed < video < other``.
|
||||||
|
"""
|
||||||
|
SMALL = 's'
|
||||||
|
MEDIUM = 'm'
|
||||||
|
LARGE = 'x'
|
||||||
|
EXTRA_LARGE = 'y'
|
||||||
|
ORIGINAL = 'w'
|
||||||
|
CROPPED_SMALL = 'a'
|
||||||
|
CROPPED_MEDIUM = 'b'
|
||||||
|
CROPPED_LARGE = 'c'
|
||||||
|
CROPPED_EXTRA_LARGE = 'd'
|
||||||
|
INLINE = 'i'
|
||||||
|
OUTLINE = 'j'
|
||||||
|
ANIMATED = 'u'
|
||||||
|
VIDEO = 'v'
|
||||||
|
|
||||||
|
def __hash__(self):
|
||||||
|
return object.__hash__(self)
|
||||||
|
|
||||||
|
__sub__ = _impl_op('__sub__')
|
||||||
|
__lt__ = _impl_op('__lt__')
|
||||||
|
__le__ = _impl_op('__le__')
|
||||||
|
__eq__ = _impl_op('__eq__')
|
||||||
|
__ne__ = _impl_op('__ne__')
|
||||||
|
__gt__ = _impl_op('__gt__')
|
||||||
|
__ge__ = _impl_op('__ge__')
|
||||||
|
|
||||||
|
def _val(self):
|
||||||
|
return self._category() * 100 + self._size()
|
||||||
|
|
||||||
|
def _category(self):
|
||||||
|
return {
|
||||||
|
Size.SMALL: 2,
|
||||||
|
Size.MEDIUM: 2,
|
||||||
|
Size.LARGE: 2,
|
||||||
|
Size.EXTRA_LARGE: 2,
|
||||||
|
Size.ORIGINAL: 2,
|
||||||
|
Size.CROPPED_SMALL: 1,
|
||||||
|
Size.CROPPED_MEDIUM: 1,
|
||||||
|
Size.CROPPED_LARGE: 1,
|
||||||
|
Size.CROPPED_EXTRA_LARGE: 1,
|
||||||
|
Size.INLINE: 4,
|
||||||
|
Size.OUTLINE: 5,
|
||||||
|
Size.ANIMATED: 3,
|
||||||
|
Size.VIDEO: 3,
|
||||||
|
}[self]
|
||||||
|
|
||||||
|
def _size(self):
|
||||||
|
return {
|
||||||
|
Size.SMALL: 1,
|
||||||
|
Size.MEDIUM: 3,
|
||||||
|
Size.LARGE: 5,
|
||||||
|
Size.EXTRA_LARGE: 6,
|
||||||
|
Size.ORIGINAL: 7,
|
||||||
|
Size.CROPPED_SMALL: 2,
|
||||||
|
Size.CROPPED_MEDIUM: 3,
|
||||||
|
Size.CROPPED_LARGE: 4,
|
||||||
|
Size.CROPPED_EXTRA_LARGE: 6,
|
||||||
|
# 0, since they're not the original photo at all
|
||||||
|
Size.INLINE: 0,
|
||||||
|
Size.OUTLINE: 0,
|
||||||
|
# same size as original or extra large (videos are large)
|
||||||
|
Size.ANIMATED: 7,
|
||||||
|
Size.VIDEO: 6,
|
||||||
|
}[self]
|
||||||
|
|
||||||
|
|
||||||
def _mk_parser(cls):
|
def _mk_parser(cls):
|
||||||
def parser(value):
|
def parser(value):
|
||||||
if isinstance(value, cls):
|
if isinstance(value, cls):
|
||||||
|
@ -57,3 +152,4 @@ def _mk_parser(cls):
|
||||||
parse_conn_mode = _mk_parser(ConnectionMode)
|
parse_conn_mode = _mk_parser(ConnectionMode)
|
||||||
parse_participant = _mk_parser(Participant)
|
parse_participant = _mk_parser(Participant)
|
||||||
parse_typing_action = _mk_parser(Action)
|
parse_typing_action = _mk_parser(Action)
|
||||||
|
parse_photo_size = _mk_parser(Size)
|
||||||
|
|
|
@ -2,4 +2,5 @@ from ._misc.enums import (
|
||||||
ConnectionMode,
|
ConnectionMode,
|
||||||
Participant,
|
Participant,
|
||||||
Action,
|
Action,
|
||||||
|
Size,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user