Skip to content

Commands ​

The ZombieClient framework makes creating robust commands incredibly easy. It handles automatic deployment to Discord API, intelligent diffing (to avoid rate limits), parameter autocomplete, and execution.

Slash Commands ​

A standard Slash Command requires exporting an object that matches the SlashCommand interface.

typescript
import { MessageFlags } from 'discord.js';
import { ChatInputCommandBuilder } from '@discordjs/builders';
import type { SlashCommand } from '@thezombiepl/zombieclient/interfaces';

const command = {
    data: new ChatInputCommandBuilder()
        .setName('ping')
        .setDescription('Sprawdź opóźnienie bota.'),
        
    // (Optional) Deploy only to specific guilds
    guild: ['1004821657455706153'],
    
    // (Optional) Developer-only command (only client.ownerId can use it)
    dev: true,
    
    // (Optional) Cooldown in seconds for this specific command
    cooldown: 3,

    execute: async (client, interaction) => {
        await interaction.reply({
            content: `Pong! ${client.ws.ping}ms`,
            flags: MessageFlags.Ephemeral,
        });
    },
} satisfies SlashCommand;

export default command;

Autocomplete ​

ZombieClient automatically routes autocomplete interactions to the matching command file if you provide the autocomplete function.

typescript
import { ChatInputCommandBuilder } from '@discordjs/builders';
import type { SlashCommand } from '@thezombiepl/zombieclient/interfaces';

const command = {
    data: new ChatInputCommandBuilder()
        .setName('select')
        .setDescription('Wybierz coś')
        .addStringOption((option) =>
            option
                .setName('choice')
                .setDescription('Wybierz jedną z opcji')
                .setAutocomplete(true) // Required for autocomplete
                .setRequired(true)
        ),
        
    execute: async (client, interaction) => {
        const choice = interaction.options.getString('choice');
        await interaction.reply(`Wybrano: ${choice}`);
    },
    
    // Autocomplete handler
    autocomplete: async (client, interaction) => {
        const focusedValue = interaction.options.getFocused();
        const options = ['Opcja A', 'Opcja B', 'Opcja C'];

        const filtered = options.filter((option) =>
            option.toLowerCase().includes(focusedValue.value.toLowerCase()),
        );

        await interaction.respond(filtered.map((option) => ({ name: option, value: option })));
    },
} satisfies SlashCommand;

export default command;

Context Menu Commands ​

Context Menu commands (User Context or Message Context) follow a very similar structure, but use ContextMenuCommandBuilder and the ContextMenuCommand interface.

typescript
import { GuildMember, MessageFlags } from 'discord.js';
import { UserContextCommandBuilder, EmbedBuilder } from '@discordjs/builders';
import type { ContextMenuCommand } from '@thezombiepl/zombieclient/interfaces';

const command = {
  data: new UserContextCommandBuilder()
    .setName('avatar'), // Name shown in the user context menu
    
  execute: async (client, interaction) => {
    // Cast is safe since we know this is a user context command
    const targetMember = interaction.member as GuildMember;

    const embed = new EmbedBuilder()
      .setColor(client.colors.BOT_ORANGE)
      .setTitle(`Awatar użytkownika: ${targetMember.displayName}`)
      .setImage(targetMember.displayAvatarURL({ size: 1024 }))
      .setTimestamp();

    await interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral });
  },
} satisfies ContextMenuCommand;

export default command;

Wszelkie prawa zastrzeżone.