Небольшим офлайн- и онлайн-бизнесам всё чаще нужен простой канал связи с клиентами: записать на услугу, принять заявку, ответить на типовые вопросы, не написав при этом собственный «личный кабинет» с авторизацией и фронтендом. Telegram-боты хорошо ложатся в этот сценарий: они доступны с телефона, поддерживают кнопки, формы, платежи и работают поверх знакомого интерфейса мессенджера.
В этой статье разбирается, как с нуля собрать минимально полезного бота для малого бизнеса (например, магазина одежды или студии услуг) на Python и библиотеке aiogram 3.x: от получения токена до развёртывания на сервере. Статья рассчитана на разработчиков, которые уже базово знакомы с Python, но ещё не работали с Telegram Bot API или современными фреймворками для ботов.
Что будет уметь бот
Рассматривается небольшой, но жизненный функционал, вокруг которого можно потом наращивать более сложные сценарии.
Бот будет:
Показывать приветствие и короткое меню по команде
/start.Давать пользователю быстрые кнопки с типичными действиями: «Каталог», «Оформить заявку», «Связаться с менеджером».
Принимать простую заявку (имя, контакт, выбранная позиция) и отправлять её менеджеру в отдельный служебный чат.
Логировать базовые события, чтобы потом понимать, как люди пользуются ботом.
Такой функционал уже закрывает типовую потребность малого бизнеса в «цифровом ресепшене» без разработки полноценного веб-приложения.
Технологический стек
Для реализации подойдёт минимальный набор инструментов, которые легко повторить на любой машине разработчика.
Понадобится:
Python версии не ниже 3.10 (большинство современных гайдов по aiogram опираются именно на эти версии).
Библиотека aiogram 3.x — асинхронный фреймворк, упрощающий работу с Telegram Bot API.
Любой текстовый редактор или IDE (VS Code, PyCharm, Vim — на усмотрение разработчика).
Учётная запись Telegram и доступ к боту BotFather для регистрации собственного бота.
Для продакшн-развёртывания — виртуальный или физический сервер с установленным Python и возможностью запустить длительный процесс (VPS у любого хостера, своё железо и т.п.).
Дополнительно можно использовать Redis или любую СУБД для хранения заявок и состояний, но в базовом примере демонстрируется простой файловый или «памятный» подход, чтобы не перегружать первый запуск.
Шаг 1. Регистрируем бота через BotFather
Telegram предоставляет отдельный служебный бот BotFather, через которого создаются и настраиваются все остальные боты.
Минимальный путь выглядит так:
В поиске Telegram найти пользователя
@BotFatherи открыть с ним диалог.Нажать кнопку
/startили ввести эту команду вручную.Выбрать команду
/newbotи следовать подсказкам: указать название (видимое пользователям) и уникальное имя, оканчивающееся наbot.В ответ BotFather пришлёт HTTP API token — строку вида
1234567890:AA..., которая используется для авторизации бота на стороне Telegram.Сохранить токен в безопасном месте и не публиковать его в репозиториях и скриншотах.
Дальше этот токен будет использоваться в конфигурации Python-приложения через переменные окружения или отдельный конфигурационный файл, который не попадает в систему контроля версий.
Шаг 2. Структурируем проект на Python
На небольших проектах соблазнительно писать всё в одном файле bot.py, но даже для простого бота лучше с самого начала отделить конфигурацию, обработчики и запуск.
Пример минимальной структуры:
project_root/ ├─ bot/ │ ├─ __init__.py │ ├─ config.py │ ├─ handlers/ │ │ ├─ __init__.py │ │ ├─ common.py │ │ └─ orders.py │ └─ main.py ├─ .env ├─ requirements.txt └─ README.md
Такой разбор по каталогам позволяет со временем добавлять новые сценарии, не превращая код в неуправляемый монолит.
Установка зависимостей
В файле requirements.txt можно указать минимум:
aiogram>=3.0.0 python-dotenv>=1.0.0
Установка через pip стандартна:
pip install -r requirements.txt
Библиотека python-dotenv используется для загрузки конфигурации (например, токена бота) из файла .env, что удобно для локальной разработки.
Конфигурация бота
Файл .env (его не стоит коммитить в репозиторий) может выглядеть так:
BOT_TOKEN=1234567890:AA... # ваш токен от BotFather ADMIN_CHAT_ID=123456789 # ID чата или пользователя, куда слать заявки
Пример кода для загрузки этих значений в модуле config.py:
from dataclasses import dataclass import os from dotenv import load_dotenv load_dotenv() @dataclass class Settings: bot_token: str admin_chat_id: int def get_settings() -> Settings: return Settings( bot_token=os.environ["BOT_TOKEN"], admin_chat_id=int(os.environ["ADMIN_CHAT_ID"]), ) settings = get_settings()
Использование dataclass делает конфигурацию типобезопасной и удобной для дальнейшей передачи в различные части приложения.
Шаг 3. Поднимаем базовый echo-бот на aiogram 3.x
Начальная цель — убедиться, что бот вообще отвечает и корректно подключён к Telegram Bot API.
Минимальный main.py может выглядеть так:
import asyncio import logging import sys from aiogram import Bot, Dispatcher, F from aiogram.client.default import DefaultBotProperties from aiogram.enums import ParseMode from aiogram.filters import CommandStart from aiogram.types import Message from bot.config import settings logging.basicConfig(level=logging.INFO, stream=sys.stdout) dp = Dispatcher() @dp.message(CommandStart()) async def cmd_start(message: Message) -> None: await message.answer( "Привет! Это бот малого бизнеса.\n" "Используйте меню ниже, чтобы посмотреть каталог или оставить заявку." ) @dp.message(F.text) async def echo(message: Message) -> None: await message.answer(f"Вы написали: {message.text}") async def main() -> None: bot = Bot( token=settings.bot_token, default=DefaultBotProperties(parse_mode=ParseMode.HTML), ) await dp.start_polling(bot) if __name__ == "__main__": asyncio.run(main())
Этот код создаёт диспетчер, регистрирует обработчик команды /start и простейший echo-обработчик всех текстовых сообщений. После запуска скрипта и отправки команды /start бот должен прислать приветствие, а на любые другие сообщения — повторять текст пользователя.
Такая заготовка часто используется в официальных и неофициальных «быстрых стартах» по aiogram, что облегчает диагностику проблем с сетью и токеном.
Шаг 4. Добавляем пользовательское меню и сценарий заявки
Echo-бот сам по себе не несёт пользы бизнесу, поэтому далее вводится простое меню и форма заявки.
Кнопки главного меню
В aiogram 3.x для создания клавиатур используются типы ReplyKeyboardMarkup и InlineKeyboardMarkup. Для простоты хватит обычной клавиатуры под полем ввода:
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton main_menu = ReplyKeyboardMarkup( keyboard=[ [KeyboardButton(text="Каталог")], [KeyboardButton(text="Оформить заявку")], [KeyboardButton(text="Связаться с менеджером")], ], resize_keyboard=True, )
Теперь можно обновить обработчик /start, чтобы он прикреплял клавиатуру к сообщению:
@dp.message(CommandStart()) async def cmd_start(message: Message) -> None: await message.answer( "Привет! Вы в боте магазина.\n" "Выберите действие в меню ниже.", reply_markup=main_menu, )
Кнопки сокращают количество «ручного» текста и помогают пользователю сразу понять, какие сценарии поддерживает бот.
Простая форма заявки через конечный автомат
Aiogram 3.x предлагает простой подход к конечным автоматам состояний, когда бот по шагам спрашивает у пользователя необходимые данные. Для бизнес-заявки разумно запросить имя, способ связи и, при необходимости, интересующий товар или услугу.
Пример упрощённого сценария в модуле handlers/orders.py:
from aiogram import Router, F from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.context import FSMContext from aiogram.types import Message from bot.config import settings router = Router() class OrderForm(StatesGroup): name = State() contact = State() comment = State() @router.message(F.text == "Оформить заявку") async def order_start(message: Message, state: FSMContext) -> None: await message.answer("Как вас зовут?") await state.set_state(OrderForm.name) @router.message(OrderForm.name) async def order_name(message: Message, state: FSMContext) -> None: await state.update_data(name=message.text.strip()) await message.answer("Укажите, пожалуйста, удобный способ связи (телефон или @username).") await state.set_state(OrderForm.contact) @router.message(OrderForm.contact) async def order_contact(message: Message, state: FSMContext) -> None: await state.update_data(contact=message.text.strip()) await message.answer("Опишите, что именно вас интересует (товар, услуга, время и т.п.).") await state.set_state(OrderForm.comment) @router.message(OrderForm.comment) async def order_comment(message: Message, state: FSMContext) -> None: await state.update_data(comment=message.text.strip()) data = await state.get_data() await state.clear() text = ( "<b>Новая заявка</b>\n" f"Имя: {data['name']}\n" f"Контакт: {data['contact']}\n" f"Комментарий: {data['comment']}" ) await message.answer("Спасибо! Заявка отправлена менеджеру.") await message.bot.send_message(chat_id=settings.admin_chat_id, text=text)
Чтобы этот роутер заработал, его нужно подключить в main.py:
from aiogram import Dispatcher from aiogram.fsm.storage.memory import MemoryStorage from bot.handlers import orders dp = Dispatcher(storage=MemoryStorage()) dp.include_router(orders.router)
Памятное хранилище (MemoryStorage) достаточно для небольших ботов и первых экспериментов; в реальных продакшн-сценариях уместно использовать Redis или другую внешнюю систему для масштабирования и отказоустойчивости.
Шаг 5. Логирование и базовая наблюдаемость
Даже у простого бота важно видеть, что именно нажимают и пишут пользователи, особенно на старте проекта.
Использование стандартного модуля logging с выводом в stdout уже даёт минимальную картину происходящего. Настроенный ранее вызов logging.basicConfig(level=logging.INFO, stream=sys.stdout) позволяет видеть в логах все входящие апдейты и ошибки, если включить соответствующие сообщения в обработчиках.
На следующем этапе можно подключить сбор логов в централизованный сервис (Elasticsearch, Loki и т.п.) или хотя бы сохранять их в файлы с ротацией, но для первых запусков часто достаточно стандартного вывода в консоль или системный журнал на сервере.
Шаг 6. Развёртывание бота на сервере
Разработчики Telegram-ботов традиционно используют два режима работы: получение обновлений через webhook или опрос (getUpdates, long polling). Aiogram 3.x упрощает организацию long polling, а для небольших ботов этого вполне достаточно, если нет жёстких требований по задержкам.
Базовый вариант деплоя:
Поднять на сервере Python требуемой версии и скопировать туда проект (через Git, SCP или другой привычный способ).
Установить зависимости с помощью
pip install -r requirements.txtв виртуальном окружении.Создать на сервере файл
.envс боевым токеном и ID чата администратора.Запустить
python -m bot.mainи убедиться по логам, что бот успешно подключился и отвечает.Для постоянной работы оформить запуск через systemd, supervisord или screen/tmux, чтобы бот перезапускался при падении и не зависел от SSH-сессии.
Документация Telegram Bot API и многочисленные практические статьи подчёркивают, что long polling остаётся валидным и надёжным вариантом для большого числа use-case’ов, особенно когда нагрузка невысока.
