Как правильно создать глобальные inline кнопки отмены и подтверждения?

Рейтинг: -1Ответов: 1Опубликовано: 14.08.2023
check = [
[InlineKeyboardButton(text="Подтвердить ✅", callback_data="approved"),
InlineKeyboardButton(text="Отменить и заполнить заново ❌", callback_data="cancel")]
]

check_button = InlineKeyboardMarkup(inline_keyboard=check, resize_keyboard=True)

Как я это вижу: У нас есть некая форма через fsm, в конце необходимо либо подтвердить и сохранить, либо заново заполнить форму.

Однако я не могу найти как это правильно написать

    @dp.message_handler(state=AdminSettings.type_food)
async def type_food(message: types.Message, state: FSMContext):
    await state.update_data(type_food=message.text)
    data = await state.get_data()
    await message.answer(f'Количество компьютеров: {data["num_pc"]}. \n Количество плэйстейш: {data["num_ps"]}. \n Количество типов еды: {data["num_food"]}. \n Наименования еды через пробелы: {data["type_food"]}.')
    await bot.send_message(chat_id=message.from_user.id, text='Подтвердите настройку вашего клуба.', reply_markup=check_button)
    if types.CallbackQuery.data == "approved":
        logging.info("Записывем в бд")
        state.finish
    elif types.CallbackQuery.data == "cancel":
        message.answer(f'Отменено пользователем. Заполним заново.')
        state.reset_data()
        AdminSettings.num_pc.set()

Ответы

▲ 0Принят

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

@dp.callback_query_handler(text="approved", state=AdminSettings.type_food)#или другое состояние, в общем, то, из которого должно происходить подтверждение
    async def accept_func(callback: types.CallbackQuery, state: FSMContext):
        #тут ваша логика
        await callback.answer()

и аналогично вторую кнопку

@dp.callback_query_handler(text="cancel", state=AdminSettings.type_food)#или другое состояние, в общем, то, из которого должно происходить подтверждение
    async def cancel_func(callback: types.CallbackQuery, state: FSMContext):
        #тут ваша логика
        await callback.answer()

При этом клавиатуру с кнопками вы отправляете из другой функции. Например, как ответ на ввод последнего поля анкеты.

Разумеется, в каждой из кнопок необходимо либо совершить переход на предыдущие состояния, либо завершать выполнение машины состояний. Вы можете делать это либо через метод set(), либо через метод finish() вашего экземпляра класса машины состояний. Если вам нужна универсальная функция выхода из машины состояний (завершения любого ввода), можете воспользоваться подобной конструкцией, в примере отменяет ввод при вводе слова "отмена" в чат, можете модифицировать его под ваши задачи:

@dp.message_handler(state="*", commands="отмена")
@dp.message_handler(Text(equals="отмена", ignore_case=True), state="*")
async def cancel_handler(message: types.Message, state: FSMContext):
    current_state= await state.get_state()
    if current_state is None:
        return
    await state.finish()