Aiogram3 проблема с работой состояний
Раньше писал на второй версии библиотеки и в боте у меня есть несколько состояний, к примеру создание анкет и их поиск. На второй версии все работало нормально и не было никаких проблем. На третей версии я могу вызывать из состояния обычные команды у которых состояние вовсе не указано и это ломает логику боту. Можно ли как-то обойтись без выдачи всем функциям кастомного состояния?
вот код:
'''
class ProfileCreate(StatesGroup):
gender = State()
find_gender = State()
photo = State()
name = State()
age = State()
city = State()
desc = State()
@router.message(filters.IsFindGender(), ProfileCreate.find_gender)
async def _find_gender(message: types.Message, state: FSMContext, find_gender: str):
await state.update_data(find_gender=find_gender)
await message.reply(msg_text.PHOTO, reply_markup=del_kb)
await state.set_state(ProfileCreate.photo)
@router.message(ProfileCreate.find_gender)
async def _incorrect_find_gender(message: types.Message):
"""Ошибка фильтра гендера"""
await message.answer(msg_text.INVALID_RESPONSE)
'''
и к примеру я вызываю команду для реферальных ссылок из состояния и она срабатывает, хотя не должна
@router.message(F.text == "✉️")
async def _invite_link_command(message: types.Message, user: Users) -> None:
"""Дает пользователю его реферальную ссылку"""
bot_user = await bot.get_me()
await message.answer(msg_text.INVITE_FRIENDS.format(
user.referral,
bot_user.username,
message.from_user.id
)
)
если нужно могу отправить более полный код, все по файлам разбито и не очень удобно демострировать
Если что про вариант StateFilter(None) я знаю, но не хотелось бы всем хендлерам прописывать это
Ответы (2 шт):
В твоем случае можно написать универсальный обработчик, который будет отлавливать пользователей в состоянии и отвечать на отправку команды определенным сообщением, в зависимости от состояния и шага состояния
@router.message(~StateFilter(None)) # Если пользователь находится в состоянии
async def _state_blocked(message: types.Message, state: FSMContext):
current_state = await state.get_state() # Получаем текущее состояние
if current_state == ProfileCreate.find_gender.state:
await message.answer("Вы должны выбрать пол перед выполнением других команд.")
elif current_state == ProfileCreate.photo.state:
await message.answer("Сначала загрузите фото, прежде чем использовать команды.")
elif current_state == ProfileCreate.name.state:
await message.answer("Введите имя, чтобы продолжить.")
else:
await message.answer("Вы заполняете анкету. Завершите ее перед выполнением других команд.")
Можно попробовать задать поведение по умолчанию через router.message.filter()
, чтобы все хендлеры по умолчанию работали только в состоянии None
, а уже у нужных явно указывать StateFilter
.
router.message.filter(StateFilter(None))
class ProfileCreate(StatesGroup):
gender = State()
find_gender = State()
photo = State()
name = State()
age = State()
city = State()
desc = State()
@router.message(filters.IsFindGender(), ProfileCreate.find_gender)
async def _find_gender(message: types.Message, state: FSMContext, find_gender: str):
await state.update_data(find_gender=find_gender)
await message.reply(msg_text.PHOTO, reply_markup=del_kb)
await state.set_state(ProfileCreate.photo)
@router.message(ProfileCreate.find_gender)
async def _incorrect_find_gender(message: types.Message):
"""Ошибка фильтра гендера"""
await message.answer(msg_text.INVALID_RESPONSE)