ITcoDe.Uz ← Maqolalar

Telegram

aiogram 3 bilan buyurtma qabul qiluvchi Telegram bot

Kichik biznes uchun Telegram bot ko'pincha saytdan foydaliroq: mijoz allaqachon shu ilovada, ro'yxatdan o'tish shart emas, xabar darhol keladi.

Bakhrullo Nasrulloyev2026-08-14~8 daqiqa

aiogram 3 va 2 farqi

Internetdagi ko'p namuna hali ham 2-versiyada yozilgan va ular 3-versiyada ishlamaydi. Asosiy farqlar:

aiogram 2aiogram 3
Handler@dp.message_handler@router.message
FiltrlarArgument sifatidaAlohida obyekt
TuzilmaDispatcher markaziyRouter'lar
Ishga tushirishexecutorasyncio.run

Router'lar tizimi katta botni bo'laklarga ajratish imkonini beradi — buyurtma alohida faylda, admin alohida faylda.

Skelet

import asyncio, logging
from aiogram import Bot, Dispatcher, Router, F
from aiogram.filters import CommandStart
from aiogram.fsm.storage.memory import MemoryStorage

router = Router()

async def main():
    bot = Bot(token=TOKEN)
    dp  = Dispatcher(storage=MemoryStorage())
    dp.include_router(router)
    await dp.start_polling(bot)

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(main())

FSM — bosqichma-bosqich suhbat

Buyurtma bir xabarda kelmaydi. Avval mahsulot, keyin miqdor, keyin manzil, keyin telefon. Bot har foydalanuvchi qaysi bosqichda ekanini eslab turishi kerak.

Buning uchun holat mashinasi ishlatiladi:

from aiogram.fsm.state import State, StatesGroup

class Order(StatesGroup):
    product = State()
    qty     = State()
    address = State()
    phone   = State()
    confirm = State()

Har bosqichda javob olinadi, saqlanadi va keyingi holatga o'tiladi:

@router.message(CommandStart())
async def start(msg, state):
    await state.clear()
    await state.set_state(Order.product)
    await msg.answer("Nima buyurtma qilamiz?", reply_markup=menu_kb())

@router.message(Order.qty, F.text.regexp(r"^\d+$"))
async def get_qty(msg, state):
    await state.update_data(qty=int(msg.text))
    await state.set_state(Order.address)
    await msg.answer("Manzilni yozing yoki joylashuvni yuboring.")

Muhim detal. F.text.regexp filtri faqat raqam kiritilgandagina ishlaydi. Agar foydalanuvchi matn yozsa, bu handler chaqirilmaydi. Shuning uchun har bosqich uchun "noto'g'ri kiritish" handleri ham kerak, aks holda bot jim qoladi va foydalanuvchi nima bo'lganini tushunmaydi.

@router.message(Order.qty)
async def qty_invalid(msg):
    await msg.answer("Faqat raqam kiriting. Masalan: 2")

Tartib muhim — aniqroq filtr yuqorida, umumiysi pastda turishi kerak.

Tugmalar

Matn kiritishdan ko'ra tugma bosish qulayroq va xato kamroq bo'ladi:

from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton

def menu_kb():
    rows = [
        [InlineKeyboardButton(text=p["name"],
                              callback_data=f"p:{p['id']}")]
        for p in PRODUCTS
    ]
    return InlineKeyboardMarkup(inline_keyboard=rows)

@router.callback_query(F.data.startswith("p:"))
async def pick(cb, state):
    pid = cb.data.split(":")[1]
    await state.update_data(product=pid)
    await state.set_state(Order.qty)
    await cb.message.answer("Nechta kerak?")
    await cb.answer()

Oxirgi qator — cb.answer() — unutilmasin. Usiz Telegram tugmada aylanuvchi belgi ko'rsatib turadi va foydalanuvchi bot osilib qolgan deb o'ylaydi.

Xotira muammosi

MemoryStorage holatni operativ xotirada saqlaydi. Bot qayta ishga tushsa, barcha yarim tugallangan buyurtmalar yo'qoladi.

Ishlab chiqarish uchun men SQLite yoki Redis ishlataman. Kichik botlar uchun aiosqlite yetarli — alohida server kerak emas, fayl sifatida saqlanadi.

Buyurtmani yakunlash

Barcha ma'lumot yig'ilgach, tasdiqlash ko'rsatiladi va adminlarga xabar yuboriladi:

@router.callback_query(F.data == "confirm")
async def confirm(cb, state, bot):
    data = await state.get_data()
    oid  = await save_order(data, cb.from_user.id)

    text = (f"🆕 Buyurtma #{oid}\n"
            f"Mahsulot: {data['product']} × {data['qty']}\n"
            f"Manzil: {data['address']}\n"
            f"Telefon: {data['phone']}")

    for admin in ADMINS:
        try:
            await bot.send_message(admin, text)
        except Exception as e:
            logging.warning("admin %s: %s", admin, e)

    await state.clear()
    await cb.message.answer(f"Qabul qilindi. Raqam: #{oid}")

try/except shart. Agar admin botni bloklagan bo'lsa, xato chiqadi va u tsiklni to'xtatib, qolgan adminlarga xabar bormay qoladi.

Joylashtirish

Bot uzluksiz ishlashi kerak, ya'ni server talab qilinadi. Bepul variantlar orasida Render va Railway qulay.

Ammo bepul tarifda muhim cheklov bor: bir muddat so'rov bo'lmasa, xizmat uxlab qoladi. Birinchi xabar kelganda esa u uyg'onishga 30–50 soniya sarflaydi va foydalanuvchi javob kutib qoladi.

Yechim — tashqi cron xizmati orqali har 10 daqiqada bir marta so'rov yuborish. Buning uchun botga oddiy HTTP endpoint qo'shiladi:

from aiohttp import web

async def health(request):
    return web.Response(text="ok")

app = web.Application()
app.router.add_get("/health", health)

Keyin cron-job.org kabi bepul xizmatda shu manzilga muntazam so'rov sozlanadi.

Xulosa

aiogram 3 da bot yozish murakkab emas, lekin uchta joyda ehtiyot bo'lish kerak: handler tartibi, holat saqlash usuli va bepul hostingdagi uyqu rejimi.

Bu uchtasi to'g'ri qo'yilsa, bot barqaror ishlaydi va mijoz uni sayt o'rniga ishlatishga rozi bo'ladi.

Telegramaiogram 3PythonFSMBot