You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js v14如何判断用户是否通过特定邀请链接加入?代码排查

问题分析

你的代码存在三个核心问题:

  • 邀请匹配逻辑完全错误:invite.uses > (invite.uses - 1) 这个条件对所有邀请都成立,find只会返回服务器的第一个邀请,根本不是用户实际使用的那个。
  • 邀请码对比不匹配:invite.code 返回的是邀请链接的短码(比如8kPqr25d78),但你拿它和完整的邀请URL(https://discord.gg/8kPqr25d78)对比,必然不相等。
  • 缺少历史邀请数据存储:要判断哪个邀请被使用,必须提前记录所有邀请的使用次数,用户加入后对比次数变化才能定位到目标邀请。
正确实现方法

要实现这个功能,你需要先缓存服务器的邀请使用次数,在用户加入时对比新旧数据找到被使用的邀请,再验证邀请码。

步骤1:初始化邀请缓存(主文件中)

首先在机器人启动时,存储每个服务器的邀请使用次数:

const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] });

// 存储每个服务器的邀请数据:key为guildId,value为Map<邀请短码, 使用次数>
client.inviteCache = new Map();

// 机器人就绪后初始化所有服务器的邀请缓存
client.on('ready', async () => {
  console.log(`Logged in as ${client.user.tag}!`);
  for (const guild of client.guilds.cache.values()) {
    try {
      const invites = await guild.invites.fetch();
      const inviteUses = new Map();
      invites.forEach(invite => inviteUses.set(invite.code, invite.uses));
      client.inviteCache.set(guild.id, inviteUses);
    } catch (err) {
      console.error(`无法获取服务器 ${guild.name} 的邀请列表:`, err);
    }
  }
});

// 机器人加入新服务器时初始化缓存
client.on('guildCreate', async (guild) => {
  try {
    const invites = await guild.invites.fetch();
    const inviteUses = new Map();
    invites.forEach(invite => inviteUses.set(invite.code, invite.uses));
    client.inviteCache.set(guild.id, inviteUses);
  } catch (err) {
    console.error(`无法获取服务器 ${guild.name} 的邀请列表:`, err);
  }
});

// 加载事件处理文件(根据你的项目结构调整)
const fs = require('fs');
const path = require('path');
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));

for (const file of eventFiles) {
  const filePath = path.join(eventsPath, file);
  const event = require(filePath);
  if (event.once) {
    client.once(event.name, (...args) => event.run(...args, client));
  } else {
    client.on(event.name, (...args) => event.run(...args, client));
  }
}

client.login('你的机器人令牌');

步骤2:修改guildMemberAdd事件处理

更新事件文件,对比新旧邀请数据找到被使用的邀请:

module.exports = {
  name: "guildMemberAdd",
  run: async (member, client) => {
    try {
      const oldInvites = client.inviteCache.get(member.guild.id);
      if (!oldInvites) {
        console.log(`服务器 ${member.guild.name} 没有缓存的邀请数据`);
        return;
      }

      // 获取最新的邀请列表
      const newInvites = await member.guild.invites.fetch();
      let usedInvite = null;

      // 对比新旧邀请的使用次数,找到次数增加的邀请
      newInvites.forEach(invite => {
        const oldUses = oldInvites.get(invite.code);
        if (oldUses !== undefined && invite.uses > oldUses) {
          usedInvite = invite;
        }
      });

      if (!usedInvite) {
        console.log(`${member.user.tag} 加入了服务器,但无法追踪使用的邀请`);
        return;
      }

      // 更新缓存为最新的使用次数
      const updatedInvites = new Map();
      newInvites.forEach(invite => updatedInvites.set(invite.code, invite.uses));
      client.inviteCache.set(member.guild.id, updatedInvites);

      // 验证目标邀请码(使用短码而非完整链接)
      const targetCode = '8kPqr25d78';
      if (usedInvite.code === targetCode) {
        console.log(`${member.user.tag} 使用指定邀请链接加入了服务器`);
      } else {
        console.log(`${member.user.tag} 使用其他邀请加入: ${usedInvite.code}`);
      }
    } catch (err) {
      console.error('追踪邀请使用情况时出错:', err);
    }
  }
};

注意事项

  • 确保机器人拥有ManageGuild权限,否则无法获取邀请列表。
  • 如果服务器有临时邀请(比如一次性邀请),需要额外处理这类邀请的过期或删除情况。
  • 缓存会在机器人重启后清空,如需持久化可以使用数据库存储。

内容的提问来源于stack exchange,提问作者Muhammad Athar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:42:51