mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-09-19 18:32:47 +03:00
2nd version. Review pending...
This commit is contained in:
parent
d0439d8dc9
commit
eb38ed5443
|
@ -1,5 +1,6 @@
|
||||||
import itertools
|
import itertools
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
from collections import OrderedDict, UserList
|
from collections import OrderedDict, UserList
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
@ -184,8 +185,7 @@ class TelegramClient(TelegramBareClient):
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def start(self, phone=None, bot_token=None, force_sms=False, code_callback=None,
|
def start(self, phone=None, password=None, bot_token=None, force_sms=False, code_callback=None):
|
||||||
password_callback=None):
|
|
||||||
"""Convenience method to interactively connect and authorize.
|
"""Convenience method to interactively connect and authorize.
|
||||||
|
|
||||||
Example usage:
|
Example usage:
|
||||||
|
@ -194,21 +194,21 @@ class TelegramClient(TelegramBareClient):
|
||||||
Please enter your password: *******
|
Please enter your password: *******
|
||||||
(You are now logged in)
|
(You are now logged in)
|
||||||
|
|
||||||
Custom `code_callback` and `password_callback` functions without arguments can be
|
A custom `code_callback` function without arguments can be provided that will be used to
|
||||||
provided that will be used to obtain the Telegram login code and 2FA password,
|
obtain the Telegram login code. It will default to the `input()` function from
|
||||||
respectively. They will default to the `input()` function from the standard library.
|
the standard library.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
phone (:obj:`str` | :obj:`int`):
|
phone (:obj:`str` | :obj:`int`):
|
||||||
The phone to which the code will be sent.
|
The phone to which the code will be sent.
|
||||||
|
password (:obj:`callable`, optional):
|
||||||
|
The password for 2FA.
|
||||||
bot_token (:obj:`str`):
|
bot_token (:obj:`str`):
|
||||||
Bot Token obtained by @BotFather to log in as a bot.
|
Bot Token obtained by @BotFather to log in as a bot.
|
||||||
force_sms (:obj:`bool`, optional):
|
force_sms (:obj:`bool`, optional):
|
||||||
Whether to force sending as SMS.
|
Whether to force sending the code request as SMS.
|
||||||
code_callback (:obj:`callable`, optional):
|
code_callback (:obj:`callable`, optional):
|
||||||
A callable that will be used to retrieve the Telegram login code.
|
A callable that will be used to retrieve the Telegram login code.
|
||||||
password_callback (:obj:`callable`, optional):
|
|
||||||
A callable that will be used to retrieve the user's 2FA password.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
:obj:`TelegramClient`: This client.
|
:obj:`TelegramClient`: This client.
|
||||||
|
@ -221,13 +221,6 @@ class TelegramClient(TelegramBareClient):
|
||||||
raise ValueError("The code_callback parameter needs to be a callable function that "
|
raise ValueError("The code_callback parameter needs to be a callable function that "
|
||||||
"returns the code you received by Telegram.")
|
"returns the code you received by Telegram.")
|
||||||
|
|
||||||
if password_callback is None:
|
|
||||||
password_callback = lambda: input("Please enter your password: ")
|
|
||||||
else:
|
|
||||||
if not callable(password_callback):
|
|
||||||
raise ValueError("The password_callback parameter needs to be a callable function "
|
|
||||||
"that returns your Telegram password.")
|
|
||||||
|
|
||||||
if (phone and bot_token) or (not phone and not bot_token):
|
if (phone and bot_token) or (not phone and not bot_token):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'You must provide either a phone number or a bot token.'
|
'You must provide either a phone number or a bot token.'
|
||||||
|
@ -239,6 +232,8 @@ class TelegramClient(TelegramBareClient):
|
||||||
if self.is_user_authorized():
|
if self.is_user_authorized():
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
two_step_detected = False
|
||||||
|
|
||||||
if bot_token:
|
if bot_token:
|
||||||
self(ImportBotAuthorizationRequest(
|
self(ImportBotAuthorizationRequest(
|
||||||
flags=0, bot_auth_token=bot_token,
|
flags=0, bot_auth_token=bot_token,
|
||||||
|
@ -246,18 +241,43 @@ class TelegramClient(TelegramBareClient):
|
||||||
))
|
))
|
||||||
elif phone or self._phone:
|
elif phone or self._phone:
|
||||||
phone = phone or self._phone
|
phone = phone or self._phone
|
||||||
self.send_code_request(phone)
|
|
||||||
provided_code = str(code_callback())
|
self.send_code_request(phone, force_sms)
|
||||||
|
|
||||||
|
attempts = 0
|
||||||
|
while attempts < 3:
|
||||||
try:
|
try:
|
||||||
# Normal login
|
# Normal login
|
||||||
self.sign_in(phone, provided_code)
|
provided_code = str(code_callback())
|
||||||
|
|
||||||
|
# raises SessionPasswordNeededError if 2FA enabled
|
||||||
|
signed_in = bool(self.sign_in(phone, provided_code))
|
||||||
|
if signed_in:
|
||||||
|
print("Signed in successfully as {}".format(self.get_me()))
|
||||||
|
break
|
||||||
|
|
||||||
except SessionPasswordNeededError:
|
except SessionPasswordNeededError:
|
||||||
# 2FA
|
two_step_detected = True
|
||||||
provided_password = str(password_callback())
|
break
|
||||||
|
except (PhoneCodeEmptyError, PhoneCodeExpiredError,
|
||||||
|
PhoneCodeHashEmptyError, PhoneCodeInvalidError) as e:
|
||||||
|
print("Invalid code. Please try again...", file=sys.stderr)
|
||||||
|
attempts += 1
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Three consecutive sign-in attempts failed. Aborting...")
|
||||||
|
|
||||||
|
if two_step_detected:
|
||||||
|
if not password:
|
||||||
|
raise ValueError("Two-step verification is enabled for this account. "
|
||||||
|
"Plase provide the 'password' argument to 'start()'.")
|
||||||
salt = self(GetPasswordRequest()).current_salt
|
salt = self(GetPasswordRequest()).current_salt
|
||||||
|
try:
|
||||||
self(CheckPasswordRequest(
|
self(CheckPasswordRequest(
|
||||||
helpers.get_password_hash(provided_password, salt)
|
helpers.get_password_hash(str(password), salt)
|
||||||
))
|
))
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError("Invalid password for two-step verification.\n"
|
||||||
|
"Nested Exception is: {}".format(e))
|
||||||
|
|
||||||
self._set_connected_and_authorized()
|
self._set_connected_and_authorized()
|
||||||
return self # We return self to allow chaining .start() with the initializer
|
return self # We return self to allow chaining .start() with the initializer
|
||||||
|
@ -315,8 +335,8 @@ class TelegramClient(TelegramBareClient):
|
||||||
result = self(SignInRequest(phone, phone_code_hash, code))
|
result = self(SignInRequest(phone, phone_code_hash, code))
|
||||||
|
|
||||||
except (PhoneCodeEmptyError, PhoneCodeExpiredError,
|
except (PhoneCodeEmptyError, PhoneCodeExpiredError,
|
||||||
PhoneCodeHashEmptyError, PhoneCodeInvalidError):
|
PhoneCodeHashEmptyError, PhoneCodeInvalidError) as e:
|
||||||
return None
|
raise e # Hand responsibility to the user
|
||||||
elif password:
|
elif password:
|
||||||
salt = self(GetPasswordRequest()).current_salt
|
salt = self(GetPasswordRequest()).current_salt
|
||||||
result = self(CheckPasswordRequest(
|
result = self(CheckPasswordRequest(
|
||||||
|
@ -388,7 +408,7 @@ class TelegramClient(TelegramBareClient):
|
||||||
or None if the request fails (hence, not authenticated).
|
or None if the request fails (hence, not authenticated).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Your own user.
|
:obj:`User`: Your own user.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return self(GetUsersRequest([InputUserSelf()]))[0]
|
return self(GetUsersRequest([InputUserSelf()]))[0]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user