使用python-telegram-bot构建菜单的正确方法 [英] Proper way to build menus with python-telegram-bot
问题描述
我使用python-telegram-bot
并尝试像BotFather bot一样构建嵌套菜单系统.例如,您有一个常规的bot菜单
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))
此代码有效,但我感觉这是不合理的-构建一棵长的elif
树.
This code works but I have a feeling that it is kind of irrational — to build a long elif
tree.
此外,我不知道如何为用户提供从第二级菜单返回主菜单的选项(因为主菜单位于另一个处理程序中,并且我无法通过回调来捕获它)来自CallbackQueryHandler
).
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?
推荐答案
您应在CallbackQueryHandler
中使用参数pattern
.将类或函数用于键盘和消息也是一件好事.
要返回主菜单,请使用特定的回调模式将返回按钮添加到子菜单.
You should use an argument pattern
in CallbackQueryHandler
. 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.
请注意:您在菜单中使用edit_message_text
.这意味着如果您从任意菜单中使用reply_text
方法调用start
函数,则不会发生任何事情.
Please note: you use edit_message_text
in menu. It's mean nothing will happen if you will call start
function with reply_text
method from any menu.
具有功能的完整工作示例:
Full working example with functions:
#!/usr/bin/python3
from telegram.ext import Updater
from telegram.ext import CommandHandler, CallbackQueryHandler
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
############################### Bot ############################################
def start(bot, update):
update.message.reply_text(main_menu_message(),
reply_markup=main_menu_keyboard())
def main_menu(bot, update):
query = update.callback_query
bot.edit_message_text(chat_id=query.message.chat_id,
message_id=query.message.message_id,
text=main_menu_message(),
reply_markup=main_menu_keyboard())
def first_menu(bot, update):
query = update.callback_query
bot.edit_message_text(chat_id=query.message.chat_id,
message_id=query.message.message_id,
text=first_menu_message(),
reply_markup=first_menu_keyboard())
def second_menu(bot, update):
query = update.callback_query
bot.edit_message_text(chat_id=query.message.chat_id,
message_id=query.message.message_id,
text=second_menu_message(),
reply_markup=second_menu_keyboard())
# and so on for every callback_data option
def first_submenu(bot, update):
pass
def second_submenu(bot, update):
pass
############################ Keyboards #########################################
def main_menu_keyboard():
keyboard = [[InlineKeyboardButton('Option 1', callback_data='m1')],
[InlineKeyboardButton('Option 2', callback_data='m2')],
[InlineKeyboardButton('Option 3', callback_data='m3')]]
return InlineKeyboardMarkup(keyboard)
def first_menu_keyboard():
keyboard = [[InlineKeyboardButton('Submenu 1-1', callback_data='m1_1')],
[InlineKeyboardButton('Submenu 1-2', callback_data='m1_2')],
[InlineKeyboardButton('Main menu', callback_data='main')]]
return InlineKeyboardMarkup(keyboard)
def second_menu_keyboard():
keyboard = [[InlineKeyboardButton('Submenu 2-1', callback_data='m2_1')],
[InlineKeyboardButton('Submenu 2-2', callback_data='m2_2')],
[InlineKeyboardButton('Main menu', callback_data='main')]]
return InlineKeyboardMarkup(keyboard)
############################# Messages #########################################
def main_menu_message():
return 'Choose the option in main menu:'
def first_menu_message():
return 'Choose the submenu in first menu:'
def second_menu_message():
return 'Choose the submenu in second menu:'
############################# Handlers #########################################
updater = Updater('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(main_menu, pattern='main'))
updater.dispatcher.add_handler(CallbackQueryHandler(first_menu, pattern='m1'))
updater.dispatcher.add_handler(CallbackQueryHandler(second_menu, pattern='m2'))
updater.dispatcher.add_handler(CallbackQueryHandler(first_submenu,
pattern='m1_1'))
updater.dispatcher.add_handler(CallbackQueryHandler(second_submenu,
pattern='m2_1'))
updater.start_polling()
################################################################################
对不起,我在标签中有两个空格. :)
Sorry, i have two spaces in tab. :)
这篇关于使用python-telegram-bot构建菜单的正确方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!