mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-03 09:20:08 +00:00
Update Step By Step
- Changed code to use latest Discordeno Boilerplate features. - Correct deprecated imports. - Change Links to use the new documentation. - Change order of files Changed some more things too
This commit is contained in:
@@ -65,9 +65,9 @@ module.exports = {
|
||||
"/stepbystep/createbot",
|
||||
"/stepbystep/createcommand",
|
||||
"/stepbystep/createevent",
|
||||
"/stepbystep/createinhibitor",
|
||||
"/stepbystep/createlanguage",
|
||||
"/stepbystep/createmonitor",
|
||||
"/stepbystep/createinhibitor",
|
||||
"/stepbystep/createtask",
|
||||
"/stepbystep/hostingbot",
|
||||
],
|
||||
|
||||
@@ -68,7 +68,7 @@ export const configs = {
|
||||
|
||||
#### Token
|
||||
|
||||
First, add your bot token. This is **required** for the bot to start. Review the [instructions](https://discordeno.netlify.app/gettingstarted#creatingyourfirstdiscordbotapplication) if you have not made your token yet.
|
||||
First, add your bot token. This is **required** for the bot to start. Review the [instructions](https://discordeno.mod.land/gettingstarted.html#creating-your-first-discord-bot-application) if you have not made your token yet.
|
||||
|
||||
#### Prefix
|
||||
|
||||
|
||||
@@ -10,8 +10,9 @@ Let's first start by taking an existing command and slightly modifying it to you
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { sendMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/channel.ts";
|
||||
import { botID } from "https://x.nest.land/Discordeno@9.0.1/src/module/client.ts";
|
||||
import { createCommand } from "../utils/helpers.ts"
|
||||
|
||||
botCache.commands.set("invite", {
|
||||
createCommand({
|
||||
name: "invite",
|
||||
execute: function (message) {
|
||||
// Replace the permission number at the end to request the permissions you wish to request. By default, this will request Admin perms.
|
||||
@@ -23,25 +24,23 @@ botCache.commands.set("invite", {
|
||||
});
|
||||
```
|
||||
|
||||
Let's break this down. The first three lines are importing the necessary things from their files so we can use them in this command. Don't worry if this doesn't make sense, most of the time, this will all be done automatically for you if you use a good code editor like Visual Studio Code. We create a command by doing:
|
||||
Let's break this down. The first four lines are importing the necessary things from their files so we can use them in this command. Don't worry if this doesn't make sense, most of the time, this will all be done automatically for you if you use a good code editor like Visual Studio Code. We create a command by doing:
|
||||
|
||||
```ts
|
||||
botCache.commands.set('commandname', {
|
||||
|
||||
createCommand({
|
||||
name: "commandname",
|
||||
})
|
||||
```
|
||||
|
||||
The command name here must be unique. If it is not unique, your commands will not work properly as you wish. For example, you can't have 2 commands with the `ping` name. In this case, our command is called `invite`.
|
||||
|
||||
The `name: 'invite'` is also written as it is useful for our help command and inhibitors! Normally, these two things will be the same. So far it's super easy right.
|
||||
|
||||
Next is the `execute`. This is where the magic happens. This is the function that is triggered when the command is ran by a user. In this case, the bot simply sends a message to a channel where the command was ran and sends an invite link. Let's take a minute and optimize this for our case. We don't **NEED** admin permissions for our bot. Let's go to the [permission calculator](https://discordapi.com/permissions.html#0) and figure out the permissions we need for our bot.
|
||||
Next is the `execute`. This is where the magic happens. This is the function that is triggered when the command is ran by a user. In this case, the bot simply sends a message to a channel where the command was ran and sends an invite link. Let's take a minute and optimize this for our case. We don't **NEED** admin permissions for our bot. Let's go to the [permission calculator](https://discordapi.com/permissions.html) and figure out the permissions we need for our bot.
|
||||
|
||||
Once you have decided which permissions you want to request, you can copy the number and replace it here. For example, if we want `68640` as our permissions. We can modify our command to be:
|
||||
|
||||
|
||||
```ts
|
||||
`https://discordapp.com/oauth2/authorize?client_id=${botID}&scope=bot&permissions=68640`,
|
||||
`https://discordapp.com/oauth2/authorize?client_id=${botID}&scope=bot&permissions=68640`,
|
||||
```
|
||||
|
||||
Lastly, let's get rid of the comment there as now it is customized to our needs.
|
||||
@@ -55,8 +54,8 @@ Right now, if you were to go to Discord and type `!help invite`, you would see q
|
||||
Let's add a custom description to our invite command.
|
||||
|
||||
```ts
|
||||
name: "invite",
|
||||
description: "Like the bot? Use this link to add it to your server!"
|
||||
name: "invite",
|
||||
description: "Like the bot? Use this link to add it to your server!",
|
||||
```
|
||||
|
||||
🎉 It's that simple. So let's restart the bot and see how it changed. Use **CTRL + C** to shut down the bot. Then run the command from earlier.
|
||||
@@ -76,9 +75,9 @@ Now, let's make this a little bit easier. What if we wanted this command to also
|
||||
Let's add in the two aliases we wanted.
|
||||
|
||||
```ts
|
||||
name: "invite",
|
||||
aliases: ["inv", "join"],
|
||||
description: "Like the bot? Use this link to add it to your server!"
|
||||
name: "invite",
|
||||
aliases: ["inv", "join"],
|
||||
description: "Like the bot? Use this link to add it to your server!",
|
||||
```
|
||||
|
||||
> **Note:** If you only want to add 1 alias, you can pass in a simple string instead of an array as well as the second argument.
|
||||
@@ -111,7 +110,7 @@ If you get stuck, don't worry. When you are ready, let's continue to the next st
|
||||
|
||||
## Creating A Command
|
||||
|
||||
Let's make a command that will allow guild admins to give or take roles from a member. Since, we are creating a `Moderation` command to give or take roles, let's go ahead and create a Category folder called `Moderation` and then create a file called `role.ts`. Once the file is made, you can paste this following base snippet to make our first command.
|
||||
Let's make a command that will allow guild admins to give or take roles from a member. Since, we are creating a `Moderation` command to give or take roles, let's go ahead and create a category folder called `Moderation` and then create a file called `role.ts`. Once the file is made, you can paste this following base snippet to make our first command.
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
@@ -119,18 +118,18 @@ import { sendMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/c
|
||||
import { PermissionLevels } from "../types/commands.ts";
|
||||
import { createCommandAliases } from "../utils/helpers";
|
||||
|
||||
botCache.commands.set("commandname", {
|
||||
createCommand({
|
||||
name: "commandname",
|
||||
aliases: [],
|
||||
dmOnly: false,
|
||||
guildOnly: false,
|
||||
nsfw: false,
|
||||
permissionLevel: [PermissionLevels.MEMBER],
|
||||
permissionLevels: [PermissionLevels.MEMBER],
|
||||
botServerPermissions: [],
|
||||
botChannelPermissions: [],
|
||||
userServerPermissions: [],
|
||||
userChannelPermissions: [],
|
||||
description: string,
|
||||
description: "description",
|
||||
cooldown: {
|
||||
seconds: 0,
|
||||
allowedUses: 0,
|
||||
@@ -184,7 +183,7 @@ Discordeno makes this pretty simple for us.
|
||||
permissionLevels: [PermissionLevels.MODERATOR, PermissionLevels.ADMIN]
|
||||
```
|
||||
|
||||
We're not going to cover this in detail, here because we will have an entire in depth guide for permission levels. If you want to pause and learn it now, feel free: [Permission Levels Advanced Guide](https://discordeno.netlify.app/advanced/permlevels)
|
||||
We're not going to cover this in detail here because we will have an entire in depth guide for permission levels. If you want to pause and learn it now, feel free: [Permission Levels Advanced Guide](https://discordeno.mod.land/advanced/permlevels.html)
|
||||
|
||||
## Permissions Check Options
|
||||
|
||||
@@ -214,7 +213,7 @@ The cooldown options go hand in hand together.
|
||||
|
||||
- `seconds` is how long to make the user wait in seconds before they can use the command again. By default, there is no wait time aka 0 seconds.
|
||||
- `allowedUses` is how many times a user is allowed to use a command before they are placed on cooldown.
|
||||
-
|
||||
|
||||
Let's use our command as an example. We don't want someone to start spamming the role command so we can add a cooldown of 60 seconds. However, this would mean every time you give a role to someone, you would need to wait a whole minute to give a role to someone else. This is where `allowedUses` shines! Let's set it to to 5 so that a user can use this command 5 times in a row before being asked to wait for 60 seconds.
|
||||
|
||||
```ts
|
||||
@@ -285,13 +284,13 @@ execute: function (message, args, guild) {
|
||||
> }
|
||||
> ```
|
||||
|
||||
Let's start out by writing some pseudo-code(comments that will help us plan the code).
|
||||
Let's start out by writing some pseudo-code (comments that will help us plan the code).
|
||||
|
||||
```ts
|
||||
execute: function (message, args, guild) {
|
||||
// If this was the everyone role alert with a silly error
|
||||
|
||||
// If this is a managed role(some bots role) we can't give/remove alert with silly error
|
||||
// If this is a managed role (some bots role) we can't give/remove it alert with silly error
|
||||
|
||||
// Get the bots highest role
|
||||
|
||||
@@ -299,8 +298,6 @@ execute: function (message, args, guild) {
|
||||
|
||||
// If the role is too high alert the user.
|
||||
|
||||
// If the user has this role already remove the role from them.
|
||||
|
||||
// Check the command author's highest role
|
||||
|
||||
// If the author does not have a role high enough to give this role alert
|
||||
@@ -330,6 +327,10 @@ if (args.role.id === message.guildID) {
|
||||
You might be seeing an error since we didn't provide the accurate typings for the `args` parameter. The message and guild parameter is automated but the args is dynamic depending on your `arguments` option for your command. So let's do this real quick.
|
||||
|
||||
```ts
|
||||
import { Role, Member } from "../../deps.ts";
|
||||
|
||||
// Lots of code here hidden so you can see the changes easily.
|
||||
|
||||
execute: function (message, args: RoleArgs, guild) {
|
||||
// If this was the everyone role alert with a silly error
|
||||
if (args.role.id === message.guildID) {
|
||||
@@ -339,6 +340,7 @@ execute: function (message, args: RoleArgs, guild) {
|
||||
// Lots of comments here hidden so you can see the changes easily.
|
||||
}
|
||||
|
||||
// Put this at the end of the file.
|
||||
interface RoleArgs {
|
||||
role: Role;
|
||||
member: Member;
|
||||
@@ -349,7 +351,8 @@ Awesome! Let's keep going.
|
||||
|
||||
|
||||
```ts
|
||||
execute: function (message, args: RoleArgs, guild) {
|
||||
// Make the function asynchronous
|
||||
execute: async function (message, args: RoleArgs, guild) {
|
||||
// If this was the everyone role alert with a silly error
|
||||
if (args.role.id === message.guildID) {
|
||||
return sendResponse(message, "I don't know if you noticed or not but I'm an extremely arrogant bot who tends to think all of his plans will work. But I can't give the everyone role to someone.");
|
||||
@@ -393,18 +396,18 @@ execute: function (message, args: RoleArgs, guild) {
|
||||
return sendResponse(message, `The role **${args.role.name}** has been added to **${args.member.tag}**.`)
|
||||
}
|
||||
```
|
||||
> **Note:** Asynchronous functions are an advanced topic, and you do not need to worry about them now. Basically, we need to do that because checking the highest Role requires the use of await.
|
||||
|
||||
The final version of the command should look something like this:
|
||||
|
||||
```ts
|
||||
import { highestRole, higherRolePosition, botID, removeRole, addRole, Role, Member } from "../../deps.ts";
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache, highestRole, higherRolePosition, botID, removeRole, addRole, Role, Member } from "../../deps.ts";
|
||||
import { PermissionLevels } from "../types/commands.ts";
|
||||
import { sendResponse } from "../utils/helpers.ts";
|
||||
import { createCommand, sendResponse } from "../utils/helpers.ts";
|
||||
|
||||
botCache.commands.set("role", {
|
||||
createCommand({
|
||||
name: "role",
|
||||
permissionLevel: [PermissionLevels.MODERATOR, PermissionLevels.ADMIN],
|
||||
permissionLevels: [PermissionLevels.MODERATOR, PermissionLevels.ADMIN],
|
||||
botServerPermissions: ["MANAGE_ROLES"],
|
||||
botChannelPermissions: ["SEND_MESSAGES"],
|
||||
cooldown: {
|
||||
@@ -427,7 +430,7 @@ botCache.commands.set("role", {
|
||||
}
|
||||
}
|
||||
],
|
||||
execute: function (message, args: RoleArgs) {
|
||||
execute: async function (message, args: RoleArgs) {
|
||||
// If this was the everyone role alert with a silly error
|
||||
if (args.role.id === message.guildID) {
|
||||
return sendResponse(
|
||||
@@ -445,7 +448,7 @@ botCache.commands.set("role", {
|
||||
}
|
||||
|
||||
// Get the bots highest role
|
||||
const botsHighestRole = highestRole(message.guildID, botID);
|
||||
const botsHighestRole = await highestRole(message.guildID, botID);
|
||||
|
||||
// Check if the bot has a role higher than the role that it will try to give. If the role is too high alert the user.
|
||||
if (!botsHighestRole || !higherRolePosition(
|
||||
@@ -460,7 +463,7 @@ botCache.commands.set("role", {
|
||||
}
|
||||
|
||||
// Check the command author's highest role
|
||||
const membersHighestRole = highestRole(message.guildID, message.author.id);
|
||||
const membersHighestRole = await highestRole(message.guildID, message.author.id);
|
||||
|
||||
// If the author does not have a role high enough to give this role alert
|
||||
if (!membersHighestRole ||
|
||||
@@ -473,7 +476,7 @@ botCache.commands.set("role", {
|
||||
}
|
||||
|
||||
// If the user has this role already we should remove it
|
||||
if (message.member()?.roles.includes(args.role.id)) {
|
||||
if (message.member?.roles.includes(args.role.id)) {
|
||||
removeRole(
|
||||
message.guildID,
|
||||
args.member.user.id,
|
||||
@@ -504,9 +507,9 @@ interface RoleArgs {
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** The response strings are a play on some funny Stargate(my favorite tv show) moments. Feel free to change as you wish to fit your bot's personality.
|
||||
> **Note:** The response strings are a play on some funny Stargate (my favorite tv show) moments. Feel free to change as you wish to fit your bot's personality.
|
||||
|
||||
## Dynamic(Advanced Level) Command Creation
|
||||
## Dynamic (Advanced Level) Command Creation
|
||||
|
||||
This is some advanced level super magical command creation skills. Discordeno gives you the power to dynamically create commands. What that means is you can write the code for one command but dynamically create like 50 commands using that same code.
|
||||
|
||||
@@ -515,9 +518,8 @@ For example, in my main bot I have a lot of "fun" commands like `.hug` or `.kiss
|
||||
- Create a file in the commands folder called `fun.ts` which will create all our fun commands.
|
||||
|
||||
```ts
|
||||
import { Member, sendMessage, chooseRandom, avatarURL } from "../../deps.ts";
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { createCommandAliases, sendEmbed } from "../utils/helpers.ts";
|
||||
import { botCache, Member, sendMessage, chooseRandom, avatarURL } from "../../deps.ts";
|
||||
import { createCommand, createCommandAliases, sendEmbed } from "../utils/helpers.ts";
|
||||
import { configs } from "../../configs.ts";
|
||||
import { Embed } from "../utils/Embed.ts";
|
||||
import { translate } from "../utils/i18next.ts";
|
||||
@@ -544,7 +546,7 @@ const funCommandData = [
|
||||
];
|
||||
|
||||
funCommandData.forEach((data) => {
|
||||
botCache.commands.set(data.name, {
|
||||
botCache.commands.set({
|
||||
name: data.name,
|
||||
botChannelPermissions: ["SEND_MESSAGES", "EMBED_LINKS"],
|
||||
cooldown: {
|
||||
@@ -559,7 +561,7 @@ funCommandData.forEach((data) => {
|
||||
],
|
||||
execute: function (message, args: FunArgs) {
|
||||
// If a member is provided use that otherwise set the member themself
|
||||
const member = args.member || message.member()!;
|
||||
const member = args.member || message.member!;
|
||||
|
||||
const type = member.user.id === message.author.id
|
||||
// Silly response like if user tries to hug themself
|
||||
@@ -575,7 +577,7 @@ funCommandData.forEach((data) => {
|
||||
translate(
|
||||
message.guildID,
|
||||
`commands/fun/${data.name}:${type}`,
|
||||
{ mention: message.member()!.mention, user: member.mention },
|
||||
{ mention: message.member!.mention, user: member.mention },
|
||||
),
|
||||
)
|
||||
.setImage(chooseRandom(data.gifs));
|
||||
@@ -596,7 +598,9 @@ interface FunArgs {
|
||||
|
||||
> **Note:** The imports in this are a bit different. I did this to show you that you can also import everything grouped like this through the `deps.ts` which will make everything available to you at ease.
|
||||
|
||||
Take a minute to realize what just happened. This has made 18 different unique commands dynamically. In 1 file, using the same piece of code, we created so many commands. You can easily add more commands to this. For example, if you wanted to add weeb(animated) versions of these commands. Then you are at 36 commands with 1 simple command file.
|
||||
> **Note:** This is only an example of dynamic command creation and won't work if you try using this code. Since this is an advanced topic we're not going to cover this in more detail here, because we will have an entire in depth guide for dynamic command creation. If you want to pause and learn it now, feel free: [Dynamic Command Creation Advanced Guide](https://discordeno.mod.land/advanced/dynamiccommands.html)
|
||||
|
||||
Take a minute to realize what just happened. This has made 18 different unique commands dynamically. In 1 file, using the same piece of code, we created so many commands. You can easily add more commands to this. For example, if you wanted to add weeb (animated) versions of these commands. Then you are at 36 commands with 1 simple command file.
|
||||
|
||||
**That ladies and gentleman is the power and magic of Discordeno!**
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ botCache.eventHandlers.ready = function () {
|
||||
};
|
||||
```
|
||||
|
||||
> **Note:** Some of the code from the ready.ts file was removed here to make it easier to understand.
|
||||
|
||||
Overall, this code is pretty self-explanatory. When the bot is ready, it logs all these things to the console for you.
|
||||
|
||||
## Creating A Custom Event
|
||||
@@ -35,7 +37,7 @@ Overall, this code is pretty self-explanatory. When the bot is ready, it logs al
|
||||
Make a new file in the events folder called `discordLog.ts` that will send a message to a discord channel whenever we get an error so we don't need to always be watching the console to see errors. Once you made the file, go ahead and paste the base event snippet below.
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache } from "../../deps.ts";
|
||||
|
||||
botCache.eventHandlers.eventname = function () {
|
||||
// Your code goes here
|
||||
@@ -48,18 +50,16 @@ botCache.eventHandlers.eventname = function () {
|
||||
```ts
|
||||
// This interface is a placeholder that allows you to easily add on custom events for your need.
|
||||
export interface CustomEvents extends EventHandlers {
|
||||
discordLog: () => unknown;
|
||||
discordLog: (error: Error) => unknown;
|
||||
}
|
||||
```
|
||||
|
||||
Awesome, now we can get started on adding the code.
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache, cache, sendMessage } from "../../deps.ts";
|
||||
import { Embed } from "../utils/Embed.ts";
|
||||
import { cache } from "../../deps.ts";
|
||||
import { configs } from "../../configs.ts";
|
||||
import { sendMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/channel.ts";
|
||||
import { sendEmbed } from "../utils/helpers.ts";
|
||||
|
||||
botCache.eventHandlers.discordLog = function (error) {
|
||||
@@ -67,12 +67,12 @@ botCache.eventHandlers.discordLog = function (error) {
|
||||
.setDescription([
|
||||
"```ts",
|
||||
error,
|
||||
"```",
|
||||
"```"
|
||||
].join("\n"))
|
||||
.setTimestamp();
|
||||
|
||||
// Get the channel we need to send this error to
|
||||
const errorChannel = cache.channels.get(configs.channelIDs.errorChannelID);
|
||||
const errorChannel = configs.channelIDs.errorChannelID;
|
||||
// If the channel is not found cancel out
|
||||
if (!errorChannel) return;
|
||||
|
||||
@@ -89,6 +89,7 @@ Now that we have fully covered events, it would be a good time to get some pract
|
||||
channelUpdate?: (channel: Channel, cachedChannel: Channel) => unknown;
|
||||
channelDelete?: (channel: Channel) => unknown;
|
||||
debug?: (args: DebugArg) => unknown;
|
||||
dispatchRequirements?: (data: DiscordPayload, shardID: number) => unknown;
|
||||
guildBanAdd?: (guild: Guild, user: Member | UserPayload) => unknown;
|
||||
guildBanRemove?: (guild: Guild, user: Member | UserPayload) => unknown;
|
||||
guildCreate?: (guild: Guild) => unknown;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Creating Inhibitors!
|
||||
|
||||
Woah! You are almost half way done with understanding all of Discordeno. Amazing isn't it? Something you may have noticed in the last section was there were some options that prevented some commands from running like `dmOnly` or the permission options. we created a setting to prevent the monitor from running in certain channels. What if we wanted to do prevent commands from happening? How would we prevent commands from running?
|
||||
Woah! You are almost half way done with understanding all of Discordeno. Amazing isn't it? Something you may have noticed in the last section was there were some options that prevented some commands from running like `dmOnly` or the permission options. We created a setting to prevent the monitor from running in certain channels. What if we wanted to do prevent commands from happening? How would we prevent commands from running?
|
||||
|
||||
## What is an Inhibitor?
|
||||
|
||||
An Inhibitor is very similar to how monitors work. A monitor runs on every message but an inhibitor runs on every command. Remember all those command options like cooldown, permissions, permissionLevel, nsfw, etc... Each and every one of these options has an inhibitor in that checks commands for these settings.
|
||||
Inhibitors are very similar to how monitors work. A monitor runs on every message but an inhibitor runs on every command. Remember all those command options like cooldown, permissions, permissionLevel, nsfw, etc... each and every one of these options has an inhibitor that checks commands for these settings.
|
||||
|
||||
Let's create our own inhibitor that would prevent commands from being used if the user is not a VIP user.
|
||||
|
||||
@@ -15,7 +15,7 @@ Let's create our own inhibitor that would prevent commands from being used if th
|
||||
Let's start by creating a file inside the inhibitors folder called `boosted.ts` and paste the following snippet of code:
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache } from "../../deps.ts";
|
||||
|
||||
botCache.inhibitors.set("inhibitorname", async function (message, command, guild) {
|
||||
// Your code goes here
|
||||
@@ -64,7 +64,7 @@ return true;
|
||||
Since we need a new option on our commands we need to add that. Open the `src/types/commands.ts` file and add in the following
|
||||
|
||||
```ts
|
||||
vipOnly?: boolean;
|
||||
vipOnly?: boolean;
|
||||
```
|
||||
|
||||
Once that is added, you can go into any command and mark them as vip only commands.
|
||||
@@ -77,4 +77,4 @@ You can now try and get a little more practice with inhibitors by trying to chal
|
||||
|
||||
Majority of Discordeno bots do not use many custom inhibitors because most of the necessary/important ones already come built for you in the inhibitors folder.
|
||||
|
||||
Next we will try our hands at creating a monitor.
|
||||
Next we will try our hands on creating tasks.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Creating Languages!
|
||||
|
||||
Woot! You have mastered Discordeno inhibitors already. Now it's time to finally make our bot multi-lingual. Vàmanos!
|
||||
Woot! You have mastered Discordeno events already. Now it's time to finally make our bot multi-lingual. Vàmanos!
|
||||
|
||||
## What Is A Discordeno Language?
|
||||
|
||||
@@ -8,7 +8,7 @@ A Discordeno language is a folder that will hold all our responses that the bot
|
||||
|
||||
## i18next
|
||||
|
||||
By default, Discordeno comes built with support for i18next(one of if not the best localization libraries). If you want to learn more, go to [i18next website](https://www.i18next.com/). For now, there is probably not going to be anything you will need to learn there. As most of the functionality has already been created for you right here in Discordeno.
|
||||
By default, Discordeno comes built with support for i18next (one of if not the best localization libraries). If you want to learn more, go to [i18next website](https://www.i18next.com/). For now, there is probably not going to be anything you will need to learn there. As most of the functionality has already been created for you right here in Discordeno.
|
||||
|
||||
## Default Language
|
||||
|
||||
@@ -16,7 +16,7 @@ The default language with Discordeno is American English which uses the name `en
|
||||
|
||||
## Understanding The Folder Structure
|
||||
|
||||
The first folder inside the languages folder must be a language folder following the name pattern like `en_US`. So for example, if we wanted to add a Spanish(Spain) language to our bot we would create a new folder called `es_ES`.
|
||||
The first folder inside the languages folder must be a language folder following the name pattern like `en_US`. So for example, if we wanted to add a Spanish (Spain) language to our bot we would create a new folder called `es_ES`.
|
||||
|
||||
You can have as many folder in here as you like. For example I can do something like `src/languages/en_US/commands/fun/hug.json`. Notice that I have created categories to help keep them categorized and easier to find. You can do it however you wish to have them. For now, just remember that files must always be `.json` files in these folders. **JSON is required.**
|
||||
|
||||
@@ -60,7 +60,7 @@ i18next allows you to pass in variables that you can use when you want in your s
|
||||
translate(
|
||||
message.guildID,
|
||||
`commands/fun/${data.name}:${type}`,
|
||||
{ mention: message.member()!.mention, user: member.mention },
|
||||
{ mention: message.member!.mention, user: member.mention },
|
||||
)
|
||||
```
|
||||
|
||||
@@ -71,7 +71,9 @@ Here we can see that we passed in:
|
||||
|
||||
## Variables
|
||||
|
||||
::: v-pre
|
||||
Variables in i18next use the `{{}}` format. So the variable `mention` would be used by doing `{{mention}}`
|
||||
:::
|
||||
|
||||
## Key Rules
|
||||
|
||||
@@ -85,7 +87,7 @@ The first one is the only one that is mandatory. The other two are recommended f
|
||||
|
||||
## Missing Keys
|
||||
|
||||
Every developer forgets stuff sometimes. When you forget to translate a key, it will be marked as a missing key and you will be alerted. If you provided a channelID in the configs file, you be be sent a message there and it will also be logged in your console.
|
||||
Every developer forgets stuff sometimes. When you forget to translate a key, it will be marked as a missing key and you would be alerted if you have provided a channelID in the configs file, and it will also be logged in your console.
|
||||
|
||||
## Spanish Version
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Let's try and create our own monitor so we can understand it better. Suppose we
|
||||
To start, we make a new file in the monitors folder called `inviteFilter.ts`. Then you can paste in the following base monitor snippet.
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache } from "../../deps.ts";
|
||||
|
||||
botCache.monitors.set("monitorname", {
|
||||
name: "monitorname",
|
||||
@@ -64,14 +64,13 @@ The default options were chosen for what the majority of monitors will use to he
|
||||
The permission options are the exact same from the commands guide. These options first make sure that either the bot or user has those necessary permissions to run this monitor. For example, our invite filter would mean we need **MANAGE MESSAGES** permission so we can delete messages sent with an invite URL.
|
||||
|
||||
```ts
|
||||
botChannelPermissions: ["MANAGE_MESSAGES"]
|
||||
botChannelPermissions: ["MANAGE_MESSAGES"]
|
||||
```
|
||||
|
||||
## Adding The Code
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { deleteMessage } from "https://x.nest.land/Discordeno@9.0.1/src/handlers/message.ts";
|
||||
import { botCache, deleteMessage } from "../../deps.ts";
|
||||
import { translate } from "../utils/i18next.ts";
|
||||
import { sendAlertResponse } from "../utils/helpers.ts";
|
||||
|
||||
@@ -104,3 +103,4 @@ botCache.monitors.set("inviteFilter", {
|
||||
```
|
||||
|
||||
Nice! Now take some time and add these translation keys to their appropriate files.
|
||||
Once, you are ready, let's jump into creating some command inhibitors.
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Creating Tasks
|
||||
|
||||
Phenomenal! Now that you have mastered monitors, let's move on to one of the final parts, Tasks. A lot of times, you will want to do something over and over again. To do this, you can use tasks. You could technically just do this with `setInterval` but, with tasks you gain a little more advantage like having reloadability. The functions that are run can be easily reloaded meaning, you don't need to restart your whole bot just for little change.
|
||||
Phenomenal! Now that you have mastered inhibitors, let's move on to one of the final parts, Tasks. A lot of times, you will want to do something over and over again. To do this, you can use tasks. You could technically just do this with `setInterval` but, with tasks you gain a little more advantage like having reloadability. The functions that are run can be easily reloaded meaning, you don't need to restart your whole bot just for little change.
|
||||
|
||||
## What is a Task?
|
||||
|
||||
A task is used to conduct a function every so often. For example, Discordeno comes with a built in task called `botlists`. This task runs every so often and updates your data in all the bot lists apis. Let's create a new task to really understand the gist of it. Let's create a task that will run every 5 minutes which will keep our cache clean and minimal allowing your bot to grow and scale much larger without needing a much bigger server to host it on. Start by pasting the following snippet below:
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache } from "../../deps.ts";
|
||||
import { Milliseconds } from "../utils/constants/time.ts";
|
||||
|
||||
botCache.tasks.set(`taskname`, {
|
||||
@@ -27,7 +27,7 @@ botCache.tasks.set(`taskname`, {
|
||||
|
||||
## What is Cache and Why Should We Sweep It?
|
||||
|
||||
Your bot's cache is the memory it is holding on to since it started. To understand this slightly easier, when you are buying a server to host your bot on you can check how much RAM(memory) it has. That amount of memory can be expensive $$$ so it is best to build a bot that does not use a ton of memory. You can use this task to tell your bot to delete any memory it is holding on to that is not necessary.
|
||||
Your bot's cache is the memory it is holding on to since it started. To understand this slightly easier we have an example: when you buy a server to host your bot on you can check how much RAM (memory) it has. That amount of memory can be expensive $$$ so it is best to build a bot that does not use a ton of memory. You can use this task to tell your bot to delete any memory it is holding on to that is not necessary.
|
||||
|
||||
- Suppose we don't want to keep any presence cached.
|
||||
- Remove any members from cache that have not been active in the last 30 minutes.
|
||||
@@ -36,7 +36,7 @@ Your bot's cache is the memory it is holding on to since it started. To understa
|
||||
## Adding Pseudo Code
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache } from "../../deps.ts";
|
||||
import { Milliseconds } from "../utils/constants/time.ts";
|
||||
|
||||
botCache.tasks.set(`taskname`, {
|
||||
@@ -59,9 +59,8 @@ botCache.tasks.set(`taskname`, {
|
||||
Now that we have a plan in place, let's add the code.
|
||||
|
||||
```ts
|
||||
import { botCache } from "../../mod.ts";
|
||||
import { botCache, cache } from "../../deps.ts";
|
||||
import { Milliseconds } from "../utils/constants/time.ts";
|
||||
import { cache } from "../../deps.ts";
|
||||
|
||||
const MESSAGE_LIFETIME = Milliseconds.MINUTE * 10
|
||||
const MEMBER_LIFETIME = Milliseconds.MINUTE * 30
|
||||
@@ -95,7 +94,7 @@ Alrighty, we managed to add most of the code. But we hit a small obstacle. There
|
||||
|
||||
## Adding Member Activity Tracker
|
||||
|
||||
Let's go to the botCache in `mod.ts` file and add a `new Collection` that will hold the member's id + server id as the key since a member can be in multiple servers. The value for the map will be a timestamp showing when they were last active. We will be able to use this check, how long ago they were last active.
|
||||
Let's go to the botCache in `cache.ts` file and add a `new Collection` that will hold the member's id + server id as the key since a member can be in multiple servers. The value for the map will be a timestamp showing when they were last active. We will be able to use this check, how long ago they were last active.
|
||||
|
||||
```ts
|
||||
memberLastActive: new Collection<string, number>()
|
||||
@@ -135,7 +134,7 @@ botCache.tasks.set(`sweeper`, {
|
||||
guild.presences.clear();
|
||||
// Delete any member who has not been active in the last 30 minutes and is not currently in a voice channel
|
||||
guild.members.forEach((member) => {
|
||||
// The user is currently active in a voice channel
|
||||
// The user is currently active in a voice channel
|
||||
if (guild.voiceStates.has(member.user.id)) return;
|
||||
|
||||
const lastActive = botCache.memberLastActive.get(member.user.id);
|
||||
|
||||
@@ -64,5 +64,5 @@ deno install --allow-read --allow-run --allow-write --allow-net -f -q --unstable
|
||||
Once, that is done you can simply run the bot.
|
||||
|
||||
```shell
|
||||
denon run --allow-read --allow-net mod.ts
|
||||
denon run --allow-net --allow-read --no-check --config tsconfig.json mod.ts
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user