callback in inline Keyboard
This commit is contained in:
parent
8b18cc444a
commit
621b3725d4
32
README.md
32
README.md
@ -558,3 +558,35 @@ async def on_user_shared(message: types.Message):
|
||||
|
||||
У колбэк-кнопок есть специальное значение **(data)**, по которому ваше приложение опознаёт, что нажато и что надо сделать. И выбор правильного data очень важен! Стоит также отметить, что, в отличие от обычных кнопок, нажатие на колбэк-кнопку позволяет сделать практически что угодно, от заказа пиццы до запуска вычислений на кластере суперкомпьютеров.
|
||||
|
||||
Сервер Telegram отправив нам кнопку callback ждет от нас подтверждения о доставке колбэка. Нам необходимо вызвать метод **answer()** в общем случае в него можем ничего не передавать, но можно вызвать специальное окошко (всплывающее сверху или поверх экрана):
|
||||
|
||||
```py
|
||||
@dp.callback_query(F.data == "random_value")
|
||||
async def send_random_value(callback: types.CallbackQuery):
|
||||
await callback.message.answer(str(randint(1, 10)))
|
||||
await callback.answer(
|
||||
text="Спасибо, что воспользовались ботом!",
|
||||
show_alert=True
|
||||
)
|
||||
# или просто await callback.answer()
|
||||
```
|
||||
> В функции send_random_value мы вызывали метод answer() не у message, а у callback.message. Это связано с тем, что колбэк-хэндлеры работают не с сообщениями (тип Message), а с колбэками (тип CallbackQuery), у которого другие поля, и само сообщение — всего лишь его часть. Учтите также, что message — это сообщение, к которому была прицеплена кнопка (т.е. отправитель такого сообщения — сам бот). Если хотите узнать, кто нажал на кнопку, смотрите поле from (в вашем коде это будет callback.from_user, т.к. слово from зарезервировано в Python)
|
||||
|
||||
Иногда пользователь, вызвав несколько раз сообщение с колбэками, может нажимать кнопки новых и старых сообщений и тогда может возникнуть ошибка, которую мы получим от Bot API, что старый и новый тексты совпадают, а бот словит исключение: ``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.
|
||||
|
||||
Ошибка MessageNotModified относится к категории Bad Request, поэтому у нас есть выбор: проигнорировать весь подобный класс ошибок, либо отловить весь класс BadRequest и попытаться по тексту ошибки опознать конкретную причину.
|
||||
|
||||
Чтобы игнорировать весь подобный класс обновим функцию ``update_num_text()``
|
||||
|
||||
```py
|
||||
# Новые импорты!
|
||||
from contextlib import suppress
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
|
||||
async def update_num_text(message: types.Message, new_value: int):
|
||||
with suppress(TelegramBadRequest):
|
||||
await message.edit_text(
|
||||
f"Укажите число: {new_value}",
|
||||
reply_markup=get_keyboard()
|
||||
)
|
||||
```
|
||||
|
73
bot2.py
73
bot2.py
@ -1,3 +1,4 @@
|
||||
from random import randint
|
||||
import re
|
||||
import asyncio
|
||||
import logging
|
||||
@ -10,6 +11,9 @@ from aiogram.client.default import DefaultBotProperties
|
||||
from aiogram.enums import ParseMode
|
||||
# новый импорт!
|
||||
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
||||
# Новые импорты!
|
||||
from contextlib import suppress
|
||||
from aiogram.exceptions import TelegramBadRequest
|
||||
|
||||
|
||||
from config_reader import config
|
||||
@ -128,6 +132,75 @@ async def handle_contact(message: types.Message):
|
||||
|
||||
# новый импорт
|
||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||
# Запускаем Callback - кнопка
|
||||
@dp.message(Command("random"))
|
||||
async def cmd_random(message: types.Message):
|
||||
builder = InlineKeyboardBuilder()
|
||||
builder.add(types.InlineKeyboardButton(
|
||||
text="Нажми меня",
|
||||
callback_data="random_value")
|
||||
)
|
||||
await message.answer(
|
||||
"Нажмите на кнопку, чтобы бот отправил число от 1 до 10",
|
||||
reply_markup=builder.as_markup()
|
||||
)
|
||||
# хэндлер обработки callback кнопки
|
||||
@dp.callback_query(F.data == "random_value")
|
||||
async def send_random_value(callback: types.CallbackQuery):
|
||||
await callback.message.answer(str(randint(1, 10)))
|
||||
# отправим всплывающее окно после результата
|
||||
await callback.answer(
|
||||
text="Спасибо, что воспользовались ботом!",
|
||||
show_alert=True
|
||||
)
|
||||
# или просто await callback.answer()
|
||||
|
||||
# Продолжим с колбэками
|
||||
# Здесь хранятся пользовательские данные.
|
||||
# Т.к. это словарь в памяти, то при перезапуске он очистится
|
||||
user_data = {}
|
||||
#сформируем инлайн-клавиатуру
|
||||
def get_keyboard():
|
||||
buttons = [
|
||||
[
|
||||
types.InlineKeyboardButton(text="-1", callback_data="num_decr"),
|
||||
types.InlineKeyboardButton(text="+1", callback_data="num_incr")
|
||||
],
|
||||
[types.InlineKeyboardButton(text="Подтвердить", callback_data="num_finish")]
|
||||
]
|
||||
keyboard = types.InlineKeyboardMarkup(inline_keyboard=buttons)
|
||||
return keyboard
|
||||
|
||||
# формируем сообщение с переменным аргументом
|
||||
async def update_num_text(message: types.Message, new_value: int):
|
||||
with suppress(TelegramBadRequest):
|
||||
await message.edit_text(
|
||||
f"Укажите число: {new_value}",
|
||||
reply_markup=get_keyboard()
|
||||
)
|
||||
|
||||
# запуск клавиатуры по команде /numbers
|
||||
@dp.message(Command("numbers"))
|
||||
async def cmd_numbers(message: types.Message):
|
||||
user_data[message.from_user.id] = 0
|
||||
await message.answer("Укажите число: 0", reply_markup=get_keyboard())
|
||||
|
||||
|
||||
@dp.callback_query(F.data.startswith("num_"))
|
||||
async def callbacks_num(callback: types.CallbackQuery):
|
||||
user_value = user_data.get(callback.from_user.id, 0)
|
||||
action = callback.data.split("_")[1]
|
||||
|
||||
if action == "incr":
|
||||
user_data[callback.from_user.id] = user_value+1
|
||||
await update_num_text(callback.message, user_value+1)
|
||||
elif action == "decr":
|
||||
user_data[callback.from_user.id] = user_value-1
|
||||
await update_num_text(callback.message, user_value-1)
|
||||
elif action == "finish":
|
||||
await callback.message.edit_text(f"Итого: {user_value}")
|
||||
|
||||
await callback.answer()
|
||||
|
||||
@dp.message(Command("inline_url"))
|
||||
async def cmd_inline_url(message: types.Message, bot: Bot):
|
||||
|
Loading…
x
Reference in New Issue
Block a user