@Bober_IT

Не работают кнопки в тг боте на python как починить?

Добавил в бота миниигру "кубик", бот выводит сообщение с описанием игры, а под ним две кнопки. Сообщение вместе с кнопками выводится, но кнопки не реагируют на нажатие, в консоли ошибок нет. Если убрать функцию "list" расположенную почти в самом начале кода, то бот будет реагировать только на кнопку "да", на другую кнопку реакции не будет, так же как и на кнопки в последующем сообщении.
Функцию list я попробовал убрать т.к. в коде всего 3 функции имеют декоратор "callback_query_handler", это не посредственно она и еще 2 нижеуказанных функции.

@bot.callback_query_handler(func=lambda call: True)
def list(call):
    if call.data == 'users':
        conn = sqlite3.connect('Gok.sql')
        cur = conn.cursor()

        cur.execute('SELECT * FROM users')
        users = cur.fetchall()

        info = ''
        for el in users:
            info += f'Имя: {el[1]}, очки: {el[2]}\n'

        cur.close()
        conn.close()

        bot.send_message(call.message.chat.id, info)


@bot.message_handler(commands=['cube'])
def cube_game(message):
    markup = types.InlineKeyboardMarkup()
    YB = types.InlineKeyboardButton('Да', callback_data='go_play')
    NB = types.InlineKeyboardButton('Нет', callback_data='dont_play_cube')
    markup.row(YB, NB)

    bot.send_message(message.chat.id, 'Игра называется кубик, бот бросает кубик после чего'
                                      'выпадает случайное число от 1 до 6, дальше ход переходит вам, хотите сыграть?', reply_markup=markup)

@bot.callback_query_handler(func=lambda call: True)
def game_processing(call):
    if call.data == 'go_play':
        markup = types.InlineKeyboardMarkup()
        YB = types.InlineKeyboardButton('Бросить кубик', callback_data='go_play_next')
        NB = types.InlineKeyboardButton('Отказаться (минус 5 очков)', callback_data='dont_play_cube')
        markup.row(YB, NB)

        global b_cp
        b_cp = random.randint(1, 6)

        bot.send_message(call.message.chat.id, f'Очки бота: {b_cp}. Ваш ход:', reply_markup=markup)


@bot.callback_query_handler(func=lambda call: True)
def game_processing_next_step(call):
    if call.data == 'go_play_next':
        p_cp = random.randint(1, 6)
        bot.send_message(call.message.chat.id, f'Ваши очки: {p_cp}')
        if p_cp > b_cp:
            conn = sqlite3.connect('Gok.sql')
            cur = conn.cursor()

            cur.execute('UPDATE users SET point = point + ? where id = ?', (3, call.message.tfrom_user.id))
            conn.commit()
            cur.close()
            conn.close()

            bot.send_message(call.message.chat.id, 'Вы победили, вот ваши 3 заслуженных очка.')

        elif p_cp == b_cp:

            bot.send_message(call.message.chat.id, 'Ничья, вы получаете 0 очков.')

        else:
            conn = sqlite3.connect('Gok.sql')
            cur = conn.cursor()

            cur.execute('UPDATE users SET point = point - ? where id = ?', (5, call.message.from_user.id))
            conn.commit()
            cur.close()
            conn.close()

            bot.send_message(call.message.chat.id, 'Бот набрал больше очков, вы проиграли.')

    elif call.data == 'dont_play_cube':
        conn = sqlite3.connect('Gok.sql')
        cur = conn.cursor()

        cur.execute('UPDATE users SET point = point - ? where id = ?', (5, call.message.from_user.id))
        conn.commit()
        cur.close()
        conn.close()

        bot.send_message(call.message.chat.id, 'Ну что ж, сыграем в другой раз')

bot.polling(none_stop=True)
  • Вопрос задан
  • 141 просмотр
Решения вопроса 1
@twistfire92
Python backend developer
При любом событии (новое сообщение, нажатие на кнопку и пр.) бот проходит по всем хендлерам и смотрит какой хендлер удовлетворяет условиям. После того, как найден нужный - выполняет описанную в нем функцию.

А теперь смотрим:
1. Пользователь жмет кнопку
2. Побежали по нашим хендлерам. Видим первый с
@bot.callback_query_handler(func=lambda call: True)

что значит "при нажатии на ЛЮБУЮ inline кнопку"
3. Выполняем функцию которая в этом хендлере описана
4. Ожидаем новых событий.

В вашем случае на 3-м шаге выполнится функция list (кстати очень неудачное название, это зарезервированное имя, его лучше не использовать, почитайте про это)
если уберете ее, выполнится game_processing

Что делать?
вариант 1 - как подсказали в комментариях, делать однин хендлер и внутри описывать все сценарии
if call.data == 'users':
    ...
elif call.data == 'go_play':
    ....
elif call.data == 'go_play_next':
    ...


Вариант 2 (более правильный) - отфильтровывать call.data в хендлерах. Сейчас там лежит func=lambda call: True, т.е. функция, возвращающая ВСЕГДА True. нужно как-то ее видоизменить, чтобы возвращалось True только при необходимых значениях call.data. Например func=lambda call: call.data=="foo" отработает только тогда, когда в call.data будет значение "foo".

Дальше сами
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Vindicar
@Vindicar
RTFM!
Проблема, я полагаю, та же что и всегда - несколько обработчиков с func=lambda call: True.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы