ChordDEV

Chord Geliştirici Dokümantasyonu

Chord Bot API ile kendi botlarını yaz: mesajları canlı dinle, komutlara yanıt ver, sunucularını otomatikleştir. Bu sayfa chord-sdk kütüphanesini, ham REST API'yi ve gateway olaylarını uçtan uca belgeler.

Nasıl çalışır?

  • Uygulama oluşturursun → sana bir bot hesabı ve bir bot tokenı verilir.
  • Botunu, sahibi/yöneticisi olduğun sunuculara eklersin.
  • Botun REST ile mesaj gönderir/okur, gateway (socket.io) ile mesajları canlı dinler.

Başlangıç

  1. Uygulamanı oluştur: Chord'u aç → Ayarlar → Geliştirici Portalı → + Yeni Uygulama. Uygulamana bir ad ver; senin için otomatik bir bot hesabı oluşturulur.
  2. Tokenını kaydet: Token yalnızca oluşturma anında bir kez gösterilir. Güvenli bir yere kaydet (kaybedersen portaldan "Tokenı Yenile" ile yenisini üretirsin — eskisi anında geçersiz olur).
  3. Botu sunucuna ekle: Uygulama detayında Sunucuya Ekle → sahibi veya yöneticisi olduğun bir sunucuyu seç → açılan yetki menüsünden bota vereceğin izinleri seç (hazır paketler: Temel / Moderasyon / Yönetici — ya da tek tek işaretle).
  4. İlk isteğini at:
curl https://chord.tr/api/bot/v1/me \
  -H "Authorization: Bot SENIN_TOKENIN"
{ "id": "...", "username": "muzikbotu-bot", "is_bot": true, "application_id": "..." }

Bu yanıtı gördüysen hazırsın — ister chord-sdk ile ister ham REST ile devam et.

Bot yetkileri & yönetilen rol

Botunu bir sunucuya eklerken Chord sana bir yetki menüsü gösterir ve bot için otomatik bir yönetilen rol oluşturur.

Yetki menüsü

  • Temel — mesaj gönderme, tepki ekleme, geçmişi okuma. Çoğu bot için yeterli.
  • Moderasyon — Temel + mesajları yönetme, üyeleri atma/yasaklama, takma adları yönetme.
  • Yönetici — tüm izinler (diğer seçimleri kapsar; dikkatli ver).
  • İstersen paket seçmeden izinleri tek tek de işaretleyebilirsin.

Yönetilen rol

  • Bot eklenince sunucuda botun adıyla bir rol açılır; seçtiğin izinler bu role yazılır ve bota atanır.
  • Rol "Chord tarafından yönetilir" — elle düzenlenemez ve silinemez; bot sunucudan çıkarılınca (at/yasakla/uygulamayı sil) otomatik kalkar.
  • İzinleri değiştirmek için botu yeniden ekle: portaldan Sunucuya Ekle → aynı sunucuyu seç → yeni izinleri işaretle. Rol güncellenir, yenisi açılmaz.

Herkese açık bot

  • Varsayılan olarak botunu yalnız sen ekleyebilirsin. Portalda uygulamanın ayarlarından "İnsanların botu kendi sunucularına eklemesine izin ver"i açarsan bot herkese açık olur.
  • Açıkken botun profil kartında "Uygulamayı Ekle" butonu görünür — herkes botu, sahibi/yöneticisi olduğu sunuculara aynı yetki menüsüyle davet edebilir.
  • Bot profillerinde arkadaş ekleme ve arama yoktur; botlarla DM açılamaz.
💡 403 mü alıyorsun? Kick/ban/mesaj silme çalışmıyorsa botu Moderasyon paketiyle (ya da ilgili izinlerle) yeniden ekle.

Token güvenliği

