Небольшим офлайн- и онлайн-бизнесам всё чаще нужен простой канал связи с клиентами: записать на услугу, принять заявку, ответить на типовые вопросы, не написав при этом собственный «личный кабинет» с авторизацией и фронтендом. 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, через которого создаются и настраиваются все остальные боты.

Минимальный путь выглядит так:

  1. В поиске Telegram найти пользователя @BotFather и открыть с ним диалог.

  2. Нажать кнопку /start или ввести эту команду вручную.

  3. Выбрать команду /newbot и следовать подсказкам: указать название (видимое пользователям) и уникальное имя, оканчивающееся на bot.

  4. В ответ BotFather пришлёт HTTP API token — строку вида 1234567890:AA..., которая используется для авторизации бота на стороне Telegram.

  5. Сохранить токен в безопасном месте и не публиковать его в репозиториях и скриншотах.

Дальше этот токен будет использоваться в конфигурации 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, а для небольших ботов этого вполне достаточно, если нет жёстких требований по задержкам.

Базовый вариант деплоя:

  1. Поднять на сервере Python требуемой версии и скопировать туда проект (через Git, SCP или другой привычный способ).

  2. Установить зависимости с помощью pip install -r requirements.txt в виртуальном окружении.

  3. Создать на сервере файл .env с боевым токеном и ID чата администратора.

  4. Запустить python -m bot.main и убедиться по логам, что бот успешно подключился и отвечает.

  5. Для постоянной работы оформить запуск через systemd, supervisord или screen/tmux, чтобы бот перезапускался при падении и не зависел от SSH-сессии.

Документация Telegram Bot API и многочисленные практические статьи подчёркивают, что long polling остаётся валидным и надёжным вариантом для большого числа use-case’ов, особенно когда нагрузка невысока.

Комментарии (0)