Turns the given peer into its input entity version. Most requests
        use this kind of :tl:`InputPeer`, so this is the most suitable call
        to make for those cases. **Generally you should let the library do
        its job** and don't worry about getting the input entity first, but
        if you're going to use an entity often, consider making the call:

        >>> import asyncio
        >>> rc = asyncio.get_event_loop().run_until_complete
        >>>
        >>> from telethon import TelegramClient
        >>> client = TelegramClient(...)
        >>> # If you're going to use "username" often in your code
        >>> # (make a lot of calls), consider getting its input entity
        >>> # once, and then using the "user" everywhere instead.
        >>> user = rc(client.get_input_entity('username'))
        >>> # The same applies to IDs, chats or channels.
        >>> chat = rc(client.get_input_entity(-123456789))

        entity (`str` | `int` | :tl:`Peer` | :tl:`InputPeer`):
            If a username or invite link is given, **the library will
            use the cache**. This means that it's possible to be using
            a username that *changed* or an old invite link (this only
            happens if an invite link for a small group chat is used
            after it was upgraded to a mega-group).

            If the username or ID from the invite link is not found in
            the cache, it will be fetched. The same rules apply to phone
            numbers (``'+34 123456789'``) from people in your contact list.

            If an exact name is given, it must be in the cache too. This
            is not reliable as different people can share the same name
            and which entity is returned is arbitrary, and should be used
            only for quick tests.

            If a positive integer ID is given, the entity will be searched
            in cached users, chats or channels, without making any call.

            If a negative integer ID is given, the entity will be searched
            exactly as either a chat (prefixed with ``-``) or as a channel
            (prefixed with ``-100``).

            If a :tl:`Peer` is given, it will be searched exactly in the
            cache as either a user, chat or channel.

            If the given object can be turned into an input entity directly,
            said operation will be done.

            Unsupported types will raise ``TypeError``.

            If the entity can't be found, ``ValueError`` will be raised.

        Returns:
            :tl:`InputPeerUser`, :tl:`InputPeerChat` or :tl:`InputPeerChannel`
            or :tl:`InputPeerSelf` if the parameter is ``'me'`` or ``'self'``.

            If you need to get the ID of yourself, you should use
            `get_me` with ``input_peer=True``) instead.

async def get_input_entity(self, peer):
        """
        Turns the given peer into its input entity version. Most requests
        use this kind of :tl:`InputPeer`, so this is the most suitable call
        to make for those cases. **Generally you should let the library do
        its job** and don't worry about getting the input entity first, but
        if you're going to use an entity often, consider making the call:

        >>> import asyncio
        >>> rc = asyncio.get_event_loop().run_until_complete
        >>>
        >>> from telethon import TelegramClient
        >>> client = TelegramClient(...)
        >>> # If you're going to use "username" often in your code
        >>> # (make a lot of calls), consider getting its input entity
        >>> # once, and then using the "user" everywhere instead.
        >>> user = rc(client.get_input_entity('username'))
        >>> # The same applies to IDs, chats or channels.
        >>> chat = rc(client.get_input_entity(-123456789))

        entity (`str` | `int` | :tl:`Peer` | :tl:`InputPeer`):
            If a username or invite link is given, **the library will
            use the cache**. This means that it's possible to be using
            a username that *changed* or an old invite link (this only
            happens if an invite link for a small group chat is used
            after it was upgraded to a mega-group).

            If the username or ID from the invite link is not found in
            the cache, it will be fetched. The same rules apply to phone
            numbers (``'+34 123456789'``) from people in your contact list.

            If an exact name is given, it must be in the cache too. This
            is not reliable as different people can share the same name
            and which entity is returned is arbitrary, and should be used
            only for quick tests.

            If a positive integer ID is given, the entity will be searched
            in cached users, chats or channels, without making any call.

            If a negative integer ID is given, the entity will be searched
            exactly as either a chat (prefixed with ``-``) or as a channel
            (prefixed with ``-100``).

            If a :tl:`Peer` is given, it will be searched exactly in the
            cache as either a user, chat or channel.

            If the given object can be turned into an input entity directly,
            said operation will be done.

            Unsupported types will raise ``TypeError``.

            If the entity can't be found, ``ValueError`` will be raised.

        Returns:
            :tl:`InputPeerUser`, :tl:`InputPeerChat` or :tl:`InputPeerChannel`
            or :tl:`InputPeerSelf` if the parameter is ``'me'`` or ``'self'``.

            If you need to get the ID of yourself, you should use
            `get_me` with ``input_peer=True``) instead.
        """
        # Short-circuit if the input parameter directly maps to an InputPeer
        try:
            return utils.get_input_peer(peer)
        except TypeError:
            pass

        # Next in priority is having a peer (or its ID) cached in-memory
        try:
            # 0x2d45687 == crc32(b'Peer')
            if isinstance(peer, int) or peer.SUBCLASS_OF_ID == 0x2d45687:
                return self._entity_cache[peer]
        except (AttributeError, KeyError):
            pass

        # Then come known strings that take precedence
        if peer in ('me', 'self'):
            return types.InputPeerSelf()

        # No InputPeer, cached peer, or known string. Fetch from disk cache
        try:
            return self.session.get_input_entity(peer)
        except ValueError:
            pass

        # Only network left to try
        if isinstance(peer, str):
            return utils.get_input_peer(
                await self._get_entity_from_string(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 and not isinstance(users[0], types.UserEmpty):
                # If the user passed a valid ID they expect to work for
                # channels but would be valid for users, we get UserEmpty.
                # Avoid returning the invalid empty input peer for that.
                #
                # We *could* try to guess if it's a channel first, and if
                # it's not, work as a chat and try to validate it through
                # another request, but that becomes too much work.
                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'
            ' find out more details.'
            .format(peer)
        )