В aiogram 3 произошли некоторые изменения, касающиеся работы с состояниями и диспетчером. В частности, для работы с состояниями теперь используется более удобный способ организации с помощью `FSMContext` и состояния, определяемые через класс, а также изменения в синтаксисе и уровне абстракции.
### Изменения в aiogram 3:
1. **Работа с состояниями:** Теперь состояния определяются как классы, используя `State` и `StatesGroup`.
2. **Декораторы:** Декораторы для обработки состояний изменились. Вместо использования `@dp.message_handler(state=...)`, теперь предпочтительно использовать `@dp.message_handler(F.state...)`, что делает код более читаемым.
3. **Упрощённая работа с контекстом:** Теперь доступ к контексту более упрощён и использует асинхронные функции во многих случаях.
### Пример организации обработки состояний
Для организации обработки сообщений в каждом из состояний можно использовать декораторы, учитывая, что у вас есть два состояния: `waiting_for_username` и `waiting_for_cost`. Можно использовать `StatesGroup`, чтобы определить состояние и обрабатывать сообщения для каждого состояния.
Вот пример кода:
```python
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.utils import executor
# Определяем состояния
class Form(StatesGroup):
waiting_for_username = State()
waiting_for_cost = State()
# Инициализация бота и диспетчера
bot = Bot(token='YOUR_TOKEN')
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
@dp.message_handler(commands='start')
async def cmd_start(message: types.Message):
await Form.waiting_for_username.set() # Установка состояния
await message.reply("Пожалуйста, введите ваше имя пользователя.")
@dp.message_handler(state=Form.waiting_for_username)
async def process_username(message: types.Message, state: FSMContext):
username = message.text
await state.update_data(username=username) # Сохранение данных
await Form.waiting_for_cost.set() # Переход к следующему состоянию
await message.reply("Теперь введите стоимость.")
@dp.message_handler(state=Form.waiting_for_cost)
async def process_cost(message: types.Message, state: FSMContext):
cost = message.text
# Здесь можно обработать стоимость
user_data = await state.get_data() # Получение данных
username = user_data.get('username')
await message.reply(f"Спасибо, {username}! Вы указали стоимость: {cost}.")
await state.finish() # Завершение состояний
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
```
В этом коде:
- Мы определяем `StatesGroup`, где задаём состояния `waiting_for_username` и `waiting_for_cost`.
- Используем `await Form.waiting_for_username.set()`, чтобы установить текущее состояние.
- Функции для обработки сообщений в разных состояниях используют `state` для получения и обновления данных.
- Завершаем состояния с помощью `await state.finish()`, когда процесс завершен.
Таким образом, при правильной настройке состояний и обработчиков сообщений вы можете избежать ошибок и плавно управлять процессом перевода.