Get discord member’s roles by ID

I am looking to get the id of every role a user has. the user being the message author in my case.

i’ve tried various things suggested such as let roles = message.author.roles.id = [] and message.guild.roles.fetch() however nether seem to do what I need.

var XPRole = {};
if (fs.existsSync('noxprole.json')) {
   XPRole = jsonfile.readFileSync('noxprole.json');
}
client.on('message', async (message) => {
    const { member } = message;
    if (message.author.bot) return;
    

    if (message.guild.id in XPRole === false) {
       XPRole[message.guild.id] = {};
    }
    const RoleID = XPRole[message.guild.id];
    if ('...' in RoleID) {
       return;
    }

Any help would be appreciated.


The intention of this code is to compare a users roles against a JSON file containing a list of roles that wont earn xp when typing.

Answer

As Elitezen mentioned in their comment, message.author is a User and Users don’t have roles, only GuildMembers. You also can’t use message.guild.roles as it returns a manager of the roles belonging to this guild, not just those belonging to the member.

You can however get the author of a message as a guild member by using the message.member property. Now, that you have the member, you can get the roles of them by accessing the member’s roles. As the roles property returns a manager, you need to access its cache property:

const roles = message.member.roles.cache;

It returns a collection of the roles of this member, and collections have a .map() method that maps each item to another value into an array. It means that you can easily create an array of role IDs this member has using roles.map:

const memberRoleIDs = roles.map((role) => role.id);
// => ['772088200214723861', '809320713752256548', '8184301957544091683']

As you can see, memberRoleIDs contains all the role IDs the member has.

I’m not sure how you store the role IDs in XPRole[message.guild.id]. It seems you store it as an object and the IDs are the keys. In that case, you can use the Array#some() method that tests if at least one element in the array passes the test implemented by the callback function.

So, if your XPRole[message.guild.id] object with IDs as keys, you can simply compare these keys to the array of role IDs. Check and run the following snippet:

let message = {
  guild: {
    id: 'guildID'
  }
}
const memberRoleIDs = [
  '7720882002147238612',
  '8093207137522565483',
  '8093207137522565481'
];
let XPRole = {
  'guildID': {
    '7437501734702175013': { /**** */ },
    '8093207137522565481': { /**** */ },
    '9483513543347850432': { /**** */ },
  }
}

const containsRole = memberRoleIDs.some(id => id in XPRole[message.guild.id]);

// returns true as 8093207137522565481 is in both
console.log({ containsRole });

If you instead store an array of role IDs like in the following example, you can still use the same some() method but with a different callback, one that checks if any of the user role IDs is included in your XPRole[message.guild.id] array:

let message = {
  guild: {
    id: 'guildID'
  }
}
const memberRoleIDs = [
  '7720882002147238612',
  '8093207137522565483',
  '8093207137522565481'
];
let XPRole = {
  'guildID': [
    '7437501734702175013',
    '8093207137522565481',
    '9483513543347850432',
  ]
}

const containsRole = memberRoleIDs.some(id => XPRole[message.guild.id].includes(id));

// returns true as 8093207137522565481 is in both
console.log({ containsRole });

Here is the full code:

let XPRole = {};
if (fs.existsSync('noxprole.json')) {
  XPRole = jsonfile.readFileSync('noxprole.json');
}

client.on('message', async (message) => {
  if (message.author.bot) return;

  const roles = message.member.roles.cache;
  const memberRoleIDs = roles.map((role) => role.id);

  if (message.guild.id in XPRole === false) {
    XPRole[message.guild.id] = {};
  }

  if (memberRoleIDs.some((id) => id in XPRole[message.guild.id])) {
    return console.log('member has at least one role id included in XPRole');
  }
});