Interações
Entenda respostas, modais, autocomplete e o contexto normalizado usado em todos os fluxos interativos.
O ciclo de uma resposta#
Uma interação pode receber uma resposta inicial e depois ser editada ou acompanhada por mensagens adicionais.
| Método | Quando usar |
|---|---|
reply() | Primeira resposta imediata |
deferReply() | Reserva a resposta quando o trabalho demora |
editReply() | Finaliza ou atualiza a resposta reservada |
followUp() | Envia uma resposta adicional |
deleteReply() | Remove a resposta original |
Client.slash({ data: new SlashCommandBuilder() .setName('relatorio') .setDescription('Gera um relatório detalhado.'), execute: async interaction => { await interaction.deferReply({ flags: 64 }) const report = await generateReport(interaction.guildId) await interaction.editReply('Relatório pronto: ' + report.url) await interaction.followUp({ content: 'A exportação expira em 24 horas.', flags: 64 }) }})Contexto normalizado#
O Core fornece uma superfície comum e mantém a interação original em interaction.interaction quando você precisa estreitar o tipo.
Identidade
user, member, guild, guildId, channel e channelId.
Resposta
reply, deferReply, editReply, followUp e estado da resposta.
Core
promptRequest, paginatorRequest, configuração e contexto isolado.
Discord.js
A propriedade interaction preserva a interação nativa completa.
Client.slash({ data: new SlashCommandBuilder() .setName('canal-suporte') .setDescription('Mostra o canal configurado.'), execute: async interaction => { const config = Client.appConfig() const supportChannel = Client.getAppChannels().support await interaction.reply({ content: 'Canal: ' + (supportChannel?.toString() ?? 'não configurado'), flags: 64 }) }})Abrindo um modal#
O comando constrói o modal; um módulo separado registra o handler para o mesmo customId.
import { ActionRowBuilder, ModalBuilder, SlashCommandBuilder, TextInputBuilder, TextInputStyle} from '@ninenity/core'import Client from '../../Shared/Settings/Client'Client.slash({ data: new SlashCommandBuilder() .setName('feedback') .setDescription('Abre o formulário de feedback.'), execute: async interaction => { const input = new TextInputBuilder() .setCustomId('message') .setLabel('Como podemos melhorar?') .setStyle(TextInputStyle.Paragraph) .setMinLength(10) .setMaxLength(1000) .setRequired(true) const modal = new ModalBuilder() .setCustomId('feedback-modal') .setTitle('Enviar feedback') .addComponents(new ActionRowBuilder<TextInputBuilder>().addComponents(input)) await interaction.interaction.showModal(modal) }})import Client from '../../Shared/Settings/Client'Client.modal({ customId: 'feedback-modal', execute: async interaction => { const text = interaction.fields.getTextInputValue('message') await saveFeedback({ authorId: interaction.user.id, guildId: interaction.guildId, text }) await interaction.reply({ content: 'Obrigado pelo feedback!', flags: 64 }) }})Autocomplete#
Declare a opção com autocomplete no comando e responda com até 25 sugestões.
Client.slash({ data: new SlashCommandBuilder() .setName('buscar') .setDescription('Busca um projeto.') .addStringOption(option => option .setName('projeto') .setDescription('Nome do projeto') .setAutocomplete(true) .setRequired(true)), autocomplete: async interaction => { const query = interaction.options.getFocused().toLowerCase() const choices = projects .filter(project => project.name.toLowerCase().includes(query)) .slice(0, 25) .map(project => ({ name: project.name, value: project.id })) await interaction.respond(choices) }, execute: async interaction => { const projectId = interaction.options.getString('projeto', true) await interaction.reply('Projeto escolhido: ' + projectId) }})Prompts e paginações registrados#
Depois de registrar uma definição uma vez, qualquer slash ou prefix pode iniciar uma instância isolada para o usuário.
Client.slash({ data: new SlashCommandBuilder() .setName('confirmar') .setDescription('Abre um prompt.'), execute: async interaction => { await interaction.promptRequest('delete-prompt', { ephemeral: true }) }})Client.prefix({ data: new PrefixCommandBuilder().setName('confirmar'), execute: async interaction => { await interaction.promptRequest('delete-prompt', { ephemeral: true }) }})Client.slash({ data: new SlashCommandBuilder() .setName('catalogo') .setDescription('Abre o catálogo paginado.'), execute: async interaction => { await interaction.paginatorRequest('catalog-pages', { ephemeral: true, pageIndex: 0 }) }})A criação das definições fica em Discord/Interactions. Consulte as páginas Prompts e Paginação para montar templates, callbacks e controles personalizados.