I'm trying to create a telegram conversation bot using python-telegram-bot
package and I wondered what is the best practice for implementing a "back to main menu" button for each state in the conversation.
For some reason, I feels like i'm doing it the wrong way. The back to main menu button actually does nothing except to drawing the main menu buttons which should be immediate, but still it's usually takes 0.5-3 seconds and sometimes even longer (Only one user at a time talking to the bot).
I'm using CallbackQueryHandler(back_to_main_menu, pattern='^main_menu$')
for each state basically which I'm quite sure it's not the right way to do it although I couldn't find any other better solution so far.
Notice: the example below is just a little example of how I use the CallbackQueryHandler
. My state machine got 13 states, in 10 of them I got a back to main menu button.
A short example of what I need:
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()
In addition, when I use multiple CallbackQueryHandler in a conversation I get the following warning:
WARNING:root:If 'per_message=False', 'CallbackQueryHandler' will not be tracked for every message
which makes me think I'm doing something wrong.
Thanks.