1

I was working on some code where if I was to do !list <role> (not a mentioned role), it would send an embed listing all users with that role. This is my code but every time I run the command it sends the embed but doesn't list the users in the role.

Code:

  const roleName = args.slice(1).join(" ");

  const userswithrole = message.guild.members.cache.filter(member => { 
       message.guild.roles.cache.find(r => r.name === roleName)}).map(member => { 
         return member.user;
})
      

  const embed = new Discord.MessageEmbed()
      .setTitle(`Users with ${roleName} role`)
      .setDescription(`${userswithrole.join('\n')}`)
      .setColor("RANDOM")
      .setFooter(`${message.author.username}`, message.author.avatarURL({ dynamic:true }))

  return message.channel.send(embed);
Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57

2 Answers2

1

First, I don't think you'll need remove the first argument (args.slice(1)) as the args array doesn't include the command.

Second, userswithrole is a mess at the moment, the filter doesn't do anything.

It would be easier to create a new role variable, check if a role exits with the entered name at all and if not, return an error. If there is a role with that name, you can filter the members.cache and check if the member.roles.cache.has(role.id). It will return a collection of members, you can use the .array() method to convert it to an array and join() them by a newline as you did in your example.

client.on('message', async (message) => {
  if (message.author.bot) return;
  const args = message.content.slice(prefix.length).split(/ +/);
  const command = args.shift().toLowerCase();

  const roleName = args.join(' ');
  const roles = await message.guild.roles.fetch();
  const role = roles.cache.find(
    (r) => r.name.toLowerCase() === roleName.toLowerCase(),
  );
  if (!role)
    return message.channel.send(
      `**Error:** ${roleName} is not a valid role on this server`,
    );
  const members = await message.guild.members.fetch();
  const usersWithRole = members.filter((member) =>
    member.roles.cache.has(role.id),
  );

  const embed = new Discord.MessageEmbed()
    .setTitle(`Users with ${roleName} role`)
    .setDescription(`${usersWithRole.array().join('\n')}`)
    .setColor('RANDOM')
    .setFooter(
      `${message.author.username}`,
      message.author.avatarURL({ dynamic: true }),
    );

  return message.channel.send(embed);
});

enter image description here

If you don't want the user's to be mentioned, you can use the map() method to get their displayName` instead:

const usersWithRole = members.filter((member) =>
  member.roles.cache.has(role.id),
).map(member => member.displayName);

enter image description here

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
  • Wow, thank you. But the command seems to not be working everytime I do it, it comes back with the embed but not actually listing the users. Sometimes it'll work but other times it'll just show nothing in the description part of the embed. Is there any solution to that. Thanks anyway! – bigballer123 Jul 29 '21 at 19:10
  • Maybe the members are not cached, I've just updated my answer above. Could you test it again? Thanks – Zsolt Meszaros Jul 29 '21 at 19:16
  • looks like the command reads the message if the role is wrong and reply's with the error message but it doesn't send the users in an embed, neither does it give an error message in the terminal. – bigballer123 Jul 29 '21 at 19:35
  • Looks like now it gives an error message, it is: ```Error [GUILD_MEMBERS_TIMEOUT]: Members didn't arrive in time.``` – bigballer123 Jul 29 '21 at 19:42
  • That means `GUILD_MEMBERS` intents are not enabled. Check out this post to enable them: https://stackoverflow.com/questions/64559390/none-of-my-discord-js-guildmember-events-are-emitting-my-user-caches-are-basica/64559391#64559391 – Zsolt Meszaros Jul 29 '21 at 19:58
  • Wow, perfect works now. Thank You so much! – bigballer123 Jul 29 '21 at 20:19
  • This is akward, both of our answers work according to the OP haha. – Elitezen Jul 30 '21 at 02:19
1

A Role has a members property which holds it's cached members who have this role.

For commands like these it's best to fetch all GuildMembers first for most accuracy. You will need to enable the GuildMember's intent for fetching to work.

This example will use async/await, ensure to make your function async otherwise use callbacks

try {
   await message.guild.members.fetch();
   const role = message.guild.roles.cache.find(r => r.name === roleName);
   const usersWithRole = role.members.map(m => `${m.user.username}`)
      .join('\n');

   // Embed work here
} catch (err) {
   console.error(err);
}
Elitezen
  • 6,551
  • 6
  • 15
  • 29