N'oluyo · Geliştirici Dokümanları · Son güncelleme: · https://noluyo.net/gelistirici

Bileşenler

Bileşen, botun mesajına eklediği buton ve menüdür. Bir kişi butona bastığında ya da menüden seçim yaptığında bot bunu INTERACTION_CREATE olayı olarak alır. Bu sayfa akışı baştan sona anlatır. Botla açılmış DM'de de aynı çalışır; tek fark etkileşimin context: 1 ile, member yerine user ile gelmesi ve kullanıcı menüsünde yalnızca DM'nin iki kişisinin, rol menüsünde hiçbir şeyin seçilememesidir. Bileşenin mesajla nasıl gönderildiği ve JSON sınırları Embed'ler ve bileşenler sayfasındadır.

Bileşenler

Bileşen, botun mesajına eklediği buton ve menüdür. Bir kişi butona bastığında ya da menüden seçim yaptığında bot bunu INTERACTION_CREATE olayı olarak alır. Bu sayfa akışı baştan sona anlatır. Botla açılmış DM'de de aynı çalışır; tek fark etkileşimin context: 1 ile, member yerine user ile gelmesi ve kullanıcı menüsünde yalnızca DM'nin iki kişisinin, rol menüsünde hiçbir şeyin seçilememesidir. Bileşenin mesajla nasıl gönderildiği ve JSON sınırları Embed'ler ve bileşenler sayfasındadır.

Akış

Bot                         N'oluyo                         Kişi
 |  POST /messages (components) |                              |
 |----------------------------->|  mesajı gösterir             |
 |                              |----------------------------->|
 |                              |  butona basar                |
 |                              |<-----------------------------|
 |                              |  mesajın şimdiki halinde     |
 |                              |  custom_id'yi denetler       |
 |  INTERACTION_CREATE          |                              |
 |<-----------------------------|                              |
 |  3 saniye içinde yanıtlar    |                              |
 |----------------------------->|                              |

Sunucu her basmada mesajın o anki bileşenlerine bakar. Bot butonu kaldırdıysa eski ekranda duran butona basmak bota hiçbir şey ulaştırmaz, kişi component_not_found alır. Bot olaya gelen custom_id'nin kendi gönderdiği bir değer olduğuna bu yüzden güvenebilir.

INTERACTION_CREATE için intent gerekmez; bağlantın ne seçmiş olursa olsun gelir. Çok shard'lı botta olay, sunucunun shard'ına gider. Alanların tamamı Olaylar sayfasında.

Olaya nasıl yanıt vereceğin Etkileşimler sayfasında.

Satır ve buton

Bileşenler eylem satırlarına konur (type: 1). Bir mesajda en çok 5 satır, bir satırda en çok 5 buton olur:

{
  "content": "Bu akşam geliyor musun?",
  "components": [
    {
      "type": 1,
      "components": [
        { "type": 2, "style": 3, "label": "Geliyorum", "custom_id": "katilim:evet" },
        { "type": 2, "style": 2, "label": "Gelemem", "custom_id": "katilim:hayir" },
        { "type": 2, "style": 5, "label": "Etkinlik sayfası", "url": "https://example.com/etkinlik" }
      ]
    }
  ]
}

Beş stil vardır:

styleAdGörünümNe zaman
1BirincilVurgu rengi, doluMesajın beklediği asıl eylem
2İkincilGri, doluYan seçenekler, vazgeçme
3BaşarılıYeşil, doluOnay, katılma, kabul
4TehlikeKırmızı, doluSilme, yasaklama, geri dönmeyen işler
5BağlantıGri, dışarı okluBir adres açar, bota bir şey gitmez

Bağlantı butonunda custom_id olmaz, url zorunludur. Basıldığında bot olay almaz. Bir butonu kapatmak için "disabled": true yaz; kapalı bileşene basma isteği component_disabled ile döner.

Menü bir satırı tek başına doldurur. Dört türü vardır. Hepsinde custom_id, placeholder, min_values, max_values ve disabled alanları ortaktır. min_values ve max_values yazılmazsa ikisi de 1 sayılır; min_values 0 ise kişi hiçbir şey seçmeden gönderebilir ve values boş liste gelir. Menüler bir formun içinde de durabilir; orada etiket alırlar.

Metin menüsü

type: 3. Seçenekleri sen yazarsın, bot seçilen value değerlerini alır:

{
  "type": 1,
  "components": [
    {
      "type": 3,
      "custom_id": "renk",
      "placeholder": "Renk seç",
      "max_values": 2,
      "options": [
        { "label": "Kırmızı", "value": "kirmizi" },
        { "label": "Mavi", "value": "mavi", "description": "Sakin olan" }
      ]
    }
  ]
}

