aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Discord Botları

Discord Slash Komut Oluşturma (discord.js v14)

Bir discord slash komut oluşturmak, modern bir Discord botu yazmanın ilk adımıdır. Eski mesaj tabanlı komutların (!ping gibi) yerini artık Discord'un yerel slash command arayüzü aldı: kullanıcı / yazdığında komutların ve seçeneklerin otomatik listelendiği, doğrulanmış girdiler sunan resmi yöntem budur. Bu rehberde discord.js v14 ve Node.js 18+ ile sıfırdan çalışan bir slash komut botu kuracağız: proje kurulumu, SlashCommandBuilder ile komut tanımı, REST API üzerinden deploy ve interactionCreate olayıyla yanıt verme.

Proje kurulumu ve bağımlılıklar

Node.js 18 veya üzeri gerekir; discord.js v14 daha eski sürümleri desteklemez. Boş bir klasörde projeyi başlatın ve tek bağımlılık olan discord.js paketini kurun:

mkdir discord-bot && cd discord-bot
npm init -y
npm install discord.js

package.json içine ESM yerine CommonJS kullanacağımız için ek ayar gerekmez, ancak modern import sözdizimi isterseniz "type": "module" ekleyebilirsiniz. Bu rehberde require tabanlı (CommonJS) JavaScript kullanıyoruz. Token ve ID gibi gizli değerleri kod içine gömmeyin; bir config.json veya ortam değişkeni kullanın:

{
  "token": "BOT_TOKENINIZ",
  "clientId": "UYGULAMA_ID",
  "guildId": "TEST_SUNUCU_ID"
}
  • token: Discord Developer Portal → Bot sekmesinden alınır.
  • clientId: Uygulamanızın (Application) ID'si.
  • guildId: Test ettiğiniz sunucunun ID'si (geliştirici modunu açıp sunucuya sağ tıklayarak alınır).

SlashCommandBuilder ile komut tanımlama

Slash komutlar SlashCommandBuilder sınıfıyla tanımlanır. Bu sınıf discord.js'in (eski adıyla @discordjs/builders) bir parçasıdır ve komutun adını, açıklamasını ve seçeneklerini tip güvenli şekilde kurmanızı sağlar. Basit bir ping ve bir parametre alan selam komutu tanımlayalım. commands adında bir klasör açıp her komutu ayrı dosyaya koymak iyi bir pratiktir, ama burada anlaşılır olması için tek bir dizi kullanıyoruz:

const { SlashCommandBuilder } = require('discord.js');

const commands = [
  new SlashCommandBuilder()
    .setName('ping')
    .setDescription('Botun gecikmesini ölçer'),

  new SlashCommandBuilder()
    .setName('selam')
    .setDescription('Bir kullanıcıyı selamlar')
    .addUserOption(option =>
      option
        .setName('kullanici')
        .setDescription('Selamlanacak kişi')
        .setRequired(true)
    ),
].map(command => command.toJSON());

module.exports = { commands };

.addUserOption, .addStringOption, .addIntegerOption gibi metotlarla komutlara parametre ekleyebilirsiniz. setRequired(true) seçeneği zorunlu kılar. En sonda toJSON() çağrısı, builder nesnesini Discord API'sinin beklediği ham JSON yapısına çevirir.

REST ile komutları deploy etmek

Komutları tanımlamak yeterli değildir; Discord'a kaydetmeniz gerekir. Bunun için REST istemcisini ve Routes yardımcılarını kullanan ayrı bir deploy script yazarız. Geliştirme sırasında Routes.applicationGuildCommands kullanın: tek bir sunucuya anında kaydolur. Global komutlar (Routes.applicationCommands) tüm sunucularda görünür ama yayılması bir saate kadar sürebilir.

const { REST, Routes } = require('discord.js');
const { token, clientId, guildId } = require('./config.json');
const { commands } = require('./commands');

const rest = new REST({ version: '10' }).setToken(token);

(async () => {
  try {
    console.log(`${commands.length} komut deploy ediliyor...`);

    const data = await rest.put(
      Routes.applicationGuildCommands(clientId, guildId),
      { body: commands },
    );

    console.log(`${data.length} komut başarıyla kaydedildi.`);
  } catch (error) {
    console.error(error);
  }
})();

Bu dosyayı node deploy-commands.js ile bir kez çalıştırın. Komutları her değiştirdiğinizde tekrar çalıştırmanız gerekir. rest.put metodu, gönderdiğiniz komut listesinin tamamını mevcut komutlarla değiştirir (üzerine yazar), bu yüzden listeden çıkardığınız komutlar silinir.

Client kurulumu ve interactionCreate olayı

Botun kendisi ayrı bir dosyada (index.js) yaşar. Client nesnesini oluştururken GatewayIntentBits ile hangi olayları almak istediğinizi belirtmeniz gerekir. Slash komutlar için yalnızca Guilds intent'i yeterlidir; mesaj içeriği okumaya gerek yoktur. Komutlara interactionCreate olayında yanıt veririz ve gelen etkileşimin gerçekten bir komut olduğunu interaction.isChatInputCommand() ile doğrularız:

const { Client, GatewayIntentBits } = require('discord.js');
const { token } = require('./config.json');

const client = new Client({
  intents: [GatewayIntentBits.Guilds],
});

client.once('clientReady', () => {
  console.log(`Giriş yapıldı: ${client.user.tag}`);
});

client.on('interactionCreate', async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === 'ping') {
    await interaction.reply(`Pong! Gecikme: ${client.ws.ping}ms`);
  }

  if (interaction.commandName === 'selam') {
    const user = interaction.options.getUser('kullanici');
    await interaction.reply(`Selam ${user}! Hoş geldin.`);
  }
});

client.login(token);

Burada dikkat edilecek noktalar:

  • isChatInputCommand(): Düğme veya menü etkileşimlerini değil, yalnızca slash komutları işler. Bu kontrol olmadan kod commandName okurken hata verebilir.
  • interaction.options.getUser('kullanici'): Tanımladığınız seçeneğin değerini alır. String, integer, boolean için getString, getInteger, getBoolean kullanın.
  • interaction.reply(): Etkileşime 3 saniye içinde yanıt vermelisiniz. Uzun süren işlemlerde önce interaction.deferReply() çağırıp sonra interaction.editReply() ile sonucu gönderin.

Botu çalıştırmak için önce komutları deploy edin, sonra istemciyi başlatın:

node deploy-commands.js
node index.js

Sık karşılaşılan hatalar

  • "Missing Access" hatası: Botu sunucuya applications.commands kapsamıyla davet etmediyseniz komutlar kaydolmaz. OAuth2 URL'sinde hem bot hem applications.commands kapsamlarını seçin.
  • Komut görünmüyor: Guild komutları anında, global komutlar gecikmeli yayılır. Geliştirmede her zaman guild komutu kullanın.
  • "Unknown interaction": Yanıt 3 saniyeden geç geldi. deferReply() kullanın.

Sık Sorulan Sorular

Slash komut ile eski prefix komut arasındaki fark nedir?

Prefix komutlar (!komut) mesaj içeriğini okumayı gerektirir ve Discord'un MessageContent ayrıcalıklı intent'ine ihtiyaç duyar. Slash komutlar ise Discord arayüzüne entegredir, otomatik tamamlama ve girdi doğrulaması sunar ve mesaj içeriği iznine gerek duymaz. Yeni botlar için slash komut zorunlu tercihtir.

Global komutlar neden hemen görünmüyor?

Discord global komutları tüm sunuculara dağıtırken önbelleğe alır; bu yayılım bir saate kadar sürebilir. Geliştirme ve test için Routes.applicationGuildCommands ile tek sunucuya kaydedin, çünkü guild komutları anında etkinleşir.

discord.js v14 için hangi Node.js sürümü gerekir?

discord.js v14, Node.js 18 veya daha yeni sürümü zorunlu kılar. Daha eski sürümlerde kurulum sırasında uyumsuzluk hatası alırsınız. node -v ile sürümünüzü kontrol edin.

Botunuzu bir sonraki seviyeye taşımak ister misiniz? Alt komutlar, otomatik tamamlama, düğmeler ve özel bir bot mimarisi için yardıma ihtiyacınız varsa benimle iletişime geçin ve projenizi birlikte hayata geçirelim.

Devamı için