I am building a discord bot that is going to be used on multiple guilds (a.k.a servers). The bot has a command called 'send' that has a set of choices inside an option:
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('send')
.setDescription('Do stuff')
.addStringOption(option =>
option.setName('choices') // setting the choices
.setDescription('users will chose one of the options bellow')
.setRequired(true)
.addChoice('choice1', 'potato')
.addChoice('choice2', 'tomato')
.setRequired(true))
async execute(interaction) {
//do stuff
}; }};
All of the other application commands are global, but this specific command must have custom choices for each different guild. All this choices are stored on a mongo db, with the respective guild id.
The DB querying is ok to do, but I'm struggling with finding a solution to 'deploy' automatically this commands with different choices for each server. This is my goal with this question, to find a solution to deploy the commands with different choices for each guild.
If needed, I can provide my deploy-commands.js code ( it follows this tutorial ) and also more detail.
Appreciate the help
As mentioned on the comments, using choices with data from the DB is not possible. The workaround is to use the 'autocomplete' option.
To do that, inside the builder, we add a .setAutocomplete(true)
. Now, we need to handle the autocomplete interaction, and fill it with the values that we want form the Database.
It is important to 'filter' the type of interaction that we are handling. Using if statements, we need to verify if the interaction is an autocomplete or a command. Below is the resulting code:
const { SlashCommandBuilder } = require('@discordjs/builders');
const mongo = require('../structures/mongo')
module.exports = {
data: new SlashCommandBuilder()
.setName('send')
.setDescription('items list')
.addStringOption((option) =>
option
.setName('items')
.setDescription('Select your item from the list')
.setRequired(true)
.setAutocomplete(true)),
async execute(interaction) {
const guildID = interaction.member.guild.id;
//query DB for the options
let guild = await mongo.getGuild(guildID)
//loop through guild token and set to autocomplete
for (let i = 0; i < guild.guild_tokens.length; i++) {
choices.push({
name: `${guild.guild_tokens[i].name}`,
value: `${i}`,
})
tokens.push(`${guild.guild_tokens[i].name}`)
}
if (interaction.isAutocomplete()) {
interaction.respond(choices)
.catch(console.error);
}
// Must handle interactions (command ones) inside the if statement
if (interaction.isCommand()) {
// do stuff
}
};
On a side note, I had an issue with the interactions at first, because on my 'interactionCreate' file I was returning if the interaction was not a command. It's also important to change that file to not return if the interaction is an 'autocomplete' type:
module.exports = { name: "interactionCreate", async execute(interaction) {
if (!(interaction.isCommand() || (interaction.type == 'APPLICATION_COMMAND_AUTOCOMPLETE'))) {
console.log('fuck')
return;
}
const command = interaction.client.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction)
} catch (err) {
if (err) console.error(err);
}
}
}