When calculating permissions after overwrites, the base permission of the at-everyone role need to be accounted for.
Role#permissions is not sufficient, as it only describes base permissions of the role itself.
fixes#11052
feat(MessageManager)!: New pinned messages routes (#10989)
BREAKING CHANGE: `fetchPinned()` has been renamed to `fetchPins()`, which is a paginated endpoint to fetch pinned messages.
* feat: message forwards
* fix: spelling
* feat: add guildId option for forward
* refactor: type
* refactor: do not use ID suffix for resolvables
* Update TextBasedChannel.js
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* types: fix recurrence rule types
* fix: endAt not endsAt
* types: remove fields that cannot be set by the client
* chore: cleanup JS lands too
* chore: missed you
* chore: bite me
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* feat(website): links to type parameters, builtin doc links in api.json
* feat(website): show default values for params and props in excerpt
* fix: link in jsdoc
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* feat: initial support for guild member banners
* feat: serialise in `toJSON()`
* feat: serialise in `toJSON()`
* docs: lowercase i
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* types: remove newMessage partial on messageUpdate event typing
* types: omit partial group DM for newMessage on messageUpdate
* types: omit partial group DM for oldMessage on messageUpdate
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* refactor: use get guild role endpoint
* style: import order
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* fix(Shard): add env, execArgv, and argv to worker-based threads
* chore: remove process only docs assertion from certain shard options
* chore: update comments for Shard.js
* refactor: Use SHARE_ENV for worker shard's env
* chore: import order
---------
Co-authored-by: Cat++ <69035887+NotGhex@users.noreply.github.com>
* feat(VoiceState): add methods for fetching voice state
* fix: links to new methods
* chore: remove unused import
* chore: use member id
* chore: requested changes
* chore: '@me' as fetch param
* chore: add ediUserVoiceState return type
* refactor: redirect function calls to VoiceAPI
---------
Co-authored-by: Almeida <almeidx@pm.me>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* Add support for Automated Message nonce handling
* Fix options property
* Address PR feedback
* Handled case where it was explicitly set to false for that iteration to not generate a nonce, and PR feedback
* Fix lint issue
* Fix lint issue
* Move to MessagePayload.resolveBody instead
* Fix test errors
* Update packages/discord.js/src/structures/MessagePayload.js
Co-authored-by: Almeida <github@almeidx.dev>
* PR feedback
* Merge
* Let and not const
---------
Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Almeida <almeidx@pm.me>
* refactor(ws): event layout
BREAKING CHANGE: All events now emit shard id as its own param
* fix: worker event forwarding
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
docs(SelectMenuBuilder): correct documentation
Corrects gramatical errors in the documentation for various set methods.
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
feat(builders): fix text input docs
Fixes incorrect references to select menu options in text input docs.
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* fix(BaseRedis): remove listeners on destroy and stop pooling when no subscription
* refactor(BaseRedis): group as constructor param and cleanup subscribers
* fix(BaseRedis): remove listeners on destroy and stop pooling when no subscription
* refactor(BaseRedis): group as constructor param and cleanup subscribers
* chore(RPCRedis): group
* Update packages/brokers/src/brokers/Broker.ts
* Update packages/brokers/src/brokers/Broker.ts
* Update packages/brokers/src/brokers/redis/BaseRedis.ts
Removed `removeAllListeners` from destroy
* chore(BaseRedis): destroy unsubscribe spread array
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* docs(MessageReference): ? is nullable, not `undefined`
* docs(MessageReference): sort by message type
* fix(Message): add throw
* docs(MessageReference): fix English
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* refactor(brokers): make option props more correct
BREAKING CHANGE: Classes now take redis client as standalone parameter, various props from the base option interface moved to redis options
* chore: update comment
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* fix(actions): always emit message create for own messages
* fix: don't re-cache
* fix: user can be missing
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Prefer boolean client status comparison before activity checks
Co-authored-by: Jacob Morrison <jake@matchmd.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* feat(discord.js): added support to setting bot banner
added feature to set banner for bot from code level
the function is in the experimental phase of Discord.
* fix: resolve requested changes
* fix: add missing type in ClientUserEditOptions
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* chore: enable npm provenance
* chore: do the same for dev releases
* chore: actually enable it in normal releases
* chore: specify provenance in `package.json`
* chore: remove `publishConfig` from api-extractor-utils as it's `private`
* feat: add support for `using` keyword on client
* fix: use async dispose
* feat: add support for web socket manager disposing
* fix: use interface for client
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* fix(website): resolve linkTags in summaries
* fix: case body as block
* fix: add discord-api-types support
* fix: remove urlDestination when undefined
* fix: breaks to if/else
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* refactor: make builders types great again
* fix: subcommands only type
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* Skip sweeping if the guild is not available
* Typo
* Fix formatting
* Fix lint
* Check if key in guild
* Bwck to guild a ailable
---------
Co-authored-by: Jake Morrison <jake.morrison@pinnsg.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* feat: add support for name param and object in `formatEmoji()`
* Update formatters.ts
* refactor: swap priority
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* refactor: mark data resolver as internal
* docs: mark relevant TypeScript symbols as `@internal`
* docs: extra additions
* style: prefer at end
* docs: add more `@internal`s
* test: update template code
* feat(website): show union members of type aliases
* refactor: suggestions from code review
* Apply suggestions from code review
---------
Co-authored-by: Noel <buechler.noel@outlook.com>
* refactor: minify api.json by shortening keys
* fix: links to other packages
* refactor: get doclink from canonicalReference, not model
* fix: types
* fix: again
* fix: @link tags with alt texts
* fix(website): cross-package links in @deprecated
* refactor: minify api.json by shortening keys
* fix: links to other packages
* refactor: get doclink from canonicalReference, not model
* fix: types
* fix: again
* fix: @link tags with alt texts
* types: use `Awaitable<T>` instead of `Promise<T> | T`
* types: use `JSONEncodable<T>` over raw definition
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
feat(collection): align/add methods with/from Set Methods proposal
BREAKING CHANGE: The `intersect` method has been renamed to `intersection`
BREAKING CHANGE: The `difference` method has been renamed to `symmetricDifference`
BREAKING CHANGE: The `subtract` method has been renamed to `difference`
* Move the getNode/canEnableFFMPEGOptimizations into a lazy loaded call the first time it's actually ever referenced
* PR feedback: Make initializeNodes return a map then nullably assign NODES, this removes an extra variable and cleans up the code
* chore: lint suggestion
Co-authored-by: Aura Román <kyradiscord@gmail.com>
* Use local map instead of recursive
* Run prettier
* Fix lint
---------
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: Aura Román <kyradiscord@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* feat(cleanContent): add missing commands and emojis
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
* fix: check for every possible name
* fix: use non capturing group
---------
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* fix(Webhook): do not call `client.deleteWebhook` in `delete`
Partially reverts #9777 which caused a regression (#9785) when using `WebhookClient`
* chore: add comment
Co-Authored-By: Souji <timoqueezle@gmail.com>
* fix: move `deleteWebhook` from `Client` to `BaseClient`
---------
Co-authored-by: Souji <timoqueezle@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
docs(formatters): remove markdown
The documentation website does not support rendering markdown
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
fix(Message): remove duplicated word 'of' in description
This commit removes the secondary 'of' in the description for the Message structure. This doesn't change anything drastically in terms of the actual code as it's just a JSDoc comment.
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* feat: onboarding mode and edit method
* feat(guild): add `editOnboarding`
* fix: use discord-api-types
* types: make arrays readonly
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* fix: bring up to date
* docs: id is a snowflake
* fix: requested changes
* refactor: make most options optional
* refactor: provide GuildEmoji or Emoji instance
* revert: changes to Util
* fix: rebase leftovers
* fix: allow passing option id
* fix: requested changes
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
* types(Partials): add toString() method to supported Partials
- includes `PartialDMChannel`, `PartialGuildMember` and `PartialUser`
- does not include
- `PartialMessage`, since `<PartialMessage>.content` is always null
- `PartialMessageReaction`, since `MessageReaction` has no `toString()` method
- `PartialThreadMember`, since `ThreadMember` has no `toString()` method
* types(Partials): replace type of `toString()` methods with return type
* test(Partials): add tests
* types(Partialize): refactor Partialize
* test(PartialThreadMember): fix typo
* types(Partials): clean up unnecessary type overrides
* test(Partials): add tests for <Partials>.partial property
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* feat(GuildAuditLogsEntry): expose ingrationType
* fix: not optional, if extra is present on these types
not necessary, as it is conditionally assigned
* fix: remove non-extra approach
* fix(types): string is not guaranteed to be the known enum
* fix: adapt type tests to new extra properties
* fix: include null in type, since extra is not always populated
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* refactor(TeamMember): deprecate permissions property
* feat: add support for team member roles
* feat: add reference to external team member role enum
* docs: suggested changes
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Explicitly add input args for readable input cases instead of just for string input cases.
Change also ensures that constant arrays are passed by value instead of by reference, preventing them from accidentally being modified.
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
* feat: add `Client#webhooksUpdate`
* feat: add deprecation in the types
* docs: add full stops
* types: reference non-deprecated type
This helps with future-proofing (deduplication).
* docs(ClientEvents): fix reference link
This now hyperlinks correctly with IntelliSense.
---------
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
@@ -11,22 +11,20 @@ is a great boon to your development process.
To get ready to work on the codebase, please do the following:
1. Fork & clone the repository, and make sure you're on the **main** branch
2. Run `yarn --immutable` ([install](https://yarnpkg.com/getting-started/install))
3. Run `yarn build` to build local packages
2. Run `pnpm install --frozen-lockfile` ([install](https://pnpm.io/installation))
3. Run `pnpm run build` to build local packages
4. Code your heart out!
5. Run `yarn test` to run ESLint and ensure any JSDoc changes are valid
5. Run `pnpm run test` to run ESLint and ensure any JSDoc changes are valid
6. [Submit a pull request](https://github.com/discordjs/discord.js/compare) (Make sure you follow the [conventional commit format](https://github.com/discordjs/discord.js/blob/main/.github/COMMIT_CONVENTION.md))
## Testing changes locally
If you want to test changes you've made locally, you can do so by using `yarn link`. This will create a symlink to your local copy of the discord.js libraries.
If you want to test changes you've made locally, you can do so by using `pnpm link <package-you-want-to-link-to-your-current-package>`. This will create a symlink to your local copy of the discord.js libraries.
1. Create a new directory `mkdir discordjs-test` and move into it `cd discordjs-test`
2. Initialize a new yarn 3 project `yarn init -2`
3.Disable pnp `yarn config set nodeLinker node-modules`
4.Now link the local discord.js project you cloned earlier `yarn link -A {PATH_TO_DISCORDJS_REPO}`
5. Install packages you'd like to test locally `yarn add discord.js@latest`, `yarn add @discordjs/rest@latest`, etc. **Note: Make sure you use `latest` tag or else yarn will try to install the remote package from npm**
6. Import the package in your source code and test them out!
2. Initialize a new pnpm project `pnpm init`
3.Now link the discord.js package from the directory you cloned earlier `pnpm link {PATH_TO_DISCORDJS_REPO}/packages/<package>`. (e.g. `pnpm link ~/discord.js/packages/rest`)
4.Import the package in your source code and test them out!
### Working with TypeScript packages
@@ -34,15 +32,18 @@ When testing local changes, you may notice you need to manually recompile TypeSc
To avoid this you can use the `--watch` parameter in the package build script to automatically recompile the project when changes are detected.
For example, to automatically recompile the `@discordjs/rest` project when changes are detected, run `yarn turbo run build --filter=@discordjs/rest -- --watch` in the root folder of where you cloned the discord.js repo.
For example, to automatically recompile the `@discordjs/rest` project when changes are detected, run `pnpm turbo run build --filter='@discordjs/rest' -- --watch` in the root folder of where you cloned the discord.js repo.
## Adding new packages
If you'd like to create another package under the `@discordjs` organization run the following command:
run:pnpm exec npm-deprecate --name "${{inputs.version}}" --message "${{inputs.message || 'This version is deprecated. Please use a newer version.'}}" --package ${{inputs.package}}
description:'Build a Docker image for a workspace',
details:
'\n This command will build a efficient Docker image which only contains necessary dependencies for the specified workspace.\n\n You have to create a Dockerfile in your workspace or your project. You can also specify the path to Dockerfile using the "-f, --file" option.\n\n Additional arguments can be passed to "docker build" directly, please check the Docker docs for more info: https://docs.docker.com/engine/reference/commandline/build/\n\n You can copy additional files or folders to a Docker image using the "--copy" option. This is useful for secret keys or configuration files. The files will be copied to "manifests" folder. The path can be either a path relative to the Dockerfile or an absolute path.\n ',
examples:[
['Build a Docker image for a workspace','yarn docker build @foo/bar'],
If you're reading this, it probably means you want to learn how to make a bot with discord.js. Awesome! You've come to the right place.
This guide will teach you things such as:
- How to get a bot [up and running](/preparations/) from scratch;
- How to properly [create](/creating-your-bot/), [organize](/creating-your-bot/command-handling.md), and expand on your commands;
- In-depth explanations and examples regarding popular topics (e.g. [reactions](/popular-topics/reactions.md), [embeds](/popular-topics/embeds.md), [canvas](/popular-topics/canvas.md));
- Working with databases (e.g. [sequelize](/sequelize/) and [keyv](/keyv/));
- Getting started with [sharding](/sharding/);
- How to get a bot [up and running](../getting-started/starting-out) from scratch;
- In-depth explanations regarding features and concepts of the API (e.g. [intents](../topics/intents), [threads](../topics/threads), [webhooks](../topics/webhooks));
- And much more.
This guide will also cover subjects like common errors and how to solve them, keeping your code clean, setting up a proper development environment, etc.
Sounds good? Great! Let's get started, then.
Sounds good? Great! Let's get started.
## Before you begin...
@@ -25,11 +22,11 @@ While you _can_ make a bot with very little JavaScript and programming knowledge
If you don't know JavaScript but would like to learn about it, here are a few links to help get you started:
- [Eloquent JavaScript, a free online book](http://eloquentjavascript.net/)
- [JavaScript.info, a modern javascript tutorial](https://javascript.info/)
discord.js v14 has released and the guide has been updated!
<br />
This includes additions and changes made in Discord, such as slash commands and message components.
This website is new! We will no longer be updating the old guide website.
</DiscordMessage>
</DiscordMessages>
@@ -33,25 +31,9 @@ We have moved from VuePress to [Next.js](https://nextjs.org/)! The source can be
## Pages
All content has been updated to use discord.js v14 syntax. The v13 version of the guide can be found at https://v13.discordjs.guide.
### New
- [Updating from v13 to v14](/additional-info/changes-in-v14.md): A list of the changes from discord.js v13 to v14
- [Slash commands](/interactions/slash-commands.md): Registering, replying to slash commands and permissions
- [Buttons](/interactions/buttons.md): Building, sending, and receiving buttons
- [Select menus](/interactions/select-menus.md): Building, sending, and receiving select menus
- [Threads](/popular-topics/threads.md): Creating and managing threads
- [Builders](/popular-topics/builders.md): A collection of builders to use with your bot
### Updated
- Commando: Replaced with [Sapphire](https://sapphirejs.dev/docs/Guide/getting-started/getting-started-with-sapphire)
- [Voice](/voice/): Rewritten to use the [_`@discordjs/voice`_](https://github.com/discordjs/discord.js/tree/main/packages/voice) package
- [Command handling](/creating-your-bot/command-handling.md/): Updated to use slash commands
- Obsolete sections removed
- _`client.on('message')`_ snippets updated to _`client.on(Events.InteractionCreate)`_
- [Message content became a privileged intent on August 31, 2022](https://support-dev.discord.com/hc/articles/4404772028055)
- Pages have been revamped to account for our new [create-discord-bot](https://github.com/discordjs/discord.js/tree/main/packages/create-discord-bot) command-line interface.
- Popular topic are now simply "topics" that detail usage of a particular concept of the API.
- Focus is primarily on discord.js, so irrelevant topics have been removed. It may be better to visit the documentation of the package you are using to learn how to use them.
Since this guide is made specifically for the discord.js community, we want to be sure to provide the most relevant and up-to-date content. We will, of course, make additions to the current pages and add new ones as we see fit, but fulfilling requests is how we know we're providing content you all want the most.
Requests may be as simple as "add an example to the [frequently asked questions](/popular-topics/faq.html) page", or as elaborate as "add a page regarding [sharding](/sharding/)". We'll do our best to fulfill all requests, as long as they're reasonable.
Requests may be as simple as "add an example to the [frequently asked questions](../topics/frequently-asked-questions) page", or as elaborate as "add a page regarding [sharding](../topics/sharding)". We'll do our best to fulfill all requests, as long as they're reasonable.
To make a request, simply head over to [the repository's issue tracker](https://github.com/discordjs/discord.js/issues) and [create a new issue](https://github.com/discordjs/discord.js/issues/new)! Title it appropriately, and let us know exactly what you mean inside the issue description. Make sure that you've looked around the site before making a request; what you want to request might already exist!
<Alert title="Tip" type="success">
<Alert title="Tip" type="info">
Remember that you can always [fork the repository](https://github.com/discordjs/discord.js/fork) and [make a pull
request](https://github.com/discordjs/discord.js/pulls) if you want to add anything to the guide yourself!
</Alert>
We'll also get into some of the more advanced features this guide does below.
We'll also get into some of the more advanced features this guide uses below. We recommended you have a look at the [source](https://github.com/discordjs/discord.js/blob/main/apps/guide/src/content/01-home/03-how-to-contribute.mdx) of this page to see exactly how they work.
Our [create-discord-bot](https://github.com/discordjs/discord.js/tree/main/packages/create-discord-bot) command-line interface sets up a basic Discord bot to help you get started on your journey.
## Creating your bot
To use discord.js, you'll need to install [Node.js](https://nodejs.org), [Deno](https://deno.com), or [Bun](https://bun.sh). discord.js v14 requires Node.js v16.11.0 or higher, but the long-term support (LTS) version is always recommended. For the purposes of this guide, we will be using Node.js.
<Alert title="Tip" type="info">
To check if you already have Node.js installed, run _`node --version`_ in your terminal. If it outputs _`v16.11.0`_ or
higher, then you're good to go!
</Alert>
### Windows
- Download from the [Node.js website](https://nodejs.org).
- Use [fnm](https://github.com/Schniz/fnm).
- Use [Volta](https://volta.sh).
### macOS
- Download from the [Node.js website](https://nodejs.org/).
- Use [fnm](https://github.com/Schniz/fnm).
- Use [Homebrew](https://formulae.brew.sh/formula/node).
- Use [nvm](https://github.com/nvm-sh/nvm?tab=readme-ov-file#installing-and-updating).
- Use [Volta](https://volta.sh).
### Linux
- Visit [this page](https://nodejs.org/en/download/package-manager) to determine how you should install Node.js.
- Use [fnm](https://github.com/Schniz/fnm).
- Use [nvm](https://github.com/nvm-sh/nvm).
- Use [Volta](https://volta.sh).
After installing Node.js, you'll be able to create a new application from your desired package manager. If you're starting out fresh, installing Node.js will also install npm, a package manager for Node.js.
You'll be asked the directory to create the application in, as well as whether TypeScript should be used. Dependencies will automatically be installed for you. After this, you've just got your startup Discord bot template _nearly_ ready!
In the next section, we will explain how to create an application to interact with Discord's API.
You'll need to create an application on Discord's developer portal so your bot has a token to interact with Discord's API.
Now that you've installed Node, discord.js, and hopefully a linter, you're almost ready to start coding! The next step you need to take is setting up an actual Discord bot application via Discord's website.
## Creating the application
It's effortless to create one. The steps you need to take are as follows:
Follow these steps:
1. Open the [Discord developer portal](https://discord.com/developers/applications) and log into your account.
1. Open the [Discord developer portal](https://discord.com/developers/applications). You'll need to be logged in.
2. Click on the "New Application" button.
3. Enter a name and confirm the pop-up window by clicking the "Create" button.
- You'll need to agree to the [Developer Terms of Service](https://discord.com/developers/docs/policies-and-agreements/terms-of-service) and [Developer Policy](https://discord.com/developers/docs/policies-and-agreements/developer-policy).
You should see a page like this:

You can edit your application's name, description, and avatar here. Once you've saved your changes, move on by selecting the "Bot" tab in the left pane.
You can edit your application's name, description, and avatar here. Copy the application id and paste it in the .env file after _`APPLICATION_ID=`_.
Once you've saved your changes, move on by selecting the "Bot" tab in the left pane.
## Your bot's token
@@ -32,9 +35,11 @@ On the bot tab, you'll see a section like this:

In this panel, you can give your bot a snazzy avatar, set its username, and make it public or private. Your bot's token will be revealed when you press the "Reset Token" button and confirm. When we ask you to paste your bot's token somewhere, this is the value that you need to put in. If you happen to lose your bot's token at some point, you need to come back to this page and reset your bot's token again which will reveal the new token, invalidating all old ones.
In this panel, you can give your bot a snazzy avatar, set its username, and make it public or private. Your bot's token will be revealed when you press the "Reset Token" button and confirm. Once you've done this, copy it and paste it in the .env file after _`DISCORD_TOKEN=`_.
### What is a token, anyway?
If you happen to lose this token at some point, you will need to come back to this page and reset it, which will reveal the new token, invalidating all old ones.
### Bot token explanation
A token is essentially your bot's password; it's what your bot uses to login to Discord. With that said, **it is vital that you do not ever share this token with anybody, purposely or accidentally**. If someone does manage to get a hold of your bot's token, they can use your bot as if it were theirs—this means they can perform malicious acts with it.
@@ -52,8 +57,6 @@ Let's imagine that you have a bot on over 1,000 servers, and it took you many, m
All that and much, much more. Sounds pretty terrible, right? So make sure to keep your bot's token as safe as possible!
In the [configuration files](../creating-your-bot/configuration-files) page of the guide, we cover how to safely store your bot's token in a configuration file.
<Alert title="Compromised tokens" type="danger">
If your bot token has been compromised by committing it to a public repository, posting it in discord.js support etc.
or otherwise see your bot's token in danger, return to this page and press "Reset Token". This will invalidate all old
- _`https://discord.com/api/oauth2/authorize`_ is Discord's standard structure for authorizing an OAuth2 application (such as your bot application) for entry to a Discord server.
- _`client_id=...`_ is to specify _which_ application you want to authorize. You'll need to replace this part with your client's id to create a valid invite link.
- _`permissions=...`_ describes the permissions that your bot will request to be granted by default upon joining the server you are adding it to.
- _`scope=bot`_ specifies that you want to add this application as a Discord bot with the ability to create slash commands.
<Alert title="Warning" type="warning">
If you get an error message saying "Bot requires a code grant", head over to your application's settings and disable
the "Requires OAuth2 Code Grant" option. You shouldn't enable this option unless you know why you need to.
</Alert>
## Creating and using your invite link
To create an invite link, head back to the [developer portal](https://discord.com/developers/applications), click on your bot application, and open the OAuth2 page.
In the sidebar, you'll find the URL generator. Select the _`bot`_ option. Once you select the _`bot`_ option, a list of permissions will appear, allowing you to configure the permissions your bot needs.
Grab the link via the "Copy" button and send it in a channel in Discord. Click on the link you just sent which should reveal this:
Choose the server you want to add the bot to and click "Authorize". Congratulations! You've successfully added your bot to your Discord server.
At this point, you should have a Discord bot you created with [create-discord-bot](https://github.com/discordjs/discord.js/tree/main/packages/create-discord-bot) with your .env file populated and your Discord bot in a server. You are now ready to do what you like.
To use discord.js, you'll need to install [Node.js](https://nodejs.org/). discord.js v14 requires Node v16.9.0 or higher.
<Alert title="Tip" type="success">
To check if you already have Node installed on your machine \(e.g., if you're using a VPS\), run _`node -v`_ in your
terminal. If it outputs _`v16.9.0`_ or higher, then you're good to go! Otherwise, continue reading.
</Alert>
On Windows, it's as simple as installing any other program. Download the latest version from [the Node.js website](https://nodejs.org/), open the downloaded file, and follow the steps from the installer.
On macOS, either:
- Download the latest version from [the Node.js website](https://nodejs.org/), open the package installer, and follow the instructions
- Use a package manager like [Homebrew](https://brew.sh/) with the command _`brew install node`_
On Linux, you can consult [this page](https://nodejs.org/en/download/package-manager/) to determine how you should install Node. Native package managers often default to outdated versions of Node, so make sure you follow the recommended approach for your chosen Linux distribution carefully.
## Preparing the essentials
To use discord.js, you'll need to install it via npm \(Node's package manager\). npm comes with every Node installation, so you don't have to worry about installing that. However, before you install anything, you should set up a new project folder.
Navigate to a suitable place on your machine and create a new folder named _`discord-bot`_ (or whatever you want). Next you'll need to open your terminal.
### Opening the terminal
<Alert title="Tip" type="success">
If you use [Visual Studio Code](https://code.visualstudio.com/), you can press <kbd>Ctrl + `</kbd> (backtick) to open
its integrated terminal.
</Alert>
On Windows, either:
- <kbd>Shift + Right-click</kbd> inside your project directory and choose the "Open command window here" option
- Press <kbd>Win + R</kbd> and run _`cmd.exe`_, and then _`cd`_ into your project directory
On macOS, either:
- Open Launchpad or Spotlight and search for "Terminal"
- In your "Applications" folder, under "Utilities", open the Terminal app
On Linux, you can quickly open the terminal with <kbd>Ctrl + Alt + T</kbd>.
With the terminal open, run the _`node -v`_ command to make sure you've successfully installed Node.js. If it outputs _`v16.9.0`_ or higher, great!
### Initiating a project folder
<CH.Code lineNumbers={false}>
```sh npm
npm init; npm pkg set type="module"
```
```sh yarn
yarn init
# You must go into your package.json file and add "type": "module"
```
```sh pnpm
pnpm init; pnpm pkg set type="module"
```
</CH.Code>
This is the next command you'll be running. This command creates a _`package.json`_ file for you, which will keep track of the dependencies your project uses, as well as other info.
This command will ask you a sequence of questions–you should fill them out as you see fit. If you're not sure of something or want to skip it as a whole, leave it blank and press enter. Setting the package type as _`module`_ tells Node that you'll be writing this project using ESM \(ECMAScript modules\), supporting the latest JavaScript syntax and features.
Once you're done with that, you're ready to install discord.js!
## Installing discord.js
Now that you've installed Node.js and know how to open your console and run commands, you can finally install discord.js! Run the following command in your terminal:
<CH.Code lineNumbers={false}>
```sh npm
npm install discord.js
```
```sh yarn
yarn add discord.js
```
```sh pnpm
pnpm add discord.js
```
</CH.Code>
And that's it! With all the necessities installed, you're almost ready to start coding your bot.
## Installing a linter
While you are coding, it's possible to run into numerous syntax errors or code in an inconsistent style. You should [install a linter](./setting-up-a-linter) to ease these troubles. While code editors generally can point out syntax errors, linters coerce your code into a specific style as defined by the configuration. While this is not required, it is advised.
After you [set up a bot application](./setting-up-a-bot-application), you'll notice that it's not in any servers yet. So how does that work?
Before you're able to see your bot in your own (or other) servers, you'll need to add it by creating and using a unique invite link using your bot application's client id.
## Bot invite links
The basic version of one such link looks like this:
- _`https://discord.com/api/oauth2/authorize`_ is Discord's standard structure for authorizing an OAuth2 application (such as your bot application) for entry to a Discord server.
- _`client_id=...`_ is to specify _which_ application you want to authorize. You'll need to replace this part with your client's id to create a valid invite link.
- _`permissions=...`_ describes the permissions that your bot will request to be granted by default upon joining the server you are adding it to.
- _`scope=bot%20applications.commands`_ specifies that you want to add this application as a Discord bot, with the ability to create slash commands.
<Alert title="Warning" type="warning">
If you get an error message saying "Bot requires a code grant", head over to your application's settings and disable
the "Require OAuth2 Code Grant" option. You shouldn't enable this option unless you know why you need to.
</Alert>
## Creating and using your invite link
To create an invite link, head back to the [My Apps](https://discord.com/developers/applications/me) page under the "Applications" section, click on your bot application, and open the OAuth2 page.
In the sidebar, you'll find the OAuth2 URL generator. Select the _`bot`_ and _`applications.commands`_ options. Once you select the _`bot`_ option, a list of permissions will appear, allowing you to configure the permissions your bot needs.
Grab the link via the "Copy" button and enter it in your browser. You should see something like this (with your bot's username and avatar):
Choose the server you want to add it to and click "Authorize". Do note that you'll need the "Manage Server" permission on a server to add your bot there. This should then present you a nice confirmation message:

Congratulations! You've successfully added your bot to your Discord server. It should show up in your server's member list somewhat like this:

Once you [add your bot to a server](../installations-and-preparations/adding-your-bot-to-servers), the next step is to start coding and get it online! Let's start by creating a config file to prepare the necessary values your client will need.
As explained in the ["What is a token, anyway?"](../installations-and-preparations/setting-up-a-bot-application.md#what-is-a-token-anyway) section, your token is essentially your bot's password, and you should protect it as best as possible. This can be done through a _`config.json`_ file or by using environment variables.
Open your application in the [Discord Developer Portal](https://discord.com/developers/applications) and go to the "Bot" page to copy your token.
## Using config.json
Storing data in a _`config.json`_ file is a common way of keeping your sensitive values safe. Create a _`config.json`_ file in your project directory and paste in your token. You can access your token inside other files by importing this file.
<CH.Code lineNumbers={false}>
```json config.json
{
"token": "your-token-goes-here"
}
```
```js index.js
import config from './config.json' assert { type: 'json' };
console.log(config.token);
```
</CH.Code>
<Alert title="Danger" type="danger">
If you're using Git, you should not commit this file and should [ignore it via `.gitignore`](#git-and-gitignore).
</Alert>
## Using environment variables
Environment variables are special values for your environment (e.g., terminal session, Docker container, or environment variable file). You can pass these values into your code's scope so that you can use them.
One way to pass in environment variables is via the command line interface. When starting your app, instead of _`node index.js`_, use _`TOKEN=your-token-goes-here node index.js`_. You can repeat this pattern to expose other values as well.
You can access the set values in your code via the _`process.env`_ global variable, accessible in any file. Note that values passed this way will always be strings and that you might need to parse them to a number, if using them to do calculations.
Another common approach is storing these values in a _`.env`_ file. This spares you from always copying your token into the command line. Each line in a _`.env`_ file should hold a _`KEY=value`_ pair.
You can use the [`dotenv` package](https://www.npmjs.com/package/dotenv) for this. Once installed, require and use the package to load your _`.env`_ file and attach the variables to _`process.env`_:
<CH.Code lineNumbers={false}>
```sh npm
npm install dotenv
```
```sh yarn
yarn add dotenv
```
```sh pnpm
pnpm add dotenv
```
</CH.Code>
<CH.Code lineNumbers={false} rows={7}>
```sh .env
A=123
B=456
DISCORD_TOKEN=your-token-goes-here
```
```js index.js
import { config } from 'dotenv';
config();
console.log(process.env.A);
console.log(process.env.B);
console.log(process.env.DISCORD_TOKEN);
```
</CH.Code>
<Alert title="Danger" type="danger">
If you're using Git, you should not commit this file and should [ignore it via `.gitignore`](#git-and-gitignore).
While we generally do not recommend using online editors as hosting solutions, but rather invest in a proper virtual private server, these services do offer ways to keep your credentials safe as well! Please see the respective service's documentation and help articles for more information on how to keep sensitive values safe:
- Glitch: [Storing secrets in .env](https://glitch.happyfox.com/kb/article/18)
- Replit: [Secrets and environment variables](https://docs.replit.com/repls/secrets-environment-variables)
</Alert>
## Git and .gitignore
Git is a fantastic tool to keep track of your code changes and allows you to upload progress to services like [GitHub](https://github.com/), [GitLab](https://about.gitlab.com/), or [Bitbucket](https://bitbucket.org/product). While this is super useful to share code with other developers, it also bears the risk of uploading your configuration files with sensitive values!
You can specify files that Git should ignore in its versioning systems with a*`.gitignore`* file. Create a _`.gitignore`_ file in your project directory and add the names of the files and folders you want to ignore:
```
node_modules
.env
config.json
```
<Alert title="Tip" type="success">
Aside from keeping credentials safe, _`node_modules`_ should be included here. Since this directory can be restored based on the entries in your _`package.json`_ and _`package-lock.json`_ files by running _`npm install`_, it does not need to be included in Git.
You can specify quite intricate patterns in _`.gitignore`_ files, check out the [Git documentation on `.gitignore`](https://git-scm.com/docs/gitignore) for more information!
This page assumes you've already prepared the [configuration files](./configuration-files) from the previous page.
We're using the _`config.json`_ approach, however feel free to substitute your own!
</Alert>
Open your code editor and create a new file. We suggest that you save the file as _`index.js`_, but you may name it whatever you wish.
Here's the base code to get you started:
<CH.Code>
```js
// Require the necessary discord.js classes
import { Client, Events, GatewayIntentBits } from 'discord.js';
import config from './config.json' assert { type: 'json' };
// Create a new client instance
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client.once(Events.ClientReady, (c) => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
// Log in to Discord with your client's token
client.login(config.token);
```
</CH.Code>
This is how you create a client instance for your Discord bot and log in to Discord. The _`GatewayIntentBits.Guilds`_ intents option is necessary for the discord.js client to work as you expect it to, as it ensures that the caches for guilds, channels, and roles are populated and available for internal use.
<Alert title="Tip" type="success">
The term "guild" is used by the Discord API and in discord.js to refer to a Discord server.
</Alert>
Intents also define which events Discord should send to your bot, and you may wish to enable more than just the minimum. You can read more about the other intents on the [Intents topic](../popular-topics/intents).
## Running your application
Open your terminal and run _`node index.js`_ to start the process. If you see "Ready!" after a few seconds, you're good to go! The next step is to start adding [slash commands](./adding-commands) to develop your bot's functionality.
<Alert title="Tip" type="success">
You can open your _`package.json`_ file and edit the _`"main": "index.js"`_ field to point to your main file. You can then run _`node .`_ in your terminal to start the process!
After closing the process with _`Ctrl + C`_, you can press the up arrow on your keyboard to bring up the latest commands you've run. Pressing up and then enter after closing the process is a quick way to start it up again.
Discord allows developers to register [slash commands](https://discord.com/developers/docs/interactions/application-commands), which provide users a first-class way of interacting directly with your application.
Slash commands provide a huge number of benefits over manual message parsing, including:
- Integration with the Discord client interface.
- Automatic command detection and parsing of the associated options/arguments.
- Typed argument inputs for command options, e.g. "String", "User", or "Role".
- Validated or dynamic choices for command options.
- Pop-up form-style inputs for capturing additional information.
...and many more!
<Alert title="Read first!" type="info">
For fully functional slash commands, there are three important pieces of code that need to be written. They are:
1. The individual command files, containing their definitions and functionality.
2. The [command handler](command-handling.html), which dynamically reads the files and executes the commands.
3. The [command deployment script](command-deployment.html), to register your slash commands with Discord so they appear in the interface.
These steps can be done in any order, but **all are required** before the commands are fully functional.
On this page, you'll complete Step 1. Make sure to also complete the other pages linked above!
</Alert>
## Before you continue
Assuming you've followed the guide so far, your project directory should look something like this:
```:no-line-numbers
discord-bot/
├── node_modules
├── config.json
├── index.js
├── package-lock.json
└── package.json
```
## Individual command files
Create a new folder named _`commands`_, which is where you'll store all of your command files.
At a minimum, the definition of a slash command must have a name and a description. Slash command names must be between 1-32 characters and contain no capital letters, spaces, or symbols other than _`-`_ and _`_`_. Using the builder, a simple _`ping`\_ command definition would look like this:
A slash command also requires a function to run when the command is used, to respond to the interaction. Using an interaction response method confirms to Discord that your bot successfully received the interaction, and has responded to the user. Discord enforces this to ensure that all slash commands provide a good user experience (UX). Failing to respond will cause Discord to show that the command failed, even if your bot is performing other actions as a result.
The simplest way to acknowledge and respond to an interaction is the _`interaction.reply()`_ method. Other methods of replying are covered on the [Response methods](../slash-commands/response-methods) page later in this section.
[`@type`](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#type) and
[`@param`](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#param-and-returns) tags allow you
to annotate your code with type information. The tags are not required for your code to run but provide autocomplete
and type information for fields and parameters, which can majorly improve your developer experience when working with
them.
</Alert>
Put these two together by creating a `commands/ping.js` file for your first command. Inside this file, you're going to define and export two items.
- The `data` property, which will provide the command definition shown above for registering to Discord.
- The `execute` method, which will contain the functionality to run from our event handler when the command is used.
The _`export`_ keyword ensures these values can be imported and read by other files; namely the command loader and command deployment scripts mentioned earlier.
[`module.exports`](https://nodejs.org/api/modules.html#modules_module_exports) is how you export data in Node.js so that you can [`require()`](https://nodejs.org/api/modules.html#modules_require_id) it in other files.
If you need to access your client instance from inside a command file, you can access it via `interaction.client`. If you need to access external files, packages, etc., you should `require()` them at the top of the file.
</Alert>
That's it for your basic ping command. Below are examples of two more commands we're going to build upon throughout the guide, so create two more files for these before you continue reading.
// interaction.guild is the object representing the Guild in which the command was run
await interaction.reply(`This server is ${interaction.guild.name} and has
${interaction.guild.memberCount} members.`);
}
```
</CH.Code>
#### Next steps
You can implement additional commands by creating additional files in the _`commands`_ folder, but these three are the ones we're going to use for the examples as we go on. For now let's move on to the code you'll need for command handling, to load the files and respond to incoming interactions.
Unless your bot project is small, it's not a very good idea to have a single file with a giant _`if`_/_`else if`_ chain for commands. If you want to implement features into your bot and make your development process a lot less painful, you'll want to implement a command handler. Let's get started on that!
<Alert title="Read first!" type="info">
For fully functional slash commands, there are three important pieces of code that need to be written. They are:
1. The [individual command files](slash-commands), containing their definitions and functionality.
2. The command handler, which dynamically reads the files and executes the commands.
3. The [command deployment script](command-deployment), to register your slash commands with Discord so they appear in the interface.
These steps can be done in any order, but **all are required** before the commands are fully functional.
This page details how to complete **Step 2**. Make sure to also complete the other pages linked above!
</Alert>
## Loading command files
Now that your command files have been created, your bot needs to load these files on startup.
In your _`index.js`_ file, make these additions to the base template:
<CH.Code>
```js JavaScript mark=1:4,9
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Client, Collection, Events, GatewayIntentBits } from 'discord.js';
import config from './config.json' assert { type: 'json' };
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const commands = new Collection();
client.once(Events.ClientReady, () => {
console.log('Ready!');
});
```
```ts TypeScript mark=1:11,16:21
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import {
Client,
Collection,
Events,
GatewayIntentBits,
type RESTPostAPIChatInputApplicationCommandsJSONBody,
type ChatInputCommandInteraction,
} from 'discord.js';
import config from './config.json';
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('data' in command && 'execute' in command) {
commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
```
</CH.Code>
First, [url.fileURLToPath()](https://nodejs.org/api/url.html) helps to construct a path to the _`commands`_ directory. The [fs.readdir()](https://nodejs.org/api/fs.html#fspromisesreaddirpath-options) method then reads the path to the directory and returns a Promise which resolves to an array of all the file names it contains, currently _`['ping.js', 'server.js', 'user.js']`_. To ensure only command files get processed, _`Array.filter()`_ removes any non-JavaScript files from the array.
With the correct files identified, the last step is to loop over the array and dynamically set each command into the _`commands`_ Collection. For each file being loaded, check that it has at least the _`data`_ and _`execute`_ properties. This helps to prevent errors resulting from loading empty, unfinished or otherwise incorrect command files while you're still developing.
## Receiving command interactions
Every slash command is an _`interaction`_, so to respond to a command, you need to create a listener for the <DocsLink type="class" parent="Client" symbol="e-interactionCreate" /> event that will execute code when your application receives an interaction. Place the code below in the _`index.js`_ file you created earlier.
Not every interaction is a slash command (e.g. _`MessageComponent`_ interactions). Make sure to only handle slash commands in this function by making use of the <DocsLink type="class" parent="BaseInteraction" symbol="isChatInputCommand" brackets /> method to exit the handler if another type is encountered. This method also provides type guarding for TypeScript users, narrowing the type from _`BaseInteraction`_ to <DocsLink type="class" parent="ChatInputCommandInteraction" />.
When your bot receives a <DocsLink type="class" parent="Client" symbol="e-interactionCreate" /> event, the interaction object contains all the information you need to dynamically retrieve and execute your commands!
Let's take a look at the _`ping`_ command again. Note the _`execute()`_ function that will reply to the interaction with "Pong!".
<CH.Code>
```js
export const data = {
name: 'ping',
description: 'Replies with Pong!',
};
export async function execute(interaction) {
await interaction.reply('Pong!');
}
```
</CH.Code>
First, you need to get the matching command from the _`commands`_ Collection based on the _`interaction.commandName`_. If no matching command is found, log an error to the console and ignore the event.
With the right command identified, all that's left to do is call the command's _`.execute()`_ method and pass in the _`interaction`_ variable as its argument. Note that the event listener has been made _`async`_, allowing Promises to be awaited. In case something goes wrong and the Promise rejects, catch and log any error to the console.
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: 'There was an error while executing this command!', ephemeral: true });
} else {
await interaction.reply({ content: 'There was an error while executing this command!', ephemeral: true });
}
}
});
```
</CH.Code>
## Command categories
So far, all of your command files are in a single _`commands`_ folder. This is fine at first, but as your project grows, the number of files in the _`commands`_ folder will too. Keeping track of that many files can be a little tough. To make this a little easier, you can categorize your commands and put them in subfolders inside the _`commands`_ folder. You will have to make a few changes to your existing code in _`index.js`_ for this to work out.
If you've been following along, your project structure should look something like this:

After moving your commands into subfolders, it will look something like this:

<Alert title="Warning" type="warning">
Make sure you put every command file you have inside one of the new subfolders. Leaving a command file directly under
the _`commands`_ folder will create problems.
</Alert>
It is not necessary to name your subfolders exactly like we have named them here. You can create any number of subfolders and name them whatever you want. Although, it is a good practice to name them according to the type of commands stored inside them.
Back in your _`index.js`_ file, where the code to [dynamically read command files](#loading-command-files) is, use the same pattern to read the subfolder directories, and then require each command inside them.
// Set a new item in the Collection with the key as the command name and the value as the exported module
if ('data' in command && 'execute' in command) {
commands.set(command.data.name, command);
} else {
console.log(`[WARNING] The command at ${filePath} is missing a required "data" or "execute" property.`);
}
}
}
```
</CH.Code>
That's it! When creating new files for commands, make sure you create them inside one of the subfolders (or a new one) in the _`commands`_ folder.
#### Next steps
Your command files are now loaded into your bot, and the event listener is prepared and ready to respond. In the next section, we cover the final step - a command deployment script you'll need to register your commands so they appear in the Discord client.
For fully functional slash commands, you need three important pieces of code:
1. The [individual command files](slash-commands), containing their definitions and functionality.
2. The [command handler](command-handling), which dynamically reads the files and executes the commands.
3. The command deployment script, to register your slash commands with Discord so they appear in the interface.
These steps can be done in any order, but **all are required** before the commands are fully functional.
This page details how to complete **Step 3**. Make sure to also complete the other pages linked above!
</Alert>
## Command registration
Slash commands can be registered in two ways; in one specific guild, or for every guild the bot is in. We're going to look at single-guild registration first, as this is a good way to develop and test your commands before a global deployment.
Your application will need the _`applications.commands`_ scope authorized in a guild for any of its slash commands to appear, and to be able to register them in a specific guild without error.
Slash commands only need to be registered once, and updated when the definition (description, options etc) is changed. As there is a daily limit on command creations, it's not necessary nor desirable to connect a whole client to the gateway or do this on every _`ClientReady`_ event. As such, a standalone script using the lighter REST manager is preferred.
This script is intended to be run separately, only when you need to make changes to your slash command **definitions** - you're free to modify parts such as the execute function as much as you like without redeployment.
### Guild commands
Create a _`deploy-commands.js`_ file in your project directory. This file will be used to register and update the slash commands for your bot application.
Add two more properties to your _`config.json`_ file, which we'll need in the deployment script:
- _`clientId`_: Your application's client id ([Discord Developer Portal](https://discord.com/developers/applications) > "General Information" > application id)
- _`guildId`_: Your development server's id ([Enable developer mode](https://support.discord.com/hc/en-us/articles/206346498) > Right-click the server title > "Copy Server ID")
<CH.Code lineNumbers={false}>
```json
{
"token": "your-token-goes-here",
"clientId": "your-application-id-goes-here",
"guildId": "your-server-id-goes-here"
}
```
</CH.Code>
With these defined, you can use the deployment script below:
<CH.Code>
```js deploy-commands.js
import { REST, Routes } from 'discord.js';
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import config from './config.json' assert { type: 'json' };
const { clientId, guildId, token } = config;
const commands = [];
// Grab all the command files from the commands directory you created earlier
// And of course, make sure you catch and log any errors!
console.error(error);
}
```
</CH.Code>
Once you fill in these values, run _`node deploy-commands.js`_ in your project directory to register your commands to the guild specified. If you see the success message, check for the commands in the server by typing _`/`_! If all goes well, you should be able to run them and see your bot's response in Discord!
### Global commands
Global application commands will be available in all the guilds your application has the _`applications.commands`_ scope authorized in, and in direct messages by default.
To deploy global commands, you can use the same script from the [guild commands](#guild-commands) section and simply adjust the route in the script to _`.applicationCommands(clientId)`_
// And of course, make sure you catch and log any errors!
console.error(error);
}
```
</CH.Code>
### Where to deploy
<Alert title="Tip" type="success">
Guild-based deployment of commands is best suited for development and testing in your own personal server. Once you're satisfied that it's ready, deploy the command globally to publish it to all guilds that your bot is in.
You may wish to have a separate application and token in the Discord Dev Portal for your dev application, to avoid duplication between your guild-based commands and the global deployment.
</Alert>
#### Further reading
You've successfully sent a response to a slash command! However, this is only the most basic of command event and response functionality. Much more is available to enhance the user experience including:
- applying this same dynamic, modular handling approach to events with an [Event handler](./event-handling).
- utilising the different [Response methods](../slash-commands/response-methods) that can be used for slash commands.
- expanding on these examples with additional validated option types in [Advanced command creation](../slash-commands/advanced-creation).
- adding formatted [Embeds](../popular-topics/embeds) to your responses.
- enhancing the command functionality with [Buttons](../interactions/buttons) and [Select Menus](../interactions/select-menus).
- prompting the user for more information with [Modals](../interactions/modals).
Node.js uses an event-driven architecture, making it possible to execute code when a specific event occurs. The discord.js library takes full advantage of this. You can visit the <DocsLink type="class" parent="Client" /> documentation to see the full list of events.
<Alert title="Tip" type="success">
This page assumes you've followed the guide up to this point, and created your _`index.js`_ and individual slash
commands according to those pages.
</Alert>
At this point, your `index.js` file has code for loading commands, and listeners for two events: `ClientReady` and `InteractionCreate`.
Currently, all of this code is in the _`index.js`_ file. <DocsLink type="class" parent="Client" symbol="e-ready" /> emits once when the _`Client`_ becomes ready for use, and <DocsLink type="class" parent="Client" symbol="e-interactionCreate" /> emits whenever an interaction is received.
Moving the event listener code into individual files is simple, and we'll be taking a similar approach to the [command handler](./handling-command-interactions).
## Individual event files
Your project directory should look something like this:
```
discord-bot/
├── commands/
├── node_modules/
├── config.json
├── deploy-commands.js
├── index.js
├── package-lock.json
└── package.json
```
Create an _`events`_ folder in the same directory. You can then move the code from your event listeners in _`index.js`_ to separate files: _`events/ready.js`_ and _`events/interactionCreate.js`_. The _`InteractionCreate`_ event is responsible for command handling, so the command loading code will move here too.
console.log(`Ready! Logged in as ${client.user.tag}`);
}
```
```js index.js
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Client, GatewayIntentBits } from 'discord.js';
import config from './config.json' assert { type: 'json' };
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.login(config.token);
```
</CH.Code>
The _`name`_ property states which event this file is for, and the _`once`_ property holds a boolean value that specifies if the event should run only once. You don't need to specify this in _`interactionCreate.js`_ as the default behavior will be to run on every event instance. The _`execute`_ function holds your event logic, which will be called by the event handler whenever the event emits.
## Reading event files
Next, let's write the code for dynamically retrieving all the event files in the _`events`_ folder. We'll be taking a similar approach to our [command handler](./handling-command-interactions). Place the new code highlighted below in your _`index.js`_.
_`fs.readdir()`_ combined with _`array.filter()`_ returns an array of all the file names in the given directory and filters for only _`.js`_ files, i.e. _`['ready.js', 'interactionCreate.js']`_.
<CH.Code>
```js focus=9:20
import { readdir } from 'node:fs/promises';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { Client, GatewayIntentBits } from 'discord.js';
import config from './config.json' assert { type: 'json' };
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
You'll notice the code looks very similar to the command loading above it - read the files in the events folder and load each one individually.
The <DocsLink type="class" parent="Client" /> class in discord.js extends the [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) class. Therefore, the _`client`_ object exposes the [`.on()`](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener) and [`.once()`](https://nodejs.org/api/events.html#events_emitter_once_eventname_listener) methods that you can use to register event listeners. These methods take two arguments: the event name and a callback function. These are defined in your separate event files as _`name`_ and _`execute`_.
The callback function passed takes argument(s) returned by its respective event, collects them in an _`args`_ array using the _`...`_ [rest parameter syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), then calls _`event.execute()`_ while passing in the _`args`_ array using the _`...`_ [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). They are used here because different events in discord.js have different numbers of arguments. The rest parameter collects these variable number of arguments into a single array, and the spread syntax then takes these elements and passes them to the _`execute`_ function.
After this, listening for other events is as easy as creating a new file in the _`events`_ folder. The event handler will automatically retrieve and register it whenever you restart your bot.
<Alert title="Tip" type="success">
In most cases, you can access your _`client`_ instance in other files by obtaining it from one of the other discord.js
structures, e.g. _`interaction.client`_ in the _`InteractionCreate`_ event. You do not need to manually pass it to
You can provide a _`filter`_ key to the object parameter of <DocsLink type="class" parent="TextChannel" symbol="createMessageCollector" brackets />. The value to this key should be a function that returns a boolean value to indicate if this message should be collected or not. To check for multiple conditions in your filter you can connect them using [logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators). If you don't provide a filter all messages in the channel the collector was started on will be collected.
You can provide a _`filter`_ key to the object parameter of <DocsLink type="class" parent="TextChannel" symbol="createMessageCollector" brackets />. The value to this key should be a function that returns a boolean value to indicate if this message should be collected or not. To check for multiple conditions in your filter you can connect them using [logical operators](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators). If you don't provide a filter all messages in the channel the collector was started on will be collected.
Note that the above example uses [implicit return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#function_body) for the filter function and passes it to the options object using the [object property shorthand](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions) notation.
Note that the above example uses [implicit return](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions#function_body) for the filter function and passes it to the options object using the [object property shorthand](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions) notation.
If a message passes through the filter, it will trigger the <DocsLink type="class" parent="Collector" symbol="e-collect" /> event for the _`collector`_ you've created. This message is then passed into the event listener as _`collected`_ and the provided function is executed. In the above example, you simply log the message. Once the collector finishes collecting based on the provided end conditions the <DocsLink type="class" parent="Collector" symbol="e-end" /> event emits.
@@ -103,7 +103,7 @@ try {
<Alert title="Tip" type="info">
If you don't understand how _`.some()`_ works, you can read about it in more detail
In this filter, you iterate through the answers to find what you want. You would like to ignore the case because simple typos can happen, so you convert each answer to its lowercase form and check if it's equal to the response in lowercase form as well. In the options section, you only want to allow one answer to pass through, hence the _`max: 1`_ setting.
Intents are an important part of establishing a WebSocket connection, as they define behavior regarding gateway events and impact received data via the REST API.
## Usage
```js
import { Client, GatewayIntentBits } from 'discord.js';
const client = new Client({
intents: [GatewayIntentBits.Guilds],
});
```
This is the most basic usage of intents for discord.js. By specifying _`GatewayIntentBits.Guilds`_, your bot will receive gateway events regarding guilds. This includes receiving initial information about guilds it is in at startup, such as role data.
You can find the full list of _`GatewayIntentBits`_ <DiscordAPITypesLink type="enum" parent="GatewayIntentBits">on the documentation</DiscordAPITypesLink> and an explanation of what each intent does [on Discord's API documentation](https://discord.com/developers/docs/topics/gateway#list-of-intents).
## Considerations
In discord.js, some intents require an extra bit of consideration.
### _`GatewayIntentBits.Guilds`_
discord.js relies heavily on caching in the library. We recommend you set at least the _`GatewayIntentBits.Guilds`_ intent to avoid these pitfalls.
### _`GatewayIntentBits.GuildMembers`_
Fetching members in a guild via <DocsLink type="class" parent="GuildMemberManager" symbol="fetch" brackets /> requests them over the gateway. As such, this intent is required and you may receive a timeout error if this intent is not specified.
<Alert title="Info" type="info">
This is a privileged intent. Read on for more information.
</Alert>
### _`GatewayIntentBits.DirectMessages`_
This intent is required to receive direct messages. In discord.js however, you **must** specify partials as well. See the partials topic on how this is done.
### _`GatewayIntentBits.MessageContent`_
Unlike other intents, this only populates user-generated fields. See [Discord's documentation](https://discord.com/developers/docs/topics/gateway#message-content-intent) on what exactly this intent unveils.
It is a common mistake to not see the message content in a message—this is usually because this intent is not specified.
<Alert title="Info" type="info">
This is a privileged intent. Read on for more information.
</Alert>
## Privileged intents
Some gateway events are considered privileged. Currently, these are:
- _`GatewayIntentBits.GuildPresences`_
- _`GatewayIntentBits.GuildMembers`_
- _`GatewayIntentBits.MessageContent`_
To use these intents, you will need to enable them in the developer portal. If your bot is in over 75 guilds, you will need to verify it and request usage of your desired intents.
Carefully think if you need these intents. They are opt-in so users across the platform can enjoy a higher level of privacy. Presences can expose some personal information, such as the games being played and overall online time. You might find that it isn't necessary for your bot to have this level of information about all guild members at all times.
### Disallowed intents
Should you receive an error stating you are using disallowed intents, please review your developer dashboard settings for all privileged intents you use. Check the Discord API documentation for up-to-date information.
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to _`.catch()`_ gets called. Here's the same code but with async/await:
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to _`.catch()`_ gets called. Here's the same code but with async/await:
@@ -10,10 +10,10 @@ It extends JavaScript's native _`Map`_ class, so it has all the _`Map`_ features
<Alert title="Warning" type="warning">
If you're not familiar with _`Map`_, read [MDN's page on
it](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) before continuing. You
should be familiar with _`Array`_
[methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as well. We will
also use some ES6 features, so read up [here](/additional-info/es6-syntax.md) if you do not know what they are.
it](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) before continuing. You should be
familiar with _`Array`_ [methods](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) as
well. We will also use some ES6 features, so read up [here](/additional-info/es6-syntax.md) if you do not know what
they are.
</Alert>
A _`Map`_ allows for an association between unique keys and their values.
@@ -52,7 +52,7 @@ Methods that follow this philosophy of staying close to the _`Array`_ interface
## Converting to Array
Since _`Collection`_ extends _`Map`_, it is an [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an _`Array`_ through either _`Array.from()`_ or spread syntax (_`...collection`_).
Since _`Collection`_ extends _`Map`_, it is an [iterable](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an _`Array`_ through either _`Array.from()`_ or spread syntax (_`...collection`_).
v14 requires Node 16.9 or higher to use, so make sure you're up to date. To check your Node.js version, use _`node --version`_ in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you with this step based on your host system.
v14 requires Node 16.11 or higher to use, so make sure you're up to date. To check your Node.js version, use _`node --version`_ in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you with this step based on your host system.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.