Bot şunu alır:

{ "custom_id": "renk", "component_type": 3, "values": ["kirmizi", "mavi"] }

Bir seçeneğe "default": true yazarsan menü o seçenek işaretli açılır; kişi değiştirmeden gönderebilir.

Listede olmayan bir değer, tekrar eden bir değer ya da min_values ve max_values dışında bir sayı validation_failed ile döner ve bota ulaşmaz.

Kullanıcı menüsü

type: 5. Kişi sunucunun üyeleri arasından seçer. default_values ile baştan seçili kişiler verebilirsin:

{
  "type": 1,
  "components": [
    { "type": 5, "custom_id": "uyar", "placeholder": "Kimi uyaralım?", "default_values": [{ "id": "14631410073600003", "type": "user" }] }
  ]
}

Bot, values içinde kimlikleri, resolved içinde kişilerin bilgisini alır:

{
  "custom_id": "uyar",
  "component_type": 5,
  "values": ["14631410073600003"],
  "resolved": {
    "users": { "14631410073600003": { "id": "14631410073600003", "username": "ayse", "display_name": "Ayşe", "avatar": null, "cosmetics": null } },
    "members": { "14631410073600003": { "user": { "id": "14631410073600003", "username": "ayse", "display_name": "Ayşe", "avatar": null, "cosmetics": null }, "nick": null, "roles": [], "joined_at": "2026-11-01T10:00:00Z", "mute": false, "deaf": false, "communication_disabled_until": null } }
  }
}

Sunucunun üyesi olmayan biri seçilemez. resolved, seçilen kişi için GUILD_MEMBERS intent'in olmasa da gelir. DM'de members yer almaz.

Rol menüsü

type: 6. Kişi sunucunun rolleri arasından seçer:

{ "type": 1, "components": [{ "type": 6, "custom_id": "rol-ver", "placeholder": "Rol seç" }] }

Bot şunu alır:

{
  "custom_id": "rol-ver",
  "component_type": 6,
  "values": ["21531879014400009"],
  "resolved": {
    "roles": { "21531879014400009": { "id": "21531879014400009", "name": "Oyuncu", "color": 3368703, "hoist": false, "mentionable": true, "position": 2, "permissions": "68672", "auto_assign": false } }
  }
}

Başka bir sunucunun rolü seçilemez.

Kanal menüsü

type: 8. Kişi yalnızca kendisinin gördüğü kanalları seçebilir. channel_types listeyi kanal türüne göre daraltır: 0 metin, 2 ses, 4 kategori.

{ "type": 1, "components": [{ "type": 8, "custom_id": "duyuru-kanali", "channel_types": [0] }] }

Bot şunu alır:

{
  "custom_id": "duyuru-kanali",
  "component_type": 8,
  "values": ["21531887403008007"],
  "resolved": {
    "channels": { "21531887403008007": { "id": "21531887403008007", "type": 0, "name": "genel", "parent_id": null } }
  }
}

Bot o kanalı görmüyor olabilir, bu yüzden resolved.channels yalnızca kimlik, tür, ad ve üst kategoriyi taşır. Konu ya da izin ayarları gelmez.

custom_id tasarımı

custom_id en çok 100 karakterdir ve mesajda tekil olmalıdır. Bot yeniden başlasa bile basmayı anlayabilsin diye gereken bilgiyi içine yaz:

  • rol:21531879014400009: hangi rol olduğu değerin içinde, ek kayıt gerekmez.
  • anket:42:evet: önce iş, sonra kayıt, sonra seçenek. : ile bölmek yeter.
  • Kişinin göreceği metin ya da gizli bilgi koyma. Değer mesajla birlikte kanalı görebilen herkesin istemcisine gider.

Sınırlar

SınırDeğer
Mesajdaki satır5
Satırdaki buton5
custom_id100 karakter
Buton yazısı80 karakter
Metin menüsü seçeneği25
Seçenek yazısı ve değeri100 karakter
placeholder150 karakter
Seçilen değer25
Basma, kişi başına kanalda5 sn'de 5
Basma, kişi başına tüm kanallarda5 sn'de 10
Basma, uygulama başınasaniyede 22
Basma, tüm uygulamalarsaniyede 67

