IlmHamroh
JavaScript Full-stack/29-qism. Backend integratsiyalar: fayl, to'lov, bot, realtime24/69-dars13 daqiqa
Mundarija (25)

Guruh, kanal botlari va inline rejim: bot chatdan tashqarida

Qisqacha: Bot shaxsiy chatdan tashqari ham ishlaydi: guruhda moderator, kanalda avtopost, istalgan chatda inline yordamchi. Guruhga qo'shilganini bot my_chat_member update'idan biladi. Sukutda privacy mode yoqiq: guruhda bot faqat o'ziga qaratilgan buyruq va javoblarni ko'radi. Moderatsiya va kanalga yozish uchun bot admin bo'lishi kerak. Inline rejimda foydalanuvchi @bot so'rov yozadi, bot answerInlineQuery bilan 50 tagacha natija qaytaradi.

Bu darsda

  • Chat turlarini va bot guruhga qo'shilganini qanday bilishni ko'rasiz.
  • Privacy mode guruhda bot nimani ko'rishini qanday cheklashini tushunasiz.
  • Admin huquqlari bilan moderatsiya va kanalga post yozishni bilasiz.
  • Inline so'rovga javob berasiz va cache_time, is_personal ni tushunasiz.
  • Poll va quiz yuborish haqida bilasiz.

Oldin bilishingiz kerak: Sessiya va ko'p qadamli dialoglar, grammY bilan bot yozish (filter query'lar), Klaviaturalar va callback query.

Shu paytgacha bot bitta odam bilan gaplashdi. Endi uni jamoa guruhiga qo'shamiz va boshqa chatlarda ham ishlatamiz.

1. Nega bu kerak?

vazifalar ilovasidan oila yoki kichik jamoa foydalanadi. Ularning umumiy Telegram guruhi bor. Uch xil ehtiyoj tug'iladi:

  1. Guruh boti. Bot guruhga qo'shiladi va "bugun kimning vazifasi bor" deb eslatadi.
  2. Kanal. Jamoa yangiliklari kanaliga bot avtomatik post yozadi.
  3. Inline yordamchi. Aziz do'sti bilan yozishayotganda @vazifalar_bot non yozadi va vazifani chatga ulashadi — botni guruhga qo'shmasdan.

O'xshatish: bot — xodim. Shaxsiy chat — uning kabineti. Guruh — majlis zali: u yerda hamma gapini eshitish uchun alohida ruxsat kerak. Kanal — e'lonlar taxtasi: yozish uchun kalit kerak. Inline rejim — xodimni istalgan suhbatga telefon orqali chaqirish.

2. Chat turlari

ctx.chat.type to'rt qiymatdan biri:

Tur Nima Chat id
private bot bilan yakkama-yakka musbat (foydalanuvchi id)
group oddiy guruh manfiy
supergroup katta guruh (admin, mavzular) manfiy, -100…
channel kanal manfiy, -100…

Kanalda xabar message emas, channel_post bo'lib keladi. grammY bilan bot yozish darsidagi :text filtri ikkalasini ham ushlaydi — kanon chiqishida text-2 (:text — message ham, channel_post ham) yozuvini ko'rgansiz.

grammY'da chat turi bo'yicha filtr: bot.chatType("private"), bot.chatType(["group", "supergroup"]). Masalan, /yangi dialogi faqat shaxsiy chatda ishlasin:

js
const shaxsiy = bot.chatType("private");
shaxsiy.command("yangi", (ctx) => ctx.conversation.enter("yangi"));

3. Bot guruhga qo'shildi: my_chat_member

Botning o'z a'zoligi o'zgarsa (qo'shildi, chiqarildi, admin bo'ldi), Telegram my_chat_member update'ini yuboradi. Unda eski va yangi holat bor.

js
bot.on("my_chat_member", (ctx) => {
  const { old_chat_member: eski, new_chat_member: yangi } =
    ctx.myChatMember;
  console.log(`bot ${eski.status} → ${yangi.status}`,
    `(${ctx.chat.title})`);
  return ctx.reply("Salom, jamoa! Vazifalar: /vazifalar");
});

