01 β Telegram botlar va aiogram bilan tanishuv¶
π README Β· π README Β· Keyingi: 02 β Birinchi bot: echo va /start β‘οΈ
Bu bobda: Telegram bot aslida nima ekanini, "klient β Telegram serveri β bot" uchligi qanday ishlashini va Bot API'ning roli nimadaligini tushunamiz. @BotFather'dan
/newbotorqali token olishni, tokenni.envfaylida xavfsiz saqlashni o'rganamiz. Polling va webhook usullarini umumiy ko'rinishda solishtiramiz: qaysi biri qachon kerak. Nega aynan aiogram 3.x (async, modulyar, magic-filter) tanlanishini ko'rib chiqamiz, unipip install aiogrambilan o'rnatamiz va ekotizimini (Bot API, aiohttp, FSM, klaviatura quruvchilar) tanishtiramiz. Oxiridaaiogram 2.xva3.xorasidagi muhim farqlarga kirib, nega bu kitobda faqat 3.x idiomi ishlatilishini ko'rsatamiz.Bu kitob siz Python asoslarini (async/await, dekorator, klass,
venv,pip, type hints) bilasiz deb faraz qiladi β kerak bo'lsa ../python/README.md ga qayting. Bu yerda esa Telegram va aiogram'ga xos HAR narsani noldan tushuntiramiz.Halol eslatma (verifikatsiya): Bu bobdagi handler marshruti (routing) va token formatini tekshirish kodi haqiqatan offline (tokensiz, internetsiz) ishga tushirib tekshirildi β
Dispatcher.feed_update()ga soxtaUpdateuzatib,bot.sessionmock qilingan holatda. Ammo jonli botni Telegram'ga ulash (long-polling, real xabar yuborish,getMe) BotFather'dan olingan haqiqiy token + internet talab qiladi β bunday bloklarni "illustrativ β jonli Telegram kerak" deb halol belgilab qo'yganmiz.
1. Telegram bot nima?¶
Telegram bot β bu Telegram ichida ishlaydigan maxsus dastur. U xuddi oddiy foydalanuvchi kabi xabar oladi va yuboradi, lekin orqasida jonli odam emas, balki siz yozgan kod turadi. Bot tugma bosishlariga javob beradi, ma'lumotlar bazasidan o'qiydi, API'larga so'rov yuboradi, fayl yuboradi β qisqasi, siz dasturlay olgan hamma narsani qila oladi.
Oddiy foydalanuvchi akkauntidan farqi:
- Botda telefon raqami yo'q; u token orqali tanilinadi.
- Bot odamga birinchi yozolmaydi β foydalanuvchi avval botga yozishi (yoki guruhga qo'shishi) kerak.
- Bot xabarlarni faqat o'ziga yuborilganda yoki guruhda chaqirilganda ko'radi (maxfiylik uchun).
- Bot maxsus imkoniyatlarga ega: inline tugmalar, klaviaturalar, to'lovlar, web app va hokazo.
Bot bilan ishlash uchun Telegram Bot API degan rasmiy interfeysni beradi. Sizning kodingiz hech qachon foydalanuvchining telefoni bilan to'g'ridan-to'g'ri gaplashmaydi β hammasi Telegram serveri orqali o'tadi.
2. Bot API qanday ishlaydi: klient β server β bot¶
Eng muhim tushuncha: bot va foydalanuvchi o'rtasida har doim Telegram serveri turadi. Hech kim hech kim bilan to'g'ridan-to'g'ri bog'lanmaydi.
Oqimni qadamma-qadam ko'rib chiqaylik:
- Foydalanuvchi Telegram klientida (telefon yoki desktop) botga "Salom" deb yozadi.
- Bu xabar Telegram serveriga (
api.telegram.org) boradi va u yerda saqlanadi. - Telegram bu xabarni Update (yangilik) ko'rinishida sizning botingizga yetkazadi.
- Sizning kodingiz Update'ni o'qiydi, mantiqni bajaradi va
sendMessagechaqiruvi bilan javob qaytaradi. - Telegram bu javobni foydalanuvchining ekraniga yetkazadi.
Update β bu Telegram sizga yuboradigan "nimadir bo'ldi" signali. Update turlari ko'p: yangi xabar (message), tugma bosildi (callback_query), xabar tahrirlandi (edited_message), guruhga a'zo qo'shildi va hokazo. Bu kitob davomida ko'pincha message va callback_query bilan ishlaymiz.
Bot API REST uslubidagi HTTP API: siz https://api.telegram.org/bot<TOKEN>/<metod> manziliga so'rov yuborasiz. Masalan, xabar yuborish metodi sendMessage. Yaxshi yangilik β aiogram bu chaqiruvlarni siz uchun bajaradi, siz message.answer("Salom") deb yozasiz, xolos. Lekin orqada nima bo'layotganini bilish foydali.
Eslatma: Bot API bilan Telegram MTProto API (Telethon, Pyrogram kabi kutubxonalar ishlatadigan) β boshqa-boshqa narsalar. Bot API rasmiy, sodda va botlar uchun mo'ljallangan. Bu kitob faqat Bot API bilan ishlaydi.
3. @BotFather'dan token olish¶
Botingiz mavjud bo'lishi uchun avval uni ro'yxatdan o'tkazish kerak. Buni Telegram'ning rasmiy boti β @BotFather qiladi. BotFather β botlarni yaratuvchi bot.
Qadamlar:
- Telegram'da @BotFather ni oching (rasmiy, ko'k tasdiq belgili).
/newbotbuyrug'ini yuboring.- Botingizga ko'rinadigan nom bering (masalan,
Mening Birinchi Botim). - So'ng username bering β u albatta
botbilan tugashi kerak (masalan,mening_birinchi_bot) va noyob bo'lishi shart. - BotFather sizga tokenni beradi. U taxminan shunday ko'rinadi:
Bu token β botingizning paroli. Token bilan kim botingizni boshqara oladi. Shuning uchun:
- Tokenni hech kimga bermang, GitHub'ga, skrinshotga, video'ga qo'ymang.
- Agar token sizib chiqsa, BotFather'da
/revokebilan yangisini oling.
BotFather'ning boshqa foydali buyruqlari:
/mybots - botlaringiz ro'yxati va sozlamalari
/setname - bot nomini o'zgartirish
/setdescription - bot tavsifi (chat ochilganda ko'rinadi)
/setuserpic - bot avatari
/setcommands - / bosilganda chiqadigan buyruqlar menyusi
/token - mavjud bot tokenini qayta ko'rsatish
/revoke - tokenni bekor qilib, yangisini olish
/deletebot - botni o'chirish
Token olish jonli Telegram ilovasida amalga oshiriladi β buni kod bilan tekshirib bo'lmaydi (illustrativ qadam). Lekin pastda tokenni formatini offline tekshirgan kodimiz bor.
4. Tokenni xavfsiz saqlash: .env¶
Tokenni hech qachon kod ichiga yozmang. Agar yozsangiz va kodni GitHub'ga qo'ysangiz, token ochiq qoladi. To'g'ri yo'l β uni .env faylida saqlash va kodda muhit o'zgaruvchisi (environment variable) sifatida o'qish.
python-dotenv paketini o'rnatamiz:
Loyiha papkasida .env faylini yarating:
Va .gitignore ga .env ni albatta qo'shing, toki u Git'ga tushib qolmasin:
Endi kodda tokenni shunday o'qiymiz:
import os
from dotenv import load_dotenv
load_dotenv() # .env faylidagi o'zgaruvchilarni yuklaydi
BOT_TOKEN = os.getenv("BOT_TOKEN")
if not BOT_TOKEN:
raise RuntimeError("BOT_TOKEN topilmadi! .env faylini tekshiring.")
Token to'g'ri formatda ekanini aiogram o'zi tekshiradi. Buni offline ko'rsatish mumkin:
from aiogram.utils.token import validate_token, TokenValidationError
# To'g'ri formatdagi (lekin soxta) token tekshiruvdan o'tadi:
print(validate_token("123456:AAH-FakeTest_abc")) # True
# Buzilgan token xato beradi:
try:
validate_token("not-a-token")
except TokenValidationError as e:
print("Token formati noto'g'ri:", e)
Offline tekshirildi: yuqoridagi
validate_tokenkodi haqiqatan ishga tushirildi β soxta tokenTrue, buzilgan tokenTokenValidationErrorqaytardi. Bu format tekshiruvi, Telegram'ga ulanish emas β token haqiqiy ishlashini faqat jonligetMebilan bilish mumkin.
5. Polling va webhook: ikki yetkazib berish usuli¶
Telegram update'larni botingizga ikki xil yo'l bilan yetkazadi. Ikkalasini ham bilish kerak, lekin rivojlash bosqichida har doim polling ishlatamiz.
Polling (so'rab-tortish)¶
Botning o'zi Telegram'dan muntazam ravishda "menga yangi xabar bormi?" deb so'raydi (getUpdates metodi). Telegram bo'lsa, yangiliklarni qaytaradi. aiogram'da bu long-polling ko'rinishida amalga oshadi β await dp.start_polling(bot) chaqiruvi shu ishni qiladi.
- Afzalligi: hech qanday public URL kerak emas, kompyuteringizdagi
localhostda ham ishlaydi. Rivojlash va o'rganish uchun ideal. - Kamchiligi: bot doimiy so'rab turadi, juda katta yuklamalarda biroz samarasiz.
Webhook (itarish)¶
Bu yerda aksincha: siz Telegram'ga "yangi xabar kelganda, mana shu HTTPS manzilga o'zing yubor" deysiz. Telegram update'ni sizning serveringizdagi URL'ga POST qiladi.
- Afzalligi: tezkor, kam yuk, minglab foydalanuvchili botlar uchun mos.
- Kamchiligi: sizda public HTTPS URL (domen + SSL sertifikat) bo'lishi shart. Sozlash murakkabroq.
Qoida: o'rganayotganda va lokal ishlaganda β polling. Productionga chiqarishda, server tayyor bo'lganda β webhook'ni ko'rib chiqamiz (deploy bobida). Bu kitobning katta qismi polling bilan ishlaydi.
Polling ham, webhook ham jonli Telegram serveri va token talab qiladi β ularni offline ishga tushirib bo'lmaydi (illustrativ). Lekin handler mantig'ini token va internetsiz
feed_updateorqali to'liq tekshirsa bo'ladi β buni keyingi bo'limda ko'rasiz.
6. Nega aiogram?¶
Telegram bot yozish uchun Python'da bir nechta kutubxona bor. Eng mashhurlari: aiogram, python-telegram-bot, pyTelegramBotAPI (telebot). Bu kitob aiogram 3.x ni tanlaydi. Sabablari:
- Async β aiogram
asyncioustiga qurilgan. Bot ko'p foydalanuvchiga bir vaqtda javob berishi kerak; async buni samarali qiladi. Siz Python'daasync/awaitbilan tanish bo'lsangiz, o'zingizni uyda his qilasiz. - Modulyar β
Router'lar yordamida katta botni mantiqiy bo'laklarga ajratish oson. Bu loyiha o'sganda tartibni saqlaydi. - Magic-filter (
F) βF.text == "salom"kabi qisqa, o'qishga oson filtrlar. Bu aiogram'ning eng yoqimli xususiyatlaridan biri. - Type hints β hamma narsa to'liq tiplangan, IDE avtoto'ldirishi ajoyib ishlaydi.
- FSM (holatlar mashinasi) β ko'p qadamli suhbatlar (masalan, anketa to'ldirish) uchun ichki qurilgan tizim.
- Faol jamiyat va hujjatlar β docs.aiogram.dev yangilanib turadi.
Solishtirish uchun: Node.js ekotizimida shunga o'xshash vazifani grammY yoki Telegraf bajaradi β agar JavaScript bilan ishlamoqchi bo'lsangiz, ../nodejs/README.md ga qarang. Tushunchalar (update, polling, webhook) bir xil, faqat sintaksis farq qiladi.
7. aiogram'ni o'rnatish¶
aiogram 3.x Python 3.9+ talab qiladi. Bu kitob Python 3.14 va aiogram 3.28 bilan tekshirilgan.
Avval loyihaga alohida virtual muhit (venv) yarating β bu Python amaliyoti, agar venv bilan tanish bo'lmasangiz ../python/README.md ga qarang:
python -m venv .venv
# Windows (PowerShell):
.venv\Scripts\Activate.ps1
# Linux / macOS:
source .venv/bin/activate
So'ng aiogram'ni o'rnating:
O'rnatilganini tekshiramiz:
Natija (illustrativ β sizning versiyangiz yangiroq bo'lishi mumkin):
aiogram bilan birga uning asosiy bog'liqliklari ham keladi β eng muhimi aiohttp (async HTTP klient/server; Telegram bilan tarmoq aloqasini shu bajaradi):
Keyingi boblarda quyidagilarni ham o'rnatamiz (hozir shart emas, faqat ekotizimni ko'rsatish uchun):
pip install python-dotenv # .env fayllari uchun
pip install aiosqlite # async SQLite (DB bobi)
pip install "sqlalchemy[asyncio]" # ORM, async rejimda (kengaytirilgan DB)
pip install redis # FSM uchun RedisStorage (production)
8. aiogram ekotizimi: nimadan iborat?¶
aiogram bitta kutubxona, lekin ichida ko'p qism bor. Hozir nomlari bilan tanishib qo'ying β har birini alohida bobda chuqur ko'ramiz:
| Komponent | Nima qiladi | Qaysi bobda |
|---|---|---|
Bot |
Telegram Bot API bilan gaplashadi (send_message, send_photo, ...) |
02 |
Dispatcher |
Update'larni qabul qilib, mos handlerga yo'naltiradi | 02 |
Router |
Handlerlarni mantiqiy guruhlarga bo'ladi | 03 |
Filtrlar (Command, F, ...) |
Qaysi update qaysi handlerga borishini hal qiladi | 03 |
| Klaviatura quruvchilar | Tugmalar va inline tugmalar yasaydi | 05 |
FSM (StatesGroup, FSMContext) |
Ko'p qadamli suhbatlar uchun holat saqlaydi | 06 |
| Middleware | Har update'dan oldin/keyin umumiy mantiq | 07 |
Update bot ichida qanday yo'l bosishini sxemada ko'rib chiqaylik:
Mantiq sodda: Update keladi -> Dispatcher uni qabul qiladi -> mos Router'ga beradi -> Router filtrlarni tartib bilan tekshiradi -> birinchi mos kelgan handler ishlaydi. Hech bir filtr mos kelmasa, update e'tiborsiz qoldiriladi (bu xato emas).
9. Birinchi "kostyumsiz" misol va uni OFFLINE tekshirish¶
Keyingi bobda to'liq botni yozamiz, lekin hozir aiogram 3.x idiomi qanday ko'rinishini ko'ring. Bu kod handler'larni ro'yxatdan o'tkazadi va β eng muhimi β biz uni token va internetsiz ishlatib, marshrut to'g'ri ishlashini isbotlay olamiz.
Mana to'liq, ishlaydigan tekshiruv skripti (biz uni haqiqatan ishga tushirdik):
import asyncio
from datetime import datetime
from unittest.mock import AsyncMock
from aiogram import Bot, Dispatcher, Router
from aiogram.filters import CommandStart, Command
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, Update, Chat, User
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
FAKE_TOKEN = "123456:AAH-FakeTest_abc" # soxta, lekin to'g'ri formatda
router = Router()
seen = [] # qaysi handler ishlaganini yozib boramiz
@router.message(CommandStart()) # 3.x idiomi: Router + Command filtri
async def start_handler(message: Message) -> None:
seen.append("start")
await message.answer(f"Salom, {message.from_user.first_name}!")
@router.message(Command("help"))
async def help_handler(message: Message) -> None:
seen.append("help")
await message.answer("Yordam matni")
def make_update(text: str) -> Update:
"""Telegram'dan kelgandek soxta Update yasaymiz."""
msg = Message(
message_id=1,
date=datetime.now(),
chat=Chat(id=1, type="private"),
from_user=User(id=1, is_bot=False, first_name="Test"),
text=text,
)
return Update(update_id=1, message=msg)
async def main():
bot = Bot(
token=FAKE_TOKEN,
default=DefaultBotProperties(parse_mode=ParseMode.HTML),
)
bot.session = AsyncMock() # tarmoqni mock qilamiz: answer() Telegram'ga ketmaydi
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(router) # 3.x idiomi: routerni dispatcherga ulaymiz
# Telegram o'rniga biz update'ni "qo'lda" beramiz:
await dp.feed_update(bot, make_update("/start"))
await dp.feed_update(bot, make_update("/help"))
await dp.feed_update(bot, make_update("oddiy matn")) # hech qaysi filtrga mos emas
await bot.session.close()
print("Ishlagan handlerlar:", seen)
assert seen == ["start", "help"] # uchinchi update hech kimga bormadi
print("Marshrut to'g'ri ishladi.")
if __name__ == "__main__":
asyncio.run(main())
Natija (haqiqatan ishga tushirildi):
E'tibor bering:
Dispatcher()vaRouter()β 3.x'ning asosiy quruvchilari.dp.include_router(router)orqali ulanadi.@router.message(CommandStart())va@router.message(Command("help"))β 3.x idiomi. Eski@dp.message_handler(commands=[...])ISHLATILMAYDI.dp.feed_update(bot, update)β Telegram o'rniga update'ni qo'lda berish. Aynan shu bizga tokensiz, internetsiz tekshirish imkonini beradi.bot.session = AsyncMock()βmessage.answer()ichida Telegram'ga so'rov ketmasligi uchun tarmoq qatlamini mock qilamiz. Real bot bo'lsa, bu yerda haqiqiy xabar yuborilardi.- Uchinchi update ("oddiy matn") hech qaysi filtrga mos kelmagani uchun e'tiborsiz qoldirildi β
seenro'yxatida yo'q.
Halol farq: Yuqoridagi kod handler marshrutini isbotlaydi β
/startva/helpto'g'ri handlerlarga bordi. Lekin foydalanuvchi ekranida "Salom" ko'rinishi β bu jonli Telegram + token talab qiladigan qism (illustrativ). Bizbot.sessionni mock qilganimiz uchun real xabar ketmadi; mantiqning to'g'riligi esa to'liq tekshirildi.
10. aiogram 2.x va 3.x: muhim farqlar¶
Internetda aiogram bo'yicha juda ko'p eski (2.x) misollar bor. Ular bu kitobda ISHLAMAYDI. 3.x β to'liq qayta yozilgan, idiomi boshqacha. Quyidagi jadval eng muhim farqlarni ko'rsatadi β eski kodga duch kelsangiz, shu jadval bilan "tarjima" qiling.
| Vazifa | β aiogram 2.x (ESKIRGAN) | β aiogram 3.x (TO'G'RI) |
|---|---|---|
| Handler qo'shish | @dp.message_handler(...) |
@router.message(...) |
| Buyruq filtri | @dp.message_handler(commands=["start"]) |
@router.message(Command("start")) |
| Pollingni boshlash | executor.start_polling(dp) |
await dp.start_polling(bot) |
| Botni yaratish | Bot(token, parse_mode="HTML") |
Bot(token, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) |
| ParseMode joyi | types.ParseMode.HTML |
aiogram.enums.ParseMode.HTML |
| Routing tuzilmasi | faqat Dispatcher |
Router + dp.include_router(r) |
| Klaviatura | ReplyKeyboardMarkup(row_width=2).add(...) |
ReplyKeyboardBuilder() (utils.keyboard) |
| Kontent turi | content_types=["text"] |
F.text magic-filter |
Eng tipik xato β aiogram 2.x'dagi executor va @dp.message_handler ni ishlatishga urinish:
# β ESKI 2.x β aiogram 3.x da MUTLAQO ISHLAMAYDI:
from aiogram import Bot, Dispatcher, executor, types
bot = Bot(token=TOKEN, parse_mode="HTML") # β parse_mode bu yerda emas
dp = Dispatcher(bot) # β Dispatcher endi botni qabul qilmaydi
@dp.message_handler(commands=["start"]) # β bunday dekorator yo'q
async def start(message: types.Message):
await message.answer("Salom")
executor.start_polling(dp, skip_updates=True) # β executor moduli olib tashlangan
3.x'da xuddi shu narsa quyidagicha yoziladi:
# β
TO'G'RI 3.x:
import asyncio
from aiogram import Bot, Dispatcher, Router
from aiogram.filters import Command
from aiogram.types import Message
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
router = Router()
@router.message(Command("start"))
async def start(message: Message) -> None:
await message.answer("Salom")
async def main() -> None:
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher()
dp.include_router(router)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())
Oltin qoida: Agar topgan misolingizda
executor,message_handler, yokiDispatcher(bot)bo'lsa β bu eski 2.x. Uni ishlatmang. Shubha tug'ilsa, docs.aiogram.dev (stable = 3.x) ga qarang. Bu kitobdagi har bir kod faqat 3.x idiomida yozilgan va tekshirilgan.
11. Yo'l xaritasi: keyin nima bo'ladi¶
Endi tushunchalar joyida. Keyingi yo'limiz:
- 02-bob β birinchi to'liq botni yozamiz:
/start, echo (foydalanuvchi yozganini qaytaruvchi) vastart_pollingbilan jonli ishga tushirish. - 03-bob β Router'lar, filtrlar (
Command,Fmagic-filter) chuqurroq. - 04-05 β xabar turlari, klaviaturalar va inline tugmalar.
- 06 β FSM bilan ko'p qadamli suhbatlar (anketa).
- 07 β middleware.
- Keyin β ma'lumotlar bazasi (../sql/README.md bilan bog'liq), to'lovlar va deploy (../git-github/README.md).
Mashqlar¶
Oson¶
-
Uchlikni chizing. Foydalanuvchi botga "Salom" yozganda xabar qaysi yo'ldan o'tadi? Klient, Telegram serveri va bot orasidagi 4-5 qadamni o'z so'zlaringiz bilan tartibda yozing.
-
Token formati. Quyidagilardan qaysi biri Telegram bot tokeniga o'xshaydi, qaysi biri yo'q? Sababini ayting: (a)
123456789:AAH-Abc123DefGhi, (b)salom-dunyo, (c)abcdef. -
Polling yoki webhook? Quyidagi vaziyatlar uchun qaysi usul to'g'ri keladi: (a) uyda noutbukda o'rganyapsiz, (b) minglab foydalanuvchili botni public serverda ishlatyapsiz, (c) sizda HTTPS domen yo'q.
-
BotFather buyruqlari. Botingiz nomini o'zgartirish,
/menyusidagi buyruqlarni o'rnatish va tokenni bekor qilish uchun BotFather'ning qaysi buyruqlaridan foydalanasiz? -
.envxavfsizligi. Nega tokenni to'g'ridan-to'g'ri.pyfaylga yozish xavfli?.envfaylini Git'ga tushib qolishidan qanday himoya qilamiz? -
Versiyani tekshiring. Kompyuteringizda aiogram qaysi versiyada o'rnatilganini ko'rsatadigan bitta qatorlik buyruqni yozing (kod ichida ham, terminalda ham).
O'rta¶
-
2.x'ni 3.x'ga tarjima qiling. Quyidagi eski kodni 3.x idiomiga aylantiring:
-
Soxta Update yasang.
idsi42,first_namesiAli, matni/helpbo'lgan shaxsiy (private) chatdan kelgan soxtaUpdateob'ektini yasaydigan funksiya yozing (9-bo'limdagimake_updatega o'xshash). -
Marshrutni isbotlang. 9-bo'limdagi skriptga
/aboutbuyrug'ini boshqaruvchi uchinchi handler qo'shing. So'ngfeed_updatebilan/aboutyuborib, faqat shu handler ishlaganiniassertbilan tekshiring. -
Mos kelmaslik. Foydalanuvchi
salom(buyruq emas, oddiy matn) yozsa, 9-bo'limdagi botda nima bo'ladi? Nega? Buniseenro'yxatini tekshirib isbotlang. -
Token tekshiruvchi.
validate_tokendan foydalanib, berilgan satr to'g'ri formatdagi token ekaniniTrue/Falseqaytaradiganis_valid_token(s)funksiyasini yozing (xatonitry/exceptbilan tuting). -
ParseMode joyi. aiogram 3.x'da
ParseModeqaysi moduldan import qilinadi va botda u qanday o'rnatiladi? BittaBot(...)qatori bilan ko'rsating.
Qiyin¶
-
Ikki routerli marshrut. Ikkita alohida
Routeryarating: birinchisida/start, ikkinchisida/helphandleri bo'lsin. Ikkalasini bittaDispatchergainclude_routerbilan ulang vafeed_updateorqali ikkala buyruq ham to'g'ri handlerga borishini offline tekshiring. -
pytest bilan handler testi. 9-bo'limdagi
start_handlernipytest-asyncioyordamida sinaydigan test yozing:/startyuborilganda handler ishlashini tekshiring. (Maslahat:@pytest.mark.asyncio,bot.session = AsyncMock().) -
Filtr tartibi. Ikkita handler bir xil update'ga mos kelsa (masalan, ikkalasi ham
F.text), qaysi biri ishlaydi? Ikki handlerli misol yozib,feed_updatebilan buni isbotlang va xulosa yozing. -
Xavfsizlik tahlili. Bir do'stingiz tokenini xabarda yuborib yubordi. Qanday xavf bor va u darhol nima qilishi kerak? BotFather'ning qaysi buyrug'i muammoni hal qiladi?
Yechimlar
Oson¶
1. Oqim: (1) Foydalanuvchi Telegram klientida "Salom" yozadi. (2) Xabar Telegram serveriga (api.telegram.org) boradi. (3) Telegram uni Update ko'rinishida botga yetkazadi (polling yoki webhook orqali). (4) Bot kodi update'ni o'qib, mantiqni bajaradi va sendMessage chaqiradi. (5) Telegram javobni foydalanuvchi ekraniga yetkazadi. Asosiy g'oya: bot va foydalanuvchi hech qachon to'g'ridan-to'g'ri bog'lanmaydi, har doim Telegram serveri orasida turadi.
2. (a) 123456789:AAH-Abc123DefGhi β tokenga o'xshaydi: raqamlar:harf-belgilar ko'rinishida, ikki nuqta bilan ajralgan. (b) salom-dunyo va (c) abcdef β token EMAS, chunki ikki nuqta (:) va boshida raqamli bot_id qismi yo'q. Buni offline tekshirish:
from aiogram.utils.token import validate_token, TokenValidationError
for s in ["123456789:AAH-Abc123DefGhi", "salom-dunyo", "abcdef"]:
try:
validate_token(s)
print(s, "-> formati to'g'ri")
except TokenValidationError:
print(s, "-> token EMAS")
3. (a) Uyda o'rganish -> polling (public URL kerakmas). (b) Minglab foydalanuvchili public bot -> webhook (tezkor, kam yuk). (c) HTTPS domen yo'q -> polling (webhook HTTPS URL talab qiladi).
4. Nomni o'zgartirish: /setname. Buyruqlar menyusi: /setcommands. Tokenni bekor qilib yangisini olish: /revoke. (Botlar ro'yxati: /mybots.)
5. .py faylga yozish xavfli, chunki kodni GitHub'ga yoki birovga bersangiz, token ham ochiq ketadi β token bilan kim botingizni to'liq boshqaradi. Himoya: tokenni .env da saqlash va .gitignore ga .env ni qo'shish β shunda u Git'ga umuman tushmaydi.
6. Kod ichida: import aiogram; print(aiogram.__version__). Terminalda:
O'rta¶
7. 3.x idiomi:
from aiogram import Router
from aiogram.filters import Command
from aiogram.types import Message
router = Router()
@router.message(Command("help"))
async def help_cmd(message: Message) -> None:
await message.answer("Yordam")
@dp.message_handler(commands=[...]) -> @router.message(Command(...)); types.Message -> to'g'ridan-to'g'ri Message import.
8.
from datetime import datetime
from aiogram.types import Message, Update, Chat, User
def make_update(text: str) -> Update:
msg = Message(
message_id=1,
date=datetime.now(),
chat=Chat(id=42, type="private"),
from_user=User(id=42, is_bot=False, first_name="Ali"),
text=text,
)
return Update(update_id=1, message=msg)
upd = make_update("/help")
print(upd.message.from_user.first_name, upd.message.text) # Ali /help
9. Skriptga qo'shamiz:
@router.message(Command("about"))
async def about_handler(message: Message) -> None:
seen.append("about")
await message.answer("Bu test bot")
# main() ichida:
seen.clear()
await dp.feed_update(bot, make_update("/about"))
assert seen == ["about"], seen
print("about marshruti to'g'ri")
10. Hech narsa bo'lmaydi β salom na CommandStart() ga, na Command("help") ga mos keladi (ikkalasi ham / bilan boshlanadigan buyruq filtri). Shuning uchun update e'tiborsiz qoldiriladi va seen ga hech narsa qo'shilmaydi. Isbot:
seen.clear()
await dp.feed_update(bot, make_update("salom"))
assert seen == [] # hech qaysi handler ishlamadi
11.
from aiogram.utils.token import validate_token, TokenValidationError
def is_valid_token(s: str) -> bool:
try:
validate_token(s)
return True
except TokenValidationError:
return False
print(is_valid_token("123456:AAH-FakeTest_abc")) # True
print(is_valid_token("not-a-token")) # False
12. ParseMode aiogram.enums modulidan import qilinadi va DefaultBotProperties orqali o'rnatiladi:
from aiogram import Bot
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
Bot(token, parse_mode="HTML") va types.ParseMode ishlatilmaydi.)
Qiyin¶
13. Ikki routerli to'liq, offline tekshiriladigan misol:
import asyncio
from datetime import datetime
from unittest.mock import AsyncMock
from aiogram import Bot, Dispatcher, Router
from aiogram.filters import CommandStart, Command
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, Update, Chat, User
start_router = Router()
help_router = Router()
seen = []
@start_router.message(CommandStart())
async def s(message: Message) -> None:
seen.append("start")
@help_router.message(Command("help"))
async def h(message: Message) -> None:
seen.append("help")
def upd(text: str) -> Update:
msg = Message(message_id=1, date=datetime.now(),
chat=Chat(id=1, type="private"),
from_user=User(id=1, is_bot=False, first_name="T"),
text=text)
return Update(update_id=1, message=msg)
async def main():
bot = Bot(token="123456:AAH-FakeTest_abc")
bot.session = AsyncMock()
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(start_router)
dp.include_router(help_router)
await dp.feed_update(bot, upd("/start"))
await dp.feed_update(bot, upd("/help"))
await bot.session.close()
assert seen == ["start", "help"], seen
print("Ikki router to'g'ri ishladi:", seen)
asyncio.run(main())
14. pytest-asyncio testi (faylga test_start.py deb saqlang, python -m pytest test_start.py bilan ishga tushiring):
import pytest
from datetime import datetime
from unittest.mock import AsyncMock
from aiogram import Bot, Dispatcher, Router
from aiogram.filters import CommandStart
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, Update, Chat, User
router = Router()
log = []
@router.message(CommandStart())
async def start(message: Message):
log.append(message.text)
await message.answer("Salom!")
@pytest.mark.asyncio
async def test_start_routes():
bot = Bot(token="123456:AAH-FakeTest_abc")
bot.session = AsyncMock()
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(router)
msg = Message(message_id=1, date=datetime.now(),
chat=Chat(id=1, type="private"),
from_user=User(id=1, is_bot=False, first_name="T"),
text="/start")
await dp.feed_update(bot, Update(update_id=1, message=msg))
await bot.session.close()
assert log == ["/start"]
pytest-asyncio kerak: pip install pytest-asyncio. --asyncio-mode=auto qulay.)
15. Bitta update bir nechta handlerga mos kelsa, ro'yxatdan o'tish tartibida birinchi mos kelgani ishlaydi, qolganlari ishlamaydi (handler "update'ni iste'mol qiladi"). Isbot:
import asyncio
from datetime import datetime
from unittest.mock import AsyncMock
from aiogram import Bot, Dispatcher, Router, F
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message, Update, Chat, User
router = Router()
seen = []
@router.message(F.text) # birinchi ro'yxatdan o'tdi
async def first(message: Message):
seen.append("first")
@router.message(F.text) # ikkinchisi ham mos, lekin ishlamaydi
async def second(message: Message):
seen.append("second")
async def main():
bot = Bot(token="123456:AAH-FakeTest_abc")
bot.session = AsyncMock()
dp = Dispatcher(storage=MemoryStorage())
dp.include_router(router)
msg = Message(message_id=1, date=datetime.now(),
chat=Chat(id=1, type="private"),
from_user=User(id=1, is_bot=False, first_name="T"),
text="salom")
await dp.feed_update(bot, Update(update_id=1, message=msg))
await bot.session.close()
assert seen == ["first"], seen # faqat birinchisi
print("Faqat birinchi handler ishladi:", seen)
asyncio.run(main())
16. Xavf: token β botning paroli; uni bilgan har kim botingiz nomidan xabar yuboradi, ma'lumotlarni o'qiydi, botni "o'g'irlaydi". Darhol qilinadigan ish: BotFather'da /revoke buyrug'i bilan eski tokenni bekor qilish va yangi token olish; so'ng kod/.env da yangi tokenni qo'yish. Eski token shu zahoti ishlamay qoladi, shuning uchun sizib chiqqani endi zarar bera olmaydi.
π README Β· π README Β· Keyingi: 02 β Birinchi bot: echo va /start β‘οΈ