TypeScript Discord Bot Handler

A simple discord bot handler with advanced features and high customization.

Features

Slash Command Handler

Simple command handler for slash commands

Prefix Command Handler

Simple command handler for prefix commands

Sharding Agent

Sharding - done EASY. Enable and manage sharding easily just using the .env file!

Dynamic Database Support

Supports various types of databases

WebHook Events

Get notified when something happens

Event Handler

Build-in event handler for Discord events

Scheduled Tasks

Automate recurring actions

File Cache System

Store data in files for faster access

Plugin System

Load plugins to extend functionality

File written logs

Interaction logs, Console logs and Guild joins are now logged into files! (can be disabled in config.json)

Plugin System

Load plugins to extend functionality

Installation

1. Clone the repository:

              
              
git clone https://github.com/cptcr/discord-development/tree/main/handler.git
              
            

2. Install dependencies:

              
              npm i
            

3. Configure the code (See Configuration section)

4. Start the bot:

              
              npx ts-node src/shard.ts
            

or:

              
              npm run start
            

Configuration

Events and Logs

File: config.json

              
              {
                "enabled-default-logs": {
                    "command-registry": true, // Enable command registry logs
                    "startup": true, // Enable startup logs
                    "database-connection": true , // Enable database connection logs
                },
                "webhook": {
                    "config": {
                        "disabled": false, // Disable webhook events
                        "url": "https://discord.com/api/webhooks/", // Your webhook url
                        "roleId": null , // Role ID to ping when a event happens (nullable)
                    },
                    "webhook-events": {
                        "command-registry": true, // Enable command registry webhook events
                        "startup": true, // Enable startup webhook events
                        "database-connection": true, // Enable database connection webhook events
                        "errors": {
                            "fatal": true, // Enable fatal error webhook events
                            "debug": true, // Enable debug error webhook events
                            "error": true, // Enable error webhook events
                            "success": true, // Enable success webhook events
                            "warn": true, // Enable warn webhook events
                            "info": true // Enable info webhook events
                        }
                    },
                    "other": {
                        "use-legal": true, // Enable legal handling (see more below on this page)
                        "use-written-logs": true , // Enable written logs
                    }
                }
                
            }

            

Bot Configuration

File: .env

              
              #=============================
                #        DISCORD BOT
                #=============================
                # Discord bot credentials and settings
                export DISCORD_TOKEN = ""  
                # Your Discord bot token (required to authenticate with the Discord API)
                export DISCORD_ID = ""     
                # Bot ID (unique identifier for your bot)
                export PREFIX = "?"        
                # Prefix for text-based bot commands (e.g., "!", "?")
                export GUILD_ID = ""     
                # Guild (server) ID for faster slash command updates
                export USE_SHARDING = false
                # Enables sharding for the bot (recommended for large servers), can be set to "auto" to automatically enable sharding if the bot is running on a large server, "false" to disble sharding, or a number to specify the number of shards to use
                
                #=============================
                #    DATABASE CONFIGURATION
                #=============================
                # Type of database to connect to. Supported values:
                #  - mysql
                #  - postgres
                #  - mariadb
                #  - sqlite
                #  - mssql
                #  - mongoose (for MongoDB)
                export DB_TYPE = "mongoose"
                # Specify the database type here (e.g., mysql, mongoose)
                
                #=============================
                #       SQL DATABASE
                #=============================
                # SQL database connection details (only required if DB_TYPE is a SQL-based database)
                export DB_HOST = ""
                # Database server hostname (IP or domain)
                export DB_USER = ""
                # Database username
                export DB_PASS = ""
                # Database password
                export DB_NAME = ""
                # Database name to connect to
                export DB_PORT = "0"
                # Port number for the database server (default ports vary by DB type)
                
                #=============================
                #      MONGODB DATABASE
                #=============================
                # MongoDB connection details (only required if DB_TYPE is "mongoose")
                export MONGO_HOST = ""
                # MongoDB connection string (e.g., mongodb+srv://:@cluster.mongodb.net/) Warning: This may or may not be different if you use a self hosted MongoDB server

            

Documentation

Deploying Slash Commands

Directory: src/slash

Example code:

              
              // src/slash/fun/ping.ts

                // Import required modules from discord.js
                import { SlashCommandBuilder, ChatInputCommandInteraction, Client } from "discord.js";
                // Import SlashCommand Interface to build a command (required)
                import { SlashCommand } from "../../dev/Interfaces/Command.js";
                
                // Define the command
                const pingCommand: SlashCommand = {
                  // Command Data (required)
                  data: new SlashCommandBuilder() // Discord.js SlashCommandBuilder to build a command and return json data for the discord api
                  .setName("ping") // The command name
                  .setDescription("Replies with Pong!"), // The command description
                
                  // Execute function (required)
                  async execute(client: Client, interaction: ChatInputCommandInteraction) {
                    // Handle the command logic
                    await interaction.reply("Pong! 🏓");
                  },
                };
                
                // MUST BE EXPORTED AS DEFAULT
                export default pingCommand;

            

Deploying Prefix Commands

Directory: src/prefix

              
              // src/prefix/fun/ping.ts

                // Import PrefixCommand Interface to build a command (required)
                import { PrefixCommand } from "../../dev/Interfaces/Command";
                // Import required modules from discord.js
                import { Client, Message } from "discord.js";
                
                // Define the command
                const pingCommand: PrefixCommand = {
                  name: "ping", // The command name (required)
                  aliases: ["p"], // The command aliases (?ping and ?p will work and return the same result) (required)
                  description: "Replies with Pong!", // The command description (required)
                
                  // Execute function (required)
                  async execute(client: Client, message: Message, args: string[]) {
                
                    // Handle the command logic
                    await message.reply("Pong! 🏓");
                  }
                };
                
                // MUST BE EXPORTED AS DEFAULT
                export default pingCommand;

            