Kurs tajribasi mock'da botni "Jamoa" guruhiga qo'shdi:

text
my_chat_member: bot left → member (Jamoa) | guruhga javob: "Salom, jamoa! Vazifalar: /vazifalar"

Holatlar: left (chiqib ketgan), member, administrator, kicked (chiqarib yuborilgan), restricted, creator. Telegram hujjatiga ko'ra shaxsiy chatda my_chat_member faqat foydalanuvchi botni bloklaganda yoki blokdan chiqarganda keladi. Bu Bot prodakshnda darsida kerak bo'ladi: bloklagan foydalanuvchiga yuborishni to'xtatish.

chat_member — boshqa a'zolarning o'zgarishi (yangi a'zo kirdi, chiqdi). Hujjatga ko'ra uni olish uchun bot guruhda admin bo'lishi va allowed_updates ro'yxatida "chat_member" ni aniq ko'rsatishi kerak. Sukutda kelmaydi. Kanon mock'i chat_member ni taqlid qilmadi.

Tekshirib ko'ring: Bot guruhdan chiqarildi. Keyin u shu guruhga sendMessage qilsa nima bo'ladi va bot buni oldindan qanday biladi?

Javob

Telegram xato qaytaradi (bot a'zo emas). Oldindan bilish uchun — my_chat_member update'i: member → kicked yoki → left. Shu paytda guruhni bazada "faol emas" deb belgilang va eslatmalarni to'xtating. Aks holda har eslatma xato bilan tugaydi.

4. Privacy mode

4.1 Bot guruhda nimani ko'radi

Telegram hujjati (2026-10-28): guruhga qo'shilgan barcha botlar sukutda privacy mode da ishlaydi va faqat "tegishli" xabarlarni ko'radi:

  • o'ziga aniq qaratilgan buyruqlar (/command@this_bot);
  • umumiy buyruqlar (/start), agar guruhga oxirgi xabarni shu bot yozgan bo'lsa;
  • shu bot orqali yuborilgan inline xabarlar;
  • shu botga qaratilgan xabarlarga javoblar (reply).

Privacy mode'dan qat'i nazar bot oladi: barcha xizmat xabarlari, shaxsiy chatdagi hamma xabar, a'zo bo'lgan kanalning hamma xabari.

Hujjat yana aytadi: guruhga admin sifatida qo'shilgan bot hamma xabarni oladi. Privacy mode'ni BotFather'da o'chirish mumkin — shunda bot hamma xabarni oddiy a'zo kabi oladi (o'zgarish kuchga kirishi uchun botni guruhga qayta qo'shish kerak). Telegram buni faqat zarur bo'lganda tavsiya qiladi.

Diqqat: Privacy mode — BotFather sozlamasi va Telegram serveri qoidasi. Kanon mock'i uni taqlid qilmaydi, bu kursda sinalmagan. Yuqoridagi ro'yxat — hujjat bo'yicha.

4.2 Nega bu muhim

Privacy mode — foydalanuvchilarni himoya qiladi. Guruhdagi odamlar bot ularning har gapini o'qiyotganini bilmasligi mumkin. Botingiz uchun ikki xulosa:

  1. Kamroq ma'lumot — kamroq javobgarlik. Botga oddiy xabarlar kerak bo'lmasa, privacy mode yoqiq qolsin. O'qimagan ma'lumotingiz oqib chiqmaydi.
  2. Buyruqni to'liq yozing. Guruhda bir nechta bot bo'lsa, /vazifalar@vazifalar_bot. grammY bot.command ikkala shaklni ham taniydi.

Spam-filtr kabi moderator botga esa hamma xabar kerak — u admin qilinadi. Bu holda foydalanuvchilarga ochiq ayting: "bu guruhdagi xabarlarni bot tekshiradi".

5. Admin huquqlari va moderatsiya

Moderatsiya metodlari: deleteMessage, banChatMember, restrictChatMember, pinChatMessage. Telegram hujjati har biri uchun yozadi: bot chatda admin bo'lishi va kerakli admin huquqiga ega bo'lishi shart.

Ikki tekshiruv kerak:

  1. Bot o'zi huquqqa egami? — getChatMember(chat, bot.id) → status: "administrator" va kerakli huquq (can_delete_messages, can_restrict_members).
  2. Buyruq bergan odam adminmi? — getChatMember(chat, ctx.from.id). Aks holda istalgan a'zo /ban yozib, boshqalarni chiqaradi.
js
bot.chatType(["group", "supergroup"]).command("ban", async (ctx) => {
  const kim = await ctx.getChatMember(ctx.from.id);
  if (!["administrator", "creator"].includes(kim.status)) {
    return ctx.reply("Faqat admin.");
  }
  const nishon = ctx.message.reply_to_message?.from;
  if (!nishon) return ctx.reply("Kimni? Xabariga javob qiling.");
  await ctx.banChatMember(nishon.id);
});

Bu kod kanonda sinalmagan (mock guruh huquqlarini taqlid qilmaydi) — naqsh hujjat bo'yicha.

getChatMember har buyruqda — tarmoq so'rovi. Ko'p ishlatilsa, admin ro'yxatini (getChatAdministrators) qisqa muddatga keshlang (Caching naqshlari) va chat_member update'ida yangilang.

Telegram FAQ cheklovi: guruhda bot daqiqasiga 20 tadan ko'p xabar yubora olmaydi. Moderator bot har o'chirilgan xabarga "o'chirildi" deb javob yozsa, tez limitga tushadi.

6. Kanal boti

Kanalga post yozish uchun bot kanalga admin sifatida qo'shiladi va unga can_post_messages huquqi beriladi (hujjat: bu huquq faqat kanallar uchun). Keyin oddiy sendMessage:

js
await bot.api.sendMessage("@sizning_kanal",
  "<b>Haftalik hisobot</b>\nBajarilgan vazifalar: 42",
  { parse_mode: "HTML" });

chat_id o'rnida ochiq kanal uchun @kanal_nomi (hujjat formati @channelusername) yoki raqamli -100… id. Yopiq kanalda faqat raqamli id ishlaydi.

Avtopost odatda vaqt bo'yicha bo'ladi — har kuni 09:00 da. Bu Cron va rejali vazifalar darsining mavzusi. Kanal posti ham xabar limitiga tushadi.

Kanalga yozish sinalmagan (kanon mock'ida kanal huquqlari yo'q).

7. Inline rejim

7.1 Qanday ishlaydi

Inline rejim BotFather'da yoqiladi (/setinline). Shundan keyin istalgan chatda foydalanuvchi @vazifalar_bot non yozadi. Telegram botga inline_query update'ini yuboradi: kim so'radi, nima yozdi. Bot answerInlineQuery bilan natijalar ro'yxatini qaytaradi. Foydalanuvchi bittasini tanlaydi — u foydalanuvchi nomidan chatga yuboriladi ("via @vazifalar_bot" belgisi bilan).

sequenceDiagram
  participant A as Aziz (do'sti bilan chat)
  participant T as Telegram
  participant B as Bot
  A->>T: "@vazifalar_bot non" yozadi
  T->>B: inline_query (from 2, query "non")
  B->>B: Azizning vazifalarini qidiradi
  B->>T: answerInlineQuery (natijalar, cache_time)
  T->>A: natijalar ro'yxati
  A->>T: bittasini tanlaydi
  T->>A: chatga "Non olish — 18:00" (via bot)

Diagrammaga qarang: bot chatga o'zi yozmaydi va chatni ko'rmaydi. U faqat so'rovga javob beradi, yuborishni foydalanuvchi qiladi. Shuning uchun inline rejim botni guruhga qo'shmasdan ishlaydi.

7.2 Kanon tajribasi

js
bot.on("inline_query", (ctx) => ctx.answerInlineQuery([{
  type: "article",
  id: "1",
  title: `"${ctx.inlineQuery.query}" bo'yicha 1 vazifa`,
  input_message_content: { message_text: "Non olish — 18:00" },
}], { cache_time: 10, is_personal: true }));

Kurs tajribasida mock'ka ketgan natijalar:

text
answerInlineQuery: [{"type":"article","id":"1","title":"\"non\" bo'yicha 1 vazifa","input_message_content":{"message_text":"Non olish — 18:00"}}]
  • type: "article" — matnli natija. Boshqa turlar: photo, document (file_id bilan — Media, fayllar va formatlash).
  • id — natijaning bir so'rov ichidagi noyob id'si.
  • title — ro'yxatda ko'rinadi; input_message_content — tanlanganda chatga ketadigan matn.

7.3 cache_time va is_personal

Hujjat bo'yicha:

  • cache_time — natija Telegram serverida necha soniya keshlanadi. Sukut — 300. Shu vaqt ichida o'sha so'rovga bot qayta so'ralmaydi.
  • is_personal: true — kesh faqat so'ragan foydalanuvchi uchun. Busiz natija o'sha so'rovni yozgan istalgan foydalanuvchiga qaytarilishi mumkin.

Bu xavfsizlik masalasi. "non" so'roviga Azizning shaxsiy vazifalarini qaytardingiz va is_personal qo'ymadingiz. Besh daqiqa ichida Dilnoza ham @vazifalar_bot non yozsa — Telegram unga Azizning keshlangan vazifalarini ko'rsatishi mumkin. Shaxsiy ma'lumot qaytaradigan har inline javobda is_personal: true va qisqa cache_time. Kanon misoli aynan shunday.

Hujjat bo'yicha bir so'rovga 50 tadan ko'p natija bo'lmaydi.

7.4 Natijalarni yasash

Natijalar ro'yxatini yasash — toza funksiya:

js
function inlineNatijalar(vazifalar, soz) {
  const q = soz.trim().toLowerCase();
  return vazifalar
    .filter((v) => !v.bajarildi && v.matn.toLowerCase().includes(q))
    .slice(0, 50)
    .map((v) => ({
      type: "article",
      id: String(v.id),
      title: v.matn,
      input_message_content: { message_text: `Vazifa: ${v.matn}` },
    }));
}

const vazifalar = [
  { id: 1, matn: "Non olish", bajarildi: false },
  { id: 2, matn: "Non pul to'lash", bajarildi: true },
  { id: 3, matn: "Hisobot", bajarildi: false },
];
const n = inlineNatijalar(vazifalar, " NON ");
console.log(n.length, n[0].id, n[0].title);
console.log(inlineNatijalar(vazifalar, "").map((x) => x.id));
console.log(inlineNatijalar(vazifalar, "yo'q").length);

Konsolda:

text
1 1 Non olish
[ '1', '3' ]
0
  • Kichik-katta harf va bo'shliq farq qilmaydi; bajarilganlar chiqmaydi.
  • Bo'sh so'rov — hamma faol vazifalar (foydalanuvchi @bot yozib, hali hech narsa yozmagan).
  • slice(0, 50) — hujjat chegarasi.
  • Natija bo'sh bo'lsa ham answerInlineQuery([]) chaqiriladi — aks holda mijoz kutib qoladi.

Ikkinchi qatorda Node [ '1', '3' ] deb chiqaradi; brauzer konsoli ['1', '3'] — ma'nosi bir xil.

8. Poll va quiz

sendPoll — so'rovnoma. Hujjat bo'yicha type — "regular" (sukut) yoki "quiz". Quiz'da to'g'ri javob(lar) beriladi; 2026-10-28 holatidagi hujjatda maydon correct_option_ids — 0 dan boshlanadigan indekslar massivi (eski kodda correct_option_id bitta son bilan uchraydi).

js
await bot.api.sendPoll(chatId, "Bugungi eng muhim vazifa?",
  [{ text: "Hisobot" }, { text: "Non olish" }],
  { is_anonymous: false });

is_anonymous: false bo'lsa, har ovoz poll_answer update'i bo'lib keladi (hujjat: bot faqat o'zi yuborgan so'rovnomalardagi yangi ovozlarni oladi). Poll va quiz kanonda sinalmagan — hujjat bo'yicha; Bot API versiyasiga qarab parametr shakli o'zgarishi mumkin, yozishdan oldin hujjatni tekshiring.

9. Hujumchi nigohi

Hujum Himoya
oddiy a'zo /ban yozadi getChatMember(from.id) — admin tekshiruvi
bot admin emas, lekin moderatsiya qiladi deb o'ylaysiz bot huquqini tekshirish, xatoni ushlash
inline kesh orqali begona vazifalarni ko'rish is_personal: true, qisqa cache_time
inline natijasida foydalanuvchi matni HTML bilan html() yoki parse_mode siz
guruhda tugmani begona a'zo bosadi ctx.from.id bo'yicha egalik (Klaviaturalar)
privacy mode o'chiq bot shaxsiy gaplarni saqlaydi kerakmas ma'lumotni saqlamaslik

10. Ko'p uchraydigan xatolar

Xato Natija To'g'risi
guruhda bot hamma xabarni oladi deb kutish ishlovchi jim privacy mode; admin yoki buyruq@bot
chat_member ni allowed_updates siz kutish update kelmaydi aniq ko'rsatish + admin
kanalga yozish uchun oddiy a'zo 400/403 admin + can_post_messages
is_personal siz shaxsiy natija boshqalarga ko'rinishi mumkin is_personal: true
bo'sh natijada javob bermaslik mijoz kutadi answerInlineQuery([])
guruhda har hodisaga xabar 20 xabar/daqiqa limiti jamlab yozish

11. Mashqlar

Mashqlar kurs/mashqlar/29/24-guruh/ da.

1-mashq (oson): bot ko'radimi?

Privacy mode yoqiq bot (admin emas) guruhda. Qaysi xabarlarni oladi?

  1. salom hammaga
  2. /vazifalar@vazifalar_bot
  3. Botning oldingi xabariga reply: rahmat
  4. Yangi a'zo qo'shilgani haqidagi xizmat xabari
Yechim
  1. Yo'q — oddiy xabar, botga qaratilmagan.
  2. Ha — aniq unga qaratilgan buyruq.
  3. Ha — bot xabariga javob.
  4. Ha — xizmat xabarlari privacy mode'dan qat'i nazar keladi.

2-mashq (o'rta): my_chat_member dan holat

holatniYangila(guruhlar, update) yozing: update — { chat: { id, title }, old_chat_member: { status }, new_chat_member: { status } }. Yangi holat member yoki administrator bo'lsa — guruh faol: true, admin — administratormi; left yoki kicked bo'lsa — faol: false. guruhlar — Map. Uch update: qo'shildi (left → member), admin qilindi (member → administrator), chiqarildi (administrator → kicked).

Yechim
js
function holatniYangila(guruhlar, u) {
  const yangi = u.new_chat_member.status;
  const faol = yangi === "member" || yangi === "administrator";
  guruhlar.set(u.chat.id, {
    nom: u.chat.title,
    faol,
    admin: yangi === "administrator",
  });
  return `${u.old_chat_member.status} → ${yangi}`;
}

const g = new Map();
const chat = { id: -100123, title: "Jamoa" };
const updatelar = [
  ["left", "member"], ["member", "administrator"],
  ["administrator", "kicked"],
];
for (const [eski, yangi] of updatelar) {
  const izoh = holatniYangila(g, {
    chat,
    old_chat_member: { status: eski },
    new_chat_member: { status: yangi },
  });
  console.log(izoh, JSON.stringify(g.get(chat.id)));
}
text
left → member {"nom":"Jamoa","faol":true,"admin":false}
member → administrator {"nom":"Jamoa","faol":true,"admin":true}
administrator → kicked {"nom":"Jamoa","faol":false,"admin":false}

faol: false bo'lgan guruhga eslatma yuborilmaydi. admin maydoni moderatsiya funksiyalarini yoqish uchun.

3-mashq (qiyin): inline kesh tuzog'i

Telegram keshini taqlid qiling: kesh — Map, kalit is_personal bo'lsa so'rov + foydalanuvchi, aks holda faqat so'rov. inlineSora(foydalanuvchi, soz, shaxsiy) avval keshni tekshiradi; bo'lmasa "bot"dan (botJavobi(f, s) — foydalanuvchining s li vazifalari) oladi va keshga qo'yadi. Avval shaxsiy = false bilan Aziz, keyin Dilnoza non so'rasin; keyin keshni tozalab shaxsiy = true bilan takrorlang.

Yechim
js
const baza = {
  aziz: ["Non olish", "Non pul"],
  dilnoza: ["Non sotib olish"],
};
const botJavobi = (f, s) => baza[f].filter((v) =>
  v.toLowerCase().includes(s));

const kesh = new Map();
function inlineSora(f, s, shaxsiy) {
  const kalit = shaxsiy ? `${s}|${f}` : s;
  if (!kesh.has(kalit)) kesh.set(kalit, botJavobi(f, s));
  return kesh.get(kalit);
}

for (const shaxsiy of [false, true]) {
  kesh.clear();
  console.log(`is_personal=${shaxsiy}`);
  for (const f of ["aziz", "dilnoza"]) {
    console.log(`${f}:`, inlineSora(f, "non", shaxsiy).join("; "));
  }
}
text
is_personal=false
aziz: Non olish; Non pul
dilnoza: Non olish; Non pul
is_personal=true
aziz: Non olish; Non pul
dilnoza: Non sotib olish

is_personal=false da Dilnoza Azizning vazifalarini ko'rdi — kesh kaliti foydalanuvchini bilmaydi. Haqiqiy Telegram keshi qanday ishlashini to'liq bilmaymiz (hujjat faqat "may be returned to any user" deydi), lekin xavf shu.

12. Loyiha qadami: tajriba va loyihaga ulash rejasi

Bu dars — tajriba. Kanon vazifalar boti hozircha faqat shaxsiy chatda ishlaydi: deep link bilan ulangan hisob, shaxsiy vazifalar, shaxsiy eslatmalar. Guruh boti va inline rejim A modulida yo'q:

  • guruhda vazifalar "kimniki" degan savol tug'iladi — bu jamoa va rollar modelini talab qiladi (28-qism: RBAC va resurs egaligi);
  • inline rejim BotFather sozlamasi va haqiqiy Telegram'siz faqat mock'da sinaladi.

Kurs tajribasi ikki naqshni ko'rsatdi: my_chat_member bilan guruhni ro'yxatga olish va is_personal li inline javob. Ular loyihaga kerak bo'lganda shu shaklda qo'shiladi. Commit yo'q.

13. Real ishda

  • O'zbek Telegram guruhlarida moderator botlar keng tarqalgan: spam havolani o'chirish, yangi a'zoni tekshirish.
  • Yangilik saytlari kanalga avtopost botlarini ishlatadi.
  • Inline botlar: qidiruv, valyuta kursi, stiker, ulashish.
  • Intervyuda: "Privacy mode nima?", "Bot guruhdan chiqarilganini qanday bilasiz?", "Inline javob keshi qanday xavf tug'diradi?"

Xulosa

  • Chat turlari: private, group, supergroup, channel; kanal xabari — channel_post.
  • my_chat_member — botning o'z a'zoligi; shaxsiy chatda — bloklash. chat_member — admin + allowed_updates.
  • Privacy mode sukutda yoqiq: guruhda bot faqat o'ziga qaratilganini ko'radi (sinalmagan, hujjat bo'yicha).
  • Moderatsiya va kanal posti — bot admin, buyruq bergan ham admin bo'lsin.
  • Inline: answerInlineQuery, ≤ 50 natija, cache_time sukut 300, shaxsiy ma'lumotda is_personal: true.

Keyingi dars: Bot prodakshnda — webhook va secret_token, 429 va ommaviy yuborish, runner va graceful shutdown.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!