电报会话机器人中后退按钮实现的最佳实践

时间:2018-04-22 23:24:35

标签: python telegram telegram-bot python-telegram-bot

我正在尝试使用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

这让我觉得我做错了什么。

感谢。

1 个答案:

答案 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