@k0sat1k

Callback-кнопка в модуле telebot (язык python) не обновляет свое содержание. Что делать?

Содержание Callback-кнопки не меняется после первого раза. То есть, если первое сообщение - слово "кот", то разбор будет выполняться только для него. Если дальше вводить сообщения, то кнопка будет все равно выводить разбор изначального слова (например слова "кот").
@bot.message_handler(func=lambda message: True)
def sayanswer(message):
	url = "https://wikislovo.ru/morphology/" + message.text
	echo_all(message)
	kb = types.InlineKeyboardMarkup(row_width=1)
	btn1 = types.InlineKeyboardButton(text="морфологический разбор", callback_data="btn1")
	kb.add(btn1)
	bot.send_message(message.chat.id, "какой разбор сделать?", reply_markup=kb)

	@bot.callback_query_handler(func=lambda callback: callback.data)
	def check(callback):
		if callback.data == "btn1":
			html = requests.get(url).text
			soup = BeautifulSoup(html, 'html.parser')
			find_text = soup.find('div', class_="morphology-analysis").get_text()
			bot.send_message(callback.message.chat.id, find_text)
  • Вопрос задан
  • 1390 просмотров
Пригласить эксперта
Ответы на вопрос 2
RimMirK
@RimMirK
Вроде человек. Вроде учусь. Вроде пайтону
можно просто в колбек кнопки записывать слово
@bot.message_handler(func=lambda message: True)
def sayanswer(message):
    kb = types.InlineKeyboardMarkup(row_width=1)
    btn1 = types.InlineKeyboardButton(text="морфологический разбор", callback_data=f"morphological | {message.text}")
    kb.add(btn1)
    bot.send_message(message.chat.id, "какой разбор сделать?", reply_markup=kb)

а в обработчике уже парсить сайт
@bot.callback_query_handler(func=lambda callback: callback.data)
def check(callback):
    if "morphological" in callback.data:
        url = "https://wikislovo.ru/morphology/" + callback.data.split(' | ')[1:]
        html = requests.get(url).text
        soup = BeautifulSoup(html, 'html.parser')
        find_text = soup.find('div', class_="morphology-analysis").get_text()
        bot.send_message(callback.message.chat.id, find_text)
Ответ написан
shurshur
@shurshur
Сисадмин, просто сисадмин...
Потому что при каждом вызове sayanswer будет создаваться новый обработчик callback_query_handler(func=lambda callback: callback.data), добавляясь к списку уже имеющихся. И естественно, что тот, который "застолбил" позицию первым, будет вызываться до скончания жизни запущенного бота. И естественно, что в нём значение url будет таким, каким было при первом запуске sayanswer.

Главная ошибка тут в том, что НЕЛЬЗЯ внутри функции объявлять другие функции, не понимая чётко, зачем это нужно. Иногда так делают для решения конкретных задач. Но в данном случае это совершенно не нужно и создаёт незапланированное поведение. Функцию check выносим на уровень выше. И не используем в ней переменные из функции sayanswer. Если нужно что-то передать в check - передаём через callback_data.

Например, можно передать "btn1:кот". В check использовать декоратор с фильтром func=lambda callback: callback.data.startswith("btn1:"). В самой функции откусывать btn1: от начала и уже только тогда формировать запрос к внешнему сервису.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы
CTRL+ Москва
от 250 000 до 320 000 ₽
CTRL+ Москва
от 200 000 до 300 000 ₽
CTRL+ Белград
от 250 000 до 320 000 ₽
22 нояб. 2024, в 00:55
500 руб./за проект
21 нояб. 2024, в 23:30
300000 руб./за проект
21 нояб. 2024, в 22:21
3000 руб./в час