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

discord.js v13机器人:Membership Screening通过后自动角色未分配求助

问题分析与解决方案

核心问题

  1. 事件监听缺失:用户通过Membership Screening时,不会触发guildMemberAdd事件,而是触发guildMemberUpdate事件(仅用户的pending状态从true变为false)。原代码只监听了guildMemberAdd,无法捕捉到用户通过筛选的动作。
  2. 逻辑判断错误:新用户刚加入服务器时,尚未拥有任何角色,因此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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:44:58