Telethon/readthedocs/extra/basic/working-with-updates.rst

205 lines
6.6 KiB
ReStructuredText
Raw Normal View History

2017-11-20 07:19:53 +03:00
.. _working-with-updates:
2017-11-20 07:12:31 +03:00
====================
Working with Updates
====================
The library comes with the `telethon.events` module. *Events* are an abstraction
over what Telegram calls `updates`__, and are meant to ease simple and common
usage when dealing with them, since there are many updates. If you're looking
for the method reference, check :ref:`telethon-events-package`, otherwise,
let's dive in!
.. important::
The library logs by default no output, and any exception that occurs
inside your handlers will be "hidden" from you to prevent the thread
from terminating (so it can still deliver events). You should enable
logging when working with events, at least the error level, to see if
this is happening so you can debug the error.
**When using updates, please enable logging:**
.. code-block:: python
import logging
logging.basicConfig(level=logging.ERROR)
2017-11-20 07:12:31 +03:00
.. contents::
Getting Started
***************
2017-11-20 07:12:31 +03:00
.. code-block:: python
2017-11-20 07:12:31 +03:00
from telethon import TelegramClient, events
2017-11-20 07:12:31 +03:00
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
client.start()
2017-11-20 07:12:31 +03:00
@client.on(events.NewMessage)
def my_event_handler(event):
if 'hello' in event.raw_text:
event.reply('hi!')
2017-11-20 07:12:31 +03:00
client.idle()
2017-11-20 07:12:31 +03:00
Not much, but there might be some things unclear. What does this code do?
2017-11-20 07:12:31 +03:00
.. code-block:: python
from telethon import TelegramClient, events
2017-11-20 07:12:31 +03:00
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
client.start()
2017-11-20 07:12:31 +03:00
This is normal initialization (of course, pass session name, API ID and hash).
Nothing we don't know already.
2017-11-20 07:12:31 +03:00
.. code-block:: python
2017-11-20 07:12:31 +03:00
@client.on(events.NewMessage)
2017-11-20 07:12:31 +03:00
This Python decorator will attach itself to the ``my_event_handler``
definition, and basically means that *on* a `NewMessage
<telethon.events.newmessage.NewMessage>` *event*,
the callback function you're about to define will be called:
2017-11-20 07:12:31 +03:00
.. code-block:: python
2017-11-20 07:12:31 +03:00
def my_event_handler(event):
if 'hello' in event.raw_text:
event.reply('hi!')
2017-11-20 07:12:31 +03:00
If a `NewMessage
<telethon.events.newmessage.NewMessage>` event occurs,
and ``'hello'`` is in the text of the message, we ``reply`` to the event
with a ``'hi!'`` message.
2017-11-20 07:12:31 +03:00
.. code-block:: python
client.idle()
2017-11-20 07:12:31 +03:00
Finally, this tells the client that we're done with our code, and want
to listen for all these events to occur. Of course, you might want to
do other things instead idling. For this refer to :ref:`update-modes`.
2017-11-20 07:12:31 +03:00
More on events
**************
2017-11-20 07:12:31 +03:00
The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
more than what was shown. You can access the ``.sender`` of the message
through that member, or even see if the message had ``.media``, a ``.photo``
or a ``.document`` (which you could download with for example
`client.download_media(event.photo) <telethon.client.downloads.DownloadMethods.download_media>`.
2017-11-20 07:12:31 +03:00
If you don't want to ``.reply`` as a reply, you can use the ``.respond()``
method instead. Of course, there are more events such as ``ChatAction`` or
``UserUpdate``, and they're all used in the same way. Simply add the
``@client.on(events.XYZ)`` decorator on the top of your handler and you're
done! The event that will be passed always is of type ``XYZ.Event`` (for
instance, ``NewMessage.Event``), except for the ``Raw`` event which just
passes the ``Update`` object.
2017-11-20 07:12:31 +03:00
Note that ``.reply()`` and ``.respond()`` are just wrappers around the
`client.send_message() <telethon.client.messages.MessageMethods.send_message>`
method which supports the ``file=`` parameter.
This means you can reply with a photo if you do ``event.reply(file=photo)``.
You can put the same event on many handlers, and even different events on
the same handler. You can also have a handler work on only specific chats,
for example:
2017-11-20 07:12:31 +03:00
.. code-block:: python
2017-11-20 07:12:31 +03:00
import ast
import random
2017-11-20 07:12:31 +03:00
# 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.
@client.on(events.NewMessage(chats=('TelethonChat', 'TelethonOffTopic')))
def normal_handler(event):
if 'roll' in event.raw_text:
event.reply(str(random.randint(1, 6)))
2017-11-20 07:12:31 +03:00
# Similarly, you can use incoming=True for messages that you receive
@client.on(events.NewMessage(chats='TelethonOffTopic', outgoing=True))
def admin_handler(event):
if event.raw_text.startswith('eval'):
expression = event.raw_text.replace('eval', '').strip()
event.reply(str(ast.literal_eval(expression)))
You can pass one or more chats to the ``chats`` parameter (as a list or tuple),
and only events from there will be processed. You can also specify whether you
want to handle incoming or outgoing messages (those you receive or those you
send). In this example, people can say ``'roll'`` and you will reply with a
random number, while if you say ``'eval 4+4'``, you will reply with the
solution. Try it!
2017-11-20 07:12:31 +03:00
Events without decorators
*************************
If for any reason you can't use the `@client.on
<telethon.client.updates.UpdateMethods.on>` syntax, don't worry.
You can call `client.add_event_handler(callback, event)
<telethon.client.updates.UpdateMethods.add_event_handler>` to achieve
the same effect.
Similarly, you also have `client.remove_event_handler
<telethon.client.updates.UpdateMethods.remove_event_handler>`
and `client.list_event_handlers
<telethon.client.updates.UpdateMethods.list_event_handlers>`.
The ``event`` type is optional in all methods and defaults to
`events.Raw <telethon.events.raw.Raw>` for adding, and ``None`` when
removing (so all callbacks would be removed).
Stopping propagation of Updates
*******************************
There might be cases when an event handler is supposed to be used solitary and
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
will cause the propagation of the update through your handlers to stop:
.. code-block:: python
from telethon.events import StopPropagation
@client.on(events.NewMessage)
def _(event):
# ... some conditions
event.delete()
# Other handlers won't have an event to work with
raise StopPropagation
@client.on(events.NewMessage)
def _(event):
# Will never be reached, because it is the second handler
# in the chain.
pass
Remember to check :ref:`telethon-events-package` if you're looking for
the methods reference.
2017-11-20 07:12:31 +03:00
__ https://lonamiwebs.github.io/Telethon/types/update.html