From faed440a7a80bba55fdeb83678bcb859f8a7525b Mon Sep 17 00:00:00 2001 From: ITOH Date: Sat, 5 Dec 2020 21:41:35 +0100 Subject: [PATCH 1/4] 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 --- docs/src/.vuepress/config.js | 2 +- docs/src/stepbystep/createbot.md | 2 +- docs/src/stepbystep/createcommand.md | 88 ++++++++++++++------------ docs/src/stepbystep/createevent.md | 15 +++-- docs/src/stepbystep/createinhibitor.md | 10 +-- docs/src/stepbystep/createlanguage.md | 12 ++-- docs/src/stepbystep/createmonitor.md | 8 +-- docs/src/stepbystep/createtask.md | 15 ++--- docs/src/stepbystep/hostingbot.md | 2 +- 9 files changed, 80 insertions(+), 74 deletions(-) diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js index 65fb00817..f2b4583dd 100755 --- a/docs/src/.vuepress/config.js +++ b/docs/src/.vuepress/config.js @@ -65,9 +65,9 @@ module.exports = { "/stepbystep/createbot", "/stepbystep/createcommand", "/stepbystep/createevent", - "/stepbystep/createinhibitor", "/stepbystep/createlanguage", "/stepbystep/createmonitor", + "/stepbystep/createinhibitor", "/stepbystep/createtask", "/stepbystep/hostingbot", ], diff --git a/docs/src/stepbystep/createbot.md b/docs/src/stepbystep/createbot.md index 056100e45..75d72729b 100644 --- a/docs/src/stepbystep/createbot.md +++ b/docs/src/stepbystep/createbot.md @@ -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 diff --git a/docs/src/stepbystep/createcommand.md b/docs/src/stepbystep/createcommand.md index 999ec099a..c980bb309 100644 --- a/docs/src/stepbystep/createcommand.md +++ b/docs/src/stepbystep/createcommand.md @@ -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!** diff --git a/docs/src/stepbystep/createevent.md b/docs/src/stepbystep/createevent.md index 70631a71c..9c5570e30 100644 --- a/docs/src/stepbystep/createevent.md +++ b/docs/src/stepbystep/createevent.md @@ -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; diff --git a/docs/src/stepbystep/createinhibitor.md b/docs/src/stepbystep/createinhibitor.md index 940981cb8..591a22010 100644 --- a/docs/src/stepbystep/createinhibitor.md +++ b/docs/src/stepbystep/createinhibitor.md @@ -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. diff --git a/docs/src/stepbystep/createlanguage.md b/docs/src/stepbystep/createlanguage.md index ff7c93d82..75d78c3ce 100644 --- a/docs/src/stepbystep/createlanguage.md +++ b/docs/src/stepbystep/createlanguage.md @@ -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 diff --git a/docs/src/stepbystep/createmonitor.md b/docs/src/stepbystep/createmonitor.md index 7f3ed5b59..3dad592d9 100644 --- a/docs/src/stepbystep/createmonitor.md +++ b/docs/src/stepbystep/createmonitor.md @@ -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. diff --git a/docs/src/stepbystep/createtask.md b/docs/src/stepbystep/createtask.md index f0372fddb..76053a56d 100644 --- a/docs/src/stepbystep/createtask.md +++ b/docs/src/stepbystep/createtask.md @@ -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() @@ -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); diff --git a/docs/src/stepbystep/hostingbot.md b/docs/src/stepbystep/hostingbot.md index 24619b404..5312c13f1 100644 --- a/docs/src/stepbystep/hostingbot.md +++ b/docs/src/stepbystep/hostingbot.md @@ -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 ``` From 924f7c0ba5dcda690fb71718c02ff3da4a681474 Mon Sep 17 00:00:00 2001 From: ITOH Date: Sat, 5 Dec 2020 22:33:04 +0100 Subject: [PATCH 2/4] Update Advanced Guide - Changed code to use latest Discordeno Boilerplate features. - Correct deprecated imports. - Change Links to use the new documentation. Changed some more things too --- docs/src/advanced/arguments.md | 14 ++--- docs/src/advanced/dynamiccommands.md | 78 ++++++---------------------- docs/src/advanced/permlevels.md | 50 +++++++++--------- docs/src/advanced/subcommands.md | 16 +++--- 4 files changed, 58 insertions(+), 100 deletions(-) diff --git a/docs/src/advanced/arguments.md b/docs/src/advanced/arguments.md index f5a212694..a69b1d438 100644 --- a/docs/src/advanced/arguments.md +++ b/docs/src/advanced/arguments.md @@ -16,6 +16,8 @@ Discordeno comes with the most useful command arguments already built for you. T - `member` When you want a member object and the user can provide a member id, @mention or their username/nickname. - `number` When you want a number. - `role` When you want a role object. The user can provide the role id, mention or role name. +- `snowflake` When you just want a snowflake. +- `..snowflakes` When you want to check if the mentioned ID is a valid snowflake. - `subcommand` When your command has subcommands. @@ -39,7 +41,7 @@ Suppose you wanted to make it possible so that the boolean argument could accept What if we also wanted to support, `yes` and `no`? Let's open up the `boolean.ts` file in the arguments folder and get started. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; botCache.arguments.set("boolean", { name: "boolean", @@ -55,7 +57,7 @@ botCache.arguments.set("boolean", { Simply update the code so it looks like the following: ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; botCache.arguments.set("boolean", { name: "boolean", @@ -80,7 +82,7 @@ First, we need to update the **CommandArgument** interface in `src/types/command - Once that's done, we can go and create the code for it. Now, lets create a new file in `src/arguments` folder called `url.ts` and paste the base snippet for a command argument below. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; botCache.arguments.set("argumentname", { name: "argumentname", @@ -93,7 +95,7 @@ botCache.arguments.set("argumentname", { First let's change the `argumentname` to be `url`. Then we can start adding the pseudo-code. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; botCache.arguments.set("url", { name: "url", @@ -111,7 +113,7 @@ botCache.arguments.set("url", { Now we can get started. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; botCache.arguments.set("url", { name: "url", @@ -163,6 +165,6 @@ arguments: [ ] ``` -We already covered using the arguments in a command in our guide when we created the role command, so we can skip that here. To re-read that you can check it out [here](https://discordeno.netlify.app/stepbystep/createcommand#arguments). +We already covered using the arguments in a command in our guide when we created the role command, so we can skip that here. To re-read that you can check it out [here](https://discordeno.mod.land/stepbystep/createcommand.html#arguments). Command arguments are an extremely powerful feature that can help make creating bots a lot easier. Discordeno provides extremely flexible command arguments. As a side benefit, command arguments are designed to be hot reloadable from the reload command. 🎉 diff --git a/docs/src/advanced/dynamiccommands.md b/docs/src/advanced/dynamiccommands.md index 209e31b9e..bb52cba04 100644 --- a/docs/src/advanced/dynamiccommands.md +++ b/docs/src/advanced/dynamiccommands.md @@ -15,12 +15,9 @@ Let's create all the commands for the entire Nekos.Life API in a very short time - Create a file in the commands folder called `nekos.ts` which will create all our fun commands. ```ts -import { botCache } from "../../mod.ts"; -import { sendMessage } from "../../deps.ts"; +import { botCache,sendMessage } from "../../deps.ts"; const nekosEndpoints = [ - { name: "spank", path: "/img/spank", nsfw: true }, - { name: "gasm", path: "/img/gasm", nsfw: true }, { name: "tickle", path: "/img/tickle", nsfw: false }, { name: "slap", path: "/img/slap", nsfw: false }, { name: "poke", path: "/img/poke", nsfw: false }, @@ -50,43 +47,7 @@ const nekosEndpoints = [ { name: "gecg", path: "/img/gecg", nsfw: false }, { name: "avatar", path: "/img/avatar", nsfw: false }, { name: "waifu", path: "/img/waifu", nsfw: false }, - // The follow name and paths have been hidden for this guide as they are NSFW. - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, - { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, + // All other paths have been removed for this guide as they are NSFW. { name: "nsfw_endpoint", path: "/img/nsfw_example", nsfw: true }, ]; @@ -98,13 +59,15 @@ nekosEndpoints.forEach((endpoint) => { execute: async function (message) { const url = `https://nekos.life/api/v2${endpoint.path}`; const result = await fetch(url).then((res) => res.json()); - sendMessage(message.channelID, result?.url); + sendMessage(message.channelID, result?.url || result[endpoint.name]); }, }); }); ``` -Take a minute to realize what just happened. This has made 68 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. +> **Note:** We have removed the endpoints that were leading to NSFW content. With them, we would just have created 68 different commands. + +Take a minute to realize what just happened. This has made 29 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. **That ladies and gentleman is the power and magic of Discordeno!** @@ -113,23 +76,13 @@ Take a minute to realize what just happened. This has made 68 different unique c If your still a little confused, don't worry. Let's break it down. ```ts -nekosEndpoints.forEach((endpoint) => { - botCache.commands.set(endpoint.name, { - name: endpoint.name, - nsfw: endpoint.nsfw, - botChannelPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], - execute: async function (message) { - const url = `https://nekos.life/api/v2${endpoint.path}`; - const result = await fetch(url).then((res) => res.json()); - sendMessage(message.channelID, result?.url); - }, - }); -}); +const nekosEndpoints = [ + { name: "tickle", path: "/img/tickle", nsfw: false }, + // ... +] ``` -This is the part where we are doing the magical stuff. So let's take a look at this a bit. Above this we had an array of all the endpoints on the API giving a name, a path, and a boolean to say if it is NSFW or not. - -We ran a loop `nekosEndpoints.forEach()` on that array and for each item in that array, we created a command. +This is just an array of all the endpoints on the API giving a name, a path, and a boolean to say if it is NSFW or not. ```ts botCache.commands.set(endpoint.name, { @@ -139,14 +92,17 @@ botCache.commands.set(endpoint.name, { execute: async function (message) { const url = `https://nekos.life/api/v2${endpoint.path}`; const result = await fetch(url).then((res) => res.json()); - sendMessage(message.channelID, result?.url); + sendMessage(message.channelID, result?.url || result[endpoint.name]); }, }); ``` -For the command name, we used the `endpoint.name` property. For the `nsfw` property we used the `endpoint.nsfw` property. Since all of these commands, send a message that is a URL we simply required those permissions in all 68 of these commands. +This is the part where we are doing the magical stuff. So let's take a look at this a bit. + +We ran a loop `nekosEndpoints.forEach()` on that array and for each item in that array, we created a command. + +For the command name, we used the `endpoint.name` property. For the `nsfw` property we used the `endpoint.nsfw` property. Since all of these commands, send a message that is a URL we simply required those permissions in all 29 of these commands. Then we simply write the code for the commands and it all just works. If you were to reload/restart your bot now with this. You will see that you have access to 68 new commands. Take a minute and try out some of the commands and how they function. - diff --git a/docs/src/advanced/permlevels.md b/docs/src/advanced/permlevels.md index 7870aacc0..be95119f2 100644 --- a/docs/src/advanced/permlevels.md +++ b/docs/src/advanced/permlevels.md @@ -21,7 +21,7 @@ Any of these can be easily modified, in their files. Let's go ahead and try and If you have a bot support server, you might also have a role setup for your bot's support team. So to make life easier, it would be nice if someone with that role could use the command without having to modify the configs file every time. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; import { PermissionLevels } from "../types/commands.ts"; import { configs } from "../../configs.ts"; @@ -38,17 +38,17 @@ Let's add some pseudo-code first. botCache.permissionLevels.set( PermissionLevels.BOT_SUPPORT, async (message) => { - // If the user id exists in the configs allow the command - if (configs.userIDs.botSupporters.includes(message.author.id)) return true - - // The users id was not in the configs, check if they have the role in bot server - - // Get the bots support server - + // If the user id exists in the configs allow the command + if (configs.userIDs.botSupporters.includes(message.author.id)) return true + + // The users id was not in the configs, check if they have the role in bot server + + // Get the bots support server + // If the user is not a member of the support server they can't be one of the support staff. // If they have the role allow the command otherwise it will be false and block the command. - }, + }, ); ``` @@ -58,12 +58,12 @@ Awesome, now that the plan is in place, let's add the code. botCache.permissionLevels.set( PermissionLevels.BOT_SUPPORT, async (message) => { - // If the user id exists in the configs allow the command - if (configs.userIDs.botSupporters.includes(message.author.id)) return true - - // The users id was not in the configs, check if they have the role in bot server - - // Get the bots support server + // If the user id exists in the configs allow the command + if (configs.userIDs.botSupporters.includes(message.author.id)) return true + + // The users id was not in the configs, check if they have the role in bot server + + // Get the bots support server const guild = cache.guilds.get(configs.supportServerID) if (!guild) return false @@ -73,7 +73,7 @@ botCache.permissionLevels.set( // If they have the role allow the command otherwise it will be false and block the command. return member.roles.includes('BOT_SUPPORT_ROLE_ID_HERE') - }, + }, ); ``` @@ -101,8 +101,8 @@ Let's add a new one for a Nitro Booster role. You can add it in any order here y ```ts export enum PermissionLevels { - MEMBER, - NITRO_BOOSTER, + MEMBER, + NITRO_BOOSTER, MODERATOR, ADMIN, SERVER_OWNER, @@ -115,19 +115,19 @@ export enum PermissionLevels { Once that's done, we can go and create the code for it. Now, lets create a new file in `permissionLevels` folder called `booster.ts` and paste the base snippet for a permission level below. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; import { PermissionLevels } from "../types/commands.ts"; import { configs } from "../../configs.ts"; botCache.permissionLevels.set( PermissionLevels, async (message) => { - // Code goes here - } + // Code goes here + } ); ``` -**NOTE:** You will see an error in the `PermissionLevels,` line because we need to select one of the permission levels. In this case we want the NITRO_BOOSTER level we just created above. +> **NOTE:** You will see an error in the `PermissionLevels,` line because we need to select one of the permission levels. In this case we want the NITRO_BOOSTER level we just created above. ```ts PermissionLevels.NITRO_BOOSTER @@ -136,7 +136,7 @@ PermissionLevels.NITRO_BOOSTER Next we can add the code in place. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; import { PermissionLevels } from "../types/commands.ts"; import { configs } from "../../configs.ts"; @@ -164,7 +164,7 @@ Awesome! You just created your very own permission level. Now let's check out ho There are two ways to use permission levels. You can provide an array of PermissionLevels or you can provide a custom function. ```ts -botCache.commands.set(`reload`, { +createCommand({ name: `reload`, permissionLevels: [PermissionLevels.BOT_OWNER], botChannelPermissions: ["SEND_MESSAGES"], @@ -185,7 +185,7 @@ If you provide an array of permission levels, only one of these is necessary to There is another way to use permission levels. You can provide a custom function that must return a boolean. For example, ```ts -botCache.commands.set(`example`, { +createCommand({ name: `example`, permissionLevels: (message, command, guild) => { // Anything you'd like to check here and return a boolean. Must return true or false. diff --git a/docs/src/advanced/subcommands.md b/docs/src/advanced/subcommands.md index 7ab7ef288..93def018c 100644 --- a/docs/src/advanced/subcommands.md +++ b/docs/src/advanced/subcommands.md @@ -9,14 +9,14 @@ A subcommand can have it's own settings for example, you can allow 1 subcommand Let's start by understanding the `prefix` command which uses subcommands. It is a good basic example, to help us understand how to create a subcommand. ```ts -import { botCache } from "../../mod.ts"; +import { botCache } from "../../deps.ts"; import { PermissionLevels } from "../types/commands.ts"; -import { sendResponse, sendEmbed, createSubcommand } from "../utils/helpers.ts"; +import { sendResponse, sendEmbed, createSubcommand, createCommand } from "../utils/helpers.ts"; import { parsePrefix } from "../monitors/commandHandler.ts"; import { Embed } from "../utils/Embed.ts"; // This command will only execute if there was no valid sub command: !prefix -botCache.commands.set("prefix", { +createCommand({ name: "prefix", arguments: [ { @@ -31,7 +31,7 @@ botCache.commands.set("prefix", { const embed = new Embed() .setTitle("Prefix Information") .setDescription(` - **Guild**: \`${message.guild()?.name}\` + **Guild**: \`${message.guild?.name}\` **Current Prefix**: \`${parsePrefix(message.guildID)}\` `) .setTimestamp(); @@ -49,7 +49,7 @@ createSubcommand("prefix", { type: "string", required: true, missing: (message) => { - sendResponse(message, `${message.member()} please provid a prefix`); + sendResponse(message, `${message.member} please provid a prefix`); }, }, ], @@ -78,7 +78,7 @@ createSubcommand("prefix", { Let's separate this to understand what is happening here. The first half of the code is the main command. This is like any other command. However, the important thing is in the arguments we requested a subcommand! ```ts -botCache.commands.set("prefix", { +createCommand({ name: "prefix", arguments: [ { @@ -93,7 +93,7 @@ botCache.commands.set("prefix", { const embed = new Embed() .setTitle("Prefix Information") .setDescription(` - **Guild**: \`${message.guild()?.name}\` + **Guild**: \`${message.guild?.name}\` **Current Prefix**: \`${parsePrefix(message.guildID)}\` `) .setTimestamp(); @@ -115,7 +115,7 @@ createSubcommand("prefix", { type: "string", required: true, missing: (message) => { - sendResponse(message, `${message.member()} please provid a prefix`); + sendResponse(message, `${message.member} please provid a prefix`); }, }, ], From 61e86a44e8be6a35c5ff2c03bc72c2f826a914e0 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Sat, 5 Dec 2020 23:06:35 +0100 Subject: [PATCH 3/4] Update arguments.md --- docs/src/advanced/arguments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/advanced/arguments.md b/docs/src/advanced/arguments.md index a69b1d438..4c0dc6291 100644 --- a/docs/src/advanced/arguments.md +++ b/docs/src/advanced/arguments.md @@ -16,8 +16,8 @@ Discordeno comes with the most useful command arguments already built for you. T - `member` When you want a member object and the user can provide a member id, @mention or their username/nickname. - `number` When you want a number. - `role` When you want a role object. The user can provide the role id, mention or role name. -- `snowflake` When you just want a snowflake. -- `..snowflakes` When you want to check if the mentioned ID is a valid snowflake. +- `snowflake` When you just want a snowflake. A snowflake is an ID generation format from Twitter that Discord uses to make their IDs unique. These IDs do never change and are used to identify users, guilds, emojis, and more. +- `...snowflakes` When you want to check if the mentioned ID is a valid snowflake. Note that this is similar to ...string, it will take all coming arguments and check them. This should always be your FINAL argument. - `subcommand` When your command has subcommands. From 28423575090640375828e005ec029f1651526c19 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Sat, 5 Dec 2020 23:08:19 +0100 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> --- docs/src/stepbystep/hostingbot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/stepbystep/hostingbot.md b/docs/src/stepbystep/hostingbot.md index 5312c13f1..90f667d0d 100644 --- a/docs/src/stepbystep/hostingbot.md +++ b/docs/src/stepbystep/hostingbot.md @@ -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-net --allow-read --no-check --config tsconfig.json mod.ts +denon run --allow-net --allow-read --no-check mod.ts ```