test

Constatic

Discord Bot Base

Conventions

Development standards for this project

You can follow some conventions from this project to develop your discord bot

Folder structure

If you follow the structure established by this project, it will be very easy to get support anywhere, not to mention that your code will be organized and also very semantic.

See below for an overview of how the project is structured.

.env
package.json
tsconfig.json
README.md
settings.json

All the following folders are inside src

Discord folder

The structures of this base such as the Command, Event and Responder classes need to be in a file that is imported before the bot to init, and everything in the src/discord folder and its subfolders will be imported before of the bot to init, thus loading all structures

Settings folder

This contains essential files for the operation of the project, such as definitions of environment variable schemes, global variables, error handlers, typing files, etc.

Database folder

This folder contains all the configuration and models of the database chosen when generating the project. See more here


ES6 Modules

This base uses "type": "module" in package.json. It is important to remember to use the .js extension when importing files with relative paths (even if they are typescript files).

If you export a function from some typescript file

src/functions/math/mycustumfunc.ts
export function sum(a: number, b: number){
    return a + b;
}

You should import by placing the .js extension at the end

src/functions/index.ts
import { sum } from "./math/mycustumfunc.js"

We can also use the await keyword at the top level of the code

hello.ts
import { setTimeout } from "node:timers/promises"
 
console.log("Hello");
await setTimeout(4000);
console.log("World");

Import alias

In this project you will find the NodeJs feature named import alias. You can import anything using import alias in package.json

With this you can export everything from an index file of these alias and easily import anywhere in your code. See the example below:

Let's export this simple function from the functions folder

src/functions/math.ts
export function sum(a: number, b: number){
  return a + b;
}

Let's export it in the index file of the functions folder, which is defined in the package.json and tsconfig.json files

src/functions/index.ts
export * from "./math.js"

Note that as this project uses the module type, we need to add the .js extension at the end. With this we can easily import this function into a file of any depth in our code

src/discord/commands/admin/context/test.ts
import { sum } from "#functions"

Without this it would be necessary to use a relative path. See how it would look:

src/discord/commands/admin/context/test.ts
import { sum } from "../../../../../functions/math.js"

In short, import alias make it easier to import anything and make your code more readable and organized.


Env file

With new versions of NodeJs we can use the --env-file flag to indicate an environment variable file for our project

node --env-file .env ./dist/index.js

Running the project with this flag in the script, the process.env object will contain all the variables defined in the .env file at the project root.

You can have two env files in your project and choose which one to use through the pre-defined scripts

package.json
{
  // ...
  "scripts":{
    "dev": "tsx --env-file .env ./src/index.ts",
    "dev:dev": "tsx --env-file .env.dev ./src/index.ts",
  }
}

If you have a .env.dev file you can run the dev:dev script

npm run dev:dev

This is the same for all other scripts

npm run start:dev
npm run watch:dev

So you can have development and production environment variables

Global vars

There are global constant variables that you can use in method or function options objects, also using the "short syntax".

These are variables with the same name as very common properties when we are creating commands and systems for our discord bot. When we use these properties that are normally optional, we set a default value for them

For example, the ephemeral property, this prop is often used when we want to make the message private only to the interaction user, however, all interaction responses are not ephemeral by default, so most of the time we define the response as ephemeral, this property will be true. On this base we have it as a global variable and we can use it as a "short syntax" in the reply method options object

command.ts
interaction.deferReply({  }); // ephemeral is true by default;

This is the file that contains the global variables

//src/settings/global.ts
Object.assign(globalThis, {
 ephemeral: true // Interaction reply property
 // ...
});
 
declare global {
 const ephemeral: true;
 // ...
}

This way, it is not necessary to import these variables as they have global visibility.


On this page