Token = botunun şifresi. Kod deposuna koyma, kimseyle paylaşma, istemci tarafı (tarayıcı) kodunda kullanma. Ortam değişkeninde tut: process.env.CHORD_TOKEN.
  • Sunucuda token yalnızca geri döndürülemez özet (sha256) olarak saklanır — biz bile göremeyiz.
  • Sızdıysa: Geliştirici Portalı → uygulaman → Tokenı Yenile. Eski token o an ölür.
  • Botlar yalnızca /api/bot/* uçlarını çağırabilir — DM, ödeme ve hesap uçları bot tokenlarına kapalıdır.

chord-sdk — resmî istemci kütüphanesi

Olay tabanlı Client, msg.reply() gibi kısayollar, otomatik hız-sınırı yönetimi ve TypeScript tip tanımları — bot yazmanın en kolay yolu.

Kurulum

npm install chord-sdk
# canlı olaylar (gateway) için:
npm install socket.io-client
  • Node.js 18+ gerekir (yerleşik fetch).
  • Yalnız REST kullanacaksan (mesaj gönder/oku) socket.io-client gerekmez.
  • npm kullanmak istemezsen kütüphaneyi tek dosya olarak indirip require('./chord-sdk.js') ile de kullanabilirsin.

Hızlı başlangıç — ping botu

const { Client } = require('chord-sdk');

const client = new Client({ token: process.env.CHORD_TOKEN, prefix: '!' });

client.command('ping', (ctx) => ctx.reply('Pong! 🏓'));

client.on('ready', (me) => console.log(`✅ ${me.username} hazır!`));
client.login();
Kütüphane kendi mesajlarını otomatik filtreler (sonsuz döngü olmaz) ve 429 yanıtlarında Retry-After kadar bekleyip isteği kendisi yineler.

Komut framework'ü — en kolay yol

Prefix ayrıştırma, alias ve cooldown'la uğraşma; komutunu kaydet, gerisini kütüphane halletsin:

client.command('selam', (ctx) => {
  ctx.send(`Merhaba ${ctx.message.author.username}! 👋`);
}, {
  aliases: ['merhaba', 'hi'],   // !merhaba ve !hi de çalışır
  cooldown: 3000,                // kullanıcı başına 3 sn bekleme
  description: 'Selam verir',
});

client.command('topla', (ctx) => {
  const [a, b] = ctx.args;       // "!topla 3 5" → args = ['3', '5']
  ctx.reply(`Sonuç: ${Number(a) + Number(b)}`);
});
ctx alanıAçıklama
ctx.messageKomutu tetikleyen Message.
ctx.argsBoşlukla ayrılmış argümanlar: ['3', '5'].
ctx.rawArgsKomut adından sonrasının ham hâli: '3 5'.
ctx.reply(içerik)Komut mesajına yanıt verir.
ctx.send(içerik)Aynı kanala normal mesaj gönderir.
ctx.clientClient'ın kendisi (örn. ctx.client.kick(...)).

Prefix'i new Client({ prefix: '?' }) ile değiştirirsin (varsayılan !). Framework kullanmak zorunda değilsin — client.on('message', ...) her zaman çalışır.

Slash komutları — otomatik ⚡

client.command() ile kaydettiğin her komut, login() sırasında sunucuya slash komutu olarak da yayınlanır. Kullanıcılar kanalda / yazınca botunun komutlarını menüde görür, seçip gönderir — ve aynı handler çalışır:

client.command('zar', (ctx) => {
  const yuz = parseInt(ctx.args[0]) || 6;
  ctx.reply(`🎲 ${1 + Math.floor(Math.random() * yuz)} attın!`);
}, { description: 'Zar atar' });   // "/" menüsünde görünen açıklama

// "!zar 20" da çalışır, "/zar 20" da — ekstra kod yok.

Parametre şeması tanımlarsan / menüsünde parametre çipleri görünür, kullanıcı yazarken aktif parametrenin açıklaması composer üstünde gösterilir ve değerlere ctx.options ile ada göre erişirsin:

client.command('uyari', (ctx) => {
  const { uye, sebep } = ctx.options;      // son parametre kalan metni alır
  ctx.reply(`⚠️ ${uye} uyarıldı — ${sebep || 'sebep yok'}`);
}, {
  description: 'Bir üyeyi uyarır',
  options: [
    { name: 'uye',   description: 'Uyarılacak üye', required: true  },
    { name: 'sebep', description: 'Uyarı sebebi',   required: false },
  ],
});
  • Kutucuklu yazım: şemalı komut seçilince composer kutu moduna geçer — her parametre ayrı kutudur, değerler boşluk içerebilir. Zorunlular baştan açıktır; opsiyoneller "+N daha"ya (ya da boş alana) tıklayınca üstte çıkan Seçenekler listesinden eklenir. Enter gönderir, Esc çıkar; boş zorunlu kutu kırmızıyla işaretlenir ve gönderim engellenir. Değerler bota ctx.options'a isimli gelir.
  • Otomatik doğrulama: zorunlu parametre eksikse bot handler'a girmeden kullanım mesajı atar (Kullanım: /uyari <uye> [sebep]). Kapatmak: { validate: false }.
  • Otomatik /yardim: tüm komutları embed'le listeler (alias help/komutlar). Kendi yardim'in varsa dokunulmaz; kapatmak: new Client({ helpCommand: false }).
  • client.onMention(msg => ...) — bot etiketlenince tetiklenir.
  • Kullanıcı /zar 20 gönderince kanala "X /zar komutunu kullandı" sistem satırı düşer (üzerine gelince tam çağrı görünür); botun yanıtı bu satıra bağlanır.
  • / menüsü botlara göre gruplanır ve en çok kullanılan komutların "Sık Kullanılan" bölümü vardır (cihaz-yerel sayaç).
  • Slash'ta ctx.slash === true, ctx.message null, ctx.interaction doludur; ctx.args/rawArgs/options/reply/send iki yolda da aynıdır.
  • Komut ve parametre adları: küçük harf/rakam/_/-, 1-32 karakter; açıklamalar en çok 100. Bot başına 50 komut, komut başına 10 parametre.
  • Alias'lar yalnız prefix yolunda geçerli — slash menüsünde ana ad görünür.
  • Botun çevrimiçi (gateway'e bağlı) olması gerekir; komut kayıtlı ama bot kapalıysa yanıt gelmez.
  • Kapatmak için: new Client({ syncCommands: false }). Ham REST'ten PUT /v1/commands ile de kaydedebilirsin.

Tek satırlık sohbet akışları — ask / confirm / paginate

"Kullanıcıdan yanıt bekle" normalde event dinleyicisi + filtre + zaman aşımı ister. chord-sdk'da tek satır:

client.command('sinav', async (ctx) => {
  const cevap = await ctx.ask('Başkent neresi?');          // Message | null (timeout)
  const emin  = await ctx.confirm(`**${cevap.content}** — emin misin?`);  // Evet/Hayır → bool
  await ctx.paginate(['Sayfa 1', new Embed().setTitle('Sayfa 2'), 'Sayfa 3']);  // ◀ 1/3 ▶
});

Alt seviye: client.awaitMessage({channelId, userId, filter, timeout}) ve client.awaitInteraction({messageId, userId, match, timeout}) — zaman aşımında null.

Küçük yardımcılar

  • Biçim: bold italic underline strike code codeBlock quote spoiler mention(id) channelMention(id)
  • Süre: duration('1h30m') → ms · await wait('3s') · client.every('30dk', fn) / client.after('10s', fn) (.stop() ile durur; TR birimler: sn/dk/sa/g/hf)
  • Diğer: pick(dizi) rastgele eleman · msg.mentions etiketlenen kullanıcı id'leri

Embed & butonlar — zengin mesajlar

Mesajlara renkli embed kartları ve tıklanabilir buton / dropdown satırları ekleyebilirsin. Builder'larla zincirleme yaz, ya da düz obje geç — ikisi de olur:

const { Embed, Button, SelectMenu, ActionRow } = require('chord-sdk');

client.command('anket', (ctx) => ctx.send({
  embeds: [
    new Embed()
      .setTitle('📊 Anket: En iyi renk?')
      .setDescription('Aşağıdaki butonlardan birini seç!')
      .setColor('#5865F2')
      .addField('Süre', '1 saat', true),
  ],
  components: [
    new ActionRow(
      new Button().setLabel('Mavi').setStyle('primary').setCustomId('anket:mavi'),
      new Button().setLabel('Kırmızı').setStyle('danger').setCustomId('anket:kirmizi'),
    ),
  ],
}));
  • Embed: setTitle setDescription setURL setColor('#RRGGBB') setAuthor setFooter setImage setThumbnail addField(ad, değer, inline?).
  • Button: setLabel setStyle('primary'|'secondary'|'success'|'danger'|'link') setCustomId setEmoji; link butonu için setURL(url) (custom_id yerine).
  • SelectMenu: setCustomId setPlaceholder addOption(etiket, değer, açıklama?).
  • ActionRow: bir satır — en çok 5 buton ya da 1 dropdown alır.
Sınırlar: mesaj başına 10 embed ve 5 satır; embed başına 25 alan; görsel URL'leri yalnız https; custom_id deseni [\w:.-], en çok 64 karakter. Sınır aşımında sunucu fazlasını sessizce kırpar/atar.

Etkileşimler — butona tıklanınca

Bir kullanıcı botunun butonuna tıkladığında ya da dropdown'dan seçim yaptığında botuna etkileşim düşer. İki şekilde yakalarsın:

// 1) Kısayol — belirli custom_id (joker '*' desteklenir):
client.onButton('anket:*', (i) => {
  const secim = i.customId.split(':')[1];
  i.reply(`**${i.user.username}** oyunu kullandı: ${secim}! 🗳️`);
});
client.onSelect('menu', (i) => i.reply(`Seçimin: ${i.values[0]}`));

// 2) Ham olay — hepsi tek yerden:
client.on('interactionCreate', (i) => { /* i.customId'ye göre dallan */ });
Interaction üyesiAçıklama
i.customIdTıklanan component'in kimliği.
i.valuesDropdown seçimleri (buton için boş dizi).
i.userTıklayan: { id, username, display_name }.
i.channelId i.serverId i.messageIdNerede olduğu; messageId component'in bulunduğu mesaj.
i.reply(içerik)Yeni mesaj gönderir (tıklanan mesaja yanıt olarak).
i.update(içerik)Orijinal mesajı günceller — anket sonucu, sayaç, sayfa değiştirme.
Her etkileşim 15 dakika içinde bir kez yanıtlanabilir (reply veya update — ikisi birden değil). İçerik string ya da { content, embeds, components } objesi olabilir.

