💬 Command CustomId Codec
The CommandCustomIdCodec
is the object responsible for encoding and decoding command custom ids. That is, custom ids
that refer to commands. With this object you can easily create components that will trigger commands when
they are used. It's stored by a CommandManager
, and you can get it via CommandManager#getCustomIdCodec()
.
It's advised that you only use this API for simple user actions. If you're looking for something more complex, you should use a dedicated handler or the 👤 Sessions API.
✨ Examples
🚧 Usage examples
These are short examples on how the API is used overall. For "real world" examples, read the next section.
- Referring to a command
- Referring with extra data
// Get the command instance
const myCommand = commandManager.getRepository().locateByTree(MyCommandClass);
if (!myCommand) throw new Error('Command not found');
// Get the customId
const customIdCodec = commandManager.getCustomIdCodec();
const customId = customIdCodec.serializeToCustomId(myCommand);
Building your custom ID:
// Get the command instance
const myCommand = commandManager.getRepository().locateByTree(MyCommandClass);
if (!myCommand) throw new Error('Command not found');
// Get the customId builder
const customIdCodec = commandManager.getCustomIdCodec();
const customIdBuilder = customIdCodec.createCustomIdBuilder(myCommand);
// Append extra data and build
const customId = customIdBuilder.setAt(0, 'Extra data').build();
Receiving and extracting the extra data from an Interaction
:
// Build a StringIterator to extract the extra data
const iterator = customIdCodec.createIteratorFromCustomId(interaction.customId);
// Get at index 0, true to throw an error if not present
const extraData = iterator.getAt(0, true);
bot.getLogger().log(extraData); // 'Extra data'
✅ Implementation examples
These are "real world" examples on how the API can be used. For "short", concrete examples, read the last section.
- Referring to a command
- Referring with extra data
// Assume this command is registered
class PingCommand extends AbstractStandaloneCommand {
public async handleInteraction(interaction: ComponentCommandInteraction) {
await interaction.reply('Pong!');
}
}
class MyReferralCommand extends AbstractStandaloneCommand {
public async execute(
interaction: ChatInputCommandInteraction,
metadata: CommandExecutionMeta,
) {
const bot = metadata.getBot();
const commandManager = bot.getCommandManager();
// Get the command instance
const pingCommand = commandManager.getRepository().locateByTree(PingCommand);
if (!pingCommand) throw new Error('Ping command not found');
// Get the customId
const customIdCodec = bot.getCommandManager().getCustomIdCodec();
const customId = customIdCodec.serializeToCustomId(pingCommand);
// Create your component
const button = new ButtonBuilder()
// When this button is clicked, it will trigger PingCommand#handleInteraction()
.setCustomId(customId)
.setLabel('Click to check your ping!')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(button);
await interaction.reply({ components: [row] });
}
}
const UserIdIndex = 0;
class AdminListCommand extends AbstractStandaloneCommand {
public async execute(
interaction: ChatInputCommandInteraction,
metadata: CommandExecutionMeta,
) {
const bot = metadata.getBot();
const commandManager = bot.getCommandManager();
// Get the command instance
const userInfoCommand = commandManager.getRepository().locateByTree(UserInfoCommand);
if (!userInfoCommand) throw new Error('User info command not found');
// Get the customId builder
const customIdCodec = bot.getCommandManager().getCustomIdCodec();
const customIdBuilder = customIdCodec.createCustomIdBuilder(userInfoCommand);
// Create customIds by cloning the builder, adding the ID and building
const adminACustomId = customIdBuilder
.clone()
.setAt(UserIdIndex, '1234567890')
.build();
const adminBCustomId = customIdBuilder
.clone()
.setAt(UserIdIndex, '0123456789')
.build();
// Create the buttons
const adminAButton = new ButtonBuilder()
.setCustomId(adminACustomId)
.setLabel('Admin A')
.setStyle(ButtonStyle.Primary);
const adminBButton = new ButtonBuilder()
.setCustomId(adminBCustomId)
.setLabel('Admin B')
.setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(adminAButton, adminBButton);
await interaction.reply({ components: [row] });
}
}
class UserInfoCommand extends AbstractStandaloneCommand {
public async handleInteraction(
interaction: ComponentCommandInteraction,
metadata: CommandExecutionMeta,
) {
const bot = metadata.getBot();
const customIdCodec = bot.getCommandManager().getCustomIdCodec();
// Build a StringIterator to extract the extra data
const iterator = customIdCodec.createIteratorFromCustomId(interaction.customId);
// Get at UserIdIndex index, true to throw an error if not present
const userId = iterator.getAt(UserIdIndex, true);
const user = await bot.client.users.fetch(userId);
await interaction.reply(`User: ${user.tag}`);
}
}
👷 Creation
You can create a command custom ID codec by either:
- Extending
DefaultCommandCustomIdCodec
from@framework
(recommended). - Implementing the
CommandCustomIdCodec
interface from@core
.
- Extending DefaultCommandCustomIdCodec
- Implementing CommandCustomIdCodec
class MyCommandCustomIdCodec extends DefaultCommandCustomIdCodec {
// ...
}
const myCodec = new MyCommandCustomIdCodec();
const myBot = Bot.create((bot) => ({
commands: DefaultCommandManager.create(bot, client, clientBus, { customIdCodec: myCodec }),
}));
class MyCommandCustomIdCodec implements CommandCustomIdCodec {
// ...
}
const myCodec = new MyCommandCustomIdCodec();
const myBot = Bot.create((bot) => ({
commands: DefaultCommandManager.create(bot, client, clientBus, { customIdCodec: myCodec }),
}));