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
相关产品推荐
相关产品推荐