Client

ÜyeAçıklama
new Client({ token, baseUrl?, allowSelf?, prefix? })token zorunlu. baseUrl varsayılanı https://chord.tr. allowSelf: true botun kendi mesajlarını da 'message' olarak yayar. prefix komut öneki (varsayılan !).
client.login()Gateway'e bağlanır; ready'de çözülür. socket.io-client ister.
client.command(ad, handler, {aliases, cooldown, description})Prefix'li komut kaydeder — komut framework'ü.
client.onButton(customId, handler) · client.onSelect(customId, handler)Buton/dropdown etkileşimi yakalar; 'anket:*' jokeri desteklenir.
client.me()Bot kimliği (REST).
client.servers()[{id, name}] — botun üye olduğu sunucular.
client.channels(serverId)Channel[] — görülebilir metin kanalları.
client.messages(channelId, {limit, before})Message[] geçmiş (limit ≤ 100).
client.sendMessage(channelId, içerik, {replyToId})Mesaj gönderir, Message döner. İçerik string ya da { content, embeds, components, replyToId }.
client.editMessage(cid, mid, içerik)Botun kendi mesajını düzenler (string ya da zengin obje).
client.deleteMessage(cid, mid)Mesaj siler (kendi / moderasyon yetkisiyle başkasının).
client.react / unreact(cid, mid, emoji)Tepki ekler/kaldırır, güncel tepki listesi döner.
client.members(serverId)Member[] — üye listesi.
client.kick(serverId, userId)Üyeyi atar (mod/admin rolü ister).
client.ban(serverId, userId, {reason})Yasaklar — atar + geri giremez.
client.unban(serverId, userId) · client.bans(serverId)Yasağı kaldırır · yasak listesini döner.
client.destroy()Gateway bağlantısını kapatır.
client.userlogin() sonrası bot kimliği.

Olaylar

OlayParametreNe zaman
readymeGateway doğrulandı, bot hazır.
messageMessageÜye olunan sunucularda yeni mesaj (kendi mesajların hariç).
messageUpdateMessageBir mesaj düzenlendi.
messageDelete{messageId, channelId}Bir mesaj silindi.
reactionUpdate{messageId, reactions}Tepkiler değişti.
typing / typingStop{userId, channelId}Yazma göstergesi.
interactionCreateInteractionBotun butonuna/dropdown'ına tıklandı.
errorErrorKimlik/bağlantı hatası.
disconnectBağlantı koptu (socket.io kendiliğinden yeniden dener).

Message

ÜyeAçıklama
msg.id msg.channelId msg.serverIdKimlikler.
msg.contentMesaj metni.
msg.author{ id, username, displayName, isBot }
msg.createdAtDate.
msg.embeds msg.componentsMesajdaki embed'ler ve component satırları (yoksa boş dizi).
msg.reply(içerik)Bu mesaja yanıt gönderir (string ya da { content, embeds, components }).
msg.send(içerik)Aynı kanala normal mesaj.
msg.edit(içerik)Mesajı düzenler (yalnız botun kendi mesajları).
msg.delete()Mesajı siler (başkasınınki için moderasyon yetkisi).
msg.react(emoji) / msg.unreact(emoji)Tepki ekler/kaldırır.
msg.rawHam API objesi (sarılmamış tüm alanlar).

Channel

ÜyeAçıklama
ch.id ch.name ch.category ch.serverIdKanal bilgileri.
ch.send(content)Kanala mesaj gönderir.

Member

ÜyeAçıklama
m.id m.username m.displayNameKimlik bilgileri.
m.role'member' | 'mod' | 'admin'.
m.isBot m.pendingBot mu / kural onayı bekliyor mu.
m.kick()Üyeyi sunucudan atar.
m.ban({reason})Üyeyi yasaklar (atar + geri giremez).

Hatalar — ChordAPIError

try {
  await msg.reply('merhaba');
} catch (err) {
  if (err.name === 'ChordAPIError') {
    console.error(err.status, err.path, err.message);  // örn. 403 /v1/channels/... "yetkin yok"
  }
}

REST Referansı

Taban adres: https://chord.tr/api/bot · Kimlik: her istekte Authorization: Bot <token> başlığı · Gövde: Content-Type: application/json.

Botlar yalnız /api/bot altındaki uçları çağırabilir; diğer tüm API'ler bot tokenına 403 döner. Aşağıdaki yönetim uçları (/apps…) ise yalnızca insan oturumuyla (portal) kullanılır — burada yalnız bot uçları belgelenmiştir.
🛡️ Bot yetkileri: Bot, sunucuda normal bir üyedir. Kick, ban ve başkasının mesajını silmek için sunucu sahibinin bota üye menüsünden mod veya admin rolü vermesi gerekir. Kendi mesajını düzenleme/silme ve tepki eklemek için rol gerekmez.
GET/v1/me

Botun kimliği.

{ "id", "username", "display_name", "is_bot": true, "application_id", "application_name" }
GET/v1/servers

Botun üye olduğu sunucular.

{ "servers": [ { "id", "name" } ] }
GET/v1/servers/:id/channels

Botun görebildiği metin kanalları (kanal izinleri uygulanır; ses kanalları listelenmez).

{ "channels": [ { "id", "name", "category" } ] }
HataSebep
403Bot bu sunucuda üye değil.
GET/v1/channels/:id/messages
Sorgu parametresiAçıklama
limit1–100 (varsayılan 50).
beforeUnix milisaniye — bu zamandan eski mesajlar (sayfalama).

Yanıt: { "messages": [ … ] } — eski → yeni sıralı. Her mesajda author_is_bot alanı vardır.

HataSebep
403Üye değil veya kanalı görme yetkisi yok.
404Kanal yok.
POST/v1/channels/:id/messages
Gövde alanıAçıklama
content1–2000 karakter. embeds ya da components varsa boş bırakılabilir.
embedsİsteğe bağlı — en çok 10 embed: { title, description, url, color, author, footer, image, thumbnail, fields }. Görsel URL'leri yalnız https, renk #RRGGBB, embed başına 25 alan.
componentsİsteğe bağlı — en çok 5 satır: { type:'row', components:[…] }. Satır başına 5 buton veya 1 select; custom_id deseni [\w:.-]{1,64}.
replyToIdİsteğe bağlı — yanıtlanan mesajın id'si. Alıntı başlığı sunucu tarafından otomatik doldurulur.
{ "message": { "id", "channel_id", "content", "author_id", "author_name", "author_is_bot": 1, "created_at", … } }   // 201
HataSebep
400content boş ya da 2000 karakterden uzun.
403Kanala yazma yetkisi yok.
429Hız sınırı — Retry-After başlığına bak.

İçerik kuralları: geçersiz/yetkisiz <:emoji:id> token'ları düz metne düşürülür; @everyone/@here yalnız botun o kanalda Herkesi Etiketle yetkisi varsa çalışır (yoksa zararsızlaştırılır).

PATCH/v1/channels/:cid/messages/:mid

