Package: pybotx-fsm
pybotx-fsmКонечный автомат (Finite state machine) для ботов на базе библиотекиpybotx.ВозможностиЛёгкое создание графа состояний и их переключений.Передача данных в следующее состояние при явном вызове перехода.Подготовка к установкеДля работы библиотеки необходим Redis, который уже встроен в последние версиикоробки.УстановкаИспользуяpoetry:poetryaddpybotx-fsmРабота с графом состоянийСоздайтеenumдля возможных состояний автомата:fromenumimportEnum,autofrompybotx_fsmimportFSMCollectorclassLoginStates(Enum):enter_email=auto()enter_password=auto()fsm=FSMCollector(LoginStates)Добавьте экземпляр автомата в мидлвари для того, чтобы бот мог использовать его:Bot(collectors=[myfile.collector,],bot_accounts=[BotAccountWithSecret(# Не забудьте заменить эти учётные данные на настоящие,# когда создадите бота в панели администратора.id=UUID("123e4567-e89b-12d3-a456-426655440000"),host="cts.example.com",secret_key="e29b417773f2feab9dac143ee3da20c5",),],middlewares=[FSMMiddleware([myfile.fsm],state_repo_key="redis_repo"),],)Добавьте вbot.state.{state_repo_key}совместимый redis репозиторий:bot.state.redis_repo=awaitRedisRepo.init(...)Создайте обработчики конкретных состояний:@fsm.on(LoginStates.enter_email)asyncdefenter_email(message:IncomingMessage,bot:Bot)->None:email=message.bodyifnotcheck_user_exist(email):awaitbot.answer_message("Wrong email, try again")returnawaitmessage.state.fsm.change_state(LoginStates.enter_password,email=email)awaitbot.answer_message("Enter your password")@fsm.on(LoginStates.enter_password)asyncdefenter_password(message:IncomingMessage,bot:Bot)->None:email=message.state.fsm_storage.emailpassword=message.bodytry:login(email,password)exceptIncorrectPasswordError:awaitbot.answer_message("Wrong password, try again")returnawaitmessage.state.fsm.drop_state()awaitbot.answer_message("Success!")Передайте управление обработчику состояний из любого обработчика сообщений:@collector.command("/login")asyncdefstart_login(message:IncomingMessage,bot:Bot)->None:awaitbot.answer_message("Enter your email")awaitmessage.state.fsm.change_state(LoginStates.enter_email)ПримерыМинимальный пример бота с конечным автоматом# Здесь и далее будут пропущены импорты и код, не затрагивающий# непосредственно pybotx_fsmclassFsmStates(Enum):EXAMPLE_STATE=auto()fsm=FSMCollector(FsmStates)@collector.command("/echo",description="Echo command")asyncdefhelp_command(message:IncomingMessage,bot:Bot)->None:awaitmessage.state.fsm.change_state(FsmStates.EXAMPLE_STATE)awaitbot.answer_message("Input your text:")@fsm.on(FsmStates.EXAMPLE_STATE)asyncdefexample_state(message:IncomingMessage,bot:Bot)->None:user_text=message.bodyawaitmessage.state.fsm.drop_state()awaitbot.answer_message(f"Your text is{user_text}")bot=Bot(collectors=[collector,],bot_accounts=[BotAccountWithSecret(# Не забудьте заменить эти учётные данные на настоящие,# когда создадите бота в панели администратора.id=UUID("123e4567-e89b-12d3-a456-426655440000"),host="cts.example.com",secret_key="e29b417773f2feab9dac143ee3da20c5",),],middlewares=[FSMMiddleware([fsm],state_repo_key="redis_repo"),],)Передача данных между состояниями@fsm.on(FsmStates.INPUT_FIRST_NAME)asyncdefinput_first_name(message:IncomingMessage,bot:Bot)->None:first_name=message.bodyawaitmessage.state.fsm.change_state(FsmStates.INPUT_LAST_NAME,first_name=first_name,)awaitbot.answer_message("Input your last name:")@fsm.on(FsmStates.INPUT_LAST_NAME)asyncdefinput_last_name(message:IncomingMessage,bot:Bot)->None:first_name=message.state.fsm_storage.first_namelast_name=message.bodyawaitmessage.state.fsm.drop_state()awaitbot.answer_message(f"Hello{first_name}{last_name}!")