diff --git a/telethon_examples/quart_login.py b/telethon_examples/quart_login.py
index b4715c66..bd6fcf83 100644
--- a/telethon_examples/quart_login.py
+++ b/telethon_examples/quart_login.py
@@ -1,10 +1,38 @@
import base64
import os
-from quart import Quart, request
+from quart import Quart, render_template_string, request, session
from telethon import TelegramClient, utils
+BASE_TEMPLATE = """
+
+
+
+
+ Telethon + Quart
+
+ {{ content | safe }}
+
+"""
+
+PHONE_FORM = """
+
+"""
+
+CODE_FORM = """
+
+"""
+
+app = Quart(__name__)
+app.secret_key = "CHANGE THIS TO SOMETHING SECRET"
+
def get_env(name, message):
if name in os.environ:
@@ -18,20 +46,6 @@ API_ID = int(get_env('TG_API_ID', 'Enter your API ID: '))
API_HASH = get_env('TG_API_HASH', 'Enter your API hash: ')
-# Helper method to add the HTML head/body
-def html(inner):
- return '''
-
-
-
-
- Telethon + Quart
-
- {}
-
-'''.format(inner)
-
-
# Helper method to format messages nicely
async def format_message(message):
if message.photo:
@@ -50,71 +64,36 @@ async def format_message(message):
)
-# Define the global phone and Quart app variables
-phone = None
-app = Quart(__name__)
-
-
-# Quart handlers
@app.route('/', methods=['GET', 'POST'])
async def root():
- # Connect if we aren't yet
- if not client.is_connected():
- await client.connect()
+ client = TelegramClient(SESSION, API_ID, API_HASH)
+ await client.connect()
- # We want to update the global phone variable to remember it
- global phone
+ if request.method == "POST":
+ form = await request.form
+ if 'phone' in form:
+ session["phone"] = form["phone"]
+ await client.send_code_request(form["phone"])
- # Check form parameters (phone/code)
- form = await request.form
- if 'phone' in form:
- phone = form['phone']
- await client.send_code_request(phone)
+ if 'code' in form:
+ session["code"] = form["code"]
- if 'code' in form:
- await client.sign_in(code=form['code'])
+ if "phone" not in session:
+ return await render_template_string(BASE_TEMPLATE, content=PHONE_FORM)
- # If we're logged in, show them some messages from their first dialog
- if await client.is_user_authorized():
- # They are logged in, show them some messages from their first dialog
- dialog = (await client.get_dialogs())[0]
- result = '{}
'.format(dialog.title)
- async for m in client.iter_messages(dialog, 10):
- result += await(format_message(m))
+ if "code" not in session:
+ return await render_template_string(BASE_TEMPLATE, content=CODE_FORM)
- return html(result)
+ await client.sign_in(code=session["code"])
+ # They are logged in, show them some messages from their first dialog
+ dialog = (await client.get_dialogs())[0]
+ result = '{}
'.format(dialog.title)
+ async for m in client.iter_messages(dialog, 10):
+ result += await(format_message(m))
- # Ask for the phone if we don't know it yet
- if phone is None:
- return html('''
-''')
-
- # We have the phone, but we're not logged in, so ask for the code
- return html('''
-''')
+ await client.disconnect()
+ return await render_template_string(BASE_TEMPLATE, content=result)
-# By default, `Quart.run` uses `asyncio.run()`, which creates a new asyncio
-# event loop. If we create the `TelegramClient` before, `telethon` will
-# use `asyncio.get_event_loop()`, which is the implicit loop in the main
-# thread. These two loops are different, and it won't work.
-#
-# So, we have to manually pass the same `loop` to both applications to
-# make 100% sure it works and to avoid headaches.
-#
-# Quart doesn't seem to offer a way to run inside `async def`
-# (see https://gitlab.com/pgjones/quart/issues/146) so we must
-# run and block on it last.
-#
-# This example creates a global client outside of Quart handlers.
-# If you create the client inside the handlers (common case), you
-# won't have to worry about any of this.
-client = TelegramClient(SESSION, API_ID, API_HASH)
-client.parse_mode = 'html' # <- render things nicely
-app.run(loop=client.loop) # <- same event loop as telethon
+if __name__ == "__main__":
+ app.run()