Создание бота для заказов на Aiogram 3 с FSM и SQLite

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

Создание бота для заказов на Aiogram 3 с FSM и SQLite

Введение: почему именно Aiogram 3 и FSM?

Telegram-боты сегодня стали самым удобным инструментом для связи с клиентами в сфере бизнеса и услуг. Автоматизированные боты для приема заказов особенно востребованы среди владельцев малого бизнеса и фрилансеров. В этой статье мы шаг за шагом создадим бота для приема заказов с помощью Python и современной библиотеки Aiogram 3.

В ходе проекта мы будем использовать технологию FSM (Finite State Machine — конечный автомат) для поэтапного сбора данных от пользователя и базу данных SQLite для сохранения полученной информации.

1. Подготовка рабочего окружения

Сначала создадим отдельное виртуальное окружение для нашего проекта и установим необходимые библиотеки. Выполните следующие команды в терминале:

python -m venv venv
source venv/bin/activate  # Для Windows: venv\Scripts\activate
pip install aiogram aiosqlite

Файловая структура нашего проекта будет выглядеть следующим образом:

  • main.py — основной файл запуска бота;
  • database.py — модуль для асинхронной работы с SQLite;
  • handlers.py — обработчики процесса заказа и команд;
  • states.py — описание состояний FSM.

2. Настройка базы данных (database.py)

Для асинхронной записи заказов в базу данных мы используем библиотеку aiosqlite. Это увеличивает скорость работы бота и предотвращает задержки в очереди запросов.

import aiosqlite

DB_NAME = "orders.db"

async def init_db():
    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute("""
            CREATE TABLE IF NOT EXISTS orders (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                user_id INTEGER,
                full_name TEXT,
                phone_number TEXT,
                product_name TEXT,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        """)
        await db.commit()

async def add_order(user_id: int, full_name: str, phone: str, product: str):
    async with aiosqlite.connect(DB_NAME) as db:
        await db.execute(
            "INSERT INTO orders (user_id, full_name, phone_number, product_name) VALUES (?, ?, ?, ?)",
            (user_id, full_name, phone, product)
        )
        await db.commit()

3. Определение состояний FSM (states.py)

В процессе оформления заказа пользователь проходит 3 шага: вводит имя, отправляет номер телефона и указывает наименование товара. Для этого создадим класс StatesGroup:

from aiogram.fsm.state import State, StatesGroup

class OrderState(StatesGroup):
    full_name = State()
    phone_number = State()
    product_name = State()

4. Обработка сообщений (handlers.py)

Теперь напишем логику работы бота. Когда пользователь вводит /start или /order, запускается FSM, и данные с каждого шага сохраняются в памяти:

from aiogram import Router, F
from aiogram.types import Message, ReplyKeyboardMarkup, KeyboardButton, ReplyKeyboardRemove
from aiogram.filters import CommandStart, Command
from aiogram.fsm.context import FSMContext
from states import OrderState
from database import add_order

router = Router()

@router.message(CommandStart())
async def start_cmd(message: Message):
    await message.answer(
        f"Здравствуйте, {message.from_user.first_name}!\n"
        "Для оформления заказа отправьте команду /order."
    )

@router.message(Command("order"))
async def order_start(message: Message, state: FSMContext):
    await state.set_state(OrderState.full_name)
    await message.answer("Пожалуйста, введите ваше полное имя:")

@router.message(OrderState.full_name)
async def process_name(message: Message, state: FSMContext):
    await state.update_data(full_name=message.text)
    await state.set_state(OrderState.phone_number)
    
    phone_btn = ReplyKeyboardMarkup(
        keyboard=[[KeyboardButton(text="Отправить номер", request_contact=True)]],
        resize_keyboard=True,
        one_time_keyboard=True
    )
    await message.answer("Отправьте ваш номер телефона или введите его вручную:", reply_markup=phone_btn)

@router.message(OrderState.phone_number)
async def process_phone(message: Message, state: FSMContext):
    if message.contact:
        phone = message.contact.phone_number
    else:
        phone = message.text
    
    await state.update_data(phone_number=phone)
    await state.set_state(OrderState.product_name)
    await message.answer("Какой товар или услугу вы хотите заказать?", reply_markup=ReplyKeyboardRemove())

@router.message(OrderState.product_name)
async def process_product(message: Message, state: FSMContext):
    product = message.text
    user_data = await state.get_data()
    
    full_name = user_data.get("full_name")
    phone = user_data.get("phone_number")
    
    # Сохранение в базу данных
    await add_order(message.from_user.id, full_name, phone, product)
    
    # Очистка состояния
    await state.clear()
    
    await message.answer(
        "Спасибо! Ваш заказ успешно принят.\n\n"
        f"Имя: {full_name}\n"
        f"Телефон: {phone}\n"
        f"Товар: {product}\n\n"
        "В скором времени оператор свяжется с вами!"
    )

5. Запуск бота (main.py)

В основном файле объединим бота и диспетчер, инициализируем базу данных и запустим бота в режиме polling:

import asyncio
import logging
from aiogram import Bot, Dispatcher
from database import init_db
from handlers import router

BOT_TOKEN = "ВАШ_ТОКЕН_БОТА"

async def main():
    logging.basicConfig(level=logging.INFO)
    bot = Bot(token=BOT_TOKEN)
    dp = Dispatcher()
    
    # Инициализация базы данных
    await init_db()
    
    # Подключение роутеров
    dp.include_router(router)
    
    print("Бот успешно запущен!")
    await dp.start_polling(bot)

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except (KeyboardInterrupt, SystemExit):
        print("Бот остановлен.")

Практические советы и расширение функционала

Для дальнейшего улучшения этого проекта вы можете добавить следующие возможности:

  1. Админ-панель: отправка уведомлений в Telegram-профиль администратора или специальную группу при поступлении нового заказа.
  2. Валидация: использование модуля regular expressions (re) для проверки корректности введенного формата номера телефона.
  3. Inline-кнопки: отображение списка товаров и предоставление пользователю возможности выбора с помощью кнопок вместо ручного ввода текста.

Заключение

Возможности FSM в Aiogram 3 позволяют организовать взаимодействие с пользователями структурированно и без ошибок. Вы можете включить этот готовый шаблон в свое портфолио или предложить его клиентам из малого бизнеса в качестве системы приема заказов.

Теги: #aiogram 3 #telegram bot #python darslari #sqlite #fsm