@@ -130,6 +130,9 @@ class Client(Methods):
130130 Pass a session string to load the session in-memory.
131131 Implies ``in_memory=True``.
132132
133+ use_qrcode (``bool``, *optional*):
134+ Pass True to login using a QR code.
135+
133136 in_memory (``bool``, *optional*):
134137 Pass True to start an in-memory session that will be discarded as soon as the client stops.
135138 In order to reconnect again using an in-memory session without having to login again, you can use
@@ -254,6 +257,7 @@ def __init__(
254257 test_mode : Optional [bool ] = False ,
255258 bot_token : Optional [str ] = None ,
256259 session_string : Optional [str ] = None ,
260+ use_qrcode : Optional [bool ] = False ,
257261 in_memory : Optional [bool ] = None ,
258262 mongodb : Optional [dict ] = None ,
259263 storage : Optional [Storage ] = None ,
@@ -289,6 +293,7 @@ def __init__(
289293 self .test_mode = test_mode
290294 self .bot_token = bot_token
291295 self .session_string = session_string
296+ self .use_qrcode = use_qrcode
292297 self .in_memory = in_memory
293298 self .mongodb = mongodb
294299 self .phone_number = phone_number
@@ -397,59 +402,76 @@ async def updates_watchdog(self):
397402 if datetime .now () - self .last_update_time > timedelta (seconds = self .UPDATES_WATCHDOG_INTERVAL ):
398403 await self .invoke (raw .functions .updates .GetState ())
399404
405+ async def _wait_for_update_login_token (self ):
406+ """
407+ Wait for an UpdateLoginToken update from Telegram.
408+ """
409+ while True :
410+ update , _ , _ = await self .dispatcher .updates_queue .get ()
411+ if isinstance (update , raw .types .UpdateLoginToken ):
412+ break
413+
400414 async def authorize (self ) -> User :
401415 if self .bot_token :
402416 return await self .sign_in_bot (self .bot_token )
403417
404418 print (f"Welcome to Pyrogram (version { __version__ } )" )
405419 print (f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n "
406420 f"under the terms of the { __license__ } .\n " )
421+ if not self .use_qrcode :
422+ while True :
423+ try :
424+ if not self .phone_number :
425+ while True :
426+ print ("Enter 'qrcode' if you want to login with qrcode." )
427+ value = await ainput ("Enter phone number or bot token: " )
407428
408- while True :
409- try :
410- if not self .phone_number :
411- while True :
412- value = await ainput ("Enter phone number or bot token: " )
429+ if not value :
430+ continue
413431
414- if not value :
415- continue
432+ if value .lower () == "qrcode" :
433+ self .use_qrcode = True
434+ break
416435
417- confirm = (await ainput (f'Is "{ value } " correct? (y/N): ' )).lower ()
436+ confirm = (await ainput (f'Is "{ value } " correct? (y/N): ' )).lower ()
418437
419- if confirm == "y" :
420- break
438+ if confirm == "y" :
439+ break
421440
422- if ":" in value :
423- self .bot_token = value
424- return await self .sign_in_bot (value )
425- else :
426- self .phone_number = value
441+ if ":" in value :
442+ self .bot_token = value
443+ return await self .sign_in_bot (value )
444+ else :
445+ self .phone_number = value
427446
428- sent_code = await self .send_code (self .phone_number )
429- except BadRequest as e :
430- print (e .MESSAGE )
431- self .phone_number = None
432- self .bot_token = None
433- else :
434- break
447+ sent_code = await self .send_code (self .phone_number )
448+ except BadRequest as e :
449+ print (e .MESSAGE )
450+ self .phone_number = None
451+ self .bot_token = None
452+ else :
453+ break
435454
436- sent_code_descriptions = {
437- enums .SentCodeType .APP : "Telegram app" ,
438- enums .SentCodeType .SMS : "SMS" ,
439- enums .SentCodeType .CALL : "phone call" ,
440- enums .SentCodeType .FLASH_CALL : "phone flash call" ,
441- enums .SentCodeType .FRAGMENT_SMS : "Fragment SMS" ,
442- enums .SentCodeType .EMAIL_CODE : "email code"
443- }
455+ sent_code_descriptions = {
456+ enums .SentCodeType .APP : "Telegram app" ,
457+ enums .SentCodeType .SMS : "SMS" ,
458+ enums .SentCodeType .CALL : "phone call" ,
459+ enums .SentCodeType .FLASH_CALL : "phone flash call" ,
460+ enums .SentCodeType .FRAGMENT_SMS : "Fragment SMS" ,
461+ enums .SentCodeType .EMAIL_CODE : "email code"
462+ }
444463
445- print (f"The confirmation code has been sent via { sent_code_descriptions [sent_code .type ]} " )
464+ print (f"The confirmation code has been sent via { sent_code_descriptions [sent_code .type ]} " )
446465
447466 while True :
448- if not self .phone_code :
467+ if not self .use_qrcode and not self . phone_code :
449468 self .phone_code = await ainput ("Enter confirmation code: " )
450469
451470 try :
452- signed_in = await self .sign_in (self .phone_number , sent_code .phone_code_hash , self .phone_code )
471+ if self .use_qrcode :
472+ signed_in = await self .sign_in_qrcode ()
473+ else :
474+ signed_in = await self .sign_in (self .phone_number , sent_code .phone_code_hash , self .phone_code )
453475 except BadRequest as e :
454476 print (e .MESSAGE )
455477 self .phone_code = None
@@ -488,7 +510,15 @@ async def authorize(self) -> User:
488510 print (e .MESSAGE )
489511 self .password = None
490512 else :
491- break
513+ if self .use_qrcode and isinstance (signed_in , raw .types .auth .LoginToken ):
514+ time_out = signed_in .expires - datetime .timestamp (datetime .now ())
515+ try :
516+ await asyncio .wait_for (self ._wait_for_update_login_token (), timeout = time_out )
517+ except asyncio .TimeoutError :
518+ print ("QR code expired, Requesting new Qr code..." )
519+ continue
520+ else :
521+ break
492522
493523 if isinstance (signed_in , User ):
494524 return signed_in
0 commit comments