Updates in Depth¶
Properties vs. Methods¶
The event shown above acts just like a
custom.Message, which means you
can access all the properties it has, like
However events are different to other methods in the client, like
Events may not send information about the sender or chat, which means it
None, but all the methods defined in the client always have this
information so it doesn’t need to be re-fetched. For this reason, you have
get_ methods, which will make a network call if necessary.
In short, you should do this:
@client.on(events.NewMessage) async def handler(event): # event.input_chat may be None, use event.get_input_chat() chat = await event.get_input_chat() sender = await event.get_sender() buttons = await event.get_buttons() async def main(): async for message in client.iter_messages('me', 10): # Methods from the client always have these properties ready chat = message.input_chat sender = message.sender buttons = message.buttons
Notice, properties (
message.sender) don’t need an
message.get_sender) do need an
and you should use methods in events for these properties that may need network.
Events Without the client¶
The code of your application starts getting big, so you decide to
separate the handlers into different files. But how can you access
the client from these files? You don’t need to! Just
# handlers/welcome.py from telethon import events @events.register(events.NewMessage('(?i)hello')) async def handler(event): client = event.client await event.respond('Hey!') await client.send_message('me', 'I said hello to someone')
Registering events is a way of saying “this method is an event handler”.
You can use
telethon.events.is_handler to check if any method is a handler.
You can think of them as a different approach to Flask’s blueprints.
It’s important to note that this does not add the handler to any client! You never specified the client on which the handler should be used. You only declared that it is a handler, and its type.
To actually use the handler, you need to
client.add_event_handler to the
client (or clients) where they should be added to:
# main.py from telethon import TelegramClient import handlers.welcome with TelegramClient(...) as client: client.add_event_handler(handlers.welcome.handler) client.run_until_disconnected()
This also means that you can register an event handler once and then add it to many clients without re-declaring the event.
Events Without Decorators¶
from telethon import TelegramClient, events async def handler(event): ... with TelegramClient(...) as client: client.add_event_handler(handler, events.NewMessage) client.run_until_disconnected()
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:
from telethon.events import StopPropagation @client.on(events.NewMessage) async def _(event): # ... some conditions await event.delete() # Other handlers won't have an event to work with raise StopPropagation @client.on(events.NewMessage) async def _(event): # Will never be reached, because it is the second handler # in the chain. pass
Remember to check Update Events if you’re looking for the methods reference.
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.
import asyncio from telethon import TelegramClient client = TelegramClient(...) ... client.run_until_disconnected()
Behind the scenes, this method is
await’ing on the
so the code above and the following are equivalent:
import asyncio from telethon import TelegramClient client = TelegramClient(...) async def main(): await client.disconnected loop = asyncio.get_event_loop() loop.run_until_complete(main())
You could also run
until it completed.
But if you don’t want to
await, then you should know what you want
to be doing instead! What matters is that you shouldn’t let your script
die. If you don’t care about updates, you don’t need any of this.
async def main(): await client.run_until_disconnected() loop.run_until_complete(main())
If you need to process updates sequentially (i.e. not in parallel),
you should set
sequential_updates=True when creating the client:
with TelegramClient(..., sequential_updates=True) as client: ...