01 β Telegram botlar va grammY bilan tanishuv¶
π README Β· Keyingi: 02 β Birinchi bot: echo va /start β‘οΈ
Bu bobda: Telegram bot aslida nima ekanini, oddiy foydalanuvchi akkauntidan farqini va nima qila olishi/qila olmasligini tushunamiz. "Foydalanuvchi β Telegram serveri β bot" uchligi qanday ishlashini, Bot API'ning oddiy HTTP API ekanini (
api.telegram.org/bot<TOKEN>/METHOD),getUpdatesvasendMessageorqali Update tushunchasini ko'rib chiqamiz. @BotFather'dan/newbotbilan token olishni, token nima ekanini (botning paroli) va uni maxfiy saqlashni o'rganamiz. Update olishning ikki yo'lini β polling va webhook β umumiy ko'rinishda solishtiramiz (chuqur farqi 13-bobda). Nega aynan grammY (zamonaviy, tez, ulkan plagin ekotizimi) tanlanishini, uning Telegraf va node-telegram-bot-api dan farqini ko'rib chiqamiz β bu juda muhim, chunki internetdagi misollarni aralashtirib yuborish eng tez-tez uchraydigan xato. Oxirida kitobning yo'l xaritasini ko'ramiz.Bu kitob siz JavaScript va Node.js asoslarini (
async/await,Promise, ESMimport,npm) bilasiz deb hisoblaydi β kerak bo'lsa ../js/README.md va ../nodejs/README.md ga qayting. Bu kitob β aiogram (Python) kitobining JavaScript ekvivalenti; tushunchalar bir xil, sintaksis farq qiladi (qiziqarli solishtirma uchun ikkalasini parallel ko'rishingiz mumkin).Halollik eslatmasi: Bu bob asosan tushunchaviy β jonli kod kam. 9-bo'limdagi kichik handler misolini biz haqiqatan offline (tokensiz, internetsiz) ishga tushirib tekshirdik: soxta
Updatenibot.handleUpdatega uzatib, chiqayotgan API chaqiruvlarini transformer bilan ushlab. Natija matnda ko'rsatilgan. Ammo jonli ishlash β Telegram'ga polling/webhook ulanishi, real xabar yuborish β @BotFather'dan olingan haqiqiy token + internet talab qiladi; bunday bloklarni "illustrativ β jonli Telegram kerak" deb 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, boshqa API'larga so'rov yuboradi, fayl yuboradi β qisqasi, siz dasturlay olgan deyarli hamma narsani qila oladi.
Oddiy foydalanuvchi akkauntidan farqi:
- Botda telefon raqami yo'q; u token orqali tanilinadi (tokenni 3-bo'limda ko'ramiz).
- Bot odamga birinchi yozolmaydi β foydalanuvchi avval botga yozishi (yoki guruhga qo'shishi, yoki tugma bosishi) kerak. Bu spam'ning oldini oladi.
- Bot xabarlarni faqat o'ziga to'g'ridan-to'g'ri yuborilganda, yoki guruhda buyruq orqali chaqirilganda ko'radi (bu "privacy mode", 19-bobda batafsil).
- Bot maxsus imkoniyatlarga ega: inline tugmalar, klaviaturalar, to'lovlar, Web App (Mini App) va hokazo.
Bot nima QILA OLADI va nima QILA OLMAYDI¶
Yangi boshlovchilar ko'pincha botdan imkonsiz narsani kutadi. Quyidagi jadval chegaralarni aniq ko'rsatadi:
| β Bot QILA OLADI | β Bot QILA OLMAYDI |
|---|---|
| Foydalanuvchi yozganda javob berish | Foydalanuvchiga o'zi birinchi yozish (oldin u yozmasa) |
| Xabar, rasm, fayl, video, ovoz yuborish | Boshqa odamning shaxsiy chatlarini o'qish |
| Inline/reply tugmalar, menyu ko'rsatish | Foydalanuvchining telefon raqamini ruxsatsiz olish (faqat tugma orqali so'raydi) |
| Guruhda moderatsiya qilish (admin bo'lsa) | Admin bo'lmagan guruhda hamma xabarni ko'rish (privacy mode) |
| To'lov qabul qilish, Telegram Stars | Foydalanuvchi o'rniga uning akkauntidan ish qilish |
| Web App (Mini App) ochish | Telegram'ning o'zini "hack" qilish |
Eslatma: Bot API bilan Telegram MTProto API (GramJS, Telethon kabi kutubxonalar ishlatadigan "user-bot") β boshqa-boshqa narsalar. Bot API rasmiy, sodda va botlar uchun mo'ljallangan. Bu kitob faqat Bot API bilan ishlaydi.
2. Bot API qanday ishlaydi: foydalanuvchi β 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. Sizning kodingiz foydalanuvchining telefoni bilan emas, faqat api.telegram.org bilan gaplashadi.
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.
Bot API β bu oddiy HTTP API¶
Bot API REST uslubidagi HTTP API. Siz quyidagi ko'rinishdagi manzilga so'rov yuborasiz:
Masalan, xabar yuborish metodi β sendMessage. Agar tokeningiz 123456789:AAH... bo'lsa, xabar yuborish manzili shunday bo'ladi:
Buni hatto oddiy curl bilan ham sinab ko'rsa bo'ladi (illustrativ β haqiqiy token va chat_id kerak):
# Illustrativ β jonli token kerak:
curl "https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAT_ID>&text=Salom"
Yaxshi yangilik shundaki β grammY bu HTTP chaqiruvlarni siz uchun bajaradi. Siz shunchaki ctx.reply("Salom") deb yozasiz, grammY esa orqada to'g'ri URL'ga to'g'ri so'rovni yuboradi. Lekin orqada nima bo'layotganini bilish ulkan foyda β xato qidirganda yoki hujjatni o'qiganda darrov tushunasiz.
Update β "nimadir bo'ldi" signali¶
Update β bu Telegram sizga yuboradigan "nimadir bo'ldi" signali. Update turlari ko'p:
| Update turi | Qachon keladi |
|---|---|
message |
Yangi xabar (matn, rasm, fayl, ...) |
edited_message |
Xabar tahrirlandi |
callback_query |
Inline tugma bosildi |
inline_query |
Foydalanuvchi inline rejimda yozyapti |
my_chat_member |
Botning o'z statusi o'zgardi (qo'shildi/chiqarildi) |
chat_member |
Guruh a'zoligi o'zgardi |
channel_post |
Kanalga post joylandi |
Bu kitob davomida ko'pincha message va callback_query bilan ishlaymiz; guruh/kanal update'lari (19β21 boblar) va Mini App (23β26) qolganlarini ham ochib beradi. grammY'da bu update'larni filter query degan qulay til bilan ushlaymiz β masalan bot.on("message:text") faqat matnli xabarlarni, bot.on(":photo") rasmlarni tutadi (4-bobda chuqur).
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 (bu ham bot, ya'ni bu kitobda o'rganadigan narsangizdan biri).
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 butun Telegram bo'ylab noyob bo'lishi shart. - BotFather sizga tokenni beradi. U taxminan shunday ko'rinadi:
Token nima va nega maxfiy?¶
Token ikki qismdan iborat: <bot_id>:<secret>. Ikki nuqtagacha bo'lgan raqam β botingizning ommaviy ID'si; undan keyingi qism β maxfiy parol. Token β bu botingizning paroli: uni bilgan har kim botingiz nomidan xabar yuboradi, ma'lumotlarni o'qiydi, botni "o'g'irlaydi". Shuning uchun:
- Tokenni hech kimga bermang; GitHub'ga, skrinshotga, video'ga, kod ichiga qo'ymang.
- Tokenni har doim
.envfaylida saqlang (buni 02-bobda amalda ko'ramiz) va.gitignorega.envni qo'shing. - Agar token sizib chiqsa, BotFather'da
/revokebilan darhol yangisini oling β eski token shu zahoti ishlamay qoladi.
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
Diqqat:
/setcommandsbilan o'rnatadigan buyruqlar menyusi β bu faqat Telegram interfeysidagi "ko'rsatma" (foydalanuvchi/bosganda chiroyli ro'yxat chiqadi). U buyruqni kodda ishlatadigan qilmaydi β buyruqning mantig'ini baribir botingizdabot.command("...")bilan yozasiz (02-bob). Menyuni kod orqali ham o'rnatish mumkin (bot.api.setMyCommands), buni 12-bobda ko'ramiz.Token olish jonli Telegram ilovasida amalga oshiriladi β buni kod bilan tekshirib bo'lmaydi (illustrativ qadam).
4. Update olishning ikki yo'li: polling va webhook¶
Telegram update'larni botingizga ikki xil yo'l bilan yetkazadi. Ikkalasini ham bilish kerak, lekin rivojlash (dev) 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. grammY'da bu long-polling ko'rinishida amalga oshadi β bot.start() chaqiruvi aynan shu ishni qiladi (uni 02-bobda yozamiz).
- 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 (lekin minglab foydalanuvchigacha mutlaqo yetarli, ayniqsa
@grammyjs/runnerbilan β 15-bob).
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. grammY'da buni webhookCallback(bot, "express") (yoki "hono", "http") yordamida web-serverga ulaymiz (13-bob).
- 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 (13-bob, deploy esa 17-bob). Bu kitobning katta qismi polling bilan ishlaydi.
Diqqat: Polling ham, webhook ham bir vaqtda ishlay olmaydi β Telegram bittasini tanlaydi. Agar siz
setWebhookqilgan bo'lsangiz,getUpdates(polling)409 Conflictxatosi qaytaradi. Webhook'dan pollingga qaytish uchunbot.api.deleteWebhook()chaqiriladi. Bu eng tez-tez uchraydigan "nega botim javob bermayapti?" sababidir (13-bobda batafsil).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
bot.handleUpdateorqali to'liq tekshirsa bo'ladi β buni 9-bo'limda ko'rasiz.
5. Nega grammY?¶
Telegram bot yozish uchun Node.js'da bir nechta kutubxona bor. Eng mashhurlari: grammY, Telegraf, node-telegram-bot-api. Bu kitob grammY ni tanlaydi. Sabablari:
- Zamonaviy va faol β grammY nisbatan yangi, ammo eng faol rivojlanayotgan kutubxona. Telegram Bot API yangi imkoniyat qo'shsa, grammY uni tez qo'llab-quvvatlaydi (anti-eskirish ahamiyatli).
- TypeScript-birinchi, ammo JS'da ham mukammal β grammY to'liq TypeScript'da yozilgan, shuning uchun avtoto'ldirish (autocomplete) va tip-ishoralar ajoyib. Lekin bu kitob sof JavaScript (ESM) ishlatadi β TypeScript shart emas. (TypeScript alohida mavzu; tiplar shunchaki "qo'shimcha foyda".)
- Filter query'lar β
bot.on("message:text"),bot.on(":photo"),bot.on("message:entities:url")kabi qisqa, o'qishga oson va kuchli filtrlar. Bu grammY'ning eng yoqimli xususiyatlaridan biri (4-bob). - Composer va middleware β handlerlarni mantiqiy modullarga ajratish,
next()bilan zanjir qurish (03 va 09 boblar). - Ulkan plagin ekotizimi β suhbatlar, menyu, sessiya saqlash, throttling, runner va h.k. β pastda ko'ramiz.
- Tezlik va eng yaxshi hujjat β grammy.dev batafsil, yangilanib turadigan rasmiy hujjat.
grammY ekotizimi: yadro va plaginlar¶
grammY "yadro + plaginlar" tamoyili bilan ishlaydi. Yadro (grammy paketi) hamma asosiy narsani biladi (Bot, Composer, Context, Keyboard, InlineKeyboard, session). Qo'shimcha imkoniyatlarni esa faqat kerak bo'lganda rasmiy @grammyjs/* plaginlari sifatida qo'shasiz.
| Paket | Nima qiladi | Qaysi bobda |
|---|---|---|
grammy |
Yadro: Bot, Composer, Context, Keyboard, InlineKeyboard, session |
02β10 |
@grammyjs/conversations |
Ko'p qadamli suhbat/forma (FSM ekvivalenti), v2 | 08 |
@grammyjs/menu |
Interaktiv, holatli inline menyu | 12 |
@grammyjs/hydrate |
ctx ga qulay metodlar (ctx.msg.editText() kabi) |
12 |
@grammyjs/runner |
Konkurensiya β update'larni parallel qayta ishlash | 15 |
@grammyjs/auto-retry |
Flood-control (429) da avtomatik qayta urinish |
15 |
@grammyjs/storage-file |
Sessiyani faylga saqlash adapteri | 10 |
Hammasini hozir o'rnatish shart emas β har birini kerakli bobda o'rnatamiz. Hozir shunchaki nomlari bilan tanishib qo'ying.
6. grammY vs Telegraf vs node-telegram-bot-api¶
Bu eng muhim bo'lim β chunki internetda uchratadigan ko'p misol grammY'niki emas, va ularni grammY kodi bilan aralashtirib yuborish β eng tez-tez uchraydigan xato. Uch kutubxona bir-biriga umuman mos kelmaydi; ularning API'lari boshqa-boshqa.
| Jihat | grammY (bu kitob) | Telegraf | node-telegram-bot-api |
|---|---|---|---|
| Holati | Zamonaviy, faol | Mashhur, lekin sekinroq yangilanadi | Eski, past darajali |
| TypeScript | To'liq, birinchi navbatda | Bor, lekin kuchsizroq | Deyarli yo'q |
| Botni yaratish | new Bot(token) |
new Telegraf(token) |
new TelegramBot(token, {polling:true}) |
| Matnli xabar | bot.on("message:text", ...) |
bot.on("text", ...) |
bot.on("message", ...) |
| Buyruq | bot.command("start", ...) |
bot.command("start", ...) |
bot.onText(/\/start/, ...) |
| Pollingni boshlash | bot.start() |
bot.launch() |
konstruktorda {polling:true} |
| Ko'p qadamli suhbat | @grammyjs/conversations |
ctx.scene / Stage |
(yo'q, qo'lda) |
| Filtr tili | filter query (:photo) |
yo'q (qo'lda) | yo'q (qo'lda) |
E'tibor bering β bot.command ikkala grammY va Telegraf'da bor, lekin qolgani farq qiladi. Mana eng xavfli "yopishtirib qo'yiladigan" naqshlar, ularni grammY loyihangizga kiritmang:
// β Telegraf β grammY'da ISHLAMAYDI:
bot.on("text", (ctx) => ctx.reply("...")); // grammY'da "message:text" bo'lishi kerak
bot.launch(); // grammY'da bot.start()
ctx.scene.enter("forma"); // grammY'da ctx.conversation.enter(...)
const kb = Markup.inlineKeyboard([...]); // grammY'da new InlineKeyboard()...
// β node-telegram-bot-api β grammY'da ISHLAMAYDI:
const bot = new TelegramBot(token, { polling: true }); // grammY'da new Bot(token)
bot.onText(/\/start/, (msg) => bot.sendMessage(msg.chat.id, "...")); // grammY'da bot.command(...)
grammY'da xuddi shu narsa quyidagicha (sof grammY idiom β buni 02-bobdan boshlab yozamiz):
// β
grammY:
import { Bot } from "grammy";
const bot = new Bot(process.env.BOT_TOKEN);
bot.command("start", (ctx) => ctx.reply("Salom!"));
bot.on("message:text", (ctx) => ctx.reply(ctx.message.text));
bot.start(); // long polling
Oltin qoida: Agar topgan misolingizda
new Telegraf(...),bot.launch(),ctx.scene,Markup.*, yokinew TelegramBot(token, {polling:...}),bot.onTextbo'lsa β bu grammY EMAS. Uni ishlatmang. Shubha tug'ilsa, har doim grammy.dev rasmiy hujjatiga qarang. Bu kitobdagi har bir kod faqat grammY idiomida yozilgan va tekshirilgan.Anti-eskirish: grammY tez rivojlanadi, ammo
Bot,bot.command,bot.on,ctx.reply,InlineKeyboard/Keyboardkabi yadro API'lari barqaror. Agar versiya yangilanib biror narsa o'zgarsa, grammy.dev vanode_modules/grammyichidagi tip-ta'riflari (.d.ts) eng ishonchli manba β taxmin qilmasdan o'sha yerga qarang.
7. Node.js va ESM muhiti¶
Bu kitob JavaScript (ESM) ishlatadi β ya'ni import { Bot } from "grammy" ko'rinishidagi zamonaviy modul sintaksisi (eski require(...) emas). Buning uchun loyihangizning package.json faylida "type": "module" bo'lishi kerak (02-bobda o'rnatamiz).
Talablar:
- Node.js 18+ (bu kitob Node v24 va ESM bilan tekshirilgan). Tekshirish:
- npm (Node bilan birga keladi). grammY'ni keyingi bobda
npm install grammybilan o'rnatamiz. - JavaScript asoslari:
async/await,Promise, ESMimport, obyekt/massiv. Eslatib qo'yamiz: deyarli har bir grammY handleriasyncbo'ladi va ichidaawait ctx.reply(...)ishlatadi. Bu bilan yaxshi tanish bo'lmasangiz, avval ../js/README.md va ../nodejs/README.md.
Eslatma: Bu kitob β aiogram (Python) kitobining ekvivalenti. Agar Python'da aiogram bilan ishlagan bo'lsangiz, ko'p tushuncha bir xil: aiogram'dagi
Dispatcher/Routerrolini grammY'daBot/Composer,@router.message(...)rolinibot.on(...), FSM rolini@grammyjs/conversationso'ynaydi. DB asoslari uchun esa ../sql/README.md, deploy/git uchun ../git-github/README.md ga ham murojaat qilamiz.
8. grammY idiomi qanday ko'rinadi (oldindan ko'rish)¶
To'liq botni 02-bobda yozamiz, lekin grammY kodi qanday ko'rinishini hozirdan ko'ring. Bu eng minimal bot:
import { Bot } from "grammy";
const bot = new Bot(process.env.BOT_TOKEN); // token .env dan
// "/start" buyrug'iga javob
bot.command("start", (ctx) => ctx.reply("Salom! Men grammY botiman."));
// Har qanday matnli xabarni qaytarish (echo)
bot.on("message:text", (ctx) => ctx.reply(ctx.message.text));
bot.start(); // long polling β Telegram'dan update so'rab turadi
Bu yerda:
new Bot(token)β bot obyekti. (grammY:new Bot(token), Telegraf'daginew TelegrafEMAS.) Token bo'sh bo'lsa, grammY darholEmpty token!xatosini beradi.bot.command("start", handler)β/startbuyrug'i uchun handler.bot.on("message:text", handler)β filter query: faqat matnli xabarlar.ctx.message.textorqali matnga kiramiz.ctx(context) β har handlerga keladigan "hamma narsa shu yerda" obyekti:ctx.message,ctx.from,ctx.chat, va javob metodlarictx.reply(...). Uni 03-bobda chuqur ochamiz.bot.start()β long polling boshlaydi (cheksiz kutadi). Bu jonli, Telegram'ga ulanadigan qism.
9. Handler marshrutini OFFLINE tekshirish¶
bot.start() jonli Telegram + token talab qiladi (illustrativ). Lekin grammY'da ajoyib narsa bor: handlerlar mantig'ini token va internetsiz tekshirsa bo'ladi. bot.handleUpdate(update) ga soxta Update beramiz, chiqayotgan API chaqiruvlarini esa transformer (bot.api.config.use) bilan ushlaymiz β shunda haqiqiy tarmoq so'rovi ketmaydi, lekin handler to'g'ri ishlaganini isbotlaymiz.
Mana to'liq, ishlaydigan tekshiruv skripti (biz uni haqiqatan ishga tushirdik):
import { Bot, InlineKeyboard } from "grammy";
const bot = new Bot("12345:FAKE"); // soxta token β tarmoqqa chiqmaymiz
// init() Telegram'ga "getMe" yubormasligi uchun botInfo'ni qo'lda beramiz:
bot.botInfo = {
id: 12345, is_bot: true, first_name: "T", username: "t_bot",
can_join_groups: true, can_read_all_group_messages: false,
supports_inline_queries: false, can_connect_to_business: false,
has_main_web_app: false,
};
// Chiqayotgan API chaqiruvlarini ushlaymiz (Telegram'ga yubormaymiz):
const calls = [];
bot.api.config.use((prev, method, payload) => {
calls.push({ method, payload });
if (method === "sendMessage") {
return Promise.resolve({
ok: true,
result: { message_id: 1, date: 0, chat: { id: payload.chat_id, type: "private" }, text: payload.text },
});
}
return Promise.resolve({ ok: true, result: true });
});
// Handlerlar (8-bo'limdagi idiom):
bot.command("start", (ctx) => ctx.reply(`Salom, ${ctx.from.first_name}!`));
bot.on("message:text", (ctx) => ctx.reply(ctx.message.text));
// Telegram'dan kelgandek soxta Update yasaymiz:
function mk(text, isCommand) {
return {
update_id: 1,
message: {
message_id: 1, date: 0, text,
chat: { id: 777, type: "private" },
from: { id: 777, is_bot: false, first_name: "Ali" },
// BUYRUQ uchun bot_command entity SHART, aks holda bot.command mos kelmaydi:
...(isCommand ? { entities: [{ type: "bot_command", offset: 0, length: text.length }] } : {}),
},
};
}
await bot.handleUpdate(mk("/start", true)); // buyruq
await bot.handleUpdate(mk("salom dunyo", false)); // oddiy matn
console.log("1:", calls[0].payload.text); // Salom, Ali!
console.log("2:", calls[1].payload.text); // salom dunyo
Natija (haqiqatan ishga tushirildi):
E'tibor bering:
bot.handleUpdate(update)β Telegram o'rniga update'ni qo'lda berish. Aynan shu bizga tokensiz, internetsiz tekshirish imkonini beradi.bot.api.config.use((prev, method, payload) => ...)β transformer: har bir chiquvchi API chaqiruvini ushlaydi. Biz uni Telegram'ga emas,callsmassiviga yo'naltirdik. Real bot bo'lsa, bu yerda haqiqiysendMessageketardi.- Buyruq (
/start) mock update'igaentities: [{ type: "bot_command", ... }]qo'shish shart β aks holda grammY uni buyruq deb tanimaydi vabot.commandishlamaydi. (Bu juda nozik nuqta; men birinchi marta unutib, "nega ishlamayapti?" deb ancha qiynalgandim.) bot.botInfo'ni qo'lda berdik β shunda grammY ishga tushishda Telegram'gagetMeso'rovini yubormaydi.
Halol farq: Yuqoridagi kod handler marshrutini isbotlaydi β
/startto'g'ri handlerga bordi, matn echo bo'lib qaytdi. Lekin foydalanuvchi ekranida "Salom, Ali!" ko'rinishi β bu jonli Telegram + token talab qiladigan qism (illustrativ). Transformer haqiqiy so'rovni to'sib turgani uchun real xabar ketmadi; mantiqning to'g'riligi esa to'liq tekshirildi. Bu offline-test naqshini 16-bobda Vitest bilan to'liq avtomatlashtirilgan testlarga aylantiramiz.
10. Kitobda nima quramiz: yo'l xaritasi¶
Endi tushunchalar joyida. Bu kitob sizni quyidagi yo'l bo'ylab olib boradi:
- Echo bot (02) β birinchi to'liq bot:
/start, echo vabot.start(). - Handlerlar, Composer, filtrlar (03β04) β
ctx, middleware, filter query'lar, buyruqlar. - Xabar, media, klaviatura, callback (05β07) β boy xabarlar, tugmalar, inline rejim.
- Conversations (08) β ko'p qadamli forma/suhbat (
@grammyjs/conversationsv2). - Middleware, sessiya, DB (09β11) β arxitektura,
session(),better-sqlite3(../sql/README.md), loyihani modullash. - Plaginlar, webhook, to'lov, broadcast (12β15) β menyu,
webhookCallback, Telegram Stars, rejali vazifalar. - Test, production, kapston (16β18) β offline test, deploy (../git-github/README.md), to'liq bot.
- Real amaliyot (19β26) β guruh/kanal boshqaruvi, majburiy obuna, Telegram Mini App va yakuniy Hamster uslubidagi clicker o'yin.
Keyingi bobda darhol amaliyotga o'tamiz: birinchi jonli botni yozamiz.
Mashqlar¶
Bu bob konseptual bo'lgani uchun mashqlar ko'pincha "izlan / tushuntir / rejalashtir" turida. Bir nechtasi 9-bo'limdagi offline naqsh bilan kod yozishni so'raydi.
Oson¶
-
Uchlikni chizing. Foydalanuvchi botga "Salom" yozganda xabar qaysi yo'ldan o'tadi? Foydalanuvchi, Telegram serveri va bot orasidagi 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 va nega: (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? -
Bot nima qila olmaydi? Quyidagilardan qaysilari botning IMKONIDA EMAS: (a) foydalanuvchi yozganda javob berish, (b) tanish bo'lmagan odamga birinchi yozish, (c) admin bo'lgan guruhda xabar o'chirish, (d) boshqa odamning shaxsiy chatini o'qish.
-
Versiyani tekshiring. Kompyuteringizda Node.js qaysi versiyada o'rnatilganini ko'rsatadigan bitta qatorlik terminal buyrug'ini yozing. Nega bu kitob uchun 18+ kerak?
O'rta¶
-
Telegraf'ni grammY'ga tarjima qiling. Quyidagi (Telegraf) kodni grammY idiomiga aylantiring:
-
node-telegram-bot-api'ni aniqlang. Quyidagi kodning qaysi kutubxonaga tegishli ekanini ayting va grammY ekvivalentini yozing:
-
Bot API URL'i. Tokeningiz
999:ABCva sizchat_id=777gatext=Salomyubormoqchisiz deylik.sendMessageuchun to'liq Bot API URL'ini yozing (formatga qarab). -
Soxta Update yasang. 9-bo'limdagi
mkga o'xshash, lekinfrom.id = 42,first_name = "Lola", matni/help(buyruq) bo'lgan soxta Update qaytaradigan funksiya yozing.entitiesni unutmang. -
Ekotizimni moslang. Quyidagi vazifalarni mos
@grammyjs/*plaginiga ulang: (a) ko'p qadamli forma, (b) interaktiv menyu, (c) sessiyani faylga saqlash, (d)429flood-control da qayta urinish. -
grammY'mi yoki yo'qmi? Quyidagi qatorlarning qaysilari grammY, qaysilari emas: (a)
bot.command("start", ...), (b)bot.launch(), (c)bot.on("message:text", ...), (d)ctx.scene.enter(...), (e)new Bot(token).
Qiyin¶
-
Marshrutni offline isbotlang. 9-bo'limdagi skriptga
bot.command("help", ...)uchinchi handlerini qo'shing (ctx.reply("Yordam")). So'ngbot.handleUpdatebilan/helpyuborib, javob matni"Yordam"ekaninicallsorqali tekshiring (entities'ni unutmang). -
Mos kelmaslikni isbotlang. 9-bo'limdagi botga
/notexist(ro'yxatdan o'tmagan buyruq) yuboring. Nechta API chaqiruvi bo'ladi? Nega?calls.lengthorqali isbotlang. (Maslahat: hech bir handler mos kelmasa, bot jim qoladi.) -
Filtr tartibi. Ikkita handler bir xil update'ga mos kelsa (ikkalasi ham
bot.on("message:text")vanext()chaqirmasa), qaysi biri ishlaydi? Ikki handlerli misol yozib,bot.handleUpdate+ transformer bilan buni isbotlang va qisqa xulosa yozing. -
Xavfsizlik tahlili. Bir do'stingiz tokenini ochiq chatda yuborib yubordi va kodini GitHub'ga
.envsiz qo'ydi. Qanday xavf bor va u darhol nima qilishi kerak? BotFather'ning qaysi buyrug'i muammoni hal qiladi va nega eski token endi zarar bermaydi?
Yechimlar
Oson¶
1. Oqim: (1) Foydalanuvchi Telegram klientida "Salom" yozadi. (2) Xabar Telegram serveriga (api.telegram.org) boradi va saqlanadi. (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 (bot_id:secret). (b) salom-dunyo va (c) abcdef β token EMAS, chunki ikki nuqta va boshida raqamli bot_id qismi yo'q. grammY bo'sh yoki butunlay yaroqsiz tokenni new Bot(...) da rad etadi (Empty token!), to'liq format esa Telegram'ga ulanishda aniqlanadi.
3. (a) Uyda o'rganish -> polling (public URL kerakmas, localhostda ishlaydi). (b) Minglab foydalanuvchili public bot -> webhook (tezkor, kam yuk) β yoki polling + @grammyjs/runner. (c) HTTPS domen yo'q -> polling (webhook public HTTPS URL talab qiladi).
4. Nomni o'zgartirish: /setname. Buyruqlar menyusi: /setcommands. Tokenni bekor qilib yangisini olish: /revoke. (Botlar ro'yxati: /mybots.)
5. Imkonida EMAS: (b) tanish bo'lmagan odamga birinchi yozish (foydalanuvchi avval botga yozishi kerak), (d) boshqa odamning shaxsiy chatini o'qish. Imkonida BOR: (a) javob berish, (c) admin bo'lgan guruhda xabar o'chirish.
6. Buyruq: node --version. 18+ kerak, chunki bu kitob zamonaviy ESM (import), await (top-level await) va grammY'ning Node talablariga tayanadi; eski Node'larda bu imkoniyatlar to'liq ishlamaydi.
O'rta¶
7. grammY idiomi:
O'zgarishlar: Telegraf'dagibot.on("text", ...) -> grammY filter query bot.on("message:text", ...); bot.launch() -> bot.start(). ctx.reply va ctx.message.text ikkalasida ham o'xshash.
8. Bu node-telegram-bot-api (new TelegramBot(token, {polling:true}) va bot.onText shu kutubxonaga xos). grammY ekvivalenti:
import { Bot } from "grammy";
const bot = new Bot(token);
bot.command("start", (ctx) => ctx.reply("Salom"));
bot.start();
chat_idni qo'lda berish shart emas β ctx.reply o'zi to'g'ri chatga javob beradi.
9. Bot API URL'i:
bot prefiksi token bilan birikadi (bot999:ABC), metod nomi sendMessage, parametrlar query string sifatida. Amalda grammY bularni siz uchun quradi.
10.
function mk(text, isCommand) {
return {
update_id: 1,
message: {
message_id: 1, date: 0, text,
chat: { id: 42, type: "private" },
from: { id: 42, is_bot: false, first_name: "Lola" },
...(isCommand ? { entities: [{ type: "bot_command", offset: 0, length: text.length }] } : {}),
},
};
}
const upd = mk("/help", true);
console.log(upd.message.from.first_name, upd.message.text); // Lola /help
entities: [{ type: "bot_command", ... }] shart.
11. (a) ko'p qadamli forma -> @grammyjs/conversations; (b) interaktiv menyu -> @grammyjs/menu; (c) sessiyani faylga saqlash -> @grammyjs/storage-file; (d) 429 flood-control da qayta urinish -> @grammyjs/auto-retry.
12. grammY: (a) bot.command("start", ...), (c) bot.on("message:text", ...), (e) new Bot(token). grammY EMAS: (b) bot.launch() β Telegraf; (d) ctx.scene.enter(...) β Telegraf (grammY'da ctx.conversation.enter(...)).
Qiyin¶
13. Skriptga uchinchi handler qo'shamiz va /help'ni tekshiramiz:
bot.command("help", (ctx) => ctx.reply("Yordam"));
calls.length = 0; // hisobni tozalaymiz
await bot.handleUpdate(mk("/help", true));
console.log(calls[0].method, calls[0].payload.text); // sendMessage Yordam
if (calls[0].payload.text !== "Yordam") throw new Error("xato!");
console.log("OK: /help marshruti to'g'ri");
/help ham buyruq bo'lgani uchun mk("/help", true) (entity bilan) ishlatiladi. Natija (offline ishlaydi): calls[0].payload.text === "Yordam".
14. 0 ta API chaqiruvi bo'ladi. Sababi: /notexist bot.command("start"), bot.command("help") ga mos kelmaydi; bot.on("message:text") esa matnli xabarlarni tutadi, lekin biz uni 9-bo'limda echo qilib qoldirgan edik β agar entities'li buyruq bo'lsa va hech bir command mos kelmasa, lekin message:text filtr baribir mos kelishi mumkin. Aniq isbot uchun faqat ikkita command qoldirib, message:text handlerini olib tashlang:
const bot = new Bot("12345:FAKE");
bot.botInfo = { id:12345, is_bot:true, first_name:"T", username:"t_bot",
can_join_groups:true, can_read_all_group_messages:false,
supports_inline_queries:false, can_connect_to_business:false, has_main_web_app:false };
const calls = [];
bot.api.config.use((prev, m, p) => { calls.push(m); return Promise.resolve({ ok:true, result:true }); });
bot.command("start", (ctx) => ctx.reply("S"));
bot.command("help", (ctx) => ctx.reply("Y"));
await bot.handleUpdate(mk("/notexist", true));
console.log("Chaqiruvlar:", calls.length); // 0
message:text handleri ham bo'lsa, u baribir ishlardi, chunki buyruq ham matnli xabar; shuning uchun isbot uchun uni olib tashladik.)
15. Bitta update bir nechta handlerga mos kelsa va birinchisi next() chaqirmasa, ro'yxatdan o'tish tartibida birinchi mos kelgani ishlaydi, qolganlari ishlamaydi. Isbot:
const bot = new Bot("12345:FAKE");
bot.botInfo = { id:12345, is_bot:true, first_name:"T", username:"t_bot",
can_join_groups:true, can_read_all_group_messages:false,
supports_inline_queries:false, can_connect_to_business:false, has_main_web_app:false };
const seen = [];
bot.api.config.use((prev, m, p) => Promise.resolve({ ok:true, result:true }));
bot.on("message:text", (ctx) => { seen.push("birinchi"); }); // next() yo'q
bot.on("message:text", (ctx) => { seen.push("ikkinchi"); }); // ishlamaydi
await bot.handleUpdate(mk("salom", false));
console.log(seen); // ["birinchi"]
["birinchi"] β ikkinchisi ishlamadi, chunki birinchisi next() chaqirmadi. Xulosa: handler tartibi muhim. Eng aniq (spetsifik) handlerlarni yuqoriroqqa qo'ying; agar zanjirni davom ettirmoqchi bo'lsangiz, handler oxirida await next() chaqiring (middleware β 09-bob).
16. Xavf: token β botning paroli; uni bilgan har kim botingiz nomidan xabar yuboradi, ma'lumotlarni o'qiydi, botni butunlay nazoratga oladi. Bundan tashqari, token GitHub'da ochiq qolsa, avtomatik skanerlar uni soniyalar ichida topadi. Darhol qilinadigan ish: BotFather'da /revoke buyrug'i bilan eski tokenni bekor qilish va yangi token olish; so'ng yangi tokenni .env da saqlash va .env ni .gitignore ga qo'shish (kodga yozmaslik). /revoke dan keyin eski token shu zahoti ishlamay qoladi β shuning uchun sizib chiqqani endi zarar bera olmaydi. (Agar maxfiy ma'lumot Git tarixiga tushgan bo'lsa, uni tarixdan ham tozalash kerak β buni ../git-github/README.md da ko'rasiz.)
π README Β· Keyingi: 02 β Birinchi bot: echo va /start β‘οΈ