Rehber - Discord Botunda Davet Takip (Invite Logger) Sistemi Nasıl Yapılır? | SroCave - SRO Destek Forumu

Rehber Discord Botunda Davet Takip (Invite Logger) Sistemi Nasıl Yapılır?

  • Konbuyu başlatan Konbuyu başlatan Jhaeger
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 0
  • Görüntüleme Görüntüleme 6

Jhaeger

King of the Underworld
Ayın En Aktif Üyesi
Katılım
9 Şub 2024
Mesajlar
925
Tepkime puanı
1,765
Puanları
93
jhaeger
Discord Davet Takip (Invite Logger) Sistemi Nasıl Yapılır?
discord.js v14 ile kimin kimi davet ettiğini takip eden bot​

Davet takip sistemi nedir?
Bir kullanıcı sunucuya katıldığında hangi davet linkiyle ve kim tarafından geldiğini gösteren sisteme invite logger denir. Şu işler için kullanılır:
  • Kimin kaç kişi davet ettiğini görmek
  • Davet yarışması ve ödüllü etkinlik düzenlemek
  • Sahte hesap ve spam girişlerini fark etmek
  • Giriş-çıkış loglarını tutmak

Sistem nasıl çalışır?
Discord bize "bu kullanıcı şu linkle girdi" demez. Bu yüzden şu mantığı kullanırız:
  1. Bot açılınca sunucudaki tüm davetleri ve kullanım sayılarını hafızaya alır.
  2. Biri sunucuya girince davetler tekrar çekilir.
  3. Kullanım sayısı artan davet bulunur, o davetin sahibi davet eden kişidir.
  4. Hafıza güncellenir.

Gerekenler
  • Node.js 18 veya üstü
  • discord.js v14 (npm i discord.js)
  • Botta Sunucuyu Yönet (Manage Server) yetkisi (davetleri okumak için şart)
  • Developer Portal'da Server Members Intent açık olmalı
  • Bildirimlerin gideceği bir log kanalı

Kod
JavaScript:
const { Client, GatewayIntentBits, Collection, EmbedBuilder, Events } = require('discord.js');

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

const LOG_CHANNEL_ID = 'LOG_KANAL_ID';

// guildId -> (davet kodu -> kullanım sayısı)
const invitesCache = new Collection();
// "guildId-userId" -> daveti yapan kişinin ID'si
const inviterOf = new Map();
// "guildId-inviterId" -> toplam davet sayısı
const inviteCounts = new Map();

const toCache = (invites) => new Collection(invites.map(i => [i.code, i.uses]));

client.once(Events.ClientReady, async () => {
  for (const guild of client.guilds.cache.values()) {
    try {
      invitesCache.set(guild.id, toCache(await guild.invites.fetch()));
    } catch {
      console.log(`${guild.name}: davetler okunamadı (yetki eksik olabilir)`);
    }
  }
  console.log(`${client.user.tag} hazır, davet takibi aktif.`);
});

// Yeni davet oluşturulunca hafızaya ekle
client.on(Events.InviteCreate, (invite) => {
  const cache = invitesCache.get(invite.guild.id) ?? new Collection();
  cache.set(invite.code, invite.uses ?? 0);
  invitesCache.set(invite.guild.id, cache);
});

// Davet silinince hafızadan çıkar
client.on(Events.InviteDelete, (invite) => {
  invitesCache.get(invite.guild.id)?.delete(invite.code);
});

// Üye girince hangi davet kullanıldı?
client.on(Events.GuildMemberAdd, async (member) => {
  const cached = invitesCache.get(member.guild.id);
  let newInvites;
  try {
    newInvites = await member.guild.invites.fetch();
  } catch {
    return;
  }

  const used = newInvites.find(i => i.uses > (cached?.get(i.code) ?? 0));
  invitesCache.set(member.guild.id, toCache(newInvites));

  const logChannel = member.guild.channels.cache.get(LOG_CHANNEL_ID);
  if (!logChannel) return;

  const embed = new EmbedBuilder()
    .setColor(0x57f287)
    .setTitle('Yeni Üye Katıldı')
    .setThumbnail(member.user.displayAvatarURL());

  if (used && used.inviter) {
    const key = `${member.guild.id}-${used.inviter.id}`;
    inviteCounts.set(key, (inviteCounts.get(key) ?? 0) + 1);
    inviterOf.set(`${member.guild.id}-${member.id}`, used.inviter.id);

    embed.setDescription(
      `${member} sunucuya katıldı.\n` +
      `**Davet eden:** ${used.inviter}\n` +
      `**Davet kodu:** \`${used.code}\`\n` +
      `**Toplam daveti:** ${inviteCounts.get(key)}`
    );
  } else {
    embed.setDescription(`${member} sunucuya katıldı.\n**Davet eden:** Bulunamadı (özel URL veya tek kullanımlık davet olabilir)`);
  }

  logChannel.send({ embeds: [embed] });
});

// Üye çıkınca davet edenin sayısını düşür
client.on(Events.GuildMemberRemove, async (member) => {
  const inviterId = inviterOf.get(`${member.guild.id}-${member.id}`);
  const logChannel = member.guild.channels.cache.get(LOG_CHANNEL_ID);
  if (!logChannel) return;

  const embed = new EmbedBuilder()
    .setColor(0xed4245)
    .setTitle('Üye Ayrıldı');

  if (inviterId) {
    const key = `${member.guild.id}-${inviterId}`;
    inviteCounts.set(key, Math.max((inviteCounts.get(key) ?? 1) - 1, 0));
    embed.setDescription(`**${member.user.tag}** sunucudan ayrıldı.\n**Onu davet eden:** <@${inviterId}>\n**Kalan daveti:** ${inviteCounts.get(key)}`);
  } else {
    embed.setDescription(`**${member.user.tag}** sunucudan ayrıldı.`);
  }

  logChannel.send({ embeds: [embed] });
});

client.login('BOT_TOKEN');

Sık yapılan hatalar
  • Davet eden hep "bulunamadı" çıkıyor: Botta Sunucuyu Yönet yetkisi yoktur veya GuildInvites intent'i eksiktir.
  • Üye girince bot hiç tepki vermiyor: Developer Portal'da Server Members Intent kapalıdır.
  • Özel URL (vanity) ile girenler: Vanity URL ile girenleri bu yöntemle yakalayamazsınız, ayrıca ele almak gerekir.
  • Tek kullanımlık davetler: Kullanıldıktan sonra silindiği için yeni listede görünmez, davet eden bulunamaz.
  • Bot kapanınca sayılar sıfırlanıyor: Kodda sayılar hafızada tutuluyor. Kalıcı olması için veritabanına kaydetmek gerekir (aşağıdaki rehbere bakın).

Sonraki adımlar
  • Davet sayılarını veritabanına kaydedip botun yeniden başlamasından etkilenmemesini sağlamak: "Discord Botunda Veritabanı Kullanmak: Kalıcı Kayıt Sistemi" rehberine bakabilirsiniz.
  • /davetlerim slash komutu ekleyip herkesin kendi davet sayısını görmesini sağlamak
  • Davet liderlik tablosu yapmak
  • X kişi davet edene otomatik rol vermek

Sorusu olan veya hata alan olursa konunun altına yazsın, birlikte çözelim.
 
Son düzenleme:
Etiketler Etiketler
#bot #botmaker #discord #gifty #guardcommunity #jhaeger #mmoelite

Geri
Üst Alt