npm install @discord-fp/djs
Try our template which includes everything you need
Create Discord.js client
utils/discord.ts
import { Client, GatewayIntentBits } from "discord.js";
export const client = new Client({ intents: [GatewayIntentBits.Guilds] });
Init Discord-FP
utils/dfp.ts
import { initDiscordFP } from "@discord-fp/djs";
import { client } from "./discord";
export const dfp = initDiscordFP();
export const command = dfp.command;
Start Discord-FP after the bot is ready
index.ts
import { client } from "./utils/discord";
import { dfp } from "./utils/dfp";
client.on("ready", () => {
dfp.start({
//the discord.js client
client,
//where to load commands
load: ["./commands"],
});
});
client.login("token");
Create a file inside the folder
Since it's file-system based, command name is same as its file name
commands/hello.ts
import { command } from "@/utils/dfp";
export default command.slash({
description: "Say Hello World",
execute: async ({ event }) => {
await event.reply(`Hello World`);
},
});
Start your bot, and run the slash command in Discord
Then you should see the bot replied "Hello World"!
You may use command group & sub command for grouping tons of commands
-
Create a folder
-
Create a
_meta.ts
/meta.js
file -
Define information for the command group in the
_meta
fileimport { command } from "@/utils/dfp"; export default command.group({ description: "My Command group", });
-
Create commands inside the folder
Inside the folder, Only slash commands are supportedimport { command } from "@/utils/dfp"; import { options } from "@discord-fp/djs"; export default command.slash({ description: "Say Hello World", execute: async ({ event, options }) => { await event.reply(`Hello World`); }, });
You may create a _meta
file for controling how the folder being loaded
For example, Command group is just a type of loader
import { command } from "@/utils/dfp";
//loader
export default command.group({
description: "My Command group",
});
Discord-FP provides type-safe middlewares & context with high code quality
On the Discord-FP init script:
utils/dfp.ts
import { initDiscordFP } from "@discord-fp/djs";
import { client } from "./discord.js";
export const dfp = initDiscordFP({
client,
});
export const command = dfp.command;
//new middleware
export const protectedCommand = dfp.command.middleware(({ event, next }) => {
//check permissions
return next({
ctx: {
message: "hello world",
},
event,
});
});
Now create a slash command with the middleware enabled:
import { protectedCommand } from "@/utils/dfp";
export default protectedCommand.slash({ ... })
You can prevent calling the event handler by returning nothing
dfp.command.middleware(({ event, next }) => {
if (isInvalid(event)) return;
return next({
ctx: {
message: "context here",
},
event,
});
});
Discord-FP also allows you to create nested middlewares
export const memberCommand = dfp.command.middleware(({ event, next }) => {
return next({
event,
ctx: "Hello World",
});
});
export const adminCommand = memberCommand.middleware(({ event, next, ctx }) => {
//ctx === "Hello World"
//...
});
We provides type-safe options out-of-the-box
import { options } from "@discord-fp/djs";
options.string({
description: "Your name",
required: false,
});
Enable auto-complete easily
options.string({
description: "Your name",
required: false,
autoComplete(e) {
const items = ["hello", "world"];
const v = e.options.getFocused();
e.respond(result);
},
});
Make your code even better with transform
options.string({
description: "Your name",
require: true,
}).transform((v) => {
return `Mr.${v}`;
}),
//Transform "Henry" -> "Mr.Henry"