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:
// 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;
Legal Handling
Create your own Privacy Policy and Terms of Service embed. People must accept them before using the bot. The data will dynamically be stored in your preferred database.
{
"privacy-policy": {
"title": "Example Embed",
"description": "This is a full embed showcasing multiple fields and styling options.",
"url": "https://example.com",
"color": 0x1ABC9C, // Hex literal for color (#1ABC9C)
// Embed authorship
"author": {
"name": "Author Name",
"url": "https://example.com",
"icon_url": "https://example.com/author-icon.png"
},
// Embed images
"thumbnail": {
"url": "https://example.com/thumbnail.png"
},
"image": {
"url": "https://example.com/large-image.png"
},
// Timestamp in ISO8601 format
"timestamp": "2025-01-13T00:00:00.000Z",
// Footer text and icon
"footer": {
"text": "Footer text here",
"icon_url": "https://example.com/footer-icon.png"
},
// Fields: short sections in the embed; can be inline or block
"fields": [
{
"name": "Regular Field",
"value": "Some value here",
"inline": false
},
{
"name": "Inline Field 1",
"value": "Some value here",
"inline": true
},
{
"name": "Inline Field 2",
"value": "Some value here",
"inline": true
}
]
},
"terms-of-service": {
"title": "Example Embed",
"description": "This is a full embed showcasing multiple fields and styling options.",
"url": "https://example.com",
"color": 0x1ABC9C, // Hex literal for color (#1ABC9C)
// Embed authorship
"author": {
"name": "Author Name",
"url": "https://example.com",
"icon_url": "https://example.com/author-icon.png"
},
// Embed images
"thumbnail": {
"url": "https://example.com/thumbnail.png"
},
"image": {
"url": "https://example.com/large-image.png"
},
// Timestamp in ISO8601 format
"timestamp": "2025-01-13T00:00:00.000Z",
// Footer text and icon
"footer": {
"text": "Footer text here",
"icon_url": "https://example.com/footer-icon.png"
},
// Fields: short sections in the embed; can be inline or block
"fields": [
{
"name": "Regular Field",
"value": "Some value here",
"inline": false
},
{
"name": "Inline Field 1",
"value": "Some value here",
"inline": true
},
{
"name": "Inline Field 2",
"value": "Some value here",
"inline": true
}
]
}
}
Credits
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