discord.js v13机器人:Membership Screening通过后自动角色未分配求助
问题分析与解决方案
核心问题
- 事件监听缺失:用户通过Membership Screening时,不会触发
guildMemberAdd事件,而是触发guildMemberUpdate事件(仅用户的pending状态从true变为false)。原代码只监听了guildMemberAdd,无法捕捉到用户通过筛选的动作。 - 逻辑判断错误:新用户刚加入服务器时,尚未拥有任何角色,因此
hasScreeningRole和hasNoRole都会是false,导致两个分支的逻辑都无法执行。
修正后的代码
const Discord = require('discord.js'); const { Client, Intents } = require('discord.js'); const config = require('../config/config.json'); const fs = require('fs'); const path = require('path'); const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES, Intents.FLAGS.GUILD_MEMBERS] }); client.commands = new Discord.Collection(); const commandDirectories = fs.readdirSync(path.join(__dirname, 'cmd'), { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) .map(dirent => dirent.name); for (const directory of commandDirectories) { const commandFiles = fs.readdirSync(path.join(__dirname, 'cmd', directory)).filter(file => file.endsWith('.js')); for (const file of commandFiles) { const command = require(path.join(__dirname, 'cmd', directory, file)); client.commands.set(command.name, command); } } client.once('ready', () => { console.log('UpstartBot is Up'); }); client.on('messageCreate', message => { if (!message.content.startsWith(config.prefix) || message.author.bot) return; const args = message.content.slice(config.prefix.length).split(/ +/); const commandName = args.shift().toLowerCase(); const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); if (!command) return; try { command.execute(message, args, Discord); } catch (error) { console.error(error); message.reply('执行该命令时出错了!'); } }); // 处理新用户加入,分配No Access角色(未通过筛选时) client.on('guildMemberAdd', async member => { console.log(`${member.user.tag} 加入了服务器!`); const noRole = member.guild.roles.cache.find(role => role.name === "No Access"); if (!noRole) return console.error('未找到「No Access」角色'); // 用户刚加入时处于pending状态,直接分配No Access if (member.pending) { try { await member.roles.add(noRole); console.log(`${member.user.tag} 已被分配「No Access」角色`); } catch (error) { console.error('分配角色失败:', error); } } }); // 监听用户通过筛选的事件(pending状态变化) client.on('guildMemberUpdate', async (oldMember, newMember) => { // 仅处理pending从true变为false的情况(用户通过了筛选) if (oldMember.pending && !newMember.pending) { console.log(`${newMember.user.tag} 通过了成员筛选!`); const screeningRole = newMember.guild.roles.cache.find(role => role.name === "Standard User"); const noRole = newMember.guild.roles.cache.find(role => role.name === "No Access"); if (!screeningRole) return console.error('未找到「Standard User」角色'); if (!noRole) return console.error('未找到「No Access」角色'); try { // 移除No Access,添加Standard User await newMember.roles.remove(noRole); await newMember.roles.add(screeningRole); console.log(`${newMember.user.tag} 已被分配「Standard User」角色`); } catch (error) { console.error('更新角色失败:', error); } } }); client.login(config.token);
关键修改点
- 添加
guildMemberUpdate事件监听,捕捉用户pending状态从true到false的变化(即通过筛选) - 调整
guildMemberAdd的逻辑:新用户加入时直接分配「No Access」角色(因为此时用户处于未通过筛选的pending状态) - 使用
async/await简化异步操作的错误处理 - 增加角色不存在的错误提示,方便排查问题
内容的提问来源于stack exchange,提问作者TechXplore
相关产品推荐
相关产品推荐

