diff --git a/README.md b/README.md index fbbd7b0..299d445 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,27 @@ -# Minimal Bot Template +# Himbot -Just the minimum to get a working bot using interactions. +A discord bot written in Typescript and running on the Deno runtime. -Make sure to install the latest version when you use it. +## It's dangerous to go alone! Take this! -## Setup +- Install Deno [here](https://deno.com/manual@v1.34.1/getting_started/installation) (required) +- The [Deno VSCode Extension](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno) (recommended) -Just rename `.env.example` to `.env` and fill it with your bot token. +## Structure -## Run Bot +Commands and Events are all stored in named files within the src/commands and src/events directories respectively. +Usage and example ts files can be found in the examples folder. -- deno run -A mod.ts +To generate a new Command or Event run `deno task new:command` or `deno task new:event` respectively. + +## Running Locally + +- Copy .env.example and rename to .env +- Create a Discord Bot with all gateway permissions enabled +- Generate a token for this discord bot and paste it in the .env for BOT_TOKEN +- Run `deno run --allow-all mod.ts` to run locally + +## Adding the bot to a server + +Use the following link (replacing BOT_TOKEN with your own Token of course...) to add your bot: +https://discord.com/oauth2/authorize?client_id=BOT_TOKEN&scope=bot&permissions=8 diff --git a/deno.json b/deno.json index 39fb758..5306c76 100644 --- a/deno.json +++ b/deno.json @@ -1,6 +1,8 @@ { "tasks": { "dev": "deno run --watch mod.ts", - "start": "deno run --allow-env --allow-net --allow-read --allow-write mod.ts" + "start": "deno run --allow-env --allow-net --allow-read --allow-write mod.ts", + "new:command": "cp ./examples/newCommand.txt ./src/commands/newCommand.ts", + "new:event": "cp ./examples/newEvent.txt ./src/events/newEvent.ts" } } diff --git a/examples/newCommand.txt b/examples/newCommand.txt new file mode 100644 index 0000000..d3c71c7 --- /dev/null +++ b/examples/newCommand.txt @@ -0,0 +1,45 @@ +import { + ApplicationCommandOptionTypes, + ApplicationCommandTypes, + InteractionResponseTypes, +} from "../../deps.ts"; + +import { createCommand } from "./mod.ts"; + +// This is the command definition. Please ensure the name matches the file name +// Also, make sure the description is meaningfull +createCommand({ + name: "command", + description: "This is an example command", + type: ApplicationCommandTypes.ChatInput, + scope: "Global", + options: [ + // This is an option that can be sent after the command and used for input + { + type: ApplicationCommandOptionTypes.String, + name: "input", + description: "Text you would like to send to this command.", + // This will make the option required + required: true, + }, + ], + execute: async (bot, interaction) => { + // In this example, we only use "input", so we just need the one item from an array of length 1. + // Options always returns an array, even if there is a single element. + const input = interaction.data?.options?.find( + (option) => option.name === "input" + ); + + // This is how the bot responds to interactions. In this case, it is via a reply. + await bot.helpers.sendInteractionResponse( + interaction.id, + interaction.token, + { + type: InteractionResponseTypes.ChannelMessageWithSource, + data: { + content: `${input?.value} was ${interaction.user.username}'s nickname in highschool.`, + }, + } + ); + }, +}); diff --git a/examples/newEvent.txt b/examples/newEvent.txt new file mode 100644 index 0000000..cb4b82c --- /dev/null +++ b/examples/newEvent.txt @@ -0,0 +1,15 @@ +import { events } from "./mod.ts"; +import { logger } from "../utils/logger.ts"; + +// Log the event name here +const log = logger({ name: "Event: messageCreate" }); + +/* + The properties of events are tied to specific discord events. + Please ensure that both the event type and the property (in this case message) + accurately reflect what you want to listen for. +*/ +events.exampleEvent = (bot, message) => { + // In this example, the message contents are simply being logged + log.info(`${message.tag}: ${message.content}`); +}; diff --git a/mod.ts b/mod.ts index b724658..b08ac54 100644 --- a/mod.ts +++ b/mod.ts @@ -22,8 +22,6 @@ await fastFileLoader(paths).catch((err) => { Deno.exit(1); }); -console.log("EVENTS!: ", events); - export const bot = enableCachePlugin( createBot({ token: Deno.env.get("BOT_TOKEN") || "", diff --git a/src/commands/wryna.ts b/src/commands/wryna.ts new file mode 100644 index 0000000..e616155 --- /dev/null +++ b/src/commands/wryna.ts @@ -0,0 +1,39 @@ +import { + ApplicationCommandOptionTypes, + ApplicationCommandTypes, + InteractionResponseTypes, +} from "../../deps.ts"; + +import { createCommand } from "./mod.ts"; + +// Thanks for the bot name idea Wryna! + +createCommand({ + name: "wryna", + description: "What was your nickname in highschool?", + type: ApplicationCommandTypes.ChatInput, + scope: "Global", + options: [ + { + type: ApplicationCommandOptionTypes.String, + name: "input", + description: "Text you would like to send to this command.", + required: true, + }, + ], + execute: async (bot, interaction) => { + const input = interaction.data?.options?.find( + (option) => option.name === "input" + ); + await bot.helpers.sendInteractionResponse( + interaction.id, + interaction.token, + { + type: InteractionResponseTypes.ChannelMessageWithSource, + data: { + content: `${input?.value} was ${interaction.user.username}'s nickname in highschool.`, + }, + } + ); + }, +}); diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts deleted file mode 100644 index 307a12e..0000000 --- a/src/events/messageCreate.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { events } from "./mod.ts"; -import { logger } from "../utils/logger.ts"; - -const log = logger({ name: "Event: messageCreate" }); - -events.messageCreate = (bot, message) => { - log.info(`${message.tag}: ${message.content}`); -};