Is there anyway to give priority for each event_handler?
For example, when someone send a file, a first handler can download the file, then anther handler process, following others. Which just works like assembly line; but this must guarantee the download handler works first.
Not yet, but I would like for this to be the case in the next version. Please suggest your "ideal model" for how'd you'd like updates to work, and maybe we can make it happen :)
(For the time being, the first ones you register will be called first.)
Refer
I was inspired by https://github.com/SuMaiKaDe/bot/tree/main/jbot:
- He separated into two modules:
-
bot: There he realized` the functions he wants. -
diy: There users who wants to add some other feature even somebody's functional code could be pleased here.
-
- Then in
__main__.pyhe callload_module()which actual in utils.py: https://github.com/SuMaiKaDe/bot/blob/0c99ddcb5fecde763c261aa1e3ffedcabc18911a/jbot/main.py#L11-L19 - In
load_module()maybe he could sort the name in folder by some strategy then he can register the function in order.(now he didn't do this, and I'm refactoring this repo.) https://github.com/SuMaiKaDe/bot/blob/0c99ddcb5fecde763c261aa1e3ffedcabc18911a/jbot/utils.py#L7-L21
But if someone wants a handler that should be done first and placed it in diy folder, it will be impossible because in step 2, load bot folder first and load diy folder later.
In springboot
The priority is inspired by springboot in https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet/RegistrationBean.html#setOrder-int-.
There springboot allow developers set order for each filter.
Thoughts may be realized
In telethon, I think we could sort _event_builders by an optional arg priority and the register order.
Every time developers add a event_handler by call add_event_handler, maybe we could add a arg like this:
def add_event_handler(
self: 'TelegramClient',
callback: Callback,
event: EventBuilder = None,
priority:int = 5):
And in: https://github.com/LonamiWebs/Telethon/blob/2e1be01ad4f6462de2e9e1f96a33537e51f44980/telethon/client/updates.py#L157 We not only add the new one, but also place it in right order.
The whole function is:
https://github.com/LonamiWebs/Telethon/blob/2e1be01ad4f6462de2e9e1f96a33537e51f44980/telethon/client/updates.py#L118-L165
And the on decorator maybe should add this arg, too:(I'm not familiar to python decorator so I don't know what to change, that is why I'm not make a pr.)
https://github.com/LonamiWebs/Telethon/blob/2e1be01ad4f6462de2e9e1f96a33537e51f44980/telethon/client/updates.py#L91-L116
What I thought
Now each handler works his own. Maybe they could work like assembly line (or filter in Springboot). Each handler handles the event as in order, if someone break the chain, raise event.StopPropagation and stop.
I think an object is passed (additional, besides event) which can be develop changed and pass some information through this process is better.
Maybe you think it's like conversation, but in section 1, some bots developed by its owner and secondary developer, this change is useful.
How should propagation work by default in your opinion? Is it stop by default, stop same priority, stop all…? How would you like to see "message passing between events"? Maybe if an event returns something, it's passed to the next. But how could this be achieved?
Propagation
First, I think propagation a chain that have same EventBuilder, but now _event_builders is a list, not server chains, so now it stop all the lasted handler. If handler2 raise the StopPropagation, handler3and so on won't run.
(If we can support it may be better, but it won't support some bot such as here because it add and remove _event_builders by hand.)
Usage
I searched through the github repos, and find that none of developer use the several handlers to handle one update. It's hard to give example for you, I only search two:
- One developer makes a bot that can download files send by user, if you want to make a plugin for the bot, which can run the file if it's end with
pyorsh. The plugin must run later than download, and if download cancel by user, this new plugin shouldn't run.

- You want to add blacklist to a bot and want to statistics the user info. If your simple change the
@bot.on(condition), it hard to statistics the user info (am I right?), so you can add a handler run first check user and add he/she to the database, if he/she is denied, raise theStopPropagation
Message
I have thought how to achieved message, there is 3 ways in my opinion:
-
Change the callback function: In: https://github.com/LonamiWebs/Telethon/blob/2e1be01ad4f6462de2e9e1f96a33537e51f44980/telethon/client/updates.py#L467
obj = {} #out the loop(line 452)await callback(event, obj)This way is breaking, most of bots should change their code, but few of them use the feature that a message can be processed by several handlers. -
Add a static variable in class and each
_dispatch_updatecall reset this variable. -
Do nothing. If some handlers need some previous handlers' information, add static variable in previous handlers' information and the later one read it. (Variable is maintained by developer.)
Anyway, it's your code, you can come up your ideas. If you think part of this or even entire one is ridiculous, you can abandon it, if there are some reasons is better.
Besides, I think if someone is in conversation with bot, the bot shouldn't response anything except the conversation, especially conv is exclusive=True.
async with client.conversation(...) as conv:
await conv.send_message('Hey, what is your name?')
response = await conv.get_response()
name = response.text
await conv.send_message('Nice to meet you, {}!'.format(name))
and
@client.on(events.NewMessage)
async def my_event_handler(event):
if 'Hello' in event.raw_text:
await event.reply('hi!')
now:
(bot): Hey, what is your name? (usr): Hello Word (bot): Nice to meet you, {Hello Word}! (bot): hi!
When we talk about "order", is it the same as "priority"? For example, if I raise stop propagation at some priority, do handlers with "higher" priority still get called? Or the same, or lower. If it's just "order" though this question makes no sense (all have same "priority", they're just called in some order).
Regarding your points:
- I personally wouldn't use that feature so I don't need the extra argument.
- This could work, but it's tricky if different clients use the same handler. It's also not really clean.
- While this works in this case, other changes in the upcoming version need a similar solution (raw updates can no longer be monkey-patched so we need to provide access to e.g. the client somehow).
I think Python-Telegram-Bot sidesteps this issue by having a single "context" parameter (at least it did some time ago). The downside is you need to type context.update (I don't know if the situation has improved since.)
Our event could be the context and contain information from previous handlers (in fact it already works as "context" because it embeds the .client). However, this doesn't work for raw updates. We could also dynamically detect if there's a second parameter and stuff everything in there (so if you only specify one parameter, things work, but if you specify two, you get extra information).
Regarding client.conversation, that's being removed (partly due to its really poor interaction and integration with updates).
Yes, the higher priority one is in front of the lower one (ordered firstly); if two have same priority, they could be run at random order(It means that we could decide their order).
Do you mean that I can add some information in EventBuilder dynamically? I think it could run.
If client.conversation is removed, there always need a way in a scene: a commend need some extra params or confirms. For exapmle:
- Wants to change the bot config file.
- Start with user command, such
/config. - Bot list all the configurations and its' options.
- User click one.
- Bot ask for new options
- User type it.
- I develop a bot which can execute shell command interactive and stop with
exit. In most scenes act withButton, the interactive way maybe re-thinking if you remove theclient.conversation. Waiting for your solutions.
I have no further questions, you can close this issue if you like. Thanks for your time and patients! Sincerely.
v2 will have a more convenient way to sort handlers.
Thanks for your time and efforts!
This is unlikely to happen in the near future so I will be closing the issue. We can reopen it if there's still interest once the time is right.