A powerful Discord bot commands, events, and components handler, fully written in TypeScript and has many typings features. Horizon Handler provides simple Discord application commands handler, supports custom options and custom arguments for listeners.
Important This package is not a part of discord.js and it's completely a separate 3ʳᵈ party package.
Collection
from discord.js).Warning If you're using TypeScript, you must install the package typescript v5.1.6 or newer.
After you meet all the requirements, you can install the package.
npm install horizon-handler
yarn add horizon-handler
pnpm add horizon-handler
Documentation: Click here
Source (GitHub): Click here
Issues: Click here
Pull requests: Click here
This is an example usage written in TypeScript. To skip this, use the CLI commands: Click here
Example Bot
├─── src
│ ├─── index.ts
│ ├─── events
│ │ └─── ready.ts
│ │ └─── interactionCreate.ts
│ └─── commands
│ └─── Utility
│ └─── ping.ts
├─── package.json
└─── tsconfig.json
Note For this example, the out directory name is dist. You can change it at anytime, but make sure that the path directory name from CommandsHandler, EventsHandler, and/or ComponentsHandler constructor parameter are also renamed to the new one.
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"outDir": "dist",
"strict": true
},
"include": [
"src"
],
"exclude": [
"node_modules",
"dist"
]
}
index.ts
)import { Client } from 'discord.js';
const client = new Client({
intents: [
'Guilds'
]
});
client.login('Your bot token goes here');
index.ts
)import { CommandsHandler, Events, EventsHandler } from 'horizon-handler';
export const cmdshandler = new CommandsHandler<Client>('./dist/commands/', true);
cmdshandler.on(Events.FileLoad, (command) => console.log(`Loaded new command: ` + command.name));
export const eventshandler = new EventsHandler<Client>('./dist/events/');
eventshandler.on(Events.FileLoad, (event) => console.log(`Loaded new event: ` + event));
(async () => {
await cmdshandler.load();
await eventshandler.load(client);
})();
ping.ts
)import { SlashCommandBuilder } from 'discord.js';
import { CommandType } from 'horizon-handler';
import { cmdshandler } from '../../index';
export default new cmdshandler.command({
type: CommandType.ChatInput,
structure: new SlashCommandBuilder()
.setName('ping')
.setDescription('Replies with Pong!'),
run: async (client, interaction) => {
await interaction.reply({
content: 'Pong!'
});
}
});
ready.ts
)import { eventshandler, cmdshandler } from '../index';
export default new eventshandler.event({
event: 'ready',
once: true,
run: async (_, client) => {
console.log(`Logged in as: ` + client.user.displayName);
await cmdshandler.deploy(client);
}
});
interactionCreate.ts
)import { eventshandler, cmdshandler } from '../index';
export default new eventshandler.event({
event: 'interactionCreate',
run: (client, interaction) => {
if (!interaction.isChatInputCommand()) return;
const command = cmdshandler.collection.get(interaction.commandName);
if (!command || command.type !== 1) return;
try {
command.run(client, interaction);
} catch (e) {
console.error(e);
};
}
});
npx horizon-handler
hhandler [command] [options] <path>
Command | Arguments | Options | Description |
---|---|---|---|
js-example | path: string | --token: string | Create a new project for a Discord bot, written in JavaScript. |
ts-example | path: string | --token: string | Create a new project for a Discord bot, written in TypeScript. |
links | - | - | View all possible useful and informative links of this package. |
about | - | - | About Horizon Handler. |
To set your bot token in the JavaScript or TypeScript example, use the option --token
with the argument with type of string.
hhandler [ts-example/js-example] <path> --token 'Your bot token'
This package uses three libraries for the CLI commands: commander, fs-extra, and colors. Install them globally:
npm install -g commander fs-extra colors
By default, the handler will make all properties in O
(Type parameter for custom options) optional.
import { Client } from 'discord.js';
interface Options {
option1: string,
option2: number,
option3: (string | number)[],
option4: (...args: any[]) => void,
option5: { suboption: string }
};
new CommandsHandler<Client, Options>(...);
Warning Make sure to emit these events from Client using the method emit(...) so they will be able to listen.
import { Client, ClientEvents } from 'discord.js';
type CustomEvents = {
a: [x: string, y: number],
b: [z: { }, w: any, string],
c: [string, number, any, { }, void, unknown, []]
};
new EventsHandler<Client, keyof ClientEvents, CustomEvents>(...);
export default new [handler].customevent(...);
import { Client } from 'discord.js';
type Args = [
x: string,
y: number,
z?: any // ← Optional because of the question mark (?)
];
new CommandsHandler<Client, { }, Args>(...);
Note This example is continued with the Example usage: Click here
Create a new interactionCreate
event file for autocomplete interactions:
import { eventshandler, collection } from "../index";
export default new eventshandler.event({
event: 'interactionCreate',
run: async (client, interaction) => {
if (!interaction.isAutocomplete()) return;
const command = collection.get(interaction.commandName);
if (!command || command.type !== 1) return;
try {
if (command.autocomplete) command.autocomplete(client, interaction);
} catch (e) {
console.error(e);
};
}
});
Create a command example with autocomplete option:
import { SlashCommandBuilder } from 'discord.js';
import { CommandType } from 'horizon-handler';
import { cmdshandler } from '../../index';
export default new cmdshandler.command({
type: CommandType.ChatInput,
structure: new SlashCommandBuilder()
.setName('autocomplete-command')
.setDescription('An autocomplete interaction command!')
.addStringOption((opt) =>
opt.setName('guild')
.setDescription('Choose a server.')
.setAutocomplete(true)
.setRequired(true)
),
run: async (client, interaction) => {
const guild = interaction.options.getString('guild', true);
await interaction.reply({
content: 'You choosed: ' + guild
});
},
autocomplete: async (client, interaction) => {
const focused = interaction.options.getFocused();
const guilds = client.guilds.cache.map((guild) => guild.name);
const filtered = guilds.filter((choice) => choice.startsWith(focused));
await interaction.respond(
filtered.map(
(choice) => ({ name: choice, value: choice })
)
);
}
});
Need any help? Join our Discord server, report to us the problem, and we will solve it for you!
The MIT License. (View here)
Generated using TypeDoc