2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-08-27 04:18:04 +00:00

Small code cleanup

This commit is contained in:
Dan 2019-09-08 08:42:12 +02:00
parent c0298542a5
commit c7782b146f

View File

@ -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[