mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 01:16:35 +03:00
Don't cache entities with min flag set, bump v1.10.2
Since layer 102, there are two access_hash. One with the min flag, and one without it. This was causing channel invalid errors. access_hash with min flag set can only be used to fetch files such as profile pictures. access_hash with min flag unset can be used under all circumstances. Previously, the library did not distinguish between these, so it was caching the hash that could hardly be used for anything. With this change, only the "full" access_hash is stored, which will work for any methods. See also: https://core.telegram.org/api/min
This commit is contained in:
parent
5c72e1286e
commit
9c06f29aaf
|
@ -100,8 +100,10 @@ class MemorySession(Session):
|
|||
p = utils.get_input_peer(e, allow_self=False)
|
||||
marked_id = utils.get_peer_id(p)
|
||||
except TypeError:
|
||||
# Note: `get_input_peer` already checks for
|
||||
# non-zero `access_hash`. See issues #354 and #392.
|
||||
# Note: `get_input_peer` already checks for non-zero `access_hash`.
|
||||
# See issues #354 and #392. It also checks that the entity
|
||||
# is not `min`, because its `access_hash` cannot be used
|
||||
# anywhere (since layer 102, there are two access hashes).
|
||||
return
|
||||
|
||||
if isinstance(p, (InputPeerUser, InputPeerChannel)):
|
||||
|
|
|
@ -17,7 +17,7 @@ except ImportError as e:
|
|||
sqlite3_err = type(e)
|
||||
|
||||
EXTENSION = '.session'
|
||||
CURRENT_VERSION = 5 # database version
|
||||
CURRENT_VERSION = 6 # database version
|
||||
|
||||
|
||||
class SQLiteSession(MemorySession):
|
||||
|
@ -143,6 +143,12 @@ class SQLiteSession(MemorySession):
|
|||
if old == 4:
|
||||
old += 1
|
||||
c.execute("alter table sessions add column takeout_id integer")
|
||||
if old == 5:
|
||||
# Not really any schema upgrade, but potentially all access
|
||||
# hashes for User and Channel are wrong, so drop them off.
|
||||
old += 1
|
||||
c.execute('delete from entities')
|
||||
|
||||
c.close()
|
||||
|
||||
@staticmethod
|
||||
|
|
|
@ -138,12 +138,34 @@ def get_input_peer(entity, allow_self=True, check_hash=True):
|
|||
Gets the input peer for the given "entity" (user, chat or channel).
|
||||
|
||||
A ``TypeError`` is raised if the given entity isn't a supported type
|
||||
or if ``check_hash is True`` but the entity's ``access_hash is None``.
|
||||
or if ``check_hash is True`` but the entity's ``access_hash is None``
|
||||
*or* the entity contains ``min`` information. In this case, the hash
|
||||
cannot be used for general purposes, and thus is not returned to avoid
|
||||
any issues which can derive from invalid access hashes.
|
||||
|
||||
Note that ``check_hash`` **is ignored** if an input peer is already
|
||||
passed since in that case we assume the user knows what they're doing.
|
||||
This is key to getting entities by explicitly passing ``hash = 0``.
|
||||
"""
|
||||
# NOTE: It is important that this method validates the access hashes,
|
||||
# because it is used when we *require* a valid general-purpose
|
||||
# access hash. This includes caching, which relies on this method.
|
||||
# Further, when resolving raw methods, they do e.g.,
|
||||
# utils.get_input_channel(client.get_input_peer(...))
|
||||
#
|
||||
# ...which means that the client's method verifies the hashes.
|
||||
#
|
||||
# Excerpt from a conversation with official developers (slightly edited):
|
||||
# > We send new access_hash for Channel with min flag since layer 102.
|
||||
# > Previously, we omitted it.
|
||||
# > That one works just to download the profile picture.
|
||||
#
|
||||
# < So, min hashes only work for getting files,
|
||||
# < but the non-min hash is required for any other operation?
|
||||
#
|
||||
# > Yes.
|
||||
#
|
||||
# More information: https://core.telegram.org/api/min
|
||||
try:
|
||||
if entity.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')
|
||||
return entity
|
||||
|
@ -159,19 +181,19 @@ def get_input_peer(entity, allow_self=True, check_hash=True):
|
|||
if isinstance(entity, types.User):
|
||||
if entity.is_self and allow_self:
|
||||
return types.InputPeerSelf()
|
||||
elif entity.access_hash is not None or not check_hash:
|
||||
elif (entity.access_hash is not None and not entity.min) or not check_hash:
|
||||
return types.InputPeerUser(entity.id, entity.access_hash)
|
||||
else:
|
||||
raise TypeError('User without access_hash cannot be input')
|
||||
raise TypeError('User without access_hash or min info cannot be input')
|
||||
|
||||
if isinstance(entity, (types.Chat, types.ChatEmpty, types.ChatForbidden)):
|
||||
return types.InputPeerChat(entity.id)
|
||||
|
||||
if isinstance(entity, (types.Channel, types.ChannelForbidden)):
|
||||
if entity.access_hash is not None or not check_hash:
|
||||
if (entity.access_hash is not None and not entity.min) or not check_hash:
|
||||
return types.InputPeerChannel(entity.id, entity.access_hash)
|
||||
else:
|
||||
raise TypeError('Channel without access_hash cannot be input')
|
||||
raise TypeError('Channel without access_hash or min info cannot be input')
|
||||
|
||||
if isinstance(entity, types.InputUser):
|
||||
return types.InputPeerUser(entity.user_id, entity.access_hash)
|
||||
|
@ -198,7 +220,15 @@ def get_input_peer(entity, allow_self=True, check_hash=True):
|
|||
|
||||
|
||||
def get_input_channel(entity):
|
||||
"""Similar to :meth:`get_input_peer`, but for :tl:`InputChannel`'s alone."""
|
||||
"""
|
||||
Similar to :meth:`get_input_peer`, but for :tl:`InputChannel`'s alone.
|
||||
|
||||
.. important::
|
||||
|
||||
This method does not validate for invalid general-purpose access
|
||||
hashes, unlike `get_input_peer`. Consider using instead:
|
||||
``get_input_channel(get_input_peer(channel))``.
|
||||
"""
|
||||
try:
|
||||
if entity.SUBCLASS_OF_ID == 0x40f202fd: # crc32(b'InputChannel')
|
||||
return entity
|
||||
|
@ -215,7 +245,15 @@ def get_input_channel(entity):
|
|||
|
||||
|
||||
def get_input_user(entity):
|
||||
"""Similar to :meth:`get_input_peer`, but for :tl:`InputUser`'s alone."""
|
||||
"""
|
||||
Similar to :meth:`get_input_peer`, but for :tl:`InputUser`'s alone.
|
||||
|
||||
.. important::
|
||||
|
||||
This method does not validate for invalid general-purpose access
|
||||
hashes, unlike `get_input_peer`. Consider using instead:
|
||||
``get_input_channel(get_input_peer(channel))``.
|
||||
"""
|
||||
try:
|
||||
if entity.SUBCLASS_OF_ID == 0xe669bf46: # crc32(b'InputUser'):
|
||||
return entity
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Versions should comply with PEP440.
|
||||
# This line is parsed in setup.py:
|
||||
__version__ = '1.10.1'
|
||||
__version__ = '1.10.2'
|
||||
|
|
Loading…
Reference in New Issue
Block a user