@Armlet_abuse

Как досрочно выйти из состояния в aiogram с помощью инлайн кнопки?

Я пишу бота, начал юзать состояния. С помощью состояния Я ловлю почту пользователей и всё как бы круто, но есть проблемка, если пользователь передумал вводить емайл, я создал инлайн кнопку отмены, но она не работает, если например писать командой, то всё збс, но с помощью инлайна не работает, банально не читает колбек,может кто подсказать как должно это работать?
  • Вопрос задан
  • 1816 просмотров
Решения вопроса 1
@Khamzabek
Если вы используете состояния, то вы можете поместить все обработчики в состояния и при нажатии на кнопки вызывать переходы в другие состояния. Для реализации кнопки отмены можно создать отдельное состояние, которое будет обрабатывать команду отмены, и при ее вызове производить переход в это состояние.

Пример реализации:

```python
from aiogram.dispatcher.filters import Command
from aiogram.types import Message, CallbackQuery
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton

class Registration(StatesGroup):
email = State()
cancel = State()

async def start_handler(message: Message):
keyboard_markup = ReplyKeyboardMarkup(resize_keyboard=True, selective=True)
keyboard_markup.add(KeyboardButton(text='Отмена'))
await message.answer(text='Введите email:', reply_markup=keyboard_markup)
await Registration.email.set()

async def email_handler(message: Message, state: FSMContext):
email = message.text
await state.update_data(email=email) # сохраняем email в состоянии
await message.answer(f'Вы ввели email {email}')
keyboard_markup = InlineKeyboardMarkup()
keyboard_markup.add(InlineKeyboardButton('Отмена', callback_data='cancel'))
await message.answer(text='Вы хотите сохранить email?', reply_markup=keyboard_markup)
await Registration.next() # переходим в следующее состояние

async def cancel_handler(callback_query: CallbackQuery, state: FSMContext):
await state.reset_state() # очищаем все состояния
await callback_query.answer(text='Отменено') # отправляем ответ пользователю
await callback_query.message.delete_reply_markup() # удаляем клавиатуру

async def save_handler(callback_query: CallbackQuery, state: FSMContext):
data = await state.get_data() # получаем данные из состояния
# сохраняем email в базу данных или выполняем другие действия
await callback_query.answer(text='Email сохранен')
await callback_query.message.delete_reply_markup() # удаляем клавиатуру
await state.finish() # завершаем состояние

# добавляем обработчики состояний
dp.register_message_handler(start_handler, commands='register')
dp.register_message_handler(email_handler, state=Registration.email, content_types=types.ContentTypes.TEXT)
dp.register_callback_query_handler(cancel_handler, state=Registration.cancel, text='cancel')
dp.register_callback_query_handler(save_handler, state=Registration.email, text='Да')

```

В примере мы добавляем два состояния: `email` и `cancel`, а также три обработчика событий:
- `start_handler` - начало регистрации, при вызове этой команды мы переходим в состояние `email` и выводим клавиатуру с кнопкой "Отмена".
- `email_handler` - обработчик ввода email, сохраняет email в состояние и переходит в состояние `cancel`. В этом состоянии мы выводим кнопку "Отмена" и кнопку "Да" для сохранения email.
- `cancel_handler` - обработчик кнопки "Отмена", удаляет клавиатуру и очищает все состояния.
- `save_handler` - обработчик кнопки "Да", сохраняет email и завершает состояние.

Кнопка "Отмена" вводится в ReplyKeyboardMarkup в обработчике `start_handler`. Кнопка "Отмена" в InlineKeyboardMarkup вводится в обработчике `email_handler`.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@ArchieWh1te
Python dev, Web dev
Выход из состояния FSM по инлаин кнопке
Для AioGram 2
@dp.callback_query_handler(text='quit', state=[ТУТ_ВАШИ_СТЕЙТЫ])
async def quit(call: types.CallbackQuery, state: FSMContext):
    await state.finish() # Останавливаем стейт
    await call.message.delete() # Удаляем прошлое сообщение
    await call.message.answer('❌Отправка отменена') # Вывод сообщения "Отправка отменена"


Для AioGram 3
@router.callback_query(F.data.startswith('quit')) # Стейты не передаются
async def quit(call: CallbackQuery, state: FSMContext):
    await state.clear() # Вместо finish используется clear
    await call.message.delete() # Удаляем прошлое сообщение
    await call.message.answer('❌Отправка отменена') # Вывод сообщения "Отправка отменена"
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы