import * as discord_js from 'discord.js'; import { SlashCommandBuilder, ChatInputCommandInteraction, Client, Message, ButtonBuilder, SelectMenuBuilder, StringSelectMenuBuilder, UserSelectMenuBuilder, RoleSelectMenuBuilder, ChannelSelectMenuBuilder, MentionableSelectMenuBuilder, APIMessageComponent, MessageFlags, TextInputStyle, ModalBuilder, MessageComponentInteraction, ButtonInteraction, REST, GuildMember, ShardingManager } from 'discord.js'; /** * Features that can be enabled in createClient to automatically configure intents */ type Features = Array<'commands' | 'messages' | 'members' | 'reactions' | 'voice' | 'v2' | 'diagnostics'>; /** * Minimal logger interface that djs-helper-kit expects */ interface Logger { debug(message: string, ...args: unknown[]): void; info(message: string, ...args: unknown[]): void; warn(message: string, ...args: unknown[]): void; error(message: string, ...args: unknown[]): void; } /** * Context passed to command handlers */ interface CommandContext { client: Client; logger: Logger; } /** * Command definition structure for djs-helper-kit */ interface CommandDefinition { /** The slash command builder from discord.js */ data: SlashCommandBuilder; /** The command handler function */ run: (interaction: ChatInputCommandInteraction, ctx: CommandContext) => Promise; /** Optional guard function that runs before the command */ guard?: (interaction: ChatInputCommandInteraction, ctx: CommandContext) => Promise; } /** * Prefix command definition structure */ interface PrefixCommandDefinition { /** Command name/trigger */ name: string; /** Command aliases */ aliases?: string[]; /** Command description */ description?: string; /** The command handler function */ run: (message: Message, args: string[], ctx: CommandContext) => Promise; /** Optional guard function that runs before the command */ guard?: (message: Message, args: string[], ctx: CommandContext) => Promise; /** Whether this command should be hidden from help */ hidden?: boolean; } /** * Configuration options for createClient */ interface CreateClientOptions { /** Discord bot token (optional, defaults to process.env.DISCORD_TOKEN) */ token?: string; /** Features to enable - automatically configures intents */ features?: Features; /** Additional intents to add beyond what features provide */ additionalIntents?: number[]; /** Discord.js partials to enable */ partials?: discord_js.Partials[]; /** Whether to install default error middleware */ handleErrors?: boolean; /** Logger instance to use */ logger?: Logger; } /** * Cache adapter interface for pluggable caching */ interface CacheAdapter { get(key: string): Promise; set(key: string, value: T, ttlSeconds?: number): Promise; del(key: string): Promise; } interface AutoShardOptions { totalShards?: number | 'auto'; respawn?: boolean; spawnTimeout?: number; logger?: Logger; } type Dict = Record>; /** * Creates a Discord.js client with automatic intent configuration based on features. * Reduces foot-guns by automatically setting up the right intents for common use cases. * * @param options - Configuration options for the client * @returns Configured Discord.js Client instance * * @example * ```typescript * import { createClient } from 'djs-helper-kit'; * * const client = createClient({ * features: ['commands', 'members', 'v2', 'diagnostics'] * }); * ``` * * @example * ```javascript * const { createClient } = require('djs-helper-kit'); * const client = createClient({ features: ['commands', 'v2'] }); * ``` */ declare function createClient(options?: CreateClientOptions): Client; /** * Runs comprehensive diagnostics on a Discord client to identify common issues. * Checks intents, permissions, latency, and configuration problems. * * @param client - The Discord.js client to diagnose * * @example * ```typescript * import { createClient, diagnose } from 'djs-helper-kit'; * * const client = createClient({ features: ['commands', 'diagnostics'] }); * await diagnose(client); // Prints actionable health checks * await client.login(process.env.DISCORD_TOKEN); * ``` * * @example * ```javascript * const { createClient, diagnose } = require('djs-helper-kit'); * const client = createClient({ features: ['commands'] }); * diagnose(client).then(() => client.login(process.env.DISCORD_TOKEN)); * ``` */ declare function diagnose(client: Client): Promise; /** * Options for deploying slash commands */ interface DeployOptions { /** Deployment scope - guild or global */ scope?: 'guild' | 'global'; /** Guild ID (required for guild scope) */ guildId?: string; /** Dry run mode - shows what would be deployed without applying changes */ dryRun?: boolean; /** Ask for confirmation before destructive changes */ confirm?: boolean; /** Logger instance for output */ logger?: Logger; } /** * Loads command definitions from a directory or array. * Automatically imports TypeScript/JavaScript files and extracts command definitions. * * @param dirOrArray - Directory path to scan or array of command definitions * @returns Array of loaded command definitions * * @example * ```typescript * import { loadCommands } from 'djs-helper-kit'; * * // Load from directory * const commands = loadCommands('./commands'); * * // Load from array * const commands = loadCommands([ * { * data: new SlashCommandBuilder().setName('ping').setDescription('Ping command'), * run: async (interaction) => interaction.reply('Pong!') * } * ]); * ``` * * @example * ```javascript * const { loadCommands } = require('djs-helper-kit'); * const commands = loadCommands('./commands'); * ``` */ declare function loadCommands(dirOrArray: string | CommandDefinition[]): CommandDefinition[]; /** * Loads commands from a directory asynchronously. * Scans for .js, .ts, .mjs files and imports them as command modules. * * @param directory - Directory path to scan * @param logger - Optional logger for debug output * @returns Promise resolving to array of command definitions * * @example * ```typescript * import { loadCommandsAsync } from 'djs-helper-kit'; * * const commands = await loadCommandsAsync('./commands'); * ``` */ declare function loadCommandsAsync(directory: string, logger?: Logger): Promise; /** * Deploys slash commands to Discord with intelligent diffing. * Shows what will change before applying and handles both guild and global deployment. * * @param client - Discord.js client instance * @param commands - Array of command definitions to deploy * @param options - Deployment options * * @example * ```typescript * import { deploy, loadCommands } from 'djs-helper-kit'; * * const commands = loadCommands('./commands'); * await deploy(client, commands, { * scope: process.env.NODE_ENV === 'production' ? 'global' : 'guild', * guildId: process.env.DEV_GUILD_ID, * confirm: true, * }); * ``` * * @example * ```javascript * const { deploy, loadCommands } = require('djs-helper-kit'); * * const commands = loadCommands([myCommand]); * await deploy(client, commands, { scope: 'guild', guildId: '123456789' }); * ``` */ declare function deploy(client: Client, commands: CommandDefinition[], options?: DeployOptions): Promise; /** * Creates a simple command handler that can be attached to the interactionCreate event. * Handles command lookup, guard checking, and error handling. * * @param commands - Array of command definitions * @param logger - Optional logger instance * @returns Event handler function * * @example * ```typescript * import { createCommandHandler } from 'djs-helper-kit'; * * const commands = loadCommands('./commands'); * const handler = createCommandHandler(commands); * * client.on('interactionCreate', handler); * ``` */ declare function createCommandHandler(commands: CommandDefinition[], logger?: Logger): (interaction: ChatInputCommandInteraction) => Promise; /** * Creates a prefix command handler for message events. * Handles command parsing, guard checking, and error handling. * * @param prefixCommands - Array of prefix command definitions * @param prefix - Command prefix (default: '!') * @param logger - Optional logger instance * @returns Event handler function * * @example * ```typescript * import { createPrefixCommandHandler } from 'djs-helper-kit'; * * const prefixCommands = [ * { * name: 'ping', * description: 'Ping command', * run: async (message, args, ctx) => { * await message.reply('Pong!'); * } * } * ]; * * const handler = createPrefixCommandHandler(prefixCommands, '!'); * client.on('messageCreate', handler); * ``` */ declare function createPrefixCommandHandler(prefixCommands: PrefixCommandDefinition[], prefix?: string, logger?: Logger): (message: Message) => Promise; type Markdownish = string; /** * Simple message builder that mimics v1 message creation * but uses Components v2 under the hood * * @example * ```typescript * const message = msg() * .title('Welcome!') * .text('This is a simple message with **markdown** support.') * .separator() * .field('Status', 'Online', true) * .buttons(btn.primary('action', 'Click me')) * .build(); * * await interaction.reply(message); * ``` */ interface SimpleMessage { /** * Add text content with markdown support * @param content - The text content to add * @returns The message builder for chaining */ text(content: string): this; /** * Add a title (bold text) * @param text - The title text * @returns The message builder for chaining */ title(text: string): this; /** * Add a subtitle (italic text) * @param text - The subtitle text * @returns The message builder for chaining */ subtitle(text: string): this; /** * Add a separator line * @returns The message builder for chaining */ separator(): this; /** * Add a small separator * @returns The message builder for chaining */ smallSeparator(): this; /** * Add an image (as text with URL) * @param url - The image URL * @param alt - Optional alt text for the image * @returns The message builder for chaining */ image(url: string, alt?: string): this; /** * Add multiple images (as text with URLs) * @param urls - Array of image URLs * @returns The message builder for chaining */ images(urls: string[]): this; /** * Add a media gallery * @param urls - Array of media URLs * @returns The message builder for chaining */ mediaGallery(urls: string[]): this; /** * Add a thumbnail * @param url - The thumbnail URL * @param alt - Optional alt text for the thumbnail * @returns The message builder for chaining */ thumbnail(url: string, alt?: string): this; /** * Add a field (name: value format) * @param name - The field name * @param value - The field value * @param inline - Whether the field should be inline * @returns The message builder for chaining */ field(name: string, value: string, inline?: boolean): this; /** * Set the color theme (affects visual styling) * @param hex - The color hex value * @returns The message builder for chaining */ color(hex: number): this; /** * Add a footer * @param text - The footer text * @returns The message builder for chaining */ footer(text: string): this; /** * Add buttons * @param buttons - The buttons to add * @returns The message builder for chaining */ buttons(...buttons: ButtonBuilder[]): this; /** * Add a select menu * @param menu - The select menu to add * @returns The message builder for chaining */ select(menu: SelectMenuBuilder | StringSelectMenuBuilder | UserSelectMenuBuilder | RoleSelectMenuBuilder | ChannelSelectMenuBuilder | MentionableSelectMenuBuilder): this; /** * Build the final message for Discord.js * @returns The built message components and flags */ build(): { components: APIMessageComponent[]; flags: MessageFlags; }; /** * Build for interaction reply * @returns The built message components and flags */ reply(): { components: APIMessageComponent[]; flags: MessageFlags; }; } /** * Simple embed builder that mimics v1 embed creation * but uses Components v2 under the hood * * @example * ```typescript * const embed = embed() * .title('Server Information') * .description('Details about the server') * .color(0x5865f2) * .field('Members', '1000', true) * .field('Channels', '50', true) * .footer('Requested by user') * .buttons(btn.success('join', 'Join Server')) * .build(); * * await interaction.reply(embed); * ``` */ interface SimpleEmbed { /** * Set the title * @param text - The title text * @returns The embed builder for chaining */ title(text: string): this; /** * Set the description * @param text - The description text * @returns The embed builder for chaining */ description(text: string): this; /** * Set the color * @param hex - The color hex value * @returns The embed builder for chaining */ color(hex: number): this; /** * Add a field * @param name - The field name * @param value - The field value * @param inline - Whether the field should be inline * @returns The embed builder for chaining */ field(name: string, value: string, inline?: boolean): this; /** * Set thumbnail * @param url - The thumbnail URL * @returns The embed builder for chaining */ thumbnail(url: string): this; /** * Set main image * @param url - The image URL * @returns The embed builder for chaining */ image(url: string): this; /** * Set footer * @param text - The footer text * @returns The embed builder for chaining */ footer(text: string): this; /** * Set timestamp * @param date - The timestamp date (defaults to current time) * @returns The embed builder for chaining */ timestamp(date?: Date): this; /** * Add buttons * @param buttons - The buttons to add * @returns The embed builder for chaining */ buttons(...buttons: ButtonBuilder[]): this; /** * Add a select menu * @param menu - The select menu to add * @returns The embed builder for chaining */ select(menu: SelectMenuBuilder | StringSelectMenuBuilder | UserSelectMenuBuilder | RoleSelectMenuBuilder | ChannelSelectMenuBuilder | MentionableSelectMenuBuilder): this; /** * Build the final embed for Discord.js * @returns The built embed components and flags */ build(): { components: APIMessageComponent[]; flags: MessageFlags; }; } /** * Options for pagination helper */ interface PaginationOptions { /** Array of items to paginate */ items: unknown[]; /** Number of items per page */ itemsPerPage: number; /** Current page number (defaults to 1) */ currentPage?: number; /** Whether to show page information (defaults to true) */ showPageInfo?: boolean; /** Whether to show navigation buttons (defaults to true) */ showNavigation?: boolean; } /** * Form field configuration for modals */ interface FormField { /** Unique identifier for the field */ id: string; /** Display label for the field */ label: string; /** Optional placeholder text */ placeholder?: string; /** Whether the field is required (defaults to true) */ required?: boolean; /** Input style (short or paragraph) */ style?: TextInputStyle; /** Minimum length for the input */ minLength?: number; /** Maximum length for the input */ maxLength?: number; /** Default value for the field */ value?: string; } /** * Modal builder with enhanced features */ interface ModalBuilderV2 { /** * Create a simple modal with text inputs * @param id - Custom ID for the modal * @param title - Modal title * @param inputs - Array of form field configurations * @returns ModalBuilder instance */ create(id: string, title: string, inputs: FormField[]): ModalBuilder; /** * Create a contact form modal * @param id - Custom ID for the modal * @returns ModalBuilder instance with contact form fields */ contact(id: string): ModalBuilder; /** * Create a feedback form modal * @param id - Custom ID for the modal * @returns ModalBuilder instance with feedback form fields */ feedback(id: string): ModalBuilder; /** * Create a settings form modal * @param id - Custom ID for the modal * @param fields - Array of field names to generate inputs for * @returns ModalBuilder instance with settings form fields */ settings(id: string, fields: string[]): ModalBuilder; } /** * Create a simple message builder * * @example * ```typescript * const message = msg() * .title('Welcome!') * .text('This is a simple message.') * .buttons(btn.primary('click', 'Click me')) * .build(); * ``` * * @returns A new SimpleMessage instance */ declare function msg(): SimpleMessage; /** * Create a simple embed builder * * @example * ```typescript * const embed = embed() * .title('Server Info') * .description('Information about the server') * .color(0x5865f2) * .build(); * ``` * * @returns A new SimpleEmbed instance */ declare function embed(): SimpleEmbed; /** * Enhanced modal builder with predefined forms * * @example * ```typescript * // Contact form * const contactModal = modalV2.contact('contact_form'); * await interaction.showModal(contactModal); * * // Custom form * const customModal = modalV2.create('custom', 'Form', [ * { id: 'name', label: 'Name', required: true }, * { id: 'email', label: 'Email', required: true } * ]); * ``` */ declare const modalV2: ModalBuilderV2; /** * Create a paginated message for large datasets * * @example * ```typescript * const items = Array.from({ length: 100 }, (_, i) => ({ * title: `Item ${i + 1}`, * description: `Description for item ${i + 1}` * })); * * const pagination = createPagination({ * items, * itemsPerPage: 5, * currentPage: 1, * showPageInfo: true, * showNavigation: true * }); * * await interaction.reply(pagination); * ``` * * @param options - Pagination configuration options * @returns Built message with pagination components */ declare function createPagination(options: PaginationOptions): { components: APIMessageComponent[]; flags: MessageFlags; }; /** * Create a custom form modal * * @example * ```typescript * const form = createForm([ * { id: 'name', label: 'Name', required: true }, * { id: 'email', label: 'Email', required: true }, * { id: 'message', label: 'Message', style: 2, required: false } * ]); * * await interaction.showModal(form); * ``` * * @param fields - Array of form field configurations * @returns ModalBuilder instance with the specified fields */ declare function createForm(fields: FormField[]): ModalBuilder; /** * Button helper namespace for creating Discord.js buttons * * @example * ```typescript * const button = btn.primary('action', 'Click me'); * const dangerButton = btn.danger('delete', 'Delete'); * const linkButton = btn.link('https://discord.js.org', 'Visit Discord.js'); * ``` */ declare const btn: { /** * Create a primary button * @param id - Custom ID for the button * @param label - Button label text * @returns ButtonBuilder configured as primary style */ primary(id: string, label: string): ButtonBuilder; /** * Create a secondary button * @param id - Custom ID for the button * @param label - Button label text * @returns ButtonBuilder configured as secondary style */ secondary(id: string, label: string): ButtonBuilder; /** * Create a danger button * @param id - Custom ID for the button * @param label - Button label text * @returns ButtonBuilder configured as danger style */ danger(id: string, label: string): ButtonBuilder; /** * Create a success button * @param id - Custom ID for the button * @param label - Button label text * @returns ButtonBuilder configured as success style */ success(id: string, label: string): ButtonBuilder; /** * Create a link button * @param url - URL for the button to link to * @param label - Button label text * @returns ButtonBuilder configured as link style */ link(url: string, label: string): ButtonBuilder; }; /** * Select menu helper namespace for creating Discord.js select menus * * @example * ```typescript * const stringMenu = select.string('choice', 'Select an option', [ * { label: 'Option 1', value: 'opt1', description: 'First option' }, * { label: 'Option 2', value: 'opt2', description: 'Second option' } * ]); * * const userMenu = select.user('user_select', 'Select a user'); * const roleMenu = select.role('role_select', 'Select a role'); * ``` */ declare const select: { /** * Create a string select menu * @param id - Custom ID for the menu * @param placeholder - Placeholder text * @param options - Array of options with label, value, and optional description * @returns StringSelectMenuBuilder */ string(id: string, placeholder: string, options: Array<{ label: string; value: string; description?: string; }>): StringSelectMenuBuilder; /** * Create a user select menu * @param id - Custom ID for the menu * @param placeholder - Placeholder text * @returns UserSelectMenuBuilder */ user(id: string, placeholder: string): UserSelectMenuBuilder; /** * Create a role select menu * @param id - Custom ID for the menu * @param placeholder - Placeholder text * @returns RoleSelectMenuBuilder */ role(id: string, placeholder: string): RoleSelectMenuBuilder; /** * Create a channel select menu * @param id - Custom ID for the menu * @param placeholder - Placeholder text * @returns ChannelSelectMenuBuilder */ channel(id: string, placeholder: string): ChannelSelectMenuBuilder; }; /** * Migration helper to convert existing EmbedBuilder to v2 format * * @example * ```typescript * import { EmbedBuilder } from 'discord.js'; * import { convertEmbed } from 'djs-helper-kit'; * * const oldEmbed = new EmbedBuilder() * .setTitle('Title') * .setDescription('Description'); * * const newEmbed = convertEmbed(oldEmbed); * await interaction.reply(newEmbed.build()); * ``` * * @param embed - Discord.js EmbedBuilder to convert * @returns SimpleEmbed with equivalent content */ declare function convertEmbed(embed: unknown): SimpleEmbed; /** * Migrate a collection of embeds to v2 format * * @example * ```typescript * const oldEmbeds = [embed1, embed2, embed3]; * const newEmbeds = migrateEmbeds(oldEmbeds).map(e => e.build()); * ``` * * @param embeds - Array of EmbedBuilder instances * @returns Array of SimpleEmbed instances */ declare function migrateEmbeds(embeds: unknown[]): SimpleEmbed[]; /** * Check if a message contains v1 embeds that need migration * * @example * ```typescript * if (needsMigration(message)) { * const newEmbeds = migrateMessage(message); * await interaction.reply(newEmbeds[0].build()); * } * ``` * * @param message - Discord message object * @returns True if message contains embeds that should be migrated */ declare function needsMigration(message: unknown): boolean; /** * Migrate a message with v1 embeds to v2 format * * @example * ```typescript * const newEmbeds = migrateMessage(message); * for (const embed of newEmbeds) { * await interaction.followUp(embed.build()); * } * ``` * * @param message - Discord message object with embeds * @returns Array of SimpleEmbed instances */ declare function migrateMessage(message: unknown): SimpleEmbed[]; /** * Configuration options for confirm dialogs */ interface ConfirmOptions { /** Custom ID for the yes button */ yesId?: string; /** Custom ID for the no button */ noId?: string; /** Timeout in milliseconds (default: 30000) */ timeoutMs?: number; /** Whether the response should be ephemeral */ ephemeral?: boolean; /** Custom UI builder function */ ui?: (_base: ReturnType) => ReturnType; } /** * Configuration options for pagination */ interface PaginateOptions { /** Items per page (default: 10) */ perPage?: number; /** Timeout in milliseconds (default: 300000 / 5 minutes) */ timeoutMs?: number; /** Whether the response should be ephemeral */ ephemeral?: boolean; /** Custom render function for each page */ render?: (_items: string[], _page: number, _totalPages: number) => ReturnType; } /** * Configuration options for component collectors */ interface CollectOptions { /** Filter function for interactions */ filter?: (_i: MessageComponentInteraction) => boolean; /** Collection timeout in milliseconds */ time?: number; /** Maximum interactions to collect */ max?: number; } /** * Shows a confirmation dialog with Yes/No buttons. * Handles timeout gracefully and provides clear user feedback. * * @param interaction - The interaction to respond to * @param text - The confirmation message text * @param options - Configuration options * @returns Promise resolving to true if confirmed, false if denied or timed out * * @example * ```typescript * import { confirm } from 'djs-helper-kit'; * * if (await confirm(interaction, "Delete this channel?")) { * // User confirmed, proceed with deletion * await interaction.channel?.delete(); * } * ``` * * @example * ```javascript * const { confirm } = require('djs-helper-kit'); * * const confirmed = await confirm(interaction, "Are you sure?", { * ephemeral: true, * timeoutMs: 15000 * }); * ``` */ declare function confirm(interaction: ChatInputCommandInteraction | ButtonInteraction, text: string, options?: ConfirmOptions): Promise; /** * Creates a paginated interface for large lists of items. * Automatically handles navigation and provides a clean interface. * * @param interaction - The interaction to respond to * @param items - Array of items to paginate * @param options - Configuration options * * @example * ```typescript * import { paginate } from 'djs-helper-kit'; * * const userList = guild.members.cache.map(m => m.user.tag); * await paginate(interaction, userList, { * perPage: 10, * ephemeral: true * }); * ``` * * @example * ```javascript * const { paginate } = require('djs-helper-kit'); * * await paginate(interaction, items, { * perPage: 5, * render: (items, page) => card().section(`Page ${page}\n${items.join('\n')}`) * }); * ``` */ declare function paginate(interaction: ChatInputCommandInteraction | ButtonInteraction, items: string[], options?: PaginateOptions): Promise; /** * Collects button interactions from a message for a specified time. * * @param message - The message to collect interactions from * @param options - Collection options * @returns Promise resolving to array of collected interactions * * @example * ```typescript * import { collectButtons } from 'djs-helper-kit'; * * const interactions = await collectButtons(message, { * filter: (i) => i.user.id === interaction.user.id, * time: 60000, * max: 1 * }); * ``` */ declare function collectButtons(message: Message, options?: CollectOptions): Promise; /** * Field definition for modal forms */ interface ModalField { /** Unique identifier for the field */ id: string; /** Display label for the field */ label: string; /** Input style - short or paragraph */ style?: 'short' | 'paragraph'; /** Whether the field is required */ required?: boolean; /** Maximum character length */ maxLength?: number; /** Placeholder text */ placeholder?: string; /** Default value */ value?: string; } /** * Creates a modal builder with predefined fields. * Simplifies modal creation with a schema-first approach. * * @param id - Modal custom ID * @param title - Modal title * @param fields - Array of field definitions * @returns ModalBuilder instance * * @example * ```typescript * import { modal } from 'djs-helper-kit'; * * const form = modal('report', 'Report User', [ * { id: 'user', label: 'User ID', required: true }, * { id: 'reason', label: 'Reason', style: 'paragraph', maxLength: 1000 } * ]); * * await interaction.showModal(form); * ``` */ declare function modal(id: string, title: string, fields: ModalField[]): ModalBuilder; /** * Waits for a modal submission and returns parsed data. * Handles timeout and provides type-safe field access. * * @param interaction - Command interaction to show modal on * @param modal - Modal builder to show * @param timeoutMs - Timeout in milliseconds (default: 300000 / 5 minutes) * @returns Promise resolving to parsed modal data * * @example * ```typescript * import { modal, awaitModal } from 'djs-helper-kit'; * * const form = modal('report', 'Report User', [ * { id: 'user', label: 'User ID', required: true }, * { id: 'reason', label: 'Reason', style: 'paragraph' } * ]); * * const data = await awaitModal(interaction, form); * await interaction.followUp(`Reported ${data.user} for: ${data.reason}`); * ``` */ declare function awaitModal(interaction: ChatInputCommandInteraction, modal: ModalBuilder, timeoutMs?: number): Promise>; interface RestOptions { maxRetries?: number; baseDelayMs?: number; logger?: Logger; } /** * Wraps a REST instance with rate limiting and retry logic. * Provides exponential backoff with jitter for failed requests. * * @param rest - Discord.js REST instance * @param options - Configuration options * @returns Enhanced REST instance with retry logic * * @example * ```typescript * import { REST } from 'discord.js'; * import { wrapRest } from 'djs-helper-kit'; * * const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN!); * const enhancedRest = wrapRest(rest, { maxRetries: 3, baseDelayMs: 1000 }); * ``` */ declare function wrapRest(rest: REST, options?: RestOptions): REST; /** * Check if a member has a specific permission. * Implementation coming in v0.2. */ declare function hasPerm(_member: GuildMember, _perm: unknown): boolean; /** * Require guild admin permissions. * Implementation coming in v0.2. */ declare function requireGuildAdmin(_interaction: ChatInputCommandInteraction): Promise; /** * Check if bot can send messages in a channel. * Implementation coming in v0.2. */ declare function canSend(_channel: unknown): Promise; interface ShardInfo { id: number; status: string; guilds: number; ping: number; uptime: number; } interface ShardHealth { total: number; online: number; offline: number; shards: ShardInfo[]; averagePing: number; totalGuilds: number; } /** * Automatically handles sharding based on guild count. * Provides auto-scaling for large bots with health monitoring. * * @param token - Discord bot token * @param options - Sharding configuration options * @returns ShardingManager instance * * @example * ```typescript * import { autoShard } from 'djs-helper-kit'; * * const manager = autoShard(process.env.DISCORD_TOKEN!, { * totalShards: 'auto', * respawn: true * }); * * manager.on('shardCreate', shard => { * console.log(`Launched shard ${shard.id}`); * }); * ``` */ declare function autoShard(token: string, options?: AutoShardOptions): ShardingManager; /** * Check health of all shards in a sharded client. * Provides comprehensive health monitoring for large bots. * * @param client - Discord.js client (can be any shard) * @returns Promise resolving to shard health information * * @example * ```typescript * import { shardHealth } from 'djs-helper-kit'; * * // Check health every 5 minutes * setInterval(async () => { * const health = await shardHealth(client); * console.log(`Online shards: ${health.online}/${health.total}`); * console.log(`Average ping: ${health.averagePing}ms`); * }, 300000); * ``` */ declare function shardHealth(client: Client): Promise; /** * Broadcast a message to all shards. * Useful for updating configuration or sending commands across all shards. * * @param client - Discord.js client (can be any shard) * @param message - Message to broadcast * @returns Promise resolving to responses from all shards * * @example * ```typescript * import { broadcastToShards } from 'djs-helper-kit'; * * // Update configuration across all shards * await broadcastToShards(client, { * type: 'UPDATE_CONFIG', * data: { maintenance: true } * }); * ``` */ declare function broadcastToShards(client: Client, message: unknown): Promise; /** * Get guild count across all shards. * * @param client - Discord.js client * @returns Promise resolving to total guild count */ declare function getTotalGuildCount(client: Client): Promise; /** * Safely get a message without throwing on partials. * Handles cases where the message might not be cached or accessible. * * @param client - Discord.js client * @param channelId - Channel ID where the message is located * @param messageId - Message ID to fetch * @returns Promise resolving to the message or null if not found * * @example * ```typescript * import { getMessageSafe } from 'djs-helper-kit'; * * const message = await getMessageSafe(client, '123456789', '987654321'); * if (message) { * console.log('Message content:', message.content); * } * ``` */ declare function getMessageSafe(client: Client, channelId: string, messageId: string): Promise; /** * Ensure a guild member is fetched and cached. * Handles cases where the member might not be cached. * * @param client - Discord.js client * @param guildId - Guild ID where the member is located * @param userId - User ID to fetch * @returns Promise resolving to the guild member or null if not found * * @example * ```typescript * import { ensureGuildMember } from 'djs-helper-kit'; * * const member = await ensureGuildMember(client, '123456789', '987654321'); * if (member) { * console.log('Member nickname:', member.nickname); * } * ``` */ declare function ensureGuildMember(client: Client, guildId: string, userId: string): Promise; /** * In-memory cache adapter with TTL support. * Simple cache implementation for development and small-scale usage. * * @returns CacheAdapter instance * * @example * ```typescript * import { memoryCache } from 'djs-helper-kit'; * * const cache = memoryCache(); * await cache.set('user:123', { name: 'John', age: 25 }, 3600); // 1 hour TTL * const user = await cache.get('user:123'); * ``` */ declare function memoryCache(): CacheAdapter; /** * Redis cache adapter (requires Redis connection). * For production use with Redis server. * * @param url - Redis connection URL * @returns CacheAdapter instance * * @example * ```typescript * import { redisCache } from 'djs-helper-kit'; * * const cache = redisCache('redis://localhost:6379'); * await cache.set('session:123', { userId: '456' }, 1800); // 30 min TTL * ``` */ declare function redisCache(_url: string): CacheAdapter; interface I18nOptions { defaultLocale?: string; fallbackLocale?: string; logger?: Logger; } interface I18nInstance { t(key: string, locale?: string, params?: Record): string; locale: string; setLocale(locale: string): void; has(key: string, locale?: string): boolean; } /** * Create an i18n instance for locale-aware responses. * Provides simple internationalization for Discord bot responses. * * @param locales - Dictionary of locale keys to translation objects * @param options - Configuration options * @returns I18nInstance * * @example * ```typescript * import { createI18n } from 'djs-helper-kit'; * * const i18n = createI18n({ * en: { * 'welcome': 'Welcome to the server!', * 'ping': 'Pong! Latency: {latency}ms' * }, * es: { * 'welcome': '¡Bienvenido al servidor!', * 'ping': '¡Pong! Latencia: {latency}ms' * } * }); * * await interaction.reply(i18n.t('welcome', 'en')); * ``` */ declare function createI18n(locales: Dict, options?: I18nOptions): I18nInstance; /** * Get user's preferred locale from Discord. * Extracts locale from user's Discord settings. * * @param user - Discord user object * @returns User's locale or fallback * * @example * ```typescript * import { getUserLocale } from 'djs-helper-kit'; * * const userLocale = getUserLocale(interaction.user); * const message = i18n.t('welcome', userLocale); * ``` */ declare function getUserLocale(_user: unknown): string; /** * Format number according to locale. * * @param number - Number to format * @param locale - Locale for formatting * @returns Formatted number string */ declare function formatNumber(number: number, locale?: string): string; /** * Format date according to locale. * * @param date - Date to format * @param locale - Locale for formatting * @param options - Intl.DateTimeFormatOptions * @returns Formatted date string */ declare function formatDate(date: Date, locale?: string, options?: Intl.DateTimeFormatOptions): string; /** * Base error class for djs-helper-kit errors */ declare class EasierError extends Error { code?: string; cause?: unknown; constructor(message: string, code?: string, cause?: unknown); } /** * Error thrown when command validation fails */ declare class CommandValidationError extends EasierError { constructor(message: string, cause?: unknown); } /** * Error thrown when permissions are insufficient */ declare class PermissionError extends EasierError { constructor(message: string, cause?: unknown); } /** * Error thrown when rate limits are exceeded */ declare class RateLimitError extends EasierError { constructor(message: string, retryAfter?: number, cause?: unknown); } /** * Installs default error handling middleware for Discord interactions. * Catches unhandled errors and provides user-friendly error messages. * * @param client - Discord.js client to install error handling on * @param logger - Optional logger for error reporting * * @example * ```typescript * import { installInteractionErrorHandler } from 'djs-helper-kit'; * * installInteractionErrorHandler(client, logger); * ``` * * @example * ```javascript * const { installInteractionErrorHandler } = require('djs-helper-kit'); * installInteractionErrorHandler(client); * ``` */ declare function installInteractionErrorHandler(client: Client, logger?: Logger): void; /** * Creates a logger with redaction capabilities * * @param options - Logger configuration * @returns Logger instance with built-in redaction * * @example * ```typescript * import { createLogger } from 'djs-helper-kit'; * * const logger = createLogger({ * level: 'info', * redact: ['password', 'token', 'secret'] * }); * ``` */ declare function createLogger(options?: { level?: 'debug' | 'info' | 'warn' | 'error'; redact?: string[]; }): Logger; export { type AutoShardOptions, type CacheAdapter, type CollectOptions, type CommandContext, type CommandDefinition, CommandValidationError, type ConfirmOptions, type CreateClientOptions, type DeployOptions, type Dict, EasierError, type Features, type FormField, type I18nInstance, type I18nOptions, type Logger, type Markdownish, type ModalBuilderV2, type ModalField, type PaginateOptions, type PaginationOptions, PermissionError, type PrefixCommandDefinition, RateLimitError, type RestOptions, type ShardHealth, type ShardInfo, type SimpleEmbed, type SimpleMessage, autoShard, awaitModal, broadcastToShards, btn, canSend, collectButtons, confirm, convertEmbed, createClient, createCommandHandler, createForm, createI18n, createLogger, createPagination, createPrefixCommandHandler, deploy, diagnose, embed, ensureGuildMember, formatDate, formatNumber, getMessageSafe, getTotalGuildCount, getUserLocale, hasPerm, installInteractionErrorHandler, loadCommands, loadCommandsAsync, memoryCache, migrateEmbeds, migrateMessage, modal, modalV2, msg, needsMigration, paginate, redisCache, requireGuildAdmin, select, shardHealth, wrapRest };