2
0
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:
Dan
2018-01-24 21:55:29 +01:00
3 changed files with 105 additions and 34 deletions

View File

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

View File

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

View File

@@ -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+)")