我正在尝试使用python-telegram-bot
包创建电报对话机器人,我想知道在对话中为每个州实施“返回主菜单”按钮的最佳做法是什么。
出于某种原因,我觉得我做错了。回到主菜单按钮实际上什么都不做,除了绘制主菜单按钮应该是立即的,但它通常需要0.5-3秒,有时甚至更长(一次只有一个用户与机器人交谈)。
我基本上都在使用CallbackQueryHandler(back_to_main_menu, pattern='^main_menu$')
,我很确定这不是正确的做法,尽管到目前为止找不到任何其他更好的解决方案。
注意:以下示例只是我如何使用CallbackQueryHandler
的一个小例子。我的状态机有13个状态,其中10个状态我回到主菜单按钮。
我需要的一个简短例子:
import os
from telegram.ext import Updater, ConversationHandler, CommandHandler, CallbackQueryHandler
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardRemove
FIRST, SECOND, MAIN_MENU = range(3)
def get_main_menu():
return [[InlineKeyboardButton("First", callback_data='first')],
[InlineKeyboardButton("Second", callback_data='second')]]
def add_main_menu_button(bot, update, message, menu):
query = update.callback_query
menu.append([InlineKeyboardButton("Back to main menu", callback_data="main_menu")])
reply_markup = InlineKeyboardMarkup(menu)
bot.edit_message_text(message, chat_id=query.message.chat_id, message_id=query.message.message_id,
reply_markup=reply_markup)
def back_to_main_menu(bot, update):
query = update.callback_query
reply_markup = InlineKeyboardMarkup(get_main_menu())
bot.edit_message_text("Example example 2", chat_id=query.message.chat_id, message_id=query.message.message_id, reply_markup=reply_markup)
return MAIN_MENU
def second(bot, update):
add_main_menu_button(bot, update, "E e", list())
def first(bot, update):
add_main_menu_button(bot, update, "T t", list())
def start(bot, update):
reply_markup = InlineKeyboardMarkup(get_main_menu())
update.message.reply_text("Example example 1", reply_markup=reply_markup)
return MAIN_MENU
def cancel(bot, update):
update.message.reply_text('Bye! I hope we can talk again some day.', reply_markup=ReplyKeyboardRemove())
return ConversationHandler.END
def main():
updater = Updater(os.environ["BOT_TOKEN"])
conversation_handler = ConversationHandler(entry_points=[CommandHandler('start', start)],
states={FIRST: [CallbackQueryHandler(back_to_main_menu, pattern='^main_menu$')],
SECOND: [CallbackQueryHandler(back_to_main_menu, pattern='^main_menu$')],
MAIN_MENU: [CallbackQueryHandler(first, pattern='first'),
CallbackQueryHandler(second)]},
fallbacks=[CommandHandler('cancel', cancel)],
allow_reentry=True
)
updater.dispatcher.add_handler(conversation_handler)
updater.start_polling()
updater.idle()
此外,当我在对话中使用多个CallbackQueryHandler时,我收到以下警告:
WARNING:root:If 'per_message=False', 'CallbackQueryHandler' will not be tracked for every message
这让我觉得我做错了什么。
感谢。
答案 0 :(得分:0)
对于每次对话,您只需指定一个CallbackQueryHandler
作为后备。例如:
START = range(1)
start_conv_handler = ConversationHandler(entry_points=[CommandHandler('start', start)],
states={
START: [CommandHandler('start', start)]
},
fallbacks= CallbackQueryHandler(main_callback_handler)]
)
然后在单个CallbackQueryHandler
内,您可以计划您希望按钮执行的所有必要操作。由于您可以向处理程序接收的查询添加所需的任何信息,因此可以通过将return CallbackQueryHandler
放在描述对话步骤的每个函数的末尾来进行更复杂的方案(start
在我的示例中)。
所以它看起来像:
def start(bot, update):
... your code here
return CallbackQueryHandler