Discord机器人验证系统错误触发私信通知问题求助
Discord机器人验证系统错误触发私信通知问题求助
嘿,我明白你遇到的麻烦了——已经验证过的用户触发任何其他交互(比如Code2里的找队友按钮)都会收到机器人的“已验证”私信,这确实很烦人。让我帮你分析下问题所在,再给你解决方案:
问题根源分析
你的Code1里犯了两个关键错误:
- 重复注册全局交互监听器:每次运行
sendverifizierung命令时,都会给client添加3个新的interactionCreate监听器。这些监听器会一直驻留在机器人进程中,只要有任何交互触发,所有这些监听器都会执行,导致重复触发逻辑。 - 未过滤交互类型:第一个监听器没有判断当前交互是否属于验证系统的组件(比如验证按钮、规则选择菜单),只要用户拥有成员角色
707275842295955530,任何交互都会触发这条私信,不管是验证按钮还是找队友按钮。
解决方案
我们需要把验证相关的交互逻辑合并成一个独立的监听器,并且只处理验证系统的组件,同时避免重复注册监听器:
步骤1:重构Code1的交互逻辑
把所有验证相关的交互处理移到模块顶层(不要放在run方法里),这样只会注册一次监听器,并且只处理验证相关的组件:
const Discord = require('discord.js') const Command = require('../../structures/CommandClass'); const { stripIndents } = require('common-tags'); const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, TextInputStyle, StringSelectMenuBuilder, Events, ModalBuilder, TextInputBuilder } = require('discord.js'); // 用Map存储用户昵称,比全局对象更安全,避免内存泄漏 module.exports = class verifiy extends Command { constructor(client) { super(client, { data: new SlashCommandBuilder() .setName('sendverifizierung') .setDescription('Sende das Verifizierungs Embed') .setDefaultMemberPermissions(PermissionFlagsBits.BanMembers) .setDMPermission(false), }); // 初始化昵称缓存(如果客户端没有的话) if (!client.nicknameCache) { client.nicknameCache = new Map(); } // 只注册一次验证交互监听器 client.on('interactionCreate', async interaction => { const memberRoleId = '707275842295955530'; // 只处理验证系统相关的交互,过滤掉其他组件 const validVerificationCustomIds = ['buttonanfrageverify', 'rulesmenü', 'rolemenü', 'ninput']; if (!validVerificationCustomIds.includes(interaction.customId)) return; const member = await interaction.member.fetch(); // 检查用户是否已验证,仅在验证交互触发时判断 if (member.roles.cache.has(memberRoleId)) { await member.send('**Du bist bereits auf YANKEEUNIT91 COMMUNITY verifiziert!**'); return interaction.deferUpdate(); } // 处理验证按钮点击 if (interaction.isButton() && interaction.customId === 'buttonanfrageverify') { const rulesmenü = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId('rulesmenü') .setPlaceholder('Antwort auswählen') .addOptions( { label: 'Ja, gelesen und einverstanden.', value: 'ja' }, { label: 'Nein, nicht gelsesen und nicht einverstanden.', value: 'nein' } ) ); await interaction.reply({ content:'**Hast du die Regeln gelesen, und bist du damit einverstanden?**', components: [rulesmenü], ephemeral: true }); } // 处理规则选择菜单 else if (interaction.isStringSelectMenu() && interaction.customId === 'rulesmenü') { const selected = interaction.values[0]; const modalsv = new ModalBuilder() .setCustomId('ninput') .setTitle('YANKEEUNIT91 COMMUNITY') .addComponents( new ActionRowBuilder().addComponents( new TextInputBuilder() .setCustomId('nameinput') .setLabel("Server Nickname") .setPlaceholder('Keine Sonderzeichen!') .setStyle(TextInputStyle.Short) .setMinLength(2) .setMaxLength(32) .setRequired(true) ) ); if (selected === 'ja') { await interaction.showModal(modalsv); } else if (selected === 'nein') { await interaction.update({ content:'**Lese dir die Regeln erneut durch! Solltest du nicht mit denn Regeln einverstanden sein, bitten wir dich denn Server zu verlassen.**', components: [], ephemeral: true }); } } // 处理昵称模态框提交 else if (interaction.isModalSubmit() && interaction.customId === 'ninput') { const rolemenü = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() .setCustomId('rolemenü') .setPlaceholder('Rolle auswählen') .addOptions( { label: 'YU91 Glocke', description: 'Erhalte extra Benachrichtigungen über Yankeeunit91.', value: 'glocke' }, { label: 'Gaming News', description: 'Erhalte extra Benachrichtigungen für Neue Infos über z.B Spiele etc.', value: 'news' }, { label: 'Keine', description: 'Erhalte keine Rolle.', value: 'keine' } ) ); await interaction.update({ content:'**Wähle eine Role für die du dich interresierst!**', components: [rolemenü], ephemeral: true }); // 存储处理后的昵称到缓存 const nickname = interaction.fields.getTextInputValue('nameinput').replace(/[^a-zA-Z0-9 ]/g, 'X'); client.nicknameCache.set(interaction.user.id, nickname); } // 处理角色选择菜单 else if (interaction.isStringSelectMenu() && interaction.customId === 'rolemenü') { const selected = interaction.values[0]; const glocke = interaction.guild.roles.cache.get('884820297977573386'); const news = interaction.guild.roles.cache.get('1032524990274351134'); const memberrole = interaction.guild.roles.cache.get(memberRoleId); const nickname = client.nicknameCache.get(interaction.user.id); let failsafe = false; switch(selected) { case 'glocke': await interaction.update({ content:'**Du hast die \`YU91 Glocke\` erhalten. Willkommen in der YANKEEUNIT91 COMMUNITY!**', components: [], ephemeral: true }); await member.roles.add(glocke); break; case 'news': await interaction.update({ content:'**Du hast die \`Gaming News\` erhalten. Willkommen in der YANKEEUNIT91 COMMUNITY!**', components: [], ephemeral: true }); await member.roles.add(news); break; case 'keine': await interaction.update({ content:'**Willkommen in der YANKEEUNIT91 COMMUNITY!**', components: [], ephemeral: true }); break; } await interaction.member.setNickname(nickname).catch(e => (failsafe = true)); await member.roles.add(memberrole); // 移除缓存的昵称,释放内存 client.nicknameCache.delete(interaction.user.id); } }); } async run(client, interaction) { let member = await interaction.member.fetch(); const verifiychannelID = '1052951990331773019'; const verifiychannel = member.guild.channels.cache.get(verifiychannelID); const verifeembed = new EmbedBuilder() .setTitle(`Verifizieren dich!`) .setColor('#00ff0c') .setDescription(stripIndents`Durch das verifizieren erhälst du zugriff auf die YANKEEUNIT91 COMMUNITY!`) .setFooter({ text: 'YANKEEUNIT91 COMMUNITY'}) .setTimestamp(); const buttonva = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('buttonanfrageverify') .setEmoji('✅') .setLabel('Verifizieren') .setStyle(ButtonStyle.Success), ); verifiychannel.send({ embeds: [verifeembed], components: [buttonva] }); await interaction.reply({ content: 'Verifizierungs Embed wurde versendet!', ephemeral: true }); } };
步骤2:修复核心逻辑
- 现在监听器只会处理验证系统的组件(通过
validVerificationCustomIds数组过滤),其他交互(比如Code2的找队友按钮)会直接跳过角色检查。 - 用
Map存储用户昵称替代全局对象,避免内存泄漏和意外覆盖。 - 监听器只在模块初始化时注册一次,不会重复添加导致逻辑重复触发。
这样修改后,只有用户触发验证相关的按钮/菜单时,才会检查是否已验证并发送私信,其他交互完全不受影响。
备注:内容来源于stack exchange,提问作者Marc-Anthony
相关产品推荐
相关产品推荐