Basma sınırları kişiyi korur, botunu cezalandırmaz: dolduğunda 429 yalnızca basan kişiye gider, mesaj akışı etkilenmez. Kişi başına sınırlar rate_limited verir; tüm kanallardaki sınır, birkaç hesabın ortak sınırı tek başına doldurmasını önler. Uygulama ve ortak sınır interaction_busy kodunu verir; ortak sınır doluyken o anda başka bir bota basan kişi de bu kodu alabilir. Sınırı aşan basma bota ulaşmaz.

Mesajın bileşenleri, embed'leriyle birlikte yayılma bütçesine sayılır: boyutları sunucunun üye sayısıyla çarpılır. Sunucu büyüdükçe en büyük mesaj küçülür; onu aşan mesaj max_bytes ile 400 fanout_too_large alır.

Kişi ne görür

Butonlar mesajın altında satır satır, uygulamanın kendi buton stilleriyle durur: birincil temanın rengini alır, ikincil gri, başarılı yeşil, tehlike kırmızıdır. Kapalı bileşen soluk görünür ve basılmaz. Bağlantı butonunun yazısının yanında bir bağlantı simgesi olur, üzerine gelince hedefin alan adı görünür. Basınca adres yeni sekmede açılır. Masaüstü uygulamasında, koda göre, varsayılan tarayıcıda açılması gerekir; bu henüz gözlenmedi. Yalnızca https adresli bağlantı butonu çizilir.

Kişi basınca buton dönen bir simgeye döner ve bot yanıtlayana kadar o mesajın bütün bileşenleri kapalı kalır: bir mesajda aynı anda tek basma olur. Bot 3 saniye içinde yanıtlamazsa kişi yaklaşık 3,5 saniye sonra bileşenlerin altında "Bot yanıt vermedi." görür. Botun çevrimdışıysa olay kaybolur ve kişi aynı metni görür: olaylar bot bağlanınca sonradan gönderilmez. Hata metni 5 saniye sonra kendiliğinden gider.

Menü satırı boydan boya kaplar ve seçim yokken placeholder'ı gösterir; yazmadıysan "Seçim yap" yazar. max_values değeri 1 olan metin menüsü uygulamanın açılır listesidir, seçim yapılır yapılmaz gönderilir. Çok seçimli metin menüsü ile kullanıcı, rol ve kanal menüleri bir pencerede liste açar: kişi seçenekleri işaretler ve "Onayla"ya basar. min_values'tan azıyla "Onayla" kapalı kalır, max_values dolunca başka seçenek işaretlenemez. Seçeneğin emoji'si adının önünde, description'ı altında küçük yazıyla görünür. Değerler bota listedeki sırayla gider.

Kullanıcı, rol ve kanal menüsünün penceresinde arama kutusu olur. Kullanıcı menüsü sunucunun üyelerini, rol menüsü @everyone dışındaki rolleri en üstteki rolden başlayarak listeler. Kanal menüsünde yalnızca kişinin gördüğü ve channel_types'a uyan kanallar çıkar. Gönderdikten sonra menü seçilenlerin adlarını gösterir. Mesaj güncellenince menüler yeniden default ve default_values ile başlar.

Klavyeyle de kullanılır: Tab bileşenler arasında gezer, Enter ya da boşluk basar. Açılır listede oklar seçeneği değiştirir, pencerede Enter ya da boşluk işaretler, Esc kapatır.

Android uygulamasında, koda göre, her menü ekranın altından açılan bir panelde listelenir; bu davranış telefonda henüz gözlenmedi. Tek seçim isteyen menüde (min_values ve max_values 1) seçeneğe dokunmak onu hemen gönderir, öbürlerinde "Onayla" vardır. Butonların dokunma alanı en az 48 dp'dir. Bağlantı butonu adresi telefonun tarayıcısında açar.

Bot type: 7 ile yanıt verince mesaj kişinin ekranında yerinde değişir: kapattığın buton soluklaşır, kaldırdığın buton gider.

Şunlar basmayı daha baştan durdurur ve bota hiçbir şey gitmez. Kişi hatayı bileşenlerin altında görür:

DurumYanıtKişinin gördüğü
Kanalı görmüyor403 missing_access"Bu kanalı görme yetkin yok."
Zaman aşımında403 missing_permissions"Bunun için yetkin yok."
Bot butonu kaldırmış404 component_not_found"Bu bileşen artık geçerli değil."
Bileşen kapalı400 component_disabled"Bu bileşen kapalı."
Bot sunucudan çıkmış ya da uygulama silinmiş409 application_unavailable"Bu mesajı gönderen bot artık burada değil."
Ephemeral mesajın süresi dolmuş400 interaction_expired"Bu etkileşimin süresi doldu."
Kişi çok hızlı basıyor429 rate_limited"Çok hızlı gidiyorsun, biraz yavaşla."
Uygulama ya da ortak sınır dolu429 interaction_busy"Bot şu an yoğun. Biraz sonra yeniden dene."

