Compare commits

...

157 Commits

Author SHA1 Message Date
Jiralite
2a067216c4 chore: Release @discordjs/voice 0.19.2 (#11450)
chore(voice): release @discordjs/voice@0.19.2

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
2026-03-13 15:23:33 +00:00
Denis-Adrian Cristea
fe5e3c2a82 chore: remove file from root (#11442)
chore: oops

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-13 09:28:42 +00:00
Snazzah
c486fb8127 fix(voice): strip padding from packets and add guards (#11449)
* fix(voice): strip padding from incoming packets

* fix(voice): add additional guards to voice recieve

* chore: apply comments

* chore: fix formatting
2026-03-13 08:36:01 +00:00
Jiralite
f3942a6319 chore: Release @discordjs/voice 0.19.1 (#11446)
* chore(voice): release @discordjs/voice@1.0.0

* chore(voice): release 0.19.1

---------

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
2026-03-09 21:26:11 +00:00
Denis-Adrian Cristea
84b85f4c91 refactor!: remove builders and formatters re-export (#11361)
BREAKING CHANGE: removed builders and formatters re-export
2026-03-07 12:25:00 +02:00
Almeida
52173b6ca8 fix: disable per option validation on chat input subcommands (#11405)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-07 00:02:56 +00:00
Denis-Adrian Cristea
41439d3a40 feat(RedisBroker): discordjs/core gateway impl (#11005)
* feat(RedisBroker): discordjs/core gateway impl

* fix: import

Co-authored-by: Almeida <github@almeidx.dev>

* chore: iterate

* fix: publish properly

* chore: deps and docs

* chore: leftover comment

* chore: suggested changes

* doc: bad comment

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-05 12:27:14 +00:00
Qjuh
d6e1609408 docs(discord.js): less omit types for better docs (#11323)
* docs(discord.js): less omit types for better docs

* chore: refactor guild scheduled event types

* fix: duplicate properties

* fix: use correct type type

* chore: apply suggestion from @almeidx

Co-authored-by: Almeida <github@almeidx.dev>

---------

Co-authored-by: Almeida <github@almeidx.dev>
2026-03-02 21:37:24 +00:00
Naiyar
3e6364070b feat: modal radio group and checkbox components (#11395)
* feat: radio group and checkbox component in modal

* chore: some doc and type fixes

* chore: missing types

* chore: update component names

* docs: radio group value now returns null if not selected

* Remove empty line at the beginning of ModalSubmitInteraction.js

* Change value property to be nullable in RadioGroupModalData

* chore: review

* chore: missing "type"

* chore: suggestion

Co-authored-by: Almeida <github@almeidx.dev>

* chore: review

Co-authored-by: Almeida <github@almeidx.dev>

---------

Co-authored-by: Almeida <github@almeidx.dev>
2026-03-02 21:09:03 +00:00
Almeida
3c9d90ad7e chore: move proxy-container to apps (#11435)
* chore: move proxy-container to apps

* chore: limit next/react rules to next apps

* chore: add standalone issue template

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-02 19:34:45 +00:00
VAKiliner
ec796caf00 fix(GuildChannel): Handle empty overwrite must only handle @everyone (#11221)
* Add check overwrite id

* Update GuildChannel.js

* Update GuildChannel.js

* chore: fmt

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-02 19:02:24 +00:00
Almeida
f1949271a0 docs: add missing ApplicationCommandPermissionsUpdateData (#11415)
* docs: add missing ApplicationCommandPermissionsUpdateData

* Update packages/discord.js/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-03-02 10:43:55 +00:00
Asad Humayun
fce498982a fix(structures): add missing toJSON method on Subscription structure (#11431)
fix(structures): add missing `toJSON` method on Subscription

When writing tests for #11407, it became apparent that I had forgotten to add the `toJSON` method for this structure when I was initially wrote the structure. I have now added this method and it passes when running the tests that I have written for this (which will be merged in a following PR).

Signed-off-by: Asad Humayun <asad.humayun@asadh.io>
2026-03-01 21:10:26 +00:00
Almeida
307b64f139 chore: make docgen package private (#11434) 2026-03-01 12:44:06 +00:00
faceboy
0cb8be490c docs(builders): edited docs to correctly link to splice (#11430)
fix(builders): edited docs to correctly link to splice

StringSelectMenuBuilder.splice()'s docs incorrectly linked to slice instead of splice in MDN docs, fixed that
2026-02-25 05:46:25 +00:00
Jiralite
77e767277b build: Upgrade dependencies and pnpm (#11420)
* build: upgrade dependencies

* build: upgrade pnpm

* test: fix voice

* build: regenerate file

* fix: reports by ESLint

* fix: docs errors

* build: downgrades

* build: no upstream bump

* build: discord-api-types 0.38.40

* build: pnpm 10.30.1

* fix: ignore @typescript-eslint/no-duplicate-type-constituents

* fix: jsdoc lint in api-extractor

* build: update template for ESLint

Co-authored-by: Almeida <github@almeidx.dev>

* chore: explicit TODO

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: revert typings lint change

---------

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
2026-02-20 17:44:38 +00:00
Qjuh
ccce987fa1 types: broadcastEval overload order (#11421)
* types: broadcastEval overload order

* types: also apply to ShardClientUtil
2026-02-16 13:20:59 +00:00
Almeida
a3e189df00 feat: emit voiceServerUpdate event (#11414)
* feat: emit voiceServerUpdate event

* fix: add back debug log

* refactor: censor token in debug logs

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-02-08 16:48:49 +00:00
Asad
c460a920ac feat(structure): add Webhook structure (#11401)
* feat(structure): add barrel exports for Webhook structure

* feat(structure): add Webhook structure

* chore(structures): lib exports consistency

* docs: update docs
2026-02-06 16:57:49 +00:00
Asad
c71228aab3 feat(structures): add SKU structure (#11389)
* feat(structures): update barrel exports in preparation for SKU structure

* feat(structures): add SKUFlagsBitField to /bitfields

* feat(structures): add SKU structure

* chore(structures): correct barrel exports

* chore(structures): export SKUBitfieldFlags

* docs(structures): correct usage of see/link doc comments

* chore(structures): correct usage of bitfields in extending classes

* docs(structures): remove unnecessary links

* fix(structures): correctly apply bitfields, introduced in #11404

---------

Co-authored-by: Almeida <github@almeidx.dev>
2026-01-28 01:08:43 +00:00
Asad
b0e413c116 feat(structure): add voice structure (#11400)
* feat(structure): add Voice structures

* feat(structure): add VoiceState structure

* feat(structure): add VoiceRegion structure

* chore(structures): lib exports consistency

---------

Co-authored-by: Almeida <github@almeidx.dev>
2026-01-27 23:17:01 +00:00
Asad
65386034b6 feat(structures): add SoundboardSound structure (#11390)
* feat(structures): update barrel exports in preparation for new structure

* feat(structures): add SoundboardSound structure

* chore(structures): update doc comment

* chore(structures): address review suggestions

* chore(structures): consistency changes and use isIdSet to retrieve id

* docs(structures): add remarks to conditionally present attributes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 23:10:19 +00:00
Asad
1251d479b0 feat(structures): add StickerPack structure (#11398)
* feat(structures): update barrel exports

* feat(structures): add StickerPack structure

* chore(structures): add createdAt and createdTimestamp to Sticker struct

* docs(structure): correct usage of links in see/link blocks

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 23:06:28 +00:00
Asad
693fcbc32b feat(structures): add Stage Instance structure (#11397)
* feat(structures): update barrel exports for stage instance structure

* feat(structures): add stage instance structure

* docs(structure): cleanup and use see/link correctly

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 23:03:09 +00:00
Asad
c126367140 feat(structures): add Team structure (#11396)
* feat(structures): add and update barrel exports in prep for new struct

* feat(structures): add TeamMember substructure

* feat(structures): add Team structure

* chore(structures): add ownerUserId attribute back

* chore(structures): add teamId attribute

* docs(structures): correctly use see/link blocks and cleanup

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 22:59:42 +00:00
Asad
fc5ba6be70 feat(structures): add Subscription structure (#11399)
* feat(structure): update barrel exports for new structure

* chore(structure): add new symbols for the Subscription structure

* feat(structure): add Subscription structure

* docs(structure): correct typos

* chore(structure): add default attributes on class params

* fix(structures): correctly expose [..]Ids properties and update docs

* fix(structures): add canceled_at to DataTemplate

* docs(structures): update doc clarity on canceledAt getter - @almeidx

This was a suggestion by Almedia.

Co-authored-by: Almeida <github@almeidx.dev>

* style: fix

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 22:56:06 +00:00
Qjuh
7a7fecbe3c fix(structures): correctly check if flags are present (#11404)
* fix(structures): correctly check if flags are present

* chore: isFieldSet type guard

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-27 16:47:56 +00:00
Vlad Frangu
323d8e7571 fix(voice): always install Davey as DAVE is becoming required (#11385)
* fix(voice): always install Davey as DAVE is becoming required

* chore: requested changes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-25 20:28:04 +00:00
Asad
3550b497f6 feat(structures): add AutoModeration structures (#11381)
* feat(structures): add barrel exports in preparation new structures

* feat(structures): add AutoModerationRule structure

* feat(structures): add AutoModerationRuleTriggerMetadata structure

* feat(structures): add AutoModerationAction substructure

* feat(structure): add AutoModerationActionMetadata substructure

* chore: correct typo

* chore: do not expose exemptRoles and exemptChannels as getters

* feat(structures): rename substructure files

* chore(structures): update barrel exports

* chore(structures): export automod structures in package barrel exports
2026-01-24 19:40:01 +00:00
René
838cd2da34 perf(collection): use object destructuring of entry tuples (#11391) 2026-01-22 09:13:43 +00:00
Almeida
017176926a refactor: move full validation to ChatInputCommandBuilder (#11304)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-16 16:54:51 +00:00
ManHam
be78e26729 feat: add Bun templates for create-discord-bot (#11348)
* feat: add Bun templates for create-discord-bot

- Add TypeScript Bun template with complete src structure
- Add JavaScript Bun template with complete src structure
- Both templates mirror the Node.js versions with Bun-specific configuration

Closes #11346

* fix: update template and bun template loading

---------

Co-authored-by: almeidx <github@almeidx.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-16 15:32:20 +00:00
jacobhumston
52a69d77d0 feat(create-discord-bot): allow certain files/folders to be included in the target directory (#11368)
* feat(create-discord-bot): allow empty git repositories

* feat(create-discord-bot): create a .gitignore for git repositories

* fix(create-discord-bot): correctly handle .git file edge case

* refactor(create-discord-bot): use next.js "is-folder-empty" utility

* refactor(create-discord-bot): combine checks

* revert: revert comment change

This reverts commit 2f8422e90d.

* feat(create-discord-bot): add .gitignore to templates

* docs(create-discord-bot): add source link to isFolderEmpty util

* docs(create-discord-bot): add @license JSDoc tag to license comment

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-16 12:57:47 +00:00
Asad
3d74122215 feat(structures): add entitlement structure (#11377)
* feat(structures): add entitlement structure

* feat(structures): create and update barrel exports

* chore: reword comment for entitlment deleted getter to be clearer

* feat(structures): add symbols to optimise ends_at, starts_at fields

* feat(structures): optimise starts_at and ends_at fields

* feat(structures): manage Date and Discord ISOs appropriately

* chore: remove accidental whitespace

* chore: correct name styles on symbols (remove 'at')

* chore: correct name styles on AtTimestamp fields (remove 'at')

* chore: call super.toJSON on toJSON override

* chore: run prettier to clear linting/formatter errors

* chore: correct usage of optimizeData

* chore: update DataTemplate override for Entitlement

* chore: update class default type param, update DataTemplate doc

* Apply suggestions from code review

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2026-01-15 23:43:39 +00:00
Asad
69432a1bca feat(structures): add emoji structure (#11369)
* feat(structures): add emoji structure

* chore: update deps

* chore: update deps

* chore: update deps

* Revert "chore: update deps"

This reverts commit 8332f48611.

* Revert "chore: update deps"

This reverts commit a168e735a3.

* Revert "chore: update deps"

This reverts commit 0b19058cda.

* chore: consistency (capitalisation)

* fix(structures): do not export substructures from emoji structure

* chore(structures): add remark detailing substructures

* chore: update remarks to reflect exported substructures (remove roles)

* chore: update remarks to explain why roles not exposed on structure
2026-01-15 23:31:35 +00:00
Aryan Bagade
8ccae833e7 types(UserManager): fix send() return type to Promise<Message<false>> (#11337)
* types(UserManager): fix send() return type to Promise<Message<false>>

UserManager.send() always sends a direct message (DM), so the return type should b Promise<Message<false>> instead of Promise<Message> to correctly indicate that the message is not in a guild context.

Closes #11331

* fix: requested changes

---------

Co-authored-by: almeidx <github@almeidx.dev>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2026-01-02 17:56:34 +00:00
Souji
c921e84531 feat(guide): update member fetch errors (#11374)
* feat(guide): update member fetch errors

* member count is no longer relevant, since the timeout resets on each chunk
* add link to the dev portal on members didn't arrive in time
* add section about opcode 8 gateway rate limit

resolves #11245 #11277

* chore: add missing period on list item

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2026-01-02 14:17:24 +00:00
kikorp78
311413e5f2 fix: broken link on sharding page (#11373) 2025-12-26 00:45:21 +00:00
yokkkoso
7884ecd3a0 fix(emojiPredicate): wrong min name length (#11371) 2025-12-23 18:54:17 +00:00
Pavel-Boyazov
427636ee75 types(Message): specify rawData arg type (#11123)
Co-authored-by: Almeida <github@almeidx.dev>
2025-12-17 19:04:17 +00:00
Almeida
cad826fc03 feat(RoleManager): add fetchMemberCounts (#11352)
* feat(RoleManager): add `fetchMemberCounts`

* docs: improve description

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>
2025-12-17 18:59:50 +00:00
Vlad Frangu
51b5d38342 feat: proper authorizing integration owners structure (#11366)
* feat: proper authorizing integration owners structure

chore: fix ci

chore: fix types

chore: fix types

chore: nits

chore: tests

chore: requested changes

chore: drop it from apitypes

chore: requested 2

chore: rofl

chore: docs

* chore: docs

* chore: docs

* Apply suggestions from code review

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-17 18:55:05 +00:00
Marko Kajzer
5f93fbd0f2 fix(voice): handle negative timeouts (#11362) 2025-12-17 18:53:10 +00:00
Snazzah
c4fc79a3cd fix(voice): handle multiple transitions simultaneously (#11100)
* fix(voice): handle multiple transitions simultaneously

* fix: fix execute transition return

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-12 15:49:37 +00:00
Vlad Frangu
5b4dbd541e feat: zstd streaming support (#10758)
* feat(ws): zstd streaming support

* chore: naming of the mode

* fix: remove `@ts-expect-error`

---------

Co-authored-by: Almeida <github@almeidx.dev>
2025-12-12 13:01:25 +00:00
Almeida
df0c28afc2 feat(GuildsAPI): add getRoleMemberCounts (#11353)
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-12-11 01:48:28 +00:00
Almeida
451a6380c6 fix: handle github api errors gracefully (#11357)
* fix: handle github api errors gracefully

* fix: remove forks and improve log
2025-12-10 23:03:32 +01:00
Almeida
01f31f374a chore: bump dependencies (#11356)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-10 17:53:48 +00:00
Denis-Adrian Cristea
9bf1f739e0 chore: remove usage of the prefer-global rules (#11279) 2025-12-10 14:05:29 +00:00
Copilot
548d75258b perf: Optimize Collection.equals() to reduce redundant map lookups (#11344)
* Initial plan

* Optimize Collection.equals() to avoid redundant map lookups

Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>

* Add explanatory comment for equals() undefined check optimization

Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-09 21:22:14 +00:00
Almeida
6a129bc054 chore: lower concurrency on index upload (#11351)
* chore: lower concurrency on index upload

* chore: increase timeout
2025-12-09 21:02:57 +00:00
Almeida
f60d3d65fe refactor!: move embedLength function to util package (#11327)
BREAKING CHANGE: Builders no longer exports a `embedLength` function. Import it from `@discordjs/util` instead.

Co-authored-by: Danial Raza <danialrazafb@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-12-09 18:40:34 +00:00
jNullj
4db1092f8f docs(voice): add DAVE dependency section (#11061)
* docs(voice): add DAVE dependency section

continues work found at https://github.com/discordjs/discord.js/issues/10735

Read more at https://discord.com/developers/docs/change-log#voice-endtoend-encryption-dave-protocol

* docs(voice): fix dave dependency note order

* remove explicit warning regarding optional dependency being optional

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
2025-12-09 17:48:24 +00:00
Almeida
eaa6863f93 fix: lockfile (#11347) 2025-12-09 13:29:01 +00:00
Almeida
06c8da23d1 chore: update deps & search indice action refactor (#11339)
* chore: update deps & search indice action refactor

- Updated pnpm, dependencies and regenerated the lockfile
- Removed immer and some eslint plugins that weren't being used
- Updated the version of `@types/node` to v24 on internal packages as
  that's the version that is being used on github actions
- Refactored the uploadSearchIndices action slightly and upgraded the
  meilisearch dependency

* chore: remove more deps
2025-12-09 13:47:46 +01:00
Jiralite
2c3bf5c817 ci: Upload README.md files (#11342)
* feat: upload README.md files

* ci: build actions

* fix: build action

* chore: force rename
2025-12-09 03:22:39 +01:00
Almeida
ec3ef7b1bd feat: use native node typescript (#11259)
* feat: use native node typescript

* fix: use basename

* Update packages/create-discord-bot/template/Bun/TypeScript/tsconfig.json

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Change module and moduleResolution to ESNext and Bundler

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-12-09 03:22:16 +01:00
Almeida
c9bc33c758 fix(stringOptionPredicate): min_length and max_length min values (#11340)
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-12-09 00:20:15 +00:00
Noel
f38395ec4e fix: update MeiliSearch API key 2025-12-09 00:48:57 +01:00
Almeida
ec76b17be3 chore: workflow and docker image tweaks (#11341) 2025-12-09 00:15:14 +01:00
Jiralite
d90a86a048 fix(Message): Optional parameter for setting allowed mentions (#11338)
feat: allow empty allowed mentions

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-08 23:14:34 +00:00
Egologics
fa43c40d34 fix(builders): handle 0 as valid attachment ID (#11330)
* fix(builders): handle 0 as valid attachment ID

Fixes #11314

The AttachmentBuilder.getRawFile() method was using a falsy check that treated 0 as invalid. Changed to use the 'in' operator to properly check for the existence of the id property.

* Update packages/builders/__tests__/messages/fileBody.test.ts

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* Apply suggestion from @almeidx

* fix: lint

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-08 23:08:36 +00:00
Almeida
d0745afbea chore: upgrade vitest to v4 (#11336) 2025-12-08 18:55:45 +00:00
Almeida
d518c97840 chore: upgrade storybook to v10 (#11334)
- Replaced deprecated `@storybook/addon-styling` with `@storybook/addon-themes`
- Removed deprecated `@storybook/addon-essentials` and `@storybook/addon-interactions`
- Upgraded `chromatic`, although it's seemingly unused anywhere
- Upgraded `@types/node` to match the ones in the guide and website

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-08 08:27:04 +00:00
Denis-Adrian Cristea
9005c8ae9c refactor!: remove AttachmentBuilder and support new file body encodables (#11278)
BREAKING CHANGE: Remove AttachmentBuilder

---------

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-12-08 10:19:43 +02:00
Almeida
5888663392 test: fix type errors (#11325)
* test: fix type errors

* chore: use MockedFunction

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-08 00:24:29 +00:00
Almeida
8d33188ac1 feat: use turbopack for prod builds (#11335) 2025-12-08 00:17:16 +00:00
Jiralite
5e6bd4b3d7 build: Bump dependencies (#11333)
* build: bump dependencies

* fix: guide build

* build: amend package.json.hbs

* build: create-discord-bot

* style: formatting

* build: final change

---------

Co-authored-by: almeidx <github@almeidx.dev>
2025-12-06 22:55:07 +00:00
Almeida
0aaba0305f fix(undiciRequest): file uploading (#11320)
* fix(undiciRequest): file uploading

* fix: different approach

* fix: revert to the previous approach

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-03 14:40:15 +00:00
IllagerCaptain
633fdd8f28 feat(Guild): Add maximumStageBitrate (#11313)
* Add `maximumStageBitrate : number`

* Add `maximumStageBitrate : number`

* oops

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-02 23:26:15 +00:00
Almeida
87b359e44d fix: replace usages of Buffer#slice() with Buffer#subarray() (#11326)
fix: replace usages of Buffer.slice() with Buffer.subarray()

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-12-02 23:13:10 +00:00
Jiralite
ec7047572e chore: Delete the pull request template (#11301)
Delete .github/PULL_REQUEST_TEMPLATE.md

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-30 21:59:23 +00:00
Jiralite
2520a0fb96 chore: @favware/cliff-jumper schema (#11328)
* chore: add schema

* chore: template pain

* build: remove from docgen
2025-11-30 21:54:51 +00:00
Jiralite
a57b4d4d29 fix: Allow mixing subcommands with subcommand groups (#11303)
fix: allow subcommand with groups

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-30 16:48:19 +00:00
Jiralite
8162ae8ce0 test: Add toJSON() to tests (#11321)
test: fix validation

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-30 16:41:48 +00:00
Jiralite
ace834b274 fix: Adjust label predicates and fix buttons emoji/label behaviour (#11317)
* fix: buttons with custom id

* fix: button labels

* fix: also add refinement to link buttons

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-30 16:17:50 +00:00
Rie
d59857e901 fix(builders): add proper snowflake validation (#11290)
* fix(builders): add proper snowflake validation

close #11289

* fix(builders): use snowflake validation for attachment id

* test(builders): add validation tests for snowflake attachment IDs

* fix: better regex

Co-authored-by: Almeida <github@almeidx.dev>

* test(builders): fix snowflake validation in fileBody test

* Update packages/builders/src/Assertions.ts

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* fix: update regex

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-30 15:30:04 +00:00
Qjuh
19253f6b7b feat: message structures (#10982)
* feat: message structures

* fix: docs

* chore: components and more

* feat: embed and more

* feat: more substructures and code review suggestions

* chore: tests and date conversions

* chore: jsdoc strings

* fix: tests

* fix: tests

* feat: hexColor getters

* chore: remove getters for nested data

* chore: apply suggestions from code review

* fix: burst_colors in toJSON

* docs: rephrase SectionBuilder remark

* chore: add LabelComponent

* fix: add name and size to file component

* chore: move resolved interaction data to interactions dir

* fix: code review

* chore: bump discord-api-types

* chore: apply code review suggestions

* fix: lockfile

* chore: update remark

* fix: missing export

* chore: code review and tests

* build: fix file

* fix: typo

* fix: missing toJSON

* fix: remove redundant patch overrides

* chore: missing component suffix

* chore: better name

* chore: add comment explaining timestamp conversion

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-11-28 16:52:42 +00:00
VAKiliner
aeb8986aa1 fix(Client): Move client initialization code (#11184)
* Update index.js

* Fix

* Fix path to ClientUser

* Update Client.js

* Migrating back to READY.js

* Move _checkReady()

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>
2025-11-28 14:12:23 +00:00
Souji
444e55a093 feat(guide): updating section (#11322)
feat: sidebar, layout, initial content

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-11-28 11:37:19 +00:00
William Bowen
b2cbdf1567 feat(guide): updated modal page for label (#11169)
* feat(guide): updated modal page for label

* feat(guide): updated modal page with modal component sections

* feat(guide): added modal to select menu page

* fix(guide): moved select menu and add text display callout

* feat(guide): reworked to show modal together instead of separately

* feat(guide): added file upload  to modal

* fix: code block focus in modals

* fix: grammar

* fix: grammar and wording

* feat: structure and readability

General improvements to structure and reading flow
* Reword sentence structure
* Use semantic code highlights
* Consistent heading casing
* Add additional explanations and elaborations
* Adapt legacy examples in text
* Omit repeated code for brevity and less scrolling

* fix: updated example Image

* chore: typos, grammar, rephrasing

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Ryan Munro <monbrey@gmail.com>

* chore: review rephrasing

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Ryan Munro <monbrey@gmail.com>

* chore: rephrasing for correctness

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* chore: rephrasing for correctness

* chore: rephrasing for correctness

* chore: formatting

* chore: rephrasing for correctness

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* chore: update text

---------

Co-authored-by: almostSouji <timoqueezle@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Ryan Munro <monbrey@gmail.com>
2025-11-28 11:33:26 +00:00
Jiralite
02fc101069 fix(DJSError): Differentiate error type (#11295)
* fix(DJSError): differentiate error type

* fix: remove `?.`
2025-11-22 20:22:55 +00:00
Jiralite
db41d5cb68 refactor(DJSError): Prefer this.constructor.name (#11294)
refactor(DJSError): prefer `this.constructor.name`
2025-11-22 12:45:33 +00:00
Danial Raza
179525d9fc fix: typos (#11293) 2025-11-22 10:08:20 +00:00
Jiralite
0b12263371 fix(GuildEmojiManager)!: Allow CreateGuildExpressions for retrieving author data (#11283)
* fix(GuildEmojiManager): allow `CreateGuildExpressions`

* fix!: update error code

BREAKING CHANGE: `MissingManageGuildExpressionsPermission` has become `MissingGuildExpressionsPermission`.
2025-11-20 23:15:58 +00:00
Almeida
456a6f4548 fix: header link on packages with entrypoints (#11285)
* fix: header link on packages with entrypoints

* types: add types

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-20 21:22:36 +00:00
Jiralite
5130d6f56c fix: Sort package versions (#11284)
* fix: sort package versions

* refactor: remove spaces

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-20 21:17:28 +00:00
Jiralite
5dea94602e ci: Remove tags instead of only deprecating (#11263)
ci: deprecate -> remove

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-20 20:17:00 +00:00
Denis-Adrian Cristea
68bb8af58a feat(builders): multipart form data output support (#11248)
* feat(builders): multipart form data output support

* refactor: proper key management

* chore: add missing remarks

* chore: requested changes

* chore: rename encodables file

* chore: requested changes

* chore: requested changes

* chore: nits

Co-authored-by: Almeida <github@almeidx.dev>

* chore: requested change

* chore: requested change

---------

Co-authored-by: Almeida <github@almeidx.dev>
2025-11-19 21:59:51 +00:00
Jiralite
315f422781 fix: Mark external links as external (#11282)
fix: mark external links as external
2025-11-18 15:56:57 +00:00
Jiralite
9d5c6b4588 fix(Util): Resolve circular dependency (#11276)
* fix(Util): resolve circular

* refactor: lazily load all other circulars
2025-11-15 10:06:05 +00:00
Danial Raza
7349a6ee3e refactor(client)!: remove BaseClient (#11274)
BREAKING CHANGE: `BaseClient` has been removed and its functionality has been merged into `Client`.
2025-11-14 23:03:39 +01:00
Jiralite
87364c7ed9 docs(MessageManager): Update fetchPins() wording (#11275)
docs(MessageManager): update `fetchPins()` wording
2025-11-14 21:23:58 +00:00
Denis-Adrian Cristea
25aff7e218 feat(GuildMemberManager): handle gateway request rate limit (#11252)
* feat(GuildMemberManager): handle gateway request ratelimit

* chore: typo no one saw

* fix: cleanup listener properly

* types: add error code

* refactor: requested changes

* fix: update emitted warning

* chore: requested changes

* refactor: remove event

* refactor: warning

* chore: wording

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
2025-11-14 20:51:54 +00:00
ckohen
9f18cb2129 refactor(Webhooks)!: remove WebhookClient (#11266)
BREAKING CHANGE: WebhookClient has been removed, use @discordjs/core instead or fetch webhooks. Alternative solutions are in the works
BREAKING CHANGE: `WebhookURLInvalid` is no longer an error code (obsolete).

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-11-13 12:57:00 -08:00
Jiralite
837af56cf8 fix: Remove data conditional check (#11250)
* fix: remove conditional

* types: sort types
2025-11-12 13:31:13 +00:00
Danial Raza
e8217e335c feat!: support new s/S timestamp styles (#11267)
BREAKING CHANGE: `TimestampStyles.LongTime` has been removed. Use `TimestampStyles.MediumTime` instead.
BREAKING CHANGE: `TimestampStyles.ShortDateTime` has been removed. Use `TimestampStyles.LongDateShortTime` instead.
BREAKING CHANGE: `TimestampStyles.LongDateTime` has been removed. Use `TimestampStyles.FullDateShortTime` instead.
2025-11-12 10:55:20 +00:00
Almeida
538b47dd00 feat: upgrade zod to v4 (#11258)
* feat: upgrade zod to v4

* fix: requested changes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-12 10:07:58 +00:00
Danial Raza
d923e90ae6 chore: migrate eslint configs (#11234)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-12 09:50:07 +00:00
Jiralite
8ed93b3269 types(DiscordjsErrorCodes): Add missing permission overwrites error codes (#11256)
types: add missing types

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-12 07:25:30 +00:00
Qjuh
5619137acd feat(api-extractor-model): use correct version for external packages (#11255)
Co-authored-by: Danial Raza <danialrazafb@gmail.com>
2025-11-11 20:40:22 +00:00
Souji
35996b7d75 fix: issue template guide (#11254)
* Add guide content issue template

* remove empty line

* fix: typo

* chore: add guide as issue template code owners

* chore: add core as additional template code owners

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-11 20:28:25 +00:00
Denis-Adrian Cristea
d3d6777ef8 feat(core): handle request all guild members rate limit (#11251)
* feat(core): handle request all guild members rate limit

BREAKING CHANGE: `Gateway` now requires `off` `once` methods

* fix: weird import update

* refactor: error class

* refactor: error class again

* refactor: requested changes

* chore: fix dep

* fix: suggested changes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-11 07:14:57 +00:00
Denis-Adrian Cristea
37a38883d7 refactor(publish-dev): take ref instead (#11236)
* refactor(publish-dev): take ref instead

* fix: main checks

* chore: relevant examples

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-10 14:39:42 +00:00
Josef
c85f18c1ee feat: optimize role manager cache getter (#11239)
Co-authored-by: Almeida <github@almeidx.dev>
2025-11-09 10:51:40 +00:00
Kendell R
9723cc590b fix: improve handling of italics in the presence of links (#11064)
* fix(formatters): don't escape * in links

* add test for * -> * in url

* `\S+` -> `\S*` (tested locally)

* @Qjuh: handle italics both inside+outside <url>s

* more accurate <link> matcher

---------

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
2025-11-09 09:02:25 +00:00
Jiralite
3cb3ecae21 docs(BaseSelectMenu): Adjust maximum wording (#11249)
docs(BaseSelectMenu): adjust wording

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-05 19:30:36 +00:00
Almeida
dafdc78e73 chore: upgrade actions/setup-node to v6 and node.js to v24 (#11237)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-05 18:38:02 +00:00
Jiralite
3122da4ea4 ci(deprecate-tag): Remove comment (#11246)
ci: remove #

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-05 18:36:06 +00:00
Souji
4da0c03784 chore: add guide issue template (#11247)
* Add guide content issue template

* remove empty line
2025-11-05 19:31:40 +01:00
Denis-Adrian Cristea
4c18a89c2f feat(ci): deprecate tag (#11235)
* feat(ci): deprecate tag

* fix: wildcard

* chore: newer deps

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-05 11:35:01 +00:00
Almeida
4359914d1a fix: open graph image in metadata (#11244)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-03 20:14:39 +00:00
ckohen
b026d0ee35 ci: fix pinning (#11243) 2025-11-03 06:37:21 +00:00
ckohen
3bb13f96b4 ci(dev): pin associated dev versions (#11238) 2025-11-02 05:38:17 +00:00
Naiyar
06a75e80bc docs: clarify wording for maximum values (#11231)
* docs(FileUpload): clarify wording

* chore: missed instances

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-11-01 14:33:34 +00:00
Danial Raza
f26a5ed869 fix: only pass relevant options to API when fetching (#11228)
* fix: only pass relevant options to API when fetching

* chore: requested changes

* fix: missed instance
2025-10-31 20:48:51 +00:00
Almeida
d06d8c0806 chore: update readme package list (#11218)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-31 11:23:16 +00:00
ckohen
d8b913449e ci: refactor turbo team to use var (#11219)
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-31 11:21:42 +00:00
Almeida
fb5c629638 chore: bump dependencies (#11225) 2025-10-31 11:15:45 +00:00
TÆMBØØ
178c9cb348 fix(GuildMember): joinedAt possibly being NaN (#11224) 2025-10-30 20:59:02 +00:00
Danial Raza
94a9b4d03c fix(Message): update pinnable to use PinMessages (#11202)
* fix(Message): update `pinnable` to use `PinMessages`

* refactor: use bitwise OR

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* fix: check if in voice based channel for pinnable

* Update packages/discord.js/src/structures/Message.js

* Update packages/discord.js/src/structures/Message.js

Co-authored-by: Almeida <github@almeidx.dev>

* Update packages/discord.js/src/structures/Message.js

Co-authored-by: Almeida <github@almeidx.dev>

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <github@almeidx.dev>
2025-10-28 14:54:22 +00:00
Almeida
4c0d667773 fix: retry google fonts fetch on fail (#11217)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-26 22:15:12 +00:00
Almeida
4f9475d937 chore: fix executable file permissions (#11216)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-26 21:48:40 +00:00
Jiralite
868be4eafc feat: Annotate result of releasing packages (#11200)
* feat: annotate result

* feat: note dry runs

* refactor: summaries
2025-10-26 21:40:49 +00:00
Copilot
ed143a6cda fix(GuildMemberFlagsBitField): Remove duplicate "guild" word (#11212)
* Initial plan

* Fix duplicate 'guild' word in GuildMemberFlagsBitField documentation

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-26 10:46:16 +00:00
Jiralite
56662ebad7 types(FileUploadModalData): Correct fields (#11210)
* types(FileUploadModalData): update fields

* docs: update more fields
2025-10-25 22:57:00 +00:00
Jiralite
8066821faa types(LabelModalData): Singular ModalData (#11207)
types(LabelModalData): no array
2025-10-25 19:12:17 +00:00
Jiralite
3048c3c0aa types(FileUploadComponentData): required should be a boolean (#11205)
types(FileUploadComponentData): `boolean`
2025-10-25 16:19:50 +00:00
Jiralite
2a5d99f0a0 ci(documentation): Ignore tag pushes for create-discord-bot (#11201)
ci(documentation): ignore create*
2025-10-25 02:42:22 +02:00
Jiralite
633d4813ef fix: Remove outdated documentation logic (#11203)
fix: remove unused stuff
2025-10-25 02:32:01 +02:00
Noel
08b87d9087 refactor(website,guide): cloudflare workers support (#11204) 2025-10-25 02:17:59 +02:00
Jiralite
756eac6bb1 fix: Use D1 for indices (#11199)
* fix: use D1 for indices

* fix: use D1 for indices

* build: remove unused packages

* fix: pass variables

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-24 20:08:49 +00:00
ckohen
ee3be2c3c3 refactor(ApplicationCommand)!: make options nullable (#11167)
BREAKING CHANGE: ApplicationCommand#options is now nullable

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-24 20:32:41 +01:00
Jiralite
c05f653f0a chore: Release create-discord-app/bot (#11198)
* build: bump versions

* build: specify `monoRepo`

Specifying that this is a monorepo seems to fix changelog generation and the conventional bumping.

* chore(create-discord-bot): release create-discord-bot@4.1.0
2025-10-24 19:06:45 +01:00
Vlad Frangu
0c1ff5ea29 types(core): use result types instead of direct types (#11140)
* types(core): use result types instead of direct types

fix: import pains

chore: apply suggestion from review

Co-authored-by: Almeida <github@almeidx.dev>

chore: fmt script

chore: requested change

* chore: rename script, fix build

* chore: types

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-24 15:36:54 +00:00
Jiralite
a990eefa31 fix: 404 for an unknown package's landing page (#11193)
* fix(page): 404 if no package

* fix: we go hard

Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>

* fix: pain

Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
Co-authored-by: Denis-Adrian Cristea <didinele.dev@gmail.com>
2025-10-24 15:06:14 +00:00
ckohen
63417e8b6c refactor(makeCache)!: make params an object (#11172)
BREAKING CHANGE: `Options.makeCache` now sends all of its parameters in an object rather than 3 individual parameters

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-24 15:55:29 +01:00
Naiyar
c9a9b6ce9d feat: file upload component (#11114)
* feat: file upload component

* docs: correct min values

* chore: rebase

* chore: resolve attachments

* chore: typings

* chore: whyyyyyyyyy

* types: `Snowflake`

* types: `Snowflake`

* docs: `Snowflake`

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-24 11:09:33 +00:00
Jiralite
83ec0fdcdf refactor: Use idPredicate for file uploads (#11195)
refactor: use `idPredicate`
2025-10-24 10:45:37 +00:00
Jiralite
c84024968e feat: File upload support (#11108)
* build: bump discord-api-types

* feat: add support

* docs: correct examples

* fix(MappedComponentTypes): fix description

Co-authored-by: advaith <advaithj1@gmail.com>

* fix: use `z.int()`

* chore: remove errors

---------

Co-authored-by: advaith <advaithj1@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-24 10:16:05 +00:00
thelegendfox
63b5923deb fix: Singular misplaced comma (#11194)
docs: Fix misplaced comma
2025-10-24 09:54:33 +00:00
Qjuh
886d4a7fcb fix(website): don't error if unstable node missing (#11191)
fix: don't error if unstable node missing
2025-10-22 16:19:33 +00:00
Qjuh
697556fd16 feat(website): parse and show unstable tsdoc tag (#11187)
feat(website): parse and show unstable tsDoc tag
2025-10-22 11:53:56 +00:00
Naiyar
68835b3ff7 refactor(guide): redirect old urls to /legacy (#11170)
* refactor(guide): redirect old urls to /legacy

* chore: suggestion

Co-authored-by: Almeida <github@almeidx.dev>

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-20 13:13:36 +00:00
Jiralite
0cc92bd5b0 fix(textInput): Allow empty strings for a value (#11182)
fix: allow empty strings

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-16 13:55:15 +00:00
Souji
d03eb5e26e chore(guide): manually sort popular topics (#11174) 2025-10-16 09:21:07 +00:00
Jiralite
25b22c67aa fix(ModalSubmitInteraction): Resolve components correctly (#11168)
* fix: resolve components correctly

* fix: remove redundant parameter

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-14 22:01:10 +00:00
ckohen
0add790169 chore: remove old release ci (#11171)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-14 19:11:43 +00:00
Naiyar
1a305fe4ad build: bump discord-api-types to 0.38.30 (#11178)
* build: bump discord-api-types to 0.38.30

* chore: slap the errors
2025-10-14 18:02:10 +00:00
Souji
93e96eb6c0 feat(guide): add reason for missing access (#11173)
* feat(guide): add reason for missing access

* chore: grammar

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-14 12:04:52 +00:00
ckohen
7a3a21b26e ci(release): better final output (#11177)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-14 09:26:11 +00:00
Souji
a2d4f187ca chore(guide): consistent sidebar capitalization (#11175) 2025-10-14 00:16:26 +00:00
Denis-Adrian Cristea
f9ca29e3e4 chore: update readme badges (#11152)
* chore: update readme badges

* chore: add href

* chore: other readmes

* chore: reintroduce badge

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-13 12:54:08 +00:00
jNullj
180dd60c61 feat(voice): Add info about DAVE protocol dependencies and support (#11145)
* Add info about DAVE protocol dependencies and support

Changes remade from https://github.com/discordjs/guide/pull/1630 due to project moving from that repo to this one.

* remove explicit warning regarding optional dependency being optional

Co-authored-by: Almeida <github@almeidx.dev>

* style: format

---------

Co-authored-by: Almeida <github@almeidx.dev>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-11 12:58:28 +00:00
Almeida
dd795252d6 refactor!: remove special cases for bot guild owner (#11160)
BREAKING CHANGE: The `GuildOwned` error code and message has been removed.

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-10-11 11:57:20 +01:00
Denis-Adrian Cristea
847fa9938d fix(GuildChannel): manageable perm check (#11166) 2025-10-11 09:01:39 +00:00
Jiralite
a97ac82619 fix(guide): Miscellaneous fixes (#11147)
* fix: miscellaneous fixes

* docs: fix contributing link

* fix: link

* fix: you

* fix: main links

* fix: update source

* fix: update link

* fix: update update link

* fix: [

* fix: remove locale

* fix: update links

* fix: update GitHub link

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-10-09 12:41:15 +00:00
633 changed files with 21771 additions and 12353 deletions

4
.github/CODEOWNERS vendored
View File

@@ -6,8 +6,11 @@
package.json @discordjs/core
pnpm-lock.yaml @discordjs/core
/.github/ISSUE_TEMPLATE/ @discordjs/guide @discordjs/core
/apps/guide/ @discordjs/website @discordjs/guide
/apps/guide/content/ @discordjs/guide
/apps/proxy-container/ @discordjs/proxy
/apps/website/ @discordjs/website
/packages/actions/ @discordjs/actions
@@ -24,7 +27,6 @@ pnpm-lock.yaml @discordjs/core
/packages/formatters/ @discordjs/formatters
/packages/next/ @discordjs/core
/packages/proxy/ @discordjs/proxy
/packages/proxy-container/ @discordjs/proxy
/packages/rest/ @discordjs/rest
/packages/scripts/ @discordjs/scripts
/packages/structures/ @discordjs/structures

View File

@@ -22,7 +22,6 @@ body:
- formatters
- next
- proxy
- proxy-container
- rest
- structures
- ui
@@ -62,9 +61,9 @@ body:
label: Versions
description: List necessary versions here. This includes your package version, runtime version, operating system etc.
placeholder: |
- discord.js 14.12.1 (`npm ls discord.js` or another package)
- Node.js 22.12.0 (`node --version`)
- TypeScript 5.1.6 (`npm ls typescript` if you use it)
- discord.js 14.24.2 (`npm ls discord.js` or another package)
- Node.js 24.11.0 (`node --version`)
- TypeScript 5.9.3 (`npm ls typescript` if you use it)
- macOS Ventura 13.3.1
validations:
required: true

View File

@@ -0,0 +1,51 @@
name: Proxy Container bug report
description: Report an issue with the proxy container.
labels: [bug, need repro, apps:proxy-container]
body:
- type: markdown
attributes:
value: |
Thank you for filing an issue! If you are here to ask a question, use Discord instead: https://discord.gg/djs
This issue form is for the proxy container.
- type: textarea
id: description
attributes:
label: Issue description
description: Describe the issue in as much detail as possible.
validations:
required: true
- type: textarea
id: steps_to_reproduce
attributes:
label: Steps to Reproduce
description: What steps must be taken to reproduce this issue?
placeholder: |
1. Pull the container image
2. Run the container with specific configuration
3. Send a request
4. Observe behavior
validations:
required: true
- type: textarea
id: versions
attributes:
label: Versions
description: List necessary versions here. This includes the container image tag, Docker version, operating system etc.
placeholder: |
- discordjs/proxy 1.0.0
- Docker 27.5.1
- Linux 6.1.0
validations:
required: true
- type: dropdown
id: priority
attributes:
label: Issue priority
description: Please be realistic. If you need to elaborate on your reasoning, please use the issue description field above.
options:
- Low (slightly annoying)
- Medium (should be fixed soon)
- High (immediate attention needed)
validations:
required: true

View File

@@ -16,6 +16,7 @@ body:
- discord.js
- Documentation
- Guide
- Proxy Container
- brokers
- builders
- collection
@@ -24,7 +25,6 @@ body:
- formatters
- next
- proxy
- proxy-container
- rest
- structures
- ui

27
.github/ISSUE_TEMPLATE/05-guide.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: Guide content
description: Request to add to the guide or change existing content
labels: [apps:guide]
type: Task
body:
- type: markdown
attributes:
value: |
Thanks for filing a suggestion! If you are here to ask a question, use Discord instead: https://discord.gg/djs
- type: dropdown
id: issuetype
attributes:
label: What is your suggestion about?
options:
- Requesting new content
- Changing existing content
- Correcting wrong information
validations:
required: true
- type: input
id: section
attributes:
label: Guide section the suggestion is about.
- type: textarea
id: body
attributes:
label: Describe your suggestion in detail.

View File

@@ -1,12 +0,0 @@
**Please describe the changes this PR makes and why it should be merged:**
**Status and versioning classification:**
<!--
Please move lines that apply to you out of the comment:
- Code changes have been tested against the Discord API, or there are no code changes
- I know how to update typings and have done so, or typings don't need updating
- This PR changes the library's interface (methods or parameters added)
- This PR includes breaking changes (methods removed or renamed, parameters moved or removed)
- This PR **only** includes non-code changes, like changes to documentation, README, etc.
-->

View File

@@ -1,6 +1,9 @@
apps:guide:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nGuide\\n"
apps:proxy-container:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nProxy Container\\n"
apps:website:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nDocumentation\\n"
@@ -31,9 +34,6 @@ packages:next:
packages:proxy:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nproxy\\n"
packages:proxy-container:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nproxy-container\\n"
packages:rest:
- "### Which (application|package|application or package) is this (bug
report|feature request) for\\?\\n\\nrest\\n"

10
.github/labeler.yml vendored
View File

@@ -3,6 +3,11 @@ apps:guide:
- any-glob-to-any-file:
- apps/guide/*
- apps/guide/**/*
apps:proxy-container:
- changed-files:
- any-glob-to-any-file:
- apps/proxy-container/*
- apps/proxy-container/**/*
apps:website:
- changed-files:
- any-glob-to-any-file:
@@ -68,11 +73,6 @@ packages:proxy:
- any-glob-to-any-file:
- packages/proxy/*
- packages/proxy/**/*
packages:proxy-container:
- changed-files:
- any-glob-to-any-file:
- packages/proxy-container/*
- packages/proxy-container/**/*
packages:rest:
- changed-files:
- any-glob-to-any-file:

4
.github/labels.yml vendored
View File

@@ -4,6 +4,8 @@
color: '5663e9'
- name: apps:guide
color: fbca04
- name: apps:proxy-container
color: fbca04
- name: apps:website
color: fbca04
- name: backlog
@@ -76,8 +78,6 @@
color: fbca04
- name: packages:proxy
color: fbca04
- name: packages:proxy-container
color: fbca04
- name: packages:rest
color: fbca04
- name: packages:structures

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Cleanup caches
run: |

View File

@@ -14,12 +14,12 @@ jobs:
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
- name: Install dependencies

View File

@@ -36,18 +36,21 @@ jobs:
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
- name: Deprecate
run: pnpm exec npm-deprecate --name "${{inputs.version}}" --message "${{inputs.message || 'This version is deprecated. Please use a newer version.'}}" --package ${{inputs.package}}
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
uses: ./packages/actions/src/deprecateVersion
with:
package: ${{ inputs.package }}
version: ${{ inputs.version }}
message: ${{ inputs.message }}
node-auth-token: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -6,10 +6,11 @@ on:
paths:
- 'packages/*/src/**'
- '!packages/create-discord-bot/**'
- '!packages/proxy-container/**'
- '!packages/ui/**'
tags:
- '**'
- '!create-discord-app@*'
- '!create-discord-bot@*'
workflow_dispatch:
inputs:
ref:
@@ -31,19 +32,19 @@ jobs:
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
REF_TYPE: ${{ inputs.ref_type || github.ref_type }}
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref || '' }}
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
- name: Install dependencies
@@ -54,7 +55,7 @@ jobs:
- name: Checkout main repository
if: ${{ inputs.ref && inputs.ref != 'main' }}
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
path: 'main'
@@ -101,13 +102,6 @@ jobs:
cd ../..
done
- name: Checkout docs repository
uses: actions/checkout@v5
with:
repository: 'discordjs/docs'
token: ${{ secrets.DJS_DOCS }}
path: 'out'
- name: Upload documentation to database
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
env:
@@ -164,20 +158,6 @@ jobs:
package: ${{ steps.extract-tag.outputs.package }}
version: ${{ steps.extract-tag.outputs.semver }}
- name: Move docs to correct directory
if: ${{ env.REF_TYPE == 'tag' }}
env:
PACKAGE: ${{ steps.extract-tag.outputs.package }}
SEMVER: ${{ steps.extract-tag.outputs.semver }}
run: |
mkdir -p "out/${PACKAGE}"
if [[ "${PACKAGE}" == "discord.js" ]]; then
mv "packages/${PACKAGE}/docs/docs.json" "out/${PACKAGE}/${SEMVER}.json"
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${SEMVER}.api.json"
else
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${SEMVER}.api.json"
fi
- name: Upload documentation to database
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
env:
@@ -222,51 +202,22 @@ jobs:
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
uses: ./main/packages/actions/src/uploadSplitDocumentation
- name: Move docs to correct directory
if: ${{ env.REF_TYPE == 'branch' }}
run: |
declare -a PACKAGES=("brokers" "builders" "collection" "core" "discord.js" "formatters" "next" "proxy" "rest" "structures" "util" "voice" "ws")
for PACKAGE in "${PACKAGES[@]}"; do
if [ ! -d "packages/${PACKAGE}" ]; then
echo "::notice::${PACKAGE} does not exist on this ref. Skipping..."
continue
fi
if [[ "${PACKAGE}" == "discord.js" ]]; then
mkdir -p "out/${PACKAGE}"
mv "packages/${PACKAGE}/docs/docs.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.json"
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.api.json"
else
mkdir -p "out/${PACKAGE}"
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.api.json"
fi
done
- name: Commit and push
run: |
cd out
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add .
git commit -m "Docs build for ${GITHUB_REF_TYPE} ${GITHUB_REF_NAME}: ${GITHUB_SHA}" || true
git push
build-indices:
needs: build-docs
name: Build & upload search indices
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
- name: Install dependencies
@@ -277,7 +228,9 @@ jobs:
- name: Upload search indices to meilisearch
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
SEARCH_API_URL: ${{ secrets.SEARCH_API_URL }}
SEARCH_API_KEY: ${{ secrets.SEARCH_API_KEY }}
uses: ./packages/actions/src/uploadSearchIndices

View File

@@ -15,7 +15,7 @@ jobs:
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Label sync
uses: crazy-max/ghaction-github-labeler@v5

View File

@@ -3,29 +3,88 @@ on:
schedule:
- cron: '0 */12 * * *'
workflow_dispatch:
env:
IMAGE_NAME: discordjs/proxy
jobs:
docker-publish:
name: Docker publish
runs-on: ubuntu-latest
if: github.repository_owner == 'discordjs'
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v5
- name: Install Node.js v22
uses: actions/setup-node@v5
with:
node-version: 22
package-manager-cache: false
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build & push docker image
run: docker build -f packages/proxy-container/Dockerfile -t discordjs/proxy:latest --push .
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: apps/proxy-container/Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v5
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Create and push manifest list
runs-on: ubuntu-latest
needs: build
steps:
- name: Download digests
uses: actions/download-artifact@v6
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:latest \
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:latest

View File

@@ -4,8 +4,8 @@ on:
- cron: '0 */12 * * *'
workflow_dispatch:
inputs:
pull:
description: 'The pull number to check out'
ref:
description: 'The ref to check out. e.g. main, feat/new-feature, refs/pull/1234/head'
required: false
default: 'main'
tag:
@@ -24,7 +24,7 @@ jobs:
id-token: write
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- uses: actions/create-github-app-token@v2
@@ -33,26 +33,17 @@ jobs:
app-id: ${{ vars.DISCORDJS_APP_ID }}
private-key: ${{ secrets.DISCORDJS_APP_KEY_RELEASE }}
- name: Decide ref
id: ref
run: |
if [ -n "${{ github.event.inputs.pull }}" ]; then
echo "ref=refs/pull/${{ github.event.inputs.pull }}/head" >> $GITHUB_OUTPUT
else
echo "ref=refs/heads/main" >> $GITHUB_OUTPUT
fi
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
ref: ${{ steps.ref.outputs.ref }}
ref: ${{ inputs.ref }}
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
registry-url: https://registry.npmjs.org/
@@ -63,13 +54,13 @@ jobs:
run: pnpm run build
- name: Checkout main repository (non-main ref)
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
uses: actions/checkout@v5
if: ${{ inputs.ref != 'main' }}
uses: actions/checkout@v6
with:
path: 'main'
- name: Install action deps (non-main ref)
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
if: ${{ inputs.ref != 'main' }}
shell: bash
working-directory: ./main
env:
@@ -79,7 +70,7 @@ jobs:
pnpm install --filter @discordjs/actions --frozen-lockfile --prefer-offline --loglevel error
- name: Publish packages (non-main ref)
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
if: ${{ inputs.ref != 'main' }}
uses: ./main/packages/actions/src/releasePackages
with:
exclude: '@discordjs/docgen'
@@ -91,7 +82,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish packages (main ref)
if: ${{ steps.ref.outputs.ref == 'refs/heads/main' }}
if: ${{ inputs.ref == 'main' }}
uses: ./packages/actions/src/releasePackages
with:
exclude: '@discordjs/docgen'

View File

@@ -1,28 +1,98 @@
name: Publish docker images
on:
workflow_dispatch:
env:
IMAGE_NAME: discordjs/proxy
jobs:
docker-publish:
name: Docker publish
runs-on: ubuntu-latest
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v5
- name: Install Node.js v22
uses: actions/setup-node@v5
with:
node-version: 22
package-manager-cache: false
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Build & push docker image
run: docker build -f packages/proxy-container/Dockerfile -t discordjs/proxy:$(cut -d '.' -f1 <<< $(jq --raw-output '.version' packages/proxy-container/package.json)) --push .
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: apps/proxy-container/Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v5
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Create and push manifest list
runs-on: ubuntu-latest
needs: build
steps:
- name: Download digests
uses: actions/download-artifact@v6
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: Checkout repository
uses: actions/checkout@v6
- name: Get Major Version
id: version
run: |
FULL_VER=$(jq --raw-output '.version' apps/proxy-container/package.json)
MAJOR=$(echo $FULL_VER | cut -d '.' -f1)
echo "major=$MAJOR" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.major }} \
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.major }}

View File

@@ -1,50 +0,0 @@
name: Publish Release
on:
release:
types: [released]
jobs:
npm-publish:
name: npm publish
runs-on: ubuntu-latest
permissions:
id-token: write
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Install Node.js v22
uses: actions/setup-node@v5
with:
node-version: 22
package-manager-cache: false
registry-url: https://registry.npmjs.org/
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
- name: Build dependencies
run: pnpm run build
- name: Extract package and semver from tag
id: extract-tag
uses: ./packages/actions/src/formatTag
with:
tag: ${{ github.ref_name }}
- name: Publish package
run: |
pnpm --filter=${{ steps.extract-tag.outputs.subpackage == 'true' && '@discordjs/' || '' }}${{ steps.extract-tag.outputs.package }} publish --provenance --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: create-discord-bot -> create-discord-app
if: steps.extract-tag.outputs.package == 'create-discord-bot'
run: |
pnpm --filter=create-discord-bot run rename-to-app
pnpm --filter=create-discord-app publish --provenance --no-git-checks
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -18,7 +18,7 @@ on:
- '@discordjs/collection'
- '@discordjs/core'
- 'create-discord-bot'
- '@discordjs/docgen'
# - '@discordjs/docgen'
- '@discordjs/formatters'
- '@discordjs/next'
- '@discordjs/proxy'
@@ -44,7 +44,7 @@ jobs:
id-token: write
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- uses: actions/create-github-app-token@v2
@@ -55,15 +55,15 @@ jobs:
permission-contents: write
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
token: ${{ steps.app-token.outputs.token }}
ref: ${{ inputs.ref || '' }}
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
registry-url: https://registry.npmjs.org/
@@ -75,7 +75,7 @@ jobs:
- name: Checkout main repository
if: ${{ inputs.ref && inputs.ref != 'main' }}
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
path: 'main'

60
.github/workflows/remove-tag.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Remove tag
on:
workflow_dispatch:
inputs:
tag:
description: The tag to remove
required: true
type: string
message:
description: Deprecation message
required: false
type: string
jobs:
removal:
runs-on: ubuntu-latest
if: github.repository_owner == 'discordjs'
strategy:
matrix:
package:
- '@discordjs/brokers'
- '@discordjs/builders'
- '@discordjs/collection'
- '@discordjs/core'
- 'create-discord-app'
- 'create-discord-bot'
- '@discordjs/formatters'
- 'discord.js'
- '@discordjs/next'
- '@discordjs/proxy'
- '@discordjs/rest'
- '@discordjs/structures'
- '@discordjs/util'
- '@discordjs/voice'
- '@discordjs/ws'
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
- name: Remove tag
run: pnpm dist-tag rm "${{ matrix.package }}" "${{ inputs.tag }}"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: Deprecate version
uses: ./packages/actions/src/deprecateVersion
with:
package: ${{ matrix.package }}
version: '*-${{ inputs.tag }}.*'
message: ${{ inputs.message }}
node-auth-token: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -12,17 +12,17 @@ jobs:
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install Node.js v22
uses: actions/setup-node@v5
- name: Install Node.js v24
uses: actions/setup-node@v6
with:
node-version: 22
node-version: 24
package-manager-cache: false
- name: Install dependencies

42
.github/workflows/upload-readmes.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: Upload README.md files
on:
push:
branches:
- 'main'
paths:
- 'packages/*/README.md'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
upload-readmes:
name: Upload README.md files
runs-on: ubuntu-latest
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version: 24
package-manager-cache: false
- name: Install dependencies
uses: ./packages/actions/src/pnpmCache
- name: Build dependencies
run: pnpm --filter @discordjs/actions... run build
- name: Upload README.md files
env:
CF_R2_READMES_ACCESS_KEY_ID: ${{ secrets.CF_R2_READMES_ACCESS_KEY_ID }}
CF_R2_READMES_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_READMES_SECRET_ACCESS_KEY }}
CF_R2_READMES_BUCKET: ${{ secrets.CF_R2_READMES_BUCKET }}
CF_R2_READMES_URL: ${{ secrets.CF_R2_READMES_URL }}
uses: ./packages/actions/src/uploadReadmeFiles

View File

@@ -5,12 +5,13 @@
</p>
<br />
<p>
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://discord.gg/djs"><img src="https://img.shields.io/badge/join_us-on_discord-5865F2?logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/tests.yml/badge.svg" alt="Tests status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main"><img src="https://img.shields.io/github/last-commit/discordjs/discord.js.svg?logo=github&logoColor=ffffff" alt="Last commit." /></a>
<a href="https://github.com/discordjs/discord.js/graphs/contributors"><img src="https://img.shields.io/github/contributors/discordjs/discord.js.svg?maxAge=3600&logo=github&logoColor=fff&color=00c7be" alt="contributors" /></a>
<a href="https://opencollective.com/discordjs"><img src="https://img.shields.io/opencollective/backers/discordjs?maxAge=3600&logo=opencollective" alt="backers" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
</p>
<p>
@@ -26,6 +27,7 @@ This repository contains multiple packages with separate [releases][github-relea
## Packages
- `discord.js` ([source][source]) - A powerful Node.js module for interacting with the Discord API
- `create-discord-bot` ([source][create-discord-bot-source]) - A CLI tool to quickly scaffold a Discord bot project
- `@discordjs/brokers` ([source][brokers-source]) - A collection of brokers for use with discord.js
- `@discordjs/builders` ([source][builders-source]) - A utility package for easily building Discord API payloads
- `@discordjs/collection` ([source][collection-source]) - A powerful utility data structure
@@ -34,10 +36,14 @@ This repository contains multiple packages with separate [releases][github-relea
- `@discordjs/proxy` ([source][proxy-source]) - A wrapper around `@discordjs/rest` for running an HTTP proxy
- `@discordjs/rest` ([source][rest-source]) - A module for interacting with the Discord REST API
- `@discordjs/structures` ([source][structures-source]) - A wrapper around Discord's structures
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
- `@discordjs/util` ([source][util-source]) - A collection of utility functions
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
- `@discordjs/ws` ([source][ws-source]) - A wrapper around Discord's gateway
## Containers
- `discordjs/proxy` ([source][proxy-container-source]) - A lightweight HTTP proxy for Discord's API
## Links
- [Website][website] ([source][website-source])
@@ -65,9 +71,9 @@ If you don't understand something in the documentation, you are experiencing pro
[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/docs
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
[guide]: https://discordjs.guide
[guide-source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
[guide-update]: https://discordjs.guide/legacy/additional-info/changes-in-v14
[discord]: https://discord.gg/djs
[discord-developers]: https://discord.gg/discord-developers
[source]: https://github.com/discordjs/discord.js/tree/main/packages/discord.js
@@ -77,6 +83,7 @@ If you don't understand something in the documentation, you are experiencing pro
[rpc-source]: https://github.com/discordjs/RPC
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
[github-releases]: https://github.com/discordjs/discord.js/releases
[create-discord-bot-source]: https://github.com/discordjs/discord.js/tree/main/packages/create-discord-bot
[brokers-source]: https://github.com/discordjs/discord.js/tree/main/packages/brokers
[builders-source]: https://github.com/discordjs/discord.js/tree/main/packages/builders
[collection-source]: https://github.com/discordjs/discord.js/tree/main/packages/collection
@@ -85,7 +92,8 @@ If you don't understand something in the documentation, you are experiencing pro
[proxy-source]: https://github.com/discordjs/discord.js/tree/main/packages/proxy
[rest-source]: https://github.com/discordjs/discord.js/tree/main/packages/rest
[structures-source]: https://github.com/discordjs/discord.js/tree/main/packages/structures
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
[util-source]: https://github.com/discordjs/discord.js/tree/main/packages/util
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
[ws-source]: https://github.com/discordjs/discord.js/tree/main/packages/ws
[proxy-container-source]: https://github.com/discordjs/discord.js/tree/main/apps/proxy-container
[good-first-issue]: https://github.com/discordjs/discord.js/contribute

View File

@@ -107,7 +107,7 @@
"allowArbitraryExtensions": false,
"allowImportingTsExtensions": false,
"module": "ESNext",
"moduleResolution": "nodenext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"resolvePackageJsonExports": false,
"resolvePackageJsonImports": false,

View File

@@ -16,7 +16,9 @@ pids
.env*.local
# Dist
.open-next
.next
.wrangler
.source
# Miscellaneous

View File

@@ -5,8 +5,9 @@
</p>
<br />
<p>
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://discord.gg/djs"><img src="https://img.shields.io/badge/join_us-on_discord-5865F2?logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/tests.yml/badge.svg" alt="Build status" /></a>
<a href="https://opencollective.com/discordjs"><img src="https://img.shields.io/opencollective/backers/discordjs?maxAge=3600&logo=opencollective" alt="backers" /></a>
</p>
<p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
@@ -24,8 +25,7 @@
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the existing guide.
See [the contribution guide][./contributing] if you'd like to submit a PR.
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the existing guide. See [the contributing guide][contributing] if you'd like to submit a pull request.
## Local Development
@@ -38,9 +38,9 @@ If you don't understand something in the documentation, you are experiencing pro
[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/docs
[guide]: https://discord.js/guide
[guide]: https://discordjs.guide
[guide-source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
[guide-update]: https://discordjs.guide/legacy/additional-info/changes-in-v14
[discord]: https://discord.gg/djs
[source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md

View File

@@ -0,0 +1,3 @@
{
"title": "Additional Features"
}

View File

@@ -143,7 +143,7 @@ client.on(Events.InteractionCreate, (interaction) => {
});
```
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:
```js title="promise-example.js" lineNumbers=9
client.on(Events.InteractionCreate, async (interaction) => {

View File

@@ -519,7 +519,7 @@ You can no longer use the `deleted` property to check if a structure was deleted
### ApplicationCommand
NFSW commands are supported.
NSFW commands are supported.
### Attachment

View File

@@ -7,10 +7,9 @@ It extends JavaScript's native `Map` class, so it has all the `Map` features and
<Callout type="warn">
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](./es6-syntax) 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](./es6-syntax) if you do not know what they are.
</Callout>
A `Map` allows for an association between unique keys and their values.
@@ -45,7 +44,7 @@ Methods that follow this philosophy of staying close to the `Array` interface ar
## 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`).
```js
// For values.

View File

@@ -1,3 +1,4 @@
{
"title": "Additional Info",
"pages": ["async-await", "collections", "es6-syntax", "notation", "rest-api", "proxy"]
}

View File

@@ -1,5 +1,5 @@
---
title: Using a proxy
title: Using a Proxy
---
This guide will show you how to set up a proxy with discord.js. This may be necessary if you are deploying your bot to a server with a firewall only allowing outside traffic through the proxy.

View File

@@ -69,7 +69,7 @@ const { request } = require('undici');
showcase!
</Callout>
Random cat's API is available at [https://aws.random.cat/meow](https://aws.random.cat/meow) and returns a [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) response. To actually fetch data from the API, you're going to do the following:
Random cat's API is available at [https://aws.random.cat/meow](https://aws.random.cat/meow) and returns a [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) response. To actually fetch data from the API, you're going to do the following:
```js
const catResult = await request('https://aws.random.cat/meow');
@@ -119,7 +119,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
});
```
Here, you are using JavaScript's native [URLSearchParams class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) to create a [query string](https://en.wikipedia.org/wiki/Query_string) for the URL so that the Urban Dictionary server can parse it and know what you want to look up.
Here, you are using JavaScript's native [URLSearchParams class](https://developer.mozilla.org/docs/Web/API/URLSearchParams) to create a [query string](https://en.wikipedia.org/wiki/Query_string) for the URL so that the Urban Dictionary server can parse it and know what you want to look up.
If you were to do `/urban hello world`, then the URL would become https://api.urbandictionary.com/v0/define?term=hello%20world since the string `"hello world"` is encoded.

View File

@@ -1,9 +1,7 @@
---
title: Creating slash commands
title: Creating Slash Commands
---
## Creating slash commands
import { Step, Steps } from 'fumadocs-ui/components/steps';
import { File, Folder, Files } from 'fumadocs-ui/components/files';

View File

@@ -49,7 +49,7 @@ Create a `deploy-commands.js` file in your project directory. This file will be
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 ID")
- `guildId`: Your development server's id ([Enable developer mode](https://support.discord.com/hc/articles/206346498) > Right-click the server title > "Copy ID")
```json title="config.json"
{

View File

@@ -64,7 +64,7 @@ We recommend attaching a `.commands` property to your client instance so that yo
native path utility module. `path` helps construct paths to access files and directories. One of the advantages of the
`path` module is that it automatically detects the operating system and uses the appropriate joiners. - The
`Collection` class extends JavaScript's native
[`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) class, and includes more
[`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) class, and includes more
extensive, useful functionality. `Collection` is used to store and efficiently retrieve commands for execution.
</Callout>

View File

@@ -204,7 +204,7 @@ You'll notice the code looks very similar to the command loading above it - read
The `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.
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/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/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.

View File

@@ -33,7 +33,7 @@ console.log(token);
## Using environment variables
Environment variables are, as the name suggets, values you can pass to your environment (e.g. terminal session, Docker container, node process). This has the benefit that you can keep your code the same for different execution contexts.
Environment variables are, as the name suggests, values you can pass to your environment (e.g. terminal session, Docker container, node process). This has the benefit that you can keep your code the same for different execution contexts.
```txt title=".env"
A=Hello World

View File

@@ -0,0 +1,3 @@
{
"title": "Improving Your Dev Environment"
}

View File

@@ -1,5 +1,5 @@
---
title: Package scripts
title: Package Scripts
---
## Setting up package.json scripts

View File

@@ -2,7 +2,7 @@
title: Introduction
---
import { GithubInfo } from 'fumadocs-ui/components/github-info';
import { GithubInfo } from '@/components/GitHubInfo';
<GithubInfo owner="discordjs" repo="discord.js" />
@@ -11,7 +11,7 @@ This guide will teach you things such as:
- How to get a bot [up and running](./legacy/preparations/app-setup) from scratch;
- How to properly [create](./legacy/app-creation/project-setup), [organize](./legacy/app-creation/handling-commands), and expand on your commands;
- In-depth explanations and examples regarding popular topics (e.g. [components](./legacy/popular-topics/display-components) ,[reactions](./legacy/popular-topics/reactions), [embeds](./legacy/popular-topics/embeds), [canvas](./legacy/popular-topics/canvas));
- In-depth explanations and examples regarding popular topics (e.g. [components](./legacy/popular-topics/display-components), [reactions](./legacy/popular-topics/reactions), [embeds](./legacy/popular-topics/embeds), [canvas](./legacy/popular-topics/canvas));
- Working with databases (e.g. [sequelize](./legacy/sequelize/) and [keyv](./legacy/keyv/keyv));
- Getting started with [sharding](./legacy/sharding/);
- And much more.
@@ -30,7 +30,7 @@ If you don't know JavaScript but would like to learn about it, here are a few li
- [JavaScript.info, a modern javascript tutorial](https://javascript.info/)
- [Codecademy's interactive JavaScript course](https://www.codecademy.com/learn/introduction-to-javascript)
- [Nodeschool, for both JavaScript and Node.js lessons](https://nodeschool.io/)
- [MDN's JavaScript guide and full documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
- [MDN's JavaScript guide and full documentation](https://developer.mozilla.org/docs/Web/JavaScript)
- [Google, your best friend](https://google.com)
Take your pick, learn some JavaScript, and once you feel like you're confident enough to make a bot, come back and get started!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -2,30 +2,27 @@
title: Modals
---
With modals you can create pop-up forms that allow users to provide you with formatted inputs through submissions. We'll cover how to create, show, and receive modal forms using discord.js!
Modals are pop-up forms that allow you to prompt users for additional input. This form-like interaction response blocks the user from interacting with Discord until the modal is submitted or dismissed. In this section, we will cover how to create, show, and receive modals using discord.js!
<Callout>
This page is a follow-up to the [interactions (slash commands) page](../slash-commands/advanced-creation). Please
carefully read that section first, so that you can understand the methods used in this section.
This page is a follow-up to the [interactions (slash commands) page](../slash-commands/advanced-creation). Reading
that page first will help you understand the concepts introduced in this page.
</Callout>
## Building and responding with modals
Unlike message components, modals aren't strictly components themselves. They're a callback structure used to respond to interactions.
With the `ModalBuilder` class, discord.js offers a convenient way to build modals step by step using setters and callbacks.
<Callout>
You can have a maximum of five `ActionRowBuilder`s per modal builder, and one `TextInputBuilder` within an
`ActionRowBuilder`. Currently, you can only use `TextInputBuilder`s in modal action rows builders.
You can have a maximum of five top-level components per modal, each of which can be a label or a text display
component.
</Callout>
To create a modal you construct a new `ModalBuilder`. You can then use the setters to add the custom id and title.
```js
const { Events, ModalBuilder } = require('discord.js');
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
@@ -35,105 +32,321 @@ client.on(Events.InteractionCreate, async (interaction) => {
```
<Callout>
The custom id is a developer-defined string of up to 100 characters. Use this field to ensure you can uniquely define
all incoming interactions from your modals!
The `customId` is a developer-defined string of up to 100 characters and uniquely identifies this modal instance. You
can use it to differentiate incoming interactions.
</Callout>
The next step is to add the input fields in which users responding can enter free-text. Adding inputs is similar to adding components to messages.
The next step is adding components to the modal, which may either request input or present information.
At the end, we then call `ChatInputCommandInteraction#showModal` to display the modal to the user.
### Label
<Callout type="warn">
If you're using typescript you'll need to specify the type of components your action row holds. This can be done by specifying the generic parameter in `ActionRowBuilder`:
```diff
- new ActionRowBuilder()
+ new ActionRowBuilder<ModalActionRowComponentBuilder>()
```
</Callout>
Label components wrap around other modal components (text input, select menus, etc.) to add a label and description to it.
Since labels are not stand-alone components, we will use this example label to wrap a text input component in the next section:
```js
const { ActionRowBuilder, Events, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');
const { LabelBuilder, ModalBuilder } = require('discord.js');
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// [!code focus:11]
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
// Add components to modal
// [!code ++:5]
const hobbiesLabel = new LabelBuilder()
// The label is a large header text that identifies the interactive component for the user.
.setLabel('What are some of your favorite hobbies?')
// The description is an additional optional subtext that aids the label.
.setDescription('Activities you like to participate in');
// Create the text input components
const favoriteColorInput = new TextInputBuilder()
.setCustomId('favoriteColorInput')
// The label is the prompt the user sees for this input
.setLabel("What's your favorite color?")
// Short means only a single line of text
.setStyle(TextInputStyle.Short);
const hobbiesInput = new TextInputBuilder()
.setCustomId('hobbiesInput')
.setLabel("What's some of your favorite hobbies?")
// Paragraph means multiple lines of text.
.setStyle(TextInputStyle.Paragraph);
// An action row only holds one text input,
// so you need one action row per text input.
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
const secondActionRow = new ActionRowBuilder().addComponents(hobbiesInput);
// Add inputs to the modal
modal.addComponents(firstActionRow, secondActionRow);
// Show the modal to the user
await interaction.showModal(modal); // [!code word:showModal]
// [!code ++:2]
// Add label to the modal
modal.addLabelComponents(hobbiesLabel);
}
});
```
Restart your bot and invoke the `/ping` command again. You should see a popup form resembling the image below:
![Modal Example](./images/modal-example.png)
<Callout type="warn">
Showing a modal must be the first response to an interaction. You cannot `defer()` or `deferUpdate()` then show a
modal later.
<Callout>
The `label` field has a max length of 45 characters. The `description` field has a max length of 100 characters.
</Callout>
### Input styles
### Text input
Currently there are two different input styles available:
Text input components prompt users for single or multi line free-form text.
- `Short`, a single-line text entry;
- `Paragraph`, a multi-line text entry similar to the HTML `<textarea>`;
```js
const { LabelBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');
### Input properties
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// [!code focus:10]
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
In addition to the `customId`, `label` and `style`, a text input can be customised in a number of ways to apply validation, prompt the user, or set default values via the `TextInputBuilder` methods:
// [!code ++:6]
const hobbiesInput = new TextInputBuilder()
.setCustomId('hobbiesInput')
// Short means a single line of text.
.setStyle(TextInputStyle.Short)
// Placeholder text displayed inside the text input box
.setPlaceholder('card games, films, books, etc.');
// [!code focus:10]
const hobbiesLabel = new LabelBuilder()
// The label is a large header that identifies the interactive component for the user.
.setLabel("What's some of your favorite hobbies?")
// The description is an additional optional subtext that aids the label.
.setDescription('Activities you like to participate in')
// [!code ++:2]
// Set text input as the component of the label
.setTextInputComponent(hobbiesInput);
// Add the label to the modal
modal.addLabelComponents(hobbiesLabel);
}
});
```
#### Input styles
Discord offers two different input styles:
- `Short`, a single-line text entry
- `Paragraph`, a multi-line text entry
#### Input properties
A text input field can be customized in a number of ways to apply validation or set default values via the following `TextInputBuilder` methods:
```js
const input = new TextInputBuilder()
// set the maximum number of characters to allow
// Set the component id (this is not the custom id)
.setId(1)
// Set the maximum number of characters allowed
.setMaxLength(1_000)
// set the minimum number of characters required for submission
// Set the minimum number of characters required for submission
.setMinLength(10)
// set a placeholder string to prompt the user
.setPlaceholder('Enter some text!')
// set a default value to pre-fill the input
// Set a default value to prefill the text input
.setValue('Default')
// require a value in this input field
// Require a value in this text input field (defaults to true)
.setRequired(true);
```
<Callout>
The `id` field is used to differentiate components within interactions (which text input, selection, etc.). In
contrast, the `customId` covered earlier identifies the interaction (which modal, command, etc.).
</Callout>
### Select menu
Select menus allow you to limit user input to a preselected list of values. Discord also offers select menus linked directly to native Discord entities like users, roles, and channels.
Since they behave very similarly to how they do in messages, please refer to the [corresponding guide page](../interactive-components/select-menus) for more information on configuring select menus.
Here again, you wrap the select menu with a label component to add context to the selection and add the label to the modal:
```js
// ...
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
// ...
// [!code focus:24]
// [!code ++:23]
const favoriteStarterSelect = new StringSelectMenuBuilder()
.setCustomId('starter')
.setPlaceholder('Make a selection!')
// Modal only property on select menus to prevent submission, defaults to true
.setRequired(true)
.addOptions(
// String select menu options
new StringSelectMenuOptionBuilder()
// Label displayed to user
.setLabel('Bulbasaur')
// Description of option
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
// Value returned to you in modal submission
.setValue('bulbasaur'),
new StringSelectMenuOptionBuilder()
.setLabel('Charmander')
.setDescription('The Fire-type Lizard Pokémon.')
.setValue('charmander'),
new StringSelectMenuOptionBuilder()
.setLabel('Squirtle')
.setDescription('The Water-type Tiny Turtle Pokémon.')
.setValue('squirtle'),
);
// ...
// [!code focus:4]
// [!code ++:4]
const favoriteStarterLabel = new LabelBuilder()
.setLabel("What's your favorite Gen 1 Pokémon starter?")
// Set string select menu as component of the label
.setStringSelectMenuComponent(favoriteStarterSelect);
// [!code focus:3]
// Add labels to modal
modal.addLabelComponents(hobbiesLabel); // [!code --]
modal.addLabelComponents(hobbiesLabel, favoriteStarterLabel); // [!code ++]
}
});
```
### Text display
Text display components offer you a way to give additional context to the user that doesn't fit into labels or isn't directly connected to any specific input field.
```js
// ...
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
// ...
// [!code focus:3]
// [!code ++:3]
const text = new TextDisplayBuilder().setContent(
'Text that could not fit in to a label or description\n-# Markdown can also be used',
);
// [!code focus:5]
// Add components to modal
modal
// [!code --]
.addLabelComponents(hobbiesLabel, favoriteStarterLabel);
// [!code ++:2]
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
.addTextDisplayComponents(text);
}
});
```
### File upload
File upload components allow you to prompt the user to upload a file from their system.
<Callout type="warn">
Discord **does not send the file data** itself in the resulting interaction. You will have to download it from
Discords CDN to process and validate it. Do not execute arbitrary code people upload via your app!
</Callout>
```js
// ...
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
// ...
// [!code focus:2]
// [!code ++]
const pictureOfTheWeekUpload = new FileUploadBuilder().setCustomId('picture');
// ...
// [!code focus:12]
// [!code ++:5]
const pictureOfTheWeekLabel = new LabelBuilder()
.setLabel('Picture of the Week')
.setDescription('The best pictures you have taken this week')
// Set file upload as component of the label
.setFileUploadComponent(pictureOfTheWeekUpload);
// Add components to modal
modal
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
// [!code --]
.addTextDisplayComponents(text);
// [!code ++:2]
.addTextDisplayComponents(text)
.addLabelComponents(pictureOfTheWeekLabel);
}
});
```
#### File upload properties
A file upload component can be customized to apply validation via the following `FileUploadBuilder` methods:
```js
const pictureOfTheWeekUpload = new FileUploadBuilder()
// Set the optional identifier for component
.setId(1)
// Minimum number of items that must be uploaded (defaults to 1); min 0, max 10
.setMinValues(1)
// Maximum number of items that can be uploaded (defaults to 1); max 10
.setMaxValues(1)
// Require a value in this file upload component (defaults to true)
.setRequired(true);
```
<Callout>
The `id` field is used to differentiate components within interactions (which text input, selection, etc.).
In contrast, the `customId` covered earlier identifies the interaction (which modal, command, etc.).
You **cannot** limit and validate the **file size** or the **file extension**.
</Callout>
### Responding with a modal
With the modal built, call `ChatInputCommandInteraction#showModal()` to send the interaction response to Discord and display the modal to the user.
<Callout type="warn">
Showing a modal must be the first response to an interaction. You **cannot** defer modals.
</Callout>
```js
// ...
// [!code focus:5]
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
// Create the modal
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
// ...
// [!code focus:9]
// Add components to modal
modal
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
.addTextDisplayComponents(text)
.addLabelComponents(pictureOfTheWeekLabel);
// [!code ++:2]
// Show modal to the user
await interaction.showModal(modal);
}
});
```
Restart your bot and invoke the `/ping` command again. You should see the modal as shown below:
![Modal Example](./images/modal-example.png)
## Receiving modal submissions
### Interaction collectors
Modal submissions can be collected within the scope of the interaction that showed it by utilising an `InteractionCollector`, or the `ChatInputCommandInteraction#awaitModalSubmit` promisified method. These both provide instances of the `ModalSubmitInteraction` class as collected items.
Modal submissions can be collected within the scope of the interaction that sent the modal by utilizing an `InteractionCollector`, or the `ChatInputCommandInteraction#awaitModalSubmit` promisified version. These both provide instances of the `ModalSubmitInteraction` class as collected items.
For a detailed guide on receiving message components via collectors, please refer to the [collectors guide](../popular-topics/collectors#interaction-collectors).
For a detailed guide on handling interactions with collectors, please refer to the [collectors guide](../popular-topics/collectors#interaction-collectors).
### The interactionCreate event
@@ -141,6 +354,8 @@ To receive a `ModalSubmitInteraction` event, attach an `Client#interactionCreate
```js
client.on(Events.InteractionCreate, (interaction) => {
// ...
// [!code word:isModalSubmit] [!code highlight:2]
if (!interaction.isModalSubmit()) return;
console.log(interaction);
});
@@ -157,7 +372,7 @@ The `ModalSubmitInteraction` class provides the same methods as the `ChatInputCo
- `deleteReply()`
- `followUp()`
If the modal was shown from a `ButtonInteraction` or `StringSelectMenuInteraction`, it will also provide these methods, which behave equally:
If the modal was prompted through a button or select menu interaction, these methods may be used to update the underlying message:
- `update()`
- `deferUpdate()`
@@ -165,28 +380,40 @@ If the modal was shown from a `ButtonInteraction` or `StringSelectMenuInteractio
```js
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isModalSubmit()) return;
console.log(interaction);
if (interaction.customId === 'myModal') {
// [!code highlight] [!code word:reply]
await interaction.reply({ content: 'Your submission was received successfully!' });
}
});
```
<Callout>
If you're using typescript, you can use the `ModalSubmitInteraction#isFromMessage` typeguard, to make sure the
received interaction was from a `MessageComponentInteraction`.
If you're using TypeScript, you can use the `ModalSubmitInteraction#isFromMessage()` type guard to make sure the
received interaction originated from a `MessageComponentInteraction`.
</Callout>
## Extracting data from modal submissions
You'll most likely need to read the data sent by the user in the modal. You can do this by accessing the `ModalSubmitInteraction#fields`. From there you can call `ModalSubmitFields#getTextInputValue` with the custom id of the text input to get the value.
You can process the submitted input fields through the use of convenience getters on `ModalSubmitInteraction#fields`. The library provides getters for all modal components with user submitted data:
```js
client.on(Events.InteractionCreate, (interaction) => {
if (!interaction.isModalSubmit()) return;
if (interaction.customId === 'myModal') {
await interaction.reply({ content: 'Your submission was received successfully!' });
// Get the data entered by the user
const favoriteColor = interaction.fields.getTextInputValue('favoriteColorInput');
const hobbies = interaction.fields.getTextInputValue('hobbiesInput');
console.log({ favoriteColor, hobbies });
// [!code focus:6]
// Get the data entered by the user
const hobbies = interaction.fields.getTextInputValue('hobbiesInput');
const starter = interaction.fields.getStringSelectValues('starter');
const picture = interaction.fields.getUploadedFiles('picture');
console.log({ hobbies, starter, picture });
}
});
```
<Callout>
Empty text input submissions return an empty string `""`. Select menus without a selection return an empty array `[]`.
</Callout>

View File

@@ -1,5 +1,5 @@
---
title: Action rows
title: Action Rows
---
Action rows are a layout component with five "slots" that can be filled with other components. At the time of writing this guide, buttons take up one slot and select menus take up five "slots". Accordingly, each `ActionRow` can hold up to 5 buttons or a single select menu. A message can have up to five rows without providing the `IsComponentsV2` message flag. If you want to place buttons or action rows into the message body, they have to be wrapped inside rows.

View File

@@ -1,3 +1,4 @@
{
"title": "Interactive Components",
"pages": ["action-rows", "buttons", "select-menus", "interactions"]
}

View File

@@ -2,13 +2,17 @@
title: Select Menus
---
Select menus are one of the `MessageComponent` classes, which can be sent via messages or interaction responses.
Select menus are interactive components which can be sent via messages, interaction responses, or in modals.
<Callout>
This page is a follow-up to the [slash commands](../slash-commands/advanced-creation) section and [action
rows](../interactive-components/action-rows) page. Please carefully read those pages first so that you can understand
the methods used here.
</Callout>
<Callout>
This page is for using select menus in messages. For using [select menus in
modals](../interactions/modals#select-menu) visit the modal page
</Callout>
## Building string select menus
@@ -22,13 +26,17 @@ const { StringSelectMenuBuilder, StringSelectMenuOptionBuilder, SlashCommandBuil
module.exports = {
// data: new SlashCommandBuilder()...
async execute(interaction) {
const select = new StringSelectMenuBuilder()
const favoriteStarterSelect = new StringSelectMenuBuilder()
.setCustomId('starter')
.setPlaceholder('Make a selection!')
.addOptions(
// String select menu options
new StringSelectMenuOptionBuilder()
// Label displayed to user
.setLabel('Bulbasaur')
// Description of option
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
// Value returned in select menu interaction
.setValue('bulbasaur'),
new StringSelectMenuOptionBuilder()
.setLabel('Charmander')
@@ -59,17 +67,21 @@ const {
StringSelectMenuOptionBuilder,
SlashCommandBuilder,
} = require('discord.js');
// [!code focus:30]
// [!code focus:33]
module.exports = {
// data: new SlashCommandBuilder()...
async execute(interaction) {
const select = new StringSelectMenuBuilder()
const favoriteStarterSelect = new StringSelectMenuBuilder()
.setCustomId('starter')
.setPlaceholder('Make a selection!')
.addOptions(
// String select menu options
new StringSelectMenuOptionBuilder()
// Label displayed to user
.setLabel('Bulbasaur')
// Description of option
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
// Value returned in select menu interaction
.setValue('bulbasaur'),
new StringSelectMenuOptionBuilder()
.setLabel('Charmander')
@@ -81,9 +93,11 @@ module.exports = {
.setValue('squirtle'),
);
// [!code ++:6]
const row = new ActionRowBuilder().addComponents(select);
// [!code ++:8]
// Adding a string select menu to an action row
const row = new ActionRowBuilder().addComponents(favoriteStarterSelect);
// Reply with the action row
await interaction.reply({
content: 'Choose your starter!',
components: [row],
@@ -99,7 +113,7 @@ module.exports = {
components](../popular-topics/display-components) system.
</Callout>
### String select menu options
## String select menu options
String select menu options are custom-defined by the user, as shown in the example above. At a minimum, each option must have it's `label` and `value` defined. The label is shown to the user, while the value is included in the interaction sent to the bot.

View File

@@ -80,7 +80,7 @@ For a more detailed setup, check out the [Keyv readme](https://github.com/jaredw
## Usage
Keyv exposes a familiar [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](../additional-info/async-await) that resolve with the data.
Keyv exposes a familiar [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](../additional-info/async-await) that resolve with the data.
```js
(async () => {
@@ -105,7 +105,7 @@ Although Keyv can assist in any scenario where you need key-value data, we will
<Callout>
This section will still work with any provider supported by Keyv. We recommend PostgreSQL for larger applications.
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticeable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
You can find out if sqlite might be a good choice for your project (it very likely is) by reading [their own article](https://www.sqlite.org/whentouse.html) on the topic.

View File

@@ -2,7 +2,7 @@
"pages": [
"[MessageCircleQuestion][FAQ](/legacy/popular-topics/faq)",
"[ArrowDownToLine][Updating to v14](/legacy/additional-info/changes-in-v14)",
"[LibraryBig][Documentation](https://discord.js.org/docs)",
"external:[LibraryBig][Documentation](https://discord.js.org/docs)",
"[Info][Introduction](/legacy)",
"---Setup---",
"preparations",

View File

@@ -75,7 +75,7 @@ await interaction.followUp(`You sent the two messages ${formatted} apart.`);
Common-tags is a library all about working with template literals.
So far, you have probably only used them for interpolating variables into your strings, but they can do a whole lot more.
If you've got time, you should check out [the MDN's documentation about _tagged literals_.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates).
If you've got time, you should check out [the MDN's documentation about _tagged literals_.](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates).
Ever got annoyed your multi-line strings had nasty bits of indentation in them,
but you did not want to remove the indentation in your source code?

View File

@@ -81,7 +81,7 @@ After importing the `@napi-rs/canvas` module and initializing it, you should loa
<Callout>
`@napi-rs/canvas` works almost identical to HTML5 Canvas. You can read the HTML5 Canvas tutorials on
[w3Schools](https://www.w3schools.com/html/html5_canvas.asp) and
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) for more information later!
[MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API) for more information later!
</Callout>
```js lineNumbers=10 title="index.js"
@@ -101,7 +101,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
Now, you need to load the image you want to use into Canvas.
We'll be using [this image](https://github.com/discordjs/guide/blob/main/guide/popular-topics/images/canvas.jpg) as the background in the welcome image, but you can use whatever you want. Be sure to download the file, name it `wallpaper.jpg`, and save it inside the same directory as your main bot file.
We'll be using [this image](https://github.com/discordjs/discord.js/blob/main/apps/guide/content/docs/legacy/popular-topics/images/canvas.jpg) as the background in the welcome image, but you can use whatever you want. Be sure to download the file, name it `wallpaper.jpg`, and save it inside the same directory as your main bot file.
```js lineNumbers=10 title="index.js"
client.on(Events.InteractionCreate, async (interaction) => {
@@ -222,7 +222,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
<Callout>
You can read more about `context.arc()` on [w3schools](https://www.w3schools.com/tags/canvas_arc.asp) or
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc).
[MDN](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/arc).
</Callout>
### Adding in text

View File

@@ -24,9 +24,9 @@ collector.on('end', (collected) => {
});
```
You can provide a `filter` key to the object parameter of `createMessageCollector()`. 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 `createMessageCollector()`. 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 `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 `end` event emits.
@@ -81,7 +81,7 @@ interaction.reply({ content: item.question, withResponse: true }).then((response
<Callout>
If you don't understand how `.some()` works, you can read about it in more detail
[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
[here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
</Callout>
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.

View File

@@ -20,7 +20,7 @@ To use the display components, you need to pass the `IsComponentsV2` message fla
## The component `id`
All components can be passed an optional, unique, `id` field holding a 32-bit integer identifier to later identify them in interaction responses. Do not confuse this with the `custom_id` field for interactive components! You can find more information about this [in the discord api documentation](https://discord.com/developers/docs/components/reference#anatomy-of-a-component). Discord will automatically populate the `id` of components that don't have the `id` specified in the payload sequentially starting from `1`. The `id` value `0` is treated as empty. The order components are automatically filled in is an implementation detail and not officially document. If you want to work with the `id` (for example to find and replace the content of a specific component lateron), you should explicitly specify it.
All components can be passed an optional, unique, `id` field holding a 32-bit integer identifier to later identify them in interaction responses. Do not confuse this with the `custom_id` field for interactive components! You can find more information about this [in the discord api documentation](https://discord.com/developers/docs/components/reference#anatomy-of-a-component). Discord will automatically populate the `id` of components that don't have the `id` specified in the payload sequentially starting from `1`. The `id` value `0` is treated as empty. The order components are automatically filled in is an implementation detail and not officially document. If you want to work with the `id` (for example to find and replace the content of a specific component later on), you should explicitly specify it.
In the following sections, we will explain all available display component types in detail and show you some examples on how you can use them.
@@ -32,6 +32,9 @@ Text Display components let you add markdown-formatted text to your message and
Sending user and role mentions in text display components **will notify users and roles**! You can and should control
mentions with the `allowedMentions` message option.
</Callout>
<Callout>
Text display components can be used in modals. See the [modal guide](../interactions/modals#text-display) for usage.
</Callout>
The example below shows how you can send a Text Display component in a channel.

View File

@@ -20,7 +20,7 @@ Example: `The messages must be an Array, Collection, or number.`
### JavaScript errors
JavaScript errors are thrown by node itself or by discord.js. These errors can easily be fixed by looking at the type of error and the stack trace. You can find a full list of types [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) and a list of common JavaScript errors [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors).
JavaScript errors are thrown by node itself or by discord.js. These errors can easily be fixed by looking at the type of error and the stack trace. You can find a full list of types [here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) and a list of common JavaScript errors [here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors).
Examples:
@@ -189,12 +189,18 @@ This error originates from an invalid call to `bulkDelete()`. Make sure you are
This error happens when fetching multiple members via `GuildMemberManager#fetch()` and:
- The `GuildMembers` intent is not specified or enabled in the dev dashboard
- The internet connection is somewhat bad
- The amount of members fetched is large (about 50 thousand and upwards)
- The `GuildMembers` intent is not specified or enabled in the [developer portal](https://discord.com/developers/applications).
- The internet connection is somewhat bad.
You can specify the time to wait for with the `time` option in the `.fetch()` call. Another solution could be to move your bot to a faster infrastructure, if available.
### Request with opcode 8 was rate limited.
You are requesting all guild members too frequently on the same guild.
- Look for instances of `GuildMemberManager#fetch()` that do not specify users.
- Make sure to handle the returned promise gracefully. Discord may change the exact values of this rate limit in the future. You can find all relevant details in the caught error.
### MaxListenersExceededWarning: Possible EventEmitter memory leak detected...
This error is caused by spawning a large number of event listeners, usually for the client. The most common cause of this is nesting your event listeners instead of separating them. The way to fix this error is to make sure you do not nest your listeners; it is **not** to use `emitter.setMaxListeners()` as the error suggests.

View File

@@ -8,7 +8,7 @@ Rather than blindly enabling all intents, consider what information you actually
## Privileged Intents
Discord defines some intents as "privileged" due to the data's sensitive nature. At the time of writing this article, privileged intents are `GuildPresences`, `MessageContent` and `GuildMembers`. If your bot is not verified and in less than 100 guilds, you can enable privileged gateway intents in the [Discord Developer Portal](https://discord.com/developers/applications) under "Privileged Gateway Intents" in the "Bot" section. If your bot is already verified or is about to [require verification](https://support-dev.discord.com/hc/en-us/articles/23926564536471), you need to request privileged intents. You can do this in your verification application or by reaching out to Discord's [support team](https://dis.gd/contact), including why you require access to each privileged intent.
Discord defines some intents as "privileged" due to the data's sensitive nature. At the time of writing this article, privileged intents are `GuildPresences`, `MessageContent` and `GuildMembers`. If your bot is not verified and in less than 100 guilds, you can enable privileged gateway intents in the [Discord Developer Portal](https://discord.com/developers/applications) under "Privileged Gateway Intents" in the "Bot" section. If your bot is already verified or is about to [require verification](https://support-dev.discord.com/hc/articles/23926564536471), you need to request privileged intents. You can do this in your verification application or by reaching out to Discord's [support team](https://dis.gd/contact), including why you require access to each privileged intent.
Before storming off and doing so, you should stop and carefully think about if you need these events. Discord made them opt-in so users across the platform can enjoy a higher level of [privacy](https://en.wikipedia.org/wiki/Privacy_by_design). Presences can expose quite a bit of personal information, including 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, considering you still get the command author as GuildMember from the command execution message and can fetch other targets separately.
@@ -75,6 +75,6 @@ If you want to view the built flags you can utilize the `.toArray()`, `.serializ
## More on Bitfields
Discord Intents and Permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
Discord Intents and Permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
In discord.js, Permissions and Intents bitfields are represented as either the decimal value of said bit field or its referenced flags. Every position in a permissions bitfield represents one of these flags and its state (either referenced `1` or not referenced `0`).

View File

@@ -1,4 +1,21 @@
{
"title": "Popular Topics",
"defaultOpen": true,
"pages": ["!faq", "...", "!display-components"]
"pages": [
"!faq",
"!display-components",
"audit-logs",
"canvas",
"collectors",
"errors",
"formatters",
"intents",
"embeds",
"partials",
"permissions",
"permissions-extended",
"reactions",
"threads",
"webhooks"
]
}

View File

@@ -49,7 +49,7 @@ if (message.partial) {
## Obtaining the full structure
Along with `.partial` to check if the structure you call it on is partial or not, the library also introduced a `.fetch()` method to retrieve the missing data from the API and complete the structure. The method returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) you need to handle. After the Promise resolves (and with it, the missing data arrived), you can use the structure as you would before.
Along with `.partial` to check if the structure you call it on is partial or not, the library also introduced a `.fetch()` method to retrieve the missing data from the API and complete the structure. The method returns a [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) you need to handle. After the Promise resolves (and with it, the missing data arrived), you can use the structure as you would before.
```js
// [!code word:partial]

View File

@@ -4,7 +4,7 @@ title: Permissions (extended)
## Discord's permission system
Discord permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
Discord permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
In discord.js, permission bit fields are represented as either the decimal value of said bit field or its referenced flags.
Every position in a permissions bit field represents one of these flags and its state (either referenced `1` or not referenced `0`).
@@ -56,6 +56,7 @@ As you only check for `SendMessages`, the bot will try to execute the send, but
- When deploying slash commands: Enable the `applications.commands` scope (for more information see the [adding your bot](../preparations/adding-your-app) section).
- Timing out a member requires `ModerateMembers`.
- Editing threads (tags, locking, closing, renaming etc.) requires `SendMessagesInThreads`.
- Adding a member to a thread requires `ViewChannel` in the parent channel for the member being added.
</Callout>
## Limitations and oddities

View File

@@ -183,7 +183,7 @@ If you try again with either of the code blocks above, you'll get the result you
<Callout>
If you aren't familiar with Promises or `async`/`await`, you can read more about them on
[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [our guide page on
[MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [our guide page on
async/await](../additional-info/async-await.md)!
</Callout>
@@ -234,8 +234,8 @@ message.reactions.cache
<Callout>
If you are not familiar with `Collection#filter` and
[`Map.has()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) take the time
to understand what they do and then come back.
[`Map.has()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/has) take the time to
understand what they do and then come back.
</Callout>
Removing reactions by a user is not as straightforward as removing by emoji or removing all reactions. The API does not provide a method for selectively removing the reactions of a user. This means you will have to iterate through reactions that include the user and remove them.

View File

@@ -93,7 +93,7 @@ const thread = await channel.threads.create({
console.log(`Created thread: ${thread.name}`);
```
They can also be created from an existing message with the `Message#startThread` method, but will be "orphaned" if that message is deleted. The thread is not deleted along with the message and will still be available through the hcannels thread list!
They can also be created from an existing message with the `Message#startThread` method, but will be "orphaned" if that message is deleted. The thread is not deleted along with the message and will still be available through the channels thread list!
```js
// [!code word:startThread]

View File

@@ -29,7 +29,7 @@ If you would like to get the webhook object that sent the message, you can use `
Webhook fetching will always make use of collections and Promises. If you do not understand either concept, revise
them, and then come back to this section. You can read about collections [here](../additional-info/collections), and
Promises [here](../additional-info/async-await) and
[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).
[here](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Using_promises).
</Callout>
### Fetching all webhooks of a guild

View File

@@ -1,5 +1,5 @@
---
title: Adding your App
title: Adding Your App
---
After you set up a bot application, you'll notice that it's not in any servers yet. So how does that work?

View File

@@ -42,7 +42,7 @@ bun add discord.js sequelize sqlite3
<Callout>
This section will still work with any provider supported by sequelize. We recommend PostgreSQL for larger applications.
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticeable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
You can find out if sqlite might be a good choice for your project (it very likely is) by reading [their own article](https://www.sqlite.org/whentouse.html) on the topic.
@@ -106,7 +106,7 @@ In any relational database, you need to create tables to store your data. This s
| bob | is the best | bob | 0 |
| tableflip | (╯°□°)╯︵ ┻━┻ | joe | 8 |
To do that in Sequelize, define a model based on this structure below the connection information, as shown below, after the `sequelize` initalisation.
To do that in Sequelize, define a model based on this structure below the connection information, as shown below, after the `sequelize` initialization.
```js title="sequelize-example.js"
// ...

View File

@@ -50,7 +50,7 @@ The above code utilizes the discord.js sharding manager to spawn the recommended
<Callout>
You can find the methods available for the ShardingManager class `ShardingManager`. Though, you may not be making much
use of this section, unlike the next feature we will explore, which you may learn about by clicking [this
link](./additional-information).
link](./sharding/additional-information).
</Callout>
## Getting started
@@ -91,12 +91,12 @@ Take the following snippet of code:
client.shard.fetchClientValues('guilds.cache.size').then(console.log); // [!code word:fetchClientValues]
```
If you run it, you will notice an output like `[898, 901, 900, 901]`. You will be correct in assuming that that's the total number of guilds per shard stored in an array in the Promise. This probably isn't the ideal output for guild count, so let's use [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to provide a better output.
If you run it, you will notice an output like `[898, 901, 900, 901]`. You will be correct in assuming that that's the total number of guilds per shard stored in an array in the Promise. This probably isn't the ideal output for guild count, so let's use [Array.reduce()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to provide a better output.
<Callout>
It's highly recommended for you to visit [the
documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to
understand how the `reduce()` method works, as you will probably find great use of it in sharding.
documentation](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to understand
how the `reduce()` method works, as you will probably find great use of it in sharding.
</Callout>
In this case, this method iterates through the array and adds each current value to the total amount:
@@ -149,7 +149,7 @@ This will run the code given to `broadcastEval` on each shard and return the res
```js
client.shard
.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)) // [!code word:boradcastEval]
.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)) // [!code word:broadcastEval]
.then((results) => {
return interaction.reply(`Total member count: ${results.reduce((acc, memberCount) => acc + memberCount, 0)}`);
})
@@ -158,7 +158,7 @@ client.shard
## Putting them together
You'd likely want to output both pieces of information in the stats command. You can combine these two results with [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
You'd likely want to output both pieces of information in the stats command. You can combine these two results with [Promise.all()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
```js
const promises = [
@@ -192,7 +192,7 @@ client.on(Events.InteractionCreate, (interaction) => {
// [!code ++:12]
const promises = [
client.shard.fetchClientValues('guilds.cache.size'),
lient.shard.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)),
client.shard.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)),
];
return Promise.all(promises)

View File

@@ -0,0 +1,3 @@
{
"title": "Slash Commands"
}

View File

@@ -37,12 +37,12 @@ module.exports = {
};
```
Since `reason` isn't a required option, the example above uses the `??` [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) to set a default value in case the user does not supply a value for `reason`.
Since `reason` isn't a required option, the example above uses the `??` [nullish coalescing operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) to set a default value in case the user does not supply a value for `reason`.
If the target user is still in the guild where the command is being run, you can also use `.getMember('target')` to get their `GuildMember` object.
<Callout>
If you want the id (Snowflake) of a structure instead, grab the option via `get()` and access the Snowflake via the `value` property. Note that you should use `const { value: name } = ...` here to [destructure and rename](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) the value obtained from the `CommandInteractionOption` structure to avoid identifier name conflicts.
If you want the id (Snowflake) of a structure instead, grab the option via `get()` and access the Snowflake via the `value` property. Note that you should use `const { value: name } = ...` here to [destructure and rename](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) the value obtained from the `CommandInteractionOption` structure to avoid identifier name conflicts.
</Callout>
In the same way as the above examples, you can get values of any type using the corresponding `CommandInteractionOptionResolver#get_____()` method. `String`, `Integer`, `Number` and `Boolean` options all provide the respective primitive types, while `User`, `Channel`, `Role`, and `Mentionable` options will provide either the respective discord.js class instance if your application has a bot user in the guild or a raw API structure for commands-only deployments.

View File

@@ -28,13 +28,13 @@ const data = new SlashCommandBuilder()
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers); // [!code ++]
```
For a kick command however, yout can allow members with the `KickMembers` permission to execute the command, so that's why the flag is listed here here.
For a kick command however, you can allow members with the `KickMembers` permission to execute the command, so that's why the flag is listed here here.
<Callout>
You can require the user to have all of multiple permissions by merging them with the `|` bitwise OR operator (for example `PermissionFlagsBits.BanMembers | PermissionFlagsBits.KickMembers`).
You cannot require any of multiple permissions. Discord evaluates against the combined permission bitfield!
If you want to learn more about the `|` bitwise OR operator you can check the [Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) articles on the topic.
If you want to learn more about the `|` bitwise OR operator you can check the [Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) articles on the topic.
</Callout>

View File

@@ -1,3 +1,3 @@
{
"pages": ["legacy", "voice"]
"pages": ["legacy", "v15", "voice"]
}

View File

@@ -0,0 +1,359 @@
---
title: Updating to v15
icon: ArrowDownToLine
---
import { Github } from 'lucide-react';
<Callout type="idea">
**Version 15 is in a pre-release** state, but should be usable!
That being said, we do not recommend you update your production instance without careful and thorough testing!
Please report any bugs you experience at our GitHub repository:
<Github className="inline text-red-400"/> https://github.com/discordjs/discord.js/issues
</Callout>
## Before you start
Make sure you're using the latest LTS version of Node. To check your Node 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.
## Breaking Changes
### ActionRow
`ActionRow.from()` has been removed. Use `ActionRowBuilder.from()` instead.
### ApplicationCommand
`ApplicationCommand#dmPermission` and `ApplicationCommand#setDMPermission()` have been removed. This was legacy functionality for commands—use contexts instead.
### ApplicationCommandManager
`ApplicationCommandManager#fetch()` method has been updated for consistency with other managers. Previously, it accepted two parameters: `id` (a snowflake or an options object) and an `options` object. Now, it only accepts a single `options` argument, which can be a snowflake or an options object that may include an `id` property.
### AnnouncementChannel
`AnnouncementChannel#addFollower()` now returns `FollowedChannelData` instead of a snowflake. This helps to expose the created webhook id in the target channel.
### BaseInteraction
`BaseInteraction#isAnySelectMenu()` has been removed. Use `BaseInteraction#isSelectMenu()` instead, which has been repurposed to accept all select menu component types.
### Client
#### Emojis
`Client#emojis` has been removed due to confusion with the introduction of application emojis and performance impact. Use the `resolveGuildEmoji()` utility function to get a cached guild emoji.
#### Ping
`Client#ping` has been added to replace the old `WebSocketManager#ping`. This will be `null` when the heartbeat from the gateway is yet to be received.
#### Premium sticker packs
`Client#fetchPremiumStickerPacks()` has been removed. Use `Client#fetchStickerPacks()` instead.
#### Ready event
`client.on("")` has been removed. `"clientReady"` is the replacement. If you used `client.on(Events.ClientReady)`, you do not need to change anything.
#### Shard disconnect event
`client.on("shardDisconnect")` has been removed as the WebSocket manager replaces this functionality.
#### Shard error event
`client.on("shardError")` has been removed as the WebSocket manager replaces this functionality.
#### Shard ready event
`client.on("shardReady")` has been removed as the WebSocket manager replaces this functionality.
#### Shard reconnecting event
`client.on("shardReconnecting")` has been removed as the WebSocket manager replaces this functionality.
#### Shard resume event
`client.on("shardResume")` has been removed as the WebSocket manager replaces this functionality.
#### Webhook update event
`client.on("webhookUpdate")` has been removed. `"webhooksUpdate"` is the replacement. If you used `client.on(Events.WebhooksUpdate)`, you do not need to change anything.
#### WebSocket
The underlying WebSocket behaviour has changed. In version 14, this was a non-breaking implementation of [ws](https://discord.js.org/docs/packages/ws/stable). Now, it is fully integrated. See these pull requests for more information:
- [discordjs/discord.js#10420](https://github.com/discordjs/discord.js/pull/10420)
- [discordjs/discord.js#10556](https://github.com/discordjs/discord.js/pull/10556)
### ClientEvents
`ClientEvents` type has been removed. Use `ClientEventTypes` instead. This change ensures consistency with the rest of the event types across the library.
### ClientOptions
Removed `ClientOptions#shards` and `ClientOptions#shardCount` in favor of `ClientOptions#ws#shardIds` and `ClientOptions#ws#shardCount`.
### ClientUser
`ClientUser#setPresence()` now returns a promise which resolves when the gateway call was sent successfully.
### ClientPresence
`ClientPresence#set()` now returns a promise which resolves when the gateway call was sent successfully.
### CommandInteractionOptionResolver
`CommandInteractionOptionResolver#getFocused()`'s parameter has been removed. `AutocompleteFocusedOption` will always be returned.
### Constants
`DeletableMessageTypes` has been removed. Use `UndeletableMessageTypes` instead.
### DiscordjsErrorCodes
The following error codes have been removed as they either have no use or are handled in another package instead:
- `WSCloseRequested`
- `WSConnectionExists`
- `WSNotOpen`
- `ManagerDestroyed`
- `ShardingInvalid`
- `ShardingRequired`
- `InvalidIntents`
- `DisallowedIntents`
- `ButtonLabel`
- `ButtonURL`
- `ButtonCustomId`
- `SelectMenuCustomId`
- `SelectMenuPlaceholder`
- `SelectOptionLabel`
- `SelectOptionValue`
- `SelectOptionDescription`
- `UserBannerNotFetched`
- `ImageFormat`
- `ImageSize`
- `SplitMaxLen`
- `MissingManageEmojisAndStickersPermission`
- `VanityURL`
- `InteractionEphemeralReplied`
### Emoji
#### Image URL is now dynamic
`Emoji#imageURL()` now dynamically handles the extension. Previously, you would have to do this:
```js
emoji.imageURL({ extension: emoji.animated ? 'gif' : 'webp' });
```
Now, you can simply do this:
```js
emoji.imageURL();
```
#### Emoji URL getter removal
`Emoji#url` has been removed. To allow more granular control of the returned extension, Use `Emoji#imageURL()` instead.
### EventEmitter
`BaseClient`, `Shard`, `ShardingManager`, and `Collector` now extend `AsyncEventEmitter` instead of `EventEmitter`. This comes from [@vladfrangu/async_event_emitter](https://npmjs.com/package/@vladfrangu/async_event_emitter).
### Events
- `Events.ShardError` has been removed.
- `Events.ShardReady` has been removed.
- `Events.ShardReconnecting` has been removed.
- `Events.ShardResume` has been removed.
- `Events.WebhooksUpdate` now returns a string of `"webhooksUpdate"`. Previously, it returned `"webhookUpdate"`. This is to bring it in line with the name of Discord's gateway event (`WEBHOOKS_UPDATE`).
- `Events.ClientReady` now returns a string of `"clientReady"`. Previously, it returned `"ready"`. This is to ensure there's no confusion with Discord's `READY` gateway event.
### Formatters
This utility has been removed. Everything in this class is redundant as all methods of the class can be imported from discord.js directly.
```js
import { Formatters } from 'discord.js'; // [!code --]
import { userMention } from 'discord.js'; // [!code ++]
Formatters.userMention('123456789012345678'); // [!code --]
userMention('123456789012345678'); // [!code ++]
```
### Guild
Removed `Guild#shard` as WebSocket shards are now handled by @discordjs/ws.
### GuildApplicationCommandManager
`GuildApplicationCommandManager#fetch()` method has been updated for consistency with other managers. Previously, it accepted two parameters: `id` (a snowflake or an options object) and an `options` object. Now, it only accepts a single `options` argument, which can be a snowflake or an options object that may include an `id` property.
### GuildAuditLogs
`GuildAuditLogsEntry.Targets.All` has been removed. It was not being used.
### GuildBanManager
`GuildBanManager#create()` no longer accepts `deleteMessageDays`. This is replaced with `deleteMessageSeconds`.
### GuildChannelManager
`GuildChannelManager#addFollower()` now returns `FollowedChannelData` instead of a snowflake. This helps to expose the created webhook id in the target channel.
### GuildMemberResolvable
`GuildMemberResolvable` type has been removed. It was defined as `GuildMember | UserResolvable`, but `UserResolvable` already includes `GuildMember`. Use `UserResolvable` instead.
### MessageManager
`MessageManager#crosspost()` has been moved to `GuildMessageManager`. This means it will no longer be exposed in `DMMessageManager`.
### IntegrationApplication
`IntegrationApplication#hook` has been removed.
### InteractionResponse
`InteractionResponse` has been removed. This class was encountered when responding to an interaction without `fetchReply` to allow ease of creating interaction collectors. This is no longer necessary as `withResponse` exposes the message.
### InteractionResponses
#### Ephemeral option removal
Previously, you would respond to an interaction ephemerally like so:
```js
// Way 1:
await interaction.reply({ content: 'This is an ephemeral response.', ephemeral: true });
// Way 2:
await interaction.reply({ content: 'This is an ephemeral response.', flags: MessageFlags.Ephemeral });
```
There are two ways to achieve the same behaviour, so the "helper" option has been removed. In this case, that would be `ephemeral`, as all that did was assign `MessageFlags.Ephemeral` internally.
#### Fetch reply option removal
`fetchReply` has been removed in favor of `withResponse`. If you were using the `fetchReply` option or fetching the response of an interaction, it is recommended to use `withResponse` instead, as the message is exposed without an additional API call:
```js
const message = await interaction.reply({ content: 'Hello!', fetchReply: true }); // [!code --]
const response = await interaction.reply({ content: 'Hello!', withResponse: true }); // [!code ++:2]
const { message } = response.resource;
```
#### Premium response type
Discord no longer supports the `PREMIUM_REQUIRED` interaction response type. In the past, you would have done this:
```js
if (!premiumLogicCheck) {
// User does not have access to our premium features.
await interaction.sendPremiumRequired();
return;
}
await interaction.reply('You have access to our premium features!');
```
However, you would have already noticed that this no longer works, so this method has been removed. Sending a premium button has been the replacement ever since.
### Invite
`Invite#stageInstance` has been removed.
### InviteStageInstance
`InviteStageInstance` has been removed.
### Message
`Message#interaction` has been removed. Use `Message#interactionMetadata` instead.
### MessagePayload
`MessagePayload#isInteraction` no longer serves a purpose and has been removed.
### NewsChannel
`NewsChannel` has been renamed to `AnnouncementChannel`.
### PermissionOverwrites
`PermissionOverwrites.resolve()` previously relied on cache if a snowflake was passed. This method no longer relies on cache and instead requires an explicit `type` if supplied.
### RoleManager
`RoleManager#fetch()` used to return `null` when fetching a role that did not exist. This logic has been removed and will throw an error instead.
### SelectMenuBuilder
`SelectMenuBuilder` has been removed. Use `StringSelectMenuBuilder` instead.
### SelectMenuComponent
`SelectMenuComponent` has been removed. Use `StringSelectMenuComponent` instead.
### SelectMenuInteraction
`SelectMenuInteraction` has been removed. Use `StringSelectMenuInteraction` instead.
### SelectMenuOptionBuilder
`SelectMenuOptionBuilder` has been removed. Use `StringSelectMenuOptionBuilder` instead.
### ShardClientUtil
`ShardClientUtil#ids` and `ShardClientUtil#count` have been removed in favor of `Client#ws#getShardIds()` and `Client#ws#getShardCount()`.
### StageInstance
`StageInstance#discoverableDisabled` has been removed.
### TeamMember
`TeamMember#permissions` has been removed. Use `TeamMemberManager#role` instead.
### TextBasedChannel
`TextBasedChannel#bulkDelete()` could return a collection containing `undefined` values. This was because in order to return these messages, the cache must be checked, especially when only snowflakes were provided. The return type of this method has thus changed to only return an array of snowflakes that were bulk deleted.
### ThreadChannel
`ThreadChannel#fetchOwner()` used to return `null` when the thread owner was not present in the thread. This logic has been removed and will throw an error instead.
### ThreadManager
`ThreadManager#fetch()` now throws an error when the provided thread id doesn't belong to the current channel.
### ThreadMember
The reason parameter of `ThreadMember#add()` and `ThreadMember#remove()` have been removed. Discord did not respect this parameter, so it did not do anything.
### ThreadMemberManager
The reason parameter of `ThreadMemberManager#remove()` has been removed. Discord did not respect this parameter, so it did not do anything.
### User
#### Avatar decoration
Discord no longer sends avatar decoration data via `User#avatarDecoration`, so this property has been removed. `User#avatarDecorationData` is the replacement.
#### Flags
`User#fetchFlags()` has been removed. All this did was fetch the user and return only its `flags` property. It was quite redundant.
### UserManager
`UserManager#fetchFlags()` has been removed. All this did was fetch the user and return only its `flags` property. It was quite redundant.
### WebSocketShardEvents
`WebSocketShardEvents` has been replaced with `WebSocketShardEvents` from @discordjs/ws.

View File

@@ -0,0 +1,7 @@
{
"title": "discord.js v15",
"description": "Work in progress...",
"pages": ["external:[LibraryBig][Documentation](https://discord.js.org/docs/packages/discord.js/main)", "index"],
"icon": "FlaskConical",
"root": true
}

View File

@@ -81,7 +81,7 @@ const resource = createAudioResource('/home/user/voice/music.mp3', {
},
});
// Not recommended - listen to errors from the audio player instead for most usecases!
// Not recommended - listen to errors from the audio player instead for most use cases!
resource.playStream.on('error', (error) => {
console.error('Error:', error.message, 'with track', resource.metadata.title);
});

View File

@@ -2,13 +2,17 @@
title: Installation
---
"Voice" refers to Discord bots being able to send audio in voice channels. This is supported in discord.js via @discordjs/voice](https://github.com/discordjs/discord.js/tree/main/packages/voice), a standalone library made by the developers of discord.js. While you can use it with any Node.js Discord API library, this guide will focus on using it with discord.js.
"Voice" refers to Discord bots being able to send audio in voice channels. This is supported in discord.js via [@discordjs/voice](https://github.com/discordjs/discord.js/tree/main/packages/voice), a standalone library made by the developers of discord.js. While you can use it with any Node.js Discord API library, this guide will focus on using it with discord.js.
## Installation
### Barebones
To add voice functionality to your discord.js bot, you will need the `@discordjs/voice` package, as well as one of the encryption packages listed below. For example:
To add voice functionality to your discord.js bot, you will need the `@discordjs/voice` package. If your system does not support aes-256-gcm you also need one of the encryption packages listed below. For example:
<Callout>
You can verify aes-256-gcm support by running `require('node:crypto').getCiphers().includes('aes-256-gcm')`.
</Callout>
```sh tab="npm"
npm install @discordjs/voice
@@ -58,6 +62,15 @@ After this, you'll be able to play Ogg and WebM Opus files without any other dep
- [`@noble/ciphers`](https://www.npmjs.com/package/@noble/ciphers)
- [`libsodium-wrappers`](https://www.npmjs.com/package/libsodium-wrappers)
#### DAVE Protocol Support for end-to-end encryption of voice audio
- [`@snazzah/davey`](https://www.npmjs.com/package/@snazzah/davey)
<Callout>
At this time, `@snazzah/davey` is the only supported DAVE protocol library in this package, and comes pre-installed.
In the future, we may support other libraries once they are created.
</Callout>
<Callout>
If you are facing issues when installing these dependencies, make sure you ticked the box to install optional build
tools when installing Node.js or try manually installing build tools and python: ```sh winget install "Visual Studio
@@ -91,6 +104,9 @@ Encryption Libraries
FFmpeg
- version: 4.2.4-1ubuntu0.1
- libopus: yes
DAVE Protocol
- @snazzah/davey: 0.1.6
--------------------------------------------------
*/
```
@@ -104,3 +120,5 @@ FFmpeg
- **FFmpeg**
- If you want to play audio from many different file types, you will need to have FFmpeg installed.
- If `libopus` is enabled, you will be able to benefit from increased performance if real-time volume alteration is disabled.
- **DAVE Protocol**
- Required for enabling end-to-end encryption in voice channels.

View File

@@ -2,7 +2,7 @@
"title": "Voice",
"description": "Working with the voice library",
"pages": [
"[LibraryBig][Documentation](https://discord.js.org/docs/packages/voice/main)",
"external:[LibraryBig][Documentation](https://discord.js.org/docs/packages/voice/main)",
"---Working with Voice---",
"index",
"life-cycles",

View File

@@ -4,7 +4,6 @@ import type { NextConfig } from 'next';
const withMDX = createMDX();
export default withMDX({
reactStrictMode: true,
serverExternalPackages: ['typescript', 'twoslash'],
images: {
dangerouslyAllowSVG: true,
@@ -23,14 +22,6 @@ export default withMDX({
fullUrl: true,
},
},
experimental: {
ppr: true,
useCache: true,
dynamicOnHover: true,
},
eslint: {
ignoreDuringBuilds: true,
},
reactCompiler: true,
typescript: {
ignoreBuildErrors: true,

View File

@@ -0,0 +1,3 @@
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
export default defineCloudflareConfig();

View File

@@ -5,11 +5,15 @@
"description": "Imagine a bot... the most popular way to build discord bots",
"private": true,
"scripts": {
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
"build:check": "tsc --noEmit",
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
"build:prod": "pnpm run build:next",
"build:next": "next build",
"build": "next build",
"preview": "next start",
"preview:cf": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
"deploy:cf": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
"dev": "next dev -p 3001 --turbopack",
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
@@ -44,65 +48,51 @@
"homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"@react-icons/all-files": "^4.1.0",
"@vercel/analytics": "^1.5.0",
"cmdk": "^1.1.1",
"cva": "1.0.0-beta.3",
"fumadocs-core": "^15.8.4",
"fumadocs-mdx": "^12.0.3",
"fumadocs-twoslash": "^3.1.8",
"fumadocs-ui": "^15.8.4",
"geist": "^1.5.1",
"immer": "^10.1.3",
"jotai": "^2.15.0",
"jotai-immer": "^0.4.1",
"lucide-react": "^0.545.0",
"mermaid": "^11.12.0",
"motion": "^12.23.22",
"next": "15.6.0-canary.45",
"next-mdx-remote-client": "^2.1.6",
"@opennextjs/cloudflare": "^1.16.5",
"@vercel/analytics": "^1.6.1",
"fumadocs-core": "^16.6.3",
"fumadocs-mdx": "^14.2.7",
"fumadocs-twoslash": "^3.1.13",
"fumadocs-ui": "^16.6.3",
"geist": "^1.7.0",
"lucide-react": "^0.559.0",
"mermaid": "^11.12.3",
"next": "^16.1.6",
"next-themes": "^0.4.6",
"nuqs": "^2.7.1",
"react": "^19.2.0",
"react-aria": "^3.44.0",
"react-aria-components": "^1.13.0",
"react-dom": "^19.2.0",
"react-error-boundary": "^6.0.0",
"sharp": "^0.34.4",
"tailwind-merge": "^3.3.1",
"p-retry": "^7.1.1",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"sharp": "^0.34.5",
"tailwind-merge": "^3.5.0",
"tw-animate-css": "^1.4.0",
"twoslash": "^0.3.4",
"usehooks-ts": "^3.1.1"
"twoslash": "^0.3.6"
},
"devDependencies": {
"@next/env": "^15.5.4",
"@shikijs/rehype": "^3.13.0",
"@tailwindcss/postcss": "^4.1.14",
"@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.14",
"@shikijs/rehype": "^3.22.0",
"@tailwindcss/postcss": "^4.2.0",
"@types/mdx": "^2.0.13",
"@types/node": "^22.18.8",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"autoprefixer": "^10.4.21",
"babel-plugin-react-compiler": "19.1.0-rc.3",
"@types/node": "^24.10.13",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"autoprefixer": "^10.4.24",
"babel-plugin-react-compiler": "^1.0.0",
"cpy-cli": "^6.0.0",
"cross-env": "^10.1.0",
"eslint": "^9.37.0",
"eslint-config-neon": "^0.2.7",
"eslint": "^9.39.2",
"eslint-config-neon": "^0.3.2",
"eslint-formatter-pretty": "^7.0.0",
"git-describe": "^4.1.1",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"remark-gfm": "^4.0.1",
"remark-rehype": "^11.1.2",
"shiki": "^3.13.0",
"tailwindcss": "^4.1.14",
"tailwindcss-react-aria-components": "^2.0.1",
"turbo": "^2.5.8",
"typescript": "^5.9.3",
"vercel": "^48.2.1"
"shiki": "^3.22.0",
"tailwindcss": "^4.2.0",
"turbo": "^2.8.10",
"typescript": "~5.9.3",
"vercel": "^49.2.0",
"wrangler": "^4.67.0"
},
"engines": {
"node": ">=22.12.0"

View File

@@ -0,0 +1,2 @@
/_next/static/*
Cache-Control: public,max-age=31536000,immutable

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/mstile-70x70.png"/>
<square150x150logo src="/mstile-150x150.png"/>
<square310x310logo src="/mstile-310x310.png"/>
<wide310x150logo src="/mstile-310x150.png"/>
<TileColor>#090a16</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="180" height="180" viewBox="0 0 180 180"><image width="180" height="180" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAMAAAAKE/YAAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKjUExURQkKFveUVAgIFAQFEv/bXFz/nVxs/////7dc//9cXAYHEwUIFbld/wcJFRESHsHBxAsLF//dXV3/n11t//v7++vr7FBRWgsNGf/bW2NkbP39/To6RP7+/viVVP/fXQwOH/9fXFts/1r/nvtbWzucZ/yXVZs7Pw8OGQ0WHIqLkBYOGREOI/9bXBMQGGVq//T09Px0WFxq/6lf/6xX8CIXHRMRKRYUGT4iXZlfO0S7d1tcZLVb/PqWVRYZI7RtQiEhLBwdKGMoMDMcIeTk5ZFKzLlFSP5nWrJd/zc9kLJZ+JuGP0ZSwRQXNrqgSFtp+O5WVyEVN6iorTQeUCgpNG86n2lCL/CPUvx8WPmNVX5m/9DR01IsdyoZQ0xNVndAr1fvlVNh5q5e/29o/2tsc5+gpJKSmIpGw+zLVhsSL/3HWlv4nRgcQvuEVi4vObe3u9nZ2/n5+a+wtMnJzKVT6PbUWVgvgTU2QPaSVDtGoFx5+Mfncp5h/4pk/7freUFMtHR0e4CBh0cnaVhNLNWBSyMpYTQoIf7TWykwcT4xJEtYzxUuKvXfYYP3jZ9R30YeJ1ZWX8NIS0M7JoBDuPDw8WI0jnlnNpaDP09c2/27WFdp7/mhVR8lU1g4Ksd3R1zRvSdjR5Vi/3X8lC93Umb+mVDei9/jaaLxgU4qcr29wUdIUVlZYXUvNCJUPos1OptP2VMiKzeHWt/AU2s4mVyK6/uuV96ETVDNgOzhZeNSVKxARGUpMKyURJNZOmZZMEBBSsGmSqdlPoNRNlzuqs2xTly6zF3prh5JOZTzh14mLs1LTbadR0ZFp2Fg6LlgRVyj21zetWZb4TxIqkO3dVlY1FyV41yx0a+IRFVQw5ygUDhzd1S2cFye3aikT0SPk6bVb2RPxmBZ2kyJzQcAAApJSURBVHja7Zr5WxNJGoDb4grdKWgI2CAwkZE1QARcSQxyCAuMgrrcoNwi54AIiAfe4on3gfd934o66jiOt6Nz7xy7O3sff8pWJaHTHTpJR9Myz7P1/uRjqlJvf/3VV1+noSgCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFA+NVCe0lD0wBCJ/MgY8PZOApCy1Cn3+YeXG24JKljn3ZmBSBzB/OY3Y9+N8yj3azDK6PiDdlDX6FBQ7sN8SzjGfGAK5EhUnQnDeZU9azfU8rRkgvBif4ThvH/KF46xLrsRxP3PiwsNI8qfLh34vXseMoD3gGBfs7o7mpKzZLShhPH+/NISxu++uzhBH8xhXtvZuugwtLYOzA8i3ZbGhquf21vbPX+bOhdtV1LI+0rtRxwSxqyQ3ullS3au1motLSfX2hcFnBDGhpuFvo7o/CmASou7ReyqJOWLQ2zP5rg74Kvh1jFpf38ApfRMqVh9l7/SRjnwb4eDxWX9lvcCWRJQ8P3kzEzZswYP97fsfyEifHKS/stygRypBNSosZgls+bN2/hXCxvdbeXn3CTVV56XLNOjnR5hUV6mOXYfa418uP5WZP8C4c8E+nIcVYipayTrgGX0jB7o8g5Kr3i/snpKSnPp5+8j+wRczE4f66zHpEOibuWaia8Ma64KmlkWtsShJee5D9j8vcJ/Pexj4XOUVH3U05kx7MInWHziZSNy9P5zx4neKZ6dNei5s4CZDPHNoXaJ8g6e2mkPHde+vQE6UBHVTzfTPFNEsOwhvLpFRbtqOnvUKnF0mMFZQ3QutpAuzSp4kONpSf5j5+xcN6YMQJppny50PlFPGPXQ00tPzkGXVbUyWxIKSCNe+3S4nHiAz3Vy9blobxYaFYUSOuepwuyIyVhpBljeFGBsmaAoRSSpujMReJQF+t46ck4yGPE0tAgyI6ojdlSZpA9sbGi3HMN0whpil7WJZLuKrXmB/P4N7ydTZoZENS79BQH5QFuLtcpKU3BdSGi/LhmzQ8mRVJamNLLyx2mgCdbUwlpkFklCnUc5VxauA1PMJQyuJKmYJz4LA9wKv0iPYrPj1GUpq+KDpmuTOhM+uDHZo4cuXfv2LHyUZO2y48ca4fKS0elH7v3y9Rh6Sdh3sNs2fKLbrSkqYAeUf9xlearR9SxY/eOfLxlS9DveekNS3hp76DWfcxoSYNm0SPMHi9rpI9gX4udTXqg1Vtg/czAjJb0etFODLdKz/rAJsdLQ8OrIIG19zebmdGRZtaJGpBw2ok0RR0SSXu/2pDAjIY03ThOvrQoqfFHSz7f53ltGdJuRXrqM3Go0Xb8fMNUBo5uTqd6OZVmnohDbY72s4ObWebXUD0cSFNTvwnyHqEddufQPh3zHqXZYqH04FXn6UEx++6MtPYOCmrF2vA9ScOsxeITETiXpqgnrd5S4OQ2eOaXdde9R4ToSbEqC7qSZg8u8ZbWXvLKM8ntWlpcPPgub9YHYRiksuPTf4qkqYSDrUEOtL3vHBp4d22XDwEZV0TFY731/jKHdly8uHLlmktf7tx59u+xdttgw52gsDBp7aDWWQMsUFaa3iPqTJNqrSNAzNmz58/7fIgJnhZrf6kDf1356Q7vMHtz/B87Lv779nagpDTICrT7DQEOSwd/6GNlpDQFY8892HlpzcqLFnVLJqFEurjm0s7zwT4P3igoDXVxIZJPW1jax4k0egrcfu6Cz/nzZ3d+eWnNmpUokXAmncX3Bs+oPxerlDRkGwfFbwQiaJnSaATSftCO08c6zPYvNKX9dqwy0nTAOlu5iwxdXNzcGABlS6MxIOP0z/XBtoFC2m9zHpeGgNY9LeY3YWRXXEQWJ3gVKkcaD4t9E3PBR1K7/jT0kLQXNEOxGZ2pTTm2D4qXUeK3iTKl0UBu++0H7RLawRfeuoaIpMf1xJlpbuoJzOkWFLr1AbQ5+F40dFcaJ3fG6Wn1I7WDYzhPSDt6jxingxSkAzprayMyAHRXGid37I2Ykdr1b4By0j0ZyFm3pycnKSk0sDEDuC1tzpIbP9trv3WoZUiHPqXRaR43OJze5t+o3ZXGe/LGNHFuv3VWy5Bu0lEUZztkIotR4EXSPtPk1VwQe84u2KeVku6+RlP0VUF/GtIIhNLtr0/9K0DucjcuCG7Qyx/+plR65JQCim0SvbxFoTZLt7889cUfPlmhma2Vuxw4XW85EF+f+uIfn6yQP9FN6cUZEGZV2R/mIOb1qT//aYXmtwg3pCku5uUPlitFE323GaEy0osCICjNEfenXhToswj7IjRr5UuD40cFEw/PAUpId1eFs5S99Fj0RN6n8R1G85Mbpct42Nc2cb7npSOTuopT8TPhiIdbmuLWCqTz3FhaO1vz7tI9g6FS5HRdaVo/tlRnObeh6LePRRkQGLfZ1vbdCsTHttLSbGeEFJ2lmRmcF9/VgQhBfiSlApyaNueCTcKlueNOTfSCq33bnKYALQUQ/iUhThDb00BIM26q84Tx6hAsDTYdnd3hWAXMmS+Y+ZYlzyUQsHocv0ZrrAfjcJXuEC2tF1aHwxrN4U2cI22wtUCwEfuUMQb6krK6NtQwscuaF+eEdjXV4o5PK9iGaB8KnDrw3dcczTNKWwOjIKV9o7cCzwtTxpqlLclqVZkedxtsVmlpJocaa6DNE4TLt+A4sHfS+G7bpJUS4vKieeNozXcdHpZmi0qqy3KT09QqlSqtrA1YLsPc4OlFzpptRv469X3DTpqCtce1wM5p+Gqjo6N9ExdUrqrzdEqzd/PT1NjYTItJa9maALAdawXOaH1blebyFiQmJmosVpqja7fOYW3eAHBopgZ/goTPTJmpyu/3dHYAU77Khjq5rr9Ir9Vq52zqQ3sw2gJaPnHBf/myxVYnN0yZsmrVmdWVlcheoyk43Le1w6hF5yXLoZk/zcfjK1evQsL4O1v00NMprd+vVgm103pz99f958eCRDMLFlRWrl59ZtWUhqW2y+y1zZjZMMUi/90fZ3+bl9f37V9+tIyfyQ9JNgGPVw5QkiyyVqkRWAbT0DDTsro6t43/Y5uSW+IJ2H1mQ0ODdYL9Z3c5BeodeyBN5Qq1MFygJlclG3VLG1CiSBv3q10tnX+AFd6coro0tUzn3BqgzGFY1OJCIe2ueC9B/dJetUxnSCkDrGlx7lxmv/8hW9IiJ9gtijkjh7a6fLXjfD6gBxIH9dJbKrWLjXC3TTlnp/dbvesyJ7U0hEUHbjmJtjot18QBSkkgW1OXrB6hoFYnl9U4LJZs0dLcfLWUt1qdn1ttVFbZrK011fWqBAqoXOfvKivhnNxhAI0m1LjgoaIyn7+rzmQEkHoPAK5m6f5byWlmh7Tk3tyy/iJXL6hQG27EHdeu5HzLqZTfe2v/AVMR936ULQrathLT5erq6n5TSZGepYGsSTSnLyox9aN5l/tNNUYtpAH1XkEK6CHM8iTmVlNOD8+DFIFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQPg/5H/D3r7K3BZFuAAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg=="></image><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
@media (prefers-color-scheme: dark) { :root { filter: none; } }
</style></svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Some files were not shown because too many files have changed in this diff Show More