diff --git a/telethon/client/users.py b/telethon/client/users.py index 1d4639c1..18c9c9d1 100644 --- a/telethon/client/users.py +++ b/telethon/client/users.py @@ -304,6 +304,26 @@ class UserMethods(TelegramBaseClient): # Also ignore Peer (0x2d45687 == crc32(b'Peer'))'s, lacking hash. return utils.get_input_peer(peer) + # If we're a bot and the user has messaged us privately users.getUsers + # will work with access_hash = 0. Similar for channels.getChannels. + # If we're not a bot but the user is in our contacts, it seems to work + # regardless. These are the only two special-cased requests. + peer = utils.get_peer(peer) + if isinstance(peer, types.PeerUser): + users = await self(functions.users.GetUsersRequest([ + types.InputUser(peer.user_id, access_hash=0)])) + if users: + return utils.get_input_peer(users[0]) + elif isinstance(peer, types.PeerChat): + return types.InputPeerChat(peer.chat_id) + elif isinstance(peer, types.PeerChannel): + try: + channels = await self(functions.channels.GetChannelsRequest([ + types.InputChannel(peer.channel_id, access_hash=0)])) + return utils.get_input_peer(channels.chats[0]) + except errors.ChannelInvalidError: + pass + raise ValueError( 'Could not find the input entity for {!r}. Please read https://' 'telethon.readthedocs.io/en/latest/extra/basic/entities.html to' diff --git a/telethon/utils.py b/telethon/utils.py index 19895253..c568467e 100644 --- a/telethon/utils.py +++ b/telethon/utils.py @@ -114,6 +114,10 @@ def get_input_peer(entity, allow_self=True, check_hash=True): 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``. + + 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``. """ try: if entity.SUBCLASS_OF_ID == 0xc91c90b6: # crc32(b'InputPeer')