@Fan_Tom_97

Как правильно написать многоуровневое меню для телеграмм бота в библиотеке telebot?

Есть вот такой код для каталога кроссовок. Мне нужно было сделать многоуровневое меню с кнопками возврата назад и в главное меню. Все работает, но думаю, что неправильно писать в одной функции около 30 if, боту нужно проверить все условия по порядку (бот частенько лагает, хотя деплой на beget, вроде хвалят его). Я решил распределить все ифы на отдельные функции, каждая из которых будет представлять из себя отдельные подменю. Но так почему-то ничего не работает, переменная call не читается из других функций, только из первой, возможно нужно сделать call глобальной переменной, или как-то по другому обращаться к callback_data из других функций, пока не нашел решения. Подскажите, пожалуйста, как лучше поступить?

import telebot
from telebot import types

token = '................................'  
bot = telebot.TeleBot(token)


@bot.message_handler(commands=['start'])

# ГЛАВНОЕ МЕНЮ
def main(message):

    st_menu = types.InlineKeyboardMarkup()

    btn1 = types.InlineKeyboardButton('Каталог', callback_data='catalog')
    st_menu.row(btn1)
    btn2 = types.InlineKeyboardButton('Частые вопросы', callback_data='questions')
    st_menu.row(btn2)
    
    bot.send_message(message.chat.id, "..................", reply_markup = st_menu)



@bot.callback_query_handler(func=lambda call: True)

# ОБРАБОТКА КНОПОК ГЛАВНОГО МЕНЮ
def call_start_menu(call):

    # КАТАЛОГ
    if call.data == 'catalog':

        cat_menu = types.InlineKeyboardMarkup()

        btn1 = types.InlineKeyboardButton('Товар 1', callback_data='01')
        btn2 = types.InlineKeyboardButton('Товар 2', callback_data='02')
        cat_menu.row(btn1, btn2)

        btn3 = types.InlineKeyboardButton('В главное меню', callback_data='home')
        cat_menu.row(btn3)

        bot.send_message(call.message.chat.id, 'Выбери мужские или женские:', reply_markup=cat_menu)

    # ЧАСТЫЕ ВОПРОСЫ
    if call.data == 'questions':

        quest_menu = types.InlineKeyboardMarkup()

        btn1 = types.InlineKeyboardButton('............', callback_data='quest1')
        btn2 = types.InlineKeyboardButton('..........', callback_data='quest2')
        quest_menu.row(btn1, btn2)

        btn5 = types.InlineKeyboardButton('В главное меню', callback_data='home')
        quest_menu.row(btn5)


        bot.send_message(call.message.chat.id, 'Выбери вопрос:', reply_markup=quest_menu)


# ОБРАБОТКА КНОПОК ЧАСТЫХ ВОПРОСОВ
def call_quest_menu(call):

    # Вопрос 1
    if call.data == 'quest1':

        dely_quest = types.InlineKeyboardMarkup()

        btn1 = types.InlineKeyboardButton('↩️Назад', callback_data='questions')
        btn2 = types.InlineKeyboardButton('Главное меню', callback_data='home')
        dely_quest.row(btn1, btn2)

        bot.send_message(call.message.chat.id, '......................', reply_markup=dely_quest)

    # Вопрос 2
    if call.data == 'quest2':
        pass


# ОБРАБОТКА КНОПОК КАТАЛОГА
def call_cat_menu(call):

    # Товар 1
    if call.data == '01':

        cat = types.InlineKeyboardMarkup()

        btn1 = types.InlineKeyboardButton('↩️Назад', callback_data='catalog')
        btn2 = types.InlineKeyboardButton('Главное меню', callback_data='home' )
        cat.row(btn1, btn2)

        bot.send_message(call.message.chat.id, '...........',  reply_markup=men_cat)

    # Товар 2
    if call.data == '02':
        pass


# ВОЗВРАТ В ГЛАВНОЕ МЕНЮ
def back_start_menu(call):

    if call.data == 'home':
        main(call.message)


bot.polling(none_stop=True)


А изначально было вот так и все работало:
..................................................................................
@bot.callback_query_handler(func=lambda call: True)
# ОБРАБОТКА КНОПОК
def call_start_menu(call):
    # КАТАЛОГ
    if call.data == 'catalog':
        cat_menu = types.InlineKeyboardMarkup()
        btn1 = types.InlineKeyboardButton('Товар 1', callback_data='01')
        btn2 = types.InlineKeyboardButton('Товар 2', callback_data='02')
        cat_menu.row(btn1, btn2)
        btn3 = types.InlineKeyboardButton('В главное меню', callback_data='home')
        cat_menu.row(btn3)
        bot.send_message(call.message.chat.id, 'Выбери мужские или женские:', reply_markup=cat_menu)
    # ЧАСТЫЕ ВОПРОСЫ
    if call.data == 'questions':
        quest_menu = types.InlineKeyboardMarkup()
        btn1 = types.InlineKeyboardButton('............', callback_data='quest1')
        btn2 = types.InlineKeyboardButton('..........', callback_data='quest2')
        quest_menu.row(btn1, btn2)
        btn5 = types.InlineKeyboardButton('В главное меню', callback_data='home')
        quest_menu.row(btn5)
        bot.send_message(call.message.chat.id, 'Выбери вопрос:', reply_markup=quest_menu)
    # Вопрос 1
    if call.data == 'quest1':
        dely_quest = types.InlineKeyboardMarkup()
        btn1 = types.InlineKeyboardButton('↩️Назад', callback_data='questions')
        btn2 = types.InlineKeyboardButton('Главное меню', callback_data='home')
        dely_quest.row(btn1, btn2)
        bot.send_message(call.message.chat.id, '......................', reply_markup=dely_quest)
    # Вопрос 2
    if call.data == 'quest2':
        pass
    # Товар 1
    if call.data == '01':
        pass
    # Товар 2
    if call.data == '02':
        pass
    # ВОЗВРАТ В ГЛАВНОЕ МЕНЮ
    if call.data == 'home':
        main(call.message)

bot.polling(none_stop=True)
  • Вопрос задан
  • 51 просмотр
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Ну первое, что я замечу: в коде только call_start_menu() помечена как обработчик событий от кнопок, потому что только перед ней стоит декоратор callback_query_handler.
Советую ознакомиться с документацией и примерами, чтобы понять, как регистрируются обработчики.
А заодно (поскольку это будет ваш следующий вопрос) понять, что такое func= и для чего оно нужно.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@TastyTea
Советую вынести все меню в отдельный файл, а лучше в конфигурационный файл. Станет сразу более читабельно и удобно в редактировании.
Также советую для каждого меню сделать свою функцию с калбеком.
Ещё не забудьте весь повторяющийся код в отдельную функцию, будет удобнее писать, да и читать в дальнейшем.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы