#TypeError [INVALID_TYPE] Supplied permissions is not an Array of ApplicationCommandPermissionData.

1 messages · Page 1 of 1 (latest)

blazing cloud
#

okay let's move here

idle cedar
#

okay

blazing cloud
#

firstly, what's this doing? what is this?

        AppCommands?.create(slashCommand.structure).then((command) => {
#

it makes a single command?

idle cedar
#

Yes.

blazing cloud
#

okay that's a problem, you're looping through and registering one by one
which is bad, too many api requests
there is a bulk-update function for registering commands

#

first let's fix that
then we can bulk update permissions as well

#

so what do you want? work with this or convert to the guide first?

idle cedar
#

I think there is no difference, bc the problem will remain in any case.

blazing cloud
#

not at all, there's a massive difference, a lot of people get rate limited and ask for help in #djs-help-v14 and there's nothing they can really do
what your system does is that it tries to update commands every time the bot's on regardless of whether or not there has been a change see
and that is sending needless api requests which could potentially get your bot rate limited
my suggestion is, fix it before it's too late, avoid api spam and discard terrible practices

#

in the end all those rate limited people can do is just wait for the rate limit to be over and theen fix their code to avoid rate limits
which is just dumb, avoid it from the start and don't let it be a pain

idle cedar
#

Okay, I will follow the guide and will mention you if it gives an error in permissions.

#

Okay?

blazing cloud
#

permissions come in later, we'll setup a neat little system after you fix your registering, we can go at it step by step since the guide doesn't mention it

idle cedar
#

I understood how much my knowledge of English allows me, good 😄

blazing cloud
#

well if there's something you don't get, show the specific line, we can help with that, that's the easy part
easier than the code 😔

idle cedar
#
let commands = []
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
let fs = require('fs')
const {clientId, token} = require("./config.json")
async function CreateCommands(guildId){
    const slashCommandsDir = fs.readdirSync("./slash")
    const commands = []
    for(const slashCommandFileName of slashCommandsDir){
        slashCommand = require(`./slash/${slashCommandFileName}`)
        commands.push(slashCommand.structure);
    }
    const rest = new REST({ version: '9' }).setToken(token);
    (async () => {
        try {
            console.log('Started refreshing application (/) commands.');
    
            await rest.put(
                Routes.applicationGuildCommands(clientId, guildId),
                { body: commands },
            );
    
            console.log('Successfully reloaded application (/) commands.');
        } catch (error) {
            console.error(error);
        }
    })();
}

module.exports.CreateCommands = CreateCommands
#

Did I do everything right?

blazing cloud
#

hmm i'll be right back

#

make it a seperate script entirely

#

follow the guide completely

idle cedar
#

This is a separate file, if you are talking about it.

blazing cloud
#

no like this should be completely detached from your entire bot functionality

#

you use like node index.js or something right? that entire process should not touch this file
you'll run this when you need to using node deploy-commands.js

idle cedar
blazing cloud
#

you can copy paste the entire guide's code too, after you understand what's going, which if you don't, ask

blazing cloud
#

okay back, @idle cedar show your file, i had to go get breakfast 🤠

idle cedar
#
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
let fs = require('fs')
let {clientId, token} = require("./config.json")
let guildId = '821411139316613182';
clientId = clientId + ''
const slashCommandsDir = fs.readdirSync("./slash")
const commands = []
for(const slashCommandFileName of slashCommandsDir){
    slashCommand = require(`./slash/${slashCommandFileName}`)
    commands.push(slashCommand.structure);
    
}
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
    try {
        console.log('Started refreshing application (/) commands.');
        await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands },
        );
    
        console.log('Successfully reloaded application (/) commands.');
    } catch (error) {
        console.error(error);
    }
})();

Right now my code looks like this (it works)

blazing cloud
#

neat

#

you use typescrpt, right?

idle cedar
#

Clear node js

blazing cloud
#

okay do you have like a command class? any like dedicated structure for commands?

#

well either way, i want you to add a permissions property to it

#

is your bot just for one server?

idle cedar
blazing cloud
#

okay then we won't have an issue

north girderBOT
blazing cloud
#

i want you to take a look at this object structure

#

so if you know how permissions work currently, it's like a switch, you mention a role or a user and you mention whether or not you want said role or user to be able to use it

idle cedar
# blazing cloud okay do you have like a command class? any like dedicated structure for commands...
const Discord = require("discord.js")
const {warns} = require("../DataBase.js")
const {createEmbed} = require("../EmbedGenerator.js")
module.exports.execute = async function execute(bot, interaction) {
    . . .
}
module.exports.structure = {
    name: 'dewarn',
    description: "Выдаёт варны",
    options: [
        . . .
    ],
    defaultPermission: false
}

module.exports.permissions =  [
  {
      id: '464464090157416448',
      type: 'ROLE',
      permission: false,
  },
];
blazing cloud
#

yee and i see you already have permissions, nice

blazing cloud
#

you see this line here?

await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands },
        );

make this a variable
call it something like registeredCommands

idle cedar
#
let registeredCommands = await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands },
        );

like that?

blazing cloud
#

yes! exactly

#

now this needs a bit of modification

const commands = []
for(const slashCommandFileName of slashCommandsDir){
    slashCommand = require(`./slash/${slashCommandFileName}`)
    commands.push(slashCommand.structure); 
}
```hmm, perhaps instead of pushing `.structure`, you can push just `slashCommand`
since we need the entire command, we need structure, and permissions
#

and here js await rest.put( Routes.applicationGuildCommands(clientId, guildId), { body: commands }, ); you can use commands.map((cmd) => cmd.structure)
in order to just use structure in the body

idle cedar
#

I did everything, how can I register permissions now?

blazing cloud
#

show me your upadted code first @idle cedar

idle cedar
#
for(const slashCommandFileName of slashCommandsDir){
    slashCommand = require(`./slash/${slashCommandFileName}`)
    commands.push(slashCommand);
    
}
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
    try {
        console.log('Started refreshing application (/) commands.');
        let registeredCommands = await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands.map((cmd) => cmd.structure) },
        );
        
    
        console.log('Successfully reloaded application (/) commands.');
    } catch (error) {
        console.error(error);
    }
})();
blazing cloud
#

okay that's great, that's great
so we need to add another request
it might be applicationGuildCommandPermissions
let me go make sure first

#

Routes.guildApplicationCommandsPermissions @idle cedar create another rest.put and this time, use Routes.guildApplicationCommandsPermissions

#

it also takes two parameters, clientId and guildId

idle cedar
#

As far as I understand, this sets permission for all commands. Can this be done for one specific one?

blazing cloud
#

we want to do it all at once, doing one by one is unnecessary

idle cedar
blazing cloud
#

no no you are changing all of them at once, they all have different overwrites

idle cedar
#
const fullPermissions = [
            {
                id: 'FirstCommandId',
                permissions: [{
                    id: '224617799434108928',
                    type: 'USER',
                    permission: false,
                }],
            },
            {
                id: 'SecondCommandId',
                permissions: [{
                    id: '464464090157416448',
                    type: 'ROLE',
                    permission: true,
                }],
            },
        ];

        await rest.put(
            Routes.guildApplicationCommandsPermissions(clientId, guildId),
            { body: fullPermissions },
        )

Like that?

blazing cloud
#

yes but you need the id

idle cedar
#

Yes, and I'm a little confused as to where I can get this from.

blazing cloud
#

remember our variable registeredCommands?

#

use this ```const fullPermissions = commands.filter((cmd) => cmd.permissions).map(cmd => {
let command = registeredCommands.find(c => c.name === cmd.structure.name)

return {id: command.id, permissions: cmd.permissions}
})``` @idle cedar
basically filter those that even include permissions and then find it's id and create the fullPermissions array

idle cedar
blazing cloud
#

sure @idle cedar could you send the entire code once more just for a check?

idle cedar
#
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
let fs = require('fs')
let {clientId, token} = require("./config.json")
let guildId = '821411139316613182';
clientId = clientId + ''
const slashCommandsDir = fs.readdirSync("./slash")
const commands = []
for(const slashCommandFileName of slashCommandsDir){
    slashCommand = require(`./slash/${slashCommandFileName}`)
    commands.push(slashCommand);
    
}
const rest = new REST({ version: '9' }).setToken(token);
(async () => {
    try {
        console.log('Started refreshing application (/) commands.');
        let registeredCommands = await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands.map((cmd) => cmd.structure) },
        );

        const fullPermissions = commands.filter((cmd) => cmd.permissions).map(cmd => {
            let command = registeredCommands.find(c => c.name === cmd.structure.name)
            
            return {id: command.id, permissions: cmd.permissions}
        })
        
        await rest.put(
            Routes.guildApplicationCommandsPermissions(clientId, guildId),
            { body: fullPermissions },
        )
        
    
        console.log('Successfully reloaded application (/) commands.');
    } catch (error) {
        console.error(error);
    }
})();
Permissions:
module.exports.permissions = [
  {
      id: '942019210589139004',
      type: 1,
      permission: true,
  },
  {
    id: '941396687006605352',
    type: 1,
    permission: false,
  }
];
#

There is just not a big problem.
defaultPermission: false doesn't work

blazing cloud
#

yep looks great 🥳
and i believe it should be default_permission then

idle cedar
blazing cloud
#

@hollow flax guess what day it is, tommorow, and that's how you implement permissions on the split up script

blazing cloud
#

the guide i told you to follow yesterday, this is how you implement permissions on that

hollow flax
#

oh right

#

lmao alr

#

wait

#

then @blazing cloud when do I actually run the script? When I make a new command or...

blazing cloud
#

npm i deploy-commands.js

#

create a new terminal ig, and run the script

hollow flax
#

nah but like

#

how often

#

not how, when

blazing cloud
#

whenever you have a change that you want to actually push

spring flame
# blazing cloud `npm i deploy-commands.js`

Hello, I followed this thread, you explained it well, can I ask you something? 😄 Can I use it like this and have module.exports.permissions in the command? Thanks

command

const { SlashCommandBuilder } = require("@discordjs/builders");
const { MessageEmbed } = require("discord.js");

module.exports = {
    data: new SlashCommandBuilder()
        .setName('idpanel')
        .setDescription('Odešle panel pro vytvoření identity')
        .setDefaultPermission(false),
    async execute(interaction) {
        
    }
}

module.exports.permissions = [
    {
        id: '556478969755467778',
        type: USER,
        permission: true,
    }
]```
#

deploy.js

const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');
const { token } = require('./config.json');
const fs = require('fs');

const commands = [];
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));

// Place your client and guild ids here
const clientId = '967415499065528390';
const guildId = '967084493229932554';

for (const file of commandFiles) {
    const command = require(`./commands/${file}`);
    commands.push(command.data.toJSON());
}

const rest = new REST({ version: '9' }).setToken(token);

(async () => {
    try {
        console.log('Started refreshing application (/) commands.');

        let registeredCommands = await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands },
        );

        const fullPermissions = commands.filter((cmd) => cmd.permissions).map(cmd => {
            let command = registeredCommands.find(c => c.name === cmd.structure.name)
            
            return {id: command.id, permissions: cmd.permissions}
        })
        
        await rest.put(
            Routes.guildApplicationCommandsPermissions(clientId, guildId),
            { body: fullPermissions },
        )

        console.log('Successfully reloaded application (/) commands.');
    } catch (error) {
        console.error(error);
    }
})();
blazing cloud
#

here's what you should do
push just command, leave out the .data.toJSON()

#
let registeredCommands = await rest.put(
            Routes.applicationGuildCommands(clientId, guildId),
            { body: commands },
        );
```over here, map commands to use data.toJSON()
`body: commands.map(cmd => cmd.data.toJSON())`
spring flame
spring flame
blazing cloud
#

how did you even
is that on phone?

spring flame
#

Now I tried it on computer and still isn't working

blazing cloud
#

they don't appear disabled/greyed out for you?

spring flame
blazing cloud
#

are you an admin?

#

do you have the use slash commands permission?

spring flame
blazing cloud
#

then i have no idea, do you have a role that it was disabled for?

blazing cloud
#

hmm, could you try restarting your discord? could be a case of discord being whacky woo hoo

blazing cloud
#

well then i have absolutely no idea