๐Ÿšจ Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis โ†’
Socket
Book a DemoInstallSign in
Socket

discord-conversation-wizard

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

discord-conversation-wizard

A powerful, library-agnostic wizard for creating multi-step conversations and forms in Discord bots. Supports discord.js and Eris with advanced validation, middleware, and state management.

latest
Source
npmnpm
Version
1.2.1
Version published
Maintainers
1
Created
Source

๐Ÿง™โ€โ™‚๏ธ Discord Conversation Wizard

A powerful, library-agnostic wizard for creating multi-step conversations and forms in Discord bots.

npm version npm downloads npm bundle size GitHub Workflow Status License: MIT TypeScript GitHub Stars

โœจ Features

  • ๐Ÿ”„ Library Agnostic - Works with discord.js v14+ and Eris v0.17+
  • โšก Type-Safe - Full TypeScript support with comprehensive type definitions
  • ๐ŸŽฏ Advanced Validation - Built-in validators with custom validation support
  • ๐Ÿ“š Built-in Validators - Email, URL, phone, regex, length, range, and more (v1.1.0+)
  • ๐Ÿ“Š Progress Indicators - Visual progress tracking with customizable format (v1.1.0+)
  • โฑ๏ธ Timeout Warnings - Configurable warnings before response timeout (v1.1.0+)
  • ๐Ÿช Middleware System - Hooks for beforeStep, afterStep, onError, and more
  • ๐Ÿงญ Step Navigation - Back, skip, jump to step, and cancel functionality
  • ๐Ÿ”€ Conditional Steps - Show/hide steps based on previous responses
  • ๐Ÿ’พ Session Persistence - Save and resume wizard sessions
  • ๐ŸŽจ Rich Components - Select menus, buttons, confirmations, and attachments
  • ๐Ÿ”ข Smart Input Types - Text, number, attachment, select menu, confirmation
  • โ™พ๏ธ Multi-Select - Support for multiple selections in select menus
  • ๐Ÿ›ก๏ธ Error Handling - Comprehensive error handling with retry limits
  • ๐Ÿ“ Data Transformation - Transform responses before validation
  • ๐ŸŽญ Event-Driven - Full event system for monitoring wizard state

๐Ÿ“ฆ Installation

npm install discord-conversation-wizard

Peer Dependencies

For Discord.js:

npm install discord.js@^14.0.0

For Eris:

npm install eris@^0.17.0

๐Ÿš€ Quick Start

Discord.js Example

import { Client, GatewayIntentBits } from 'discord.js';
import { Wizard, DiscordJSAdapter, StepType } from 'discord-conversation-wizard';

const client = new Client({
    intents: [
        GatewayIntentBits.Guilds,
        GatewayIntentBits.GuildMessages,
        GatewayIntentBits.MessageContent,
    ],
});

client.on('messageCreate', async (message) => {
    if (message.content === '!register') {
        const adapter = new DiscordJSAdapter(client);
        
        const wizard = new Wizard(adapter, {
            steps: [
                {
                    id: 'name',
                    type: StepType.TEXT,
                    prompt: '๐Ÿ‘‹ What is your name?',
                    validate: (response) => {
                        if (response.length < 2) return 'Name must be at least 2 characters';
                        if (response.length > 32) return 'Name must be less than 32 characters';
                        return true;
                    },
                },
                {
                    id: 'age',
                    type: StepType.NUMBER,
                    prompt: '๐ŸŽ‚ How old are you?',
                    minValue: 13,
                    maxValue: 120,
                },
                {
                    id: 'role',
                    type: StepType.SELECT_MENU,
                    prompt: '๐ŸŽญ Select your preferred role:',
                    options: [
                        { label: 'Developer', value: 'dev', emoji: '๐Ÿ’ป' },
                        { label: 'Designer', value: 'design', emoji: '๐ŸŽจ' },
                        { label: 'Manager', value: 'manager', emoji: '๐Ÿ“Š' },
                    ],
                },
            ],
            allowBack: true,
            allowCancel: true,
        });

        wizard.on('complete', (responses) => {
            message.channel.send(
                `โœ… Registration complete!\n` +
                `**Name:** ${responses.name}\n` +
                `**Age:** ${responses.age}\n` +
                `**Role:** ${responses.role}`
            );
        });

        wizard.on('cancel', () => {
            message.channel.send('โŒ Registration cancelled.');
        });

        await wizard.start({
            userId: message.author.id,
            channelId: message.channel.id,
            guildId: message.guild?.id,
        });
    }
});

client.login('YOUR_BOT_TOKEN');

Eris Example

import Eris from 'eris';
import { Wizard, ErisAdapter, StepType } from 'discord-conversation-wizard';

const bot = new Eris('YOUR_BOT_TOKEN');

bot.on('messageCreate', async (message) => {
    if (message.content === '!survey') {
        const adapter = new ErisAdapter(bot);
        
        const wizard = new Wizard(adapter, {
            steps: [
                {
                    id: 'feedback',
                    type: StepType.TEXT,
                    prompt: '๐Ÿ’ฌ What do you think about our service?',
                    maxLength: 500,
                },
                {
                    id: 'rating',
                    type: StepType.SELECT_MENU,
                    prompt: 'โญ Rate your experience:',
                    options: [
                        { label: 'โญโญโญโญโญ Excellent', value: '5' },
                        { label: 'โญโญโญโญ Good', value: '4' },
                        { label: 'โญโญโญ Average', value: '3' },
                        { label: 'โญโญ Poor', value: '2' },
                        { label: 'โญ Terrible', value: '1' },
                    ],
                },
            ],
        });

        wizard.on('complete', (responses) => {
            bot.createMessage(message.channel.id, `Thank you for your feedback! Rating: ${responses.rating}/5`);
        });

        await wizard.start({
            userId: message.author.id,
            channelId: message.channel.id,
        });
    }
});

bot.connect();

๐Ÿ“– Advanced Usage

Conditional Steps

Show or hide steps based on previous responses:

const wizard = new Wizard(adapter, {
    steps: [
        {
            id: 'hasExperience',
            type: StepType.CONFIRMATION,
            prompt: 'Do you have previous experience?',
        },
        {
            id: 'yearsOfExperience',
            type: StepType.NUMBER,
            prompt: 'How many years of experience do you have?',
            minValue: 0,
            maxValue: 50,
            condition: (responses) => responses.hasExperience === 'wizard_confirm_hasExperience',
        },
    ],
});

Middleware Hooks

Add custom logic at different stages:

const wizard = new Wizard(adapter, {
    steps: [...],
    middleware: {
        beforeStep: async (step, context) => {
            console.log(`Starting step: ${step.id}`);
        },
        afterStep: async (step, response, context) => {
            console.log(`Completed step ${step.id} with response:`, response);
            // Save to database, log analytics, etc.
        },
        onError: async (error, step, context) => {
            console.error(`Error in step ${step.id}:`, error);
            // Send to error tracking service
        },
        onComplete: async (responses, context) => {
            console.log('Wizard completed!', responses);
            // Save final data to database
        },
        onCancel: async (context) => {
            console.log('Wizard cancelled at step:', context.stepId);
        },
    },
});

Data Transformation

Transform user input before validation:

{
    id: 'email',
    type: StepType.TEXT,
    prompt: '๐Ÿ“ง Enter your email address:',
    transform: (response) => response.toLowerCase().trim(),
    validate: (email) => {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(email) || 'Please enter a valid email address';
    },
}

Multi-Select Menus

Allow users to select multiple options:

{
    id: 'interests',
    type: StepType.SELECT_MENU,
    prompt: '๐ŸŽฏ Select your interests (you can choose multiple):',
    allowMultiple: true,
    options: [
        { label: 'Gaming', value: 'gaming', emoji: '๐ŸŽฎ' },
        { label: 'Music', value: 'music', emoji: '๐ŸŽต' },
        { label: 'Sports', value: 'sports', emoji: 'โšฝ' },
        { label: 'Art', value: 'art', emoji: '๐ŸŽจ' },
        { label: 'Technology', value: 'tech', emoji: '๐Ÿ’ป' },
    ],
}

Session Persistence & Resume

Save wizard state and resume later:

const wizard = new Wizard(adapter, {
    steps: [...],
    persistSession: true,
    sessionId: 'user_' + userId, // Optional custom session ID
});

wizard.on('sessionSaved', (session) => {
    console.log('Session saved:', session.sessionId);
});

// Resume a previously started wizard
await wizard.resume('session_id_here');

Step Navigation

Enable powerful navigation controls:

const wizard = new Wizard(adapter, {
    steps: [...],
    allowBack: true,    // User can type "back" to go to previous step
    allowSkip: true,    // User can type "skip" to skip optional steps
    allowCancel: true,  // User can type "cancel" to abort the wizard
});

// Programmatic navigation
await wizard.goBack();
await wizard.skip();
await wizard.jumpToStep('stepId');
wizard.cancel();

Attachment Validation

Request and validate file uploads:

{
    id: 'avatar',
    type: StepType.ATTACHMENT,
    prompt: '๐Ÿ“Ž Upload your profile picture:',
    validate: (attachment) => {
        const validTypes = ['image/png', 'image/jpeg', 'image/gif'];
        if (!validTypes.includes(attachment.contentType)) {
            return 'Please upload a PNG, JPEG, or GIF image';
        }
        if (attachment.size > 5 * 1024 * 1024) {
            return 'Image must be smaller than 5MB';
        }
        return true;
    },
}

Retry Limits

Configure maximum retry attempts for validation failures:

{
    id: 'code',
    type: StepType.TEXT,
    prompt: 'Enter the verification code:',
    retry: 3, // Maximum 3 attempts
    validate: (code) => {
        return code === 'SECRET123' || 'Invalid verification code';
    },
}

Built-in Validators (v1.1.0+)

Use pre-built validators for common validation patterns:

import { validators } from 'discord-conversation-wizard';

const wizard = new Wizard(adapter, {
    steps: [
        {
            id: 'email',
            type: StepType.TEXT,
            prompt: '๐Ÿ“ง Enter your email:',
            validate: validators.email(),
            transform: (value) => value.toLowerCase().trim(),
        },
        {
            id: 'website',
            type: StepType.TEXT,
            prompt: '๐ŸŒ Enter your website:',
            validate: validators.url({ requireProtocol: false }),
        },
        {
            id: 'phone',
            type: StepType.TEXT,
            prompt: '๐Ÿ“ฑ Enter your phone number:',
            validate: validators.phone(),
        },
        {
            id: 'username',
            type: StepType.TEXT,
            prompt: '๐Ÿ‘ค Enter your username:',
            validate: validators.regex(/^[a-zA-Z0-9_]{3,16}$/, {
                message: 'Username must be 3-16 characters (letters, numbers, underscores only)'
            }),
        },
        {
            id: 'bio',
            type: StepType.TEXT,
            prompt: '๐Ÿ“ Write your bio:',
            validate: validators.length({ min: 10, max: 500 }),
        },
        {
            id: 'age',
            type: StepType.NUMBER,
            prompt: '๐ŸŽ‚ Enter your age:',
            validate: validators.range({ min: 13, max: 120 }),
        },
        {
            id: 'password',
            type: StepType.TEXT,
            prompt: '๐Ÿ”’ Create a password:',
            validate: validators.combine([
                validators.length({ min: 8, max: 128 }),
                validators.regex(/[A-Z]/, { message: 'Must contain uppercase' }),
                validators.regex(/[0-9]/, { message: 'Must contain number' }),
            ]),
        },
    ],
});

Available Validators:

  • validators.email() - Valid email address
  • validators.url() - Valid URL with optional protocol requirements
  • validators.phone() - International phone number format
  • validators.regex(pattern) - Custom regex pattern matching
  • validators.length({ min, max }) - String length validation
  • validators.range({ min, max }) - Numeric range validation
  • validators.combine([...]) - Combine multiple validators (AND logic)
  • validators.oneOf([...]) - Value must be in allowed list

Progress Indicators (v1.1.0+)

Show visual progress throughout the wizard:

const wizard = new Wizard(adapter, {
    steps: [...],
    showProgress: true,
    progressFormat: '๐Ÿ“Š Step {current}/{total}', // or '{percent}%'
});

Format Placeholders:

  • {current} - Current step number (1-indexed)
  • {total} - Total number of steps
  • {percent} - Progress percentage (0-100)

Default format: ๐Ÿ“Š Step {current}/{total}

Timeout Warnings (v1.1.0+)

Send warnings before response timeout expires:

const wizard = new Wizard(adapter, {
    steps: [...],
    timeout: 60, // seconds
    timeoutWarning: true, // warns 15 seconds before by default
    // OR
    timeoutWarning: 20, // warns 20 seconds before timeout
    timeoutWarningMessage: 'โฐ Hurry! Time is running out!',
});

Options:

  • timeoutWarning: true - Warns 15 seconds before timeout (default)
  • timeoutWarning: <number> - Warns N seconds before timeout
  • timeoutWarningMessage - Custom warning message

๐Ÿ“š API Reference

Wizard

Main wizard class for managing conversation flow.

Constructor

new Wizard(adapter: AdapterInterface, options: WizardOptions)

Methods

  • start(context: WizardContext): Promise<void> - Start the wizard
  • resume(sessionId: string): Promise<boolean> - Resume a saved session
  • cancel(): void - Cancel the wizard
  • goBack(): Promise<boolean> - Navigate to previous step
  • skip(): Promise<boolean> - Skip current step
  • jumpToStep(stepId: string): Promise<boolean> - Jump to a specific step
  • getResponses(): Record<string, any> - Get all collected responses
  • getCurrentStepIndex(): number - Get current step index
  • isActive(): boolean - Check if wizard is running
  • getSessionId(): string - Get session ID

Events

  • start - Wizard started
  • step - New step started
  • skip - Step was skipped
  • complete - Wizard completed successfully
  • cancel - Wizard was cancelled
  • error - Error occurred
  • sessionSaved - Session was saved
  • resume - Session was resumed
  • maxRetriesReached - Maximum retry attempts reached

WizardOptions

Configuration options for the wizard.

interface WizardOptions {
    steps: WizardStep[];
    title?: string;
    timeout?: number;
    middleware?: WizardMiddleware;
    allowBack?: boolean;
    allowSkip?: boolean;
    allowCancel?: boolean;
    sessionId?: string;
    persistSession?: boolean;
}

WizardStep

Configuration for a single step.

interface WizardStep {
    id: string;
    prompt: string;
    type: StepType;
    options?: StepOption[];
    validate?: (response: any, context: WizardStepContext) => boolean | string | Promise<boolean | string>;
    transform?: (response: any, context: WizardStepContext) => any | Promise<any>;
    timeout?: number;
    minLength?: number;
    maxLength?: number;
    minValue?: number;
    maxValue?: number;
    required?: boolean;
    allowMultiple?: boolean;
    condition?: (responses: Record<string, any>, context: WizardContext) => boolean | Promise<boolean>;
    onSkip?: (context: WizardStepContext) => void | Promise<void>;
    retry?: number;
}

StepType

Available step types:

  • StepType.TEXT - Text input
  • StepType.NUMBER - Numeric input with validation
  • StepType.SELECT_MENU - Discord select menu (dropdown)
  • StepType.BUTTON - Button interactions
  • StepType.CONFIRMATION - Yes/No confirmation buttons
  • StepType.ATTACHMENT - File upload

๐Ÿค Contributing

Contributions are welcome! Please check out the Contributing Guide for more information.

๐Ÿ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

Created with โค๏ธ by Jersuxs

โญ Star us on GitHub if you find this helpful!

Keywords

discord

FAQs

Package last updated on 30 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts