# Tarifler

Bu sayfadaki dokuz tarif, sunucularda en sık istenen bot işlerinin baştan sona çalışan halleridir. Her tarif hem **JavaScript** (`noluyo-bot`, Node.js 22+) hem **Python** (`noluyo_bot`, Python 3.11+) sekmesiyle yazılmıştır; istediğin sekmeyi kopyalayıp `.env` dosyanla doğrudan çalıştırabilirsin.

Kütüphaneyi henüz kurmadıysan önce [Kurulum](https://noluyo.net/gelistirici/kurulum.md) sayfasındaki beş dakikalık hazırlığı tamamla. Paket kurmadan düz `fetch` ve `WebSocket` kullanan örnekler istersen [Örnekler](https://noluyo.net/gelistirici/ornekler.md) sayfasına; kart, buton, form, komut ve ses ayrıntıları için [Embed'ler](https://noluyo.net/gelistirici/embedler.md), [Bileşenler](https://noluyo.net/gelistirici/bilesenler.md), [Etkileşimler](https://noluyo.net/gelistirici/etkilesimler.md), [Komutlar](https://noluyo.net/gelistirici/komutlar.md), [Formlar](https://noluyo.net/gelistirici/formlar.md) ve [Ses](https://noluyo.net/gelistirici/ses.md) rehberlerine bak.

## 1. Hoş geldin mesajı

Sunucuya yeni bir üye katıldığında belirlediğin kanala karşılama kartı gönderir.

- **Gereken intent:** `GUILD_MEMBERS` (`2`) — **ayrıcalıklıdır**, portalda **Sunucu üyeleri**'ni aç.
- **Gereken izinler:** `ViewChannel` + `SendMessages` (`izin=3072`).
- **Hız sınırı notu:** `bot_message` sınıfına tabidir (kanal başına 5 saniyede 5 mesaj); toplu girişlerde resmi SDK bucket kuyruğu istekleri sıraya dizer.

```js tab=JavaScript
import { Client, Intents } from "noluyo-bot";

const bot = new Client({
  token: process.env.BOT_TOKEN,
  intents: Intents.GUILD_MEMBERS,
});

bot.on("GUILD_MEMBER_ADD", async (member) => {
  await bot.rest.createMessage(process.env.WELCOME_CHANNEL_ID, {
    content: `<@${member.user.id}> aramıza katıldı!`,
    embeds: [
      {
        title: "Hoş geldin!",
        description: "Kurallar kanalına göz atmayı ve kendini tanıtmayı unutma.",
        color: 0x3b82f6,
      },
    ],
  });
});

await bot.login();
```

```py tab=Python
import os
import noluyo_bot

bot = noluyo_bot.Client(
    token=os.environ["BOT_TOKEN"],
    intents=noluyo_bot.Intents.GUILD_MEMBERS,
)

@bot.on("GUILD_MEMBER_ADD")
async def on_member_join(member):
    await bot.rest.create_message(
        os.environ["WELCOME_CHANNEL_ID"],
        {
            "content": f"<@{member['user']['id']}> aramıza katıldı!",
            "embeds": [
                {
                    "title": "Hoş geldin!",
                    "description": "Kurallar kanalına göz atmayı ve kendini tanıtmayı unutma.",
                    "color": 0x3B82F6,
                }
            ],
        },
    )

bot.run()
```

## 2. Otomatik rol verme

Sunucuya katılan her yeni üyeye (botlar hariç) belirlediğin başlangıç rolünü kendiliğinden verir.

- **Gereken intent:** `GUILD_MEMBERS` (`2`) — portalda **Sunucu üyeleri** açık olmalıdır.
- **Gereken izinler:** `ManageRoles` (`izin=268435456`). Sunucu ayarlarında **Roller** listesinde botun kendi rolünü, vereceği rolün **üstüne** sürükle; aksi halde `403 role_hierarchy` döner.
- **Hız sınırı notu:** `bot_write` sınıfındadır; SDK `X-RateLimit-Reset-After` süresine kendiliğinden uyar.

```js tab=JavaScript
import { Client, Intents } from "noluyo-bot";

const bot = new Client({
  token: process.env.BOT_TOKEN,
  intents: Intents.GUILD_MEMBERS,
});

bot.on("GUILD_MEMBER_ADD", async (member) => {
  if (member.user.bot) return;
  await bot.rest.addMemberRole(member.guild_id, member.user.id, process.env.AUTO_ROLE_ID);
});

await bot.login();
```

```py tab=Python
import os
import noluyo_bot

bot = noluyo_bot.Client(
    token=os.environ["BOT_TOKEN"],
    intents=noluyo_bot.Intents.GUILD_MEMBERS,
)

@bot.on("GUILD_MEMBER_ADD")
async def on_member_join(member):
    if member["user"].get("bot"):
        return
    await bot.rest.add_member_role(
        member["guild_id"],
        member["user"]["id"],
        os.environ["AUTO_ROLE_ID"],
    )

bot.run()
```

## 3. Butonla rol seçici

`/rol-paneli` komutuyla kanala butonlu bir mesaj bırakır; butona basan üyede rol yoksa verir, varsa geri alır ve sonucu yalnızca basan kişiye (`ephemeral`) gösterir.

- **Gereken intent:** `0` (`INTERACTION_CREATE` hiçbir intent istemez).
- **Gereken izinler:** `ViewChannel` + `SendMessages` + `ManageRoles` (`izin=268438528`), ayrıca botun rolü verilecek rolün üstünde olmalıdır.
- **Hız sınırı notu:** İlk etkileşim yanıtı (`i.reply`) **3 saniye içinde** gönderilmelidir; bu yüzden önce rol işlemi değil, ya hızlı yanıt ya da ertelenmiş yanıt (`defer`) kullanılır.

```js tab=JavaScript
import { Client } from "noluyo-bot";

const ROLE_ID = process.env.PICKER_ROLE_ID;
const bot = new Client({ token: process.env.BOT_TOKEN, intents: 0 });

bot.on("READY", async () => {
  await bot.commands.sync([
    {
      name: "rol-paneli",
      description: "Duyuru rolü seçme butonunu gönderir",
      default_member_permissions: "268435456",
      contexts: [0],
    },
  ]);
});

bot.interactions.on("rol-paneli", async (i) => {
  await i.reply({
    content: "Duyuru bildirimlerini açıp kapatmak için aşağıdaki butona bas:",
    components: [
      {
        type: 1,
        components: [{ type: 2, style: 1, label: "Duyuru Rolü", custom_id: "toggle_duyuru" }],
      },
    ],
  });
});

bot.interactions.on("toggle_duyuru", async (i) => {
  await i.defer({ ephemeral: true });
  const hasRole = i.member.roles.includes(ROLE_ID);
  if (hasRole) {
    await bot.rest.removeMemberRole(i.guild_id, i.member.user.id, ROLE_ID);
    await i.editReply({ content: "Duyuru rolü senden alındı." });
  } else {
    await bot.rest.addMemberRole(i.guild_id, i.member.user.id, ROLE_ID);
    await i.editReply({ content: "Duyuru rolü sana verildi." });
  }
});

await bot.login();
```

```py tab=Python
import os
import noluyo_bot

ROLE_ID = os.environ["PICKER_ROLE_ID"]
bot = noluyo_bot.Client(token=os.environ["BOT_TOKEN"], intents=0)

@bot.on("READY")
async def on_ready(_):
    await bot.commands.sync(
        [
            {
                "name": "rol-paneli",
                "description": "Duyuru rolü seçme butonunu gönderir",
                "default_member_permissions": "268435456",
                "contexts": [0],
            }
        ]
    )

@bot.interactions.on("rol-paneli")
async def rol_paneli(i):
    await i.reply(
        {
            "content": "Duyuru bildirimlerini açıp kapatmak için aşağıdaki butona bas:",
            "components": [
                {
                    "type": 1,
                    "components": [
                        {"type": 2, "style": 1, "label": "Duyuru Rolü", "custom_id": "toggle_duyuru"}
                    ],
                }
            ],
        }
    )

@bot.interactions.on("toggle_duyuru")
async def toggle_duyuru(i):
    await i.defer(ephemeral=True)
    has_role = ROLE_ID in i.member["roles"]
    user_id = i.member["user"]["id"]
    if has_role:
        await bot.rest.remove_member_role(i.guild_id, user_id, ROLE_ID)
        await i.edit_reply({"content": "Duyuru rolü senden alındı."})
    else:
        await bot.rest.add_member_role(i.guild_id, user_id, ROLE_ID)
        await i.edit_reply({"content": "Duyuru rolü sana verildi."})

bot.run()
```

## 4. Sözcük süzgeci

Kanalda yazılan mesajlarda yasaklı listedeki sözcüklerden biri geçerse mesajı siler ve kısa bir uyarı bırakır.

- **Gereken intent'ler:** `GUILD_MESSAGES | MESSAGE_CONTENT` (`33280`) — portalda **Mesaj içeriği** açık olmalıdır.
- **Gereken izinler:** `ViewChannel` + `SendMessages` + `ManageMessages` + `ReadMessageHistory` (`izin=76800`).
- **Hız sınırı notu:** Tek tek silme `bot_write`, uyarı mesajı `bot_message` sınıfındadır; bot kendi mesajlarını görmezden gelmelidir (`author.bot` kontrolü) yoksa sonsuz döngüye girer.

```js tab=JavaScript
import { Client, Intents } from "noluyo-bot";

const WORDS = (process.env.BLOCKED_WORDS ?? "reklam,bedava ödül")
  .split(",")
  .map((w) => w.trim().toLocaleLowerCase("tr-TR"))
  .filter(Boolean);

const bot = new Client({
  token: process.env.BOT_TOKEN,
  intents: Intents.GUILD_MESSAGES | Intents.MESSAGE_CONTENT,
});

bot.on("MESSAGE_CREATE", async (msg) => {
  if (msg.author.bot || !msg.content) return;
  const text = msg.content.toLocaleLowerCase("tr-TR");
  if (!WORDS.some((w) => text.includes(w))) return;

  await bot.rest.deleteMessage(msg.channel_id, msg.id);
  const warn = await bot.rest.createMessage(msg.channel_id, {
    content: `<@${msg.author.id}> bu sözcük sunucuda yasak.`,
  });
  setTimeout(() => {
    bot.rest.deleteMessage(msg.channel_id, warn.id).catch(() => {});
  }, 8000);
});

await bot.login();
```

```py tab=Python
import asyncio
import os
import noluyo_bot

WORDS = [
    w.strip().lower()
    for w in os.environ.get("BLOCKED_WORDS", "reklam,bedava ödül").split(",")
    if w.strip()
]

bot = noluyo_bot.Client(
    token=os.environ["BOT_TOKEN"],
    intents=noluyo_bot.Intents.GUILD_MESSAGES | noluyo_bot.Intents.MESSAGE_CONTENT,
)

@bot.on("MESSAGE_CREATE")
async def on_message(msg):
    if msg["author"].get("bot") or not msg.get("content"):
        return
    text = msg["content"].lower()
    if not any(w in text for w in WORDS):
        return

    await bot.rest.delete_message(msg["channel_id"], msg["id"])
    warn = await bot.rest.create_message(
        msg["channel_id"],
        {"content": f"<@{msg['author']['id']}> bu sözcük sunucuda yasak."},
    )
    await asyncio.sleep(8)
    try:
        await bot.rest.delete_message(msg["channel_id"], warn["id"])
    except noluyo_bot.ApiError:
        pass

bot.run()
```

## 5. Zamanlı hatırlatma ve duyuru

Belirlediğin kanala her saat başı (ya da seçtiğin aralıkla) hatırlatma mesajı gönderir.

- **Gereken intent:** `0` (yalnızca REST ile mesaj gönderdiği için gateway olayı dinlemesi bile gerekmez).
- **Gereken izinler:** `ViewChannel` + `SendMessages` (`izin=3072`).
- **Hız sınırı notu:** Kanalda yavaş mod (`slowmode`) açıksa ve aralığın ondan kısaysa `429 slowmode` döner; resmi SDK `retry_after` süresini bekleyip gönderir.

```js tab=JavaScript
import { Client } from "noluyo-bot";

const bot = new Client({ token: process.env.BOT_TOKEN, intents: 0 });
const CHANNEL_ID = process.env.REMINDER_CHANNEL_ID;
const INTERVAL_MS = 60 * 60 * 1000; // 1 saat

async function sendReminder() {
  try {
    await bot.rest.createMessage(CHANNEL_ID, {
      content: "Saatlik hatırlatma: su içmeyi ve kısa bir mola vermeyi unutma!",
    });
  } catch (err) {
    console.error("Hatırlatma gönderilemedi:", err.message);
  }
}

await sendReminder();
setInterval(sendReminder, INTERVAL_MS);
```

```py tab=Python
import asyncio
import os
import noluyo_bot

CHANNEL_ID = os.environ["REMINDER_CHANNEL_ID"]
INTERVAL_SECONDS = 3600  # 1 saat

async def main():
    bot = noluyo_bot.Client(token=os.environ["BOT_TOKEN"], intents=0)
    try:
        while True:
            try:
                await bot.rest.create_message(
                    CHANNEL_ID,
                    {"content": "Saatlik hatırlatma: su içmeyi ve kısa bir mola vermeyi unutma!"},
                )
            except noluyo_bot.ApiError as err:
                print("Hatırlatma gönderilemedi:", err)
            await asyncio.sleep(INTERVAL_SECONDS)
    finally:
        await bot.close()

asyncio.run(main())
```

## 6. Butonlu anket

`/anket` komutuyla iki seçenekli bir oylama kartı açar; her üyenin tek oyu vardır, diğer butona basarsa oyu taşınır ve kart anında güncellenir.

- **Gereken intent:** `0`.
- **Gereken izinler:** `ViewChannel` + `SendMessages` (`izin=3072`).
- **Hız sınırı notu:** Buton yanıtları `interaction` sınıfındadır; mesajı ayrı bir `PATCH` yerine doğrudan etkileşim yanıtı (`i.update` / `type: 7`) ile güncellemek ek mesaj kotası harcamaz.

```js tab=JavaScript
import { Client } from "noluyo-bot";

const polls = new Map();
let nextPollId = 1;
const bot = new Client({ token: process.env.BOT_TOKEN, intents: 0 });

function renderPoll(id, poll) {
  return {
    embeds: [
      {
        title: poll.question,
        fields: [
          { name: poll.a, value: `${poll.votesA.size} oy`, inline: true },
          { name: poll.b, value: `${poll.votesB.size} oy`, inline: true },
        ],
        color: 0x10b981,
      },
    ],
    components: [
      {
        type: 1,
        components: [
          { type: 2, style: 1, label: poll.a, custom_id: `vote:${id}:a` },
          { type: 2, style: 2, label: poll.b, custom_id: `vote:${id}:b` },
        ],
      },
    ],
  };
}

bot.on("READY", async () => {
  await bot.commands.sync([
    {
      name: "anket",
      description: "İki seçenekli butonlu anket başlatır",
      contexts: [0],
      options: [
        { type: 3, name: "soru", description: "Anket sorusu", required: true },
        { type: 3, name: "secenek_a", description: "Birinci seçenek", required: true },
        { type: 3, name: "secenek_b", description: "İkinci seçenek", required: true },
      ],
    },
  ]);
});

bot.interactions.on("anket", async (i) => {
  const id = String(nextPollId++);
  const poll = {
    question: String(i.option("soru")),
    a: String(i.option("secenek_a")),
    b: String(i.option("secenek_b")),
    votesA: new Set(),
    votesB: new Set(),
  };
  polls.set(id, poll);
  await i.reply(renderPoll(id, poll));
});

bot.interactions.on(/^vote:/, async (i) => {
  const [, id, side] = i.data.custom_id.split(":");
  const poll = polls.get(id);
  if (!poll) return i.reply({ content: "Bu anket sona erdi.", ephemeral: true });
  const uid = i.person.id;
  poll.votesA.delete(uid);
  poll.votesB.delete(uid);
  (side === "a" ? poll.votesA : poll.votesB).add(uid);
  await i.update(renderPoll(id, poll));
});

await bot.login();
```

```py tab=Python
import itertools
import os
import re
import noluyo_bot

polls = {}
poll_seq = itertools.count(1)
bot = noluyo_bot.Client(token=os.environ["BOT_TOKEN"], intents=0)

def render_poll(pid, poll):
    return {
        "embeds": [
            {
                "title": poll["question"],
                "fields": [
                    {"name": poll["a"], "value": f"{len(poll['votes_a'])} oy", "inline": True},
                    {"name": poll["b"], "value": f"{len(poll['votes_b'])} oy", "inline": True},
                ],
                "color": 0x10B981,
            }
        ],
        "components": [
            {
                "type": 1,
                "components": [
                    {"type": 2, "style": 1, "label": poll["a"], "custom_id": f"vote:{pid}:a"},
                    {"type": 2, "style": 2, "label": poll["b"], "custom_id": f"vote:{pid}:b"},
                ],
            }
        ],
    }

@bot.on("READY")
async def on_ready(_):
    await bot.commands.sync(
        [
            {
                "name": "anket",
                "description": "İki seçenekli butonlu anket başlatır",
                "contexts": [0],
                "options": [
                    {"type": 3, "name": "soru", "description": "Anket sorusu", "required": True},
                    {"type": 3, "name": "secenek_a", "description": "Birinci seçenek", "required": True},
                    {"type": 3, "name": "secenek_b", "description": "İkinci seçenek", "required": True},
                ],
            }
        ]
    )

@bot.interactions.on("anket")
async def create_poll(i):
    pid = str(next(poll_seq))
    poll = {
        "question": str(i.option("soru")),
        "a": str(i.option("secenek_a")),
        "b": str(i.option("secenek_b")),
        "votes_a": set(),
        "votes_b": set(),
    }
    polls[pid] = poll
    await i.reply(render_poll(pid, poll))

@bot.interactions.on(re.compile(r"^vote:"))
async def handle_vote(i):
    _, pid, side = i.data["custom_id"].split(":", 2)
    poll = polls.get(pid)
    if not poll:
        await i.reply({"content": "Bu anket sona erdi."}, ephemeral=True)
        return
    uid = i.person["id"]
    poll["votes_a"].discard(uid)
    poll["votes_b"].discard(uid)
    poll["votes_a" if side == "a" else "votes_b"].add(uid)
    await i.update(render_poll(pid, poll))

bot.run()
```

## 7. Basit seviye ve mesaj sayacı

Üyelerin sunucuda kaç mesaj yazdığını sayar (mesajların metnini okumadan!) ve `/seviye` komutu sorulduğunda kişinin puanını ve seviyesini gösterir.

- **Gereken intent:** `GUILD_MESSAGES` (`512`) — metin okunmadığı için ayrıcalıklı `MESSAGE_CONTENT` intent'ine **ihtiyaç yoktur**!
- **Gereken izinler:** `ViewChannel` + `SendMessages` (`izin=3072`).
- **Hız sınırı notu:** Her mesaja kanalda otomatik "Seviye atladın!" yazmak kalabalık kanallarda `bot_message` kotasını doldurur ve sohbeti böler; sayacı sessizce tutup `/seviye` komutuyla göstermek çok daha temizdir.

```js tab=JavaScript
import { Client, Intents } from "noluyo-bot";

const counts = new Map();
const bot = new Client({
  token: process.env.BOT_TOKEN,
  intents: Intents.GUILD_MESSAGES,
});

bot.on("READY", async () => {
  await bot.commands.sync([
    { name: "seviye", description: "Mesaj sayını ve seviyeni gösterir", contexts: [0] },
  ]);
});

bot.on("MESSAGE_CREATE", (msg) => {
  if (msg.author.bot || !msg.guild_id) return;
  const key = `${msg.guild_id}:${msg.author.id}`;
  counts.set(key, (counts.get(key) ?? 0) + 1);
});

bot.interactions.on("seviye", async (i) => {
  const key = `${i.guild_id}:${i.member.user.id}`;
  const total = counts.get(key) ?? 0;
  const level = Math.floor(Math.sqrt(total / 5)) + 1;
  await i.reply({
    content: `Toplam mesajın: **${total}** — Seviyen: **${level}**`,
    ephemeral: true,
  });
});

await bot.login();
```

```py tab=Python
import math
import os
import noluyo_bot

counts = {}
bot = noluyo_bot.Client(
    token=os.environ["BOT_TOKEN"],
    intents=noluyo_bot.Intents.GUILD_MESSAGES,
)

@bot.on("READY")
async def on_ready(_):
    await bot.commands.sync(
        [{"name": "seviye", "description": "Mesaj sayını ve seviyeni gösterir", "contexts": [0]}]
    )

@bot.on("MESSAGE_CREATE")
async def on_message(msg):
    if msg["author"].get("bot") or not msg.get("guild_id"):
        return
    key = f"{msg['guild_id']}:{msg['author']['id']}"
    counts[key] = counts.get(key, 0) + 1

@bot.interactions.on("seviye")
async def seviye(i):
    key = f"{i.guild_id}:{i.member['user']['id']}"
    total = counts.get(key, 0)
    level = int(math.sqrt(total / 5)) + 1
    await i.reply(
        {
            "content": f"Toplam mesajın: **{total}** — Seviyen: **{level}**",
            "ephemeral": True,
        }
    )

bot.run()
```

## 8. Duyuru komutu (`/duyuru`)

Yalnızca `ManageGuild` yetkisi olan yöneticilerin kullanabildiği `/duyuru` komutuyla seçilen yazı kanalına düzenli bir duyuru embed'i gönderir.

- **Gereken intent:** `0`.
- **Gereken izinler:** Hedef kanalda `ViewChannel` + `SendMessages` (`izin=3072`).
- **Hız sınırı notu:** Binlerce üyeli sunucularda çok büyük embed göndermek ortak yayılma bütçesine (`fanout_too_large`) takılabilir; duyuru metnini öz ve okunaklı tut.

```js tab=JavaScript
import { Client } from "noluyo-bot";

const bot = new Client({ token: process.env.BOT_TOKEN, intents: 0 });

bot.on("READY", async () => {
  await bot.commands.sync([
    {
      name: "duyuru",
      description: "Seçilen kanala resmi duyuru kartı gönderir",
      default_member_permissions: "32", // ManageGuild
      contexts: [0],
      options: [
        { type: 7, name: "kanal", description: "Duyuru kanalı", required: true, channel_types: [0] },
        { type: 3, name: "baslik", description: "Duyuru başlığı", required: true },
        { type: 3, name: "metin", description: "Duyuru metni", required: true },
      ],
    },
  ]);
});

bot.interactions.on("duyuru", async (i) => {
  const channelId = String(i.option("kanal"));
  const title = String(i.option("baslik"));
  const description = String(i.option("metin"));

  await i.defer({ ephemeral: true });
  await bot.rest.createMessage(channelId, {
    embeds: [
      {
        title,
        description,
        color: 0xf59e0b,
        footer: { text: `Duyuran: ${i.member.user.username}` },
      },
    ],
    allowed_mentions: { parse: [] },
  });
  await i.editReply({ content: `Duyuru <#${channelId}> kanalına gönderildi.` });
});

await bot.login();
```

```py tab=Python
import os
import noluyo_bot

bot = noluyo_bot.Client(token=os.environ["BOT_TOKEN"], intents=0)

@bot.on("READY")
async def on_ready(_):
    await bot.commands.sync(
        [
            {
                "name": "duyuru",
                "description": "Seçilen kanala resmi duyuru kartı gönderir",
                "default_member_permissions": "32",  # ManageGuild
                "contexts": [0],
                "options": [
                    {
                        "type": 7,
                        "name": "kanal",
                        "description": "Duyuru kanalı",
                        "required": True,
                        "channel_types": [0],
                    },
                    {"type": 3, "name": "baslik", "description": "Duyuru başlığı", "required": True},
                    {"type": 3, "name": "metin", "description": "Duyuru metni", "required": True},
                ],
            }
        ]
    )

@bot.interactions.on("duyuru")
async def duyuru(i):
    channel_id = str(i.option("kanal"))
    title = str(i.option("baslik"))
    description = str(i.option("metin"))

    await i.defer(ephemeral=True)
    await bot.rest.create_message(
        channel_id,
        {
            "embeds": [
                {
                    "title": title,
                    "description": description,
                    "color": 0xF59E0B,
                    "footer": {"text": f"Duyuran: {i.member['user']['username']}"},
                }
            ],
            "allowed_mentions": {"parse": []},
        },
    )
    await i.edit_reply({"content": f"Duyuru <#{channel_id}> kanalına gönderildi."})

bot.run()
```

## 9. Zaman aşımı moderasyon komutu (`/sustur`)

`ModerateMembers` izni olan moderatörlerin `/sustur` komutuyla bir üyeyi belirlenen dakika boyunca zaman aşımına almasını sağlar.

- **Gereken intent:** `0`.
- **Gereken izinler:** `ModerateMembers` (`izin=1099511627776`). Botun rolü, susturulacak üyenin en yüksek rolünden yukarıda olmalıdır; sunucu sahibi ve `Administrator` olanlar susturulamaz (`403 cannot_timeout`).
- **Hız sınırı notu:** `PATCH /guilds/{guild_id}/members/{user_id}` isteği `bot_write` sınıfındadır; komut kaydetme (`commands.sync`) ise uygulama başına dakikada 20 oluşturma sınırına sahip olduğundan yalnızca başlangıçta bir kez çağrılmalıdır.

```js tab=JavaScript
import { ApiError, Client } from "noluyo-bot";

const bot = new Client({ token: process.env.BOT_TOKEN, intents: 0 });

bot.on("READY", async () => {
  await bot.commands.sync([
    {
      name: "sustur",
      description: "Bir üyeyi belirtilen dakika boyunca zaman aşımına alır",
      default_member_permissions: "1099511627776", // ModerateMembers
      contexts: [0],
      options: [
        { type: 6, name: "uye", description: "Susturulacak üye", required: true },
        {
          type: 4,
          name: "dakika",
          description: "Süre (1-1440 dakika)",
          required: true,
          min_value: 1,
          max_value: 1440,
        },
      ],
    },
  ]);
});

bot.interactions.on("sustur", async (i) => {
  const targetId = String(i.option("uye"));
  const minutes = Number(i.option("dakika"));
  const until = new Date(Date.now() + minutes * 60_000).toISOString();

  await i.defer({ ephemeral: true });
  try {
    await bot.rest.updateMember(i.guild_id, targetId, {
      communication_disabled_until: until,
    });
    await i.editReply({ content: `<@${targetId}> ${minutes} dakika boyunca susturuldu.` });
  } catch (err) {
    if (err instanceof ApiError && err.code === "role_hierarchy") {
      await i.editReply({ content: "Bu üyenin rolü benim rolümden yüksek ya da eşit." });
      return;
    }
    throw err;
  }
});

await bot.login();
```

```py tab=Python
from datetime import datetime, timedelta, timezone
import os
import noluyo_bot

bot = noluyo_bot.Client(token=os.environ["BOT_TOKEN"], intents=0)

@bot.on("READY")
async def on_ready(_):
    await bot.commands.sync(
        [
            {
                "name": "sustur",
                "description": "Bir üyeyi belirtilen dakika boyunca zaman aşımına alır",
                "default_member_permissions": "1099511627776",  # ModerateMembers
                "contexts": [0],
                "options": [
                    {"type": 6, "name": "uye", "description": "Susturulacak üye", "required": True},
                    {
                        "type": 4,
                        "name": "dakika",
                        "description": "Süre (1-1440 dakika)",
                        "required": True,
                        "min_value": 1,
                        "max_value": 1440,
                    },
                ],
            }
        ]
    )

@bot.interactions.on("sustur")
async def sustur(i):
    target_id = str(i.option("uye"))
    minutes = int(i.option("dakika"))
    until = (datetime.now(timezone.utc) + timedelta(minutes=minutes)).isoformat()

    await i.defer(ephemeral=True)
    try:
        await bot.rest.update_member(
            i.guild_id,
            target_id,
            {"communication_disabled_until": until},
        )
        await i.edit_reply({"content": f"<@{target_id}> {minutes} dakika boyunca susturuldu."})
    except noluyo_bot.ApiError as err:
        if err.code == "role_hierarchy":
            await i.edit_reply({"content": "Bu üyenin rolü benim rolümden yüksek ya da eşit."})
            return
        raise

bot.run()
```

## Bu sayfayı yapay zekaya verirsen

> **İpucu:** Bu tarifleri birleştirip daha kapsamlı bir bot yazdırırken yapay zekaya şunları hatırlat:
>
> - Birden çok tarifi tek botta toplarken `intents` bitlerini `|` ile birleştir (örneğin `Intents.GUILD_MEMBERS | Intents.GUILD_MESSAGES | Intents.MESSAGE_CONTENT`) ve ayrıcalıklı olanları portalda aç.
> - `bot.commands.sync([...])` dizisine tüm komutları tek seferde ver; ayrı ayrı `sync` çağrısı yapmak önceki komutların üzerine yazar.
> - Rol verme ve susturma işlemlerinde botun kendi rolü hedef rolden veya hedef üyeden yukarıda olmalıdır (`role_hierarchy`).

## Sırada ne var

- [JavaScript kütüphanesi](https://noluyo.net/gelistirici/kutuphane-js.md) ve [Python kütüphanesi](https://noluyo.net/gelistirici/kutuphane-python.md): `Client`, `rest`, `commands`, `interactions` ve `voice` yöntemlerinin tam referansı
- [Sık hatalar](https://noluyo.net/gelistirici/sik-hatalar.md): rol sırası, boş `content`, `4014` ve etkileşim süresi sorunlarının hızlı çözümü
- [Botu açık tut](https://noluyo.net/gelistirici/botu-acik-tut.md): hazırladığın botu bir Linux sunucuda 7/24 çalıştırmak
