diff --git a/readthedocs/concepts/chats-vs-channels.rst b/readthedocs/concepts/chats-vs-channels.rst index 87281373..51ffef7a 100644 --- a/readthedocs/concepts/chats-vs-channels.rst +++ b/readthedocs/concepts/chats-vs-channels.rst @@ -100,12 +100,12 @@ Note that this function can also work with other types, like :tl:`Chat` or :tl:`Channel` instances. If you need to convert other types like usernames which might need to perform -API calls to find out the identifier, you can use ``client.get_peer_id``: +API calls to find out the identifier, you can use ``client.get_profile``: .. code-block:: python - print(await client.get_peer_id('me')) # your id + print((await client.get_profile('me')).id) # your id If there is no "mark" (no minus sign), Telethon will assume your identifier diff --git a/readthedocs/concepts/full-api.rst b/readthedocs/concepts/full-api.rst index ac38e3d4..374633f4 100644 --- a/readthedocs/concepts/full-api.rst +++ b/readthedocs/concepts/full-api.rst @@ -129,7 +129,7 @@ as you wish. Remember to use the right types! To sum up: .. code-block:: python result = await client(SendMessageRequest( - await client.get_input_entity('username'), 'Hello there!' + await client.get_profile('username'), 'Hello there!' )) diff --git a/readthedocs/concepts/strings.rst b/readthedocs/concepts/strings.rst index a696b684..b8e25c12 100644 --- a/readthedocs/concepts/strings.rst +++ b/readthedocs/concepts/strings.rst @@ -8,7 +8,7 @@ does a result have? Well, the easiest thing to do is printing it: .. code-block:: python - entity = await client.get_entity('username') + entity = await client.get_profile('username') print(entity) That will show a huge **string** similar to the following: diff --git a/readthedocs/examples/chats-and-channels.rst b/readthedocs/examples/chats-and-channels.rst index 2c3823c3..4d84615b 100644 --- a/readthedocs/examples/chats-and-channels.rst +++ b/readthedocs/examples/chats-and-channels.rst @@ -107,7 +107,7 @@ use :tl:`GetMessagesViewsRequest`, setting ``increment=True``: .. code-block:: python - # Obtain `channel' through dialogs or through client.get_entity() or anyhow. + # Obtain `channel' through dialogs or through client.get_profile() or anyhow. # Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list. await client(GetMessagesViewsRequest( diff --git a/readthedocs/misc/v2-migration-guide.rst b/readthedocs/misc/v2-migration-guide.rst index 86ee2194..3c649b46 100644 --- a/readthedocs/misc/v2-migration-guide.rst +++ b/readthedocs/misc/v2-migration-guide.rst @@ -54,6 +54,7 @@ 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 +// TODO get_peer_id is gone now too! Synchronous compatibility mode has been removed diff --git a/readthedocs/quick-references/client-reference.rst b/readthedocs/quick-references/client-reference.rst index a713907f..482ce320 100644 --- a/readthedocs/quick-references/client-reference.rst +++ b/readthedocs/quick-references/client-reference.rst @@ -118,9 +118,7 @@ Users get_me is_bot is_user_authorized - get_entity - get_input_entity - get_peer_id + get_profile Chats ----- diff --git a/telethon/_client/bots.py b/telethon/_client/bots.py index 22945cbf..e1e5fe5f 100644 --- a/telethon/_client/bots.py +++ b/telethon/_client/bots.py @@ -16,9 +16,9 @@ async def inline_query( dialog: 'hints.DialogLike' = None, offset: str = None, geo_point: '_tl.GeoPoint' = None) -> _custom.InlineResults: - bot = await self.get_input_entity(bot) + bot = await self._get_input_peer(bot) if dialog: - peer = await self.get_input_entity(dialog) + peer = await self._get_input_peer(dialog) else: peer = _tl.InputPeerEmpty() diff --git a/telethon/_client/chats.py b/telethon/_client/chats.py index 2bb34d45..f132d66d 100644 --- a/telethon/_client/chats.py +++ b/telethon/_client/chats.py @@ -30,7 +30,7 @@ class _ChatAction: return self._once().__await__() async def __aenter__(self): - self._request = dataclasses.replace(self._request, peer=await self._client.get_input_entity(self._request.peer)) + self._request = dataclasses.replace(self._request, peer=await self._client._get_input_peer(self._request.peer)) self._running = True self._task = asyncio.create_task(self._update()) return self @@ -47,7 +47,7 @@ class _ChatAction: self._task = None async def _once(self): - self._request = dataclasses.replace(self._request, peer=await self._client.get_input_entity(self._request.peer)) + self._request = dataclasses.replace(self._request, peer=await self._client._get_input_peer(self._request.peer)) await self._client(_tl.fn.messages.SetTyping(self._chat, self._action)) async def _update(self): @@ -114,7 +114,7 @@ class _ParticipantsIter(requestiter.RequestIter): else: raise RuntimeError('unhandled enum variant') - entity = await self.client.get_input_entity(entity) + entity = await self.client._get_input_peer(entity) ty = helpers._entity_type(entity) if search and (filter or ty != helpers._EntityType.CHANNEL): # We need to 'search' ourselves unless we have a PeerChannel @@ -172,7 +172,7 @@ class _ParticipantsIter(requestiter.RequestIter): else: self.total = 1 if self.limit != 0: - user = await self.client.get_entity(entity) + user = await self.client.get_profile(entity) if self.filter_entity(user): self.buffer.append(user) @@ -232,7 +232,7 @@ class _AdminLogIter(requestiter.RequestIter): else: events_filter = None - self.entity = await self.client.get_input_entity(entity) + self.entity = await self.client._get_input_peer(entity) admin_list = [] if admins: @@ -240,7 +240,7 @@ class _AdminLogIter(requestiter.RequestIter): admins = (admins,) for admin in admins: - admin_list.append(await self.client.get_input_entity(admin)) + admin_list.append(await self.client._get_input_peer(admin)) self.request = _tl.fn.channels.GetAdminLog( self.entity, q=search or '', min_id=min_id, max_id=max_id, @@ -278,7 +278,7 @@ class _ProfilePhotoIter(requestiter.RequestIter): async def _init( self, entity, offset, max_id ): - entity = await self.client.get_input_entity(entity) + entity = await self.client._get_input_peer(entity) ty = helpers._entity_type(entity) if ty == helpers._EntityType.USER: self.request = _tl.fn.photos.GetUserPhotos( @@ -481,8 +481,8 @@ async def edit_admin( anonymous: bool = None, is_admin: bool = None, title: str = None) -> _tl.Updates: - entity = await self.get_input_entity(chat) - user = await self.get_input_entity(user) + entity = await self._get_input_peer(chat) + user = await self._get_input_peer(user) ty = helpers._entity_type(user) perm_names = ( @@ -499,7 +499,7 @@ async def edit_admin( if post_messages or edit_messages: # TODO get rid of this once sessions cache this information if entity.channel_id not in self._megagroup_cache: - full_entity = await self.get_entity(entity) + full_entity = await self.get_profile(entity) self._megagroup_cache[entity.channel_id] = full_entity.megagroup if self._megagroup_cache[entity.channel_id]: @@ -545,7 +545,7 @@ async def edit_permissions( change_info: bool = True, invite_users: bool = True, pin_messages: bool = True) -> _tl.Updates: - entity = await self.get_input_entity(chat) + entity = await self._get_input_peer(chat) ty = helpers._entity_type(entity) rights = _tl.ChatBannedRights( @@ -570,7 +570,7 @@ async def edit_permissions( banned_rights=rights )) - user = await self.get_input_entity(user) + user = await self._get_input_peer(user) if isinstance(user, _tl.InputPeerSelf): raise ValueError('You cannot restrict yourself') @@ -586,8 +586,8 @@ async def kick_participant( chat: 'hints.DialogLike', user: 'typing.Optional[hints.DialogLike]' ): - entity = await self.get_input_entity(chat) - user = await self.get_input_entity(user) + entity = await self._get_input_peer(chat) + user = await self._get_input_peer(user) ty = helpers._entity_type(entity) if ty == helpers._EntityType.CHAT: @@ -620,14 +620,14 @@ async def get_permissions( chat: 'hints.DialogLike', user: 'hints.DialogLike' = None ) -> 'typing.Optional[_custom.ParticipantPermissions]': - entity = await self.get_entity(chat) + entity = await self.get_profile(chat) if not user: if helpers._entity_type(entity) != helpers._EntityType.USER: return entity.default_banned_rights - entity = await self.get_input_entity(entity) - user = await self.get_input_entity(user) + entity = await self._get_input_peer(entity) + user = await self._get_input_peer(user) if helpers._entity_type(entity) == helpers._EntityType.CHANNEL: participant = await self(_tl.fn.channels.GetParticipant( @@ -653,7 +653,7 @@ async def get_stats( chat: 'hints.DialogLike', message: 'typing.Union[int, _tl.Message]' = None, ): - entity = await self.get_input_entity(chat) + entity = await self._get_input_peer(chat) message = utils.get_message_id(message) if message is not None: diff --git a/telethon/_client/dialogs.py b/telethon/_client/dialogs.py index c1d12028..7b3b722f 100644 --- a/telethon/_client/dialogs.py +++ b/telethon/_client/dialogs.py @@ -122,7 +122,7 @@ class _DraftsIter(requestiter.RequestIter): peers = [] for entity in entities: peers.append(_tl.InputDialogPeer( - await self.client.get_input_entity(entity))) + await self.client._get_input_peer(entity))) r = await self.client(_tl.fn.messages.GetPeerDialogs(peers)) items = r.dialogs @@ -189,7 +189,7 @@ async def delete_dialog( else: deactivated = False - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) ty = helpers._entity_type(entity) if ty == helpers._EntityType.CHANNEL: return await self(_tl.fn.channels.LeaveChannel(entity)) diff --git a/telethon/_client/downloads.py b/telethon/_client/downloads.py index f73b1412..0f919510 100644 --- a/telethon/_client/downloads.py +++ b/telethon/_client/downloads.py @@ -190,7 +190,7 @@ async def download_profile_photo( INPUTS = (0xc91c90b6, 0xe669bf46, 0x40f202fd) entity = profile if not isinstance(entity, tlobject.TLObject) or entity.SUBCLASS_OF_ID in INPUTS: - entity = await self.get_entity(entity) + entity = await self.get_profile(entity) possible_names = [] if entity.SUBCLASS_OF_ID not in ENTITIES: @@ -217,7 +217,7 @@ async def download_profile_photo( dc_id = photo.dc_id loc = _tl.InputPeerPhotoFileLocation( - peer=await self.get_input_entity(entity), + peer=await self._get_input_peer(entity), photo_id=photo.photo_id, big=thumb >= enums.Size.LARGE ) @@ -244,7 +244,7 @@ async def download_profile_photo( except errors.LocationInvalidError: # See issue #500, Android app fails as of v4.6.0 (1155). # The fix seems to be using the full channel chat photo. - ie = await self.get_input_entity(entity) + ie = await self._get_input_peer(entity) ty = helpers._entity_type(ie) if ty == helpers._EntityType.CHANNEL: full = await self(_tl.fn.channels.GetFullChannel(ie)) diff --git a/telethon/_client/messageparse.py b/telethon/_client/messageparse.py index ab828209..1111afe5 100644 --- a/telethon/_client/messageparse.py +++ b/telethon/_client/messageparse.py @@ -19,7 +19,7 @@ async def _replace_with_mention(self: 'TelegramClient', entities, i, user): try: entities[i] = _tl.InputMessageEntityMentionName( entities[i].offset, entities[i].length, - await self.get_input_entity(user) + await self._get_input_peer(user) ) return True except (ValueError, TypeError): diff --git a/telethon/_client/messages.py b/telethon/_client/messages.py index f5ab9ff3..c2f7ff89 100644 --- a/telethon/_client/messages.py +++ b/telethon/_client/messages.py @@ -28,7 +28,7 @@ class _MessagesIter(requestiter.RequestIter): ): # Note that entity being `None` will perform a global search. if entity: - self.entity = await self.client.get_input_entity(entity) + self.entity = await self.client._get_input_peer(entity) else: self.entity = None if self.reverse: @@ -62,8 +62,8 @@ class _MessagesIter(requestiter.RequestIter): offset_id = 1 if from_user: - from_user = await self.client.get_input_entity(from_user) - self.from_id = await self.client.get_peer_id(from_user) + from_user = await self.client._get_input_peer(from_user) + self.from_id = await self.client._get_peer_id(from_user) else: self.from_id = None @@ -272,7 +272,7 @@ class _IDsIter(requestiter.RequestIter): self.total = len(ids) self._ids = list(reversed(ids)) if self.reverse else ids self._offset = 0 - self._entity = (await self.client.get_input_entity(entity)) if entity else None + self._entity = (await self.client._get_input_peer(entity)) if entity else None self._ty = helpers._entity_type(self._entity) if self._entity else None # 30s flood wait every 300 messages (3 requests of 100 each, 30 of 10, etc.) @@ -327,7 +327,7 @@ async def _get_peer(self: 'TelegramClient', input_peer: 'hints.DialogLike'): return utils.get_peer(input_peer) except TypeError: # Can only be self by now - return _tl.PeerUser(await self.get_peer_id(input_peer)) + return _tl.PeerUser(await self._get_peer_id(input_peer)) def get_messages( @@ -466,7 +466,7 @@ async def send_message( elif not isinstance(message, InputMessage): raise TypeError(f'message must be either str, Message or InputMessage, but got: {message!r}') - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) if comment_to is not None: entity, reply_to = await _get_comment_data(self, entity, comment_to) elif reply_to: @@ -540,11 +540,11 @@ async def forward_messages( if as_album is not None: warnings.warn('the as_album argument is deprecated and no longer has any effect') - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) if from_dialog: - from_peer = await self.get_input_entity(from_dialog) - from_peer_id = await self.get_peer_id(from_peer) + from_peer = await self._get_input_peer(from_dialog) + from_peer_id = await self._get_peer_id(from_peer) else: from_peer = None from_peer_id = None @@ -632,7 +632,7 @@ async def edit_message( else: return await self(request) - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) request = _tl.fn.messages.EditMessage( peer=entity, id=utils.get_message_id(message), @@ -659,7 +659,7 @@ async def delete_messages( ) if dialog: - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) ty = helpers._entity_type(entity) else: # no entity (None), set a value that's not a channel for private delete @@ -689,7 +689,7 @@ async def mark_read( else: max_id = message.id - entity = await self.get_input_entity(dialog) + entity = await self._get_input_peer(dialog) if clear_mentions: await self(_tl.fn.messages.ReadMentions(entity)) @@ -726,7 +726,7 @@ async def unpin_message( async def _pin(self, entity, message, *, unpin, notify=False, pm_oneside=False): message = utils.get_message_id(message) or 0 - entity = await self.get_input_entity(entity) + entity = await self._get_input_peer(entity) if message <= 0: # old behaviour accepted negative IDs to unpin await self(_tl.fn.messages.UnpinAllMessages(entity)) return diff --git a/telethon/_client/telegramclient.py b/telethon/_client/telegramclient.py index 66673b73..3c242647 100644 --- a/telethon/_client/telegramclient.py +++ b/telethon/_client/telegramclient.py @@ -3326,7 +3326,7 @@ class TelegramClient: ... # Note that for this to work the phone number must be in your contacts - some_id = await client.get_peer_id('+34123456789') + some_id = (await client.get_profile('+34123456789')).id """ # endregion Users @@ -3395,4 +3395,12 @@ class TelegramClient: progress_callback: 'hints.ProgressCallback' = None) -> '_tl.TypeInputFile': pass + @forward_call(users._get_input_peer) + async def _get_input_peer(self, *, save=True, **changes): + pass + + @forward_call(users._get_peer_id) + async def _get_peer_id(self, *, save=True, **changes): + pass + # endregion Private diff --git a/telethon/_client/uploads.py b/telethon/_client/uploads.py index c91acdcb..d5b79c81 100644 --- a/telethon/_client/uploads.py +++ b/telethon/_client/uploads.py @@ -168,7 +168,7 @@ async def _send_album(self: 'TelegramClient', entity, files, caption='', # In theory documents can be sent inside the albums but they appear # as different messages (not inside the album), and the logic to set # the attributes/avoid cache is already written in .send_file(). - entity = await self.get_input_entity(entity) + entity = await self._get_input_peer(entity) if not utils.is_list_like(caption): caption = (caption,) diff --git a/telethon/_client/users.py b/telethon/_client/users.py index 63138e53..909b15b4 100644 --- a/telethon/_client/users.py +++ b/telethon/_client/users.py @@ -166,7 +166,7 @@ async def get_profile( if isinstance(x, str): inputs.append(x) else: - inputs.append(await self.get_input_entity(x)) + inputs.append(await self._get_input_peer(x)) lists = { helpers._EntityType.USER: [], @@ -220,7 +220,7 @@ async def get_profile( return result[0] if single else result -async def get_input_entity( +async def _get_input_peer( self: 'TelegramClient', peer: 'hints.DialogLike') -> '_tl.TypeInputPeer': # Short-circuit if the input parameter directly maps to an InputPeer @@ -287,7 +287,7 @@ async def get_input_entity( .format(peer, type(peer).__name__) ) -async def get_peer_id( +async def _get_peer_id( self: 'TelegramClient', peer: 'hints.DialogLike') -> int: if isinstance(peer, int): @@ -296,9 +296,9 @@ async def get_peer_id( try: if peer.SUBCLASS_OF_ID not in (0x2d45687, 0xc91c90b6): # 0x2d45687, 0xc91c90b6 == crc32(b'Peer') and b'InputPeer' - peer = await self.get_input_entity(peer) + peer = await self._get_input_peer(peer) except AttributeError: - peer = await self.get_input_entity(peer) + peer = await self._get_input_peer(peer) if isinstance(peer, _tl.InputPeerSelf): peer = _tl.PeerUser(self._session_state.user_id) @@ -372,13 +372,13 @@ async def _get_input_dialog(self: 'TelegramClient', dialog): """ try: if dialog.SUBCLASS_OF_ID == 0xa21c9795: # crc32(b'InputDialogPeer') - return dataclasses.replace(dialog, peer=await self.get_input_entity(dialog.peer)) + return dataclasses.replace(dialog, peer=await self._get_input_peer(dialog.peer)) elif dialog.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer') return _tl.InputDialogPeer(dialog) except AttributeError: pass - return _tl.InputDialogPeer(await self.get_input_entity(dialog)) + return _tl.InputDialogPeer(await self._get_input_peer(dialog)) async def _get_input_notify(self: 'TelegramClient', notify): """ @@ -389,9 +389,9 @@ async def _get_input_notify(self: 'TelegramClient', notify): try: if notify.SUBCLASS_OF_ID == 0x58981615: if isinstance(notify, _tl.InputNotifyPeer): - return dataclasses.replace(notify, peer=await self.get_input_entity(notify.peer)) + return dataclasses.replace(notify, peer=await self._get_input_peer(notify.peer)) return notify except AttributeError: pass - return _tl.InputNotifyPeer(await self.get_input_entity(notify)) + return _tl.InputNotifyPeer(await self._get_input_peer(notify)) diff --git a/telethon/_events/chataction.py b/telethon/_events/chataction.py index 6b4d21e9..435ab459 100644 --- a/telethon/_events/chataction.py +++ b/telethon/_events/chataction.py @@ -307,7 +307,7 @@ class ChatAction(EventBuilder): Returns `added_by` but will make an API call if necessary. """ if not self.added_by and self._added_by: - self._added_by = await self._client.get_entity(self._added_by) + self._added_by = await self._client.get_profile(self._added_by) return self._added_by @@ -328,7 +328,7 @@ class ChatAction(EventBuilder): Returns `kicked_by` but will make an API call if necessary. """ if not self.kicked_by and self._kicked_by: - self._kicked_by = await self._client.get_entity(self._kicked_by) + self._kicked_by = await self._client.get_profile(self._kicked_by) return self._kicked_by diff --git a/telethon/types/_custom/draft.py b/telethon/types/_custom/draft.py index fba7f4d2..60aabdaf 100644 --- a/telethon/types/_custom/draft.py +++ b/telethon/types/_custom/draft.py @@ -58,7 +58,7 @@ class Draft: if not self.entity and await self.get_input_entity(): try: self._entity =\ - await self._client.get_entity(self._input_entity) + await self._client.get_profile(self._input_entity) except ValueError: pass diff --git a/telethon/types/_custom/inlineresult.py b/telethon/types/_custom/inlineresult.py index 84d8f64d..0a659f8e 100644 --- a/telethon/types/_custom/inlineresult.py +++ b/telethon/types/_custom/inlineresult.py @@ -143,7 +143,7 @@ class InlineResult: """ if entity: - entity = await self._client.get_input_entity(entity) + entity = await self._client.get_input_peer(entity) elif self._entity: entity = self._entity else: diff --git a/telethon/types/_custom/messagebutton.py b/telethon/types/_custom/messagebutton.py index ce5f7ed1..9286c042 100644 --- a/telethon/types/_custom/messagebutton.py +++ b/telethon/types/_custom/messagebutton.py @@ -72,7 +72,7 @@ class MessageButton: it will be "clicked" and the :tl:`BotCallbackAnswer` returned. If it's an inline :tl:`KeyboardButtonUserProfile` button, the - `client.get_entity` will be called and the resulting :tl:User will be + `client.get_profile` will be called and the resulting :tl:User will be returned. If it's an inline :tl:`KeyboardButtonSwitchInline` button, the @@ -112,7 +112,7 @@ class MessageButton: except BotResponseTimeoutError: return None elif isinstance(self.button, _tl.KeyboardButtonUserProfile): - return await self._client.get_entity(self.button.user_id) + return await self._client.get_profile(self.button.user_id) elif isinstance(self.button, _tl.KeyboardButtonSwitchInline): return await self._client(_tl.fn.messages.StartBot( bot=self._bot, peer=self._chat, start_param=self.button.query, diff --git a/telethon_examples/gui.py b/telethon_examples/gui.py index 78dcfb34..fb369c2f 100644 --- a/telethon_examples/gui.py +++ b/telethon_examples/gui.py @@ -322,7 +322,7 @@ class App(tkinter.Tk): try: old = self.chat_id # Valid chat ID, set it and configure the colour back to white - self.chat_id = await self.cl.get_peer_id(chat) + self.chat_id = (await self.cl.get_profile(chat)).id self.chat.configure(bg='white') # If the chat ID changed, clear the diff --git a/telethon_generator/data/friendly.csv b/telethon_generator/data/friendly.csv index 4d53c862..524746d5 100644 --- a/telethon_generator/data/friendly.csv +++ b/telethon_generator/data/friendly.csv @@ -23,4 +23,4 @@ messages.MessageMethods,delete_messages,channels.deleteMessages messages.deleteM messages.MessageMethods,send_read_acknowledge,messages.readMentions channels.readHistory messages.readHistory updates.UpdateMethods,catch_up,updates.getDifference updates.getChannelDifference uploads.UploadMethods,send_file,messages.sendMedia messages.sendMultiMedia messages.uploadMedia -users.UserMethods,get_entity,users.getUsers messages.getChats channels.getChannels contacts.resolveUsername +users.UserMethods,get_profile,users.getUsers messages.getChats channels.getChannels contacts.resolveUsername diff --git a/telethon_generator/generators/tlobject.py b/telethon_generator/generators/tlobject.py index 0893cca1..f52c497b 100644 --- a/telethon_generator/generators/tlobject.py +++ b/telethon_generator/generators/tlobject.py @@ -16,11 +16,11 @@ AUTO_GEN_NOTICE = \ AUTO_CASTS = { 'InputPeer': - 'utils.get_input_peer(await client.get_input_entity({}))', + 'utils.get_input_peer(await client._get_input_peer({}))', 'InputChannel': - 'utils.get_input_channel(await client.get_input_entity({}))', + 'utils.get_input_channel(await client._get_input_peer({}))', 'InputUser': - 'utils.get_input_user(await client.get_input_entity({}))', + 'utils.get_input_user(await client._get_input_peer({}))', 'InputDialogPeer': 'await client._get_input_dialog({})', 'InputNotifyPeer': 'await client._get_input_notify({})', @@ -33,7 +33,7 @@ AUTO_CASTS = { } NAMED_AUTO_CASTS = { - ('chat_id', 'int'): 'await client.get_peer_id({})' + ('chat_id', 'int'): 'await client._get_peer_id({})' } # Secret chats have a chat_id which may be negative.