Discord.js使用.addChoices()方法动态地向斜杠命令添加选项。

huangapple go评论118阅读模式
英文:

Discord.js dynamically add options to slash command with .addChoices()

问题

我有一个需要用户提供3个选择的斜杠命令:team1、team2和游戏数量。我正在将它们作为命令的参数添加,代码如下:

  1. data: new SlashCommandBuilder()
  2. .setName('addgame')
  3. .setDescription('Sets up a game for placing bets.')
  4. .addStringOption(option =>
  5. option.setName('team1')
  6. .setDescription('Team 1')
  7. .setRequired(true)
  8. .addChoices(
  9. { name: 'Bilibili Gaming', value: 'Bilibili Gaming'},
  10. { name: 'JDG Gaming', value: 'JDG Gaming'},
  11. { name: 'Gen.G', value: 'Gen.G'},
  12. { name: 'T1', value: 'T1'},
  13. { name: 'Cloud9', value: 'Cloud9'},
  14. { name: 'Golden Guardians', value: 'Golden Guardians'},
  15. { name: 'G2 Esports', value: 'G2 Esports'},
  16. ))
  17. .addStringOption(option =>
  18. option.setName('team2')
  19. .setDescription('Team 2')
  20. .setRequired(true)
  21. .addChoices(
  22. { name: 'Bilibili Gaming', value: 'Bilibili Gaming'},
  23. { name: 'JDG Gaming', value: 'JDG Gaming'},
  24. { name: 'Gen.G', value: 'Gen.G'},
  25. { name: 'T1', value: 'T1'},
  26. { name: 'Cloud9', value: 'Cloud9'},
  27. { name: 'Golden Guardians', value: 'Golden Guardians'},
  28. { name: 'G2 Esports', value: 'G2 Esports'},
  29. ))
  30. .addStringOption(option =>
  31. option.setName('series')
  32. .setDescription('Number of games')
  33. .setRequired(true)
  34. .addChoices(
  35. { name: '1', value: '1'},
  36. { name: '3', value: '3'},
  37. { name: '5', value: '5'},
  38. )),
  39. async execute(interaction) {
  40. // Set up team information
  41. const teamList = await getTeams();
  42. const team1 = interaction.options.getString('team1');
  43. const team2 = interaction.options.getString('team2');
  44. ...

这里的.addChoices()属性不仅多余且难以维护,而且我稍后在斜杠命令中使用getTeams()函数从数据库中获取相同的值。我想知道如何调用getTeams异步函数并使用结果填充addChoices()

我可以这样做:

  1. const teamList = await getTeams();
  2. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  3. ...
  4. .addChoices(...choices)

然而,由于getTeams()是一个异步函数,我不能在async execute(interaction)方法之外使用await

我想做的事情是否不可能?如果我必须重新构造斜杠命令来实现这一点,那会是什么样子?任何建议都将不胜感激。

编辑:
我甚至尝试在我的index.js中做这样的事情:

  1. async function fetchTeamList() {
  2. const teamList = await getTeams();
  3. const teams = teamList.map(team => ({ name: team.Name, value: team.Name }));
  4. return teams;
  5. }
  6. ...
  7. fetchTeamList().then(teams => {
  8. console.log(teams);
  9. module.exports.teams = teams;
  10. });

然后在我的斜杠命令文件中导入teams,但这也不起作用。我不确定我想做的事情是否可能...
使用Node.js v18.17.0和discord.js: ^14.11.0

编辑:
我也尝试过这样做:

  1. data: new SlashCommandBuilder()
  2. .setName('addgame')
  3. .setDescription('Sets up a game for placing bets.')
  4. .addStringOption(async option =>{
  5. const teamList = await getTeams();
  6. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  7. return option
  8. .setName('team1')
  9. .setDescription('Team 1')
  10. .setRequired(true)
  11. .addChoices(...choices)
  12. })

这是根据一个答案中的建议,但这会引发与@sapphire/shapeshif包相关的错误。我认为这不起作用是因为我在addStringOption中使用了一个异步回调来动态获取团队选择,但后续的选项是同步添加的...这可能会引发问题。

英文:

I have a slash command that requires 3 choices from the user: team1, team2, and how many games. I'm adding those as parameters for the command like this:

  1. data: new SlashCommandBuilder()
  2. .setName('addgame')
  3. .setDescription('Sets up a game for placing bets.')
  4. .addStringOption(option =>
  5. option.setName('team1')
  6. .setDescription('Team 1')
  7. .setRequired(true)
  8. .addChoices(
  9. { name: 'Bilibili Gaming', value: 'Bilibili Gaming'},
  10. { name: 'JDG Gaming', value: 'JDG Gaming'},
  11. { name: 'Gen.G', value: 'Gen.G'},
  12. { name: 'T1', value: 'T1'},
  13. { name: 'Cloud9', value: 'Cloud9'},
  14. { name: 'Golden Guardians', value: 'Golden Guardians'},
  15. { name: 'G2 Esports', value: 'G2 Esports'},
  16. ))
  17. .addStringOption(option =>
  18. option.setName('team2')
  19. .setDescription('Team 2')
  20. .setRequired(true)
  21. .addChoices(
  22. { name: 'Bilibili Gaming', value: 'Bilibili Gaming'},
  23. { name: 'JDG Gaming', value: 'JDG Gaming'},
  24. { name: 'Gen.G', value: 'Gen.G'},
  25. { name: 'T1', value: 'T1'},
  26. { name: 'Cloud9', value: 'Cloud9'},
  27. { name: 'Golden Guardians', value: 'Golden Guardians'},
  28. { name: 'G2 Esports', value: 'G2 Esports'},
  29. ))
  30. .addStringOption(option =>
  31. option.setName('series')
  32. .setDescription('Number of games')
  33. .setRequired(true)
  34. .addChoices(
  35. { name: '1', value: '1'},
  36. { name: '3', value: '3'},
  37. { name: '5', value: '5'},
  38. )),
  39. async execute(interaction) {
  40. // Set up team information
  41. const teamList = await getTeams();
  42. const team1 = interaction.options.getString('team1');
  43. const team2 = interaction.options.getString('team2');
  44. ...

Not only are the .addChoices() properties redundant here and harder to maintain, but I actually get those same values from the database later in the slash command using a getTeams() function. I'm wondering how I could call that getTeams async function and use the result to populate addChoices()?

I could do something like this:

  1. const teamList = await getTeams();
  2. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  3. ...
  4. .addChoices(...choices)

However, because getTeams() is an async function I can't use await outside of the async execute(interaction) method.

Is what I'm wanting to do not possible? If I had to restructure the slash command to achieve this, what would that look like? Any advice appreciated.

EDIT:
I even tried doing something like this in my index.js:

  1. async function fetchTeamList() {
  2. const teamList = await getTeams();
  3. const teams = teamList.map(team => ({ name: team.Name, value: team.Name }));
  4. return teams;
  5. }
  6. ...
  7. fetchTeamList().then(teams => {
  8. console.log(teams);
  9. module.exports.teams = teams;
  10. });

And then importing teams in my slash command file but that didn't work either. I'm not sure that what I'm trying to do is possible...
Using Node.js v18.17.0 and discord.js: ^14.11.0

EDIT:

I have tried this as well:

  1. data: new SlashCommandBuilder()
  2. .setName('addgame')
  3. .setDescription('Sets up a game for placing bets.')
  4. .addStringOption(async option =>{
  5. const teamList = await getTeams();
  6. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  7. return option
  8. .setName('team1')
  9. .setDescription('Team 1')
  10. .setRequired(true)
  11. .addChoices(...choices)
  12. })

As was recommended in an answer but this throws an error dealing with the ```@sapphire/shapeshifpackage. I believe this isn't working because I'm using an asynchronous callback foraddStringOption```` to fetch the team choices dynamically but the subsequent options are added synchronously... which might cause a problem?

答案1

得分: 1

你可以将addStringOption函数设置为异步函数,并在函数内部获取团队信息,代码如下所示:

  1. .addStringOption(async option => {
  2. const teamList = await getTeams();
  3. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  4. return option
  5. .setName('team1')
  6. .setDescription('Team 1')
  7. .setRequired(true)
  8. .addChoices(...choices)
  9. })
英文:

You can make the addStringOpton function async and get the teams inside the function like this

  1. .addStringOption(async option => {
  2. const teamList = await getTeams();
  3. const choices = teamList.map(team => ({ name: team.name, value: team.value }));
  4. return option
  5. .setName('team1')
  6. .setDescription('Team 1')
  7. .setRequired(true)
  8. .addChoices(...choices)
  9. }),
  10. </details>

huangapple
  • 本文由 发表于 2023年8月9日 09:19:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76863994.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定