Mesajı düzenler — yalnız botun kendi mesajları. Gövde: { content, embeds?, components? } (POST'la aynı içerik kuralları; embeds/components gönderilmezse eskisi korunur, null gönderilirse temizlenir). Hız sınırı mesaj sınıfıdır (1/sn).

HataSebep
403Mesaj botun değil.
404Kanal/mesaj yok (DM mesajlarına erişilemez).

Yanıt: { "message": … }edited_at dolu, reactions korunmuş.

DELETE/v1/channels/:cid/messages/:mid

Mesajı siler. Yetki: kendi mesajı her zaman; başkasınınki için botun mod/admin rolü ya da o kanalda Mesajları Yönet izni olmalı.

HataSebep
403Silme yetkisi yok.
404Kanal/mesaj yok.
POSTDELETE/v1/channels/:cid/messages/:mid/reactions

Tepki ekler / botun tepkisini kaldırır. Gövde: { emoji } — unicode emoji ("👍") ya da özel emoji token'ı (<:ad:id>). DELETE'te emoji ?emoji= sorgu parametresiyle de verilebilir.

{ "messageId", "reactions": [ { "emoji", "count", "users" } ] }
HataSebep
400Geçersiz emoji.
403Kanalı görme/katılım yetkisi yok.
PUTGET/v1/commands

Slash komutlarını kaydeder — PUT tüm listeyi değiştirir (bulk overwrite), GET mevcut listeyi döner. chord-sdk bunu login()'de senin için yapar; ham REST kullanıyorsan elle çağır.

PUT { "commands": [ {
  "name": "uyari", "description": "Bir üyeyi uyarır",
  "options": [ { "name": "uye", "description": "Uyarılacak üye", "required": true } ]
} ] }
HataSebep
400Geçersiz komut/parametre adı (küçük harf/rakam/_/-, 1-32) ya da 50 komut sınırı.

options isteğe bağlıdır (≤10): menüde çip olarak görünür, kullanıcı yazarken aktif parametrenin açıklaması gösterilir. Değerler yine args (serbest metin) olarak taşınır — chord-sdk bunları ctx.options'a ada göre eşler.

Kayıtlı komutlar, botun üye olduğu her sunucuda kullanıcıların / menüsünde görünür. Kullanım bota gateway'de interaction_create (type:'command') olarak düşer — respond ucuyla yanıtla.

POST/v1/interactions/:id/respond

Bir buton/dropdown etkileşimini yanıtlar. id ve token gateway'deki interaction_create olayından gelir; her etkileşim 15 dk içinde bir kez yanıtlanabilir.

Gövde alanıAçıklama
tokenZorunluinteraction_create yükündeki tek kullanımlık token.
content / embeds / componentsMesaj içeriği (POST /messages ile aynı kurallar).
updatetrue → component'in bulunduğu orijinal mesaj güncellenir; yoksa tıklanan mesaja yanıt olarak yeni mesaj gönderilir.
HataSebep
404Etkileşim yok, süresi doldu (15 dk), zaten yanıtlandı, token uyuşmuyor ya da etkileşim başka botun.
400İçerik boş (yeni mesajda content/embeds/components'ten en az biri gerekli) ya da 2000 karakteri aşıyor.

Yanıt: { "message": … } — gönderilen (201) ya da güncellenen (200) mesaj. chord-sdk'da bunu i.reply() / i.update() senin için yapar.

GET/v1/servers/:id/members

Sunucu üye listesi (moderasyon botları için).

{ "members": [ { "id", "username", "display_name", "role", "is_bot", "pending" } ] }

role: member | mod | admin.

DELETE/v1/servers/:sid/members/:uid

Kick — üyeyi sunucudan atar. Botun sunucuda mod/admin rolü olmalı.

HataSebep
403Botun mod/admin rolü yok.
400Hedef sunucu sahibi ya da botun kendisi.
404Sunucu ya da üye bulunamadı.
POSTDELETEGET/v1/servers/:sid/bans/:uid · /bans

Ban / Unban / Yasak listesi. POST gövdesi: { reason? }. Ban, üyeyi aynı zamanda sunucudan atar ve davetle geri girmesini engeller. Üçü de mod/admin rolü ister.

// GET /v1/servers/:sid/bans →
{ "bans": [ { "user_id", "username", "reason", "banned_by", "created_at", … } ] }

Gateway — canlı olaylar

Gateway, Chord'un socket.io sunucusudur. chord-sdk bunu senin için yönetir (client.login()); ham kullanım:

const { io } = require('socket.io-client');
const socket = io('https://chord.tr');

socket.on('connect', () => socket.emit('authenticate', 'Bot SENIN_TOKENIN'));
socket.on('authenticated', ({ userId }) => console.log('bağlı:', userId));
socket.on('auth_error', (m) => console.error('kimlik hatası:', m));

socket.on('new_message', ({ message }) => {
  if (message.author_is_bot) return;   // kendi/diğer bot mesajlarını yok say
  console.log(`#${message.channel_id}: ${message.author_name}: ${message.content}`);
});

Önemli davranışlar

  • Bot doğrulanınca üye olduğu tüm sunucuların odalarına katılır; kısıtlı kanalların olayları izinsizse gelmez.
  • Kendi mesajların da gelir — sonsuz döngüye girmemek için author_id ile filtrele (chord-sdk bunu otomatik yapar).
  • Bağlantı koparsa socket.io kendisi yeniden dener; yeniden bağlandığında authenticate'i tekrar göndermelisin (chord-sdk otomatik).
  • Bot başına tek gateway bağlantısı kur.
  • Bot sunucuya eklendiğinde/çıkarıldığında oda üyeliği sunucu tarafından anında güncellenir.

new_message yükü

{ "message": {
  "id", "channel_id", "author_id", "content", "created_at",
  "author_name", "author_display", "author_is_bot",
  "reply_to_id", "attachment_url", "reactions": [],
  "embeds": [], "components": []
} }

Diğer olaylar

OlayYükNe zaman
message_edited{ message } (tam mesaj)Bir mesaj düzenlendi.
message_deleted{ messageId, channelId }Bir mesaj silindi.
reaction_update{ messageId, reactions }Bir mesajın tepkileri değişti.
user_typing / user_stopped_typing{ userId, channelId }Biri yazmaya başladı/bitirdi.
interaction_create{ id, token, type, customId?, values?, command?, args?, user, channelId, serverId, messageId }type:'component' → butona/dropdown'a tıklandı; type:'command' → slash komutu kullanıldı (command+args dolu). Yalnız o bota gider; id+token ile respond ucunu çağır (15 dk, tek kullanım).
removed_from_server{ serverId }Bot sunucudan atıldı/yasaklandı.

chord-sdk bunları messageUpdate, messageDelete, reactionUpdate, typing/typingStop, interactionCreate olayları olarak sarar — ham socket dinlemene gerek yok.

Hız sınırları

KapsamSınırAşılınca
Tüm REST istekleri (uygulama başına)5 istek / saniye429 + Retry-After: 1
Mesaj gönderme1 mesaj / saniye429 + Retry-After: 1

chord-sdk 429 aldığında Retry-After kadar bekleyip isteği kendiliğinden üç kez yineler. Ham REST kullanıyorsan aynısını yapmalısın — 429'u yut, bekle, tekrar dene.

Örnek botlar

1) Komut botu — !ping, !zar, !yardım

const { Client } = require('chord-sdk');
const client = new Client({ token: process.env.CHORD_TOKEN, prefix: '!' });

client.command('ping',   (ctx) => ctx.reply('Pong! 🏓'));
client.command('zar',    (ctx) => ctx.reply(`🎲 ${1 + Math.floor(Math.random() * 6)} attın!`), { cooldown: 2000 });
client.command('yardım', (ctx) => ctx.reply('Komutlar: !ping, !zar, !yardım'), { aliases: ['help'] });

client.login();

2) Hoş geldin yanıtlayıcısı

