Как сделать ветвление в aiogram FSM в зависимости от ответа?

Рейтинг: 0Ответов: 2Опубликовано: 19.01.2023

Есть код бота aoigram, FSM работает отлично, но вот появилась задача, сделать логику в зависимости от ответа пользователя.

class FSMHelp(StatesGroup):
    state1 = State()
    state2 = State()
    state3 = State()
    state4 = State()


async def cm_start(message: types.Message):
    await FSMHelp.state1.set()
    await message.reply('Выберите тип', reply_markup=but.buttons2)


async def load_state1(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['state1'] = message.text
    await FSMHelp.next()
    await message.reply('Укажите документ', reply_markup=but.cancel_btn)


async def load_state2(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data ['state2'] = message.text
    await FSMHelp.next()
    await message.reply('Название организации', reply_markup=but.cancel_btn)


async def load_state3(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['state3'] = message.text
    await FSMHelp.next()
    await message.reply('Контактное лицо', reply_markup=but.cancel_btn)


async def load_state4(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data ['state4'] = message.text
    await message.reply(answer, reply_markup=but.buttons)
    await state.finish()



def register_message_order(dp : Dispatcher):
    dp.register_message_handler(cm_start, regexp='.*заявка', state=None)
    dp.register_message_handler(load_state1, state=FSMHelp.state1)
    dp.register_message_handler(load_state2, state=FSMHelp.state2)
    dp.register_message_handler(load_state3, state=FSMHelp.state3)
    dp.register_message_handler(load_state4, state=FSMHelp.state4)

Как сделать, чтобы при вводе в state1 "нет", пропускать ввод state2? А если было да, то выполнять всё...

Ответы

▲ 0Принят

Не знаю, лучше это или нет, но я вообще перестал использовать StatesGroup-ы.

Для меня намного удобнее выбирать state через строку - await state.set_state('name-of-state'), после чего отлавливать по этой строке в хендлере - dp.register_message_handler(handler, state='name-of-state'.

Думаю, в вашем случае так будет сделать проще и удобнее. Пример кода:

async def action_one(message: types.Message, state: FSMContext):

    await state.set_state('next_state')
    ...


async def action_two(message: types.Message, state: FSMContext):

    await state.finish()
    ...

dp.register_message_handler(action_one)
dp.register_message_handler(action_two, state='next_state')

При смене state через set_state данные стейта не пропадают.

▲ 0

Вроде разобрался, а может и нет, но всё равно работает как я хотел:

class FSMHelp(StatesGroup):
    state1 = State()
    state2 = State()
    state3 = State()
    state4 = State()


async def cm_start(message: types.Message):
    await FSMHelp.state1.set()
    await message.reply('Выберите тип', reply_markup=but.buttons2)


async def load_state1_yes(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['state1'] = message.text
    await FSMHelp.next()
    await message.reply('Укажите документ', reply_markup=but.cancel_btn)


async def load_state1_no(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['state1'] = message.text
    async with state.proxy() as data:
        data ['state2'] = 'нет'
    await message.reply('Название организации', reply_markup=but.cancel_btn)
    await state.set_state(FSMHelp.state3)


async def load_state2(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data ['state2'] = message.text
    await FSMHelp.next()
    await message.reply('Название организации', reply_markup=but.cancel_btn)


async def load_state3(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['state3'] = message.text
    await FSMHelp.next()
    await message.reply('Контактное лицо', reply_markup=but.cancel_btn)


async def load_state4(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data ['state4'] = message.text
    await message.reply(answer, reply_markup=but.buttons)
    await state.finish()



def register_message_order(dp : Dispatcher):
    dp.register_message_handler(cm_start, regexp='.*заявка', state=None)
    dp.register_message_handler(load_state1_yes, (lambda message: message.text == 'Yes'), state=FSMHelp.state1)
    dp.register_message_handler(load_state1_no, (lambda message: message.text == 'No'), state=FSMHelp.state1)
    dp.register_message_handler(load_state2, state=FSMHelp.state2)
    dp.register_message_handler(load_state3, state=FSMHelp.state3)
    dp.register_message_handler(load_state4, state=FSMHelp.state4)

Может кто-то проверить насколько правильно я сделал?