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 очень важен! Стоит также отметить, что, в отличие от обычных кнопок, нажатие на колбэк-кнопку позволяет сделать практически что угодно, от заказа пиццы до запуска вычислений на кластере суперкомпьютеров.
|
У колбэк-кнопок есть специальное значение **(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 re
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
@ -10,6 +11,9 @@ from aiogram.client.default import DefaultBotProperties
|
|||||||
from aiogram.enums import ParseMode
|
from aiogram.enums import ParseMode
|
||||||
# новый импорт!
|
# новый импорт!
|
||||||
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
||||||
|
# Новые импорты!
|
||||||
|
from contextlib import suppress
|
||||||
|
from aiogram.exceptions import TelegramBadRequest
|
||||||
|
|
||||||
|
|
||||||
from config_reader import config
|
from config_reader import config
|
||||||
@ -128,6 +132,75 @@ async def handle_contact(message: types.Message):
|
|||||||
|
|
||||||
# новый импорт
|
# новый импорт
|
||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
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"))
|
@dp.message(Command("inline_url"))
|
||||||
async def cmd_inline_url(message: types.Message, bot: Bot):
|
async def cmd_inline_url(message: types.Message, bot: Bot):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user