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:
(attention!)
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
:
The first handler whose check_update() method returns True will be used.
Switching the order of the handlers in the PARENT_STATE
should 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