mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-10 19:46:36 +03:00
Rewrite the first part of the docs for asyncio
This commit is contained in:
parent
5e322a6ca9
commit
f733f8e565
49
README.rst
49
README.rst
|
@ -4,8 +4,11 @@ Telethon
|
||||||
|
|
||||||
⭐️ Thanks **everyone** who has starred the project, it means a lot!
|
⭐️ Thanks **everyone** who has starred the project, it means a lot!
|
||||||
|
|
||||||
**Telethon** is Telegram client implementation in **Python 3** which uses
|
**Telethon** is an `asyncio <https://docs.python.org/3/library/asyncio.html>`_
|
||||||
the latest available API of Telegram.
|
**Python 3** library to interact with Telegram's API.
|
||||||
|
|
||||||
|
If you don't like ``asyncio``, you can still use `a simpler version
|
||||||
|
<https://github.com/LonamiWebs/Telethon/tree/sync>`_ that uses threads instead.
|
||||||
|
|
||||||
|
|
||||||
What is this?
|
What is this?
|
||||||
|
@ -22,7 +25,7 @@ Installing
|
||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
||||||
pip3 install telethon
|
pip3 install telethon-aio
|
||||||
|
|
||||||
|
|
||||||
Creating a client
|
Creating a client
|
||||||
|
@ -30,15 +33,18 @@ Creating a client
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
from telethon import TelegramClient
|
import asyncio
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
# These example values won't work. You must get your own api_id and
|
from telethon import TelegramClient
|
||||||
# api_hash from https://my.telegram.org, under API Development.
|
|
||||||
api_id = 12345
|
|
||||||
api_hash = '0123456789abcdef0123456789abcdef'
|
|
||||||
|
|
||||||
client = TelegramClient('session_name', api_id, api_hash)
|
# These example values won't work. You must get your own api_id and
|
||||||
client.start()
|
# api_hash from https://my.telegram.org, under API Development.
|
||||||
|
api_id = 12345
|
||||||
|
api_hash = '0123456789abcdef0123456789abcdef'
|
||||||
|
|
||||||
|
client = TelegramClient('session_name', api_id, api_hash)
|
||||||
|
loop.run_until_complete(client.start())
|
||||||
|
|
||||||
|
|
||||||
Doing stuff
|
Doing stuff
|
||||||
|
@ -46,20 +52,23 @@ Doing stuff
|
||||||
|
|
||||||
.. code:: python
|
.. code:: python
|
||||||
|
|
||||||
print(client.get_me().stringify())
|
async def main():
|
||||||
|
me = await client.get_me()
|
||||||
|
print(me.stringify())
|
||||||
|
|
||||||
client.send_message('username', 'Hello! Talking to you from Telethon')
|
await client.send_message('username', 'Hello! Talking to you from Telethon')
|
||||||
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
await client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||||
|
|
||||||
client.download_profile_photo('me')
|
await client.download_profile_photo('me')
|
||||||
messages = client.get_messages('username')
|
messages = await client.get_messages('username')
|
||||||
client.download_media(messages[0])
|
await messages[0].download_media()
|
||||||
|
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
|
|
||||||
Next steps
|
Next steps
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Do you like how Telethon looks? Check out
|
Do you like how Telethon looks? Check out `Read The Docs
|
||||||
`Read The Docs <http://telethon.rtfd.io/>`_
|
<http://telethon.rtfd.io/>`_ for a more in-depth explanation,
|
||||||
for a more in-depth explanation, with examples,
|
with examples, troubleshooting issues, and more useful information.
|
||||||
troubleshooting issues, and more useful information.
|
|
||||||
|
|
|
@ -69,7 +69,9 @@ Or we call `client.get_input_entity
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
peer = client.get_input_entity('someone')
|
import asyncio
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
peer = loop.run_until_complete(client.get_input_entity('someone'))
|
||||||
|
|
||||||
When you're going to invoke an API method, most require you to pass an
|
When you're going to invoke an API method, most require you to pass an
|
||||||
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
|
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
|
||||||
|
@ -81,7 +83,7 @@ instead:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
entity = client.get_entity('someone')
|
entity = loop.run_until_complete(client.get_entity('someone'))
|
||||||
|
|
||||||
In the later case, when you use the entity, the library will cast it to
|
In the later case, when you use the entity, the library will cast it to
|
||||||
its "input" version for you. If you already have the complete user and
|
its "input" version for you. If you already have the complete user and
|
||||||
|
@ -110,7 +112,9 @@ request we do:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
result = client(SendMessageRequest(peer, 'Hello there!'))
|
result = loop.run_until_complete(
|
||||||
|
client(SendMessageRequest(peer, 'Hello there!'))
|
||||||
|
)
|
||||||
# __call__ is an alias for client.invoke(request). Both will work
|
# __call__ is an alias for client.invoke(request). Both will work
|
||||||
|
|
||||||
Message sent! Of course, this is only an example. There are nearly 250
|
Message sent! Of course, this is only an example. There are nearly 250
|
||||||
|
@ -119,19 +123,21 @@ as you wish. Remember to use the right types! To sum up:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
result = client(SendMessageRequest(
|
result = loop.run_until_complete(client(SendMessageRequest(
|
||||||
client.get_input_entity('username'), 'Hello there!'
|
client.get_input_entity('username'), 'Hello there!'
|
||||||
))
|
)))
|
||||||
|
|
||||||
|
|
||||||
This can further be simplified to:
|
This can further be simplified to:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
result = client(SendMessageRequest('username', 'Hello there!'))
|
async def main():
|
||||||
# Or even
|
result = await client(SendMessageRequest('username', 'Hello there!'))
|
||||||
result = client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
|
# Or even
|
||||||
|
result = await client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
|
||||||
|
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -4,141 +4,46 @@
|
||||||
Update Modes
|
Update Modes
|
||||||
============
|
============
|
||||||
|
|
||||||
|
With ``asyncio``, the library has several tasks running in the background.
|
||||||
|
One task is used for sending requests, another task is used to receive them,
|
||||||
|
and a third one is used to handle updates.
|
||||||
|
|
||||||
The library can run in four distinguishable modes:
|
To handle updates, you must keep your script running. You can do this in
|
||||||
|
several ways. For instance, if you are *not* running ``asyncio``'s event
|
||||||
|
loop, you should use `client.run_until_disconnected
|
||||||
|
<telethon.client.updates.UpdateMethods.run_until_disconnected>`:
|
||||||
|
|
||||||
- With no extra threads at all.
|
.. code-block:: python
|
||||||
- With an extra thread that receives everything as soon as possible (default).
|
|
||||||
- With several worker threads that run your update handlers.
|
|
||||||
- A mix of the above.
|
|
||||||
|
|
||||||
Since this section is about updates, we'll describe the simplest way to
|
import asyncio
|
||||||
work with them.
|
from telethon import TelegramClient
|
||||||
|
|
||||||
|
client = TelegramClient(...)
|
||||||
|
...
|
||||||
|
client.run_until_disconnected()
|
||||||
|
|
||||||
|
|
||||||
Using multiple workers
|
Behind the scenes, this method is ``await``'ing on the `client.disconnected
|
||||||
**********************
|
<telethon.client.telegrambaseclient.disconnected>` property, so the code above
|
||||||
|
and the following are equivalent:
|
||||||
When you create your client, simply pass a number to the
|
|
||||||
``update_workers`` parameter:
|
|
||||||
|
|
||||||
``client = TelegramClient('session', api_id, api_hash, update_workers=2)``
|
|
||||||
|
|
||||||
You can set any amount of workers you want. The more you put, the more
|
|
||||||
update handlers that can be called "at the same time". One or two should
|
|
||||||
suffice most of the time, since setting more will not make things run
|
|
||||||
faster most of the times (actually, it could slow things down).
|
|
||||||
|
|
||||||
The next thing you want to do is to add a method that will be called when
|
|
||||||
an `Update`__ arrives:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
def callback(update):
|
|
||||||
print('I received', update)
|
|
||||||
|
|
||||||
client.add_event_handler(callback)
|
|
||||||
# do more work here, or simply sleep!
|
|
||||||
|
|
||||||
That's it! This is the old way to listen for raw updates, with no further
|
|
||||||
processing. If this feels annoying for you, remember that you can always
|
|
||||||
use :ref:`working-with-updates` but maybe use this for some other cases.
|
|
||||||
|
|
||||||
Now let's do something more interesting. Every time an user talks to us,
|
|
||||||
let's reply to them with the same text reversed:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from telethon.tl.types import UpdateShortMessage, PeerUser
|
|
||||||
|
|
||||||
def replier(update):
|
|
||||||
if isinstance(update, UpdateShortMessage) and not update.out:
|
|
||||||
client.send_message(PeerUser(update.user_id), update.message[::-1])
|
|
||||||
|
|
||||||
|
|
||||||
client.add_event_handler(replier)
|
.. code-block:: python
|
||||||
input('Press enter to stop this!')
|
|
||||||
client.disconnect()
|
|
||||||
|
|
||||||
We only ask you one thing: don't keep this running for too long, or your
|
import asyncio
|
||||||
contacts will go mad.
|
from telethon import TelegramClient
|
||||||
|
|
||||||
|
client = TelegramClient(...)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await client.disconnected
|
||||||
|
|
||||||
|
asyncio.get_event_loop().run_until_complete(main())
|
||||||
|
|
||||||
|
|
||||||
Spawning no worker at all
|
You could also run `client.disconnected
|
||||||
*************************
|
<telethon.client.telegrambaseclient.disconnected>` until it completed.
|
||||||
|
|
||||||
All the workers do is loop forever and poll updates from a queue that is
|
But if you don't want to ``await``, then you should know what you want
|
||||||
filled from the ``ReadThread``, responsible for reading every item off
|
to be doing instead! What matters is that you shouldn't let your script
|
||||||
the network. If you only need a worker and the ``MainThread`` would be
|
die. If you don't care about updates, you don't need any of this.
|
||||||
doing no other job, this is the preferred way. You can easily do the same
|
|
||||||
as the workers like so:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
update = client.updates.poll()
|
|
||||||
if not update:
|
|
||||||
continue
|
|
||||||
|
|
||||||
print('I received', update)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
break
|
|
||||||
|
|
||||||
client.disconnect()
|
|
||||||
|
|
||||||
Note that ``poll`` accepts a ``timeout=`` parameter, and it will return
|
|
||||||
``None`` if other thread got the update before you could or if the timeout
|
|
||||||
expired, so it's important to check ``if not update``.
|
|
||||||
|
|
||||||
This can coexist with the rest of ``N`` workers, or you can set it to ``0``
|
|
||||||
additional workers:
|
|
||||||
|
|
||||||
``client = TelegramClient('session', api_id, api_hash, update_workers=0)``
|
|
||||||
|
|
||||||
You **must** set it to ``0`` (or higher), as it defaults to ``None`` and that
|
|
||||||
has a different meaning. ``None`` workers means updates won't be processed
|
|
||||||
*at all*, so you must set it to some integer value if you want
|
|
||||||
``client.updates.poll()`` to work.
|
|
||||||
|
|
||||||
|
|
||||||
Using the main thread instead the ``ReadThread``
|
|
||||||
************************************************
|
|
||||||
|
|
||||||
If you have no work to do on the ``MainThread`` and you were planning to have
|
|
||||||
a ``while True: sleep(1)``, don't do that. Instead, don't spawn the secondary
|
|
||||||
``ReadThread`` at all like so:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
client = TelegramClient(
|
|
||||||
...
|
|
||||||
spawn_read_thread=False
|
|
||||||
)
|
|
||||||
|
|
||||||
And then ``.idle()`` from the ``MainThread``:
|
|
||||||
|
|
||||||
``client.idle()``
|
|
||||||
|
|
||||||
You can stop it with :kbd:`Control+C`, and you can configure the signals
|
|
||||||
to be used in a similar fashion to `Python Telegram Bot`__.
|
|
||||||
|
|
||||||
As a complete example:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
def callback(update):
|
|
||||||
print('I received', update)
|
|
||||||
|
|
||||||
client = TelegramClient('session', api_id, api_hash,
|
|
||||||
update_workers=1, spawn_read_thread=False)
|
|
||||||
|
|
||||||
client.connect()
|
|
||||||
client.add_event_handler(callback)
|
|
||||||
client.idle() # ends with Ctrl+C
|
|
||||||
|
|
||||||
|
|
||||||
This is the preferred way to use if you're simply going to listen for updates.
|
|
||||||
|
|
||||||
__ https://lonamiwebs.github.io/Telethon/types/update.html
|
|
||||||
__ https://github.com/python-telegram-bot/python-telegram-bot/blob/4b3315db6feebafb94edcaa803df52bb49999ced/telegram/ext/updater.py#L460
|
|
||||||
|
|
123
readthedocs/extra/basic/asyncio-crash-course.rst
Normal file
123
readthedocs/extra/basic/asyncio-crash-course.rst
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
.. _asyncio-crash-course:
|
||||||
|
|
||||||
|
===========================
|
||||||
|
A Crash Course into asyncio
|
||||||
|
===========================
|
||||||
|
|
||||||
|
|
||||||
|
Why asyncio?
|
||||||
|
************
|
||||||
|
|
||||||
|
Python's `asyncio <https://docs.python.org/3/library/asyncio.html>`_ is the
|
||||||
|
standard way to run asynchronous code from within Python. Since Python 3.5,
|
||||||
|
using ``async def`` and ``await`` became possible, and Python 3.6 further
|
||||||
|
improves what you can do with asynchronous code, although it's not the only
|
||||||
|
way (other projects like `Trio <https://github.com/python-trio>`_ also exist).
|
||||||
|
|
||||||
|
Telegram is a service where all API calls are executed in an asynchronous
|
||||||
|
way. You send your request, and eventually, Telegram will process it and
|
||||||
|
respond to it. It feels natural to make a library that also behaves this
|
||||||
|
way: you send a request, and you can ``await`` for its result.
|
||||||
|
|
||||||
|
Having understood that Telegram's API follows an asynchronous model and
|
||||||
|
developing a library that does the same greatly simplifies the internal
|
||||||
|
code and eases working with the API.
|
||||||
|
|
||||||
|
Using ``asyncio`` keeps a cleaner library that will be easier to understand,
|
||||||
|
develop, and that will be faster than using threads, which are harder to get
|
||||||
|
right and can cause issues. It also enables to use the powerful ``asyncio``
|
||||||
|
system such as futures, timeouts, cancellation, etc. in a natural way.
|
||||||
|
|
||||||
|
If you're still not convinced or you're just not ready for using ``asyncio``,
|
||||||
|
the library offers a synchronous interface without the need for all the
|
||||||
|
``async`` and ``await`` you would otherwise see. `Follow this link
|
||||||
|
<https://github.com/LonamiWebs/Telethon/tree/sync>`_ to find out more.
|
||||||
|
|
||||||
|
|
||||||
|
How do I get started?
|
||||||
|
*********************
|
||||||
|
|
||||||
|
To get started with ``asyncio``, all you need is to setup your main
|
||||||
|
``async def`` like so:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
pass # Your code goes here
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
|
|
||||||
|
Inside ``async def main():``, you can use the ``await`` keyword. Most
|
||||||
|
methods in the :ref:`TelegramClient <telethon-client>` are ``async def``.
|
||||||
|
You must ``await`` all ``async def``, also known as a coroutine:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
client = TelegramClient(...)
|
||||||
|
|
||||||
|
# client.start() is a coroutine (async def), it needs an await
|
||||||
|
await client.start()
|
||||||
|
|
||||||
|
# Sending a message also interacts with the API, and needs an await
|
||||||
|
await client.send_message('me', 'Hello myself!')
|
||||||
|
|
||||||
|
|
||||||
|
If you don't know anything else about ``asyncio``, this will be enough
|
||||||
|
to get you started. Once you're ready to learn more about it, you will
|
||||||
|
be able to use that power and everything you've learnt with Telethon.
|
||||||
|
Just remember that if you use ``await``, you need to be inside of an
|
||||||
|
``async def``.
|
||||||
|
|
||||||
|
Another way to use ``async def`` is to use ``loop.run_until_complete(f())``,
|
||||||
|
but the loop must not be running before.
|
||||||
|
|
||||||
|
If you want to handle updates (and don't let the script die), you must
|
||||||
|
`await client.disconnected <telethon.client.telegrambaseclient.disconnected>`
|
||||||
|
which is a property that you can wait on until you call
|
||||||
|
`await client.disconnect() <telethon.client.telegrambaseclient.disconnect>`:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
client = TelegramClient(...)
|
||||||
|
|
||||||
|
@client.on(events.NewMessage)
|
||||||
|
async def handler(event):
|
||||||
|
print(event)
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
await client.start()
|
||||||
|
await client.disconnected
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
|
This is the same as using the ``run_until_disconnected()`` method:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
client = TelegramClient(...)
|
||||||
|
|
||||||
|
@client.on(events.NewMessage)
|
||||||
|
async def handler(event):
|
||||||
|
print(event)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(client.start())
|
||||||
|
client.run_until_disconnected()
|
||||||
|
|
||||||
|
|
||||||
|
More resources to learn asyncio
|
||||||
|
*******************************
|
||||||
|
|
||||||
|
If you would like to learn a bit more about why ``asyncio`` is something
|
||||||
|
you should learn, `check out my blog post
|
||||||
|
<https://lonamiwebs.github.io/blog/asyncio/>`_ that goes into more detail.
|
|
@ -26,6 +26,14 @@ one is very simple:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
# Rename loop.run_until_complete(...) as rc(...), we will use it a lot.
|
||||||
|
# This basically lets us run the event loop (necessary in asyncio) to
|
||||||
|
# execute all the requests we need.
|
||||||
|
rc = loop.run_until_complete
|
||||||
|
|
||||||
from telethon import TelegramClient
|
from telethon import TelegramClient
|
||||||
|
|
||||||
# Use your own values here
|
# Use your own values here
|
||||||
|
@ -54,7 +62,7 @@ your disk. This is by default a database file using Python's ``sqlite3``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client.start()
|
rc(client.start())
|
||||||
|
|
||||||
This is explained after going through the manual process.
|
This is explained after going through the manual process.
|
||||||
|
|
||||||
|
@ -64,14 +72,14 @@ Doing so is very easy:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client.connect() # Must return True, otherwise, try again
|
rc(client.connect()) # Must return True, otherwise, try again
|
||||||
|
|
||||||
You may or may not be authorized yet. You must be authorized
|
You may or may not be authorized yet. You must be authorized
|
||||||
before you're able to send any request:
|
before you're able to send any request:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client.is_user_authorized() # Returns True if you can send requests
|
rc(client.is_user_authorized()) # Returns True if you can send requests
|
||||||
|
|
||||||
If you're not authorized, you need to `.sign_in
|
If you're not authorized, you need to `.sign_in
|
||||||
<telethon.client.auth.AuthMethods.sign_in>`:
|
<telethon.client.auth.AuthMethods.sign_in>`:
|
||||||
|
@ -79,8 +87,8 @@ If you're not authorized, you need to `.sign_in
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
phone_number = '+34600000000'
|
phone_number = '+34600000000'
|
||||||
client.send_code_request(phone_number)
|
rc(client.send_code_request(phone_number))
|
||||||
myself = client.sign_in(phone_number, input('Enter code: '))
|
myself = rc(client.sign_in(phone_number, input('Enter code: ')))
|
||||||
# If .sign_in raises PhoneNumberUnoccupiedError, use .sign_up instead
|
# If .sign_in raises PhoneNumberUnoccupiedError, use .sign_up instead
|
||||||
# If .sign_in raises SessionPasswordNeeded error, call .sign_in(password=...)
|
# If .sign_in raises SessionPasswordNeeded error, call .sign_in(password=...)
|
||||||
# You can import both exceptions from telethon.errors.
|
# You can import both exceptions from telethon.errors.
|
||||||
|
@ -103,10 +111,14 @@ As a full example:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client = TelegramClient('anon', api_id, api_hash)
|
client = TelegramClient('anon', api_id, api_hash)
|
||||||
assert client.connect()
|
|
||||||
if not client.is_user_authorized():
|
async def main():
|
||||||
client.send_code_request(phone_number)
|
assert await client.connect()
|
||||||
me = client.sign_in(phone_number, input('Enter code: '))
|
if not await client.is_user_authorized():
|
||||||
|
await client.send_code_request(phone_number)
|
||||||
|
me = await client.sign_in(phone_number, input('Enter code: '))
|
||||||
|
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
|
|
||||||
All of this, however, can be done through a call to `.start()
|
All of this, however, can be done through a call to `.start()
|
||||||
|
@ -115,7 +127,7 @@ All of this, however, can be done through a call to `.start()
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client = TelegramClient('anon', api_id, api_hash)
|
client = TelegramClient('anon', api_id, api_hash)
|
||||||
client.start()
|
loop.run_until_complete(client.start())
|
||||||
|
|
||||||
|
|
||||||
The code shown is just what `.start()
|
The code shown is just what `.start()
|
||||||
|
@ -169,11 +181,12 @@ again with a ``password=``:
|
||||||
import getpass
|
import getpass
|
||||||
from telethon.errors import SessionPasswordNeededError
|
from telethon.errors import SessionPasswordNeededError
|
||||||
|
|
||||||
client.sign_in(phone)
|
async def main():
|
||||||
try:
|
await client.sign_in(phone)
|
||||||
client.sign_in(code=input('Enter code: '))
|
try:
|
||||||
except SessionPasswordNeededError:
|
await client.sign_in(code=input('Enter code: '))
|
||||||
client.sign_in(password=getpass.getpass())
|
except SessionPasswordNeededError:
|
||||||
|
await client.sign_in(password=getpass.getpass())
|
||||||
|
|
||||||
|
|
||||||
The mentioned `.start()
|
The mentioned `.start()
|
||||||
|
@ -196,32 +209,33 @@ See the examples below:
|
||||||
|
|
||||||
from telethon.errors import EmailUnconfirmedError
|
from telethon.errors import EmailUnconfirmedError
|
||||||
|
|
||||||
# Sets 2FA password for first time:
|
async def main():
|
||||||
client.edit_2fa(new_password='supersecurepassword')
|
# Sets 2FA password for first time:
|
||||||
|
await client.edit_2fa(new_password='supersecurepassword')
|
||||||
|
|
||||||
# Changes password:
|
# Changes password:
|
||||||
client.edit_2fa(current_password='supersecurepassword',
|
await client.edit_2fa(current_password='supersecurepassword',
|
||||||
new_password='changedmymind')
|
new_password='changedmymind')
|
||||||
|
|
||||||
# Clears current password (i.e. removes 2FA):
|
# Clears current password (i.e. removes 2FA):
|
||||||
client.edit_2fa(current_password='changedmymind', new_password=None)
|
await client.edit_2fa(current_password='changedmymind', new_password=None)
|
||||||
|
|
||||||
# Sets new password with recovery email:
|
# Sets new password with recovery email:
|
||||||
try:
|
try:
|
||||||
client.edit_2fa(new_password='memes and dreams',
|
await client.edit_2fa(new_password='memes and dreams',
|
||||||
email='JohnSmith@example.com')
|
email='JohnSmith@example.com')
|
||||||
# Raises error (you need to check your email to complete 2FA setup.)
|
# Raises error (you need to check your email to complete 2FA setup.)
|
||||||
except EmailUnconfirmedError:
|
except EmailUnconfirmedError:
|
||||||
# You can put email checking code here if desired.
|
# You can put email checking code here if desired.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Also take note that unless you remove 2FA or explicitly
|
# Also take note that unless you remove 2FA or explicitly
|
||||||
# give email parameter again it will keep the last used setting
|
# give email parameter again it will keep the last used setting
|
||||||
|
|
||||||
# Set hint after already setting password:
|
# Set hint after already setting password:
|
||||||
client.edit_2fa(current_password='memes and dreams',
|
await client.edit_2fa(current_password='memes and dreams',
|
||||||
new_password='memes and dreams',
|
new_password='memes and dreams',
|
||||||
hint='It keeps you alive')
|
hint='It keeps you alive')
|
||||||
|
|
||||||
__ https://github.com/Anorov/PySocks#installation
|
__ https://github.com/Anorov/PySocks#installation
|
||||||
__ https://github.com/Anorov/PySocks#usage-1
|
__ https://github.com/Anorov/PySocks#usage-1
|
||||||
|
|
|
@ -40,33 +40,34 @@ Through the use of the :ref:`sessions`, the library will automatically
|
||||||
remember the ID and hash pair, along with some extra information, so
|
remember the ID and hash pair, along with some extra information, so
|
||||||
you're able to just do this:
|
you're able to just do this:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def main():
|
||||||
# Dialogs are the "conversations you have open".
|
# Dialogs are the "conversations you have open".
|
||||||
# This method returns a list of Dialog, which
|
# This method returns a list of Dialog, which
|
||||||
# has the .entity attribute and other information.
|
# has the .entity attribute and other information.
|
||||||
dialogs = client.get_dialogs()
|
dialogs = await client.get_dialogs()
|
||||||
|
|
||||||
# All of these work and do the same.
|
# All of these work and do the same.
|
||||||
lonami = client.get_entity('lonami')
|
lonami = await client.get_entity('lonami')
|
||||||
lonami = client.get_entity('t.me/lonami')
|
lonami = await client.get_entity('t.me/lonami')
|
||||||
lonami = client.get_entity('https://telegram.dog/lonami')
|
lonami = await client.get_entity('https://telegram.dog/lonami')
|
||||||
|
|
||||||
# Other kind of entities.
|
# Other kind of entities.
|
||||||
channel = client.get_entity('telegram.me/joinchat/AAAAAEkk2WdoDrB4-Q8-gg')
|
channel = await client.get_entity('telegram.me/joinchat/AAAAAEkk2WdoDrB4-Q8-gg')
|
||||||
contact = client.get_entity('+34xxxxxxxxx')
|
contact = await client.get_entity('+34xxxxxxxxx')
|
||||||
friend = client.get_entity(friend_id)
|
friend = await client.get_entity(friend_id)
|
||||||
|
|
||||||
# Getting entities through their ID (User, Chat or Channel)
|
# Getting entities through their ID (User, Chat or Channel)
|
||||||
entity = client.get_entity(some_id)
|
entity = await client.get_entity(some_id)
|
||||||
|
|
||||||
# You can be more explicit about the type for said ID by wrapping
|
# You can be more explicit about the type for said ID by wrapping
|
||||||
# it inside a Peer instance. This is recommended but not necessary.
|
# it inside a Peer instance. This is recommended but not necessary.
|
||||||
from telethon.tl.types import PeerUser, PeerChat, PeerChannel
|
from telethon.tl.types import PeerUser, PeerChat, PeerChannel
|
||||||
|
|
||||||
my_user = client.get_entity(PeerUser(some_id))
|
my_user = await client.get_entity(PeerUser(some_id))
|
||||||
my_chat = client.get_entity(PeerChat(some_id))
|
my_chat = await client.get_entity(PeerChat(some_id))
|
||||||
my_channel = client.get_entity(PeerChannel(some_id))
|
my_channel = await client.get_entity(PeerChannel(some_id))
|
||||||
|
|
||||||
|
|
||||||
All methods in the :ref:`telegram-client` call `.get_input_entity()
|
All methods in the :ref:`telegram-client` call `.get_input_entity()
|
||||||
|
@ -134,9 +135,10 @@ library, the raw requests you make to the API are also able to call
|
||||||
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
|
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
|
||||||
wherever needed, so you can even do things like:
|
wherever needed, so you can even do things like:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client(SendMessageRequest('username', 'hello'))
|
async def main():
|
||||||
|
await client(SendMessageRequest('username', 'hello'))
|
||||||
|
|
||||||
The library will call the ``.resolve()`` method of the request, which will
|
The library will call the ``.resolve()`` method of the request, which will
|
||||||
resolve ``'username'`` with the appropriated :tl:`InputPeer`. Don't worry if
|
resolve ``'username'`` with the appropriated :tl:`InputPeer`. Don't worry if
|
||||||
|
|
|
@ -21,6 +21,9 @@ Creating a client
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
from telethon import TelegramClient
|
from telethon import TelegramClient
|
||||||
|
|
||||||
# These example values won't work. You must get your own api_id and
|
# These example values won't work. You must get your own api_id and
|
||||||
|
@ -29,7 +32,7 @@ Creating a client
|
||||||
api_hash = '0123456789abcdef0123456789abcdef'
|
api_hash = '0123456789abcdef0123456789abcdef'
|
||||||
|
|
||||||
client = TelegramClient('session_name', api_id, api_hash)
|
client = TelegramClient('session_name', api_id, api_hash)
|
||||||
client.start()
|
loop.run_until_complete(client.start())
|
||||||
|
|
||||||
**More details**: :ref:`creating-a-client`
|
**More details**: :ref:`creating-a-client`
|
||||||
|
|
||||||
|
@ -39,31 +42,36 @@ Basic Usage
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Getting information about yourself
|
async def main():
|
||||||
print(client.get_me().stringify())
|
# Getting information about yourself
|
||||||
|
me = await client.get_me()
|
||||||
|
print(me.stringify())
|
||||||
|
|
||||||
# Sending a message (you can use 'me' or 'self' to message yourself)
|
# Sending a message (you can use 'me' or 'self' to message yourself)
|
||||||
client.send_message('username', 'Hello World from Telethon!')
|
await client.send_message('username', 'Hello World from Telethon!')
|
||||||
|
|
||||||
# Sending a file
|
# Sending a file
|
||||||
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
await client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||||
|
|
||||||
# Retrieving messages from a chat
|
# Retrieving messages from a chat
|
||||||
from telethon import utils
|
from telethon import utils
|
||||||
for message in client.iter_messages('username', limit=10):
|
async for message in client.iter_messages('username', limit=10):
|
||||||
print(utils.get_display_name(message.sender), message.message)
|
print(utils.get_display_name(message.sender), message.message)
|
||||||
|
|
||||||
# Listing all the dialogs (conversations you have open)
|
# Listing all the dialogs (conversations you have open)
|
||||||
for dialog in client.get_dialogs(limit=10):
|
async for dialog in client.get_dialogs(limit=10):
|
||||||
print(utils.get_display_name(dialog.entity), dialog.draft.text)
|
print(dialog.name, dialog.draft.text)
|
||||||
|
|
||||||
# Downloading profile photos (default path is the working directory)
|
# Downloading profile photos (default path is the working directory)
|
||||||
client.download_profile_photo('username')
|
await client.download_profile_photo('username')
|
||||||
|
|
||||||
# Once you have a message with .media (if message.media)
|
# Once you have a message with .media (if message.media)
|
||||||
# you can download it using client.download_media():
|
# you can download it using client.download_media(),
|
||||||
messages = client.get_messages('username')
|
# or even using message.download_media():
|
||||||
client.download_media(messages[0])
|
messages = await client.get_messages('username')
|
||||||
|
await messages[0].download_media()
|
||||||
|
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
**More details**: :ref:`telegram-client`
|
**More details**: :ref:`telegram-client`
|
||||||
|
|
||||||
|
@ -77,15 +85,11 @@ Handling Updates
|
||||||
|
|
||||||
from telethon import events
|
from telethon import events
|
||||||
|
|
||||||
# We need to have some worker running
|
|
||||||
client.updates.workers = 1
|
|
||||||
|
|
||||||
@client.on(events.NewMessage(incoming=True, pattern='(?i)hi'))
|
@client.on(events.NewMessage(incoming=True, pattern='(?i)hi'))
|
||||||
def handler(event):
|
async def handler(event):
|
||||||
event.reply('Hello!')
|
await event.reply('Hello!')
|
||||||
|
|
||||||
# If you want to handle updates you can't let the script end.
|
client.run_until_disconnected()
|
||||||
input('Press enter to exit.')
|
|
||||||
|
|
||||||
**More details**: :ref:`working-with-updates`
|
**More details**: :ref:`working-with-updates`
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,14 @@ For instance, retrieving your own user can be done in a single line:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
myself = client.get_me()
|
import asyncio
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
myself = await client.get_me()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
Internally, this method has sent a request to Telegram, who replied with
|
Internally, this method has sent a request to Telegram, who replied with
|
||||||
the information about your own user, and then the desired information
|
the information about your own user, and then the desired information
|
||||||
|
@ -46,10 +53,11 @@ how the library refers to either of these:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# The method will infer that you've passed an username
|
async def main():
|
||||||
# It also accepts phone numbers, and will get the user
|
# The method will infer that you've passed an username
|
||||||
# from your contact list.
|
# It also accepts phone numbers, and will get the user
|
||||||
lonami = client.get_entity('lonami')
|
# from your contact list.
|
||||||
|
lonami = await client.get_entity('lonami')
|
||||||
|
|
||||||
The so called "entities" are another important whole concept on its own,
|
The so called "entities" are another important whole concept on its own,
|
||||||
but for now you don't need to worry about it. Simply know that they are
|
but for now you don't need to worry about it. Simply know that they are
|
||||||
|
@ -59,30 +67,31 @@ Many other common methods for quick scripts are also available:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Note that you can use 'me' or 'self' to message yourself
|
async def main():
|
||||||
client.send_message('username', 'Hello World from Telethon!')
|
# Note that you can use 'me' or 'self' to message yourself
|
||||||
|
await client.send_message('username', 'Hello World from Telethon!')
|
||||||
|
|
||||||
# .send_message's parse mode defaults to markdown, so you
|
# .send_message's parse mode defaults to markdown, so you
|
||||||
# can use **bold**, __italics__, [links](https://example.com), `code`,
|
# can use **bold**, __italics__, [links](https://example.com), `code`,
|
||||||
# and even [mentions](@username)/[mentions](tg://user?id=123456789)
|
# and even [mentions](@username)/[mentions](tg://user?id=123456789)
|
||||||
client.send_message('username', '**Using** __markdown__ `too`!')
|
await client.send_message('username', '**Using** __markdown__ `too`!')
|
||||||
|
|
||||||
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
await client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||||
|
|
||||||
# The utils package has some goodies, like .get_display_name()
|
# The utils package has some goodies, like .get_display_name()
|
||||||
from telethon import utils
|
from telethon import utils
|
||||||
for message in client.iter_messages('username', limit=10):
|
async for message in client.iter_messages('username', limit=10):
|
||||||
print(utils.get_display_name(message.sender), message.message)
|
print(utils.get_display_name(message.sender), message.message)
|
||||||
|
|
||||||
# Dialogs are the conversations you have open
|
# Dialogs are the conversations you have open
|
||||||
for dialog in client.get_dialogs(limit=10):
|
async for dialog in client.get_dialogs(limit=10):
|
||||||
print(utils.get_display_name(dialog.entity), dialog.draft.text)
|
print(dialog.name, dialog.draft.text)
|
||||||
|
|
||||||
# Default path is the working directory
|
# Default path is the working directory
|
||||||
client.download_profile_photo('username')
|
await client.download_profile_photo('username')
|
||||||
|
|
||||||
# Call .disconnect() when you're done
|
# Call .disconnect() when you're done
|
||||||
client.disconnect()
|
await client.disconnect()
|
||||||
|
|
||||||
Remember that you can call ``.stringify()`` to any object Telegram returns
|
Remember that you can call ``.stringify()`` to any object Telegram returns
|
||||||
to pretty print it. Calling ``str(result)`` does the same operation, but on
|
to pretty print it. Calling ``str(result)`` does the same operation, but on
|
||||||
|
|
|
@ -34,37 +34,38 @@ let's dive in!
|
||||||
Getting Started
|
Getting Started
|
||||||
***************
|
***************
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from telethon import TelegramClient, events
|
import asyncio
|
||||||
|
from telethon import TelegramClient, events
|
||||||
|
|
||||||
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
|
client = TelegramClient('name', api_id, api_hash)
|
||||||
client.start()
|
|
||||||
|
|
||||||
@client.on(events.NewMessage)
|
@client.on(events.NewMessage)
|
||||||
def my_event_handler(event):
|
async def my_event_handler(event):
|
||||||
if 'hello' in event.raw_text:
|
if 'hello' in event.raw_text:
|
||||||
event.reply('hi!')
|
await event.reply('hi!')
|
||||||
|
|
||||||
client.idle()
|
asyncio.get_event_loop().run_until_complete(client.start())
|
||||||
|
client.run_until_disconnected()
|
||||||
|
|
||||||
|
|
||||||
Not much, but there might be some things unclear. What does this code do?
|
Not much, but there might be some things unclear. What does this code do?
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from telethon import TelegramClient, events
|
import asyncio
|
||||||
|
from telethon import TelegramClient, events
|
||||||
|
|
||||||
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
|
client = TelegramClient('name', api_id, api_hash)
|
||||||
client.start()
|
|
||||||
|
|
||||||
|
|
||||||
This is normal initialization (of course, pass session name, API ID and hash).
|
This is normal creation (of course, pass session name, API ID and hash).
|
||||||
Nothing we don't know already.
|
Nothing we don't know already.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@client.on(events.NewMessage)
|
@client.on(events.NewMessage)
|
||||||
|
|
||||||
|
|
||||||
This Python decorator will attach itself to the ``my_event_handler``
|
This Python decorator will attach itself to the ``my_event_handler``
|
||||||
|
@ -72,11 +73,11 @@ definition, and basically means that *on* a `NewMessage
|
||||||
<telethon.events.newmessage.NewMessage>` *event*,
|
<telethon.events.newmessage.NewMessage>` *event*,
|
||||||
the callback function you're about to define will be called:
|
the callback function you're about to define will be called:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def my_event_handler(event):
|
async def my_event_handler(event):
|
||||||
if 'hello' in event.raw_text:
|
if 'hello' in event.raw_text:
|
||||||
event.reply('hi!')
|
await event.reply('hi!')
|
||||||
|
|
||||||
|
|
||||||
If a `NewMessage
|
If a `NewMessage
|
||||||
|
@ -84,14 +85,16 @@ If a `NewMessage
|
||||||
and ``'hello'`` is in the text of the message, we ``reply`` to the event
|
and ``'hello'`` is in the text of the message, we ``reply`` to the event
|
||||||
with a ``'hi!'`` message.
|
with a ``'hi!'`` message.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
client.idle()
|
asyncio.get_event_loop().run_until_complete(client.start())
|
||||||
|
client.run_until_disconnected()
|
||||||
|
|
||||||
|
|
||||||
Finally, this tells the client that we're done with our code, and want
|
Finally, this tells the client that we're done with our code. We run the
|
||||||
to listen for all these events to occur. Of course, you might want to
|
``asyncio`` loop until the client starts, and then we run it again until
|
||||||
do other things instead idling. For this refer to :ref:`update-modes`.
|
we are disconnected. Of course, you can do other things instead of running
|
||||||
|
until disconnected. For this refer to :ref:`update-modes`.
|
||||||
|
|
||||||
|
|
||||||
More on events
|
More on events
|
||||||
|
@ -130,17 +133,17 @@ for example:
|
||||||
# Either a single item or a list of them will work for the chats.
|
# Either a single item or a list of them will work for the chats.
|
||||||
# You can also use the IDs, Peers, or even User/Chat/Channel objects.
|
# You can also use the IDs, Peers, or even User/Chat/Channel objects.
|
||||||
@client.on(events.NewMessage(chats=('TelethonChat', 'TelethonOffTopic')))
|
@client.on(events.NewMessage(chats=('TelethonChat', 'TelethonOffTopic')))
|
||||||
def normal_handler(event):
|
async def normal_handler(event):
|
||||||
if 'roll' in event.raw_text:
|
if 'roll' in event.raw_text:
|
||||||
event.reply(str(random.randint(1, 6)))
|
await event.reply(str(random.randint(1, 6)))
|
||||||
|
|
||||||
|
|
||||||
# Similarly, you can use incoming=True for messages that you receive
|
# Similarly, you can use incoming=True for messages that you receive
|
||||||
@client.on(events.NewMessage(chats='TelethonOffTopic', outgoing=True))
|
@client.on(events.NewMessage(chats='TelethonOffTopic', outgoing=True,
|
||||||
def admin_handler(event):
|
pattern='eval (.+)'))
|
||||||
if event.raw_text.startswith('eval'):
|
async def admin_handler(event):
|
||||||
expression = event.raw_text.replace('eval', '').strip()
|
expression = event.pattern_match.group(1)
|
||||||
event.reply(str(ast.literal_eval(expression)))
|
await event.reply(str(ast.literal_eval(expression)))
|
||||||
|
|
||||||
|
|
||||||
You can pass one or more chats to the ``chats`` parameter (as a list or tuple),
|
You can pass one or more chats to the ``chats`` parameter (as a list or tuple),
|
||||||
|
@ -178,23 +181,23 @@ it makes no sense to process any other handlers in the chain. For this case,
|
||||||
it is possible to raise a `telethon.events.StopPropagation` exception which
|
it is possible to raise a `telethon.events.StopPropagation` exception which
|
||||||
will cause the propagation of the update through your handlers to stop:
|
will cause the propagation of the update through your handlers to stop:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from telethon.events import StopPropagation
|
from telethon.events import StopPropagation
|
||||||
|
|
||||||
@client.on(events.NewMessage)
|
@client.on(events.NewMessage)
|
||||||
def _(event):
|
async def _(event):
|
||||||
# ... some conditions
|
# ... some conditions
|
||||||
event.delete()
|
await event.delete()
|
||||||
|
|
||||||
# Other handlers won't have an event to work with
|
# Other handlers won't have an event to work with
|
||||||
raise StopPropagation
|
raise StopPropagation
|
||||||
|
|
||||||
@client.on(events.NewMessage)
|
@client.on(events.NewMessage)
|
||||||
def _(event):
|
async def _(event):
|
||||||
# Will never be reached, because it is the second handler
|
# Will never be reached, because it is the second handler
|
||||||
# in the chain.
|
# in the chain.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
Remember to check :ref:`telethon-events-package` if you're looking for
|
Remember to check :ref:`telethon-events-package` if you're looking for
|
||||||
|
|
|
@ -22,6 +22,17 @@ when you upgrade!
|
||||||
contains the friendly methods that **you should use** most of the time.
|
contains the friendly methods that **you should use** most of the time.
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The library uses `asyncio <https://docs.python.org/3/library/asyncio.html>`_
|
||||||
|
by default, but you if you don't know how to use ``asyncio`` you can use
|
||||||
|
`a simpler version <https://github.com/LonamiWebs/Telethon/tree/sync>`_
|
||||||
|
(select the "sync" version in ``readthedocs``' bottom left corner).
|
||||||
|
|
||||||
|
However, **you are encouraged to use asyncio**, it will make your scripts
|
||||||
|
faster and more powerful. :ref:`asyncio-crash-course` will teach you why
|
||||||
|
``asyncio`` is good and how to use it.
|
||||||
|
|
||||||
|
|
||||||
What is this?
|
What is this?
|
||||||
*************
|
*************
|
||||||
|
|
||||||
|
@ -39,6 +50,7 @@ heavy job for you, so you can focus on developing an application.
|
||||||
|
|
||||||
extra/basic/getting-started
|
extra/basic/getting-started
|
||||||
extra/basic/installation
|
extra/basic/installation
|
||||||
|
extra/basic/asyncio-crash-course
|
||||||
extra/basic/creating-a-client
|
extra/basic/creating-a-client
|
||||||
extra/basic/telegram-client
|
extra/basic/telegram-client
|
||||||
extra/basic/entities
|
extra/basic/entities
|
||||||
|
|
|
@ -174,8 +174,8 @@ class NewMessage(EventBuilder):
|
||||||
>>> from telethon import TelegramClient, events
|
>>> from telethon import TelegramClient, events
|
||||||
>>> client = TelegramClient(...)
|
>>> client = TelegramClient(...)
|
||||||
>>>
|
>>>
|
||||||
>>> @client.on(events.NewMessage(pattern=r'hi (\w+)!'))
|
>>> @client.on(events.NewMessage(pattern=r'hi (\\w+)!'))
|
||||||
... def handler(event):
|
... async def handler(event):
|
||||||
... # In this case, the result is a ``Match`` object
|
... # In this case, the result is a ``Match`` object
|
||||||
... # since the ``str`` pattern was converted into
|
... # since the ``str`` pattern was converted into
|
||||||
... # the ``re.compile(pattern).match`` function.
|
... # the ``re.compile(pattern).match`` function.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user