client.on('message', async (msg) => {
  if (/^(selam|merhaba|hey)\b/i.test(msg.content)) {
    await msg.reply(`Selam ${msg.author.displayName || msg.author.username}! 👋`);
  }
});

3) Zamanlanmış duyuru (gateway'siz, yalnız REST)

const { Client } = require('chord-sdk');
const client = new Client({ token: process.env.CHORD_TOKEN });
const KANAL = 'KANAL_ID';

setInterval(async () => {
  await client.sendMessage(KANAL, '⏰ Saat başı hatırlatma!');
}, 60 * 60 * 1000);

4) Moderasyon botu — sil, uyar, üçüncüde at

const YASAKLI = ['spam', 'reklam'];
const ihlal = new Map();   // userId → ihlal sayısı

client.on('message', async (msg) => {
  if (!YASAKLI.some(k => msg.content.toLowerCase().includes(k))) return;

  await msg.delete();                        // mesajı kaldır (mod rolü ister)
  const n = (ihlal.get(msg.author.id) || 0) + 1;
  ihlal.set(msg.author.id, n);

  if (n >= 3) {
    await client.kick(msg.serverId, msg.author.id);   // 3. ihlalde at
  } else {
    const uyarı = await msg.send(`⚠️ ${msg.author.username}, kurallara uy (${n}/3).`);
    await uyarı.react('👮');
  }
});
Bu botun çalışması için botu Moderasyon yetki paketiyle eklemiş olman gerekir — Bot yetkileri & rolü.

5) Anket botu — embed + butonlar + canlı sonuç

const { Client, Embed, Button, ActionRow } = require('chord-sdk');
const client = new Client({ token: process.env.CHORD_TOKEN, prefix: '!' });
const oylar = new Map();   // messageId → { evet:Set, hayir:Set }

client.command('anket', async (ctx) => {
  if (!ctx.rawArgs) return ctx.reply('Kullanım: !anket <soru>');
  const msg = await ctx.send({
    embeds: [new Embed().setTitle(`📊 ${ctx.rawArgs}`).setColor('#5865F2')
      .setFooter('Oy vermek için butona tıkla')],
    components: [new ActionRow(
      new Button().setLabel('Evet 👍').setStyle('success').setCustomId('oy:evet'),
      new Button().setLabel('Hayır 👎').setStyle('danger').setCustomId('oy:hayir'),
    )],
  });
  oylar.set(msg.id, { evet: new Set(), hayir: new Set() });
});

client.onButton('oy:*', async (i) => {
  const oy = oylar.get(i.messageId);
  if (!oy) return i.reply('Bu anket artık aktif değil.');
  const secim = i.customId.split(':')[1];        // 'evet' | 'hayir'
  oy.evet.delete(i.user.id); oy.hayir.delete(i.user.id);
  oy[secim].add(i.user.id);                        // son oy geçerli
  await i.update({                                 // orijinal mesajı güncelle
    embeds: [new Embed().setTitle('📊 Anket').setColor('#5865F2')
      .addField('Evet 👍', `${oy.evet.size} oy`, true)
      .addField('Hayır 👎', `${oy.hayir.size} oy`, true)],
  });
});

client.login();
i.update() orijinal mesajı yerinde günceller — anket sonucu herkese anında yansır. components göndermediğimizde butonlar yerinde kalır (oylama sürer); anketi kapatırken butonları kaldırmak için components: [] gönder.

SSS & sınırlamalar

Botum mesaj atamıyor (403)?

Bot o sunucuda üye mi (portaldan ekledin mi)? Kanalda Mesaj Gönder izni var mı? Botlar sunucuda normal üye rolündedir — kanal izinlerini rol/overwrite'larla yönetebilirsin.

Token'ı kaybettim.

Geliştirici Portalı → uygulaman → Tokenı Yenile. Eski token anında geçersiz olur, botunu yeni token'la yeniden başlat.

Kaç uygulama oluşturabilirim?

Kullanıcı başına 5 aktif uygulama.

Botum kick/ban yapamıyor (403)?

Botu eklerken Moderasyon (ya da Yönetici) yetki paketini seçmemişsindir. Portaldan Sunucuya Ekle → aynı sunucuyu seç → Moderasyon'u işaretle; botun yönetilen rolü güncellenir. Alternatif: sunucu sahibi bota üye listesinden mod/admin rolü verebilir.

