Compare commits

...

98 Commits

Author SHA1 Message Date
iCrawl
acc560204f chore(proxy): release @discordjs/proxy@2.0.0 2023-07-31 21:28:52 +02:00
iCrawl
ccf65c2d09 chore(ws): release @discordjs/ws@1.0.0 2023-07-31 21:27:09 +02:00
iCrawl
d04987f09b chore(rest): release @discordjs/rest@2.0.0 2023-07-31 21:24:28 +02:00
iCrawl
ca5a2626b4 chore(collection): release @discordjs/collection@1.5.2 2023-07-31 21:22:35 +02:00
iCrawl
3c5a4dc7a7 chore(util): release @discordjs/util@1.0.0 2023-07-31 21:18:33 +02:00
iCrawl
447652ec8a chore: format 2023-07-31 21:08:13 +02:00
iCrawl
488aa58b29 chore: fixup yarn.lock 2023-07-30 23:16:45 +02:00
iCrawl
a92d19212d ci: publishing dev version semver 2023-07-30 23:08:46 +02:00
iCrawl
fd8197fe5b chore: deps 2023-07-30 02:13:39 +02:00
ckohen
8f4256db8a refactor(REST): remove double classing (#9722)
* refactor(REST): remove double classing

BREAKING CHANGE: `REST` and `RequestManager` have been combined, most of the properties, methods, and events from both classes can now be found on `REST`
BREAKING CHANGE: `REST#raw` has been removed in favor of `REST#queueRequest`
BREAKING CHANGE: `REST#getAgent` has been removed in favor of `REST#agent`

* chore: update for /rest changes
2023-07-25 08:40:21 +00:00
Saya
6307f81385 feat: add ws option support for "buildIdentifyThrottler" (#9728)
* feat: add option support for "buildIdentifyThrottler"

* docs: add documentation for buildIdentifyThrottler

* docs: fix example code
2023-07-22 08:57:24 +00:00
iCrawl
d26e022afc chore: deps 2023-07-19 11:59:42 +02:00
iCrawl
afa98793cd chore: deps 2023-07-17 09:45:07 +02:00
Vlad Frangu
386f206caf feat: no-de-no-de, now with extra buns (#9683)
BREAKING CHANGE: The REST and RequestManager classes now extend AsyncEventEmitter
from `@vladfrangu/async_event_emitter`, which aids in cross-compatibility
between Node, Deno, Bun, CF Workers, Vercel Functions, etc.

BREAKING CHANGE: DefaultUserAgentAppendix has been adapted to support multiple
different platforms (previously mentioned Deno, Bun, CF Workers, etc)

BREAKING CHANGE: the entry point for `@discordjs/rest` will now differ
in non-node-like environments (CF Workers, etc.)

Co-authored-by: Suneet Tipirneni <77477100+suneettipirneni@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: suneettipirneni <suneettipirneni@icloud.com>
2023-07-17 08:27:57 +02:00
David Malchin
351a18bc35 feat(create-discord-bot): throw error if the directory is a file (#9719) 2023-07-16 17:38:22 +00:00
Suneet Tipirneni
84f1b1890d feat(create-discord-bot): Add prompts, command handler and deployment script (#9570)
* feat(create-discord-bot): Add prompts, command handler and deployment script

* fix: revert package template name

* chore: make requested changes

* chore: make requested changes

* fix: remove uneeded listeners

* fix: use `0` for eslint

* fix: remaining requested changes

* chore: requested changes

* fix: remove redundant call
2023-07-16 17:13:18 +00:00
Jiralite
e5effb6f6a docs: Change Channel to BaseChannel (#9718)
docs: change `Channel` to `BaseChannel`
2023-07-16 15:06:14 +00:00
Jiralite
125405f1cf docs(BaseChannel): Remove APIChannel (#9717)
docs(BaseChannel): remove `APIChannel`
2023-07-16 14:59:35 +00:00
David Malchin
bc83cabfda feat(WebhooksAPI): allow with token requests without bot auth (#9715)
* Also move `get`'s `token` parameter to options.
2023-07-16 10:25:29 +00:00
brynpttrsn
20268ac0c4 feat(website): switch overload on hash location (#9699)
* feat(website): switch overload on hash location

* Update apps/website/src/components/OverloadSwitcher.tsx

---------

Co-authored-by: Noel <buechler.noel@outlook.com>
2023-07-15 19:34:28 +02:00
Aura Román
3c85fb21e6 feat(Client): add guildAvailable event (#9692)
* feat(Client): add `guildAvailable` event

* refactor: sort entries alphabetically

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-15 17:33:47 +00:00
brynpttrsn
4141405dcd fix(website): type alias search symbol (#9705) 2023-07-15 19:25:56 +02:00
David Malchin
8c782bfd52 fix(WebSocketShard): close errors not being catchable (#9704)
* fix(WebSocketShard): close errors not being catchable

* fix(WebSocketShard): requested changes
2023-07-15 10:55:05 +00:00
Almeida
8d97017458 feat: user avatar decorations (#8914)
feat(User): add avatar decorations

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2023-07-13 20:33:38 +00:00
DD
ceab07bec8 refactor(WebSocketShard): throttling error handling (#9701)
* refactor(WebSocketShard): handle unknown identify errors

* chore: use better abort check

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-12 17:19:11 +00:00
Jiralite
7fb91c57f7 fix(ChannelUpdate): Check against unknown channels (#9697)
fix(ChannelUpdate): check against unknown channels
2023-07-11 18:13:25 +00:00
Aura Román
09b0382c45 perf(Channel): linear speed position getter (#9497)
* perf(Channel): linear speed position getter

* fix: add another set of parens

* perf: lower memory and CPU usage

* refactor: add shared private utility for group types

* perf: improve readability and performance

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>

* feat: add support for voice sortables

---------

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-09 20:57:33 +00:00
Jiralite
719e54a921 fix(Action): Use existing recipients if available (#9653)
* fix(Action): use existing recipients if available

* fix: account for message delete -> interaction

* fix(Action): use `last_message_id` if it exists

* refactor(Action): use ternary

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-09 19:30:48 +00:00
Jiralite
ede9f4e5e2 docs(BuildersSelectMenuOption): Update link (#9690)
docs(BuildersSelectMenuOption): update link
2023-07-09 19:26:21 +00:00
MovementGH
df40dcdb85 feat: add silent option to ShardingManager (#9506)
* feat: add silent option to ShardingManager

* chore: update ShardingManagerOptions type

* chore: update typings

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2023-07-07 23:32:29 +00:00
RedGuy12
53c17e00c0 feat(EmbedBuilder): add .length (#8682)
* feat(Embed): add `.length`

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* Move to mainlib

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* types: add typings

---------

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-07 21:53:19 +00:00
Almeida
dc73c938ff feat: guild onboarding (#9120)
* feat: guild onboarding

* feat: types and /core method

* fix: route

* fix: make emoji name non-nullable

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-07 21:48:17 +00:00
Jiralite
a48d0efb09 types(MessageManager): Allow comparison of messages again (#9612)
* types(MessageManager): allow comparison of messages again

* feat: match TypeScript

* docs: update wording

* chore: revert breaking change

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-07 21:39:01 +00:00
GrapeColor
a73d54e43a feat: add resume event in shard (#9650)
Co-authored-by: GrapeColor <grapecolor@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-07 21:34:42 +00:00
Rodrigo Leitão
cf8012c200 refactor(User): remove deprecation warning from tag (#9660)
* refactor(User): remove deprecation warning from tag

* fix: remove unnecessary declarations

* style: fix formatting issue

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-06 16:49:03 +00:00
Synbulat Biishev
0803eb562b fix: everyone role members (#9685)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-06 14:09:31 +00:00
David Malchin
78381a56cf feat(ChannelsAPI): add permission overwrites (#9651)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-07-06 13:55:29 +00:00
Suneet Tipirneni
6d5840c61e fix(core): fix inconsistencies on core (#9680)
* fix(core): fix inconsistencies on `core`

* fix: add `createForumPost` back

* fix: create -> createWebhook
2023-07-06 13:35:10 +00:00
ShadowAya
75d91b52b3 setNameLocalization typo (#9656)
fix JSDoc typo in NameAndDescription.ts > setNameLocalization
2023-06-17 14:29:35 +00:00
Almeida
766be94b93 chore: bump discord-api-types to 0.37.45 (#9654) 2023-06-15 19:06:52 +00:00
RedGuy12
b61e4fb0dc fix: awaitMessageComponent with MessageComponentInteractions (#8598)
* fix: `awaitMessageComponent` with `MessageComponentInteraction`s

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

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

Co-authored-by: Almeida <almeidx@pm.me>

* types: revert unrelated changes

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* Remove unneeded truey check

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* chore: remove extra block

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* fix: `awaitMessageComponent` with `MessageComponentInteraction`s

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

* fix: `awaitMessageComponent` with `MessageComponentInteraction`s

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>

---------

Signed-off-by: RedGuy12 <61329810+RedGuy12@users.noreply.github.com>
Co-authored-by: Almeida <almeidx@pm.me>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 18:25:53 +00:00
Jiralite
d64330a157 types(AutoModerationActionExecution): Add forum channels as a possible type in channel() (#9623)
types(AutoModerationActionExecution): type forum channels

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 18:14:16 +00:00
Jiralite
2818d7cc1d fix(client): Add missing application command permissions update event (#9639)
fix(client): add missing event

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 18:11:00 +00:00
RedGuy12
a6dbe163dd fix(ThreadManager): Fix internal crash upon conditionally resolving thread members (#9648)
* fix(ThreadManager): Fix crash

* chore: prettier

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 18:07:48 +00:00
Souji
73c2f8aa17 feat(presence): re-introduce image resolving for other platforms (#9637)
* spotify, youtube, twitch
* regression born from misunderstanding in 9a6e691

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 17:45:28 +00:00
GrapeColor
a873ec1e85 feat: Add message to send resume event to shard (#9626)
* fix(WebSocketManager): Fix not ready after reconnect

* fix(WebSocketManager): Move fixes from Ready to Resume

* fix: undo changes

* feat: Add message to send resume event to shard

---------

Co-authored-by: GrapeColor <grapecolor@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-14 11:43:23 +00:00
dependabot[bot]
db925fa269 build(deps-dev): bump vite from 4.3.8 to 4.3.9 (#9625)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 4.3.8 to 4.3.9.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v4.3.9/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-13 19:20:07 +00:00
Ryan Munro
8f3bd38072 fix(User): check global name in equals (#9631)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-13 19:17:21 +00:00
ckohen
8f014c65ef chore: unpin rest, unbump node version req (#9632)
* chore: unpin rest, unbump node version req

* chore: update readmes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-13 19:08:35 +00:00
brynpttrsn
1716202f44 fix(website): Overload switcher duplicates reference links (#9614)
fix(website): add idx to link key
2023-06-13 21:01:18 +02:00
Rodrigo Leitão
1cab79f6fd types(ModalSubmitFields): components is an array (#9406)
* types(ModalSubmitFields): components is an array

* types(ModalSubmitFields): make type coherent with docs

* refactor(ModalSubmitInteraction): remove undefined props
2023-06-13 20:58:50 +02:00
brynpttrsn
7b494aca5b fix(website): switch signature with overload (#9643) 2023-06-13 20:55:56 +02:00
Jiralite
cd6986854f types: Use readonly arrays and const type parameters in places (#9641)
* types: wrap arrays in `Readonly<>`

* refactor: prefer `readonly` syntax

Co-authored-by: Almeida <almeidx@pm.me>

* types: `const` type parameters

* test: add tests

* fix: fix more instances

---------

Co-authored-by: Almeida <almeidx@pm.me>
2023-06-12 18:00:45 +00:00
Jiralite
6c2242f4f9 types(BaseInteraction): appPermissions not null in guilds (#9601)
types(BaseInteraction): allow `appPermissions` only in guilds

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-09 10:02:22 +00:00
Mogyuchi
75308f2669 fix(WebSocketManager): await WebSocket destroy (#9519)
fix(WebSocketManager): await ws destroy

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-09 09:59:18 +00:00
İbrahim
bc2798b8ee docs: Define /core token in example (#9586)
* Importing Token

Importing token was missing, so I added it. It is getting the token from configuration file. 

It could have been done with defining a constant variable too, but importing makes more sense.

* Updated Token Field to "dotenv"

From now, user's can use dotenv package to keep their Discord client token.

* Referring token as DISCORD_TOKEN

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>

---------

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-09 09:41:07 +00:00
volcanofr
a531dc9f1c RESTOptions: (really) small description update for cdn (#9615)
Small option update cnd REST.ts

I just add "``" to uniform cdn @defaultValue with others one (like api).
The link is not broken anymore, because it do not work anymore.

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-09 09:00:20 +00:00
Ryoh827
911e6eff75 docs(ClientOptions): change default value of sweepers in docs (#9591)
* docs(ClientOptions): change default value of sweepers in docs

* docs(ClientOptions): set sweeper defaults by type

* docs(ClientOptions): add 'this.' to DefaultSweeperSettings in docs

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-06-09 08:45:42 +00:00
Synbulat Biishev
1ab60f9da4 feat: support new username system (#9512)
* feat: support new username system

* docs(GuildMember#displayName): update

* fix(User#hasNewUsername): use User#discriminator

* feat(User#tag): add new username

* docs(User#tag): update

* docs(User#hasNewUsername): update

* docs: update

* feat(User#defaultAvatarURL): update

* feat: remove some newly added properties

* docs(User#discriminator): update

* docs(User#globalName): bad Copilot

* feat(User#displayName): return display name

* types(User#displayName): not a partial structure

* feat: add `calculateUserDefaultAvatarId` function

* docs(CND#defaultAvatar): update

* docs(CDN#defaultAvatar): update

* feat: change default avatar id to type

* feat: deprecate `User#tag`

* docs(CDN#defaultAvatar): update

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

* docs(User): update

Co-authored-by: Rodrigo Leitão <38259440+ImRodry@users.noreply.github.com>

* feat: update

* typing: update

Co-authored-by: Jan <66554238+vaporoxx@users.noreply.github.com>

* feat: change the param type to `Snowflake`

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Rodrigo Leitão <38259440+ImRodry@users.noreply.github.com>
Co-authored-by: Jan <66554238+vaporoxx@users.noreply.github.com>
2023-06-08 18:16:42 +00:00
Qjuh
df8b6e9934 fix(WebSocketManager): always cache result of fetchGatewayInformation (#9611)
* fix(WebSocketManager): always cache result of fetchGatewayInformation

* fix: add comment
2023-05-29 18:45:17 +00:00
nopeless
24a61495b9 fix(Client): safe call for possibly null WebSocket (#9600)
fix(client): safe call for possibly null Websocket
2023-05-26 17:27:17 +00:00
Jiralite
e1b6eeed0e docs(Client): Correct invite gateway permission checks (#9597)
docs: correct invite gateway permission checks
2023-05-26 08:18:48 +00:00
Jiralite
53aa24d418 fix(ThreadManager): Ensure fetchActive() only returns active threads in a channel (#9568)
fix(ThreadManager): revert breaking change

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-25 17:16:48 +00:00
iCrawl
9b06734445 chore: deps 2023-05-23 20:14:15 +02:00
Digital
9345d1b1ac fix(LimitedCollection): allow items to be stored if keepOverLimit is true when maxSize is 0 (#9534)
Update LimitedCollection.js

Keep value if it matches the limit.

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-22 08:11:47 +00:00
Jiralite
47843493a5 feat(guide): Add formatters popular topic (#9566)
* feat: add formatters page

* chore: rename pages
2023-05-22 10:06:48 +02:00
David Malchin
6c7a5ed1e7 fix(api): various fixes for overlooked stuff (#9588)
* types(GuildsAPI): fix `getWidgetSettings()` result type

* types(GuildsAPI): fix `beginPrune()` result type

* types(GuildsAPI): fix `editAutoModerationRule()` result type

* types(ApplicationCommandsAPI): fix guild application types

* types(GuildsAPI): fix `createTemplate()` body type

* fix(InteractionsAPI): make `followUp()` return the message

According to the Discord docs, creating a followup message is the same as executing a webhook, but *wait is always true*, meaning we always get the message.

* types(WebhooksAPI): fix result types
2023-05-22 07:59:57 +00:00
Jaw0r3k
985def3f25 feat(api): add stage instances (#9578)
* feat(core): add stage instances

* chore: use one import

* Apply suggestions from code review

Co-authored-by: Aura Román <kyradiscord@gmail.com>

* chore: requested changes

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

* Apply suggestions from code review

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

---------

Co-authored-by: Aura Román <kyradiscord@gmail.com>
Co-authored-by: David Malchin <malchin459@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-19 19:18:33 +00:00
Jiralite
1c4a12c7d6 types: use Snowflake instead of string for snowflakes (#9583)
fix: use `Snowflake` not `string`

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-19 17:33:43 +00:00
brynpttrsn
8107c5c0e7 fix(website): header and sidebar icons (#9574)
* fix: header icons

* Reorder imports

* remove field symbol

* fix type sidebar icon

* remove import

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-19 17:28:37 +00:00
Aura Román
b85a3f2dde refactor(collection): reduce reduce's code (#9581)
* refactor(collection): reduce `reduce`'s code

* fix: resolved bug in tests

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-18 21:05:48 +00:00
David Malchin
3535321b98 fix(GuildsAPI): use level rather than mfa_level when editing MFA (#9584) 2023-05-18 17:03:09 +00:00
Idris
46167a79d7 refactor(GuildMember): make _roles property non-enumerable (#9387)
* refactor(GuildMember): make _roles a getter and roles a normal prop

* fix: revert changes

* fix: requested changes

* fix: requested changes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-18 10:13:19 +00:00
Idris
cffa5d19c9 feat(guide): port Collectors page (#9567)
* feat(guide): port Collectors page

* fix: requested changes

* fix: requested changes

* fix: suggested changes

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-18 09:06:00 +00:00
David Malchin
5d6eed6414 feat(GuildsAPI): add removeMember() (#9576) 2023-05-16 09:37:06 +00:00
iCrawl
90e243d350 chore: deps 2023-05-16 00:14:14 +02:00
David Malchin
590f5bc38e feat(api): add getMemberBans() query options and getMemberBan() (#9569) 2023-05-14 07:40:04 +00:00
Jiralite
7196fe36e8 fix(AutocompleteInteraction): Prevent snake casing of locales (#9565)
* fix(AutocompleteInteraction): prevent snake casing of locales

* fix: avoid unnecessary overhead ops

Co-authored-by: Aura Román <kyradiscord@gmail.com>

---------

Co-authored-by: Aura Román <kyradiscord@gmail.com>
2023-05-12 22:03:10 +00:00
iCrawl
5351ab429b build(ui): tree-shake ui components 2023-05-12 20:20:42 +02:00
iCrawl
d033f925e0 fix(websites/guide): remove flex-basis 2023-05-12 20:02:04 +02:00
iCrawl
13073acefc fix(ui): expose options for discord components 2023-05-12 20:00:02 +02:00
iCrawl
7c8849fae5 chore: deps 2023-05-12 19:58:51 +02:00
Jiralite
d01e8aa8af docs: Fix broken links to new documentation (#9563)
docs: fix broken links
2023-05-12 16:54:25 +00:00
DD
4dcc9c50f8 fix(WebSocketShard): handle initial connect being a resume (#9549)
* fix(WebSocketShard): handle initial connect being a resume

* chore: remove leftover

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-11 17:42:10 +00:00
Jiralite
a51c48e743 fix(webhooks): Remove incorrect properties in edit message code sample (#9562)
fix(webhooks): remove incorrect properties in edit message code sample
2023-05-11 16:43:54 +00:00
Jiralite
1edd01a7a4 feat(client): Support more request member fields (#9475)
feat(client): support more request member fields

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-10 16:40:52 +00:00
Jiralite
7b617bd22e feat: Create discord-api-types documentation component (#9555)
feat: add discord-api-types link component

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-09 19:49:07 +00:00
brynpttrsn
0c175c02e9 fix(website): package and version button formatting (#9556)
* fix for djs package button and removed redundant divs

* version arrow formatting

* formatting
2023-05-09 16:02:52 +02:00
Jiralite
460ac7dfe2 chore: Add repository directory (#9552)
chore: add repository directory
2023-05-08 17:12:31 +00:00
Jiralite
64324a8be1 feat: Check for empty directory (#9539)
* feat: check for empty directory

* fix: correct error

Co-authored-by: space <spaceeec@yahoo.com>

---------

Co-authored-by: space <spaceeec@yahoo.com>
2023-05-08 09:00:09 +02:00
Jiralite
b6162bc5b5 fix: Resolve imports for Windows (#9546)
fix: windows why

Co-authored-by: DD <didinele.dev@gmail.com>
Co-authored-by: Almeida <almeidx@pm.me>
2023-05-08 08:59:53 +02:00
synicalsyntax
280ed0ce08 fix(website): various UI improvements (#9538)
* fix(website): raise category z-index to prevent clipping

* refactor(website): wrap footer badges when necessary to prevent overflow
2023-05-08 08:59:25 +02:00
Jaw0r3k
5b8d535fd6 fix: Non-existing data property (#9544)
fix: not existed data prop

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-07 19:39:43 +00:00
Almeida
c4a3120354 feat(create-discord-bot): inherit stdio when installing deps (#9543) 2023-05-07 19:27:33 +00:00
Jaw0r3k
8482e3c95d fix(create-discord-bot): Fix start script (#9542)
fix: not working npm start

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-05-07 19:08:23 +00:00
Superchupu
12482b70ed docs: add Cloudflare sponsorship in create-discord-bot readme (#9540)
chore: add cloudflare sponsorship in `create-discord-bot` readme
2023-05-07 18:47:46 +00:00
iCrawl
fa746b079d chore: patch tsup 2023-05-07 19:17:10 +02:00
iCrawl
fc3f0756a4 chore: configs 2023-05-07 18:26:46 +02:00
256 changed files with 9001 additions and 8368 deletions

View File

@@ -42,6 +42,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Install node.js v18
uses: actions/setup-node@v3

View File

@@ -14,11 +14,6 @@ logFilters:
nodeLinker: node-modules
packageExtensions:
'@storybook/core-common@*':
dependencies:
'@storybook/react-vite': 7.0.9
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: '@yarnpkg/plugin-interactive-tools'

View File

@@ -44,17 +44,17 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@code-hike/mdx": "^0.8.3",
"@code-hike/mdx": "^0.9.0",
"@discordjs/ui": "workspace:^",
"@react-icons/all-files": "^4.1.0",
"@vercel/analytics": "^1.0.1",
"@vercel/edge-config": "^0.1.9",
"@vercel/og": "^0.5.4",
"@vercel/edge-config": "^0.2.1",
"@vercel/og": "^0.5.9",
"ariakit": "^2.0.0-next.44",
"cmdk": "^0.2.0",
"contentlayer": "^0.3.2",
"next": "^13.4.1",
"next-contentlayer": "^0.3.2",
"contentlayer": "0.3.1",
"next": "^13.4.12",
"next-contentlayer": "0.3.1",
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-custom-scrollbars-2": "^4.5.0",
@@ -62,37 +62,37 @@
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"sharp": "^0.32.1"
"sharp": "^0.32.4"
},
"devDependencies": {
"@next/bundle-analyzer": "^13.4.1",
"@next/bundle-analyzer": "^13.4.12",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/html-escaper": "^3.0.0",
"@types/node": "18.16.5",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@unocss/cli": "^0.51.12",
"@unocss/eslint-config": "^0.51.12",
"@unocss/reset": "^0.51.12",
"@vitejs/plugin-react": "^4.0.0",
"@vitest/coverage-c8": "^0.31.0",
"concurrently": "^8.0.1",
"@types/node": "18.17.1",
"@types/react": "^18.2.17",
"@types/react-dom": "^18.2.7",
"@unocss/cli": "^0.54.0",
"@unocss/eslint-config": "^0.54.0",
"@unocss/reset": "^0.54.0",
"@vitejs/plugin-react": "^4.0.3",
"@vitest/coverage-c8": "^0.33.0",
"concurrently": "^8.2.0",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"happy-dom": "^9.10.9",
"happy-dom": "^10.5.2",
"hast-util-to-string": "^2.0.0",
"hastscript": "^7.2.0",
"html-escaper": "^3.0.3",
"lighthouse": "^10.2.0",
"lighthouse": "^10.4.0",
"prettier": "^2.8.8",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"unocss": "^0.51.12",
"vercel": "^29.1.1",
"vitest": "^0.31.0"
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"unocss": "^0.54.0",
"vercel": "^31.2.0",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=18.13.0"

View File

@@ -3,7 +3,7 @@
import { Providers } from './providers';
import { inter } from '~/util/fonts';
export default function GlobalError({ error }: { error: Error }) {
export default function GlobalError({ error }: { readonly error: Error }) {
console.error(error);
return (

View File

@@ -1,6 +1,6 @@
'use client';
export default function Error({ error }: { error: Error }) {
export default function Error({ error }: { readonly error: Error }) {
console.error(error);
return (

View File

@@ -6,7 +6,7 @@ export async function generateStaticParams() {
return allContents.map((content) => ({ slug: [content.slug] }));
}
export default function Page({ params }: { params: { slug: string[] } }) {
export default function Page({ params }: { readonly params: { slug: string[] } }) {
const content = allContents.find((content) => content.slug === params.slug?.join('/'));
if (!content) {

View File

@@ -0,0 +1,91 @@
import { FiExternalLink } from '@react-icons/all-files/fi/FiExternalLink';
import type { PropsWithChildren } from 'react';
import {
BASE_URL_DISCORD_API_TYPES,
DISCORD_API_TYPES_VERSION,
DISCORD_API_TYPES_VOICE_VERSION,
} from '~/util/constants';
interface DiscordAPITypesLinkOptions {
/**
* The initial documentation enum, interface, function etc.
*
* @example `'RESTJSONErrorCodes'`
*/
readonly parent?: string;
/**
* The scope of where this link lives.
*
* @remarks API does not have a scope.
*/
readonly scope?: 'gateway' | 'globals' | 'payloads' | 'rest' | 'rpc' | 'utils' | 'voice';
/**
* The symbol belonging to the parent.
*
* @example '`MaximumNumberOfGuildsReached'`
*/
readonly symbol?: string;
/**
* The type of the {@link DiscordAPITypesLinkOptions.parent}.
*
* @example `'enum'`
* @example `'interface'`
*/
readonly type?: string;
}
export function DiscordAPITypesLink({
parent,
scope,
symbol,
type,
children,
}: PropsWithChildren<DiscordAPITypesLinkOptions>) {
let url = BASE_URL_DISCORD_API_TYPES;
let text = 'discord-api-types';
if (type || parent) {
url += `/api/discord-api-types`;
switch (scope) {
case 'globals':
url += `-${scope}`;
break;
case 'gateway':
case 'payloads':
case 'rest':
url += `-${scope}/common`;
break;
case 'rpc':
case 'utils':
url += `-${scope}/${DISCORD_API_TYPES_VERSION}`;
break;
case 'voice':
url += `-${scope}/${DISCORD_API_TYPES_VOICE_VERSION}`;
break;
default:
url += `-${DISCORD_API_TYPES_VERSION}`;
}
if (type) {
url += `/${type}/${parent}`;
if (symbol) url += `#${symbol}`;
} else {
url += `#${parent}`;
}
text = `${parent}${symbol ? `#${symbol}` : ''}${type?.toUpperCase() === 'FUNCTION' ? '()' : ''}`;
}
return (
<a
className="inline-flex flex-row place-items-center gap-1"
href={url}
rel="external noopener noreferrer"
target="_blank"
>
{children ?? text}
<FiExternalLink size={18} />
</a>
);
}

View File

@@ -8,19 +8,19 @@ interface DocsLinkOptions {
*
* @remarks Functions automatically infer this.
*/
brackets?: boolean;
readonly brackets?: boolean;
/**
* The package.
*
* @defaultValue `'discord.js'`
*/
package?: (typeof PACKAGES)[number];
readonly package?: (typeof PACKAGES)[number];
/**
* The initial documentation class, function, interface etc.
*
* @example `'Client'`
*/
parent?: string;
readonly parent?: string;
/**
* Whether to reference a static property.
*
@@ -28,20 +28,20 @@ interface DocsLinkOptions {
* This should only be used for the https://discord.js.org domain
* as static properties are not identified in the URL.
*/
static?: boolean;
readonly static?: boolean;
/**
* The symbol belonging to the parent.
*
* @example '`login'`
*/
symbol?: string;
readonly symbol?: string;
/**
* The type of the {@link DocsLinkOptions.parent}.
*
* @example `'class'`
* @example `'Function'`
*/
type?: string;
readonly type?: string;
}
export function DocsLink({

View File

@@ -5,8 +5,8 @@ import workersLogo from '~/assets/powered-by-workers.png';
export default function Footer() {
return (
<footer className="md:pl-12 md:pr-12">
<div className="flex flex-wrap place-content-center gap-6 md:flex-nowrap md:gap-12">
<div className="flex basis-full flex-wrap place-content-center place-items-center gap-4 md:basis-auto">
<div className="flex flex-col flex-wrap place-content-center gap-6 pt-12 sm:flex-row md:gap-12">
<div className="flex flex-wrap place-content-center place-items-center gap-4">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
@@ -40,54 +40,56 @@ export default function Footer() {
/>
</a>
</div>
<div className="max-w-max flex grow basis-0 flex-col gap-2 md:basis-auto">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.gg/djs"
rel="external noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js/discussions"
rel="external noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
<div className="flex flex-col place-self-center gap-6 sm:flex-row md:gap-12">
<div className="max-w-max flex flex-col gap-2">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.gg/djs"
rel="external noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js/discussions"
rel="external noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
</div>
</div>
<div className="max-w-max flex grow basis-0 flex-col gap-2 md:basis-auto">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.js.org/docs"
rel="noopener noreferrer"
target="_blank"
>
discord.js documentation
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord-api-types.dev"
rel="external noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
<div className="max-w-max flex flex-col gap-2">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.js.org/docs"
rel="noopener noreferrer"
target="_blank"
>
discord.js documentation
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord-api-types.dev"
rel="external noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>
</div>

View File

@@ -2,6 +2,7 @@
import { Alert, Section, DiscordMessages, DiscordMessage, DiscordMessageEmbed } from '@discordjs/ui';
import { useMDXComponent } from 'next-contentlayer/hooks';
import { DiscordAPITypesLink } from './DiscordAPITypesLink';
import { H1 } from './H1';
import { H2 } from './H2';
import { H3 } from './H3';
@@ -9,7 +10,7 @@ import { H4 } from './H4';
import { DocsLink } from '~/components/DocsLink';
import { ResultingCode } from '~/components/ResultingCode';
export function Mdx({ code }: { code: string }) {
export function Mdx({ code }: { readonly code: string }) {
const Component = useMDXComponent(code);
return (
@@ -20,6 +21,7 @@ export function Mdx({ code }: { code: string }) {
DiscordMessages,
DiscordMessage,
DiscordMessageEmbed,
DiscordAPITypesLink,
DocsLink,
ResultingCode,
h1: H1,

View File

@@ -5,7 +5,7 @@ const LINK_HEIGHT = 30;
const INDICATOR_SIZE = 10;
const INDICATOR_OFFSET = (LINK_HEIGHT - INDICATOR_SIZE) / 2;
export function Outline({ headings }: { headings: any[] }) {
export function Outline({ headings }: { readonly headings: any[] }) {
// eslint-disable-next-line react/hook-use-state
const [active /* setActive */] = useState(0);

View File

@@ -1,4 +1,12 @@
export function PageButton({ url, title, direction }: { direction: 'next' | 'prev'; title: string; url: string }) {
export function PageButton({
url,
title,
direction,
}: {
readonly direction: 'next' | 'prev';
readonly title: string;
readonly url: string;
}) {
return (
<a
className="flex flex-row flex-col transform-gpu cursor-pointer select-none appearance-none place-items-center gap-2 rounded bg-light-600 px-4 py-3 leading-none no-underline outline-none active:translate-y-px active:bg-light-800 dark:bg-dark-600 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-400 dark:hover:bg-dark-500"

View File

@@ -162,4 +162,4 @@ client.on(Events.GuildAuditLogEntryCreate, async (auditLog) => {
</CH.Code>
If you want to check who banned a user, it's the same example as above except the _`action`_ should be _`AuditLogEvent.MemberBanAdd`_. You can check the rest of the types over at the [discord-api-types documentation](https://discord-api-types.dev/api/discord-api-types-v10/enum/AuditLogEvent).
If you want to check who banned a user, it's the same example as above except the _`action`_ should be <DiscordAPITypesLink type="enum" parent="AuditLogEvent" symbol="MemberBanAdd" />. You can check the rest of the possible actions on this page.

View File

@@ -0,0 +1,223 @@
---
title: Collectors
category: Popular topics
---
# Collectors
## Message collectors
{/* prettier-ignore */}
<DocsLink type="class" parent="Collector">Collectors</DocsLink> are useful to enable your bot to obtain _additional_ input after the first command was sent. An example would be initiating a quiz, where the bot will "await" a correct response from somebody.
### Basic message collector
Let's take a look at a basic message collector:
<CH.Code>
```js
const collectorFilter = (message) => message.content.includes('discord');
const collector = interaction.channel.createMessageCollector({ filter: collectorFilter, time: 15_000 });
collector.on('collect', (message) => {
console.log(`Collected ${message.content}`);
});
collector.on('end', (collected) => {
console.log(`Collected ${collected.size} messages`);
});
```
</CH.Code>
You can provide a _`filter`_ key to the object parameter of <DocsLink type="class" parent="TextChannel" symbol="createMessageCollector" brackets />. The value to this key should be a function that returns a boolean value to indicate if this message should be collected or not. To check for multiple conditions in your filter you can connect them using [logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators). If you don't provide a filter all messages in the channel the collector was started on will be collected.
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.
If a message passes through the filter, it will trigger the <DocsLink type="class" parent="Collector" symbol="e-collect" /> event for the _`collector`_ you've created. This message is then passed into the event listener as _`collected`_ and the provided function is executed. In the above example, you simply log the message. Once the collector finishes collecting based on the provided end conditions the <DocsLink type="class" parent="Collector" symbol="e-end" /> event emits.
You can control when a collector ends by supplying additional option keys when creating a collector:
- _`time`_: Amount of time in milliseconds the collector should run for
- _`max`_: Number of messages to successfully pass the filter
- _`maxProcessed`_: Number of messages encountered (no matter the filter result)
The benefit of using an event-based collector over _`awaitMessages()`_ (its promise-based counterpart) is that you can do something directly after each message is collected, rather than just after the collector ended. You can also stop the collector manually by calling <DocsLink type="class" parent="Collector" symbol="stop" brackets />.
### Await messages
Using <DocsLink type="class" parent="TextChannel" symbol="awaitMessages" brackets /> can be easier if you understand [Promises](../additional-info/understanding-async-await), and it allows you to have cleaner code overall. It is essentially identical to <DocsLink type="class" parent="TextChannel" symbol="createMessageCollector" brackets />, except promisified. However, the drawback of using this method is that you cannot do things before the Promise is resolved or rejected, either by an error or completion. However, it should do for most purposes, such as awaiting the correct response in a quiz. Instead of taking their example, let's set up a basic quiz command using the _`.awaitMessages()`_ feature.
First, you'll need some questions and answers to choose from, so here's a basic set:
<CH.Code>
```json
[
{
"question": "What color is the sky?",
"answers": ["blue"]
},
{
"question": "How many letters are there in the alphabet?",
"answers": ["26", "twenty-six", "twenty six", "twentysix"]
}
]
```
</CH.Code>
The provided set allows for responder error with an array of answers permitted. Ideally, it would be best to place this in a JSON file, which you can call _`quiz.json`_ for simplicity.
<CH.Code>
```js
import quiz from './quiz.json' assert { type: 'json' };
// ...
const item = quiz[Math.floor(Math.random() * quiz.length)];
const collectorFilter = (response) => {
return item.answers.some((answer) => answer.toLowerCase() === response.content.toLowerCase());
};
await interaction.reply({ content: item.question });
try {
const collected = await interaction.channel.awaitMessages({
filter: collectorFilter,
max: 1,
time: 30_000,
errors: ['time'],
});
await interaction.followUp(`${collected.first().author} got the correct answer!`);
} catch {
await interaction.followUp('Looks like nobody got the answer this time.');
}
```
</CH.Code>
<Alert title="Tip" type="info">
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).
</Alert>
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.
The filter looks for messages that match one of the answers in the array of possible answers to pass through the collector. The _`max`_ option (the second parameter) specifies that only a maximum of one message can go through the filter successfully before the Promise successfully resolves. The _`errors`_ section specifies that time will cause it to error out, which will cause the Promise to reject if one correct answer is not received within the time limit of one minute. As you can see, there is no _`collect`_ event, so you are limited in that regard.
## Reaction collectors
### Basic reaction collector
These work quite similarly to message collectors, except that you apply them on a message rather than a channel. This example uses the <DocsLink type="class" parent="Message" symbol="createReactionCollector" brackets /> method. The filter will check for the 👍 emojiin the default skin tone specifically, so be wary of that. It will also check that the person who reacted shares the same id as the author of the original message that the collector was assigned to.
```js
const collectorFilter = (reaction, user) => {
return reaction.emoji.name === '👍' && user.id === message.author.id;
};
const collector = message.createReactionCollector({ filter: collectorFilter, time: 15_000 });
collector.on('collect', (reaction, user) => {
console.log(`Collected ${reaction.emoji.name} from ${user.tag}`);
});
collector.on('end', (collected) => {
console.log(`Collected ${collected.size} items`);
});
```
### Await reactions
<DocsLink type="class" parent="Message" symbol="awaitReactions" brackets /> works almost the same as a reaction collector,
except it is Promise-based. The same differences apply as with channel collectors.
```js
const collectorFilter = (reaction, user) => {
return reaction.emoji.name === '👍' && user.id === message.author.id;
};
try {
const collected = await message.awaitReactions({ filter: collectorFilter, max: 1, time: 60_000, errors: ['time'] });
console.log(collected.size);
} catch (collected) {
console.log(`After a minute, the user did not react.`);
}
```
## Interaction collectors
The third type of collector allows you to collect interactions; such as when users activate a slash command or click on a button in a message.
### Basic message component collector
Collecting interactions from message components works similarly to reaction collectors. In the following example, you will check that the interaction came from a button, and that the user clicking the button is the same user that initiated the command.
One important difference to note with interaction collectors is that Discord expects a response to _all_ interactions within 3 seconds - even ones that you don't want to collect. For this reason, you may wish to _`.deferUpdate()`_ all interactions in your filter, or not use a filter at all and handle this behavior in the _`collect`_ event.
```js
import { ComponentType } from 'discord.js';
const collector = message.createMessageComponentCollector({ componentType: ComponentType.Button, time: 15_000 });
collector.on('collect', (i) => {
if (i.user.id === interaction.user.id) {
await i.reply(`${i.user.id} clicked on the ${i.customId} button.`);
} else {
await i.reply({ content: `These buttons aren't for you!`, ephemeral: true });
}
});
collector.on('end', (collected) => {
console.log(`Collected ${collected.size} interactions.`);
});
```
### Await message component
As before, this works similarly to the message component collector, except it is Promise-based.
Unlike other Promise-based collectors, this method will only ever collect one interaction that passes the filter. If no interactions are collected before the time runs out, the Promise will reject. This behavior aligns with Discord's requirement that actions should immediately receive a response. In this example, you will use _`.deferUpdate()`_ on all interactions in the filter.
```js
import { ComponentType } from 'discord.js';
const collectorFilter = (i) => {
i.deferUpdate();
return i.user.id === interaction.user.id;
};
try {
const interaction = await message.awaitMessageComponent({
filter: collectorFilter,
componentType: ComponentType.StringSelect,
time: 60_000,
});
await interaction.editReply(`You selected ${interaction.values.join(', ')}!`);
} catch (error) {
console.log('No interactions were collected.');
}
```
### Await modal submit
If you want to wait for the submission of a modal within the context of another command or button execution, you may find the promisified collector <DocsLink type="class" parent="CommandInteraction" symbol="awaitModalSubmit" brackets /> useful.
As Discord does not inform you if the user dismisses the modal, supplying a maximum _`time`_ to wait for is crucial:
```js
try {
const interaction = await initialInteraction.awaitModalSubmit({ time: 60_000, filter });
await interaction.editReply('Thank you for your submission!');
} catch (error) {
console.log('No modal submit interaction was collected');
}
```
For more information on working with modals, see the [modals section of this guide](../interactions/modals).

View File

@@ -0,0 +1,95 @@
---
title: Formatters
category: Popular topics
---
# Formatters
discord.js provides the <DocsLink package="formatters" /> package which contains a variety of utilities you can use when writing your Discord bot.
## Basic Markdown
These functions format strings into all the different markdown styles supported by Discord.
<CH.Code>
```js
import { bold, italic, strikethrough, underscore, spoiler, quote, blockQuote } from 'discord.js';
const string = 'Hello!';
const boldString = bold(string);
const italicString = italic(string);
const strikethroughString = strikethrough(string);
const underscoreString = underscore(string);
const spoilerString = spoiler(string);
const quoteString = quote(string);
const blockquoteString = blockQuote(string);
```
</CH.Code>
## Links
There are also two functions to format hyperlinks. _`hyperlink()`_ will format the URL into a masked markdown link, and _`hideLinkEmbed()`_ will wrap the URL in _`<>`_, preventing it from embedding.
<CH.Code>
```js
import { hyperlink, hideLinkEmbed } from 'discord.js';
const url = 'https://discord.js.org/';
const link = hyperlink('discord.js', url);
const hiddenEmbed = hideLinkEmbed(url);
```
</CH.Code>
## Code blocks
You can use _`inlineCode()`_ and _`codeBlock()`_ to turn a string into an inline code block or a regular code block with or without syntax highlighting.
<CH.Code>
```js
import { inlineCode, codeBlock } from 'discord.js';
const jsString = 'const value = true;';
const inline = inlineCode(jsString);
const codeblock = codeBlock(jsString);
const highlighted = codeBlock('js', jsString);
```
</CH.Code>
## Timestamps
With _`time()`_, you can format Unix timestamps and dates into a Discord time string.
<CH.Code>
```js
import { time, TimestampStyles } from 'discord.js';
const date = new Date();
const timeString = time(date);
const relative = time(date, TimestampStyles.RelativeTime);
```
</CH.Code>
## Mentions
_`userMention()`_, _`channelMention()`_, and _`roleMention()`_ all exist to format Snowflakes into mentions.
<CH.Code>
```js
import { channelMention, roleMention, userMention } from 'discord.js';
const id = '123456789012345678';
const channel = channelMention(id);
const role = roleMention(id);
const user = userMention(id);
```
</CH.Code>

View File

@@ -208,8 +208,6 @@ You can use <DocsLink type="class" parent="Webhook" symbol="editMessage" bracket
```js
const message = await webhook.editMessage('123456789012345678', {
content: 'Edited!',
username: 'some-username',
avatarURL: 'https://guide.discordjs.dev/assets/discordjs.png',
embeds: [embed],
});
```

View File

@@ -41,7 +41,7 @@ discord.js v14 makes the switch to Discord API v10!
Any areas that used to accept a _`string`_ or _`number`_ type for an enum parameter will now only accept a _`number`_.
In addition, the old enums exported by discord.js v13 and lower are replaced with new enums from [discord-api-types](https://discord-api-types.dev/api/discord-api-types-v10).
In addition, the old enums exported by discord.js v13 and lower are replaced with new enums from <DiscordAPITypesLink />.
#### New enum differences
@@ -121,7 +121,7 @@ Areas like _`Client`_ initialization, JSON slash commands and JSON message compo
#### Channels
Some channel type guard methods that narrowed to one channel type have been removed. Instead compare the _`type`_ property against a [ChannelType](https://discord-api-types.dev/api/discord-api-types-v10/enum/ChannelType) enum member to narrow channels.
Some channel type guard methods that narrowed to one channel type have been removed. Instead compare the _`type`_ property against a <DiscordAPITypesLink type="enum" parent="ChannelType" /> enum member to narrow channels.
<CH.Code>
@@ -361,7 +361,7 @@ _`IntegrationApplication#summary`_ has been removed as it is no longer supported
### Interaction
Whenever an interaction is replied to and one fetches the reply, it could possibly give an [APIMessage](https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMessage) if the guild was not cached. However, interaction replies now always return a discord.js <DocsLink type="class" parent="Message"/> object with _`fetchReply`_ as _`true`_.
Whenever an interaction is replied to and one fetches the reply, it could possibly give an <DiscordAPITypesLink type="interface" parent="APIMessage" /> if the guild was not cached. However, interaction replies now always return a discord.js <DocsLink type="class" parent="Message"/> object with _`fetchReply`_ as _`true`_.
The base interaction class is now <DocsLink type="class" parent="BaseInteraction"/>.
@@ -690,7 +690,7 @@ Added support for role connection metadata.
A new <DocsLink type="class" parent="Collector" symbol="e-ignore"/> event has been added which is emitted whenever an element is not collected by the collector.
Component collector options now use the [ComponentType](https://discord-api-types.dev/api/discord-api-types-v10/enum/ComponentType) enum values:
Component collector options now use the <DiscordAPITypesLink type="enum" parent="ComponentType" /> enum values:
<CH.Code>

View File

@@ -2,6 +2,8 @@ export const BASE_URL = 'https://discord.js.org/docs/packages' as const;
export const BASE_URL_LEGACY = 'https://old.discordjs.dev/#/docs/discord.js' as const;
export const BASE_URL_DISCORD_API_TYPES = 'https://discord-api-types.dev' as const;
export const DESCRIPTION = 'Imagine a guide... that explores the many possibilities for your discord.js bot.';
export const GITHUB_BASE_PAGES_PATH = 'https://github.com/discordjs/discord.js/tree/main/apps/guide/src/pages';
@@ -25,3 +27,13 @@ export const PACKAGES = [
* The stable version of discord.js.
*/
export const VERSION = '14.11.0' as const;
/**
* The API version (for discord-api-types). This is prefixed with a "v".
*/
export const DISCORD_API_TYPES_VERSION = 'v10' as const;
/**
* The voice API version (for discord-api-types). This is prefixed with a "v".
*/
export const DISCORD_API_TYPES_VOICE_VERSION = 'v4' as const;

View File

@@ -49,19 +49,19 @@
"@discordjs/api-extractor-utils": "workspace:^",
"@discordjs/scripts": "workspace:^",
"@discordjs/ui": "workspace:^",
"@microsoft/api-extractor-model": "7.26.8",
"@microsoft/api-extractor-model": "7.27.5",
"@microsoft/tsdoc": "0.14.2",
"@planetscale/database": "1.7.0",
"@react-icons/all-files": "^4.1.0",
"@vercel/analytics": "^1.0.1",
"@vercel/edge-config": "^0.1.9",
"@vercel/og": "^0.5.4",
"@vercel/edge-config": "^0.2.1",
"@vercel/og": "^0.5.9",
"ariakit": "^2.0.0-next.44",
"bright": "^0.8.2",
"class-variance-authority": "^0.6.0",
"bright": "^0.8.4",
"class-variance-authority": "^0.7.0",
"cmdk": "^0.2.0",
"meilisearch": "^0.32.3",
"next": "^13.4.1",
"meilisearch": "^0.33.0",
"next": "^13.4.12",
"next-mdx-remote": "^4.4.1",
"next-themes": "^0.2.1",
"react": "^18.2.0",
@@ -71,34 +71,34 @@
"rehype-raw": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"sharp": "^0.32.1",
"swr": "^2.1.5"
"sharp": "^0.32.4",
"swr": "^2.2.0"
},
"devDependencies": {
"@next/bundle-analyzer": "^13.4.1",
"@next/bundle-analyzer": "^13.4.12",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "18.16.5",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"@unocss/cli": "^0.51.12",
"@unocss/eslint-config": "^0.51.12",
"@unocss/reset": "^0.51.12",
"@vitejs/plugin-react": "^4.0.0",
"@vitest/coverage-c8": "^0.31.0",
"concurrently": "^8.0.1",
"cpy-cli": "^4.2.0",
"@types/node": "18.17.1",
"@types/react": "^18.2.17",
"@types/react-dom": "^18.2.7",
"@unocss/cli": "^0.54.0",
"@unocss/eslint-config": "^0.54.0",
"@unocss/reset": "^0.54.0",
"@vitejs/plugin-react": "^4.0.3",
"@vitest/coverage-c8": "^0.33.0",
"concurrently": "^8.2.0",
"cpy-cli": "^5.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"happy-dom": "^9.10.9",
"lighthouse": "^10.2.0",
"happy-dom": "^10.5.2",
"lighthouse": "^10.4.0",
"prettier": "^2.8.8",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vercel": "^29.1.1",
"vitest": "^0.31.0"
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vercel": "^31.2.0",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=18.13.0"

View File

@@ -73,7 +73,7 @@ export const metadata: Metadata = {
},
};
export default function GlobalError({ error }: { error: Error }) {
export default function GlobalError({ error }: { readonly error: Error }) {
console.error(error);
return (

View File

@@ -116,7 +116,7 @@ export async function generateStaticParams({ params: { package: packageName, ver
}));
}
function Member({ member }: { member?: ApiItem }) {
function Member({ member }: { readonly member?: ApiItem }) {
switch (member?.kind) {
case 'Class':
return <Class clazz={member as ApiClass} />;

View File

@@ -1,6 +1,6 @@
'use client';
export default function Error({ error }: { error: Error }) {
export default function Error({ error }: { readonly error: Error }) {
console.error(error);
return (

View File

@@ -27,7 +27,7 @@ export default async function Page({ params }: { params: VersionRouteParams }) {
return (
<div className="max-w-none prose">
{/* @ts-expect-error async component */}
{/* @ts-expect-error SyntaxHighlighter is assignable */}
<MDXRemote components={{ pre: SyntaxHighlighter }} options={mdxOptions} source={readmeSource} />
</div>
);

View File

@@ -36,7 +36,7 @@ export default async function Page({ params }: { params: { package: string } })
href={`/docs/packages/${params.package}/${version}`}
key={`${version}-${idx}`}
>
<div className="flex flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscVersions size={25} />
<h2 className="font-semibold">{version}</h2>

View File

@@ -13,16 +13,11 @@ export default function Page() {
<div className="mx-auto min-h-screen min-w-xs flex flex-col gap-8 px-4 py-6 sm:w-md lg:px-6 lg:py-6">
<h1 className="text-2xl font-semibold">Select a package:</h1>
<div className="flex flex-col gap-4">
<a
className="h-11 flex transform-gpu cursor-pointer select-none appearance-none place-content-between border border-neutral-300 rounded bg-white p-4 text-base font-semibold leading-none text-black outline-none active:translate-y-px dark:border-dark-100 active:bg-neutral-200 dark:bg-dark-400 hover:bg-neutral-100 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300"
href="https://old.discordjs.dev/#/docs/discord.js"
>
<a className={buttonVariants({ variant: 'secondary' })} href="https://old.discordjs.dev/#/docs/discord.js">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">discord.js</h2>
</div>
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">discord.js</h2>
</div>
<VscArrowRight size={20} />
</div>
@@ -34,31 +29,27 @@ export default function Page() {
key={`${pkg}-${idx}`}
>
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">{pkg}</h2>
</div>
{/* <Link href={`/docs/packages/${pkg}`}>
<div
className="bg-blurple focus:ring-width-2 flex h-6 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-center place-items-center rounded border-0 px-2 text-xs font-semibold leading-none text-white outline-none focus:ring focus:ring-white active:translate-y-px"
role="link"
>
Select version
</div>
</Link> */}
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">{pkg}</h2>
</div>
{/* <Link href={`/docs/packages/${pkg}`}>
<div
className="bg-blurple focus:ring-width-2 flex h-6 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-center place-items-center rounded border-0 px-2 text-xs font-semibold leading-none text-white outline-none focus:ring focus:ring-white active:translate-y-px"
role="link"
>
Select version
</div>
</Link> */}
<VscArrowRight size={20} />
</div>
</Link>
))}
<a className={buttonVariants({ variant: 'secondary' })} href="https://discord-api-types.dev/">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">discord-api-types</h2>
</div>
<div className="flex flex-row place-content-between place-items-center gap-4">
<VscPackage size={25} />
<h2 className="font-semibold">discord-api-types</h2>
</div>
<FiExternalLink size={20} />
</div>

View File

@@ -1,6 +1,6 @@
'use client';
export default function Error({ error }: { error: Error }) {
export default function Error({ error }: { readonly error: Error }) {
console.error(error);
return (

View File

@@ -20,9 +20,12 @@ export default function Page() {
Discord bots.
</h1>
<p className="my-6 leading-normal text-neutral-700 dark:text-neutral-300">{DESCRIPTION}</p>
<div className="flex gap-4 md:flex-row">
<Link className={buttonVariants()} href="/docs">
<div className="flex flex-wrap place-content-center gap-4 md:flex-row">
<a className={buttonVariants()} href="https://old.discordjs.dev/#/docs" rel="noopener noreferrer">
Docs
</a>
<Link className={buttonVariants()} href="/docs">
Module docs
</Link>
<a
className={buttonVariants({ variant: 'secondary' })}

View File

@@ -1,6 +1,6 @@
import { FiLink } from '@react-icons/all-files/fi/FiLink';
export function Anchor({ href }: { href: string }) {
export function Anchor({ href }: { readonly href: string }) {
return (
<a className="mr-1 inline-block rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple" href={href}>
<FiLink size={20} />

View File

@@ -8,7 +8,10 @@ export enum BadgeColor {
Warning = 'bg-yellow-500',
}
export function Badge({ children, color = BadgeColor.Primary }: PropsWithChildren<{ color?: BadgeColor | undefined }>) {
export function Badge({
children,
color = BadgeColor.Primary,
}: PropsWithChildren<{ readonly color?: BadgeColor | undefined }>) {
return (
<span
className={`h-5 flex flex-row place-content-center place-items-center rounded-full px-3 text-center text-xs font-semibold uppercase text-white ${color}`}
@@ -18,7 +21,7 @@ export function Badge({ children, color = BadgeColor.Primary }: PropsWithChildre
);
}
export function Badges({ item }: { item: ApiDocumentedItem }) {
export function Badges({ item }: { readonly item: ApiDocumentedItem }) {
const isStatic = ApiStaticMixin.isBaseClassOf(item) && item.isStatic;
const isProtected = ApiProtectedMixin.isBaseClassOf(item) && item.isProtected;
const isReadonly = ApiReadonlyMixin.isBaseClassOf(item) && item.isReadonly;

View File

@@ -4,7 +4,6 @@ import type { ApiItemKind } from '@microsoft/api-extractor-model';
import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
import { VscSymbolField } from '@react-icons/all-files/vsc/VscSymbolField';
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty';
@@ -28,7 +27,7 @@ function resolveIcon(item: keyof typeof ApiItemKind) {
case 'Property':
return <VscSymbolProperty className="shrink-0" size={25} />;
case 'TypeAlias':
return <VscSymbolField className="shrink-0" size={25} />;
return <VscSymbolVariable className="shrink-0" size={25} />;
case 'Variable':
return <VscSymbolVariable className="shrink-0" size={25} />;
default:

View File

@@ -5,15 +5,15 @@ export interface CodeListingProps {
/**
* The value of this heading.
*/
children: ReactNode;
readonly children: ReactNode;
/**
* Additional class names to apply to the root element.
*/
className?: string | undefined;
readonly className?: string | undefined;
/**
* The href of this heading.
*/
href?: string | undefined;
readonly href?: string | undefined;
}
export function CodeHeading({ href, className, children }: CodeListingProps) {

View File

@@ -8,11 +8,11 @@ export interface ExcerptTextProps {
/**
* The tokens to render.
*/
excerpt: Excerpt;
readonly excerpt: Excerpt;
/**
* The model to resolve item references from.
*/
model: ApiModel;
readonly model: ApiModel;
}
/**
@@ -49,7 +49,7 @@ export function ExcerptText({ model, excerpt }: ExcerptTextProps) {
<ItemLink
className="text-blurple"
itemURI={resolveItemURI(item)}
key={`${item.displayName}-${item.containerKey}`}
key={`${item.displayName}-${item.containerKey}-${idx}`}
packageName={item.getAssociatedPackage()?.displayName.replace('@discordjs/', '')}
>
{token.text}

View File

@@ -5,92 +5,90 @@ import workersLogo from '~/assets/powered-by-workers.png';
export default function Footer() {
return (
<footer className="md:pl-12 md:pr-12">
<div className="mx-auto max-w-6xl flex flex-col place-items-center gap-12 pt-12 lg:place-content-center">
<div className="w-full flex flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
<div className="flex flex-col gap-4 lg:flex-row">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="external noopener noreferrer"
target="_blank"
title="Vercel"
>
<Image
alt="Vercel"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
height={44}
placeholder="blur"
src={vercelLogo}
width={212}
/>
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://www.cloudflare.com"
rel="external noopener noreferrer"
target="_blank"
title="Cloudflare Workers"
>
<Image
alt="Cloudflare"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
height={44}
placeholder="blur"
priority
src={workersLogo}
/>
</a>
</div>
<div className="flex flex-row gap-6 md:gap-12">
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.gg/djs"
rel="external noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js/discussions"
rel="external noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
<div className="flex flex-col flex-wrap place-content-center gap-6 pt-12 sm:flex-row md:gap-12">
<div className="flex flex-wrap place-content-center place-items-center gap-4">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="external noopener noreferrer"
target="_blank"
title="Vercel"
>
<Image
alt="Vercel"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
height={44}
placeholder="blur"
src={vercelLogo}
width={212}
/>
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://www.cloudflare.com"
rel="external noopener noreferrer"
target="_blank"
title="Cloudflare Workers"
>
<Image
alt="Cloudflare"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
height={44}
placeholder="blur"
priority
src={workersLogo}
/>
</a>
</div>
<div className="flex flex-col place-self-center gap-6 sm:flex-row md:gap-12">
<div className="max-w-max flex flex-col gap-2">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.gg/djs"
rel="external noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js/discussions"
rel="external noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discordjs.guide"
rel="noopener noreferrer"
target="_blank"
>
discord.js guide
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord-api-types.dev"
rel="external noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
<div className="max-w-max flex flex-col gap-2">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://github.com/discordjs/discord.js"
rel="external noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord.js.org/docs"
rel="noopener noreferrer"
target="_blank"
>
discord.js documentation
</a>
<a
className="rounded outline-none focus:ring focus:ring-width-2 focus:ring-blurple"
href="https://discord-api-types.dev"
rel="external noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>

View File

@@ -2,7 +2,7 @@ import type { ApiDeclaredItem } from '@microsoft/api-extractor-model';
import { ItemLink } from './ItemLink';
import { resolveItemURI } from './documentation/util';
export function InheritanceText({ parent }: { parent: ApiDeclaredItem }) {
export function InheritanceText({ parent }: { readonly parent: ApiDeclaredItem }) {
return (
<span className="font-semibold">
Inherited from{' '}

View File

@@ -10,17 +10,17 @@ export interface ItemLinkProps
extends Omit<LinkProps, 'href'>,
RefAttributes<HTMLAnchorElement>,
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps> {
className?: string;
readonly className?: string;
/**
* The URI of the api item to link to. (e.g. `/RestManager`)
*/
itemURI: string;
readonly itemURI: string;
/**
* The name of the package the item belongs to.
*/
packageName?: string | undefined;
readonly packageName?: string | undefined;
}
/**

View File

@@ -9,7 +9,7 @@ import { useNav } from '~/contexts/nav';
const PackageSelect = dynamic(async () => import('./PackageSelect'));
const VersionSelect = dynamic(async () => import('./VersionSelect'));
export function Nav({ members }: { members: SidebarSectionItemData[] }) {
export function Nav({ members }: { readonly members: SidebarSectionItemData[] }) {
const { opened } = useNav();
return (

View File

@@ -4,7 +4,7 @@ import { Scrollbars } from './Scrollbars';
import type { TableOfContentsSerialized } from './TableOfContentItems';
import { TableOfContentItems } from './TableOfContentItems';
export function Outline({ members }: { members: TableOfContentsSerialized[] }) {
export function Outline({ members }: { readonly members: TableOfContentsSerialized[] }) {
return (
<aside className="fixed bottom-0 right-0 top-[50px] z-20 hidden h-[calc(100vh_-_65px)] w-64 border-l border-light-800 bg-white pr-2 xl:block dark:border-dark-100 dark:bg-dark-600">
<Scrollbars

View File

@@ -4,17 +4,52 @@ import { VscChevronDown } from '@react-icons/all-files/vsc/VscChevronDown';
import { VscVersions } from '@react-icons/all-files/vsc/VscVersions';
import { Menu, MenuButton, MenuItem, useMenuState } from 'ariakit/menu';
import type { PropsWithChildren, ReactNode } from 'react';
import { useMemo, useState } from 'react';
import { useCallback, useMemo, useState, useEffect } from 'react';
export interface OverloadSwitcherProps {
methodName: string;
overloads: ReactNode[];
}
export default function OverloadSwitcher({ overloads, children }: PropsWithChildren<{ overloads: ReactNode[] }>) {
export default function OverloadSwitcher({
methodName,
overloads,
children,
}: PropsWithChildren<{ readonly methodName: string; readonly overloads: ReactNode[] }>) {
const [hash, setHash] = useState(() => (typeof window === 'undefined' ? '' : window.location.hash));
const hashChangeHandler = useCallback(() => {
setHash(window.location.hash);
}, []);
const [overloadIndex, setOverloadIndex] = useState(1);
const overloadedNode = overloads[overloadIndex - 1]!;
const menu = useMenuState({ gutter: 8, sameWidth: true, fitViewport: true });
useEffect(() => {
window.addEventListener('hashchange', hashChangeHandler);
return () => {
window.removeEventListener('hashchange', hashChangeHandler);
};
});
useEffect(() => {
if (hash) {
const elementId = hash.replace('#', '');
const [name, idx] = elementId.split(':');
if (name && methodName === name) {
if (idx) {
const hashOverload = Number.parseInt(idx, 10);
const resolvedOverload = Math.max(Math.min(hashOverload, overloads.length), 1);
setOverloadIndex(Number.isNaN(resolvedOverload) ? 1 : resolvedOverload);
}
const element = document.querySelector(`[id^='${name}']`);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}
}
}, [hash, methodName, overloads.length]);
const menuItems = useMemo(
() =>
overloads.map((_, idx) => (

View File

@@ -10,7 +10,7 @@ const columnStyles = {
Type: 'font-mono whitespace-pre-wrap break-normal',
};
export function ParameterTable({ item }: { item: ApiDocumentedItem & ApiParameterListMixin }) {
export function ParameterTable({ item }: { readonly item: ApiDocumentedItem & ApiParameterListMixin }) {
const params = resolveParameters(item);
const rows = useMemo(

View File

@@ -16,8 +16,8 @@ export function Property({
children,
inheritedFrom,
}: PropsWithChildren<{
inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
item: ApiProperty | ApiPropertySignature;
readonly inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
readonly item: ApiProperty | ApiPropertySignature;
}>) {
const hasSummary = Boolean(item.tsdocComment?.summarySection);

View File

@@ -14,7 +14,7 @@ export function isPropertyLike(item: ApiItem): item is ApiProperty | ApiProperty
return item.kind === ApiItemKind.Property || item.kind === ApiItemKind.PropertySignature;
}
export function PropertyList({ item }: { item: ApiItemContainerMixin }) {
export function PropertyList({ item }: { readonly item: ApiItemContainerMixin }) {
const members = resolveMembers(item, isPropertyLike);
const propertyItems = useMemo(

View File

@@ -3,7 +3,6 @@
import type { ApiItemKind } from '@microsoft/api-extractor-model';
import { VscSymbolClass } from '@react-icons/all-files/vsc/VscSymbolClass';
import { VscSymbolEnum } from '@react-icons/all-files/vsc/VscSymbolEnum';
import { VscSymbolField } from '@react-icons/all-files/vsc/VscSymbolField';
import { VscSymbolInterface } from '@react-icons/all-files/vsc/VscSymbolInterface';
import { VscSymbolMethod } from '@react-icons/all-files/vsc/VscSymbolMethod';
import { VscSymbolVariable } from '@react-icons/all-files/vsc/VscSymbolVariable';
@@ -74,7 +73,6 @@ function resolveIcon(item: string) {
case 'Interfaces':
return <VscSymbolInterface size={20} />;
case 'Types':
return <VscSymbolField size={20} />;
case 'Variables':
return <VscSymbolVariable size={20} />;
default:
@@ -82,7 +80,7 @@ function resolveIcon(item: string) {
}
}
export function Sidebar({ members }: { members: SidebarSectionItemData[] }) {
export function Sidebar({ members }: { readonly members: SidebarSectionItemData[] }) {
const segment = useSelectedLayoutSegment();
const { setOpened } = useNav();
@@ -94,7 +92,7 @@ export function Sidebar({ members }: { members: SidebarSectionItemData[] }) {
.filter((group) => groupItems[group].length)
.map((group, idx) => (
<Section
buttonClassName="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-400 dark:hover:bg-dark-300 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple rounded p-3 outline-none focus:ring"
buttonClassName="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-400 dark:hover:bg-dark-300 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple rounded p-3 outline-none focus:ring z-10"
icon={resolveIcon(group)}
key={`${group}-${idx}`}
title={group}

View File

@@ -1,9 +1,9 @@
import type { ApiModel, Excerpt } from '@microsoft/api-extractor-model';
import { ExcerptText } from './ExcerptText';
export function SignatureText({ excerpt, model }: { excerpt: Excerpt; model: ApiModel }) {
export function SignatureText({ excerpt, model }: { readonly excerpt: Excerpt; readonly model: ApiModel }) {
return (
<h4 className="break-all font-mono text-lg font-bold">
<h4 className="break-all text-lg font-bold font-mono">
<ExcerptText excerpt={excerpt} model={model} />
</h4>
);

View File

@@ -4,11 +4,9 @@ export function SyntaxHighlighter(props: typeof Code) {
return (
<>
<div data-theme="dark">
{/* @ts-expect-error async component */}
<Code codeClassName="font-mono" lang={props.lang ?? 'typescript'} {...props} theme="github-dark-dimmed" />
</div>
<div className="[&_pre]:border [&_pre]:border-gray-300 [&_pre]:rounded-md" data-theme="light">
{/* @ts-expect-error async component */}
<Code codeClassName="font-mono" lang={props.lang ?? 'typescript'} {...props} theme="min-light" />
</div>
</>

View File

@@ -7,9 +7,9 @@ export function Table({
columns,
columnStyles,
}: {
columnStyles?: Record<string, string>;
columns: string[];
rows: Record<string, ReactNode>[];
readonly columnStyles?: Record<string, string>;
readonly columns: string[];
readonly rows: Record<string, ReactNode>[];
}) {
const cols = useMemo(
() =>

View File

@@ -19,10 +19,10 @@ export interface TableOfContentsSerializedProperty {
export type TableOfContentsSerialized = TableOfContentsSerializedMethod | TableOfContentsSerializedProperty;
export interface TableOfContentsItemProps {
serializedMembers: TableOfContentsSerialized[];
readonly serializedMembers: TableOfContentsSerialized[];
}
export function TableOfContentsPropertyItem({ property }: { property: TableOfContentsSerializedProperty }) {
export function TableOfContentsPropertyItem({ property }: { readonly property: TableOfContentsSerializedProperty }) {
return (
<a
className="ml-[10px] border-l border-light-800 p-[5px] pl-6.5 text-sm outline-none focus:border-0 dark:border-dark-100 focus:rounded active:bg-light-800 hover:bg-light-700 focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-100 dark:hover:bg-dark-200"
@@ -35,7 +35,7 @@ export function TableOfContentsPropertyItem({ property }: { property: TableOfCon
);
}
export function TableOfContentsMethodItem({ method }: { method: TableOfContentsSerializedMethod }) {
export function TableOfContentsMethodItem({ method }: { readonly method: TableOfContentsSerializedMethod }) {
if (method.overloadIndex && method.overloadIndex > 1) {
return null;
}

View File

@@ -10,7 +10,7 @@ const rowElements = {
Default: 'font-mono whitespace-pre break-normal',
};
export function TypeParamTable({ item }: { item: ApiTypeParameterListMixin }) {
export function TypeParamTable({ item }: { readonly item: ApiTypeParameterListMixin }) {
const model = item.getAssociatedModel()!;
const rows = useMemo(
() =>

View File

@@ -19,6 +19,7 @@ function generateIcon(kind: ApiItemKind) {
case ApiItemKind.Interface:
return <VscSymbolInterface />;
case ApiItemKind.TypeAlias:
case ApiItemKind.Variable:
return <VscSymbolVariable />;
default:
return <VscSymbolMethod />;
@@ -29,7 +30,7 @@ export function Header({
kind,
name,
sourceURL,
}: PropsWithChildren<{ kind: ApiItemKind; name: string; sourceURL?: string | undefined }>) {
}: PropsWithChildren<{ readonly kind: ApiItemKind; readonly name: string; readonly sourceURL?: string | undefined }>) {
return (
<div className="flex flex-col">
<h2 className="flex flex-row place-items-center justify-between gap-2 break-all text-2xl font-bold">

View File

@@ -2,7 +2,13 @@ import type { ApiClass, ApiInterface, Excerpt } from '@microsoft/api-extractor-m
import { ApiItemKind } from '@microsoft/api-extractor-model';
import { ExcerptText } from '../ExcerptText';
export function HierarchyText({ item, type }: { item: ApiClass | ApiInterface; type: 'Extends' | 'Implements' }) {
export function HierarchyText({
item,
type,
}: {
readonly item: ApiClass | ApiInterface;
readonly type: 'Extends' | 'Implements';
}) {
const model = item.getAssociatedModel()!;
if (

View File

@@ -3,7 +3,7 @@ import { MethodsSection } from './section/MethodsSection';
import { PropertiesSection } from './section/PropertiesSection';
import { hasProperties, hasMethods } from './util';
export function Members({ item }: { item: ApiDeclaredItem & ApiItemContainerMixin }) {
export function Members({ item }: { readonly item: ApiDeclaredItem & ApiItemContainerMixin }) {
return (
<>
{hasProperties(item) ? <PropertiesSection item={item} /> : null}

View File

@@ -4,7 +4,7 @@ import { Header } from './Header';
import { SummarySection } from './section/SummarySection';
export interface ObjectHeaderProps {
item: ApiDeclaredItem;
readonly item: ApiDeclaredItem;
}
export function ObjectHeader({ item }: ObjectHeaderProps) {

View File

@@ -6,7 +6,7 @@ import { parametersString } from '../util';
import { DocumentationSection } from './DocumentationSection';
import { CodeHeading } from '~/components/CodeHeading';
export function ConstructorSection({ item }: { item: ApiConstructor }) {
export function ConstructorSection({ item }: { readonly item: ApiConstructor }) {
return (
<DocumentationSection icon={<VscSymbolMethod size={20} />} padded title="Constructor">
<div className="flex flex-col gap-2">

View File

@@ -19,7 +19,7 @@ function isMethodLike(item: ApiItem): item is ApiMethod | ApiMethodSignature {
);
}
export function MethodsSection({ item }: { item: ApiItemContainerMixin }) {
export function MethodsSection({ item }: { readonly item: ApiItemContainerMixin }) {
const members = resolveMembers(item, isMethodLike);
const methodItems = useMemo(

View File

@@ -3,7 +3,7 @@ import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParamete
import { ParameterTable } from '../../ParameterTable';
import { DocumentationSection } from './DocumentationSection';
export function ParameterSection({ item }: { item: ApiDocumentedItem & ApiParameterListMixin }) {
export function ParameterSection({ item }: { readonly item: ApiDocumentedItem & ApiParameterListMixin }) {
return (
<DocumentationSection icon={<VscSymbolParameter size={20} />} padded title="Parameters">
<ParameterTable item={item} />

View File

@@ -3,7 +3,7 @@ import { VscSymbolProperty } from '@react-icons/all-files/vsc/VscSymbolProperty'
import { PropertyList } from '../../PropertyList';
import { DocumentationSection } from './DocumentationSection';
export function PropertiesSection({ item }: { item: ApiItemContainerMixin }) {
export function PropertiesSection({ item }: { readonly item: ApiItemContainerMixin }) {
return (
<DocumentationSection icon={<VscSymbolProperty size={20} />} padded title="Properties">
<PropertyList item={item} />

View File

@@ -3,7 +3,7 @@ import { VscListSelection } from '@react-icons/all-files/vsc/VscListSelection';
import { TSDoc } from '../tsdoc/TSDoc';
import { DocumentationSection } from './DocumentationSection';
export function SummarySection({ item }: { item: ApiDeclaredItem }) {
export function SummarySection({ item }: { readonly item: ApiDeclaredItem }) {
return (
<DocumentationSection icon={<VscListSelection size={20} />} padded separator title="Summary">
{item.tsdocComment?.summarySection ? (

View File

@@ -3,7 +3,7 @@ import { VscSymbolParameter } from '@react-icons/all-files/vsc/VscSymbolParamete
import { TypeParamTable } from '../../TypeParamTable';
import { DocumentationSection } from './DocumentationSection';
export function TypeParameterSection({ item }: { item: ApiTypeParameterListMixin }) {
export function TypeParameterSection({ item }: { readonly item: ApiTypeParameterListMixin }) {
return (
<DocumentationSection icon={<VscSymbolParameter size={20} />} padded title="Type Parameters">
<TypeParamTable item={item} />

View File

@@ -1,7 +1,7 @@
import { Alert } from '@discordjs/ui';
import type { PropsWithChildren } from 'react';
export function Block({ children, title }: PropsWithChildren<{ title: string }>) {
export function Block({ children, title }: PropsWithChildren<{ readonly title: string }>) {
return (
<div className="flex flex-col gap-2">
<h5 className="font-bold">{title}</h5>
@@ -13,7 +13,7 @@ export function Block({ children, title }: PropsWithChildren<{ title: string }>)
export function ExampleBlock({
children,
exampleIndex,
}: PropsWithChildren<{ exampleIndex?: number | undefined }>): JSX.Element {
}: PropsWithChildren<{ readonly exampleIndex?: number | undefined }>): JSX.Element {
return <Block title={`Example ${exampleIndex ? exampleIndex : ''}`}>{children}</Block>;
}

View File

@@ -8,7 +8,7 @@ import { SyntaxHighlighter } from '../../SyntaxHighlighter';
import { resolveItemURI } from '../util';
import { DefaultValueBlock, DeprecatedBlock, ExampleBlock, RemarksBlock, ReturnsBlock, SeeBlock } from './BlockComment';
export function TSDoc({ item, tsdoc }: { item: ApiItem; tsdoc: DocNode }): JSX.Element {
export function TSDoc({ item, tsdoc }: { readonly item: ApiItem; readonly tsdoc: DocNode }): JSX.Element {
const createNode = useCallback(
(tsdoc: DocNode, idx?: number): ReactNode => {
switch (tsdoc.kind) {
@@ -66,7 +66,7 @@ export function TSDoc({ item, tsdoc }: { item: ApiItem; tsdoc: DocNode }): JSX.E
case DocNodeKind.CodeSpan: {
const { code } = tsdoc as DocFencedCode;
return (
<code className="font-mono text-sm" key={idx}>
<code className="text-sm font-mono" key={idx}>
{code}
</code>
);

View File

@@ -10,7 +10,7 @@ import { ConstructorSection } from '../documentation/section/ConstructorSection'
import { TypeParameterSection } from '../documentation/section/TypeParametersSection';
// import { serializeMembers } from '../documentation/util';
export function Class({ clazz }: { clazz: ApiClass }) {
export function Class({ clazz }: { readonly clazz: ApiClass }) {
const constructor = clazz.members.find((member) => member.kind === ApiItemKind.Constructor) as
| ApiConstructor
| undefined;

View File

@@ -7,7 +7,7 @@ import { ObjectHeader } from '../documentation/ObjectHeader';
import { TypeParameterSection } from '../documentation/section/TypeParametersSection';
// import { serializeMembers } from '../documentation/util';
export function Interface({ item }: { item: ApiInterface }) {
export function Interface({ item }: { readonly item: ApiInterface }) {
return (
<Documentation>
<ObjectHeader item={item} />

View File

@@ -4,7 +4,7 @@ import { Documentation } from '../documentation/Documentation';
import { Header } from '../documentation/Header';
import { SummarySection } from '../documentation/section/SummarySection';
export function TypeAlias({ item }: { item: ApiTypeAlias }) {
export function TypeAlias({ item }: { readonly item: ApiTypeAlias }) {
return (
<Documentation>
<Header kind={item.kind} name={item.displayName} sourceURL={item.sourceLocation.fileUrl} />

View File

@@ -2,7 +2,7 @@ import type { ApiVariable } from '@microsoft/api-extractor-model';
import { Documentation } from '../documentation/Documentation';
import { ObjectHeader } from '../documentation/ObjectHeader';
export function Variable({ item }: { item: ApiVariable }) {
export function Variable({ item }: { readonly item: ApiVariable }) {
return (
<Documentation>
<ObjectHeader item={item} />

View File

@@ -6,7 +6,7 @@ import { ObjectHeader } from '../../documentation/ObjectHeader';
import { DocumentationSection } from '../../documentation/section/DocumentationSection';
import { EnumMember } from './EnumMember';
export function Enum({ item }: { item: ApiEnum }) {
export function Enum({ item }: { readonly item: ApiEnum }) {
return (
<Documentation>
<ObjectHeader item={item} />

View File

@@ -3,7 +3,7 @@ import { SignatureText } from '../../SignatureText';
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
import { CodeHeading } from '~/components/CodeHeading';
export function EnumMember({ member }: { member: ApiEnumMember }) {
export function EnumMember({ member }: { readonly member: ApiEnumMember }) {
return (
<div className="flex flex-col scroll-mt-30" id={member.displayName}>
<CodeHeading className="md:-ml-8.5" href={`#${member.displayName}`}>

View File

@@ -5,7 +5,7 @@ import { FunctionBody } from './FunctionBody';
const OverloadSwitcher = dynamic(async () => import('../../OverloadSwitcher'));
export function Function({ item }: { item: ApiFunction }) {
export function Function({ item }: { readonly item: ApiFunction }) {
const header = <Header kind={item.kind} name={item.name} sourceURL={item.sourceLocation.fileUrl} />;
if (item.getMergedSiblings().length > 1) {
@@ -16,7 +16,7 @@ export function Function({ item }: { item: ApiFunction }) {
return (
<div>
{header}
<OverloadSwitcher overloads={overloads} />
<OverloadSwitcher methodName={item.displayName} overloads={overloads} />
</div>
);
}

View File

@@ -10,7 +10,7 @@ export interface FunctionBodyProps {
overloadDocumentation: React.ReactNode[];
}
export function FunctionBody({ item }: { item: ApiFunction }) {
export function FunctionBody({ item }: { readonly item: ApiFunction }) {
return (
<Documentation>
{/* @ts-expect-error async component */}

View File

@@ -5,6 +5,7 @@ import type {
ApiMethodSignature,
} from '@microsoft/api-extractor-model';
import dynamic from 'next/dynamic';
import { Fragment } from 'react';
import { MethodDocumentation } from './MethodDocumentation';
import { MethodHeader } from './MethodHeader';
@@ -14,23 +15,20 @@ export function Method({
method,
inheritedFrom,
}: {
inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
method: ApiMethod | ApiMethodSignature;
readonly inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
readonly method: ApiMethod | ApiMethodSignature;
}) {
if (method.getMergedSiblings().length > 1) {
// We have overloads, use the overload switcher, but render
// each overload node on the server.
const overloads = method
.getMergedSiblings()
.map((sibling, idx) => (
<MethodDocumentation key={`${sibling.displayName}-${idx}`} method={sibling as ApiMethod | ApiMethodSignature} />
));
const overloads = method.getMergedSiblings().map((sibling, idx) => (
<Fragment key={`${sibling.displayName}-${idx}`}>
<MethodHeader method={sibling as ApiMethod | ApiMethodSignature} />
<MethodDocumentation method={sibling as ApiMethod | ApiMethodSignature} />
</Fragment>
));
return (
<OverloadSwitcher overloads={overloads}>
<MethodHeader method={method} />
</OverloadSwitcher>
);
return <OverloadSwitcher methodName={method.displayName} overloads={overloads} />;
}
// We have just a single method, render it on the server.

View File

@@ -9,8 +9,8 @@ import { ParameterTable } from '../../ParameterTable';
import { TSDoc } from '../../documentation/tsdoc/TSDoc';
export interface MethodDocumentationProps {
inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
method: ApiMethod | ApiMethodSignature;
readonly inheritedFrom?: (ApiDeclaredItem & ApiItemContainerMixin) | undefined;
readonly method: ApiMethod | ApiMethodSignature;
}
export function MethodDocumentation({ method, inheritedFrom }: MethodDocumentationProps) {

View File

@@ -5,7 +5,7 @@ import { CodeHeading } from '~/components/CodeHeading';
import { ExcerptText } from '~/components/ExcerptText';
import { parametersString } from '~/components/documentation/util';
export function MethodHeader({ method }: { method: ApiMethod | ApiMethodSignature }) {
export function MethodHeader({ method }: { readonly method: ApiMethod | ApiMethodSignature }) {
const key = useMemo(
() => `${method.displayName}${method.overloadIndex && method.overloadIndex > 1 ? `:${method.overloadIndex}` : ''}`,
[method.displayName, method.overloadIndex],

View File

@@ -7,7 +7,7 @@ export const buttonVariants = cva(
variant: {
primary: 'bg-blurple text-white border-0',
secondary:
'bg-white text-gray-800 border-gray-400 border border-light-900 text-black transition duration-200 active:translate-y-px dark:border-dark-100 hover:border-black active:bg-light-300 dark:bg-dark-400 hover:bg-light-200 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300',
'bg-white text-gray-800 border-gray-400 border border-light-900 text-black transition duration-200 active:translate-y-px dark:border-dark-100 hover:border-black active:bg-light-300 dark:bg-dark-400 hover:bg-light-200 dark:text-white focus:ring focus:ring-width-2 focus:ring-blurple dark:active:bg-dark-200 dark:hover:bg-dark-300 dark:hover:border-white',
},
},
defaultVariants: {

View File

@@ -46,20 +46,20 @@
},
"homepage": "https://discord.js.org",
"devDependencies": {
"@commitlint/cli": "^17.6.3",
"@commitlint/config-angular": "^17.6.3",
"@favware/cliff-jumper": "^2.0.0",
"@commitlint/cli": "^17.6.7",
"@commitlint/config-angular": "^17.6.7",
"@favware/cliff-jumper": "^2.1.1",
"@favware/npm-deprecate": "^1.0.7",
"conventional-changelog-cli": "^2.2.2",
"conventional-changelog-cli": "^3.0.0",
"husky": "^8.0.3",
"is-ci": "^3.0.1",
"lint-staged": "^13.2.2",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"unocss": "^0.51.12",
"vercel": "^29.1.1",
"vitest": "^0.31.0"
"lint-staged": "^13.2.3",
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"unocss": "^0.54.0",
"vercel": "^31.2.0",
"vitest": "^0.33.0"
},
"resolutions": {
"@microsoft/tsdoc-config@~0.16.1": "patch:@microsoft/tsdoc-config@npm%3A0.16.2#./.yarn/patches/@microsoft-tsdoc-config-npm-0.16.2-30fd115d09.patch",

View File

@@ -43,22 +43,22 @@
"dependencies": {
"@actions/core": "^1.10.0",
"@actions/glob": "^0.4.0",
"@planetscale/database": "^1.7.0",
"tslib": "^2.5.0",
"undici": "^5.22.0"
"@planetscale/database": "^1.10.0",
"tslib": "^2.6.1",
"undici": "^5.22.1"
},
"devDependencies": {
"@types/node": "16.18.26",
"@vitest/coverage-c8": "^0.31.0",
"@types/node": "16.18.39",
"@vitest/coverage-c8": "^0.33.0",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vitest": "^0.31.0"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=16.9.0"

View File

@@ -32,19 +32,19 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@microsoft/api-extractor-model": "7.26.8",
"@microsoft/api-extractor-model": "7.27.5",
"@microsoft/tsdoc": "0.14.2"
},
"devDependencies": {
"@types/node": "16.18.26",
"@types/node": "16.18.39",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6"
},
"engines": {
"node": ">=16.9.0"

View File

@@ -59,23 +59,23 @@
"homepage": "https://discord.js.org",
"dependencies": {
"@msgpack/msgpack": "^3.0.0-beta2",
"@vladfrangu/async_event_emitter": "^2.2.1",
"@vladfrangu/async_event_emitter": "^2.2.2",
"ioredis": "^5.3.2"
},
"devDependencies": {
"@favware/cliff-jumper": "^2.0.0",
"@microsoft/api-extractor": "^7.34.8",
"@types/node": "16.18.26",
"@vitest/coverage-c8": "^0.31.0",
"@favware/cliff-jumper": "^2.1.1",
"@microsoft/api-extractor": "^7.36.3",
"@types/node": "16.18.39",
"@vitest/coverage-c8": "^0.33.0",
"cross-env": "^7.0.3",
"eslint": "^8.40.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vitest": "^0.31.0"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=16.9.0"

View File

@@ -71,7 +71,7 @@ export abstract class BaseRedisBroker<TEvents extends Record<string, any>>
*/
public async subscribe(group: string, events: (keyof TEvents)[]): Promise<void> {
await Promise.all(
// eslint-disable-next-line consistent-return
// @ts-expect-error: Intended
events.map(async (event) => {
this.subscribedEvents.add(event as string);
try {

View File

@@ -58,28 +58,28 @@
"dependencies": {
"@discordjs/formatters": "workspace:^",
"@discordjs/util": "workspace:^",
"@sapphire/shapeshift": "^3.8.2",
"discord-api-types": "^0.37.41",
"@sapphire/shapeshift": "^3.9.2",
"discord-api-types": "^0.37.50",
"fast-deep-equal": "^3.1.3",
"ts-mixer": "^6.0.3",
"tslib": "^2.5.0"
"tslib": "^2.6.1"
},
"devDependencies": {
"@favware/cliff-jumper": "^2.0.0",
"@microsoft/api-extractor": "^7.34.8",
"@types/node": "16.18.26",
"@vitest/coverage-c8": "^0.31.0",
"@favware/cliff-jumper": "^2.1.1",
"@microsoft/api-extractor": "^7.36.3",
"@types/node": "16.18.39",
"@vitest/coverage-c8": "^0.33.0",
"cross-env": "^7.0.3",
"downlevel-dts": "^0.11.0",
"esbuild-plugin-version-injector": "^1.1.0",
"eslint": "^8.40.0",
"esbuild-plugin-version-injector": "^1.2.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vitest": "^0.31.0"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=16.9.0"

View File

@@ -54,7 +54,7 @@ export class SharedNameAndDescription {
}
/**
* SSets a name localization for this command.
* Sets a name localization for this command.
*
* @param locale - The locale to set
* @param localizedName - The localized name for the given `locale`

View File

@@ -52,7 +52,7 @@ export class SlashCommandIntegerOption
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
}
return { ...this };
return { ...this } as APIApplicationCommandIntegerOption;
}
}

View File

@@ -52,7 +52,7 @@ export class SlashCommandNumberOption
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
}
return { ...this };
return { ...this } as APIApplicationCommandNumberOption;
}
}

View File

@@ -63,7 +63,7 @@ export class SlashCommandStringOption extends ApplicationCommandOptionBase {
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
}
return { ...this };
return { ...this } as APIApplicationCommandStringOption;
}
}

View File

@@ -2,6 +2,22 @@
All notable changes to this project will be documented in this file.
# [@discordjs/collection@1.5.2](https://github.com/discordjs/discord.js/compare/@discordjs/collection@1.5.1...@discordjs/collection@1.5.2) - (2023-07-31)
## Refactor
- **collection:** Reduce `reduce`'s code (#9581) ([b85a3f2](https://github.com/discordjs/discord.js/commit/b85a3f2ddee8fc5974749b95fc07389a03093df2))
# [@discordjs/collection@1.5.1](https://github.com/discordjs/discord.js/compare/@discordjs/collection@1.5.0...@discordjs/collection@1.5.1) - (2023-05-01)
## Bug Fixes
- Fix external links (#9313) ([a7425c2](https://github.com/discordjs/discord.js/commit/a7425c29c4f23f1b31f4c6a463107ca9eb7fd7e2))
## Documentation
- Generate static imports for types with api-extractor ([98a76db](https://github.com/discordjs/discord.js/commit/98a76db482879f79d6bb2fb2e5fc65ac2c34e2d9))
# [@discordjs/collection@1.5.1](https://github.com/discordjs/discord.js/compare/@discordjs/collection@1.5.0...@discordjs/collection@1.5.1) - (2023-05-01)
## Bug Fixes

View File

@@ -700,12 +700,17 @@ describe('reduce() tests', () => {
test('reduce collection into a single value with initial value', () => {
const sum = coll.reduce((a, x) => a + x, 0);
expect(sum).toStrictEqual(6);
expect<number>(sum).toStrictEqual(6);
});
test('reduce collection into a single value without initial value', () => {
const sum = coll.reduce<number>((a, x) => a + x);
expect(sum).toStrictEqual(6);
const sum = coll.reduce((a, x) => a + x);
expect<number>(sum).toStrictEqual(6);
});
test('reduce empty collection with initial value', () => {
const coll = createCollection();
expect(coll.reduce((a, x) => a + x, 0)).toStrictEqual(0);
});
test('reduce empty collection without initial value', () => {

View File

@@ -1,6 +1,6 @@
{
"name": "@discordjs/collection",
"version": "1.5.1",
"version": "1.5.2",
"description": "Utility data structure used in discord.js",
"scripts": {
"test": "vitest run",
@@ -52,20 +52,20 @@
},
"homepage": "https://discord.js.org",
"devDependencies": {
"@favware/cliff-jumper": "^2.0.0",
"@microsoft/api-extractor": "^7.34.8",
"@types/node": "16.18.26",
"@vitest/coverage-c8": "^0.31.0",
"@favware/cliff-jumper": "^2.1.1",
"@microsoft/api-extractor": "^7.36.3",
"@types/node": "16.18.39",
"@vitest/coverage-c8": "^0.33.0",
"cross-env": "^7.0.3",
"esbuild-plugin-version-injector": "^1.1.0",
"eslint": "^8.40.0",
"esbuild-plugin-version-injector": "^1.2.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vitest": "^0.31.0"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=16.9.0"

View File

@@ -514,30 +514,20 @@ export class Collection<K, V> extends Map<K, V> {
* collection.reduce((acc, guild) => acc + guild.memberCount, 0);
* ```
*/
public reduce<T>(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T {
public reduce<T = V>(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T {
if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`);
let accumulator!: T;
if (initialValue !== undefined) {
const iterator = this.entries();
if (initialValue === undefined) {
if (this.size === 0) throw new TypeError('Reduce of empty collection with no initial value');
accumulator = iterator.next().value[1];
} else {
accumulator = initialValue;
for (const [key, val] of this) accumulator = fn(accumulator, val, key, this);
return accumulator;
}
let first = true;
for (const [key, val] of this) {
if (first) {
accumulator = val as unknown as T;
first = false;
continue;
}
accumulator = fn(accumulator, val, key, this);
}
// No items iterated.
if (first) {
throw new TypeError('Reduce of empty collection with no initial value');
for (const [key, value] of iterator) {
accumulator = fn(accumulator, value, key, this);
}
return accumulator;

View File

@@ -23,7 +23,7 @@
## Installation
**Node.js 18.12.0 or newer is required.**
**Node.js 16.9.0 or newer is required.**
```sh
npm install @discordjs/core
@@ -39,10 +39,10 @@ import { WebSocketManager } from '@discordjs/ws';
import { GatewayDispatchEvents, GatewayIntentBits, InteractionType, MessageFlags, Client } from '@discordjs/core';
// Create REST and WebSocket managers directly
const rest = new REST({ version: '10' }).setToken(token);
const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
const gateway = new WebSocketManager({
token,
token: process.env.DISCORD_TOKEN,
intents: GatewayIntentBits.GuildMessages | GatewayIntentBits.MessageContent,
rest,
});

View File

@@ -57,28 +57,28 @@
"@discordjs/rest": "workspace:^",
"@discordjs/util": "workspace:^",
"@discordjs/ws": "workspace:^",
"@sapphire/snowflake": "^3.4.2",
"@vladfrangu/async_event_emitter": "^2.2.1",
"discord-api-types": "^0.37.41"
"@sapphire/snowflake": "^3.5.1",
"@vladfrangu/async_event_emitter": "^2.2.2",
"discord-api-types": "^0.37.50"
},
"devDependencies": {
"@favware/cliff-jumper": "^2.0.0",
"@microsoft/api-extractor": "^7.34.8",
"@types/node": "18.16.5",
"@vitest/coverage-c8": "^0.31.0",
"@favware/cliff-jumper": "^2.1.1",
"@microsoft/api-extractor": "^7.36.3",
"@types/node": "18.17.1",
"@vitest/coverage-c8": "^0.33.0",
"cross-env": "^7.0.3",
"esbuild-plugin-version-injector": "^1.1.0",
"eslint": "^8.40.0",
"esbuild-plugin-version-injector": "^1.2.0",
"eslint": "^8.46.0",
"eslint-config-neon": "^0.1.47",
"eslint-formatter-pretty": "^5.0.0",
"prettier": "^2.8.8",
"tsup": "^6.7.0",
"turbo": "^1.9.4-canary.10",
"typescript": "^5.0.4",
"vitest": "^0.31.0"
"tsup": "^7.1.0",
"turbo": "^1.10.12",
"typescript": "^5.1.6",
"vitest": "^0.33.0"
},
"engines": {
"node": ">=18.12.0"
"node": ">=16.9.0"
},
"publishConfig": {
"access": "public"

View File

@@ -5,18 +5,26 @@ import {
Routes,
type RESTGetAPIApplicationCommandPermissionsResult,
type RESTGetAPIApplicationCommandResult,
type RESTGetAPIApplicationCommandsQuery,
type RESTGetAPIApplicationCommandsResult,
type RESTGetAPIApplicationGuildCommandResult,
type RESTGetAPIApplicationGuildCommandsQuery,
type RESTGetAPIApplicationGuildCommandsResult,
type RESTGetAPIGuildApplicationCommandsPermissionsResult,
type RESTPatchAPIApplicationCommandJSONBody,
type RESTPatchAPIApplicationCommandResult,
type RESTPatchAPIApplicationGuildCommandJSONBody,
type RESTPatchAPIApplicationGuildCommandResult,
type RESTPostAPIApplicationCommandsJSONBody,
type RESTPostAPIApplicationCommandsResult,
type RESTPostAPIApplicationGuildCommandsJSONBody,
type RESTPostAPIApplicationGuildCommandsResult,
type RESTPutAPIApplicationCommandPermissionsJSONBody,
type RESTPutAPIApplicationCommandPermissionsResult,
type RESTPutAPIApplicationCommandsJSONBody,
type RESTGetAPIApplicationCommandsQuery,
type RESTPutAPIApplicationCommandsResult,
type RESTGetAPIApplicationGuildCommandsQuery,
type RESTPutAPIApplicationGuildCommandsJSONBody,
type RESTPutAPIApplicationGuildCommandsResult,
type Snowflake,
} from 'discord-api-types/v10';
@@ -28,8 +36,8 @@ export class ApplicationCommandsAPI {
*
* @see {@link https://discord.com/developers/docs/interactions/application-commands#get-global-application-commands}
* @param applicationId - The application id to fetch commands for
* @param query - The query options to use when fetching commands
* @param options - The options to use when fetching commands
* @param query - The query options for fetching commands
* @param options - The options for fetching commands
*/
public async getGlobalCommands(
applicationId: Snowflake,
@@ -47,8 +55,8 @@ export class ApplicationCommandsAPI {
*
* @see {@link https://discord.com/developers/docs/interactions/application-commands#create-global-application-command}
* @param applicationId - The application id to create the command for
* @param body - The data to use when creating the command
* @param options - The options to use when creating the command
* @param body - The data for creating the command
* @param options - The options for creating the command
*/
public async createGlobalCommand(
applicationId: Snowflake,
@@ -67,7 +75,7 @@ export class ApplicationCommandsAPI {
* @see {@link https://discord.com/developers/docs/interactions/application-commands#get-global-application-command}
* @param applicationId - The application id to fetch the command from
* @param commandId - The command id to fetch
* @param options - The options to use when fetching the command
* @param options - The options for fetching the command
*/
public async getGlobalCommand(
applicationId: Snowflake,
@@ -85,7 +93,7 @@ export class ApplicationCommandsAPI {
* @see {@link https://discord.com/developers/docs/interactions/application-commands#edit-global-application-command}
* @param applicationId - The application id of the command
* @param commandId - The id of the command to edit
* @param body - The data to use when editing the command
* @param body - The data for editing the command
* @param options - The options for editing the command
*/
public async editGlobalCommand(
@@ -121,7 +129,7 @@ export class ApplicationCommandsAPI {
*
* @see {@link https://discord.com/developers/docs/interactions/application-commands#bulk-overwrite-global-application-commands}
* @param applicationId - The application id to overwrite commands for
* @param body - The data to use when overwriting commands
* @param body - The data for overwriting commands
* @param options - The options for overwriting commands
*/
public async bulkOverwriteGlobalCommands(
@@ -141,8 +149,8 @@ export class ApplicationCommandsAPI {
* @see {@link https://discord.com/developers/docs/interactions/application-commands#get-guild-application-commands}
* @param applicationId - The application id to fetch commands for
* @param guildId - The guild id to fetch commands for
* @param query - The data to use when fetching commands
* @param options - The options to use when fetching commands
* @param query - The data for fetching commands
* @param options - The options for fetching commands
*/
public async getGuildCommands(
applicationId: Snowflake,
@@ -153,7 +161,7 @@ export class ApplicationCommandsAPI {
return this.rest.get(Routes.applicationGuildCommands(applicationId, guildId), {
query: makeURLSearchParams(query),
signal,
}) as Promise<RESTGetAPIApplicationCommandsResult>;
}) as Promise<RESTGetAPIApplicationGuildCommandsResult>;
}
/**
@@ -162,19 +170,19 @@ export class ApplicationCommandsAPI {
* @see {@link https://discord.com/developers/docs/interactions/application-commands#create-guild-application-command}
* @param applicationId - The application id to create the command for
* @param guildId - The guild id to create the command for
* @param body - The data to use when creating the command
* @param options - The options to use when creating the command
* @param body - The data for creating the command
* @param options - The options for creating the command
*/
public async createGuildCommand(
applicationId: Snowflake,
guildId: Snowflake,
body: RESTPostAPIApplicationCommandsJSONBody,
body: RESTPostAPIApplicationGuildCommandsJSONBody,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.applicationGuildCommands(applicationId, guildId), {
body,
signal,
}) as Promise<RESTPostAPIApplicationCommandsResult>;
}) as Promise<RESTPostAPIApplicationGuildCommandsResult>;
}
/**
@@ -184,7 +192,7 @@ export class ApplicationCommandsAPI {
* @param applicationId - The application id to fetch the command from
* @param guildId - The guild id to fetch the command from
* @param commandId - The command id to fetch
* @param options - The options to use when fetching the command
* @param options - The options for fetching the command
*/
public async getGuildCommand(
applicationId: Snowflake,
@@ -194,7 +202,7 @@ export class ApplicationCommandsAPI {
) {
return this.rest.get(Routes.applicationGuildCommand(applicationId, guildId, commandId), {
signal,
}) as Promise<RESTGetAPIApplicationCommandResult>;
}) as Promise<RESTGetAPIApplicationGuildCommandResult>;
}
/**
@@ -204,20 +212,20 @@ export class ApplicationCommandsAPI {
* @param applicationId - The application id of the command
* @param guildId - The guild id of the command
* @param commandId - The command id to edit
* @param body - The data to use when editing the command
* @param options - The options to use when editing the command
* @param body - The data for editing the command
* @param options - The options for editing the command
*/
public async editGuildCommand(
applicationId: Snowflake,
guildId: Snowflake,
commandId: Snowflake,
body: RESTPatchAPIApplicationCommandJSONBody,
body: RESTPatchAPIApplicationGuildCommandJSONBody,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.patch(Routes.applicationGuildCommand(applicationId, guildId, commandId), {
body,
signal,
}) as Promise<RESTPatchAPIApplicationCommandResult>;
}) as Promise<RESTPatchAPIApplicationGuildCommandResult>;
}
/**
@@ -244,19 +252,19 @@ export class ApplicationCommandsAPI {
* @see {@link https://discord.com/developers/docs/interactions/application-commands#bulk-overwrite-guild-application-commands}
* @param applicationId - The application id to overwrite commands for
* @param guildId - The guild id to overwrite commands for
* @param body - The data to use when overwriting commands
* @param options - The options to use when overwriting the commands
* @param body - The data for overwriting commands
* @param options - The options for overwriting the commands
*/
public async bulkOverwriteGuildCommands(
applicationId: Snowflake,
guildId: Snowflake,
body: RESTPutAPIApplicationCommandsJSONBody,
body: RESTPutAPIApplicationGuildCommandsJSONBody,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.put(Routes.applicationGuildCommands(applicationId, guildId), {
body,
signal,
}) as Promise<RESTPutAPIApplicationCommandsResult>;
}) as Promise<RESTPutAPIApplicationGuildCommandsResult>;
}
/**
@@ -305,8 +313,8 @@ export class ApplicationCommandsAPI {
* @param applicationId - The application id to edit the permissions for
* @param guildId - The guild id to edit the permissions for
* @param commandId - The id of the command to edit the permissions for
* @param body - The data to use when editing the permissions
* @param options - The options to use when editing the permissions
* @param body - The data for editing the permissions
* @param options - The options for editing the permissions
*/
public async editGuildCommandPermissions(
userToken: string,

View File

@@ -3,6 +3,8 @@
import { makeURLSearchParams, type RawFile, type REST, type RequestData } from '@discordjs/rest';
import {
Routes,
type RESTPostAPIChannelWebhookJSONBody,
type RESTPostAPIChannelWebhookResult,
type RESTDeleteAPIChannelResult,
type RESTGetAPIChannelInvitesResult,
type RESTGetAPIChannelMessageReactionUsersQuery,
@@ -25,9 +27,18 @@ import {
type RESTPostAPIChannelMessageCrosspostResult,
type RESTPostAPIChannelMessageJSONBody,
type RESTPostAPIChannelMessageResult,
type RESTPutAPIChannelPermissionJSONBody,
type Snowflake,
type RESTPostAPIChannelThreadsJSONBody,
type RESTPostAPIChannelThreadsResult,
type APIThreadChannel,
type RESTPostAPIGuildForumThreadsJSONBody,
} from 'discord-api-types/v10';
export interface StartForumThreadOptions extends RESTPostAPIGuildForumThreadsJSONBody {
message: RESTPostAPIGuildForumThreadsJSONBody['message'] & { files?: RawFile[] };
}
export class ChannelsAPI {
public constructor(private readonly rest: REST) {}
@@ -36,8 +47,8 @@ export class ChannelsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#create-message}
* @param channelId - The id of the channel to send the message in
* @param body - The data to use when sending the message
* @param options - The options to use when sending the message
* @param body - The data for sending the message
* @param options - The options for sending the message
*/
public async createMessage(
channelId: Snowflake,
@@ -57,8 +68,8 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/channel#edit-message}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to edit
* @param body - The data to use when editing the message
* @param options - The options to use when editing the message
* @param body - The data for editing the message
* @param options - The options for editing the message
*/
public async editMessage(
channelId: Snowflake,
@@ -80,7 +91,7 @@ export class ChannelsAPI {
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to get the reactions for
* @param emoji - The emoji to get the reactions for
* @param query - The query options to use when fetching the reactions
* @param query - The query options for fetching the reactions
* @param options - The options for fetching the message reactions
*/
public async getMessageReactions(
@@ -233,7 +244,7 @@ export class ChannelsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#get-channel-messages}
* @param channelId - The id of the channel to fetch messages from
* @param query - The query options to use when fetching messages
* @param query - The query options for fetching messages
* @param options - The options for fetching the messages
*/
public async getMessages(
@@ -389,7 +400,7 @@ export class ChannelsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#create-channel-invite}
* @param channelId - The id of the channel to create an invite for
* @param body - The data to use when creating the invite
* @param body - The data for creating the invite
* @param options - The options for creating the invite
*/
public async createInvite(
@@ -415,6 +426,51 @@ export class ChannelsAPI {
return this.rest.get(Routes.channelInvites(channelId), { signal }) as Promise<RESTGetAPIChannelInvitesResult>;
}
/**
* Creates a new thread
*
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-from-message}
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-without-message}
* @param channelId - The id of the channel to start the thread in
* @param body - The data for starting the thread
* @param messageId - The id of the message to start the thread from
* @param options - The options for starting the thread
*/
public async createThread(
channelId: Snowflake,
body: RESTPostAPIChannelThreadsJSONBody,
messageId?: Snowflake,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.threads(channelId, messageId), {
body,
signal,
}) as Promise<RESTPostAPIChannelThreadsResult>;
}
/**
* Creates a new forum post
*
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-in-forum-channel}
* @param channelId - The id of the forum channel to start the thread in
* @param body - The data for starting the thread
* @param options - The options for starting the thread
*/
public async createForumThread(
channelId: Snowflake,
{ message, ...optionsBody }: StartForumThreadOptions,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
const { files, ...messageBody } = message;
const body = {
...optionsBody,
message: messageBody,
};
return this.rest.post(Routes.threads(channelId), { files, body, signal }) as Promise<APIThreadChannel>;
}
/**
* Fetches the archived threads of a channel
*
@@ -422,7 +478,7 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/channel#list-private-archived-threads}
* @param channelId - The id of the channel to fetch archived threads from
* @param archivedStatus - The archived status of the threads to fetch
* @param query - The options to use when fetching archived threads
* @param query - The options for fetching archived threads
* @param options - The options for fetching archived threads
*/
public async getArchivedThreads(
@@ -442,7 +498,7 @@ export class ChannelsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#list-joined-private-archived-threads}
* @param channelId - The id of the channel to fetch joined archived threads from
* @param query - The options to use when fetching joined archived threads
* @param query - The options for fetching joined archived threads
* @param options - The options for fetching joined archived threads
*/
public async getJoinedPrivateArchivedThreads(
@@ -456,13 +512,74 @@ export class ChannelsAPI {
}) as Promise<RESTGetAPIChannelUsersThreadsArchivedResult>;
}
/**
* Creates a new webhook
*
* @see {@link https://discord.com/developers/docs/resources/webhook#create-webhook}
* @param channelId - The id of the channel to create the webhook in
* @param body - The data for creating the webhook
* @param options - The options for creating the webhook
*/
public async createWebhook(
channelId: Snowflake,
body: RESTPostAPIChannelWebhookJSONBody,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.post(Routes.channelWebhooks(channelId), {
reason,
body,
signal,
}) as Promise<RESTPostAPIChannelWebhookResult>;
}
/**
* Fetches the webhooks of a channel
*
* @see {@link https://discord.com/developers/docs/resources/webhook#get-channel-webhooks}
* @param id - The id of the channel
* @param channelId - The id of the channel
*/
public async getWebhooks(id: Snowflake) {
return this.rest.get(Routes.channelWebhooks(id)) as Promise<RESTGetAPIChannelWebhooksResult>;
public async getWebhooks(channelId: Snowflake) {
return this.rest.get(Routes.channelWebhooks(channelId)) as Promise<RESTGetAPIChannelWebhooksResult>;
}
/**
* Edits the permission overwrite for a user or role in a channel
*
* @see {@link https://discord.com/developers/docs/resources/channel#edit-channel-permissions}
* @param channelId - The id of the channel to edit the permission overwrite in
* @param overwriteId - The id of the user or role to edit the permission overwrite for
* @param body - The data for editing the permission overwrite
* @param options - The options for editing the permission overwrite
*/
public async editPermissionOverwrite(
channelId: Snowflake,
overwriteId: Snowflake,
body: RESTPutAPIChannelPermissionJSONBody,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
await this.rest.put(Routes.channelPermission(channelId, overwriteId), {
reason,
body,
signal,
});
}
/**
* Deletes the permission overwrite for a user or role in a channel
*
* @see {@link https://discord.com/developers/docs/resources/channel#delete-channel-permission}
* @param channelId - The id of the channel to delete the permission overwrite in
* @param overwriteId - The id of the user or role to delete the permission overwrite for
* @param options - The options for deleting the permission overwrite
*/
public async deletePermissionOverwrite(
channelId: Snowflake,
overwriteId: Snowflake,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
await this.rest.delete(Routes.channelPermission(channelId, overwriteId), {
reason,
signal,
});
}
}

View File

@@ -1,93 +1,99 @@
/* eslint-disable jsdoc/check-param-names */
import { makeURLSearchParams, type REST, type RawFile, type RequestData } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v10';
import type {
RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
RESTPatchAPIGuildVoiceStateCurrentMemberResult,
GuildMFALevel,
GuildWidgetStyle,
RESTGetAPIAuditLogQuery,
RESTGetAPIAuditLogResult,
RESTGetAPIAutoModerationRuleResult,
RESTGetAPIAutoModerationRulesResult,
RESTGetAPIGuildBansResult,
RESTGetAPIGuildChannelsResult,
RESTGetAPIGuildEmojiResult,
RESTGetAPIGuildEmojisResult,
RESTGetAPIGuildIntegrationsResult,
RESTGetAPIGuildInvitesResult,
RESTGetAPIGuildMemberResult,
RESTGetAPIGuildMembersResult,
RESTGetAPIGuildMembersQuery,
RESTGetAPIGuildMembersSearchResult,
RESTGetAPIGuildPreviewResult,
RESTGetAPIGuildPruneCountResult,
RESTGetAPIGuildResult,
RESTGetAPIGuildRolesResult,
RESTGetAPIGuildScheduledEventQuery,
RESTGetAPIGuildScheduledEventResult,
RESTGetAPIGuildScheduledEventsQuery,
RESTGetAPIGuildScheduledEventsResult,
RESTGetAPIGuildScheduledEventUsersQuery,
RESTGetAPIGuildScheduledEventUsersResult,
RESTGetAPIGuildStickerResult,
RESTGetAPIGuildStickersResult,
RESTGetAPIGuildTemplatesResult,
RESTGetAPIGuildThreadsResult,
RESTGetAPIGuildVanityUrlResult,
RESTGetAPIGuildVoiceRegionsResult,
RESTGetAPIGuildPruneCountQuery,
RESTPostAPIGuildStickerFormDataBody,
RESTPostAPIGuildStickerResult,
RESTGetAPIGuildMembersSearchQuery,
RESTGetAPIGuildWebhooksResult,
RESTGetAPIGuildWelcomeScreenResult,
RESTGetAPIGuildWidgetImageResult,
RESTGetAPIGuildWidgetJSONResult,
RESTGetAPITemplateResult,
RESTPatchAPIAutoModerationRuleJSONBody,
RESTPatchAPIGuildChannelPositionsJSONBody,
RESTPatchAPIGuildEmojiJSONBody,
RESTPatchAPIGuildEmojiResult,
RESTPatchAPIGuildJSONBody,
RESTPatchAPIGuildMemberJSONBody,
RESTPatchAPIGuildMemberResult,
RESTPatchAPIGuildResult,
RESTPatchAPIGuildRoleJSONBody,
RESTPatchAPIGuildRolePositionsJSONBody,
RESTPatchAPIGuildRolePositionsResult,
RESTPatchAPIGuildRoleResult,
RESTPatchAPIGuildScheduledEventJSONBody,
RESTPatchAPIGuildScheduledEventResult,
RESTPatchAPIGuildStickerJSONBody,
RESTPatchAPIGuildStickerResult,
RESTPatchAPIGuildTemplateJSONBody,
RESTPatchAPIGuildTemplateResult,
RESTPatchAPIGuildVoiceStateUserJSONBody,
RESTPatchAPIGuildWelcomeScreenJSONBody,
RESTPatchAPIGuildWelcomeScreenResult,
RESTPatchAPIGuildWidgetSettingsJSONBody,
RESTPatchAPIGuildWidgetSettingsResult,
RESTPostAPIAutoModerationRuleJSONBody,
RESTPostAPIAutoModerationRuleResult,
RESTPostAPIGuildChannelJSONBody,
RESTPostAPIGuildChannelResult,
RESTPostAPIGuildEmojiJSONBody,
RESTPostAPIGuildEmojiResult,
RESTPostAPIGuildPruneJSONBody,
RESTPostAPIGuildRoleJSONBody,
RESTPostAPIGuildRoleResult,
RESTPostAPIGuildScheduledEventJSONBody,
RESTPostAPIGuildScheduledEventResult,
RESTPostAPIGuildsJSONBody,
RESTPostAPIGuildsMFAResult,
RESTPostAPIGuildsResult,
RESTPostAPIGuildTemplatesResult,
RESTPostAPITemplateCreateGuildJSONBody,
RESTPutAPIGuildBanJSONBody,
RESTPutAPIGuildTemplateSyncResult,
Snowflake,
import {
Routes,
type GuildMFALevel,
type GuildWidgetStyle,
type RESTGetAPIAuditLogQuery,
type RESTGetAPIAuditLogResult,
type RESTGetAPIAutoModerationRuleResult,
type RESTGetAPIAutoModerationRulesResult,
type RESTGetAPIGuildBanResult,
type RESTGetAPIGuildBansQuery,
type RESTGetAPIGuildBansResult,
type RESTGetAPIGuildChannelsResult,
type RESTGetAPIGuildEmojiResult,
type RESTGetAPIGuildEmojisResult,
type RESTGetAPIGuildIntegrationsResult,
type RESTGetAPIGuildInvitesResult,
type RESTGetAPIGuildMemberResult,
type RESTGetAPIGuildMembersQuery,
type RESTGetAPIGuildMembersResult,
type RESTGetAPIGuildMembersSearchQuery,
type RESTGetAPIGuildMembersSearchResult,
type RESTGetAPIGuildOnboardingResult,
type RESTGetAPIGuildPreviewResult,
type RESTGetAPIGuildPruneCountQuery,
type RESTGetAPIGuildPruneCountResult,
type RESTGetAPIGuildResult,
type RESTGetAPIGuildRolesResult,
type RESTGetAPIGuildScheduledEventQuery,
type RESTGetAPIGuildScheduledEventResult,
type RESTGetAPIGuildScheduledEventUsersQuery,
type RESTGetAPIGuildScheduledEventUsersResult,
type RESTGetAPIGuildScheduledEventsQuery,
type RESTGetAPIGuildScheduledEventsResult,
type RESTGetAPIGuildStickerResult,
type RESTGetAPIGuildStickersResult,
type RESTGetAPIGuildTemplatesResult,
type RESTGetAPIGuildThreadsResult,
type RESTGetAPIGuildVanityUrlResult,
type RESTGetAPIGuildVoiceRegionsResult,
type RESTGetAPIGuildWebhooksResult,
type RESTGetAPIGuildWelcomeScreenResult,
type RESTGetAPIGuildWidgetImageResult,
type RESTGetAPIGuildWidgetJSONResult,
type RESTGetAPIGuildWidgetSettingsResult,
type RESTGetAPITemplateResult,
type RESTPatchAPIAutoModerationRuleJSONBody,
type RESTPatchAPIAutoModerationRuleResult,
type RESTPatchAPIGuildChannelPositionsJSONBody,
type RESTPatchAPIGuildEmojiJSONBody,
type RESTPatchAPIGuildEmojiResult,
type RESTPatchAPIGuildJSONBody,
type RESTPatchAPIGuildMemberJSONBody,
type RESTPatchAPIGuildMemberResult,
type RESTPatchAPIGuildResult,
type RESTPatchAPIGuildRoleJSONBody,
type RESTPatchAPIGuildRolePositionsJSONBody,
type RESTPatchAPIGuildRolePositionsResult,
type RESTPatchAPIGuildRoleResult,
type RESTPatchAPIGuildScheduledEventJSONBody,
type RESTPatchAPIGuildScheduledEventResult,
type RESTPatchAPIGuildStickerJSONBody,
type RESTPatchAPIGuildStickerResult,
type RESTPatchAPIGuildTemplateJSONBody,
type RESTPatchAPIGuildTemplateResult,
type RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody,
type RESTPatchAPIGuildVoiceStateCurrentMemberResult,
type RESTPatchAPIGuildVoiceStateUserJSONBody,
type RESTPatchAPIGuildWelcomeScreenJSONBody,
type RESTPatchAPIGuildWelcomeScreenResult,
type RESTPatchAPIGuildWidgetSettingsJSONBody,
type RESTPatchAPIGuildWidgetSettingsResult,
type RESTPostAPIAutoModerationRuleJSONBody,
type RESTPostAPIAutoModerationRuleResult,
type RESTPostAPIGuildChannelJSONBody,
type RESTPostAPIGuildChannelResult,
type RESTPostAPIGuildEmojiJSONBody,
type RESTPostAPIGuildEmojiResult,
type RESTPostAPIGuildPruneJSONBody,
type RESTPostAPIGuildPruneResult,
type RESTPostAPIGuildRoleJSONBody,
type RESTPostAPIGuildRoleResult,
type RESTPostAPIGuildScheduledEventJSONBody,
type RESTPostAPIGuildScheduledEventResult,
type RESTPostAPIGuildStickerFormDataBody,
type RESTPostAPIGuildStickerResult,
type RESTPostAPIGuildTemplatesJSONBody,
type RESTPostAPIGuildTemplatesResult,
type RESTPostAPIGuildsJSONBody,
type RESTPostAPIGuildsMFAResult,
type RESTPostAPIGuildsResult,
type RESTPutAPIGuildBanJSONBody,
type RESTPutAPIGuildTemplateSyncResult,
type Snowflake,
} from 'discord-api-types/v10';
export class GuildsAPI {
@@ -100,7 +106,7 @@ export class GuildsAPI {
* @param guildId - The id of the guild
* @param options - The options for fetching the guild
*/
public async get(guildId: string, { signal }: Pick<RequestData, 'signal'> = {}) {
public async get(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guild(guildId), { signal }) as Promise<RESTGetAPIGuildResult>;
}
@@ -164,7 +170,7 @@ export class GuildsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/guild#list-guild-members}
* @param guildId - The id of the guild
* @param query - The query to use when fetching the guild members
* @param query - The query for fetching the guild members
* @param options - The options for fetching the guild members
*/
public async getMembers(
@@ -241,12 +247,32 @@ export class GuildsAPI {
/**
* Fetches a guild member ban
*
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-bans}
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-ban}
* @param guildId - The id of the guild to fetch the ban from
* @param options - The options for fetching the guild member ban
* @param userId - The id of the user to fetch the ban
* @param options - The options for fetching the ban
*/
public async getMemberBans(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guildBans(guildId), { signal }) as Promise<RESTGetAPIGuildBansResult>;
public async getMemberBan(guildId: Snowflake, userId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guildBan(guildId, userId), { signal }) as Promise<RESTGetAPIGuildBanResult>;
}
/**
* Fetches guild member bans
*
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-bans}
* @param guildId - The id of the guild to fetch the bans from
* @param query - The query options for fetching the bans
* @param options - The options for fetching the bans
*/
public async getMemberBans(
guildId: Snowflake,
query: RESTGetAPIGuildBansQuery = {},
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.get(Routes.guildBans(guildId), {
query: makeURLSearchParams(query),
signal,
}) as Promise<RESTGetAPIGuildBansResult>;
}
/**
@@ -384,7 +410,7 @@ export class GuildsAPI {
return this.rest.post(Routes.guildMFA(guildId), {
reason,
signal,
body: { mfa_level: level },
body: { level },
}) as Promise<RESTPostAPIGuildsMFAResult>;
}
@@ -424,7 +450,7 @@ export class GuildsAPI {
body,
reason,
signal,
}) as Promise<RESTGetAPIGuildPruneCountResult>;
}) as Promise<RESTPostAPIGuildPruneResult>;
}
/**
@@ -484,7 +510,9 @@ export class GuildsAPI {
* @param options - The options for fetching the widget settings
*/
public async getWidgetSettings(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guildWidgetSettings(guildId), { signal }) as Promise<RESTGetAPIGuildWidgetImageResult>;
return this.rest.get(Routes.guildWidgetSettings(guildId), {
signal,
}) as Promise<RESTGetAPIGuildWidgetSettingsResult>;
}
/**
@@ -1029,7 +1057,7 @@ export class GuildsAPI {
reason,
body,
signal,
}) as Promise<RESTPatchAPIAutoModerationRuleJSONBody>;
}) as Promise<RESTPatchAPIAutoModerationRuleResult>;
}
/**
@@ -1085,7 +1113,7 @@ export class GuildsAPI {
* @see {@link https://discord.com/developers/docs/resources/guild#modify-guild-member}
* @param guildId - The id of the guild
* @param userId - The id of the user
* @param body - The data to use when editing the guild member
* @param body - The data for editing the guild member
* @param options - The options for editing the guild member
*/
public async editMember(
@@ -1101,6 +1129,22 @@ export class GuildsAPI {
}) as Promise<RESTPatchAPIGuildMemberResult>;
}
/**
* Removes a member from a guild
*
* @see {@link https://discord.com/developers/docs/resources/guild#remove-guild-member}
* @param guildId - The id of the guild
* @param userId - The id of the user
* @param options - The options for removing the guild member
*/
public async removeMember(
guildId: Snowflake,
userId: Snowflake,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.delete(Routes.guildMember(guildId, userId), { reason, signal });
}
/**
* Adds a role to a guild member
*
@@ -1153,12 +1197,12 @@ export class GuildsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/guild-template#create-guild-template}
* @param templateCode - The code of the template
* @param body - The data to use when creating the template
* @param body - The data for creating the template
* @param options - The options for creating the template
*/
public async createTemplate(
templateCode: string,
body: RESTPostAPITemplateCreateGuildJSONBody,
body: RESTPostAPIGuildTemplatesJSONBody,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.template(templateCode), { body, signal }) as Promise<RESTPostAPIGuildTemplatesResult>;
@@ -1179,11 +1223,22 @@ export class GuildsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state}
* @param guildId - The id of the guild
* @param body - The options to use when setting the voice state
* @param body - The options for setting the voice state
*/
public async setVoiceState(guildId: Snowflake, body: RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody = {}) {
return this.rest.patch(Routes.guildVoiceState(guildId, '@me'), {
body,
}) as Promise<RESTPatchAPIGuildVoiceStateCurrentMemberResult>;
}
/**
* Fetches a guild onboarding
*
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-onboarding}
* @param guildId - The id of the guild
* @param options - The options for fetching the guild onboarding
*/
public async getOnboarding(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.guildOnboarding(guildId), { signal }) as Promise<RESTGetAPIGuildOnboardingResult>;
}
}

View File

@@ -6,6 +6,7 @@ import { InteractionsAPI } from './interactions.js';
import { InvitesAPI } from './invite.js';
import { OAuth2API } from './oauth2.js';
import { RoleConnectionsAPI } from './roleConnections.js';
import { StageInstancesAPI } from './stageInstances.js';
import { StickersAPI } from './sticker.js';
import { ThreadsAPI } from './thread.js';
import { UsersAPI } from './user.js';
@@ -19,6 +20,7 @@ export * from './interactions.js';
export * from './invite.js';
export * from './oauth2.js';
export * from './roleConnections.js';
export * from './stageInstances.js';
export * from './sticker.js';
export * from './thread.js';
export * from './user.js';
@@ -40,6 +42,8 @@ export class API {
public readonly roleConnections: RoleConnectionsAPI;
public readonly stageInstances: StageInstancesAPI;
public readonly stickers: StickersAPI;
public readonly threads: ThreadsAPI;
@@ -57,6 +61,7 @@ export class API {
this.invites = new InvitesAPI(rest);
this.roleConnections = new RoleConnectionsAPI(rest);
this.oauth2 = new OAuth2API(rest);
this.stageInstances = new StageInstancesAPI(rest);
this.stickers = new StickersAPI(rest);
this.threads = new ThreadsAPI(rest);
this.users = new UsersAPI(rest);

View File

@@ -21,8 +21,8 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data to use when replying
* @param options - The options to use when replying
* @param body - The callback data for replying
* @param options - The options for replying
*/
public async reply(
interactionId: Snowflake,
@@ -47,8 +47,8 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param data - The data to use when deferring the reply
* @param options - The options to use when deferring
* @param data - The data for deferring the reply
* @param options - The options for deferring
*/
public async defer(
interactionId: Snowflake,
@@ -72,7 +72,7 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param options - The options to use when deferring
* @param options - The options for deferring
*/
public async deferMessageUpdate(
interactionId: Snowflake,
@@ -94,8 +94,8 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-followup-message}
* @param applicationId - The application id of the interaction
* @param interactionToken - The token of the interaction
* @param body - The callback data to use when replying
* @param options - The options to use when replying
* @param body - The callback data for replying
* @param options - The options for replying
*/
public async followUp(
applicationId: Snowflake,
@@ -103,7 +103,7 @@ export class InteractionsAPI {
body: APIInteractionResponseCallbackData & { files?: RawFile[] },
{ signal }: Pick<RequestData, 'signal'> = {},
) {
await this.webhooks.execute(applicationId, interactionToken, body, { signal });
return this.webhooks.execute(applicationId, interactionToken, { ...body, wait: true }, { signal });
}
/**
@@ -113,9 +113,9 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#edit-followup-message}
* @param applicationId - The application id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The callback data to use when editing the reply
* @param callbackData - The callback data for editing the reply
* @param messageId - The id of the message to edit. If omitted, the original reply will be edited
* @param options - The options to use when editing the reply
* @param options - The options for editing the reply
*/
public async editReply(
applicationId: Snowflake,
@@ -135,7 +135,7 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#get-original-interaction-response}
* @param applicationId - The application id of the interaction
* @param interactionToken - The token of the interaction
* @param options - The options to use when fetching the reply
* @param options - The options for fetching the reply
*/
public async getOriginalReply(
applicationId: Snowflake,
@@ -159,7 +159,7 @@ export class InteractionsAPI {
* @param applicationId - The application id of the interaction
* @param interactionToken - The token of the interaction
* @param messageId - The id of the message to delete. If omitted, the original reply will be deleted
* @param options - The options to use when deleting the reply
* @param options - The options for deleting the reply
*/
public async deleteReply(
applicationId: Snowflake,
@@ -176,8 +176,8 @@ export class InteractionsAPI {
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#create-interaction-response}
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The callback data to use when updating the interaction
* @param options - The options to use when updating the interaction
* @param callbackData - The callback data for updating the interaction
* @param options - The options for updating the interaction
*/
public async updateMessage(
interactionId: Snowflake,
@@ -203,7 +203,7 @@ export class InteractionsAPI {
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The callback data for the autocomplete response
* @param options - The options to use when sending the autocomplete response
* @param options - The options for sending the autocomplete response
*/
public async createAutocompleteResponse(
interactionId: Snowflake,
@@ -228,7 +228,7 @@ export class InteractionsAPI {
* @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction
* @param callbackData - The modal callback data to send
* @param options - The options to use when sending the modal
* @param options - The options for sending the modal
*/
public async createModal(
interactionId: Snowflake,

View File

@@ -11,8 +11,8 @@ export class InvitesAPI {
*
* @see {@link https://discord.com/developers/docs/resources/invite#get-invite}
* @param code - The invite code
* @param query - The options to use when fetching the invite
* @param options - The options to use when fetching the invite
* @param query - The options for fetching the invite
* @param options - The options for fetching the invite
*/
public async get(code: string, query: RESTGetAPIInviteQuery = {}, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.invite(code), {
@@ -26,7 +26,7 @@ export class InvitesAPI {
*
* @see {@link https://discord.com/developers/docs/resources/invite#delete-invite}
* @param code - The invite code
* @param options - The options to use when deleting the invite
* @param options - The options for deleting the invite
*/
public async delete(code: string, { reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {}) {
await this.rest.delete(Routes.invite(code), { reason, signal });

View File

@@ -17,7 +17,7 @@ export class RoleConnectionsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/application-role-connection-metadata#get-application-role-connection-metadata-records}
* @param applicationId - The id of the application to get role connection metadata records for
* @param options - The options to use when fetching the role connection metadata records
* @param options - The options for fetching the role connection metadata records
*/
public async getMetadataRecords(applicationId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.applicationRoleConnectionMetadata(applicationId), {
@@ -31,7 +31,7 @@ export class RoleConnectionsAPI {
* @see {@link https://discord.com/developers/docs/resources/application-role-connection-metadata#update-application-role-connection-metadata-records}
* @param applicationId - The id of the application to update role connection metadata records for
* @param body - The new role connection metadata records
* @param options - The options to use when updating the role connection metadata records
* @param options - The options for updating the role connection metadata records
*/
public async updateMetadataRecords(
applicationId: Snowflake,

View File

@@ -0,0 +1,76 @@
/* eslint-disable jsdoc/check-param-names */
import type { RequestData, REST } from '@discordjs/rest';
import {
type Snowflake,
type RESTGetAPIStageInstanceResult,
type RESTPatchAPIStageInstanceJSONBody,
type RESTPatchAPIStageInstanceResult,
type RESTPostAPIStageInstanceJSONBody,
type RESTPostAPIStageInstanceResult,
Routes,
} from 'discord-api-types/v10';
export class StageInstancesAPI {
public constructor(private readonly rest: REST) {}
/**
* Creates a new stage instance
*
* @see {@link https://discord.com/developers/docs/resources/stage-instance#get-stage-instance}
* @param body - The data for creating the new stage instance
* @param options - The options for creating the new stage instance
*/
public async create(
body: RESTPostAPIStageInstanceJSONBody,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.post(Routes.stageInstances(), {
body,
reason,
signal,
}) as Promise<RESTPostAPIStageInstanceResult>;
}
/**
* Fetches a stage instance
*
* @see {@link https://discord.com/developers/docs/resources/stage-instance#get-stage-instance}
* @param channelId - The id of the channel
* @param options - The options for fetching the stage instance
*/
public async get(channelId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.stageInstance(channelId), { signal }) as Promise<RESTGetAPIStageInstanceResult>;
}
/**
* Edits a stage instance
*
* @see {@link https://discord.com/developers/docs/resources/stage-instance#modify-stage-instance}
* @param channelId - The id of the channel
* @param body - The new stage instance data
* @param options - The options for editing the stage instance
*/
public async edit(
channelId: Snowflake,
body: RESTPatchAPIStageInstanceJSONBody,
{ reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.patch(Routes.stageInstance(channelId), {
body,
reason,
signal,
}) as Promise<RESTPatchAPIStageInstanceResult>;
}
/**
* Deletes a stage instance
*
* @see {@link https://discord.com/developers/docs/resources/stage-instance#delete-stage-instance}
* @param channelId - The id of the channel
* @param options - The options for deleting the stage instance
*/
public async delete(channelId: Snowflake, { reason, signal }: Pick<RequestData, 'reason' | 'signal'> = {}) {
await this.rest.delete(Routes.stageInstance(channelId), { reason, signal });
}
}

View File

@@ -15,7 +15,7 @@ export class StickersAPI {
* Fetches all of the nitro sticker packs
*
* @see {@link https://discord.com/developers/docs/resources/sticker#list-nitro-sticker-packs}
* @param options - The options to use when fetching the sticker packs
* @param options - The options for fetching the sticker packs
*/
public async getNitroStickers({ signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.nitroStickerPacks(), { signal }) as Promise<RESTGetNitroStickerPacksResult>;
@@ -26,7 +26,7 @@ export class StickersAPI {
*
* @see {@link https://discord.com/developers/docs/resources/sticker#get-sticker}
* @param stickerId - The id of the sticker
* @param options - The options to use when fetching the sticker
* @param options - The options for fetching the sticker
*/
public async get(stickerId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.sticker(stickerId), { signal }) as Promise<RESTGetAPIStickerResult>;

View File

@@ -1,86 +1,22 @@
/* eslint-disable jsdoc/check-param-names */
import type { RawFile, RequestData, REST } from '@discordjs/rest';
import type { RequestData, REST } from '@discordjs/rest';
import {
Routes,
type APIThreadChannel,
type APIThreadMember,
type RESTGetAPIChannelThreadMembersResult,
type RESTPostAPIChannelThreadsJSONBody,
type RESTPostAPIChannelThreadsResult,
type RESTPostAPIGuildForumThreadsJSONBody,
type Snowflake,
} from 'discord-api-types/v10';
export interface StartForumThreadOptions extends RESTPostAPIGuildForumThreadsJSONBody {
message: RESTPostAPIGuildForumThreadsJSONBody['message'] & { files?: RawFile[] };
}
export class ThreadsAPI {
public constructor(private readonly rest: REST) {}
/**
* Fetches a thread
*
* @see {@link https://discord.com/developers/docs/resources/channel#get-channel}
* @param threadId - The id of the thread
* @param options - The options to use when fetching the thread
*/
public async get(threadId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.channel(threadId), { signal }) as Promise<APIThreadChannel>;
}
/**
* Creates a new thread
*
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-from-message}
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-without-message}
* @param channelId - The id of the channel to start the thread in
* @param body - The data to use when starting the thread
* @param messageId - The id of the message to start the thread from
* @param options - The options to use when starting the thread
*/
public async create(
channelId: Snowflake,
body: RESTPostAPIChannelThreadsJSONBody,
messageId?: Snowflake,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.threads(channelId, messageId), {
body,
signal,
}) as Promise<RESTPostAPIChannelThreadsResult>;
}
/**
* Creates a new forum post
*
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-in-forum-channel}
* @param channelId - The id of the forum channel to start the thread in
* @param body - The data to use when starting the thread
* @param options - The options to use when starting the thread
*/
public async createForumThread(
channelId: Snowflake,
{ message, ...optionsBody }: StartForumThreadOptions,
{ signal }: Pick<RequestData, 'signal'> = {},
) {
const { files, ...messageBody } = message;
const body = {
...optionsBody,
message: messageBody,
};
return this.rest.post(Routes.threads(channelId), { files, body, signal }) as Promise<APIThreadChannel>;
}
/**
* Adds the current user to a thread
*
* @see {@link https://discord.com/developers/docs/resources/channel#join-thread}
* @param threadId - The id of the thread to join
* @param options - The options to use when joining the thread
* @param options - The options for joining the thread
*/
public async join(threadId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
await this.rest.put(Routes.threadMembers(threadId, '@me'), { signal });
@@ -92,7 +28,7 @@ export class ThreadsAPI {
* @see {@link https://discord.com/developers/docs/resources/channel#add-thread-member}
* @param threadId - The id of the thread to add the member to
* @param userId - The id of the user to add to the thread
* @param options - The options to use when adding the member to the thread
* @param options - The options for adding the member to the thread
*/
public async addMember(threadId: Snowflake, userId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
await this.rest.put(Routes.threadMembers(threadId, userId), { signal });
@@ -103,7 +39,7 @@ export class ThreadsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#leave-thread}
* @param threadId - The id of the thread to leave
* @param options - The options to use when leaving the thread
* @param options - The options for leaving the thread
*/
public async leave(threadId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
await this.rest.delete(Routes.threadMembers(threadId, '@me'), { signal });
@@ -115,7 +51,7 @@ export class ThreadsAPI {
* @see {@link https://discord.com/developers/docs/resources/channel#remove-thread-member}
* @param threadId - The id of the thread to remove the member from
* @param userId - The id of the user to remove from the thread
* @param options - The options to use when removing the member from the thread
* @param options - The options for removing the member from the thread
*/
public async removeMember(threadId: Snowflake, userId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
await this.rest.delete(Routes.threadMembers(threadId, userId), { signal });
@@ -127,7 +63,7 @@ export class ThreadsAPI {
* @see {@link https://discord.com/developers/docs/resources/channel#get-thread-member}
* @param threadId - The id of the thread to fetch the member from
* @param userId - The id of the user
* @param options - The options to use when fetching the member
* @param options - The options for fetching the member
*/
public async getMember(threadId: Snowflake, userId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.threadMembers(threadId, userId), { signal }) as Promise<APIThreadMember>;
@@ -138,7 +74,7 @@ export class ThreadsAPI {
*
* @see {@link https://discord.com/developers/docs/resources/channel#list-thread-members}
* @param threadId - The id of the thread to fetch the members from
* @param options - The options to use when fetching the members
* @param options - The options for fetching the members
*/
public async getAllMembers(threadId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.threadMembers(threadId), { signal }) as Promise<RESTGetAPIChannelThreadMembersResult>;

View File

@@ -28,7 +28,7 @@ export class UsersAPI {
*
* @see {@link https://discord.com/developers/docs/resources/user#get-user}
* @param userId - The id of the user to fetch
* @param options - The options to use when fetching the user
* @param options - The options for fetching the user
*/
public async get(userId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.user(userId), { signal }) as Promise<RESTGetAPIUserResult>;
@@ -38,7 +38,7 @@ export class UsersAPI {
* Returns the user object of the requester's account
*
* @see {@link https://discord.com/developers/docs/resources/user#get-current-user}
* @param options - The options to use when fetching the current user
* @param options - The options for fetching the current user
*/
public async getCurrent({ signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.user('@me'), { signal }) as Promise<RESTGetAPICurrentUserResult>;
@@ -48,8 +48,8 @@ export class UsersAPI {
* Returns a list of partial guild objects the current user is a member of
*
* @see {@link https://discord.com/developers/docs/resources/user#get-current-user-guilds}
* @param query - The query options to use when fetching the current user's guilds
* @param options - The options to use when fetching the guilds
* @param query - The query options for fetching the current user's guilds
* @param options - The options for fetching the guilds
*/
public async getGuilds(query: RESTGetAPICurrentUserGuildsQuery = {}, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.userGuilds(), {
@@ -153,8 +153,8 @@ export class UsersAPI {
*
* @see {@link https://discord.com/developers/docs/resources/user#update-user-application-role-connection}
* @param applicationId - The id of the application
* @param body - The data to use when updating the application role connection
* @param options - The options to use when updating the application role connection
* @param body - The data for updating the application role connection
* @param options - The options for updating the application role connection
*/
public async updateApplicationRoleConnection(
applicationId: Snowflake,

View File

@@ -10,7 +10,7 @@ export class VoiceAPI {
* Fetches all voice regions
*
* @see {@link https://discord.com/developers/docs/resources/voice#list-voice-regions}
* @param options - The options to use when fetching the voice regions
* @param options - The options for fetching the voice regions
*/
public async getVoiceRegions({ signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.get(Routes.voiceRegions(), { signal }) as Promise<RESTGetAPIVoiceRegionsResult>;

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