Почему бот на Aiogram зацикливается при изменении имени пользователя

    При разработке телеграм-бота на библиотеке Aiogram часто возникает ситуация, когда после ввода имени пользователя бот не переходит к следующему шагу (например, запросу группы), а снова просит изменить имя. В этой статье мы разберём причины такого поведения и предложим рабочее решение.

    Основная причина проблемы

    В предоставленном коде определены две функции с одинаковым именем echo, что приводит к переопределению последней. Кроме того, отсутствует привязка хендлера к состоянию - бот обрабатывает любое текстовое сообщение одной и той же функцией, не проверяя, на каком этапе находится пользователь. В результате после сохранения имени бот снова вызывает ту же функцию, пытаясь изменить имя, вместо того чтобы запросить группу.

    Как это исправить: пошаговое руководство

    1. Используйте машину состояний (FSM)

    Aiogram предоставляет встроенный механизм FSM (Finite State Machine) для управления сценариями диалога. Установите состояния: NameState и GroupState. После команды /start переведите пользователя в состояние ожидания имени, а после получения имени - в состояние ожидания группы.

    2. Разделите хендлеры по состояниям

    Создайте отдельные обработчики для каждого состояния. Например, @dp.message(StateFilter(NameState)) будет ловить только сообщения, когда бот ждёт имя. А @dp.message(StateFilter(GroupState)) - когда ждёт группу. Это исключит повторный вызов одного и того же кода.

    3. Обновляйте сообщения в буфере правильно

    Если вы используете @dp.message() без фильтра, все входящие сообщения будут обрабатываться одним хендлером. Вместо этого применяйте декораторы с указанием состояния или текстовых команд. Для обновления сообщений в буфере (например, для удаления предыдущих) используйте метод message.edit_text() или bot.edit_message_text() с правильным message_id.

    Пример исправленного кода

    Ниже приведён корректный фрагмент с использованием FSM:

    from aiogram.dispatcher.filters.state import State, StatesGroup
    from aiogram.dispatcher import FSMContext
    
    class UserRegistration(StatesGroup):
        waiting_for_name = State()
        waiting_for_group = State()
    
    @dp.message_handler(commands=['start'])
    async def start(message: types.Message):
        if not botDB.user_exists(message.from_user.id):
            botDB.add_user(message.from_user.id)
        await message.answer('Привет! Как тебя зовут?')
        await UserRegistration.waiting_for_name.set()
    
    @dp.message_handler(state=UserRegistration.waiting_for_name)
    async def process_name(message: types.Message, state: FSMContext):
        botDB.edit_username(message.from_user.id, message.text)
        await message.answer('Отлично! Теперь напиши свою учебную группу.')
        await UserRegistration.waiting_for_group.set()
    
    @dp.message_handler(state=UserRegistration.waiting_for_group)
    async def process_group(message: types.Message, state: FSMContext):
        botDB.det_grup(message.from_user.id, message.text)
        await message.answer('Регистрация завершена!')
        await state.finish()

    Распространённые ошибки и их предотвращение

    • Дублирование функций: не объявляйте две функции с одинаковым именем - это приводит к перезаписи.
    • Отсутствие проверки состояния: без FSM бот не знает, какой шаг ожидать, и может зациклиться.
    • Неправильная работа с БД: убедитесь, что методы edit_username и det_grup корректно обновляют записи, а не вставляют новые.

    Заключение

    Использование машины состояний - стандартный подход для многошаговых диалогов в Aiogram. Он позволяет чётко разделить этапы регистрации, избежать зацикливания и сделать код читаемым. Внедрите FSM, и ваш бот будет работать предсказуемо.

    Часто задаваемые вопросы