Ir para o conteúdo principal

Slash Commands

Comandos de Golpe são a nova e emocionante maneira de construir e interagir com bots no Discord. Com Slash Commands, tudo que você tem que fazer é digitar / e você estará pronto para utilizar seu bot favorito. Você pode ver facilmente todos os comandos que um bot tem, e a validação e a manipulação de erros ajudam você a obter o comando corretamente na primeira vez.

Slash Commands

Comandos Globais

tip

Comandos globais são armazenados em cache por uma hora. Novos comandos globais vão se espalhar lentamente em todas as guildas e só será garantido que serão atualizados após uma hora. Comandos de servidor atualizam instantaneamente. Com isso, recomendamos que você use comandos baseados a servidores durante o desenvolvimento e publique eles como comandos globais quando eles estiverem prontos para o uso do público.

Leia mais sobre configuração modo dev

Crie o arquivo app.commands.ts e adicione um método com o decorador SlashCommand.

app.commands.ts
import { Injectable } from '@nestjs/common';
import { Context, SlashCommand, SlashCommandContext } from 'necord';

@Injectable()
export class AppCommands {
@SlashCommand({
name: 'ping',
description: 'Comando Ping-Pong'
})
public async onPing(@Context() [interaction]: SlashCommandContext) {
return interaction.reply({ content: 'Pong!' });
}
}

Comandos de Servidor

Se você quer ter comandos específicos de um servidor, use a propriedade guilds no decorador SlashCommand

app.commands.ts
import { Injectable } from '@nestjs/common';
import { Context, SlashCommand, SlashCommandContext } from 'necord';

@Injectable()
export class AppCommands {
@SlashCommand({
name: 'ping',
description: 'Comando Ping-Pong',
guilds: [process.env.DEV_GUILD]
})
public async onPing(@Context() [interaction]: SlashCommandContext) {
return interaction.reply({ content: 'Pong!' });
}
}

Você pode usar decoradores em classes e métodos.

Opções

Use o decorador de opção para definir um parâmetro em um slash command, vamos criar a classe LengthDto:

length.dto.ts
import { StringOption } from 'necord';

export class TextDto {
@StringOption({
name: 'text',
description: 'Seu texto',
required: true
})
text: string;
}

Tem apenas uma propriedade básica. Então, nós podemos usar o recém-criado DTO dentro do AppCommands:

app.commands.ts
import { Injectable } from '@nestjs/common';
import { Context, SlashCommand, Options, SlashCommandContext } from 'necord';
import { TextDto } from './length.dto';

@Injectable()
export class AppCommands {
@SlashCommand({
name: 'tamanho',
description: 'Consiga o tamanho de um texto'
})
public async onLength(@Context() [interaction]: SlashCommandContext, @Options() { text }: TextDto) {
return interaction.reply({content: `Tamanho do seu texto ${text.length}`});
}
}

Lista de todos os decoradores de opção incorporados:

DecoradorTipoDescrição
StringOptionstringUma opção de texto
NumberOptionnumberUma opção numérica
IntegerOptionnumberUma opção de inteiro
BooleanOptionbooleanUma opção booleana
UserOptionUserUma opção de usuário
MemberOptionGuildMemberUma opção de membro
ChannelOptionGuildChannelUma opção de canal
RoleOptionRoleUma opção de cargo
MentionableOptionGuildMember | Role | UserUma opção mencionável
AttachmentOptionAttachmentUma opção de anexo

Autocompletar

Para adicionar autocompletar ao seu slash command você precisará de um interceptor primeiro. Esta classe interceptará todas as solicitações do usuário depois de digitar o campo de opção de preenchimento automático

anime.interceptor.ts
import { Injectable } from '@nestjs/common';
import { AutocompleteInteraction } from 'discord.js';
import { AutocompleteInterceptor } from 'necord';

@Injectable()
export class AnimeAutocompleteInterceptor extends AutocompleteInterceptor {
public transformOptions(interaction: AutocompleteInteraction) {
const focused = interaction.options.getFocused(true);
let choices: string[];

if (focused.name === 'anime') {
choices = ['Hunter x Hunter', 'Naruto', 'One Piece'];
}

return interaction.respond(
choices
.filter(choice => choice.startsWith(focused.value.toString()))
.map(choice => ({ name: choice, value: choice }))
);
}
}

Você terá que adicionar autoComplete: true para sua classe de opções:

anime.dto.ts
importar { StringOption } de 'necord';

export class AnimeDto {
@StringOption({
name: 'anime',
description: 'O anime para procurar',
autocomplete: true,
required: true
})
anime: string;
}

E por último, mas não menos importante, aplicar o interceptor ao seu slash command

anime-commands.service.ts
import { Injectable, UseInterceptors } from '@nestjs/common';
import { Context, SlashCommand, Options, SlashCommandContext } from 'necord';
import { AnimeDto } from '/anime.dto';
import { AnimeAutocompleteInterceptor } from './anime.interceptor';

@Injectable()
export class AnimeCommands {
@UseInterceptors(AnimeAutocompleteInterceptor)
@SlashCommand({
name: 'anime',
description: 'Procura informações sobre um anime'
})
public async onSearch(@Context() [interaction]: SlashCommandContext, @Options() { anime }: AnimeDto) {
return interaction.reply({content: `Eu encontrei o anime ${anime}`});
}
}

Grupos

DICA

Para esses desenvolvedores que desejam fazer grupos de comandos mais organizados e complexos, procure apenas subgrupos e grupos.

Use decoradores SlashGroup em nível de classe (Grupo) e nível método (Subgrupo):

utils-commands.service.ts
import { createCommandGroupDecorator, Subcommand } from 'necord';

export const UtilsCommandDecorator = createCommandGroupDecorator({
name: 'utilidades',
description: 'Grupo de utilidades',
});

@UtilsCommandDecorator()
export class UtilsCommands {
@Subcommand({
name: 'ping',
description: 'Comando Ping-pong'
})
public async onPing(...) {
...
}
}

@UtilsCommandDecorator({
name: 'texto',
descriptionn: 'Comandos de utilidade de texto'
})
export class UtilsStringCommands {
@Subcommand({
name: 'tamanho',
description: 'Comando de tamanho de texto'
})
public async onLength(...) {
...
}
}


Após os comandos serem registrados, o bot irá processar os comandos /utilidades ping e /utilidades texto tamanho, como aqui:

Comandos

Você pode ver um exemplo funcional aqui.