Telegram-бот — это небольшая программа, которая общается с людьми через Telegram. В этой статье напишем такого бота на Python с помощью aiogram 3, популярного асинхронного фреймворка для ботов. Наш бот здоровается, показывает клавиатуру и отправляет сообщения обратно. Статья для тех, кто знает основы Python, но ещё не писал ботов. Понадобится минут двадцать, а та же структура потом вырастает в настоящие проекты.
Что понадобится
- Python 3.12 или новее. Проверьте командой
python3 --version(в Windowspython --version). Если ставите Python в Windows с python.org, отметьте в установщике пункт «Add python.exe to PATH». - Аккаунт в Telegram.
- Любой редактор кода.
Получаем токен у BotFather
Любой бот создаётся через @BotFather, официального бота Telegram для управления ботами. Откройте его, отправьте /newbot, придумайте отображаемое имя, а затем username, который заканчивается на bot, например my_first_aiogram_bot. В ответ BotFather пришлёт токен вида 123456789:AAH.... Там же командами /setdescription и /setuserpic можно задать боту описание и аватарку: именно их человек видит, когда впервые открывает бота.
Токен — это пароль бота. У кого токен, тот и управляет ботом, так что берегите его как пароль.
Готовим проект
Создайте папку с виртуальным окружением, чтобы пакеты бота не смешивались с остальной системой, и установите aiogram:
mkdir my-bot && cd my-bot
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U aiogram
Позже команда pip freeze > requirements.txt сохранит точные версии пакетов, чтобы на сервере бот установился точно так же.
Пишем бота
Создайте файл bot.py:
import asyncio
import logging
import os
from aiogram import Bot, Dispatcher, F, Router, html
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
from aiogram.filters import CommandStart
from aiogram.types import KeyboardButton, Message, ReplyKeyboardMarkup
router = Router()
menu = ReplyKeyboardMarkup(
keyboard=[[KeyboardButton(text="О боте"), KeyboardButton(text="Помощь")]],
resize_keyboard=True,
)
@router.message(CommandStart())
async def start(message: Message) -> None:
name = html.quote(message.from_user.full_name)
await message.answer(
f"Привет, <b>{name}</b>! Пришлите мне любой текст.",
reply_markup=menu,
)
@router.message(F.text == "О боте")
async def about(message: Message) -> None:
await message.answer("Я демо-бот на aiogram 3.")
@router.message(F.text == "Помощь")
async def help_(message: Message) -> None:
await message.answer("Напишите что угодно, и я пришлю это обратно.")
@router.message(F.text)
async def echo(message: Message) -> None:
await message.answer(html.quote(message.text))
async def main() -> None:
bot = Bot(
token=os.environ["BOT_TOKEN"],
default=DefaultBotProperties(parse_mode=ParseMode.HTML),
)
dp = Dispatcher()
dp.include_router(router)
await dp.start_polling(bot)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.run(main())
Как это работает
- Router группирует обработчики. В крошечном боте их можно вешать прямо на
Dispatcher, но в растущем проекте роутеры помогают держать порядок: свой роутер на каждую функцию, и все они подключаются к диспетчеру. - Обработчики — асинхронные функции с фильтром в декораторе.
CommandStart()ловит/start,F.text == "О боте"ловит ровно этот текст, аF.textлюбое текстовое сообщение. aiogram перебирает обработчики в порядке регистрации и останавливается на первом подходящем, поэтому общий эхо-обработчик стоит последним. - DefaultBotProperties включает HTML-разметку для всех сообщений, поэтому
<b>превращается в жирный текст. По этой же причине текст пользователя проходит черезhtml.quote: иначе сообщение с символом<сломает разметку, и Telegram отклонит ответ. - start_polling постоянно спрашивает у Telegram новые обновления. Это самый простой способ запустить бота: не нужны ни публичный адрес, ни домен, ни сертификат.
- message.answer отвечает в тот же чат, откуда пришло сообщение, так что ID чата вручную передавать не нужно.
- async позволяет одному небольшому процессу обслуживать много людей: пока один обработчик ждёт ответа от Telegram, остальные продолжают работать.
Запуск и остановка
Положите токен в переменную окружения и запустите бота:
export BOT_TOKEN="123456789:AAH..." # PowerShell: $env:BOT_TOKEN = "..."
python bot.py
Откройте бота в Telegram и нажмите «Запустить». В терминале появится запись о каждом полученном обновлении. Чтобы остановить бота, нажмите Ctrl+C, и aiogram аккуратно закроет соединение. Если закрыть терминал, бот тоже остановится; чтобы он работал постоянно, нужен сервер, об этом ниже. А если забыть про переменную, os.environ["BOT_TOKEN"] сразу упадёт с KeyError, и это лучше, чем непонятная ошибка потом.
Две вещи часто удивляют новичков. Бот не может написать человеку первым: сначала человек должен открыть бота и нажать «Запустить». И опрашивать Telegram может только одна копия бота одновременно: если запустить вторую, например на ноутбуке и на сервере сразу, Telegram вернёт ошибку конфликта.
Храните токен в секрете
Никогда не пишите токен в коде и не коммитьте его в Git. Публичные репозитории постоянно сканируют в поисках секретов, а тот, кто найдёт токен, получит управление ботом.
Если надоело каждый раз писать export, храните токен в файле .env, добавьте .env в .gitignore и загружайте его библиотекой вроде python-dotenv. Папку .venv тоже добавьте в .gitignore, в репозитории ей не место. Если токен всё же утёк, отправьте BotFather команду /revoke и получите новый. Старый токен сразу перестанет работать.
Что дальше
- FSM (машина состояний) для многошаговых диалогов, например анкеты, которая спрашивает сначала имя, потом телефон.
- Inline-клавиатуры и callback-запросы для кнопок прямо под сообщением.
- Вебхуки вместо опроса, когда бот переедет на сервер с HTTPS.
- База данных, например PostgreSQL с SQLAlchemy, чтобы помнить пользователей и их настройки.
- systemd или Docker, чтобы бот работал постоянно и перезапускался после сбоя или перезагрузки.
В документации aiogram (откроется в новой вкладке) всё это разобрано на примерах. Сделайте что-нибудь небольшое, чем вы или ваши друзья будут на самом деле пользоваться: так учиться быстрее всего.


