diff --git a/readthedocs/misc/v2-migration-guide.rst b/readthedocs/misc/v2-migration-guide.rst index 22bd2acd..995a412e 100644 --- a/readthedocs/misc/v2-migration-guide.rst +++ b/readthedocs/misc/v2-migration-guide.rst @@ -31,6 +31,29 @@ will need to migrate that to support the new size requirement of 8 bytes. For the full list of types changed, please review the above link. +Peer IDs, including chat_id and sender_id, no longer follow bot API conventions +------------------------------------------------------------------------------- + +Both the ``utils.get_peer_id`` and ``client.get_peer_id`` methods no longer have an ``add_mark`` +parameter. Both will always return the original ID as given by Telegram. This should lead to less +confusion. However, it also means that an integer ID on its own no longer embeds the information +about the type (did it belong to a user, chat, or channel?), so ``utils.get_peer`` can no longer +guess the type from just a number. + +Because it's not possible to know what other changes Telegram will do with identifiers, it's +probably best to get used to transparently storing whatever value they send along with the type +separatedly. + +As far as I can tell, user, chat and channel identifiers are globally unique, meaning a channel +and a user cannot share the same identifier. The library currently makes this assumption. However, +this is merely an observation (I have never heard of such a collision exist), and Telegram could +change at any time. If you want to be on the safe side, you're encouraged to save a pair of type +and identifier, rather than just the number. + +// TODO we DEFINITELY need to provide a way to "upgrade" old ids +// TODO and storing type+number by hand is a pain, provide better alternative + + Synchronous compatibility mode has been removed ----------------------------------------------- @@ -244,6 +267,9 @@ The following ``utils`` methods no longer exist or have been made private: * ``utils.pack_bot_file_id``. It was half-broken. * ``utils.resolve_invite_link``. It has been broken for a while, so this just makes its removal official (see `issue #1723 `__). +* ``utils.resolve_id``. Marked IDs are no longer used thorough the library. The removal of this + method also means ``utils.get_peer`` can no longer get a ``Peer`` from just a number, as the + type is no longer embedded inside the ID. // TODO provide the new clean utils diff --git a/telethon/_client/telegramclient.py b/telethon/_client/telegramclient.py index 811ad94b..f3671e0b 100644 --- a/telethon/_client/telegramclient.py +++ b/telethon/_client/telegramclient.py @@ -3541,17 +3541,13 @@ class TelegramClient: async def get_peer_id( self: 'TelegramClient', - peer: 'hints.EntityLike', - add_mark: bool = True) -> int: + peer: 'hints.EntityLike') -> int: """ Gets the ID for the given entity. This method needs to be ``async`` because `peer` supports usernames, invite-links, phone numbers (from people in your contact list), etc. - If ``add_mark is False``, then a positive ID will be returned - instead. By default, bot-API style IDs (signed) are returned. - Example .. code-block:: python diff --git a/telethon/_client/users.py b/telethon/_client/users.py index f3393196..72786fe5 100644 --- a/telethon/_client/users.py +++ b/telethon/_client/users.py @@ -317,10 +317,9 @@ async def _get_peer(self: 'TelegramClient', peer: 'hints.EntityLike'): async def get_peer_id( self: 'TelegramClient', - peer: 'hints.EntityLike', - add_mark: bool = True) -> int: + peer: 'hints.EntityLike') -> int: if isinstance(peer, int): - return utils.get_peer_id(peer, add_mark=add_mark) + return utils.get_peer_id(peer) try: if peer.SUBCLASS_OF_ID not in (0x2d45687, 0xc91c90b6): @@ -332,7 +331,7 @@ async def get_peer_id( if isinstance(peer, _tl.InputPeerSelf): peer = await self.get_me(input_peer=True) - return utils.get_peer_id(peer, add_mark=add_mark) + return utils.get_peer_id(peer) async def _get_entity_from_string(self: 'TelegramClient', string): @@ -381,7 +380,7 @@ async def _get_entity_from_string(self: 'TelegramClient', string): .format(username)) from e try: - pid = utils.get_peer_id(result.peer, add_mark=False) + pid = utils.get_peer_id(result.peer) if isinstance(result.peer, _tl.PeerUser): return next(x for x in result.users if x.id == pid) else: diff --git a/telethon/_misc/entitycache.py b/telethon/_misc/entitycache.py index b6f87697..a191dc6f 100644 --- a/telethon/_misc/entitycache.py +++ b/telethon/_misc/entitycache.py @@ -119,12 +119,10 @@ class EntityCache: update.user_id not in dct: return False - if cid in has_chat_id and \ - utils.get_peer_id(_tl.PeerChat(update.chat_id)) not in dct: + if cid in has_chat_id and update.chat_id not in dct: return False - if cid in has_channel_id and \ - utils.get_peer_id(_tl.PeerChannel(update.channel_id)) not in dct: + if cid in has_channel_id and update.channel_id not in dct: return False if cid in has_peer and \ diff --git a/telethon/_misc/utils.py b/telethon/_misc/utils.py index a92aff0b..e412d563 100644 --- a/telethon/_misc/utils.py +++ b/telethon/_misc/utils.py @@ -961,10 +961,7 @@ def get_inner_text(text, entities): def get_peer(peer): try: - if isinstance(peer, int): - pid, cls = resolve_id(peer) - return cls(pid) - elif peer.SUBCLASS_OF_ID == 0x2d45687: + if peer.SUBCLASS_OF_ID == 0x2d45687: return peer elif isinstance(peer, ( _tl.contacts.ResolvedPeer, _tl.InputNotifyPeer, @@ -993,24 +990,13 @@ def get_peer(peer): _raise_cast_fail(peer, 'Peer') -def get_peer_id(peer, add_mark=True): +def get_peer_id(peer): """ - Convert the given peer into its marked ID by default. - - This "mark" comes from the "bot api" format, and with it the peer type - can be identified back. User ID is left unmodified, chat ID is negated, - and channel ID is "prefixed" with -100: - - * ``user_id`` - * ``-chat_id`` - * ``-100channel_id`` - - The original ID and the peer type class can be returned with - a call to :meth:`resolve_id(marked_id)`. + Extract the integer ID from the given peer. """ # First we assert it's a Peer TLObject, or early return for integers if isinstance(peer, int): - return peer if add_mark else resolve_id(peer)[0] + return peer # Tell the user to use their client to resolve InputPeerSelf if we got one if isinstance(peer, _tl.InputPeerSelf): @@ -1024,34 +1010,9 @@ def get_peer_id(peer, add_mark=True): if isinstance(peer, _tl.PeerUser): return peer.user_id elif isinstance(peer, _tl.PeerChat): - # Check in case the user mixed things up to avoid blowing up - if not (0 < peer.chat_id <= 0x7fffffff): - peer.chat_id = resolve_id(peer.chat_id)[0] - - return -peer.chat_id if add_mark else peer.chat_id + return peer.chat_id else: # if isinstance(peer, _tl.PeerChannel): - # Check in case the user mixed things up to avoid blowing up - if not (0 < peer.channel_id <= 0x7fffffff): - peer.channel_id = resolve_id(peer.channel_id)[0] - - if not add_mark: - return peer.channel_id - - # Growing backwards from -100_0000_000_000 indicates it's a channel - return -(1000000000000 + peer.channel_id) - - -def resolve_id(marked_id): - """Given a marked ID, returns the original ID and its :tl:`Peer` type.""" - if marked_id >= 0: - return marked_id, _tl.PeerUser - - marked_id = -marked_id - if marked_id > 1000000000000: - marked_id -= 1000000000000 - return marked_id, _tl.PeerChannel - else: - return marked_id, _tl.PeerChat + return peer.channel_id def _rle_decode(data): diff --git a/telethon/events/common.py b/telethon/events/common.py index 405537d2..f7b2e066 100644 --- a/telethon/events/common.py +++ b/telethon/events/common.py @@ -18,14 +18,7 @@ async def _into_id_set(client, chats): result = set() for chat in chats: if isinstance(chat, int): - if chat < 0: - result.add(chat) # Explicitly marked IDs are negative - else: - result.update({ # Support all valid types of peers - utils.get_peer_id(_tl.PeerUser(chat)), - utils.get_peer_id(_tl.PeerChat(chat)), - utils.get_peer_id(_tl.PeerChannel(chat)), - }) + result.add(chat) elif isinstance(chat, tlobject.TLObject) and chat.SUBCLASS_OF_ID == 0x2d45687: # 0x2d45687 == crc32(b'Peer') result.add(utils.get_peer_id(chat)) diff --git a/telethon/sessions/memory.py b/telethon/sessions/memory.py index d3d6e22a..5da811b2 100644 --- a/telethon/sessions/memory.py +++ b/telethon/sessions/memory.py @@ -165,17 +165,8 @@ class MemorySession(Session): def get_entity_rows_by_id(self, id, exact=True): try: - if exact: - return next((id, hash) for found_id, hash, _, _, _ - in self._entities if found_id == id) - else: - ids = ( - utils.get_peer_id(_tl.PeerUser(id)), - utils.get_peer_id(_tl.PeerChat(id)), - utils.get_peer_id(_tl.PeerChannel(id)) - ) - return next((id, hash) for found_id, hash, _, _, _ - in self._entities if found_id in ids) + return next((id, hash) for found_id, hash, _, _, _ + in self._entities if found_id == id) except StopIteration: pass diff --git a/telethon/sessions/sqlite.py b/telethon/sessions/sqlite.py index 5b4505c8..15fe5eaf 100644 --- a/telethon/sessions/sqlite.py +++ b/telethon/sessions/sqlite.py @@ -316,16 +316,8 @@ class SQLiteSession(MemorySession): 'select id, hash from entities where name = ?', name) def get_entity_rows_by_id(self, id, exact=True): - if exact: - return self._execute( - 'select id, hash from entities where id = ?', id) - else: - return self._execute( - 'select id, hash from entities where id in (?,?,?)', - utils.get_peer_id(_tl.PeerUser(id)), - utils.get_peer_id(_tl.PeerChat(id)), - utils.get_peer_id(_tl.PeerChannel(id)) - ) + return self._execute( + 'select id, hash from entities where id = ?', id) # File processing diff --git a/telethon_generator/generators/tlobject.py b/telethon_generator/generators/tlobject.py index 9cb43140..bb310c5a 100644 --- a/telethon_generator/generators/tlobject.py +++ b/telethon_generator/generators/tlobject.py @@ -32,7 +32,7 @@ AUTO_CASTS = { } NAMED_AUTO_CASTS = { - ('chat_id', 'int'): 'await client.get_peer_id({}, add_mark=False)' + ('chat_id', 'int'): 'await client.get_peer_id({})' } # Secret chats have a chat_id which may be negative.