对话状态的双重性。如何强制bot仅在子ConversationHandler中检查更新?

0 投票
1 回答
66 浏览
提问于 2025-04-14 16:44

我在使用ConversationHandler的时候遇到了一些问题,可能是因为我对它的用法理解得不太透彻。我在PTB中使用父子ConversationHandlers,具体是这样:

...
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)

我进行的操作如下:

  1. 发送了/start_parent来启动父ConversationHandler;
  2. start_parent_func这个回调函数返回了对话状态PARENT_STATE;
  3. 发送了/start_child来启动子ConversationHandler;
  4. start_child_func这个回调函数返回了对话状态CHILD_STATE;

(注意!)

  1. 发送了/stats命令,CommandHandler("stats", stats)被触发(stats回调函数正常工作!)。

看起来所有的更新首先都是由PARENT_STATE的处理器来检查。这意味着机器人同时处于两个状态:PARENT_STATE和CHILD_STATE。出于某种原因,PARENT_STATE的优先级更高。但我希望CHILD_STATE的优先级更高,能够先被检查。

是的,我可以把children_conv_handler放在列表的最前面,这样就能得到我想要的结果(触发MessageHandler(filters.TEXT, fallback_message)),但如果我需要两个子处理器child_conv_handler1和child_conv_handler2呢?在这种情况下,我不知道该怎么做。如何让CHILD_STATE成为主要状态,或者如何让parent_conv_handler进入某种“死胡同状态”,以便子处理器可以启动?

更新1: 这是一个包含两个子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)

1 个回答

0

根据ConversationHandler的文档

第一个返回True的处理器的check_update()方法将会被使用。

调整一下中处理器的顺序应该能解决你的问题。

更新1:在确定哪个处理器来处理更新时,并没有特别处理子对话。所以目前没有内置的方法来处理有两个子对话的情况。一个解决办法是把每个子对话放在不同的父状态中,或者把两个子对话合并成一个。我已经把这个问题添加到https://github.com/python-telegram-bot/python-telegram-bot/issues/2770上。


免责声明:我目前是python-telegram-bot的维护者。

撰写回答