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);
});

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);
