Aiogram 3: туториал по созданию Telegram-бота на Python (2025)
Пошаговое руководство по созданию Telegram-бота на Aiogram 3 — хендлеры, FSM, инлайн-клавиатуры, деплой. Без воды.
Aiogram 3 — это асинхронный Python-фреймворк для Telegram-ботов. Я использовал его в 20+ продакшн-проектах. Вот всё, что нужно чтобы пройти путь от нуля до запущенного бота, не продираясь через устаревшие туториалы.
Почему именно Aiogram 3
Есть несколько Python-библиотек для Telegram-ботов. Aiogram 3 выигрывает для продакшна потому что:
- Async-first — построен на asyncio, обрабатывает тысячи обновлений эффективно
- Система роутеров — разделяйте хендлеры по модулям чисто и аккуратно
- Magic filters —
F.text == "привет",F.photo,F.from_user.id == 123456— выразительно и читаемо - FSM — встроенный конечный автомат для многошаговых диалогов
- Типобезопасность — полная типизация во всём фреймворке
Старый python-telegram-bot тоже работает, но архитектура Aiogram 3 чище для любого проекта сложнее игрушечного.
Установка
pip install aiogram
Получите токен бота у @BotFather — отправьте /newbot, следуйте инструкциям.
Структура проекта, которую я использую:
mybot/
├── bot.py # точка входа
├── config.py # токен + настройки
├── handlers/
│ ├── start.py
│ └── orders.py
├── keyboards/
│ └── kb.py
└── states/
└── states.py
config.py:
import os
BOT_TOKEN = os.getenv("BOT_TOKEN", "your_token_here")
Первый бот: хендлер /start
# bot.py
import asyncio
from aiogram import Bot, Dispatcher
from aiogram.filters import CommandStart
from aiogram.types import Message
bot = Bot(token="YOUR_TOKEN")
dp = Dispatcher()
@dp.message(CommandStart())
async def cmd_start(message: Message):
await message.answer(f"Привет, {message.from_user.first_name}!")
async def main():
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
Запустите, отправьте /start своему боту. Это база.
Роутеры: держим код в порядке
В Aiogram 3 Router — ключевая абстракция. Вместо того чтобы регистрировать всё на Dispatcher, создавайте роутеры на каждый модуль и подключайте их:
# handlers/start.py
from aiogram import Router, F
from aiogram.filters import CommandStart
from aiogram.types import Message
router = Router()
@router.message(CommandStart())
async def cmd_start(message: Message):
await message.answer("Добро пожаловать!")
@router.message(F.text == "помощь")
async def help_text(message: Message):
await message.answer("Вот как работает этот бот...")
# bot.py
from handlers import start, orders
dp.include_router(start.router)
dp.include_router(orders.router)
Это сохраняет больших ботов поддерживаемыми. Каждый файл хендлеров остаётся сфокусированным.
Magic filters: F.
Объект F — то, где Aiogram 3 особенно хорош:
from aiogram import F
# Точное совпадение текста
@router.message(F.text == "Купить")
# Сообщения с фото
@router.message(F.photo)
# Конкретный пользователь
@router.message(F.from_user.id == 123456789)
# Комбинирование фильтров
@router.message(F.text.startswith("заказ:") & F.from_user.is_premium)
# Отрицание
@router.message(~F.text.in_({"стоп", "отмена"}))
Больше никаких if message.text == "Купить": внутри хендлеров. Фильтры объявлены декларативно — их легко читать и комбинировать.
Инлайн-клавиатуры и колбэки
# keyboards/kb.py
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.types import InlineKeyboardMarkup
def main_kb() -> InlineKeyboardMarkup:
b = InlineKeyboardBuilder()
b.button(text="📦 Товары", callback_data="products")
b.button(text="📋 Мои заказы", callback_data="my_orders")
b.button(text="💬 Контакт", url="https://t.me/yourusername")
b.adjust(2, 1)
return b.as_markup()
# handler
from aiogram.types import CallbackQuery
@router.message(CommandStart())
async def cmd_start(message: Message):
await message.answer("Выберите:", reply_markup=main_kb())
@router.callback_query(F.data == "products")
async def show_products(callback: CallbackQuery):
await callback.answer()
await callback.message.edit_text("Вот наши товары...", reply_markup=products_kb())
Всегда вызывайте callback.answer() первой — без неё кнопка остаётся в состоянии загрузки 30 секунд.
FSM: многошаговые диалоги
FSM (конечный автомат) — это то, как обрабатывать сценарии, которые длятся несколько сообщений: формы заказа, регистрация, опросы.
# states/states.py
from aiogram.fsm.state import State, StatesGroup
class OrderForm(StatesGroup):
waiting_name = State()
waiting_phone = State()
waiting_description = State()
# handlers/orders.py
from aiogram.fsm.context import FSMContext
from states.states import OrderForm
@router.callback_query(F.data == "new_order")
async def start_order(callback: CallbackQuery, state: FSMContext):
await state.set_state(OrderForm.waiting_name)
await callback.answer()
await callback.message.answer("Как вас зовут?")
@router.message(OrderForm.waiting_name)
async def got_name(message: Message, state: FSMContext):
await state.update_data(name=message.text)
await state.set_state(OrderForm.waiting_phone)
await message.answer("Ваш номер телефона:")
@router.message(OrderForm.waiting_phone)
async def got_phone(message: Message, state: FSMContext):
await state.update_data(phone=message.text)
await state.set_state(OrderForm.waiting_description)
await message.answer("Опишите задачу:")
@router.message(OrderForm.waiting_description)
async def got_description(message: Message, state: FSMContext):
data = await state.get_data()
await state.clear()
await message.answer(
f"✅ Заказ принят!\n"
f"Имя: {data['name']}\n"
f"Телефон: {data['phone']}\n"
f"Задача: {message.text}"
)
FSMContext автоматически внедряется Aiogram. Состояние хранится между сообщениями. По умолчанию используется MemoryStorage (теряется при перезапуске) — для продакшна переключайтесь на RedisStorage.
Middleware: код на каждое обновление
from aiogram import BaseMiddleware
from aiogram.types import TelegramObject
class LoggingMiddleware(BaseMiddleware):
async def __call__(self, handler, event: TelegramObject, data: dict):
print(f"Обновление от пользователя {event.from_user.id}")
return await handler(event, data)
dp.update.middleware(LoggingMiddleware())
Я использую middleware чтобы автоматом сохранять пользователей в базу при первом контакте — это выполняется до любого хендлера, никогда не забудешь добавить.
Деплой: systemd на VPS
Простейшая продакшн-установка: Ubuntu VPS, systemd сервис. Docker не нужен для простых ботов.
# /etc/systemd/system/mybot.service
[Unit]
Description=My Telegram Bot
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/mybot
Environment="BOT_TOKEN=your_token"
ExecStart=/home/ubuntu/mybot/.venv/bin/python bot.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl enable mybot
sudo systemctl start mybot
sudo systemctl status mybot
journalctl -u mybot -f
Бот теперь переживает перезагрузки VPS и автоматически перезапускается после падений.
Что изучать дальше
Когда освоите базу:
- PostgreSQL + asyncpg — большинству ботов рано или поздно нужна база данных
- Telegram Stars платежи —
send_invoice(),pre_checkout_query,successful_payment - Webhooks — быстрее чем polling для высоконагруженных ботов, нужен HTTPS домен
- Telegram Mini App — полноценный веб-интерфейс внутри Telegram
- Система рассылок — отправка сообщений всем пользователям без превышения лимитов
Документация на docs.aiogram.dev отличная. Telegram-чат Aiogram (@aiogram) активный и полезный.
Сделайте реальный проект, запустите его, смотрите как работает. Только так реально учишься.
поделиться