Почему бот на 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, и ваш бот будет работать предсказуемо.