Handle all entity types on isinstance checks

Only the uses of `isinstance` against `InputPeer*` types were
reviewed. Notably, `utils` is exempt on this because it needs
to deal with everything on a case-by-case basis.

Since the addition of `*FromMessage` peers, any manual `isinstance`
checks to determine the type were prone to breaking or being
forgotten to be updated, so a common `helpers._entity_type()`
method was made to share this logic.

Since the conversion to `Peer` would be too expensive, a simpler
check against the name is made, which should be fast and cheap.
This commit is contained in:
Lonami Exo
2019-12-23 13:52:07 +01:00
parent 627e176f8e
commit fa736f81af
9 changed files with 97 additions and 37 deletions

View File

@@ -1,10 +1,17 @@
"""Various helpers not related to the Telegram API itself"""
import asyncio
import enum
import os
import struct
from hashlib import sha1
class _EntityType(enum.Enum):
USER = 0
CHAT = 1
CHANNEL = 2
# region Multiple utilities
@@ -131,6 +138,41 @@ def _sync_exit(self, *args):
return loop.run_until_complete(self.__aexit__(*args))
def _entity_type(entity):
# This could be a `utils` method that just ran a few `isinstance` on
# `utils.get_peer(...)`'s result. However, there are *a lot* of auto
# casts going on, plenty of calls and temporary short-lived objects.
#
# So we just check if a string is in the class name.
# Still, assert that it's the right type to not return false results.
try:
if entity.SUBCLASS_OF_ID not in (
0x2d45687, # crc32(b'Peer')
0xc91c90b6, # crc32(b'InputPeer')
0xe669bf46, # crc32(b'InputUser')
0x40f202fd, # crc32(b'InputChannel')
0x2da17977, # crc32(b'User')
0xc5af5d94, # crc32(b'Chat')
0x1f4661b9, # crc32(b'UserFull')
0xd49a2697, # crc32(b'ChatFull')
):
raise TypeError('{} does not have any entity type'.format(entity))
except AttributeError:
raise TypeError('{} is not a TLObject, cannot determine entity type'.format(entity))
name = entity.__class__.__name__
if 'User' in name:
return _EntityType.USER
elif 'Chat' in name:
return _EntityType.CHAT
elif 'Channel' in name:
return _EntityType.CHANNEL
elif 'Self' in name:
return _EntityType.USER
# 'Empty' in name or not found, we don't care, not a valid entity.
raise TypeError('{} does not have any entity type'.format(entity))
# endregion
# region Cryptographic related utils