I work with python-telegram-bot
and try to build a system of nested menus as BotFather bot does. For instance, you have a general bot menu
where you can choose "Edit Bot" and get the new corresponding menu
with an option to get back to the previous menu.
I try to achieve that with code:
# main menu
def start(bot, update):
menu_main = [[InlineKeyboardButton('Option 1', callback_data='m1')],
[InlineKeyboardButton('Option 2', callback_data='m2')],
[InlineKeyboardButton('Option 3', callback_data='m3')]]
reply_markup = InlineKeyboardMarkup(menu_main)
update.message.reply_text('Choose the option:', reply_markup=reply_markup)
# all other menus
def menu_actions(bot, update):
query = update.callback_query
if query.data == 'm1':
# first submenu
menu_1 = [[InlineKeyboardButton('Submenu 1-1', callback_data='m1_1')],
[InlineKeyboardButton('Submenu 1-2', callback_data='m1_2')]]
reply_markup = InlineKeyboardMarkup(menu_1)
bot.edit_message_text(chat_id=query.message.chat_id,
message_id=query.message.message_id,
text='Choose the option:',
reply_markup=reply_markup)
elif query.data == 'm2':
# second submenu
# first submenu
menu_2 = [[InlineKeyboardButton('Submenu 2-1', callback_data='m2_1')],
[InlineKeyboardButton('Submenu 2-2', callback_data='m2_2')]]
reply_markup = InlineKeyboardMarkup(menu_2)
bot.edit_message_text(chat_id=query.message.chat_id,
message_id=query.message.message_id,
text='Choose the option:',
reply_markup=reply_markup)
elif query.data == 'm1_1':
...
elif query.data == 'm1_2':
...
# and so on for every callback_data option
...
# handlers
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(CallbackQueryHandler(menu_actions))
This code works but I have a feeling that it is kind of irrational — to build a long elif
tree.
Moreover, I can't figure out how to give to the user an option to get back to the main menu from second level menus (since the main menu is located in another handler and I can't catch it with a callback from CallbackQueryHandler
).
So the question is — what is the best practice to build that kind of menu systems?
You should use an argument
pattern
inCallbackQueryHandler
. Also is a good thing use a classes or functions for keyboards and messages.To return to main menu add return button to submenu with specific callback pattern.
Please note: you use
edit_message_text
in menu. It's mean nothing will happen if you will callstart
function withreply_text
method from any menu.Full working example with functions:
Sorry, i have two spaces in tab. :)