Botun rolünü düzenleyemiyorum / silemiyorum?

Normaldir — botun adını taşıyan rol Chord tarafından yönetilir: elle düzenlenemez ve silinemez. İzinleri botu yeniden ekleyerek değiştirirsin; bot sunucudan çıkınca rol otomatik silinir.

Butonlarım tıklanınca hiçbir şey olmuyor?

Botun gateway'e bağlı olmalı (client.login()) — etkileşimler REST'e değil, canlı bağlantıya düşer. Ayrıca her etkileşim 15 dakika içinde ve bir kez yanıtlanabilir; süresi geçen tıklamalara 404 alırsın. client.onButton()'daki custom_id'nin mesajdakiyle eşleştiğini de kontrol et.

Slash komutlarım "/" menüsünde görünmüyor?

Komutlar login() sırasında kaydedilir — botunu en az bir kez login() ile çalıştırdın mı? syncCommands: false vermediğinden ve komut adlarının kurallara uyduğundan (küçük harf/rakam/_/-, 1-32) emin ol. Menü sunucu başına ~1 dk önbelleklidir; görünmezse kanalı değiştirip dön.

Neler henüz yok?

  • DM gönderme/okuma (botlar yalnız sunucu kanallarında).
  • Slash komutlarında yapılandırılmış parametreler (şimdilik ctx.args serbest metin).
  • Bot mesajları bildirim (mention rozeti) üretmez.

Botu nasıl kaldırırım?

Sunucudan: normal üye gibi at (sağ tık → At). Tamamen: portaldan Uygulamayı Sil — token ölür, bot tüm sunuculardan çıkar; mesaj geçmişi kalır.

Sürüm notları

v1.5 (SDK ekleri) — Tek satırlık sohbet akışları: ctx.ask (soru-cevap), ctx.confirm (Evet/Hayır butonları), ctx.paginate (◀ ▶ sayfalı gezgin); alt seviye awaitMessage/awaitInteraction collector'ları; biçimlendiriciler (bold, codeBlock, mention…); duration('1h30m')/wait/pick; client.every/after zamanlayıcıları; msg.mentions.

v1.5 — Slash kutucukları: şemalı komutlarda composer kutu moduna geçer (parametre başına kutu, boşluklu değer, zorunlular baştan açık, opsiyoneller "Seçenekler" listesinden); değerler bota isimli (interaction.options) taşınır. chord-sdk 1.5.0: eksik zorunluda otomatik kullanım mesajı (validate:false ile kapanır), otomatik /yardim (helpCommand), client.onMention().

v1.4 — Slash v2: komutlara parametre şeması (options: ad + açıklama + zorunlu); / menüsü bot gruplarıyla ve "Sık Kullanılan" bölümüyle yenilendi (çipler + açıklamalar); yazarken composer üstünde aktif parametre ipucu çubuğu; sistem satırında /komut vurgusu + hover'da tam çağrı. chord-sdk 1.4.0: options tanımı ve ctx.options (son parametre kalan metni alır).

v1.3 — Slash komutları: PUT /v1/commands ile kayıt, istemcide / menüsü, kanala "X /komut kullandı" sistem satırı, bota interaction_create (type:'command'); herkese açık bot bayrağı (PATCH /apps/:id) + profilde "Uygulamayı Ekle"; bot profillerinde arkadaş ekleme/arama kaldırıldı. chord-sdk 1.3.0: komutlar login()'de otomatik slash olarak yayınlanır (syncCommands), slash'ta aynı ctx (ctx.slash, ctx.interaction).

v1.2 — Etkileşim çağı: mesajlarda embed kartları ve buton/dropdown component'leri; interaction_create gateway olayı + POST /v1/interactions/:id/respond; bot eklerken yetki menüsü (Temel/Moderasyon/Yönetici) ve otomatik yönetilen rol; yanıtlarda alıntı başlığı sunucuda otomatik dolduruluyor. chord-sdk 1.2.0: client.command() komut framework'ü (prefix/alias/cooldown), Embed/Button/SelectMenu/ActionRow builder'ları, Interaction (i.reply/i.update), client.onButton/onSelect.

v1.1 — Moderasyon: mesaj düzenleme/silme, kick/ban/unban, üye listesi, tepkiler; gateway'de message_edited/message_deleted/reaction_update/typing dokümante edildi; chord-sdk 1.1.0 (Member sınıfı, msg.edit/delete/react, yeni olaylar).

v1.0 — İlk sürüm: uygulama/token yönetimi, REST v1 (me, servers, channels, messages get/post), gateway new_message, chord-sdk 1.0.0 (npm).

Soru & geri bildirim: destek@chord.tr · chord.tr · Bot tokenınla ilgili bir güvenlik sorunu bulursan lütfen sorumlu bildirim yap.