Starts or completes the sign in process with the given phone number
        or code that Telegram sent.

        Args:
            phone (`str` | `int`):
                The phone to send the code to if no code was provided,
                or to override the phone that was previously used with
                these requests.

            code (`str` | `int`):
                The code that Telegram sent. Note that if you have sent this
                code through the application itself it will immediately
                expire. If you want to send the code, obfuscate it somehow.
                If you're not doing any of this you can ignore this note.

            password (`str`):
                2FA password, should be used if a previous call raised
                SessionPasswordNeededError.

            bot_token (`str`):
                Used to sign in as a bot. Not all requests will be available.
                This should be the hash the @BotFather gave you.

            phone_code_hash (`str`, optional):
                The hash returned by `send_code_request`. This can be left as
                ``None`` to use the last hash known for the phone to be used.

        Returns:
            The signed in user, or the information about
            :meth:`send_code_request`.

async def sign_in(
            self, phone=None, code=None, *, password=None,
            bot_token=None, phone_code_hash=None):
        """
        Starts or completes the sign in process with the given phone number
        or code that Telegram sent.

        Args:
            phone (`str` | `int`):
                The phone to send the code to if no code was provided,
                or to override the phone that was previously used with
                these requests.

            code (`str` | `int`):
                The code that Telegram sent. Note that if you have sent this
                code through the application itself it will immediately
                expire. If you want to send the code, obfuscate it somehow.
                If you're not doing any of this you can ignore this note.

            password (`str`):
                2FA password, should be used if a previous call raised
                SessionPasswordNeededError.

            bot_token (`str`):
                Used to sign in as a bot. Not all requests will be available.
                This should be the hash the @BotFather gave you.

            phone_code_hash (`str`, optional):
                The hash returned by `send_code_request`. This can be left as
                ``None`` to use the last hash known for the phone to be used.

        Returns:
            The signed in user, or the information about
            :meth:`send_code_request`.
        """
        me = await self.get_me()
        if me:
            return me

        if phone and not code and not password:
            return await self.send_code_request(phone)
        elif code:
            phone, phone_code_hash = \
                self._parse_phone_and_hash(phone, phone_code_hash)

            # May raise PhoneCodeEmptyError, PhoneCodeExpiredError,
            # PhoneCodeHashEmptyError or PhoneCodeInvalidError.
            result = await self(functions.auth.SignInRequest(
                phone, phone_code_hash, str(code)))
        elif password:
            pwd = await self(functions.account.GetPasswordRequest())
            result = await self(functions.auth.CheckPasswordRequest(
                pwd_mod.compute_check(pwd, password)
            ))
        elif bot_token:
            result = await self(functions.auth.ImportBotAuthorizationRequest(
                flags=0, bot_auth_token=bot_token,
                api_id=self.api_id, api_hash=self.api_hash
            ))
        else:
            raise ValueError(
                'You must provide a phone and a code the first time, '
                'and a password only if an RPCError was raised before.'
            )

        return self._on_login(result.user)