From c7782b146f8739af6719ba390ce060a7ade917cb Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sun, 8 Sep 2019 08:42:12 +0200 Subject: [PATCH] Small code cleanup --- pyrogram/client/client.py | 410 ++++++-------------------------------- 1 file changed, 58 insertions(+), 352 deletions(-) diff --git a/pyrogram/client/client.py b/pyrogram/client/client.py index dd587dd6..eae20e50 100644 --- a/pyrogram/client/client.py +++ b/pyrogram/client/client.py @@ -39,12 +39,8 @@ from pyrogram.client.handlers.handler import Handler from pyrogram.client.methods.password.utils import compute_check from pyrogram.crypto import AES from pyrogram.errors import ( - PhoneMigrate, NetworkMigrate, PhoneNumberInvalid, - PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty, - PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded, - PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned, - VolumeLocNotFound, UserMigrate, ChannelPrivate, PhoneNumberOccupied, - PasswordRecoveryNa, PasswordEmpty, AuthBytesInvalid, + PhoneMigrate, NetworkMigrate, SessionPasswordNeeded, + FloodWait, PeerIdInvalid, VolumeLocNotFound, UserMigrate, ChannelPrivate, AuthBytesInvalid, BadRequest) from pyrogram.session import Auth, Session from .ext import utils, Syncer, BaseClient, Dispatcher @@ -68,24 +64,24 @@ class Client(Methods, BaseClient): :meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can pass here as argument. - api_id (``int``, *optional*): - The *api_id* part of your Telegram API Key, as integer. E.g.: 12345 + api_id (``int`` | ``str``, *optional*): + The *api_id* part of your Telegram API Key, as integer. E.g.: "12345". This is an alternative way to pass it if you don't want to use the *config.ini* file. api_hash (``str``, *optional*): The *api_hash* part of your Telegram API Key, as string. E.g.: "0123456789abcdef0123456789abcdef". - This is an alternative way to pass it if you don't want to use the *config.ini* file. + This is an alternative way to set it if you don't want to use the *config.ini* file. app_version (``str``, *optional*): - Application version. Defaults to "Pyrogram X.Y.Z" + Application version. Defaults to "Pyrogram |version|". This is an alternative way to set it if you don't want to use the *config.ini* file. device_model (``str``, *optional*): - Device model. Defaults to *platform.python_implementation() + " " + platform.python_version()* + Device model. Defaults to *platform.python_implementation() + " " + platform.python_version()*. This is an alternative way to set it if you don't want to use the *config.ini* file. system_version (``str``, *optional*): - Operating System version. Defaults to *platform.system() + " " + platform.release()* + Operating System version. Defaults to *platform.system() + " " + platform.release()*. This is an alternative way to set it if you don't want to use the *config.ini* file. lang_code (``str``, *optional*): @@ -99,69 +95,52 @@ class Client(Methods, BaseClient): proxy (``dict``, *optional*): Your SOCKS5 Proxy settings as dict, e.g.: *dict(hostname="11.22.33.44", port=1080, username="user", password="pass")*. - *username* and *password* can be omitted if your proxy doesn't require authorization. + The *username* and *password* can be omitted if your proxy doesn't require authorization. This is an alternative way to setup a proxy if you don't want to use the *config.ini* file. test_mode (``bool``, *optional*): - Enable or disable login to the test servers. Defaults to False. - Only applicable for new sessions and will be ignored in case previously - created sessions are loaded. + Enable or disable login to the test servers. + Only applicable for new sessions and will be ignored in case previously created sessions are loaded. + Defaults to False. bot_token (``str``, *optional*): Pass your Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11" Only applicable for new sessions. This is an alternative way to set it if you don't want to use the *config.ini* file. - phone_number (``str`` | ``callable``, *optional*): + phone_number (``str``, *optional*): Pass your phone number as string (with your Country Code prefix included) to avoid entering it manually. - Or pass a callback function which accepts no arguments and must return the correct phone number as string - (e.g., "391234567890"). Only applicable for new sessions. - phone_code (``str`` | ``callable``, *optional*): - Pass the phone code as string (for test numbers only) to avoid entering it manually. Or pass a callback - function which accepts a single positional argument *(phone_number)* and must return the correct phone code - as string (e.g., "12345"). + phone_code (``str``, *optional*): + Pass the phone code as string (for test numbers only) to avoid entering it manually. Only applicable for new sessions. password (``str``, *optional*): Pass your Two-Step Verification password as string (if you have one) to avoid entering it manually. - Or pass a callback function which accepts a single positional argument *(password_hint)* and must return - the correct password as string (e.g., "password"). Only applicable for new sessions. - recovery_code (``callable``, *optional*): - Pass a callback function which accepts a single positional argument *(email_pattern)* and must return the - correct password recovery code as string (e.g., "987654"). - Only applicable for new sessions. - - force_sms (``str``, *optional*): + force_sms (``bool``, *optional*): Pass True to force Telegram sending the authorization code via SMS. Only applicable for new sessions. - - first_name (``str``, *optional*): - Pass a First Name as string to avoid entering it manually. Or pass a callback function which accepts no - arguments and must return the correct name as string (e.g., "Dan"). It will be used to automatically create - a new Telegram account in case the phone number you passed is not registered yet. - Only applicable for new sessions. - - last_name (``str``, *optional*): - Same purpose as *first_name*; pass a Last Name to avoid entering it manually. It can - be an empty string: "". Only applicable for new sessions. + Defaults to False. workers (``int``, *optional*): - Thread pool size for handling incoming updates. Defaults to 4. + Thread pool size for handling incoming updates. + Defaults to 4. workdir (``str``, *optional*): - Define a custom working directory. The working directory is the location in your filesystem - where Pyrogram will store your session files. Defaults to the parent directory of the main script. + Define a custom working directory. The working directory is the location in your filesystem where Pyrogram + will store your session files. + Defaults to the parent directory of the main script. config_file (``str``, *optional*): - Path of the configuration file. Defaults to ./config.ini + Path of the configuration file. + Defaults to ./config.ini plugins (``dict``, *optional*): Your Smart Plugins settings as dict, e.g.: *dict(root="plugins")*. - This is an alternative way to setup plugins if you don't want to use the *config.ini* file. + This is an alternative way setup plugins if you don't want to use the *config.ini* file. no_updates (``bool``, *optional*): Pass True to completely disable incoming updates for the current session. @@ -175,17 +154,6 @@ class Client(Methods, BaseClient): download_media, ...) are less prone to throw FloodWait exceptions. Only available for users, bots will ignore this parameter. Defaults to False (normal session). - - Example: - .. code-block:: python - - from pyrogram import Client - - app = Client("my_account") - - with app: - app.send_message("me", "Hi!") - """ def __init__( @@ -202,12 +170,9 @@ class Client(Methods, BaseClient): test_mode: bool = False, bot_token: str = None, phone_number: str = None, - phone_code: Union[str, callable] = None, + phone_code: str = None, password: str = None, - recovery_code: callable = None, force_sms: bool = False, - first_name: str = None, - last_name: str = None, workers: int = BaseClient.WORKERS, workdir: str = BaseClient.WORKDIR, config_file: str = BaseClient.CONFIG_FILE, @@ -232,10 +197,7 @@ class Client(Methods, BaseClient): self.phone_number = phone_number self.phone_code = phone_code self.password = password - self.recovery_code = recovery_code self.force_sms = force_sms - self.first_name = first_name - self.last_name = last_name self.workers = workers self.workdir = Path(workdir) self.config_file = Path(config_file) @@ -682,36 +644,37 @@ class Client(Methods, BaseClient): return True def authorize(self) -> User: - if self.bot_token is not None: + if self.bot_token: return self.sign_in_bot(self.bot_token) while True: - if self.phone_number is None: - while True: - value = input("Enter phone number or bot token: ") - confirm = input("Is \"{}\" correct? (y/n): ".format(value)) - - if confirm in ("y", "1"): - break - elif confirm in ("n", "2"): - continue - - if ":" in value: - self.bot_token = value - return self.sign_in_bot(value) - else: - self.phone_number = value - try: + if not self.phone_number: + while True: + value = input("Enter phone number or bot token: ") + + if not value: + continue + + confirm = input("Is \"{}\" correct? (y/N): ".format(value)).lower() + + if confirm == "y": + break + + if ":" in value: + self.bot_token = value + return self.sign_in_bot(value) + else: + self.phone_number = value + sent_code = self.send_code(self.phone_number) except BadRequest as e: print(e.MESSAGE) self.phone_number = None + self.bot_token = None except FloodWait as e: print(e.MESSAGE.format(x=e.x)) time.sleep(e.x) - except Exception as e: - log.error(e, exc_info=True) else: break @@ -728,7 +691,7 @@ class Client(Methods, BaseClient): )) while True: - if self.phone_code is None: + if not self.phone_code: self.phone_code = input("Enter confirmation code: ") try: @@ -742,14 +705,14 @@ class Client(Methods, BaseClient): while True: print("Password hint: {}".format(self.get_password_hint())) - if self.password is None: + if not self.password: self.password = input("Enter password (empty to recover): ") try: - if self.password == "": + if not self.password: confirm = input("Confirm password recovery (y/n): ") - if confirm in ("y", "1"): + if confirm == "y": email_pattern = self.send_recovery_code() print("The recovery code has been sent to {}".format(email_pattern)) @@ -766,8 +729,7 @@ class Client(Methods, BaseClient): except Exception as e: log.error(e, exc_info=True) raise - - elif confirm in ("n", "2"): + else: self.password = None else: return self.check_password(self.password) @@ -777,14 +739,9 @@ class Client(Methods, BaseClient): except FloodWait as e: print(e.MESSAGE.format(x=e.x)) time.sleep(e.x) - except Exception as e: - log.error(e, exc_info=True) - raise except FloodWait as e: print(e.MESSAGE.format(x=e.x)) time.sleep(e.x) - except Exception as e: - log.error(e, exc_info=True) else: break @@ -792,20 +749,18 @@ class Client(Methods, BaseClient): return signed_in while True: - self.first_name = input("Enter first name: ") - self.last_name = input("Enter last name (empty to skip): ") + first_name = input("Enter first name: ") + last_name = input("Enter last name (empty to skip): ") try: signed_up = self.sign_up( self.phone_number, sent_code.phone_code_hash, - self.first_name, - self.last_name + first_name, + last_name ) except BadRequest as e: print(e.MESSAGE) - self.first_name = None - self.last_name = None except FloodWait as e: print(e.MESSAGE.format(x=e.x)) time.sleep(e.x) @@ -854,9 +809,9 @@ class Client(Methods, BaseClient): log.warning("Takeout session {} initiated".format(self.takeout_id)) self.send(functions.updates.GetState()) - except Exception as e: + except (Exception, KeyboardInterrupt): self.disconnect() - raise e + raise else: self.initialize() return self @@ -969,7 +924,7 @@ class Client(Methods, BaseClient): app3.stop() """ - def signal_handler(*args): + def signal_handler(_, __): Client.is_idling = False for s in stop_signals: @@ -1183,255 +1138,6 @@ class Client(Methods, BaseClient): self.parse_mode = parse_mode - def authorize_bot(self): - try: - r = self.send( - functions.auth.ImportBotAuthorization( - flags=0, - api_id=self.api_id, - api_hash=self.api_hash, - bot_auth_token=self.bot_token - ) - ) - except UserMigrate as e: - self.session.stop() - - self.storage.dc_id = e.x - self.storage.auth_key = Auth(self, self.storage.dc_id).create() - self.session = Session(self, self.storage.dc_id, self.storage.auth_key) - - self.session.start() - - self.authorize_bot() - else: - self.storage.user_id = r.user.id - - print("Logged in successfully as @{}".format(r.user.username)) - - def authorize_user(self): - phone_number_invalid_raises = self.phone_number is not None - phone_code_invalid_raises = self.phone_code is not None - password_invalid_raises = self.password is not None - first_name_invalid_raises = self.first_name is not None - - def default_phone_number_callback(): - while True: - phone_number = input("Enter phone number: ") - confirm = input("Is \"{}\" correct? (y/n): ".format(phone_number)) - - if confirm in ("y", "1"): - return phone_number - elif confirm in ("n", "2"): - continue - - while True: - self.phone_number = ( - default_phone_number_callback() if self.phone_number is None - else str(self.phone_number()) if callable(self.phone_number) - else str(self.phone_number) - ) - - self.phone_number = self.phone_number.strip("+") - - try: - r = self.send( - functions.auth.SendCode( - phone_number=self.phone_number, - api_id=self.api_id, - api_hash=self.api_hash, - settings=types.CodeSettings() - ) - ) - except (PhoneMigrate, NetworkMigrate) as e: - self.session.stop() - - self.storage.dc_id = e.x - self.storage.auth_key = Auth(self, self.storage.dc_id).create() - - self.session = Session(self, self.storage.dc_id, self.storage.auth_key) - - self.session.start() - except (PhoneNumberInvalid, PhoneNumberBanned) as e: - if phone_number_invalid_raises: - raise - else: - print(e.MESSAGE) - self.phone_number = None - except FloodWait as e: - if phone_number_invalid_raises: - raise - else: - print(e.MESSAGE.format(x=e.x)) - time.sleep(e.x) - except Exception as e: - log.error(e, exc_info=True) - raise - else: - break - - phone_registered = r.phone_registered - phone_code_hash = r.phone_code_hash - terms_of_service = r.terms_of_service - - if terms_of_service and not Client.terms_of_service_displayed: - print("\n" + terms_of_service.text + "\n") - Client.terms_of_service_displayed = True - - if self.force_sms: - self.send( - functions.auth.ResendCode( - phone_number=self.phone_number, - phone_code_hash=phone_code_hash - ) - ) - - while True: - if not phone_registered: - self.first_name = ( - input("First name: ") if self.first_name is None - else str(self.first_name()) if callable(self.first_name) - else str(self.first_name) - ) - - self.last_name = ( - input("Last name: ") if self.last_name is None - else str(self.last_name()) if callable(self.last_name) - else str(self.last_name) - ) - - self.phone_code = ( - input("Enter phone code: ") if self.phone_code is None - else str(self.phone_code(self.phone_number)) if callable(self.phone_code) - else str(self.phone_code) - ) - - try: - if phone_registered: - try: - r = self.send( - functions.auth.SignIn( - phone_number=self.phone_number, - phone_code_hash=phone_code_hash, - phone_code=self.phone_code - ) - ) - except PhoneNumberUnoccupied: - log.warning("Phone number unregistered") - phone_registered = False - continue - else: - try: - r = self.send( - functions.auth.SignUp( - phone_number=self.phone_number, - phone_code_hash=phone_code_hash, - phone_code=self.phone_code, - first_name=self.first_name, - last_name=self.last_name - ) - ) - except PhoneNumberOccupied: - log.warning("Phone number already registered") - phone_registered = True - continue - except (PhoneCodeInvalid, PhoneCodeEmpty, PhoneCodeExpired, PhoneCodeHashEmpty) as e: - if phone_code_invalid_raises: - raise - else: - print(e.MESSAGE) - self.phone_code = None - except FirstnameInvalid as e: - if first_name_invalid_raises: - raise - else: - print(e.MESSAGE) - self.first_name = None - except SessionPasswordNeeded as e: - print(e.MESSAGE) - - def default_password_callback(password_hint: str) -> str: - print("Hint: {}".format(password_hint)) - return input("Enter password (empty to recover): ") - - def default_recovery_callback(email_pattern: str) -> str: - print("An e-mail containing the recovery code has been sent to {}".format(email_pattern)) - return input("Enter password recovery code: ") - - while True: - try: - r = self.send(functions.account.GetPassword()) - - self.password = ( - default_password_callback(r.hint) if self.password is None - else str(self.password(r.hint) or "") if callable(self.password) - else str(self.password) - ) - - if self.password == "": - r = self.send(functions.auth.RequestPasswordRecovery()) - - self.recovery_code = ( - default_recovery_callback(r.email_pattern) if self.recovery_code is None - else str(self.recovery_code(r.email_pattern)) if callable(self.recovery_code) - else str(self.recovery_code) - ) - - r = self.send( - functions.auth.RecoverPassword( - code=self.recovery_code - ) - ) - else: - r = self.send( - functions.auth.CheckPassword( - password=compute_check(r, self.password) - ) - ) - except (PasswordEmpty, PasswordRecoveryNa, PasswordHashInvalid) as e: - if password_invalid_raises: - raise - else: - print(e.MESSAGE) - self.password = None - self.recovery_code = None - except FloodWait as e: - if password_invalid_raises: - raise - else: - print(e.MESSAGE.format(x=e.x)) - time.sleep(e.x) - self.password = None - self.recovery_code = None - except Exception as e: - log.error(e, exc_info=True) - raise - else: - break - break - except FloodWait as e: - if phone_code_invalid_raises or first_name_invalid_raises: - raise - else: - print(e.MESSAGE.format(x=e.x)) - time.sleep(e.x) - except Exception as e: - log.error(e, exc_info=True) - raise - else: - break - - if terms_of_service: - assert self.send( - functions.help.AcceptTermsOfService( - id=terms_of_service.id - ) - ) - - self.password = None - self.storage.user_id = r.user.id - - print("Logged in successfully as {}".format(r.user.first_name)) - def fetch_peers( self, peers: List[