mirror of
https://github.com/pyrogram/pyrogram
synced 2025-09-01 06:45:39 +00:00
Merge branch 'master' into docs
This commit is contained in:
@@ -60,7 +60,7 @@ Pyrogram executing API calls with your identity.
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The authorization process is executed only once.
|
The authorization process is executed only once.
|
||||||
However, the code above is always required; as soon as a valid session file exists,
|
However, the code above is always required; as long as a valid session file exists,
|
||||||
Pyrogram will use that and won't ask you to enter your phone number again when you restart your script.
|
Pyrogram will use that and won't ask you to enter your phone number again when you restart your script.
|
||||||
|
|
||||||
.. _`Country Code`: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
.. _`Country Code`: https://en.wikipedia.org/wiki/List_of_country_calling_codes
|
@@ -37,7 +37,7 @@ from pyrogram.api.errors import (
|
|||||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||||
PasswordHashInvalid, FloodWait, PeerIdInvalid, FilePartMissing,
|
PasswordHashInvalid, FloodWait, PeerIdInvalid, FilePartMissing,
|
||||||
ChatAdminRequired
|
ChatAdminRequired, FirstnameInvalid
|
||||||
)
|
)
|
||||||
from pyrogram.api.types import (
|
from pyrogram.api.types import (
|
||||||
User, Chat, Channel,
|
User, Chat, Channel,
|
||||||
@@ -64,21 +64,57 @@ class Client:
|
|||||||
Args:
|
Args:
|
||||||
session_name (:obj:`str`):
|
session_name (:obj:`str`):
|
||||||
Name to uniquely identify an authorized session. It will be used
|
Name to uniquely identify an authorized session. It will be used
|
||||||
to save the session to a file named ``<session_name>.session``.
|
to save the session to a file named *<session_name>.session* and to load
|
||||||
|
it when you restart your script. As long as a valid session file exists,
|
||||||
|
Pyrogram won't ask you again to input your phone number.
|
||||||
|
|
||||||
test_mode (:obj:`bool`, optional):
|
test_mode (:obj:`bool`, optional):
|
||||||
Enable or disable log-in to testing servers. Defaults to False.
|
Enable or disable log-in to testing servers. Defaults to False.
|
||||||
Only applicable for new sessions and will be ignored in case previously
|
Only applicable for new sessions and will be ignored in case previously
|
||||||
created sessions are loaded.
|
created sessions are loaded.
|
||||||
|
|
||||||
|
phone_number (:obj:`str`, optional):
|
||||||
|
Pass your phone number (with your Country Code prefix included) to avoid
|
||||||
|
entering it manually. Only applicable for new sessions.
|
||||||
|
|
||||||
|
phone_code (:obj:`str` | :obj:`callable`, optional):
|
||||||
|
Pass the phone code as string (for test numbers only), or pass a callback function
|
||||||
|
which must return the correct phone code as string (e.g., "12345").
|
||||||
|
Only applicable for new sessions.
|
||||||
|
|
||||||
|
password (:obj:`str`, optional):
|
||||||
|
Pass your Two-Step Verification password (if you have one) to avoid entering it
|
||||||
|
manually. Only applicable for new sessions.
|
||||||
|
|
||||||
|
first_name (:obj:`str`, optional):
|
||||||
|
Pass a First Name to avoid entering it manually. It will be used to automatically
|
||||||
|
create a new Telegram account in case the phone number you passed is not registered yet.
|
||||||
|
|
||||||
|
last_name (:obj:`str`, optional):
|
||||||
|
Same purpose as *first_name*; pass a Last Name to avoid entering it manually. It can
|
||||||
|
be an empty string: ""
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INVITE_LINK_RE = re.compile(r"^(?:https?://)?t\.me/joinchat/(.+)$")
|
INVITE_LINK_RE = re.compile(r"^(?:https?://)?t\.me/joinchat/(.+)$")
|
||||||
DIALOGS_AT_ONCE = 100
|
DIALOGS_AT_ONCE = 100
|
||||||
|
|
||||||
def __init__(self, session_name: str, test_mode: bool = False):
|
def __init__(self,
|
||||||
|
session_name: str,
|
||||||
|
test_mode: bool = False,
|
||||||
|
phone_number: str = None,
|
||||||
|
phone_code: str or callable = None,
|
||||||
|
password: str = None,
|
||||||
|
first_name: str = None,
|
||||||
|
last_name: str = None):
|
||||||
self.session_name = session_name
|
self.session_name = session_name
|
||||||
self.test_mode = test_mode
|
self.test_mode = test_mode
|
||||||
|
|
||||||
|
self.phone_number = phone_number
|
||||||
|
self.password = password
|
||||||
|
self.phone_code = phone_code
|
||||||
|
self.first_name = first_name
|
||||||
|
self.last_name = last_name
|
||||||
|
|
||||||
self.dc_id = None
|
self.dc_id = None
|
||||||
self.auth_key = None
|
self.auth_key = None
|
||||||
self.user_id = None
|
self.user_id = None
|
||||||
@@ -100,7 +136,11 @@ class Client:
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""Use this method to start the Client after creating it.
|
"""Use this method to start the Client after creating it.
|
||||||
Requires no parameters."""
|
Requires no parameters.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`pyrogram.Error`
|
||||||
|
"""
|
||||||
self.load_config()
|
self.load_config()
|
||||||
self.load_session(self.session_name)
|
self.load_session(self.session_name)
|
||||||
|
|
||||||
@@ -112,6 +152,7 @@ class Client:
|
|||||||
print("\n".join(terms.splitlines()), "\n")
|
print("\n".join(terms.splitlines()), "\n")
|
||||||
|
|
||||||
self.user_id = self.authorize()
|
self.user_id = self.authorize()
|
||||||
|
self.password = None
|
||||||
self.save_session()
|
self.save_session()
|
||||||
|
|
||||||
self.rnd_id = self.session.msg_id
|
self.rnd_id = self.session.msg_id
|
||||||
@@ -171,21 +212,27 @@ class Client:
|
|||||||
return self.session.send(data)
|
return self.session.send(data)
|
||||||
|
|
||||||
def authorize(self):
|
def authorize(self):
|
||||||
|
phone_number_invalid_raises = self.phone_number is not None
|
||||||
|
phone_code_invalid_raises = self.phone_code is not None
|
||||||
|
password_hash_invalid_raises = self.password is not None
|
||||||
|
first_name_invalid_raises = self.first_name is not None
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
phone_number = input("Enter phone number: ")
|
if self.phone_number is None:
|
||||||
|
self.phone_number = input("Enter phone number: ")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
confirm = input("Is \"{}\" correct? (y/n): ".format(phone_number))
|
confirm = input("Is \"{}\" correct? (y/n): ".format(self.phone_number))
|
||||||
|
|
||||||
if confirm in ("y", "1"):
|
if confirm in ("y", "1"):
|
||||||
break
|
break
|
||||||
elif confirm in ("n", "2"):
|
elif confirm in ("n", "2"):
|
||||||
phone_number = input("Enter phone number: ")
|
self.phone_number = input("Enter phone number: ")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SendCode(
|
functions.auth.SendCode(
|
||||||
phone_number,
|
self.phone_number,
|
||||||
self.config.api_id,
|
self.config.api_id,
|
||||||
self.config.api_hash
|
self.config.api_hash
|
||||||
)
|
)
|
||||||
@@ -201,14 +248,18 @@ class Client:
|
|||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SendCode(
|
functions.auth.SendCode(
|
||||||
phone_number,
|
self.phone_number,
|
||||||
self.config.api_id,
|
self.config.api_id,
|
||||||
self.config.api_hash
|
self.config.api_hash
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
except PhoneNumberInvalid as e:
|
except PhoneNumberInvalid as e:
|
||||||
print(e.MESSAGE)
|
if phone_number_invalid_raises:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
print(e.MESSAGE)
|
||||||
|
self.phone_number = None
|
||||||
except FloodWait as e:
|
except FloodWait as e:
|
||||||
print(e.MESSAGE.format(x=e.x))
|
print(e.MESSAGE.format(x=e.x))
|
||||||
time.sleep(e.x)
|
time.sleep(e.x)
|
||||||
@@ -221,59 +272,80 @@ class Client:
|
|||||||
phone_code_hash = r.phone_code_hash
|
phone_code_hash = r.phone_code_hash
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
phone_code = input("Enter phone code: ")
|
self.phone_code = (
|
||||||
|
input("Enter phone code: ") if self.phone_code is None
|
||||||
|
else self.phone_code if type(self.phone_code) is str
|
||||||
|
else self.phone_code()
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if phone_registered:
|
if phone_registered:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SignIn(
|
functions.auth.SignIn(
|
||||||
phone_number,
|
self.phone_number,
|
||||||
phone_code_hash,
|
phone_code_hash,
|
||||||
phone_code
|
self.phone_code
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
self.send(
|
self.send(
|
||||||
functions.auth.SignIn(
|
functions.auth.SignIn(
|
||||||
phone_number,
|
self.phone_number,
|
||||||
phone_code_hash,
|
phone_code_hash,
|
||||||
phone_code
|
self.phone_code
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except PhoneNumberUnoccupied:
|
except PhoneNumberUnoccupied:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
first_name = input("First name: ")
|
self.first_name = self.first_name if self.first_name is not None else input("First name: ")
|
||||||
last_name = input("Last name: ")
|
self.last_name = self.last_name if self.last_name is not None else input("Last name: ")
|
||||||
|
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SignUp(
|
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 (PhoneCodeInvalid, PhoneCodeEmpty, PhoneCodeExpired, PhoneCodeHashEmpty) as e:
|
except (PhoneCodeInvalid, PhoneCodeEmpty, PhoneCodeExpired, PhoneCodeHashEmpty) as e:
|
||||||
print(e.MESSAGE)
|
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:
|
except SessionPasswordNeeded as e:
|
||||||
print(e.MESSAGE)
|
print(e.MESSAGE)
|
||||||
|
r = self.send(functions.account.GetPassword())
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
r = self.send(functions.account.GetPassword())
|
|
||||||
|
|
||||||
print("Hint: {}".format(r.hint))
|
if self.password is None:
|
||||||
password = input("Enter password: ") # TODO: Use getpass
|
print("Hint: {}".format(r.hint))
|
||||||
|
self.password = input("Enter password: ") # TODO: Use getpass
|
||||||
|
|
||||||
password = r.current_salt + password.encode() + r.current_salt
|
if type(self.password) is str:
|
||||||
password_hash = sha256(password).digest()
|
self.password = r.current_salt + self.password.encode() + r.current_salt
|
||||||
|
|
||||||
|
password_hash = sha256(self.password).digest()
|
||||||
|
|
||||||
r = self.send(functions.auth.CheckPassword(password_hash))
|
r = self.send(functions.auth.CheckPassword(password_hash))
|
||||||
except PasswordHashInvalid as e:
|
except PasswordHashInvalid as e:
|
||||||
print(e.MESSAGE)
|
if password_hash_invalid_raises:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
print(e.MESSAGE)
|
||||||
|
self.password = None
|
||||||
except FloodWait as e:
|
except FloodWait as e:
|
||||||
print(e.MESSAGE.format(x=e.x))
|
print(e.MESSAGE.format(x=e.x))
|
||||||
time.sleep(e.x)
|
time.sleep(e.x)
|
||||||
|
@@ -31,7 +31,6 @@ from . import utils
|
|||||||
|
|
||||||
|
|
||||||
class HTML:
|
class HTML:
|
||||||
SMP_RE = re.compile(r"[\U00010000-\U0010FFFF]")
|
|
||||||
HTML_RE = re.compile(r"<(\w+)(?: href=\"(.*)\")?>(.*)</\1>")
|
HTML_RE = re.compile(r"<(\w+)(?: href=\"(.*)\")?>(.*)</\1>")
|
||||||
MENTION_RE = re.compile(r"tg://user\?id=(\d+)")
|
MENTION_RE = re.compile(r"tg://user\?id=(\d+)")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user