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

为何Discord.js中member.roles.add方法无法正常工作?

Discord.js 角色添加失败问题排查与修复

问题描述

我用以下代码为用户设置颜色专属角色,已经通过console.log确认roleColor能返回正确的角色对象,但始终无法将角色添加到用户身上,尝试传入角色ID也没有效果:

async function role(color) {
  let user = message.member

  user.roles.cache.map(v => { return v }).filter(v => v.name.startsWith('MerasuMin-Clr-')).forEach(role => {
    console.log(role)
    user.roles.remove(role)
  })

  let roleColor = message.guild.roles.cache.find(v => v.name === ("MerasuMin-Clr-"+color))

  user.roles.add(roleColor)

  user.send('Your name in '+message.guild.name+' has colorized to '+color)
}

完整代码如下:

const { Client, EmbedBuilder } = require('discord.js')

module.exports = {
  name: "color",
  type: "customization",
  description: "Customize the color of your name",
  aliases: ["clr", "cl"],
  callback: async(client, message, args, cmd) => {
    let emb = new EmbedBuilder()
    .setTitle('Colorize Name!')
    .setDescription('Colors Available\n\n1⃣ - Black\n2⃣ - Purple\n3⃣ - Pink\n4⃣ - Green\n5⃣ - Orange\n6⃣ - Red\n7⃣ - Blue\n8⃣ - Yellow\n9⃣ - LightBlue')
    .setColor(0xADD8E6)
    .setFooter({ text: message.author.tag, iconUrl: message.author.displayAvatarURL() })
    
    message.reply({embeds:[emb]}).then((msg) => {
      msg.react('1⃣')
      msg.react('2⃣')
      msg.react('3⃣')
      msg.react('4⃣')
      msg.react('5⃣')
      msg.react('6⃣')
      msg.react('7⃣')
      msg.react('8⃣')
      msg.react('9⃣')

      let filter = (reaction, user) => {
        return user.id === message.author.id
      }
      
      msg.awaitReactions({filter, max: 1, time: 172800000, errors: ['time']})
      .then(goods)
      .catch(gan)
      
      async function goods(collected) {
        let reaction = collected.first()
        
        if(reaction.emoji.name === '1⃣') {
          reaction.users.remove(message.author.id)
          return role('Black')
        } else if(reaction.emoji.name === '2⃣') {
          reaction.users.remove(message.author.id)
          return role('Purple')
        } else if(reaction.emoji.name === '3⃣') {
          reaction.users.remove(message.author.id)
          return role('Pink')
        } else if(reaction.emoji.name === '4⃣') {
          reaction.users.remove(message.author.id)
          return role('Green')
        } else if(reaction.emoji.name === '5⃣') {
          reaction.users.remove(message.author.id)
          return role('Orange')
        } else if(reaction.emoji.name === '6⃣') {
          reaction.users.remove(message.author.id)
          return role('Red')
        } else if(reaction.emoji.name === '7⃣') {
          reaction.users.remove(message.author.id)
          return role('Blue')
        } else if(reaction.emoji.name === '8⃣') {
          reaction.users.remove(message.author.id)
          return role('Yellow')
        } else if(reaction.emoji.name === '9⃣') {
          reaction.users.remove(message.author.id)
          return role('LightBlue')
        }

        async function role(color) {
          let user = message.member

          user.roles.cache.map(v => { return v }).filter(v => v.name.startsWith('MerasuMin-Clr-')).forEach(role => {
            console.log(role)
            user.roles.remove(role)
          })

          let roleColor = message.guild.roles.cache.find(v => v.name === ("MerasuMin-Clr-"+color))

          user.roles.add(roleColor)

          user.send('Your name in '+message.guild.name+' has colorized to '+color)
        }
      }
      
      async function gan() {
        setTimeout(() => {
          msg.edit('USED!')
        }, 1000)
      }
    })
  }
}

修复方案

1. 等待异步操作完成

user.roles.add()和user.roles.remove()都是异步Promise方法,原代码直接调用但未等待完成,会导致操作还没执行就跳过。同时forEach无法等待内部异步操作,需改用Promise.all批量处理:

async function role(color) {
  const user = message.member;
  // 过滤用户已有的颜色角色
  const existingColorRoles = user.roles.cache.filter(role => role.name.startsWith('MerasuMin-Clr-'));
  // 等待所有角色移除操作完成
  await Promise.all(existingColorRoles.map(role => user.roles.remove(role)));

  const targetRole = message.guild.roles.cache.find(v => v.name === `MerasuMin-Clr-${color}`);
  if (!targetRole) {
    return user.send('指定颜色的角色不存在,请检查配置');
  }

  try {
    // 等待角色添加操作完成
    await user.roles.add(targetRole);
    await user.send(`你在 ${message.guild.name} 中的昵称颜色已设置为 ${color}`);
  } catch (err) {
    console.error('角色操作失败:', err);
    user.send('设置颜色失败,请联系管理员排查权限问题');
  }
}

2. 检查机器人权限与角色层级

  • 确保机器人拥有ManageRoles权限;
  • 服务器角色设置中,机器人的角色必须高于所有MerasuMin-Clr-*角色,否则无法修改用户的这些角色;
  • 若用户是服务器所有者,机器人无法修改其角色(这是Discord的权限限制)。

3. 代码结构优化

把role函数移到goods函数的最顶部,避免函数提升带来的潜在问题,同时给reaction.users.remove()添加await:

async function goods(collected) {
  // 先定义role函数
  async function role(color) {
    // ...修复后的代码
  }

  let reaction = collected.first()
  // 后续的条件判断逻辑
  if(reaction.emoji.name === '1⃣') {
    await reaction.users.remove(message.author.id);
    return role('Black')
  }
  // ...其他条件分支
}

内容的提问来源于stack exchange,提问作者Filipino ako

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:05:27