I have a problem with ConversationHandler, that may come from the fact that I haven't understand very well how to use it. I use parent and child ConversationHandlers in PTB like this:
...
child_conv_handler = ConversationHandler(
entry_points=[CommandHandler("start_child", start_child_func)],
states={
CHILD_STATE: [
CommandHandler("search", search),
CommandHandler("add", add),
CommandHandler("exit", exit),
],
},
fallbacks=[MessageHandler(filters.TEXT, fallback_message),],
)
parent_conv_handler = ConversationHandler(
entry_points=[CommandHandler("start_parent", start_parent_func)],
states={
PARENT_STATE: [
CommandHandler("stats", stats),
child_conv_handler,
],
},
fallbacks=[CommandHandler("stop", stop)],
)
application.add_handler(parent_conv_handler)
application.run_polling(allowed_updates=Update.ALL_TYPES)
I make following actions:
- sent /start_parent to start parent ConversationHandler;
- start_parent_func callback function returns dialog state PARENT_STATE;
- sent /start_child to start child ConversationHandler;
- start_child_func callback function returns dialog state CHILD_STATE;
(attention!)
- sent /stats command and
CommandHandler("stats", stats)triggered (stats callback function does its job!).
Its look like all updates firstly checks by handlers from PARENT_STATE. That mean BOT is in two states simultaneously PARENT_STATE and CHILD_STATE. For some reason PARENT_STATE has priority. But i need to CHILD_STATE has priority and checked first.
Yes i can place children_conv_handler in this example first on the list and get result which i want (trigger MessageHandler(filters.TEXT, fallback_message)), but what if i need two child_conv_handler1 and child_conv_handler2? In this case i don't know what to do. How make CHILD_STATE be the main state or how to put parent_conv_handler into some type of "dead end state" while child_conv_handler starts?
UPD1: Example with two child ConversationHandlers:
...
child_conv_handler1 = ConversationHandler(
entry_points=[CommandHandler("start_child1", start_child_func1)],
states={
CHILD_STATE1: [
CommandHandler("stats", child_stats1),
],
},
fallbacks=[MessageHandler(filters.TEXT, fallback_message),],
)
child_conv_handler2 = ConversationHandler(
entry_points=[CommandHandler("start_child2", start_child_func2)],
states={
CHILD_STATE2: [
CommandHandler("stats", child_stats2),
],
},
fallbacks=[MessageHandler(filters.TEXT, fallback_message),],
)
parent_conv_handler = ConversationHandler(
entry_points=[CommandHandler("start_parent", start_parent_func)],
states={
PARENT_STATE: [
CommandHandler("stats", parent_stats),
child_conv_handler1,
child_conv_handler2
],
},
fallbacks=[CommandHandler("stop", stop)],
)
application.add_handler(parent_conv_handler)
application.run_polling(allowed_updates=Update.ALL_TYPES)
Citing the docs of
ConversationHandler:Switching the order of the handlers in the
PARENT_STATEshould solve your issue.UPD1: There is no special handling for child conversations in how it is determined which handler will handle an update. So there is currently no built-in way to handle the situation with two child conversations. A workaround could be to put each child conversation in a different parent state or to combine both child conversations into one. I've added this to https://github.com/python-telegram-bot/python-telegram-bot/issues/2770
Disclaimer: I'm currently the maintainer of
python-telegram-bot