@EnotShow

Как вызывать команды внутри машины состояний aiogram?

Например у нас есть state:
class FSMRegister(StatesGroup):
    age = State()
    sex = State()
    name = State()
    city = State()
    find = State()
    about = State()
    photo = State()
    some = State()

И код который работает в этом state:
async def get_age(self, message: types.Message, state: FSMContext):
        try:
            async with state.proxy() as data:
                message.text = int(message.text)
                data['age'] = int(message.text)
            await self.FSM.next()
            await bot.send_message(message.from_user.id, 'Кто ты', reply_markup=sexb1)
        except:
            await bot.send_message(message.from_user.id, 'Возраст должен быть указан числом')

dp.register_message_handler(user_register.get_age, state=FSMRegister.age)

Как сделать так, что бы можно было находясь в этом state, вызвать функции, которые вызываются из команд ? Например /start. Желательно с примером кода. буду очень благодарен.
  • Вопрос задан
  • 958 просмотров
Решения вопроса 1
@corydoras_aeneus
Была подобная проблема, пока пользуюсь таким кодом
async def filter_commands(message: Message, state: FSMContext):
    text = message.text
    if text.startswith('/'):
        cmd = text.lstrip('/')
        if cmd in COMMANDS:
            handlers = dp.message_handlers.handlers
            for h in handlers:
                filters = [f.filter for f in h.filters if type(f.filter) == Command and cmd in f.filter.COMMANDS]
                if len(filters) > 0:
                    await state.reset_state()
                    await h.handler(message)
                    return True
    return False

Использование - в начало обработчика вставляю, например
async def get_age(self, message: types.Message, state: FSMContext):
    if await filter_commands(message, state):
        return
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
shurshur
@shurshur
Сисадмин, просто сисадмин...
Лучше всего, конечно, выносить общую часть функционала в отдельную функцию. Например, пусть в обработчике /start информация о пользователе добавляется в базу и отправляется приветственное сообщение с какой-нибудь справкой по использованию. Скорее всего, повторно добавлять в базу не надо, а вот приветственное сообщение можно и выделить в какую-нибудь send_welcome_message (естественно, с параметром chat_id и при необходимости другими параметрами, нужными для её работы). Типа, пользователь запустил бота, поотвечал на вопросы, потом получил опять приветственное сообщение с информацией о своей работе, которую пользователь уже успел забыть, пока заполнял анкету.

Но если прям очень хочется, то можно вызвать функцию напрямую. Но если она обёрнута декоратором, то её вызвать напрямую может быть опасно, так как после применения декоратора это будет уже другая функция, которая имеет право создавать какие-нибудь спецэффекты при своём запуске. Если регистрировать без декораторов, вызовами register_message_handler, то исходная функция изменяться не будет, но с декораторами можно писать более красиво.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы