npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

cordify-plus

v1.0.0

Published

Premium Discord bot framework with plugin system, advanced event handling, and comprehensive logging

Readme

Cordify+ 🚀

Cordify+ is a premium Discord bot framework with advanced plugin architecture, comprehensive event handling, and professional-grade logging. Built for developers who need a robust, extensible foundation for Discord bots.

✨ Features

  • 🔐 Authentication System - Secure username/password authentication for authorized users only
  • 🧩 Plugin/Extension System - Auto-discovery and hot-reload support for modular bot features
  • Advanced Event System - EventEmitter-based architecture wrapping Discord.js events
  • 📝 Professional Logging - Winston-based logging with configurable levels and outputs
  • Config Validation - Joi schema validation ensuring proper configuration before startup
  • 🎯 Command Management - Support for both prefix and slash commands
  • 🧪 Testing Utilities - Mock Discord entities for unit testing
  • 🔄 Plugin Lifecycle - Clean initialization, loading, and unloading of plugins

📦 Installation

npm install cordify-plus

🚀 Quick Start

Note: The authentication system is a feature for bot operators to control who can run their bot. It does NOT affect npm installation - anyone can install this package normally with npm install cordify-plus.

1. Create a Bot Instance

const { CordifyClient } = require('cordify-plus');

const bot = new CordifyClient('./config.json');

bot.start().catch(error => {
  console.error('Failed to start bot:', error);
  process.exit(1);
});

2. Configure Your Bot

Create a config.json:

{
  "discord": {
    "token": "YOUR_DISCORD_BOT_TOKEN",
    "prefix": "!",
    "intents": ["Guilds", "GuildMessages", "MessageContent"]
  },
  "auth": {
    "enabled": true,
    "usersFile": "authorized-users.json"
  },
  "logging": {
    "level": "info"
  },
  "plugins": {
    "directory": "plugins",
    "autoLoad": true
  }
}

3. Set Up Authentication (Optional)

Authentication is disabled by default. To enable it, set auth.enabled: true in your config and create authorized-users.json:

{
  "users": [
    {
      "username": "your-username",
      "password": "your-password",
      "note": "Main admin"
    }
  ]
}

When authentication is enabled, you'll be prompted for credentials when starting the bot.

🧩 Creating Plugins

Plugins are the core of Cordify+. Each plugin is a self-contained module in the plugins/ directory.

Plugin Structure

plugins/
└── my-plugin/
    └── index.js

Example Plugin

module.exports = {
  name: 'my-plugin',
  version: '1.0.0',
  description: 'My awesome plugin',
  dependencies: [],

  async init(context) {
    const { client, logger, eventSystem, config, registerCommand, on, emit } = context;

    logger.info('My plugin is initializing!');

    // Register a command
    registerCommand({
      name: 'hello',
      description: 'Say hello',
      execute: async (message, args) => {
        await message.reply('Hello from my plugin!');
      }
    });

    // Listen to events
    on('ready', (client) => {
      logger.info(`Plugin ready! Connected as ${client.user.tag}`);
    });

    on('messageCreate', (message) => {
      if (message.content.includes('hello')) {
        logger.debug('Someone said hello!');
      }
    });
  },

  async destroy(context) {
    context.logger.info('My plugin is shutting down...');
  }
};

📚 Plugin Context API

When your plugin's init() function is called, it receives a context object with:

| Property | Description | |----------|-------------| | client | The Discord.js client instance | | logger | Logger instance for your plugin | | eventSystem | Event system for emitting/listening to events | | config | Your plugin's configuration from config.json | | registerCommand(cmd) | Register a prefix or slash command | | on(event, listener) | Listen to an event | | emit(event, ...args) | Emit a custom event |

🎯 Command Types

Prefix Commands

registerCommand({
  name: 'ping',
  description: 'Check bot latency',
  aliases: ['p'],
  execute: async (message, args) => {
    const latency = Date.now() - message.createdTimestamp;
    await message.reply(`Pong! ${latency}ms`);
  }
});

Slash Commands

registerCommand({
  type: 'slash',
  name: 'greet',
  description: 'Greet a user',
  options: [
    {
      name: 'user',
      description: 'User to greet',
      type: 'USER',
      required: true
    }
  ],
  execute: async (interaction) => {
    const user = interaction.options.getUser('user');
    await interaction.reply(`Hello, ${user}!`);
  }
});

🎪 Events

Cordify+ emits various events you can listen to:

Discord.js Events

  • ready - Bot is ready
  • messageCreate - New message received
  • interactionCreate - Interaction received
  • guildMemberAdd - Member joined a guild
  • guildMemberRemove - Member left a guild

Cordify+ Events

  • commandInvoked - Prefix command was executed
  • slashCommandInvoked - Slash command was executed
  • commandError - Error in command execution
  • pluginLoaded - Plugin was loaded
  • pluginUnloaded - Plugin was unloaded
  • allPluginsLoaded - All plugins finished loading
  • shutdown - Bot is shutting down

🧪 Testing

Cordify+ includes testing utilities for unit testing your plugins:

const { TestUtils } = require('cordify-plus');
const { createMockMessage, createMockChannel, simulateCommand } = TestUtils;

describe('My Plugin', () => {
  test('ping command responds', async () => {
    const channel = createMockChannel();
    const message = createMockMessage('!ping', null, channel);
    
    // Your command logic here
    await message.reply('Pong!');
    
    expect(channel.getLastMessage().content).toBe('Pong!');
  });
});

📝 Logging

Use the logger provided in your plugin context:

logger.error('Something went wrong!');
logger.warn('Warning message');
logger.info('Info message');
logger.debug('Debug details');

Set log level via environment variable:

LOG_LEVEL=debug node bot.js

⚙️ Configuration Schema

Cordify+ validates all configuration at startup. Required fields:

{
  discord: {
    token: string (required),
    intents: string[] (optional),
    prefix: string (default: '!')
  },
  auth: {
    enabled: boolean (default: true),
    usersFile: string (default: 'authorized-users.json')
  },
  logging: {
    level: 'error' | 'warn' | 'info' | 'debug' (default: 'info'),
    file: string | null (default: null)
  },
  plugins: {
    directory: string (default: 'plugins'),
    autoLoad: boolean (default: true),
    hotReload: boolean (default: false)
  }
}

🔄 Plugin Lifecycle

  1. Discovery - Cordify+ scans the plugins directory
  2. Load - Each plugin's index.js is required
  3. Validate - Plugin metadata is checked
  4. Initialize - Plugin's init() function is called
  5. Register - Commands and event listeners are registered
  6. Ready - Plugin is active and running

To unload/reload a plugin programmatically:

bot.getPluginManager().unloadPlugin('my-plugin');
bot.getPluginManager().reloadPlugin('my-plugin');

🛡️ Error Handling

Cordify+ automatically:

  • Catches and logs plugin errors without crashing the bot
  • Wraps command execution in try/catch
  • Handles unhandled promise rejections
  • Gracefully shuts down on SIGINT/SIGTERM

🌟 Environment Variables

DISCORD_TOKEN=your_token_here
LOG_LEVEL=info
NODE_ENV=development

📖 Examples

Check the example/ directory for:

  • Complete bot setup
  • Sample configuration
  • Example plugin demonstrating best practices

🤝 Contributing

To create a new plugin:

  1. Create a folder in plugins/
  2. Add an index.js with name, version, init()
  3. Register commands and event listeners in init()
  4. Test thoroughly
  5. Share with the community!

📄 License

MIT

🔗 Links


Made with ❤️ for the Discord bot development community