├── .gitignore
├── .env.example
├── .gitattributes
├── models
└── user.js
├── structures
├── EventClass.js
├── Functions.js
├── CommandClass.js
└── Client.js
├── index.js
├── events
├── guild
│ └── interactionCreate.js
└── client
│ └── ready.js
├── package.json
├── handlers
├── Event.js
└── Command.js
├── commands
└── general
│ └── test.js
├── README.md
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | /node_modules
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | TOKEN=
2 | GUILD_ID=
3 | MONGO_URI=
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/models/user.js:
--------------------------------------------------------------------------------
1 | const Mongoose = require("mongoose");
2 |
3 | // Example of a schema for a user.
4 | const UserSchema = new Mongoose.Schema({
5 | _id: {
6 | type: String,
7 | },
8 | });
9 |
10 | module.exports = Mongoose.model("User", UserSchema);
11 |
--------------------------------------------------------------------------------
/structures/EventClass.js:
--------------------------------------------------------------------------------
1 | // Do not touch this unless you know what you are doing.
2 |
3 | module.exports = class Event {
4 | constructor(client, options = {}) {
5 | this.client = client;
6 | this.name = options.name;
7 | }
8 |
9 | async run() {
10 | throw new Error(`The Event "${this.name}" does not provide a run method.`);
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/structures/Functions.js:
--------------------------------------------------------------------------------
1 | /*
2 | Use this file to store functions that you want to use in multiple files in your bot.
3 | Example of a function that checks if an interaction exists.
4 | */
5 |
6 | module.exports = {
7 | interactionExists: async (client, message) => {
8 | const channel = client.channels.cache.get(message.channel.id);
9 | try {
10 | await channel.messages.fetch(message.id);
11 | return true;
12 | } catch (err) {
13 | return false;
14 | }
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/structures/CommandClass.js:
--------------------------------------------------------------------------------
1 | // Do not touch this unless you know what you are doing.
2 |
3 | module.exports = class Command {
4 | constructor(client, meta = {}) {
5 | this.client = client;
6 | this.name = meta.name;
7 | this.type = meta.type;
8 | this.options = meta.options || [];
9 | this.isModal = meta.isModal || false;
10 | this.category = meta.category || null;
11 | this.description = meta.description || null;
12 | }
13 |
14 | async run() {
15 | throw new Error(
16 | `The Slash Command "${this.name}" does not provide a run method.`
17 | );
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | Name: index.js
3 | Path: /
4 | Description: This is the main file of the bot. It is the entry point of the bot.
5 | Author: carvethedegen
6 | Version: 1.0.0
7 | License: Apache-2.0
8 |
9 | Instructions:
10 | 1. Install the required packages with npm install.
11 | 2. Create a .env file in the root directory of the bot.
12 | 3. Add the following to the .env file:
13 | TOKEN=YOUR_BOT_TOKEN
14 | GUILD_ID=YOUR_GUILD_ID
15 | MONGO_URI=YOUR_MONGO_URI
16 | 4. Run the bot with node index.js
17 | */
18 |
19 | require("dotenv").config();
20 |
21 | const Client = require("./structures/Client");
22 |
23 | const client = new Client();
24 |
25 | client.login();
26 |
--------------------------------------------------------------------------------
/events/guild/interactionCreate.js:
--------------------------------------------------------------------------------
1 | const Discord = require("discord.js");
2 | const Event = require("../../structures/EventClass");
3 |
4 | module.exports = class InteractionCreate extends Event {
5 | constructor(client) {
6 | super(client, {
7 | name: "interactionCreate",
8 | });
9 | }
10 | async run(interaction) {
11 | if (interaction.type === Discord.InteractionType.ApplicationCommand) {
12 | const command = this.client.commands.get(interaction.commandName);
13 |
14 | if (!command) return;
15 |
16 | try {
17 | if (!command.isModal) {
18 | await interaction.deferReply();
19 | }
20 | command.run(this.client, interaction);
21 | } catch (e) {
22 | console.log(e);
23 | }
24 | }
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/structures/Client.js:
--------------------------------------------------------------------------------
1 | // This is the main client file for the bot.
2 |
3 | const Discord = require("discord.js");
4 | const EventHandler = require("../handlers/Event");
5 | const Mongoose = require("mongoose");
6 |
7 | module.exports = class BotClient extends Discord.Client {
8 | constructor(...opt) {
9 | super({
10 | opt,
11 | intents: 131071,
12 | });
13 |
14 | this.events = new Discord.Collection();
15 | this.commands = new Discord.Collection();
16 | new EventHandler(this).build("../events");
17 | }
18 |
19 | async login() {
20 | // Connect to MongoDB
21 | // If you don't want to use MongoDB, remove this or comment it out.
22 | await Mongoose.connect(process.env.MONGO_URI)
23 | .then(() => console.log("MongoDB Connected."))
24 | .catch((err) => console.log(err));
25 |
26 | await super.login(process.env.TOKEN);
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "djs-14-framework",
3 | "version": "1.0.0",
4 | "description": "A framework to build discord bots on the most recent DJS version.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "npm run test"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/carvethedegen/djs-14-framework.git"
12 | },
13 | "keywords": [
14 | "discordbot",
15 | "discord",
16 | "djs",
17 | "framework"
18 | ],
19 | "author": "carvethedegen",
20 | "license": "Apache-2.0",
21 | "bugs": {
22 | "url": "https://github.com/carvethedegen/djs-14-framework/issues"
23 | },
24 | "homepage": "https://github.com/carvethedegen/djs-14-framework#readme",
25 | "dependencies": {
26 | "discord.js": "^14.7.1",
27 | "dotenv": "^16.0.3",
28 | "fs": "^0.0.1-security",
29 | "mongoose": "^6.10.0",
30 | "path": "^0.12.7"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/handlers/Event.js:
--------------------------------------------------------------------------------
1 | // This is the event handler, it will load all the events in the events folder.
2 |
3 | const fs = require("fs");
4 | const path = require("path");
5 | const BaseEvent = require("../structures/EventClass");
6 |
7 | module.exports = class EventClass {
8 | constructor(client) {
9 | this.client = client;
10 | }
11 |
12 | async build(dir) {
13 | const filePath = path.join(__dirname, dir);
14 | const files = await fs.promises.readdir(filePath);
15 | for (const file of files) {
16 | const stat = await fs.promises.lstat(path.join(filePath, file));
17 | if (stat.isDirectory()) this.build(path.join(dir, file));
18 | if (file.endsWith(".js")) {
19 | const Event = require(path.join(filePath, file));
20 | if (Event.prototype instanceof BaseEvent) {
21 | const event = new Event(this.client);
22 | this.client.events.set(event.name, event);
23 | this.client.on(event.name, event.run.bind(event));
24 | }
25 | }
26 | }
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/commands/general/test.js:
--------------------------------------------------------------------------------
1 | // This is a command that has subcommands.
2 |
3 | const Discord = require("discord.js");
4 | const Command = require("../../structures/CommandClass");
5 |
6 | module.exports = class Test extends Command {
7 | constructor(client) {
8 | super(client, {
9 | name: "test",
10 | isModal: false,
11 | category: "General",
12 | type: Discord.ApplicationCommandType.ChatInput,
13 | description: "Test command.",
14 | options: [
15 | {
16 | name: "meow",
17 | description: "meow command.",
18 | type: Discord.ApplicationCommandOptionType.Subcommand,
19 | },
20 | {
21 | name: "bark",
22 | description: "woof command",
23 | type: Discord.ApplicationCommandOptionType.Subcommand,
24 | },
25 | ],
26 | });
27 | }
28 |
29 | async run(client, interaction) {
30 | if (interaction.options.getSubcommand() === "meow") {
31 | interaction.editReply("Meow...");
32 | } else if (interaction.options.getSubcommand() === "bark") {
33 | interaction.editReply("Woof!");
34 | }
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/events/client/ready.js:
--------------------------------------------------------------------------------
1 | // This is the file called when the bot logs in with the token from your .env file.
2 |
3 | const Event = require("../../structures/EventClass");
4 | const CommandHandler = require("../../handlers/Command");
5 | const { ActivityType } = require("discord.js");
6 |
7 | module.exports = class ReadyEvent extends Event {
8 | constructor(client) {
9 | super(client, {
10 | name: "ready",
11 | });
12 | }
13 |
14 | async run() {
15 | // This is the code that loads all the slash commands.
16 | const guild = this.client.guilds.cache.get(process.env.GUILD_ID);
17 | await guild.members.fetch();
18 | await new CommandHandler(this.client)
19 | .build("../commands")
20 | .then(() => console.log("Slash commands loaded."));
21 | console.log(`${this.client.user.tag} is online.`);
22 |
23 | // Set the bot's presence.
24 | // You can change the status and activity type.
25 | this.client.user.setPresence({
26 | activities: [
27 | {
28 | name: `For your commands...`,
29 | type: ActivityType.Watching,
30 | },
31 | ],
32 | status: "dnd",
33 | });
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/handlers/Command.js:
--------------------------------------------------------------------------------
1 | // This is the command handler for slash commands (interactions), it will load all the commands in the commands folder.
2 |
3 | const fs = require("fs");
4 | const path = require("path");
5 | const BaseCommand = require("../structures/CommandClass");
6 |
7 | module.exports = class CommandClass {
8 | constructor(client) {
9 | this.client = client;
10 | }
11 |
12 | async build(dir) {
13 | try {
14 | const filePath = path.join(__dirname, dir);
15 | const files = await fs.promises.readdir(filePath);
16 | for (const file of files) {
17 | const stat = await fs.promises.lstat(path.join(filePath, file));
18 | if (stat.isDirectory()) this.build(path.join(dir, file));
19 | if (file.endsWith(".js")) {
20 | const Command = require(path.join(filePath, file));
21 | if (Command.prototype instanceof BaseCommand) {
22 | const cmd = new Command(this.client);
23 | await this.client.commands.set(cmd.name, cmd);
24 | await this.client.guilds.cache
25 | .get(process.env.GUILD_ID)
26 | .commands.create(cmd);
27 | }
28 | }
29 | }
30 | } catch (e) {
31 | console.log(e);
32 | }
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | A Discord.JS v14 framework that allows you to create advanced discord bots without having to create everything from scratch. 10 |
11 |