7 самых частых ошибок при разработке Telegram-ботов и способы их решения

Автор: Javohir Abdullayev · · Telegram-боты

7 самых частых ошибок при разработке Telegram-ботов и способы их решения

Почему при разработке Telegram-ботов часто возникают ошибки?

Сегодня Telegram-боты стали одним из самых популярных инструментов для бизнеса и сервисов в Узбекистане. Многие начинающие разработчики входят в мир программирования именно через Python и библиотеку aiogram. Однако, как только число пользователей проекта переваливает за несколько сотен, бот начинает зависать, сообщения теряются или сервер неожиданно падает.

В этой статье мы рассмотрим 7 наиболее серьезных технических ошибок, часто допускаемых при разработке Telegram-ботов, и профессиональные методы их устранения.

1. Хардкод токена бота в коде (Hardcoded Secrets)

Одна из самых опасных и, к сожалению, распространенных ошибок — это прописывание токена бота прямо внутри файла Python. При загрузке кода на GitHub или GitLab токен бота может быть скомпрометирован, и управление ботом перейдет в чужие руки.

Правильное решение: Используйте переменные окружения (environment variables) и файл .env. В качестве библиотек рекомендуются python-decouple или pydantic-settings.

from aiogram import Bot
from decouple import config

BOT_TOKEN = config('BOT_TOKEN')
bot = Bot(token=BOT_TOKEN)

Никогда не забывайте добавлять строку .env в файл .gitignore.

2. Хранение состояний (State) в оперативной памяти (In-Memory)

Начинающие разработчики часто хранят состояния FSM (Finite State Machine) с помощью MemoryStorage или удерживают данные пользователей в обычном словаре Python (dict). В итоге при перезапуске бота (restart) все заполняемые пользователями заявки и корзины безвозвратно удаляются.

Правильное решение: Для хранения состояний используйте быстрые базы данных в памяти, такие как Redis:

from aiogram.fsm.storage.redis import RedisStorage
from redis.asyncio import Redis

redis = Redis(host='localhost', port=6379)
storage = RedisStorage(redis=redis)

3. Выполнение медленного и тяжелого кода в основном Event Loop

Асинхронные библиотеки в Python (aiogram, asyncio) работают в одном потоке (single thread). Если при обработке запроса одного пользователя вы вызываете requests.get(), тяжелую обработку файлов или синхронный time.sleep(), весь бот блокируется и перестает отвечать другим пользователям.

Правильное решение: Все запросы должны быть асинхронными. Вместо requests используйте aiohttp или httpx. Тяжелые вычисления выносите в отдельный фоновый поток с помощью asyncio.to_thread() или инструментов вроде Celery.

import asyncio
import aiohttp

# Неправильно: time.sleep(5)
# Правильно:
await asyncio.sleep(5)

# Неправильно: requests.get(url)
# Правильно:
async with aiohttp.ClientSession() as session:
    async with session.get(url) as response:
        data = await response.json()

4. Игнорирование лимитов Telegram (Rate Limits)

При массовой рассылке (broadcast) сообщений разработчики нередко запускают цикл по всем ID и подряд вызывают await bot.send_message(). В результате Telegram выдает ошибку 429 Too Many Requests: retry after X seconds, и отправка прекращается.

Telegram разрешает отправлять не более 30 сообщений в секунду. Для массовых рассылок обязательно используйте очереди сообщений (например, Celery, RabbitMQ), асинхронные ограничители (asyncio.Semaphore) или готовые библиотеки, такие как aiogram-broadcaster.

5. Отсутствие фильтрации и валидации пользовательского ввода

Любой текст, номер телефона или формат файла, отправленный пользователем, может отличаться от ожидаемого. Запись необработанных («сырых») данных напрямую в базу данных приводит к сбоям или SQL-инъекциям.

Всегда проверяйте длину и формат входящего текста. При отправке ответов с HTML-разметкой обязательно экранируйте текст пользователя с помощью html.escape() или функций из aiogram.utils.text_decorations.

6. Неиспользование drop_pending_updates при перезапуске

Если бот был отключен на некоторое время или остановился из-за сбоя сервера, на серверах Telegram накапливаются обновления. При повторном запуске бот пытается моментально обработать все скопившиеся старые сообщения, что может перегрузить сервер или отправить пользователям неактуальные ответы.

Правильное решение: Очищайте старые запросы перед запуском polling:

await bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot)

7. Отсутствие глобального обработчика ошибок (Error Handling Middleware)

Когда бот сталкивается с непредвиденной ситуацией (например, внешний API не отвечает или пользователь заблокировал бота), он падает с ошибкой и никак не отвечает пользователю, оставаясь безмолвным. Из-за этого у пользователя создается впечатление, что сервис полностью сломался.

В aiogram 3.x для отлова ошибок предусмотрен специальный Error Router:

from aiogram import Router
from aiogram.types.error_event import ErrorEvent
import logging

error_router = Router()

@error_router.errors()
async def global_error_handler(event: ErrorEvent):
    logging.exception(f'Непредвиденная ошибка: {event.exception}')
    if event.update.message:
        await event.update.message.answer(
            'Извините, произошел сбой в системе. Пожалуйста, попробуйте позже.'
        )

Заключение

Создание качественного Telegram-бота, способного выдерживать миллионы пользователей, — это не просто добавление кнопок интерфейса. Соблюдение правил асинхронного программирования, хранение состояний в Redis и грамотное управление лимитами выведут разработку вашего бота на профессиональный уровень.

Теги: #telegram bot #aiogram #python #backend