Как изменять сообщение бота несколько раз подряд?

Я пытаюсь создать бота с использованием библиотеки pyTelegramBotAPI который при запуске бота выводила текст "x=0" с Inline кнопкой "+1", при нажатии которой тексте будет меняться на "x=1" и т.д. при дальнейших нажатиях.

Вот сам код:

import telebot
from telebot import types

bot = telebot.TeleBot("6967578479:AAHAq-E5xM7K96kYkkV---5BrOkH0yyX1bM")
x=0

@bot.message_handler(commands=['start'])
def start(message):
    keyboard = types.InlineKeyboardMarkup()
    button = types.InlineKeyboardButton(text="+1", callback_data="+1")
    keyboard.row(button)
    bot.send_message(message.chat.id, f"x={x}.", reply_markup=keyboard)

    @bot.callback_query_handler(func = lambda callback: True)
    def callback_messange(callback):
        if callback.data == "+1":
            x=+1
            bot.edit_message_text(chat_id=callback.message.chat.id,text= f"x={x}.",message_id=message.message_id+1,reply_markup=keyboard)

bot.infinity_polling()

Но при 2 нажатии выдает ошибку:

telebot.apihelper.ApiTelegramException: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: message is not modified: specified new message content and reply markup are exactly the same as a current content and reply markup of the message


Ответы (2 шт):

Автор решения: Amgarak

В общем, вы не правильно получаете id своего сообщения, отсюда и ошибки. Вот вам небольшой пример:

import telebot
from telebot import types

bot = telebot.TeleBot('TOKEN')

@bot.message_handler(commands=['start'])
def start(message):
    keyboard = types.InlineKeyboardMarkup(row_width=1)
    button = types.InlineKeyboardButton(text="Счет: 0", callback_data="increment")
    keyboard.add(button)
    bot.send_message(message.chat.id, 'Счет: 0', reply_markup=keyboard)

# Обработчик нажатия
@bot.callback_query_handler(func=lambda call: call.data == "increment")
def increment_callback(call):
    # Получаем текущее значение счетчика из текста калбэка
    count = int(call.message.text.split(":")[1].strip()) + 1
    keyboard = types.InlineKeyboardMarkup(row_width=1)
    button = types.InlineKeyboardButton(text=f"Счет: {count}", callback_data="increment")
    keyboard.add(button)
    # Изменяем текст существующего сообщения с обновленным счетчиком и кнопкой, но наверное лучше удалять и отправлять новое сообщение
    bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=f'Счет: {count}',
                          reply_markup=keyboard)

bot.polling()
→ Ссылка
Автор решения: mrBars1k

Ваша проблема была в том, что Вы не проверяли значение x. Вы объявили x в глобальной области видимости и при каждом нажатии кнопки, он возвращал своё значение на 0 и затем прибавлял 1.

А так, как он уже был равен 1, после первого нажатия кнопки, то бот пытается изменить сообщение x=1 на точно такое же - x=1, из-за этого и ошибка.

В данном способе, я указал x=0 просто первоначальной строкой, а затем при каждом нажатии кнопки, бот берёт значение из текста сообщения, находит там значение x, делает из него тип данных int и прибавляет к нему 1, а затем изменяет сообщение на прибавленное значение. И так после каждого нажатия кнопки.

! Важно: стоит написать свой алгоритм распознавания текущего значения x, после каждого нажатия кнопки. Мой способ лишь для примера, он ищет значение по разделению строки на список строк, если между частями есть знак равно (=).

Но если добавить туда текст, точку в конце или что-то ещё, всё сломается. Можете написать регулярное выражение или найти другой способ распознания.

Также, если x будет в глобальной области видимости, то это повлияет на всех пользователей бота сразу.

import telebot
from telebot import types

bot = telebot.TeleBot("TOKEN")

@bot.message_handler(commands=['start'])
def start(message):
    keyboard = types.InlineKeyboardMarkup()
    button1 = types.InlineKeyboardButton(text="-1", callback_data="-1")
    button2 = types.InlineKeyboardButton(text="+1", callback_data="+1")

    keyboard.row(button1, button2)

    bot.send_message(message.chat.id, f"x=0", reply_markup=keyboard)

    @bot.callback_query_handler(func = lambda callback: True)
    def callback_messange(callback):
        text = callback.message.text # текст сообщения, на котором нажата была кнопка;
        x_form = text.split("=") # разделяем строку на значения до и после знака равно и получаем формат: ['x', '0'];
        x_value = x_form[1] # обращаемся к второму элементу списка, где будет значение x;

        if callback.data == "+1":
            x = int(x_value) + 1 # делаем  строку значения числом и прибавляем 1;
            bot.edit_message_text(chat_id=callback.message.chat.id, message_id=callback.message.id, text= f"x={x}", reply_markup=keyboard)

        if callback.data == "-1":
            x = int(x_value) - 1 # делаем  строку значения числом и отнимаем 1;
            bot.edit_message_text(chat_id=callback.message.chat.id, message_id=callback.message.id, text= f"x={x}", reply_markup=keyboard)

bot.infinity_polling()

upd: заметил, что у Вы странно берёте id сообщения, решил поправить.

→ Ссылка