• Как сделать машину состояний aiogram на множество событий?

    @filippovI Автор вопроса
    В общем, обошелся с FSM только для запроса начальных данных.
    Дальше исходя из этих данных формируем нужные нам списки в функции стэйта, в ней же посылаем первый вопрос и дальше обрабатываем ответы в пустом хендлере, который читает все сообщения, отправленные боту.

    Вот примерная реализация
    @dp.message(Command("start"))
    async def start(message: types.Message, state: FSMContext):
        await state.set_state(Start.start_name)
        await bot.send_message(message.from_user.id,
                               text='Можно выбрать один материк или перечислить несколько через пробел:\n'
                                    '1 - Европа\n'
                                    '2 - Азия\n'
                                    '3 - Африка\n'
                                    '4 - Северная Америка\n'
                                    '5 - Южная Америка\n'
                                    '6 - Австралия\n')
    
    
    @dp.message(Start.start_name)
    async def test(message: types.Message, state: FSMContext):
        await state.update_data(name=message.text)
        data = await state.get_data()
        
        # Создаем словарь перемешанных вопросов и ответов
        cities: dict = {}
    
        # Список вариантов материков
        data_list: list = [i for i in data["name"].strip(' ').split(' ') if i]
        
        # Исходя из списка вариантов и основного словаря со столицами CD обновляем cities
        for i in data_list:
            cities.update(CD[int(i)])
            
        # Разбиваем на словари вопросов и ответов для записи в БД
        questions_list, answers_list = list(shuffle_dict(cities))
        
        # Записываем в БД (создаем нового юзера, если нет. Создаем под него вопросы и ответы, если нет. Иначе обновляем)
        await db.insert('users', [message.from_user.id, message.from_user.username, 1])
        await db.insert('questions', [message.from_user.id, ', '.join(questions_list), ', '.join(answers_list), 0])
        
        # Отправляем первый вопрос. Завершаем стейт
        await bot.send_message(message.from_user.id, await db.select_question(message.from_user.id))
        await state.clear()
    
    
    @dp.message()
    async def test1(message: types.Message):
    
        # Проверяем, что пользователь играет (флажок in_game из БД)
        if await db.select_in_game(message.from_user.id) == 1:
    
            # Если его ответ совпал с ответом из БД, то:
            # 1. Увеличиваем счетчик вопросов в БД на 1
            # 2. Отправляем следующий вопрос, исходя из счетчика
            if message.text == await db.select_answer(message.from_user.id):
                await db.update_question_number(message.from_user.id)
                await bot.send_message(message.from_user.id, await db.select_question(message.from_user.id))
    
            # Если его ответ = 1, то:
            # 1. Отправляем правильный ответ
            # 2. Увеличиваем счетчик вопросов в БД на 1
            # 3. Отправляем следующий вопрос
            if message.text == '1':
                await bot.send_message(message.from_user.id, await db.select_answer(message.from_user.id))
                await db.update_question_number(message.from_user.id)
                await bot.send_message(message.from_user.id, await db.select_question(message.from_user.id))
    
            # Если его ответ = 0, то:
            # 1. Завершаем игру. Чистим все нужные строки в БД.
            # 2. Отправляем сообщение о завершении
            if message.text == '0':
                await db.the_end(message.from_user.id)
                await bot.send_message(message.from_user.id, 'Завершено')
    Ответ написан
    Комментировать