Custom Events

Directory: src/events

              
              // Import required modules from discord.js
                import { Client, GuildMember } from 'discord.js';
                // Import Event Interface to build the event (required)
                import  Event  from '../../dev/Interfaces/Event';
                // Import info log to display that a member joined the server (optional)
                import { info } from '../../dev/utils/logs';
                
                // Exporting the Event
                export default {
                  name: 'guildMemberAdd', // The event name, must be the same as the event name in discord.js (required)
                  once: false, // Whether the event should only be triggered once (optional, default: false)
                  execute(client: Client, member: GuildMember) { // The event function (required)
                    info(true, `${member.user.tag} joined ${member.guild.name}`); // Display a message in the console
                    // Additional logic for welcoming the new member, etc.
                  },
                } as Event;

            

Schedules

Directory: src/schedules

              
              // Import the Schedule Interface
                import { Schedule } from '../dev/Interfaces/Schedule';
                // Import Discord Modules (required: Client)
                import { Client } from 'discord.js';
                
                export default {
                  name: 'dailyReminder', // Name of the schedule
                  cron: '0 9 * * *', // runs every day at 9:00 AM server time 
                  async run(client: Client) {
                    // Handle the logic here
                  },
                } as Schedule;

            

Database Configuration

MongoDB Configuration:

              
              import database from "database";
database();

            

SQL Database Configuration:

              
              import database from "database";
const db = database(); // This will return the database object which is declared as the variable "db" to be used in your code.

            

Cache System

Basic Usage:

Caches the data in a map.

              
              // Example command file: /src/commands/fetchUser.ts
                import { globalCache } from '../dev/utils/globalCache';
                
                export async function fetchUser(userId: string) {
                  const cacheKey = `user:${userId}`;
                
                  // 1. Check cache
                  let data = globalCache.get(cacheKey);
                
                  // 2. If not found, fetch from some imaginary function or API
                  if (!data) {
                    data = await fakeDatabaseCallOrExternalAPI(userId);
                
                    // 3. Store it in the cache with a 10-minute TTL
                    globalCache.set(cacheKey, data, 600);
                  }
                
                  // Return the data (from cache or freshly fetched)
                  return data;
                }
                
                async function fakeDatabaseCallOrExternalAPI(userId: string): Promise {
                  // Just an example function
                  return { id: userId, name: 'John Doe' };
                }

            

Cache With File:

Caches the data in a json file.

              
              // /src/index.ts

                import { FileCache } from './dev/utils/cacheWithFile';
                
                // Create an instance of FileCache
                // By default, it writes to and reads from "cacheData.json" in the same folder.
                export const fileCache = new FileCache('cacheData.json');

// Usage example
import { fileCache } from '../index'; // Import the same instance from index.ts

export async function handleWelcomeCommand(args: string[]) {
  // If the user types something like "!welcome set Hello Everyone!"
  // Then 'args' might be ["set", "Hello", "Everyone!"] etc.

  const subCommand = args[0];

  if (subCommand === 'set') {
    // The rest of args is the new message
    const newMessage = args.slice(1).join(' ');
    fileCache.set('welcomeMessage', newMessage);
    return `Set welcome message to: "${newMessage}"`;
  } 
  
  else if (subCommand === 'get') {
    const storedMessage = fileCache.get('welcomeMessage');
    return storedMessage 
      ? `Current welcome message: "${storedMessage}"`
      : `No welcome message set yet.`;
  }
  
  else {
    return `Usage: !welcome [set|get] [message]`;
  }
}

            

Developing Plugins & Importing Plugins

Plugins are used to extend the functionality of the bot. They can be used to add new commands, modify existing ones, or even create new features.


Requirements for developing and importing Plugins:

  • Plugin File Name MUST be the same as the plugin name.
  • If you add a plugin, make sure to add the plugin name into config.json["plugins"] array.

  •               
                  // Import the Interface to build a plugin
                    import Plugin from '../dev/Interfaces/Plugin';
                    
                    const HelloPlugin: Plugin = { // Define the plugin
                      name: 'my-bot-plugin-hello', // Unique name for the plugin
                      version: '1.0.0', // Version of the plugin
                      github: "https://github.com/cptcr/discord-development/tree/main/handler/src/plugins/example.ts", // GitHub link to the plugin
                      author: "cptcr" // Author of the plugin
                      
                      async onLoad(client, botConfig) {
                        // Logic of the plugin
                      },
                    
                      onUnload() {
                        // Optionally remove the event listener or cleanup
                        // But depends on whether your code can actually unhook events dynamically
                      }
                    };
                    
                    export default HelloPlugin;
    
                

    Credits

    Node.js

    For the Node.js runtime environment

    nodejs.org

    Discord.js

    For handling the Discord API

    discord.js.org

    Mongoose

    For handling the MongoDB database

    mongoosejs.com

    Sequelize

    For handling multiple databases

    sequelize.org

    TypeScript

    For type checking and compilation

    typescriptlang.org

    Additional Tools

    • Chalk - For colorful console output
    • Inquirer - For user input handling
    • Dotenv - For environment variables

    License

    This project is licensed under the Apache 2.0 License which is a permissive free software license written by the Apache Software Foundation. The license allows users to freely use, modify, and distribute the software.

    View License