简体   繁体   English

Discord.js SlashCommandBuilder():从异步列表中获取选项选择 function

[英]Discord.js SlashCommandBuilder() : get option choices from a list in an async function

I'm trying to create a slash command /test3 with an option input that has choices.我正在尝试创建一个带有选项input的斜杠命令/test3 However, I'd like to get these choices from an async function, but the way I'm trying to do it isn't working.但是,我想从异步 function 中获得这些选择,但我尝试这样做的方式不起作用。

Here is the code to generate a simplified version of my argument list, in tools.js这是在tools.js中生成我的参数列表的简化版本的代码

module.exports = {
    getArgumentList: () => getArgumentList()
}

async function getArgumentList(){
    return [
        {name: '1', value:'One'},
        {name: '2', value:'Two'},
        {name: '3', value:'Three'},
        {name: '4', value:'Four'},
        {name: '5', value:'Five'}
    ]
}

And the code for the command, in test3.js以及命令的代码,在test3.js

const { SlashCommandBuilder } = require("discord.js");
const { getArgumentList } = require("../tools.js")

module.exports = {
    data: new SlashCommandBuilder()
            .setName('test3')
            .setDescription('Test command for commands with options.')
            .addStringOption(option =>
                getArgumentList()
                        .then(list => option.setName('input')
                                                .setDescription('The input to echo back.') 
                                                .setChoices(...list) )),           
    async execute(interaction){ 
        console.log('Testing')
    }
}

Here I get this error:在这里我得到这个错误:

ExpectedValidationError: Expected
    at InstanceValidator.handle 
    ...
    at Module._load (node:internal/modules/cjs/loader:922:12) {
  validator: 's.instance(V)',
  given: Promise { <pending> },
  expected: [Function: SlashCommandStringOption]
}

Node.js v18.13.0

Would there be a good way of doing this?会有这样做的好方法吗?

The .then() function always returns a promise, so you can't set it as the return value of .addStringOption() . .then .then() function 始终返回 promise,因此您不能将其设置为.addStringOption()的返回值。 Using async/await would make this a lot cleaner and easier.使用 async/await 会让这一切变得更清晰、更容易。

data: new SlashCommandBuilder()
            .setName('test3')
            .setDescription('Test command for commands with options.')
            .addStringOption(async option => {
               let list = await getArgumentList()
               return option.setName('input')
                   .setDescription('The input to echo back.')
                   .setChoices(...list)
            })

Refactor your command system to have data be a function, and in your slash command deploy script (or wherever you used the data property before) await it, so you can then change data to be this:重构您的命令系统,使数据成为 function,并在您的斜杠命令部署脚本(或您之前使用数据属性的任何地方)等待它,这样您就可以将数据更改为:

module.exports = {
    data: async () => {
        // The list is fetched here (where we can use promises and async-await) before the SlashCommandBuilder gets made.
        const list = await getArgumentList();
        return new SlashCommandBuilder()
            .setName("test3")
            .setDescription("Test command for commands with options.")
            .addStringOption((option) =>
                option
                    .setName("input")
                    .setDescription("The input to echo back.")
                    .setChoices(...list)
            );
    };
}

Example slash command deploy script:示例斜杠命令部署脚本:

const commands = await Promise.all(
    client.commandRegistry.map((command) => (await command.data()).toJSON())
);

You can also pass a default SlashCommandBuilder to the data function now if you want:如果需要,您现在还可以将默认的 SlashCommandBuilder 传递给数据 function:

module.exports = {
    data: async (b) => {
        // The list is fetched here (where we can use promises and async-await) before the SlashCommandBuilder gets made.
        const list = await getArgumentList();
        // no .setName() required anymore! Deploy script set it for us.
        return b
            .setDescription("Test command for commands with options.")
            .addStringOption((option) =>
                option
                    .setName("input")
                    .setDescription("The input to echo back.")
                    .setChoices(...list)
            );
    };
}
const commands = await Promise.all(
    client.commandRegistry.map((command, key) =>
        (await command.data(new SlashCommandBuilder().setName(key))).toJSON()
    )
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM