So my goal is to have a command that shows all the bots commands and the attached user permissions. I have the function to fetch the list of commands
var commands = await interaction.guild.commands.fetch()
.catch(error => {
interaction.reply({content: 'Unknown Error', ephemeral: true})
})
And this all works fine, i get a nice collection of my commands, my question is, (which i have been unable to solve for 2 hours). Is how can i iterate over this collection and get the perms for each command, i know how to get the perms for a single command with this
var perms = await interaction.guild.commands.permissions.fetch({command: command.id})
but how can i get a JSON list with all the perms for each command that also can accommodate for perms being undefined (as some commands dont have attached perms)
The issue i have been having is that a function to do so like this
await commands.each(async (command) => {
await interaction.guild.commands.permissions.fetch({command: command.id})
.then(perms => {
console.log(`**${command.name}** \`${command.id}\``)
fields.push({title: command.id, value: perms})
})
.catch(error => {
//Triggered if command has no perms
fields.push({title: command.id, value: 'None'})
})
})
with this the code afterwards that uses fields continues before the fields is filled meaning my message is always empty. How can i make the following code wait for this loop to have fully finished
You have to use Promise.all like this:
await Promise.all(commands.map(async (command) => {
try {
const perms = await interaction.guild.commands.permissions.fetch({command: command.id})
console.log(`**${command.name}** \`${command.id}\``)
fields.push({title: command.id, value: perms})
}
catch(e) {
//Triggered if command has no perms
fields.push({title: command.id, value: 'None'})
}
}))
// At this point the fields array is full (order not guaranteed however)
First of all, I wouldn't mix up await with .then().
You can use Array.from() to convert the Discord.Collection of ApplicationCommands into an array and then simply use for...of.
Also note that ApplicationCommand has .permissions property, so you can take advantage of that.
Straightforward solution (no callbacks):
const fields = [];
const commands = await interaction.guild.commands.fetch();
for (const command of Array.from(commands.values())) {
try {
const permissions = await command.permissions.fetch();
fields.push({title: command.id, value: permissions});
} catch {
fields.push({title: command.id, value: "None"});
}
}
After that the fields array will look something like this (converted into a JSON for visualization):
[
{
"title": "878405785552551936",
"value": "None"
},
{
"title": "878405793769193473",
"value": "None"
},
{
"title": "878405796118003714",
"value": [
{
"id": "878405800618491907",
"permission": true,
"type": "USER"
}
]
}
]
Tested using discord.js ^13.1.0.
Maybe using for await...of
The for await...of statement creates a loop iterating over async iterable objects as well as on sync iterables, including: built-in String, Array, Array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined async/sync iterables. It invokes a custom iteration hook with statements to be executed for the value of each distinct property of the object. This statement can only be used inside an async function.