Чтобы реализовать автоматическую остановку конечного автомата (FSM) на основе временного лимита, вам нужно создать таймер, который будет отсчитывать время, после истечения которого FSM покинет текущее состояние и уведомит пользователя о том, что время вышло.
Приведу пример реализации на Python с использованием библиотеки `aiogram`, которая часто используется для создания Telegram-ботов.
### Пример кода
```python
import asyncio
from aiogram import Bot, Dispatcher, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher import FSMContext, State, StatesGroup
from aiogram.utils import executor
# Создаем бота и диспетчер
API_TOKEN = 'YOUR_API_TOKEN'
bot = Bot(token=API_TOKEN)
storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
class Form(StatesGroup):
waiting_for_name = State() # Ожидание имени пользователя
async def timeout_task(chat_id, state):
await asyncio.sleep(600) # Задержка 10 минут
# Проверим, находится ли пользователь все еще в этом состоянии
if state == Form.waiting_for_name:
await bot.send_message(chat_id, "Время вышло! Вы не ввели имя.")
await state.finish() # Завершаем состояние
@dp.message_handler(commands=['register'])
async def cmd_register(message: types.Message):
await Form.waiting_for_name.set()
await message.reply("Пожалуйста, введите ваше имя (или напишите /cancel для отмены).")
# Запускаем таймер
asyncio.create_task(timeout_task(message.chat.id, Form.waiting_for_name))
@dp.message_handler(state=Form.waiting_for_name)
async def process_name(message: types.Message, state: FSMContext):
# Получаем и сохраняем имя пользователя
user_name = message.text
await state.update_data(name=user_name)
await message.reply(f"Спасибо, {user_name}, вы зарегистрированы!")
await state.finish() # Завершаем состояние
@dp.message_handler(commands=['cancel'], state=Form.waiting_for_name)
async def cancel_registration(message: types.Message, state: FSMContext):
await state.finish() # Завершаем состояние
await message.reply("Регистрация отменена.")
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
```
### Объяснение
1. **Импортируем необходимые модули** и создаем экземпляры `Bot` и `Dispatcher`.
2. **Создаем состояния для FSM**. В нашем примере есть одно состояние `waiting_for_name`.
3. **Обработчик команды `/register`**:
- Устанавливает состояние ожидания ввода имени.
- Отправляет пользователю сообщение с просьбой ввести имя.
- Запускает асинхронную задачу `timeout_task`, которая будет ожидать 10 минут (600 секунд) и проверит, все еще ли пользователь в состоянии ожидания имени.
4. **Обработчик для ввода имени**:
- Если пользователь вводит имя, оно сохраняется, и пользователю отправляется подтверждение.
- FSM завершается.
5. **Обработчик команды `/cancel`**:
- Позволяет пользователю отменить процесс регистрации и завершить состояние FSM.
### Заметки
- Важно убедиться, что вы используете асинхронные функции и подходящие методы для работы с состояниями.
- Убедитесь также, что вы корректно обрабатываете сценарии, когда пользователь может завершить состояние до истечения времени.
- При использовании таймера, вам нужно убедиться, что на одном чате не запустится несколько таймеров (в зависимости от логики вашего бота).
Этот код служит базовым примером, и вы можете адаптировать его под свои нужды, добавляя необходимые проверки и обработку ошибок.