Ekranı henüz güncellenmemiş biri botunun kaldırdığı bir butona basarsa basma bota ulaşmaz, kişi "Bu bileşen artık geçerli değil." görür. Uygulama 429'u beklemez ve yeniden denemez: geç kalan bir basma botunun 3 saniyesini zaten kaçırmış olur.

Kanalı gören herkes basabilir, SendMessages gerekmez: salt okunur bir duyuru kanalındaki rol butonu böyle çalışır.

Yalnızca basan kişinin göreceği butonlu mesaj için Etkileşimler sayfasına bak.

Yetkiyi sen denetlersin

member.permissions kişinin bu kanaldaki izinleridir, ondalık metin olarak gelir. BigInt ile denetle:

const BAN_MEMBERS = 1n << 2n;

if (!(BigInt(d.member.permissions) & BAN_MEMBERS)) {
  // Yetkisi yok: işi yapma.
}

app_permissions de botun kendi izinleridir. DM'de member yerine user gelir ve izinler DM'in sabit izinleridir.

Tam örnek: rol seçme botu

Node.js 22 veya üstü yeter. Gateway sayfasındaki gateway.mjs ile Örnekler sayfasındaki api.mjs aynı klasörde olmalı. Botun ManageRoles izni olmalı ve rolü kendi rolünün altında kalmalı. Bot her açıldığında kanala bir buton atar, basan kişiye rolü verir, yeniden basana geri alır. Ekranda değişen bir şey olmadığı için yanıtı type: 6'dır:

import { connect } from "./gateway.mjs";
import { call } from "./api.mjs";

const { CHANNEL_ID, ROLE_ID } = process.env;
if (!CHANNEL_ID || !ROLE_ID) throw new Error("CHANNEL_ID ve ROLE_ID tanımlı olmalı");

let posted = false;

async function onPress(d) {
  // Sunucu custom_id'yi doğruladı: içindeki rol bizim yazdığımız roldür.
  const [kind, roleId] = d.data.custom_id.split(":");
  if (kind !== "rol" || !d.member) return;
  await call("POST", `/interactions/${d.id}/${d.token}/callback`, { type: 6 });
  const path = `/guilds/${d.guild_id}/members/${d.member.user.id}/roles/${roleId}`;
  await call(d.member.roles.includes(roleId) ? "DELETE" : "PUT", path);
}

await connect({
  intents: 0,
  onEvent(t, d) {
    if (t === "READY" && !posted) {
      posted = true;
      call("POST", `/channels/${CHANNEL_ID}/messages`, {
        content: "Rolü almak ya da bırakmak için bas.",
        components: [{ type: 1, components: [
          { type: 2, style: 1, label: "Oyuncu", custom_id: `rol:${ROLE_ID}` },
        ] }],
      }).catch(console.error);
    }
    if (t === "INTERACTION_CREATE") onPress(d).catch(console.error);
  },
});

Çalıştırmak için:

BOT_TOKEN='kopyaladigin_token' CHANNEL_ID='kanal id degeri' ROLE_ID='rol id degeri' node rol-botu.mjs

Sık hatalar

  • Olay hiç gelmiyor. Bot bağlı mı? Çevrimdışı bota olay sonradan gönderilmez. Çok shard'lı botta olay sunucunun shard'ına gider, her shard'ı dinle.
  • component_not_found alan kişiler var. Bot mesajı düzenleyip custom_id'yi değiştirmiş; ekranı güncellenmemiş kişi eski değere basıyor. Bu doğru davranıştır.
  • custom_id iki kez kullanılmış. Mesaj gönderilirken validation_failed döner; değer mesajda tekil olmalıdır.
  • Yönetim butonuna herkes basabiliyor. Yetkiyi sunucu denetlemez, member.permissions'a bak.
  • Rol verilemiyor. Botun ManageRoles izni yoksa ya da rol botun rolünün üstündeyse REST isteği 403 döner.
  • values içinde kimlik yerine başka bir şey bekleniyor. Kullanıcı, rol ve kanal menülerinde values kimliklerdir; ayrıntı resolved içindedir.

Bu sayfayı yapay zekaya verirsen

Sırada ne var

  • Etkileşimler: butona ve menüye basıldığında gelen olayın yanıt türleri
  • Formlar: buton tıklamasıyla en çok beş alanlı pencere açmak
  • Hazır tarifler: butonlu rol seçici ve anket örnekleri