# Etkileşimler

Biri botunun butonuna bastığında ya da komutunu çalıştırdığında bot `INTERACTION_CREATE` alır ve ona yanıt verir. Bu sayfa yanıtın dört türünü, süreleri ve sonradan gelen mesajları anlatır. Basmanın kendisi ve bileşenlerin nasıl yazıldığı [Bileşenler](https://noluyo.net/gelistirici/bilesenler.md) sayfasında.

## Zaman çizelgesi

| Ne zaman | Ne olur |
|---|---|
| 0 sn | Kişi basar, bot `INTERACTION_CREATE` alır. Olayda `id` ve `token` vardır. |
| 3 sn | İlk yanıtın son anı. Sonrası `400 interaction_timeout` döner, kişi "Bot yanıt vermedi" görür. |
| 15 dk | Token'ın ömrü. `@original` düzenlemesi ve takip mesajları buraya kadar çalışır, sonrası `400 interaction_expired` döner. |

Her etkileşim tek bir ilk yanıt alır. İkincisi `400 interaction_already_acknowledged` döner. Reddedilen bir yanıt hakkını harcamaz: hatayı düzeltip süre içinde yeniden gönderebilirsin.

## Gateway mı HTTP mi

Etkileşim botuna iki yoldan gelebilir. Uygulamanın [etkileşim adresi](https://noluyo.net/gelistirici/http-teslim.md) yoksa gateway'den, varsa yalnızca o adrese. İçerik ikisinde aynıdır; değişen, yanıtı nasıl verdiğindir:

| | Gateway | HTTP adresi |
|---|---|---|
| Etkileşim nasıl gelir | `INTERACTION_CREATE` olayı | Adresine imzalı `POST` |
| İlk yanıt | `callback` rotası, bot token'ıyla | Aynı isteğin `200` gövdesi; ya da `202` dönüp `callback` rotası |
| 3 saniye | Etkileşimin kimliğinden sayılır | Adresine bağlanma ve yanıtın tamamı dahil |
| Reddedilen yanıt | Hata kodunu sen alırsın, süre içinde düzeltip yeniden gönderebilirsin | Kişi "Bot zamanında yanıt vermedi." görür, kod teslim günlüğüne yazılır |
| Bot kapalıysa | Etkileşim kaybolur, kişi 3 saniye sonra hatayı görür | Kişi hatayı hemen görür |
| Takip, `@original` | Aynı rotalar | Aynı rotalar, bot token'ıyla |
| Sınırlar | `interaction` sınıfı ve ortak tavanlar | Aynısı |

Kişi hangi yolu kullandığını görmez.

## Sunucuda mı DM'de mi

Her etkileşim `context` alanını taşır: `0` sunucu kanalı, `1` kişinin botunla açtığı DM. Basma, komut, otomatik tamamlama ve form DM'de de aynı çalışır; fark yalnızca kimin nerede olduğundadır:

| Alan | Sunucuda | DM'de |
|---|---|---|
| `context` | `0` | `1` |
| `guild_id` | Sunucunun kimliği | Yok |
| `member` | Kişi, `permissions` dolu | Yok |
| `user` | Yok | Kişi |
| `app_permissions` | Botun bu kanaldaki izinleri | DM'nin sabit izinleri |

```js
// Aynı kod sunucuda ve DM'de çalışır.
const guildId = interaction.guild_id ?? null; // DM'de null
const person = interaction.member?.user ?? interaction.user;
const inDM = interaction.context === 1;
if (inDM) {
  // Rol yok, izin yok: yetki isteyen işi burada yapma.
}
```

Yanıt rotaları DM'de de aynıdır. Kişi DM'yi kapatır ya da botu engellerse yanıt `403 dm_closed` alır ([Özel mesajlar](https://noluyo.net/gelistirici/ozel-mesajlar.md#kapatma-ve-engel)).

## Hangi yanıtı seçmeliyim?

| İşin 3 saniyeden uzun sürer mi? | Neyi değiştiriyorsun? | Seç |
|---|---|---|
| Hayır | Kanala yeni bir mesaj yazıyorsun | `type: 4` |
| Hayır | Butonun durduğu mesajı değiştiriyorsun | `type: 7` |
| Evet | Sonuç yeni bir mesaj olacak | `type: 5`, sonra `PATCH @original` |
| Evet | Butonun durduğu mesajı değiştireceksin | `type: 6`, sonra [kanal mesajını düzenle](https://noluyo.net/gelistirici/api-messages.md#editMessage) |
| Evet ya da hayır | Görünen hiçbir şey değişmiyor | `type: 6` |
| Hayır | Bir komuta yanıt veriyorsun | `type: 4` |
| Evet | Bir komuta yanıt veriyorsun | `type: 5`, sonra `PATCH @original` |

Her yanıt her etkileşime uymaz. Uymayanı göndermek `400 interaction_response_invalid` döner:

| Etkileşim | `type: 4` | `type: 5` | `type: 6` | `type: 7` | `type: 8` | `type: 9` |
|---|---|---|---|---|---|---|
| Butona basma, menüden seçme (`type: 3`) | Evet | Evet | Evet | Evet | Hayır | Evet |
| [Komut çalıştırma](https://noluyo.net/gelistirici/komutlar.md#komutu-yanitla) (`type: 2`) | Evet | Evet | Hayır | Hayır | Hayır | Evet |
| [Otomatik tamamlama](https://noluyo.net/gelistirici/otomatik-tamamlama.md) (`type: 4`) | Hayır | Hayır | Hayır | Hayır | Evet | Hayır |
| [Gönderilen form](https://noluyo.net/gelistirici/formlar.md) (`type: 5`) | Evet | Evet | Butondan açıldıysa | Butondan açıldıysa | Hayır | Hayır |

Komut çalıştırmanın üzerinde durduğu bir mesaj yoktur; değiştirilecek bir şey olmadığı için `6` ve `7` almaz. `type: 8` kişi yazarken önerdiğin seçeneklerdir (`data.choices`) ve yalnızca otomatik tamamlamaya uyar. `type: 9` kişiye bir [form](https://noluyo.net/gelistirici/formlar.md) açar; ilk yanıt olmalıdır ve gönderilen form sana yeni bir etkileşim olarak gelir.

Yanıtı yalnızca basan kişi görsün istiyorsan `data` içine `flags: 64` ekle: [Yalnızca basan kişi görsün](https://noluyo.net/gelistirici/etkilesimler.md#yalnizca-basan-kisi-gorsun).

## Yanıt rotası

Dört tür de aynı rotaya gider:

```bash
curl -X POST "https://noluyo.net/api/v1/interactions/$INTERACTION_ID/$INTERACTION_TOKEN/callback" \
  -H "Authorization: Bot $BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"type":4,"data":{"content":"Kaydın alındı."}}'
```

### type 4: yeni mesajla yanıt

Kanala yeni bir mesaj yazar. `data` bir mesaj gibidir: `content`, `embeds`, `components`, `allowed_mentions`. Metin ya da embed zorunludur.

```json
{ "type": 4, "data": { "content": "Kaydın alındı." } }
```

Yanıt `200` ve mesajdır. Mesajın `interaction` alanı kimin bastığını söyler:

```json
{
  "message": {
    "id": "111600000000000500",
    "type": 0,
    "channel_id": "111500000000000100",
    "content": "Kaydın alındı.",
    "application_id": "111540000000000000",
    "interaction": {
      "id": "111600000000000400",
      "type": 3,
      "user": { "id": "111540000000000009", "username": "ayse" }
    }
  }
}
```

### type 5: önce "düşünüyor", sonra sonuç

İşin uzun sürecekse hemen bunu gönder. Kanala boş bir mesaj düşer ve `flags: 128` taşır; kişi onu "düşünüyor" olarak görür. `data` içinden yalnızca `flags` okunur: `content`, `embeds` ve `components` gönderirsen yok sayılır, onları `PATCH @original` ile gönder.

```json
{ "type": 5 }
```

Yanıt `200` ve mesajdır:

```json
{
  "message": {
    "id": "111600000000000500",
    "type": 0,
    "content": "",
    "flags": 128,
    "interaction": {
      "id": "111600000000000400",
      "type": 3,
      "user": { "id": "111540000000000009", "username": "ayse" }
    }
  }
}
```

İş bitince mesajı doldur. `flags`'teki `128` kendiliğinden silinir, mesaj "(düzenlendi)" olarak işaretlenmez:

```bash
curl -X PATCH "https://noluyo.net/api/v1/interactions/$INTERACTION_ID/$INTERACTION_TOKEN/messages/@original" \
  -H "Authorization: Bot $BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"Rapor hazır."}'
```

> **Uyarı:** Botun hiç dönmezse mesaj kanalda boş kalır, `flags: 128` da silinmez. İstemciler böyle bir mesajı süre dolunca "Bot yanıt vermedi" diye gösterir; bu kuralı kendi istemcinde de uygula. Bu mesajı doldurmak bildirim göndermez: içindeki etiket kişiye haber vermez. Haber vermek istiyorsan bir takip mesajı at.

### type 6: sessiz onay

Bastığını aldığını söyler, ekranda hiçbir şey değişmez. Mesaj oluşmaz, `SendMessages` da gerekmez. `data` gönderirsen yok sayılır.

```json
{ "type": 6 }
```

Yanıt `204`, gövdesizdir. Sonra kanala bir şey yazmak istersen takip mesajı kullan. Butonun durduğu mesajı değiştirmek istersen [mesaj düzenleme rotası](https://noluyo.net/gelistirici/api-messages.md#editMessage) çalışır; `@original` burada işe yaramaz, çünkü bu yanıtın mesajı yoktur: istek `200` döner ama ekranda bir şey değişmez.

### type 7: basılan mesajı güncelle

Butonun durduğu mesajı değiştirir. Göndermediğin alan olduğu gibi kalır, boş `components` listesi butonları kaldırır. Yalnızca `components` değişirse mesaj "(düzenlendi)" olarak işaretlenmez.

```json
{ "type": 7, "data": { "content": "Oylama bitti.", "components": [] } }
```

Yanıt `200` ve güncellenen mesajdır:

```json
{
  "message": {
    "id": "111600000000000000",
    "content": "Oylama bitti.",
    "edited_timestamp": "2026-11-07T20:00:00.000Z"
  }
}
```

Bu rotalarda yeni dosya gönderilemez. Görsel göndermek istiyorsan takip mesajı kullan.

## @original ve takip mesajları

İlk yanıtı verdikten sonra token 15 dakika boyunca çalışır:

| İstek | Ne yapar | Yanıt |
|---|---|---|
| `POST /interactions/{id}/{token}/messages` | Yeni takip mesajı yazar, dosya da alır | `200` ve mesaj |
| `PATCH /interactions/{id}/{token}/messages/@original` | `type: 4` ya da `type: 5` mesajını düzenler | `200` ve mesaj |
| `PATCH /interactions/{id}/{token}/messages/{message_id}` | Bu etkileşimin bir mesajını düzenler | `200` ve mesaj |
| `DELETE /interactions/{id}/{token}/messages/{message_id}` | Bu etkileşimin bir mesajını siler, `@original` da olur | `204` |

Token yalnızca kendi etkileşiminin mesajlarına ulaşır. Aynı kanaldaki başka bir mesaj `404 unknown_message` döner. Bir etkileşim en çok 5 takip mesajı atabilir, altıncısı `429` döner. Takip mesajı dosya almak için `multipart/form-data` kullanır; biçimi [mesaj gönderme](https://noluyo.net/gelistirici/api-messages.md#createMessage) ile aynıdır.

```bash
curl -X POST "https://noluyo.net/api/v1/interactions/$INTERACTION_ID/$INTERACTION_TOKEN/messages" \
  -H "Authorization: Bot $BOT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"content":"Bir şey daha: rapor e-postana da gitti."}'
```

Ephemeral takip mesajı dosya almaz ama beşe aynı sayılır. Bir etkileşimin ephemeral mesajları 5 saniyede en çok 5 kez düzenlenebilir, fazlası `429` döner. Ayrıca tüm botlar birlikte bir kişiye 5 saniyede en çok 262144 bayt ephemeral mesaj gönderebilir (metin, embed'ler ve bileşenlerin üç katı sayılır); fazlası `429 rate_limited` döner ve kişiye bir şey gitmez. Yanıtlara yavaş mod ve mesaj sınırı işlemez, çünkü onları bir kişinin basması tetikler. `SendMessages` izni, otomatik moderasyon ve [`interaction` sınıfı](https://noluyo.net/gelistirici/rate-limit.md) ile ortak tavanlar yine geçerlidir.

## Yalnızca basan kişi görsün

`data` içine `flags: 64` eklersen yanıtı yalnızca basan kişi görür. Buna ephemeral mesaj denir. `type: 4`, `type: 5` ve takip mesajında çalışır:

```json
{ "type": 4, "data": { "content": "Kaydın alındı. Bunu yalnızca sen görüyorsun.", "flags": 64 } }
```

Yanıt `200` ve `{"message": ...}`, takip mesajında yalnızca mesajdır. `flags` `64` gelir, `mentions` her zaman boştur. İlk yanıtın kimliği etkileşimin kimliğidir, takip mesajı yeni kimlik alır.

`type: 5` ile `flags: 64` gönderirsen kişi "düşünüyor" görür ve `flags` `192` gelir. `PATCH @original` ile doldurduğunda `64` olur. Bu `PATCH` ve diğerleri yalnızca basan kişiye gider. Kişi artık kanalı görmüyorsa `404 unknown_channel` döner, ona bir şey gitmez.

### Ne zaman kaybolur

N'oluyo bu mesajı saklamaz. Kişi sayfayı yenilerse ya da uygulamayı yeniden açarsa mesaj gider. O anda açık olan başka cihazında da görünür, sonradan açtığı cihazda görünmez. Kişi mesajdaki "Kapat" düğmesiyle onu kendi ekranından kaldırabilir, bu sana haber vermez. Mesaj geçmişte çıkmaz, okunmadı sayacını ve `last_message_id`'yi oynatmaz, bildirim göndermez. Diğer üyeler ve botlar, senin botun da, `MESSAGE_CREATE` almaz.

Kalıcı olması gereken bir şeyi burada söyleme. Kişi mesajı kaybetse de sonucu bulabilmeli.

### Ne yapamaz

| Yapılamayan | Olan | Yerine |
|---|---|---|
| Görsel ya da dosya | `400 ephemeral_files`, hem `attachment://` hem `multipart/form-data` | Dosya bir mesaj satırına bağlıdır, burada satır yok. Görseli herkese açık mesajla gönder. |
| Tepki, sabitleme | Satırı olmayan mesajda çalışmaz | Bileşen kullan. |
| Kanala doğrudan atma | `POST /channels/{id}/messages` `400 ephemeral_forbidden` döner | Bir etkileşime yanıt ver: kime gösterileceğini basma söyler. |
| Kanal mesajı rotalarıyla okuma, düzenleme | `404 unknown_message` | Etkileşim rotalarını kullan. |
| 15 dakika sonra basma | Kişi `400 interaction_expired` alır, sana bir şey gelmez | Mesajı değiştirirsen süre yeniden başlar. |

> **Uyarı:** Ephemeral mesajı düzenlerken göndermediğin alan **boş** sayılır, olduğu gibi kalmaz. Birleştirilecek bir satır yok. `PATCH` ya da `type: 7` içinde yalnızca `embeds` gönderirsen metin gider, yalnızca `components` gönderirsen `400 validation_failed` alırsın. Bedeli şu: metni unutursan kişi onu kaybeder. Her seferinde mesajın tamamını gönder.

### Butonlu ephemeral

Bileşen eklersen kişi basabilir. Mesaj saklanmadığı için botuna gelen `message` kısadır: `id`, `channel_id`, `flags`, `author` ve `components`. **Metni gelmez**, gerekiyorsa bilgiyi `custom_id`'ye koy ya da kendi veritabanında tut.

```json
{
  "type": 4,
  "data": {
    "content": "Silinsin mi?",
    "flags": 64,
    "components": [{ "type": 1, "components": [
      { "type": 2, "style": 4, "label": "Sil", "custom_id": "sil:42" }
    ] }]
  }
}
```

Kişi bastığında:

```json
{
  "id": "111600000000000700",
  "type": 3,
  "token": "...",
  "channel_id": "111500000000000100",
  "data": { "custom_id": "sil:42", "component_type": 2 },
  "message": {
    "id": "111600000000000400",
    "channel_id": "111500000000000100",
    "flags": 64,
    "author": { "id": "111540000000000001", "username": "botun" },
    "components": [{ "type": 1, "components": [
      { "type": 2, "style": 4, "label": "Sil", "custom_id": "sil:42" }
    ] }]
  }
}
```

`type: 7` basılan mesajı değiştirir. `type: 4` ile `flags: 64` yeni bir ephemeral açar, `flags` olmadan herkese açık yanıt verir. `type: 7` sonrası düzenleme için `@original` değil, `message.id` kullan: `PATCH /interactions/{id}/{token}/messages/{message.id}`.

```json
{ "type": 7, "data": { "content": "Silindi.", "components": [] } }
```

> **Not:** Bileşenler mesajla birlikte mühürlenip kişinin istemcisine gider, basarken `ephemeral_state` olarak geri gelir. Kişi onu kurcalarsa, başkasının durumunu ya da mesajda olmayan bir `custom_id` gönderirse `404 component_not_found` alır ve sana bir şey gelmez. Yani gelen `custom_id` senin gönderdiğindir. Ama **güncel olmayabilir**: mesajı değiştirdikten sonra kişi eski durumla, 15 dakika içinde, eski butona yeniden basabilir. Bir kez yapılması gereken işi kendi tarafında denetle. `ephemeral_state` yanıtında sana gelmez.

Satırı olmayan kimlik ephemeral sayıldığı için `type: 6` ya da `type: 7` sonrası `@original` `200` döner ama ekranda bir şey değişmez: o kimlikte mesaj yoktur. İstemci ephemeral `MESSAGE_UPDATE` ve `MESSAGE_DELETE` olayını yalnızca elinde `flags: 64` ile tuttuğu ve `application_id`'si aynı olan mesaja uygular. Böylece bir bot başka botun mesajını değiştiremez.

## Kişi ne görür

> **Not:** Bu bölüm webde gözlenen davranışı anlatır. Masaüstü uygulaması aynı web kodunu kullanır ama ayrıca çalıştırılmadı. Android ve iOS uygulamalarında henüz gözlenmedi.

Etkileşime yanıt olan mesajın üstünde, yanıt satırı gibi, "ad kullandı" yazar. Herkese açık yanıtta bunu kanaldaki herkes görür. Böyle bir mesaj botunun bir önceki mesajıyla tek blokta birleşmez, adı ve avatarıyla ayrı başlar.

`type: 5` sonrası mesajda üç nokta oynar ve "Botun adı düşünüyor…" yazar. `PATCH @original` gelince yerini yanıt alır. Bot 15 dakika içinde doldurmazsa yazı "Bot yanıt vermedi." olur; kişi sonsuza dek bekleyen bir mesaj görmez.

Ephemeral mesaj hafif renkli bir zeminde, solunda temanın renginde bir çizgiyle durur, altında "Yalnızca sen görüyorsun · Kapat" yazar. Üzerinde mesaj araç çubuğu ve sağ tık menüsü yoktur: yanıtlanamaz, iletilemez, sabitlenemez, tepki eklenemez ve bildirilemez. "Kapat" mesajı yalnızca o ekrandan kaldırır. Sayfa yenilenince ephemeral mesajlar gider; okunmadı sayacı ve kanalın son mesajı yerinde kalır.

Ephemeral mesajın butonları ve menüleri herkese açık mesajdakiler gibi çizilir ve basılır. Basınca uygulama mesajla gelen `ephemeral_state`'i geri gönderir, sunucu bileşenleri onunla doğrular. `type: 7` ile yanıt verirsen ephemeral mesaj yerinde değişir. Mesaj gelişinden ya da son güncellenişinden 15 dakika sonra basan kişi "Bu etkileşimin süresi doldu." görür.

## Token'ı koru

> **Uyarı:** Etkileşim token'ı adres satırında durur, bu yüzden log'a kolayca düşer. Kendi log'larında tam adresi yazma. Token'ı kullanıcıya gösterme, başka bir sisteme aktarma.

Token tek başına yetmez: dört rota da `Authorization: Bot` başlığı ister ve token'ı yalnızca etkileşimin gittiği bot kullanabilir. Başka bir botun göndermesi `400 interaction_token_invalid` döner. Sunucu bu rotaların adresindeki token'ı kendi log'larına yazmaz.

## Hatalar

| Kod | Ne oldu | Ne yap |
|---|---|---|
| `interaction_timeout` | İlk yanıt 3 saniyeyi geçti | İşi yanıttan önce yapma. Önce `type: 5` ya da `type: 6` gönder, sonra işe başla. |
| `interaction_already_acknowledged` | Bu etkileşime zaten yanıt verdin | Sonrası için takip mesajı ya da `@original` kullan. |
| `interaction_not_acknowledged` | Takip ya da düzenleme ilk yanıttan önce geldi | Önce `callback` gönder ve yanıtını bekle. |
| `interaction_response_invalid` | Bu etkileşime uymayan bir `type` gönderdin, `type: 7`'de `data` yok, `choices` `type: 8` dışında geldi, ya da `type: 9` otomatik tamamlamaya veya gönderilen forma gitti | Basmaya `4`, `5`, `6`, `7` ya da `9`, komuta `4`, `5` ya da `9`, otomatik tamamlamaya `8` gönder. |
| `interaction_token_invalid` | Token bozuk, adresteki kimlikle uyuşmuyor ya da başka bir botun | `id` ve `token`'ı aynı olaydan al, kendi bot token'ınla gönder. |
| `interaction_expired` | Token'ın 15 dakikası doldu | Kanala normal [mesaj](https://noluyo.net/gelistirici/api-messages.md#createMessage) gönder. |
| `ephemeral_files` | Ephemeral mesajda dosya ya da `attachment://` var | Görseli herkese açık mesajla gönder. |
| `validation_failed` | `data` bir mesaj olarak geçersiz, örneğin metin yok | `errors` alanına bak. Hakkın gitmedi, düzeltip yeniden gönder. |
| `missing_permissions` | Botun bu kanalda `SendMessages` izni yok | `type: 6` izin istemez. Diğerleri için izni ver. |
| `rate_limited` | Sınır doldu; `X-RateLimit-Scope: shared` ise tüm botların ortak tavanı | `retry_after` kadar bekle. 3 saniye geçtiyse ilk yanıt artık kabul edilmez. |

Her tür için hangisi gelebilir:

| Kod | `type: 4` | `type: 5` | `type: 6` | `type: 7` |
|---|---|---|---|---|
| `interaction_timeout` | Evet | Evet | Evet | Evet |
| `interaction_already_acknowledged` | Evet | Evet | Evet | Evet |
| `validation_failed` | Evet | Yalnızca `flags` | Hayır | Evet |
| `missing_permissions` | Evet | Evet | Hayır | Evet |
| `automod_blocked` | Evet | Hayır | Hayır | Evet |

## Tam örnek: sayaç botu

Node.js 22 veya üstü yeter. [Gateway](https://noluyo.net/gelistirici/gateway.md#tam-bir-istemci) sayfasındaki `gateway.mjs` ile [Örnekler](https://noluyo.net/gelistirici/ornekler.md) sayfasındaki `api.mjs` aynı klasörde olmalı. Bot açılınca kanala bir buton atar. Her basmada sayıyı bir artırıp aynı mesajı `type: 7` ile günceller. Sayı `custom_id`'nin içinde durur, bot yeniden başlasa da kaybolmaz:

```js title=sayac-botu.mjs
import { connect } from "./gateway.mjs";
import { call } from "./api.mjs";

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

// Mesajın gövdesi: hem ilk gönderimde hem güncellemede aynı biçim.
const view = (count) => ({
  content: `Sayaç: ${count}`,
  components: [{ type: 1, components: [
    { type: 2, style: 1, label: "Artır", custom_id: `sayac:${count}` },
  ] }],
});

async function onPress(d) {
  const [kind, count] = d.data.custom_id.split(":");
  if (kind !== "sayac") return;
  await call("POST", `/interactions/${d.id}/${d.token}/callback`, {
    type: 7,
    data: view(Number(count) + 1),
  });
}

let posted = false;

await connect({
  intents: 0,
  onEvent(t, d) {
    if (t === "READY" && !posted) {
      posted = true;
      call("POST", `/channels/${CHANNEL_ID}/messages`, view(0)).catch(console.error);
    }
    if (t === "INTERACTION_CREATE") onPress(d).catch(console.error);
  },
});
```

Çalıştırmak için:

```bash
BOT_TOKEN='kopyaladigin_token' CHANNEL_ID='kanal id degeri' node sayac-botu.mjs
```

İki kişi aynı anda basarsa ikisi de aynı sayıyı görüp aynı sonucu yazar. Sayım önemliyse sayıyı kendi veritabanında tut.

## Bu sayfayı yapay zekaya verirsen

> **İpucu:** Bu sayfayı bir yapay zeka asistanına verip kod yazdırıyorsan şu kuralları da ekle:
>
> - Token koda yazılmaz, `process.env.BOT_TOKEN`'dan okunur.
> - İlk yanıt 3 saniye içinde gider. `INTERACTION_CREATE` gelince önce yanıt verilir; iş daha uzun sürecekse `type: 5` ya da `type: 6` gönderilir, iş ondan sonra yapılır.
> - Etkileşim başına tek `callback` gönderilir; sonrası `@original` ya da takip mesajıdır.
> - Etkileşim token'ı 15 dakika yaşar. Etkileşim başına en çok 5 takip mesajı olur; ephemeral mesajlar 5 saniyede en çok 5 kez düzenlenir.
> - Dört rotada da `Authorization: Bot` başlığı zorunludur.
> - Etkileşim token'ı ve tam adres asla log'a yazılmaz.
> - Yetki isteyen işte önce `member.permissions`'a bakılır. DM'de (`context: 1`) `member` yoktur, kişi `user` içindedir: kişi `interaction.member?.user ?? interaction.user` ile, sunucu `interaction.guild_id ?? null` ile okunur.
> - `flags: 64` dosya almaz; düzenlerken mesajın tamamı gönderilir, gönderilmeyen alan silinir.
> - Ephemeral mesajın metni basınca geri gelmez; gereken bilgi `custom_id`'ye konur.

## Sırada ne var

- [Komutlar](https://noluyo.net/gelistirici/komutlar.md): `/` menüsü, kullanıcı ve mesaj komutlarının tanımı
- [Formlar](https://noluyo.net/gelistirici/formlar.md): `type: 9` ile çok satırlı form penceresi açmak
- [HTTP ile teslim](https://noluyo.net/gelistirici/http-teslim.md): etkileşimleri gateway yerine kendi HTTPS adresine almak
