Compare commits

...

132 Commits

Author SHA1 Message Date
iCrawl
a319607af6 chore(release): builders, collection, rest and voice 2022-01-24 17:14:02 +01:00
iCrawl
487a5a2669 chore: update changelogs 2022-01-24 16:42:33 +01:00
Suneet Tipirneni
c10afeadc7 types: make required a boolean (#7307) 2022-01-20 14:30:03 +01:00
ckohen
d0fa5aaa26 fix(rest): don't add empty query (#7308) 2022-01-20 12:14:31 +01:00
ckohen
d8ea572fb8 fix(rest): use http agent when protocol is not https (#7309) 2022-01-20 12:14:12 +01:00
Jiralite
1c6c9449ad types: Fix channel create overloads (#7294) 2022-01-19 22:06:07 +01:00
Jan
b4ed8fd3ed refactor: remove transformPermissions (#7303) 2022-01-19 22:05:54 +01:00
Suneet Tipirneni
857bba4480 fix(guildchannelmanager): remove reverse enum lookup (#7304) 2022-01-19 22:05:38 +01:00
Shubham Parihar
bd33ebb507 docs(StageInstance): deprecate discoverableDisabled (#7179) 2022-01-19 20:37:05 +01:00
Jiralite
cf25de9373 feat(GuildPreview): Add stickers (#7152) 2022-01-19 20:36:05 +01:00
SpaceEEC
5b4dbc3359 ci(publish-dev): only build dependencies when releasing (#7302) 2022-01-19 14:54:25 +01:00
Suneet Tipirneni
213acd7997 feat: Enum resolvers & internal enum string removal (#7290)
Co-authored-by: Almeida <almeidx@pm.me>
2022-01-19 14:11:10 +01:00
Jiralite
164589c551 refactor: Remove VoiceChannel#editable (#7291) 2022-01-19 07:14:33 +01:00
Jiralite
347ff80bbc refactor: Remove boolean option for Webhook#fetchMessage (#7293) 2022-01-19 07:13:38 +01:00
Khafra
307389a335 BaseClient: pass captureRejections option (#7288) 2022-01-18 11:21:05 +01:00
awned
9181a31e0b feat(guildemojimanager): add delete and edit methods (#7286)
Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com>
Co-authored-by: Antonio Román <kyradiscord@gmail.com>
2022-01-18 08:35:36 +01:00
Almeida
86d9d06743 fix(builders): dont export Button component stuff twice (#7289) 2022-01-17 22:13:51 +01:00
Suneet Tipirneni
da05a8856b feat(interaction): add isRepliable type guard (#7259)
Co-authored-by: Almeida <almeidx@pm.me>
Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com>
2022-01-17 20:17:34 +01:00
Parbez
6112767128 refactor(subcommandgroup): required default to false (#7217) 2022-01-17 16:46:31 +01:00
Rodry
26a9dc3206 types: fix regressions and inconsistencies (#7260) 2022-01-17 16:45:23 +01:00
Almeida
18b0ed4cbe refactor(invite): make channel and inviter getters (#7278) 2022-01-17 13:51:34 +01:00
Parbez
c90e47f904 refactor: remove required from getMember (#7188) 2022-01-17 13:51:13 +01:00
Suneet Tipirneni
3bb4829800 feat: rest hash and handler sweeping (#7255)
Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
Co-authored-by: Antonio Román <kyradiscord@gmail.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
2022-01-17 13:50:41 +01:00
Almeida
e65da44d9c docs(shardingmanager): fix type of execArgv option (#7284) 2022-01-17 13:15:46 +01:00
Suneet Tipirneni
0951309b32 chore(cdn): default to animated images (#7265)
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <almeidx@pm.me>
2022-01-17 13:14:03 +01:00
Suneet Tipirneni
101d7c5ffa refactor: remove djs components and use /builders components instead (#7252)
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
2022-01-17 13:13:48 +01:00
Jan
599f96740e ci: fix docs workflow (#7287) 2022-01-17 11:40:53 +01:00
Jan
9054f2f7ad feat: rest docs (#7281) 2022-01-17 10:56:48 +01:00
Almeida
ecf2430f6e ci: dont run auto-deprecated and publish-dev on forks (#7279) 2022-01-16 21:24:31 +01:00
Jiralite
7c07976018 refactor: Default *URL methods to animated hash (#7149)
Co-authored-by: Jan <66554238+vaporox@users.noreply.github.com>
2022-01-14 18:03:09 +01:00
Antonio Román
8ddd44ed85 fix: import clear{Timeout,Interval} from node:timers (#7269) 2022-01-14 13:34:59 +01:00
Jan
0b23b7f039 refactor: use setPosition inside edit (#7263) 2022-01-14 00:21:32 +01:00
Koyamie
06f5210f58 fix(ApplicationCommand): use new ApplicationCommandOptionType enums (#7257) 2022-01-14 00:20:45 +01:00
Almeida
f284a4641f fix: use enums from discord-api-types (#7258) 2022-01-14 00:19:35 +01:00
Rodry
37ec0bda6d docs(interaction): add locale list link (#7261) 2022-01-13 18:19:30 +01:00
Jan
0a5d5f38c0 refactor: don't disable import order lint (#7262) 2022-01-13 17:59:49 +01:00
Vitor
0dd56afe1c docs: fix a typo and use milliseconds instead of ms (#7251) 2022-01-13 17:59:28 +01:00
Jiralite
7b53978a73 chore: Add prefer-object-has-own rule (#7264) 2022-01-13 17:59:10 +01:00
Suneet Tipirneni
2bb40fd767 feat: add components to /builders (#7195)
Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
2022-01-12 20:50:08 +01:00
Rodry
37a22e04c2 feat(Channel): improve typeguards (#6957)
Co-authored-by: Papageorgiadis Savvas <50584606+papsavas@users.noreply.github.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Almeida <almeidx@pm.me>
2022-01-12 20:30:06 +01:00
Koyamie
f753882592 fix(exports): export ApplicationCommandType properly (#7256) 2022-01-12 20:27:41 +01:00
Suneet Tipirneni
aa6d1c74de refactor: remove discord.js enums and use discord-api-types enums instead (#7077) 2022-01-12 02:00:41 +01:00
Jan
1479e40bce refactor(application): remove fetchAssets (#7250) 2022-01-11 22:03:17 +01:00
Voxelli
1745973024 refactor: PresenceUpdate and demuxProbe (#7248) 2022-01-11 22:02:54 +01:00
iCrawl
62c74b8333 test(voice): fix tests 2022-01-11 21:53:08 +01:00
Suneet Tipirneni
db25f529b2 types: add ReadonlyCollection (#7245)
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
2022-01-11 12:30:16 +01:00
Noel
16938da355 chore: improve linting (#7244) 2022-01-11 12:30:08 +01:00
Voxelli
ff3a8b8323 fix(Shard): EventEmitter listener warning (#7240)
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2022-01-11 12:30:00 +01:00
ckohen
86ab526d49 refactor(files): file data can be much more than buffer (#7238) 2022-01-11 12:29:48 +01:00
Suneet Tipirneni
d8efba24e0 refactor: make intersect perform a true intersection (#7211)
Co-authored-by: Antonio Román <kyradiscord@gmail.com>
2022-01-11 12:29:41 +01:00
Suneet Tipirneni
9052e321d1 feat: Add Locales to Interactions (#7131)
Co-authored-by: Rodry <38259440+ImRodry@users.noreply.github.com>
2022-01-11 08:55:49 +01:00
Parbez
22fdbb0a29 chore: commit scope name in lowercase (#7246) 2022-01-11 08:53:26 +01:00
Suneet Tipirneni
ed0cfd91ed fix: ref delay for rate limited requests (#7239) 2022-01-10 10:21:44 +01:00
Noel
b2dfb2ec70 revert "chore: optimize Turbo pipelines" (#7237) 2022-01-09 23:22:25 +01:00
iCrawl
56b69a749a ci: only run assignment when a pr opens 2022-01-09 22:44:06 +01:00
Jonah Snider
fae39efc7f chore: optimize Turbo pipelines (#7236) 2022-01-09 22:32:02 +01:00
iCrawl
7ddd337c4a ci: more automation for prs 2022-01-09 22:30:52 +01:00
Rodry
a8509c91ca fix(timestamps): account for timestamps of 0 when creating Dates (#7226) 2022-01-09 21:48:45 +01:00
Jonah Snider
a0a4a2258a chore: format all supported Prettier files (#7233) 2022-01-09 21:42:04 +01:00
Almeida
4770c814b2 chore: update readme links (#7229) 2022-01-09 19:35:18 +01:00
iCrawl
4917eb3539 ci: revert auto-labeling 2022-01-09 19:28:32 +01:00
iCrawl
c0824ae419 ci: try different syntax in yaml file 2022-01-09 19:23:33 +01:00
iCrawl
174782e132 ci: update version of labeler 2022-01-09 19:15:21 +01:00
iCrawl
538d6683bc ci: escape backslashes in yml 2022-01-09 18:57:19 +01:00
iCrawl
0236308581 ci: better labeler for issues and prs 2022-01-09 18:33:27 +01:00
Rodry
822dc678da refactor(embeds): don't create new embed instances when unnecessary (#7227) 2022-01-09 17:35:32 +01:00
Suneet Tipirneni
f1d4bd68ec chore: allow typescript to typecheck .d.ts files (#7222) 2022-01-09 15:14:29 +01:00
Hyro
e38d79988a chore: license for REST module (#7223) 2022-01-09 13:21:43 +01:00
Vitor
bd7a6f2652 docs(SlashCommandSubcommands): updating old links from Discord developer portal (#7224) 2022-01-09 13:20:43 +01:00
Raiden-Ei
37cad54dbd fix(MessageEmbed): createdAt field can be zero (#7218) 2022-01-09 13:20:07 +01:00
Rodry
4fd127e79e refactor(GuildMember): throw better errors on #kickable and #bannable (#7137) 2022-01-09 13:18:50 +01:00
J-Human
ab3ff5a262 feat(Permissions): remove deprecated thread-related permissions (#6755) 2022-01-09 11:49:27 +01:00
J-Human
b92a7d7233 fix(BaseClient): do not append default options if provided is not an object (#6453) 2022-01-09 11:49:03 +01:00
J-Human
caaef53dd9 feat(VoiceRegion): remove the unsent vip field (#6759) 2022-01-09 11:48:15 +01:00
muchnameless
68b9564f18 types(interaction): remove renamed typeguards (#7220) 2022-01-09 11:44:24 +01:00
muchnameless
962f4bf882 fix: snowflakeutil import (#7219) 2022-01-09 11:43:35 +01:00
iCrawl
e07c374337 ci: fix publishing dev versions 2022-01-08 23:30:28 +01:00
iCrawl
7832dbc07a chore: yarn lock 2022-01-08 23:17:01 +01:00
iCrawl
4a2dbd6238 test: fix voice secretbox tests 2022-01-08 23:16:38 +01:00
iCrawl
b593bd32a9 test: fix voice tests 2022-01-08 22:57:29 +01:00
iCrawl
1d532d9468 ci: don't cache deps for publish 2022-01-08 22:53:10 +01:00
iCrawl
3f36746561 types: assertType -> expectType 2022-01-08 20:52:11 +01:00
Antonio Román
e082dfb158 refactor(SnowflakeUtil): switch to @sapphire/snowflake (#7079) 2022-01-08 19:11:33 +01:00
Matt (IPv4) Cowley
ae876d9624 refactor(InteractionCreate): remove interaction event (#6326) 2022-01-08 14:43:30 +01:00
Matt (IPv4) Cowley
171e917fb9 refactor(MessageCreate): remove message event (#6324) 2022-01-08 14:43:12 +01:00
Koyamie
63034b44c9 fix(Role): remove unused process (#7215) 2022-01-08 14:10:56 +01:00
Rodry
13eb78256d refactor(integration): turn undefined into null and consistency (#7209) 2022-01-08 12:44:28 +01:00
IlluminatiFish
1c615d1bb2 fix(WebhookClient): Updated webhook url regex (#6804) 2022-01-08 12:42:50 +01:00
Suneet Tipirneni
1db6c2d37e chore(ThreadMemberManager): make #fetch only take one object parameter (#6997) 2022-01-08 12:42:30 +01:00
Antonio Román
cee7fd181c refactor: remove deleted field (#7092) 2022-01-08 12:41:35 +01:00
Jan
55e21f5366 refactor(Dates): save timestamps everywhere and use Date.parse (#7108) 2022-01-08 12:41:20 +01:00
Commandtechno
d06d70ccf2 feat(richpresenceassets): add YouTube and custom image support (#7184) 2022-01-08 12:40:35 +01:00
Koyamie
95f8375d42 fix(Sweepers): add sweepStickers function (#7213) 2022-01-08 12:39:48 +01:00
Suneet Tipirneni
137ea249df docs: fix command interaction docs (#7212) 2022-01-08 11:21:06 +01:00
Koyamie
49dada35f9 fix(InteractionCreate): use ChatInputCommandInteraction instead (#7210) 2022-01-08 02:31:23 +01:00
iCrawl
53971f0de9 ci: use yarn to create new version 2022-01-08 01:47:00 +01:00
iCrawl
9760fd1b77 ci: fix publishing dev version 2022-01-08 01:44:17 +01:00
Raiden-Ei
fbef454894 fix(Structues): rename old module's name (#7207) 2022-01-08 01:41:22 +01:00
Jiralite
fbbac27978 refactor(RoleManager): Remove comparePositions() (#7201) 2022-01-08 01:35:32 +01:00
Rodry
dbf5ce3e6c ci(documentation): add repository_owner check (#7205) 2022-01-08 01:35:20 +01:00
Antonio Román
ef6f035b5d chore: add myself to contributors (#7206) 2022-01-08 01:35:07 +01:00
iCrawl
9d17904eff chore: deps 2022-01-08 01:33:47 +01:00
Raiden-Ei
033151cf92 fix(WebSocket): Remove application command handler (#7202) 2022-01-08 01:29:56 +01:00
Rodry
3269ec1984 chore(VSCode): add extension recommendations (#6666) 2022-01-08 00:51:19 +01:00
ckohen
c969cbf652 refactor(rest): rename attachment to file (#7199) 2022-01-08 00:49:34 +01:00
Suneet Tipirneni
3872acfeb8 fix(User): bannerURL() should not throw when not present (#6789) 2022-01-08 00:48:46 +01:00
ckohen
12ffa069aa chore(Caching): clean up deprecated cache sweeping (#7118)
Co-authored-by: Antonio Román <kyradiscord@gmail.com>
2022-01-08 00:48:17 +01:00
Suneet Tipirneni
1f9b9225f2 types(Collection): union types on intersect and difference (#7196) 2022-01-08 00:47:55 +01:00
Suneet Tipirneni
b7856e7809 refactor: Better Command Terminology (#7197) 2022-01-08 00:47:41 +01:00
Jan
5022b14da0 refactor(Actions): remove deleted maps (#7076) 2022-01-08 00:34:47 +01:00
iCrawl
fbe40031cf chore: manually update changelog 2022-01-08 00:03:51 +01:00
Jiralite
a0d5f13dd9 fix(VoiceState): Ensure suppress & streaming have proper fallback values (#6377) 2022-01-07 23:40:58 +01:00
Rodry
6085b4f727 refactor(Client): remove applicationCommand events (#6492) 2022-01-07 23:40:50 +01:00
Jiralite
0c24cc8ec0 refactor: Remove Util.removeMentions() (#6530) 2022-01-07 23:40:36 +01:00
Rodry
75616a305f refactor(Constants): change APPLICATION_COMMAND -> CHAT_INPUT_COMMAND (#7018) 2022-01-07 23:40:01 +01:00
Antonio Román
2b480cb14e feat(Collector): yield all collected values (#7073) 2022-01-07 23:39:49 +01:00
LePtitMetalleux
b454740ae8 docs(TextBasedChannel): fixed syntax error in examples (#7163) 2022-01-07 23:38:58 +01:00
Suneet Tipirneni
c978dbb623 types: fix cache types resolving to never (#7164) 2022-01-07 23:37:17 +01:00
n1ck_pro
d4e6e03708 docs(TextBasedChannel): fix #createMessageComponentCollector description (#7168) 2022-01-07 23:18:46 +01:00
GoldenAngel
db669b8971 docs: fixes the examples for kick and ban (#7170) 2022-01-07 23:18:25 +01:00
awned
f79ea67d3a docs(RoleManager): fix incorrect example (#7174) 2022-01-07 23:17:57 +01:00
ckohen
ae2f013653 fix(sweepers): provide default for object param (#7182) 2022-01-07 23:16:00 +01:00
Souji
37587e2bcb chore: issue template changes for monorepo (#7198) 2022-01-07 23:13:04 +01:00
Almeida
43e5e3c339 refactor(Guild): remove deprecated setXPositions methods (#6897) 2022-01-07 23:12:31 +01:00
Almeida
b246fc4101 refactor(UserFlags): update flag names (#6938) 2022-01-07 23:12:05 +01:00
Antonio Román
4293b74253 chore: bump Node.js to 16.9.0 (#7035) 2022-01-07 21:03:00 +01:00
iCrawl
c8bfb24589 ci: use pull_request_target for auto labeling 2022-01-07 20:54:51 +01:00
iCrawl
b08c41d425 chore: remove labeling chore for now 2022-01-07 20:49:47 +01:00
iCrawl
4a80710e7a chore: add auto-labeler 2022-01-07 20:42:43 +01:00
iCrawl
1060dcdd4e chore: add more labels 2022-01-07 20:17:48 +01:00
iCrawl
967e9ace21 ci: max simultaneous of 1 for documentation runners 2022-01-07 17:27:26 +01:00
iCrawl
3c9a9c2c18 ci: force push to avoid non-fast-forward errors 2022-01-07 17:23:13 +01:00
251 changed files with 5502 additions and 6403 deletions

View File

@@ -15,13 +15,13 @@ Messages must be matched by the following regex:
Appears under "Features" header, `GuildMember` subheader:
```
feat(GuildMember): add 'tag' method
feat(guildmember): add 'tag' method
```
Appears under "Bug Fixes" header, `Guild` subheader, with a link to issue #28:
```
fix(Guild): handle events correctly
fix(guild): handle events correctly
close #28
```
@@ -37,7 +37,7 @@ BREAKING CHANGE: The 'bar' option has been removed.
The following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header.
```
revert: feat(Managers): add Managers
revert: feat(managers): add Managers
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
```

View File

@@ -1,12 +1,23 @@
name: Bug report
description: Report incorrect or unexpected behavior of discord.js
description: Report incorrect or unexpected behavior of a package
labels: [bug, need repro]
body:
- type: markdown
attributes:
value: |
Use Discord for questions: https://discord.gg/djs
If you are reporting a voice issue, please post your issue at https://github.com/discordjs/voice/issues
- type: dropdown
id: package
attributes:
label: Which package is this bug report for?
options:
- discord.js
- builders
- collection
- rest
- voice
validations:
required: true
- type: textarea
id: description
attributes:
@@ -30,28 +41,16 @@ body:
description: Include a reproducible, minimal code sample. This will be automatically formatted into code, so no need for backticks.
render: typescript
placeholder: |
const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS] });
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong!');
}
});
client.login('token');
Your code sample should be...
... Minimal - Use as little code as possible that still produces the same problem (and is understandable)
... Complete - Provide all parts someone else needs to reproduce your problem
... Reproducible - Test the code you're about to provide to make sure it reproduces the problem
- type: input
id: djs-version
attributes:
label: discord.js version
description: Which version of discord.js are you using? Run `npm list discord.js` in your project directory and paste the output.
placeholder: 13.x.x (we no longer support version 12 or earlier)
label: Package version
description: Which version of are you using? Run `npm list <package>` in your project directory and paste the output.
placeholder: We no longer support version 12 or earlier of discord.js
validations:
required: true
- type: input
@@ -61,7 +60,7 @@ body:
description: |
Which version of Node.js are you using? Run `node --version` in your project directory and paste the output.
If you are using TypeScript, please include its version (`npm list typescript`) as well.
placeholder: Node.js version 16.6+ is required for version 13.0.0+
placeholder: Node.js version 16.9+ is required for version 14.0.0+
validations:
required: true
- type: input
@@ -89,6 +88,7 @@ body:
Tip: you can select multiple items
options:
- Not applicable (subpackage bug)
- No Partials
- USER
- CHANNEL
@@ -104,10 +104,12 @@ body:
attributes:
label: Which gateway intents are you subscribing to?
description: |
Check your Client constructor for the `intents` key.
Check your Client constructor options for the `intents` key.
Tip: you can select multiple items
options:
- Not applicable (subpackage bug)
- No Intents
- GUILDS
- GUILD_MEMBERS
- GUILD_BANS
@@ -131,8 +133,8 @@ body:
id: dev-release
attributes:
label: I have tested this issue on a development release
placeholder: d23280c
placeholder: d23280c (commit hash)
description: |
The issue might already be fixed in a development release. This is not required, but helps us greatly.
To install the latest development release run `npm i discord.js@dev` in your project directory.
The issue might already be fixed in a development release or main. This is not required, but helps us greatly.
[discord.js only] To install the latest development release run `npm i discord.js@dev` in your project directory.
Run `npm list discord.js` and use the last part of the printed information (`d23280c` for `discord.js@xx.x.x-dev.1530234593.d23280c`)

View File

@@ -1,5 +1,5 @@
name: Feature request
description: Request a new feature (documented features of the official Discord developer API only!)
description: Request a new feature (discord.js accepts documented features of the official Discord developer API only!)
labels: [feature request]
body:
- type: markdown
@@ -8,6 +8,18 @@ body:
We can only implement features that Discord publishes, documents and merges into the Discord API documentation.
We do not implement unreleased features.
Use Discord for questions: https://discord.gg/djs
- type: dropdown
id: package
attributes:
label: Which package is the feature request for?
options:
- discord.js
- builders
- collection
- rest
- voice
validations:
required: true
- type: textarea
id: description
attributes:

7
.github/auto_assign.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
addReviewers: true
reviewers:
- iCrawl
- SpaceEEC
- kyranet
- vladfrangu
numberOfReviewers: 0

27
.github/labeler.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
chore:
- any: ['*']
all: ['!packages/*', '!packages/**/*']
'packages:builders':
- packages/builders/*
- packages/builders/**/*
'packages:collection':
- packages/collection/*
- packages/collection/**/*
'packages:discord.js':
- packages/discord.js/*
- packages/discord.js/**/*
'packages:rest':
- packages/rest/*
- packages/rest/**/*
'packages:voice':
- packages/voice/*
- packages/voice/**/*
'packages:ws':
- packages/ws/*
- packages/ws/**/*

12
.github/labels.yml vendored
View File

@@ -44,6 +44,18 @@
color: 'e4e669'
- name: 'need repro'
color: 'c66037'
- name: 'packages:builders'
color: 'fbca04'
- name: 'packages:collection'
color: 'fbca04'
- name: 'packages:discord.js'
color: 'fbca04'
- name: 'packages:rest'
color: 'fbca04'
- name: 'packages:voice'
color: 'fbca04'
- name: 'packages:ws'
color: 'fbca04'
- name: 'performance'
color: '80c042'
- name: 'permissions'

View File

@@ -7,6 +7,7 @@ jobs:
auto-deprecate:
name: npm auto deprecate
runs-on: ubuntu-latest
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v2

View File

@@ -11,6 +11,7 @@ jobs:
build:
name: Build documentation
runs-on: ubuntu-latest
if: github.repository_owner == 'discordjs'
outputs:
BRANCH_NAME: ${{ steps.env.outputs.BRANCH_NAME }}
BRANCH_OR_TAG: ${{ steps.env.outputs.BRANCH_OR_TAG }}
@@ -58,9 +59,10 @@ jobs:
name: Upload Documentation
needs: build
strategy:
max-parallel: 1
fail-fast: false
matrix:
package: ['builders', 'collection', 'discord.js', 'voice']
package: ['builders', 'collection', 'discord.js', 'rest', 'voice']
runs-on: ubuntu-latest
env:
BRANCH_NAME: ${{ needs.build.outputs.BRANCH_NAME }}

View File

@@ -9,14 +9,14 @@ on:
paths:
- '.github/labels.yml'
jobs:
labeler:
name: Labeler
labelsync:
name: Label sync
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Run label sync
- name: Label sync
uses: crazy-max/ghaction-github-labeler@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

16
.github/workflows/pr-automation.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: 'PR Automation'
on:
pull_request_target:
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Automatically label PR
uses: actions/labeler@v3
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
sync-labels: true
- name: Automatically assign reviewers
if: ${{ github.event.action == 'opened' }}
uses: kentaro-m/auto-assign-action@v1.1.2

View File

@@ -7,6 +7,7 @@ jobs:
npm:
name: npm
runs-on: ubuntu-latest
if: github.repository_owner == 'discordjs'
steps:
- name: Checkout repository
uses: actions/checkout@v2
@@ -19,6 +20,15 @@ jobs:
cache: 'yarn'
cache-dependency-path: yarn.lock
- name: Turbo cache
id: turbo-cache
uses: actions/cache@v2
with:
path: .turbo
key: turbo-${{ github.job }}-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
turbo-${{ github.job }}-${{ github.ref_name }}-
- name: Check previous released version
id: pre-release
run: |
@@ -30,6 +40,10 @@ jobs:
if: steps.pre-release.outputs.release == 'true'
run: yarn --immutable
- name: Build dependencies
if: steps.pre-release.outputs.release == 'true'
run: yarn build --cache-dir=".turbo"
- name: Deprecate old versions
if: steps.pre-release.outputs.release == 'true'
run: npm deprecate discord.js@"~$(jq --raw-output '.version' packages/discord.js/package.json)" "no longer supported" || true
@@ -39,7 +53,7 @@ jobs:
- name: Publish
if: steps.pre-release.outputs.release == 'true'
run: |
npm version --git-tag-version=false $(jq --raw-output '.version' packages/discord.js/package.json).$(date +%s).$(git rev-parse --short HEAD)
yarn publish --tag dev || true
yarn workspace discord.js version --no-git-tag-version --new-version $(jq --raw-output '.version' packages/discord.js/package.json).$(date +%s).$(git rev-parse --short HEAD)
yarn workspace discord.js publish --tag dev || true
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}

View File

@@ -27,5 +27,11 @@ jobs:
- name: Install dependencies
run: yarn --immutable
- name: Run eslint
- name: ESLint
run: yarn lint --cache-dir=".turbo"
- name: Tests
run: yarn test --cache-dir=".turbo"
- name: Build
run: yarn build --cache-dir=".turbo"

3
.gitignore vendored
View File

@@ -19,6 +19,9 @@ dist/
# Miscellaneous
.tmp/
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
.idea/
.DS_Store
.turbo

View File

@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
yarn lint-staged && yarn lint:fix
yarn format

View File

@@ -1,3 +0,0 @@
{
"*.{json,yml,yaml}": "prettier --write"
}

12
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,12 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"tamasfe.even-better-toml",
"github.vscode-pull-request-github",
"codezombiech.gitignore",
"eamodio.gitlens",
"christian-kohler.npm-intellisense",
"christian-kohler.path-intellisense"
]
}

View File

@@ -1,3 +1,9 @@
{
"eslint.workingDirectories": [{ "pattern": "./packages/*" }]
"eslint.workingDirectories": [{ "pattern": "./packages/*" }],
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.organizeImports": false
}
}

View File

@@ -8,7 +8,7 @@
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/workflows/Testing/badge.svg" alt="Tests status" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
</p>
</div>
@@ -24,7 +24,7 @@ discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to
## Installation
**Node.js 16.6.0 or newer is required.**
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install discord.js
@@ -38,7 +38,7 @@ pnpm add discord.js
- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`)
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
- [@discordjs/voice](https://github.com/discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
## Example usage

View File

@@ -7,7 +7,6 @@
"build": "turbo run build",
"test": "turbo run test",
"lint": "turbo run lint",
"lint:fix": "turbo run lint:fix",
"format": "turbo run format",
"fmt": "turbo run format",
"postinstall": "is-ci || husky install",
@@ -39,17 +38,16 @@
},
"homepage": "https://discord.js.org",
"devDependencies": {
"@commitlint/cli": "^16.0.1",
"@commitlint/cli": "^16.1.0",
"@commitlint/config-angular": "^16.0.0",
"@favware/npm-deprecate": "^1.0.4",
"conventional-changelog-cli": "^2.2.2",
"husky": "^7.0.4",
"lint-staged": "^12.1.4",
"prettier": "^2.5.1",
"turbo": "^1.0.24-canary.2"
"turbo": "1.0.28"
},
"engines": {
"node": ">=16.6.0"
"node": ">=16.9.0"
},
"workspaces": [
"packages/*"
@@ -70,7 +68,9 @@
"dependsOn": [
"^build"
],
"outputs": []
"outputs": [
"coverage/**"
]
},
"lint": {
"dependsOn": [
@@ -78,16 +78,13 @@
],
"outputs": []
},
"lint:fix": {
"dependsOn": [
"^build"
],
"outputs": []
},
"format": {
"outputs": []
},
"docs": {
"dependsOn": [
"^build"
],
"outputs": [
"docs/docs.json"
]

View File

@@ -8,9 +8,5 @@
"ignorePatterns": ["**/dist/*"],
"env": {
"jest": true
},
"rules": {
"no-redeclare": 0,
"@typescript-eslint/naming-convention": 0
}
}

View File

@@ -0,0 +1,8 @@
# Autogenerated
CHANGELOG.md
.turbo
dist/
docs/**/*
!docs/index.yml
!docs/README.md
coverage/

View File

@@ -1,153 +1,126 @@
# Changelog
All notable changes to this project will be documented in this file.
# [0.12.0](https://github.com/discordjs/discord.js/compare/@discordjs/builders@0.11.0...@discordjs/builders@0.12.0) (2021-12-08)
## Bug Fixes
- **builders:** Dont export `Button` component stuff twice (#7289) ([86d9d06](https://github.com/discordjs/discord.js/commit/86d9d0674347c08d056cd054cb4ce4253195bf94))
## Documentation
- **SlashCommandSubcommands:** Updating old links from Discord developer portal (#7224) ([bd7a6f2](https://github.com/discordjs/discord.js/commit/bd7a6f265212624199fb0b2ddc8ece39759c63de))
## Features
- Add components to /builders (#7195) ([2bb40fd](https://github.com/discordjs/discord.js/commit/2bb40fd767cf5918e3ba422ff73082734bfa05b0))
## Typings
- Make `required` a boolean (#7307) ([c10afea](https://github.com/discordjs/discord.js/commit/c10afeadc702ab98bec5e077b3b92494a9596f9c))
# [0.11.0](https://github.com/discordjs/builders/compare/v0.10.0...v0.11.0) (2021-12-29)
## Bug Fixes
### Bug Fixes
* **ApplicationCommandOptions:** clean up code for builder options ([#68](https://github.com/discordjs/builders/issues/68)) ([b5d0b15](https://github.com/discordjs/builders/commit/b5d0b157b1262bd01fa011f8e0cf33adb82776e7))
- **ApplicationCommandOptions:** clean up code for builder options ([#68](https://github.com/discordjs/builders/issues/68)) ([b5d0b15](https://github.com/discordjs/builders/commit/b5d0b157b1262bd01fa011f8e0cf33adb82776e7))
# [0.10.0](https://github.com/discordjs/builders/compare/v0.9.0...v0.10.0) (2021-12-24)
## Bug Fixes
### Bug Fixes
* use zod instead of ow for max/min option validation ([#66](https://github.com/discordjs/builders/issues/66)) ([beb35fb](https://github.com/discordjs/builders/commit/beb35fb1f65bd6be2321e17cc792f67e8615fd48))
### Features
* add max/min option for int and number builder options ([#47](https://github.com/discordjs/builders/issues/47)) ([2e1e860](https://github.com/discordjs/builders/commit/2e1e860b46e3453398b20df63dabb6d4325e32d1))
- use zod instead of ow for max/min option validation ([#66](https://github.com/discordjs/builders/issues/66)) ([beb35fb](https://github.com/discordjs/builders/commit/beb35fb1f65bd6be2321e17cc792f67e8615fd48))
## Features
- add max/min option for int and number builder options ([#47](https://github.com/discordjs/builders/issues/47)) ([2e1e860](https://github.com/discordjs/builders/commit/2e1e860b46e3453398b20df63dabb6d4325e32d1))
# [0.9.0](https://github.com/discordjs/builders/compare/v0.8.2...v0.9.0) (2021-12-02)
## Bug Fixes
### Bug Fixes
* replace ow with zod ([#58](https://github.com/discordjs/builders/issues/58)) ([0b6fb81](https://github.com/discordjs/builders/commit/0b6fb8161b858e42781855fb73aaa873fec58160))
### Features
* **SlashCommandBuilder:** add autocomplete ([#53](https://github.com/discordjs/builders/issues/53)) ([05b07a7](https://github.com/discordjs/builders/commit/05b07a7e88848188c27d7380d9f948cba25ef778))
- replace ow with zod ([#58](https://github.com/discordjs/builders/issues/58)) ([0b6fb81](https://github.com/discordjs/builders/commit/0b6fb8161b858e42781855fb73aaa873fec58160))
## Features
- **SlashCommandBuilder:** add autocomplete ([#53](https://github.com/discordjs/builders/issues/53)) ([05b07a7](https://github.com/discordjs/builders/commit/05b07a7e88848188c27d7380d9f948cba25ef778))
## [0.8.2](https://github.com/discordjs/builders/compare/v0.8.1...v0.8.2) (2021-10-30)
## Bug Fixes
### Bug Fixes
* downgrade ow because of esm issues ([#55](https://github.com/discordjs/builders/issues/55)) ([3722d2c](https://github.com/discordjs/builders/commit/3722d2c1109a7a5c0abad63c1a7eb944df6e46c8))
- downgrade ow because of esm issues ([#55](https://github.com/discordjs/builders/issues/55)) ([3722d2c](https://github.com/discordjs/builders/commit/3722d2c1109a7a5c0abad63c1a7eb944df6e46c8))
## [0.8.1](https://github.com/discordjs/builders/compare/v0.8.0...v0.8.1) (2021-10-29)
## Bug Fixes
### Bug Fixes
* documentation ([e33ec8d](https://github.com/discordjs/builders/commit/e33ec8dfd5785312f82e0afb017a3dac614fd71d))
# [0.8.0](https://github.com/discordjs/builders/compare/v0.7.0...v0.8.0) (2021-10-29)
- documentation ([e33ec8d](https://github.com/discordjs/builders/commit/e33ec8dfd5785312f82e0afb017a3dac614fd71d))
# [0.7.0](https://github.com/discordjs/builders/compare/v0.6.0...v0.7.0) (2021-10-18)
## Bug Fixes
### Bug Fixes
* properly type `toJSON` methods ([#34](https://github.com/discordjs/builders/issues/34)) ([7723ad0](https://github.com/discordjs/builders/commit/7723ad0da169386e638188de220451a97513bc25))
### Features
* **ContextMenus:** add context menu command builder ([#29](https://github.com/discordjs/builders/issues/29)) ([f0641e5](https://github.com/discordjs/builders/commit/f0641e55733de8992600f3082bcf054e6f815cf7))
* add support for channel types on channel options ([#41](https://github.com/discordjs/builders/issues/41)) ([f6c187e](https://github.com/discordjs/builders/commit/f6c187e0ad6ebe03e65186ece3e95cb1db5aeb50))
- properly type `toJSON` methods ([#34](https://github.com/discordjs/builders/issues/34)) ([7723ad0](https://github.com/discordjs/builders/commit/7723ad0da169386e638188de220451a97513bc25))
## Features
- **ContextMenus:** add context menu command builder ([#29](https://github.com/discordjs/builders/issues/29)) ([f0641e5](https://github.com/discordjs/builders/commit/f0641e55733de8992600f3082bcf054e6f815cf7))
- add support for channel types on channel options ([#41](https://github.com/discordjs/builders/issues/41)) ([f6c187e](https://github.com/discordjs/builders/commit/f6c187e0ad6ebe03e65186ece3e95cb1db5aeb50))
# [0.6.0](https://github.com/discordjs/builders/compare/v0.5.0...v0.6.0) (2021-08-24)
## Bug Fixes
### Bug Fixes
* **SlashCommandBuilder:** allow subcommands and groups to coexist at the root level ([#26](https://github.com/discordjs/builders/issues/26)) ([0be4daf](https://github.com/discordjs/builders/commit/0be4dafdfc0b5747c880be0078c00ada913eb4fb))
### Features
* create `Embed` builder ([#11](https://github.com/discordjs/builders/issues/11)) ([eb942a4](https://github.com/discordjs/builders/commit/eb942a4d1f3bcec9a4e370b6af602a713ad8f9b7))
* **SlashCommandBuilder:** create setDefaultPermission function ([#19](https://github.com/discordjs/builders/issues/19)) ([5d53759](https://github.com/discordjs/builders/commit/5d537593937a8da330153ce4711b7d093a80330e))
* **SlashCommands:** add number option type ([#23](https://github.com/discordjs/builders/issues/23)) ([1563991](https://github.com/discordjs/builders/commit/1563991d421bb07bf7a412c87e7613692d770f04))
- **SlashCommandBuilder:** allow subcommands and groups to coexist at the root level ([#26](https://github.com/discordjs/builders/issues/26)) ([0be4daf](https://github.com/discordjs/builders/commit/0be4dafdfc0b5747c880be0078c00ada913eb4fb))
## Features
- create `Embed` builder ([#11](https://github.com/discordjs/builders/issues/11)) ([eb942a4](https://github.com/discordjs/builders/commit/eb942a4d1f3bcec9a4e370b6af602a713ad8f9b7))
- **SlashCommandBuilder:** create setDefaultPermission function ([#19](https://github.com/discordjs/builders/issues/19)) ([5d53759](https://github.com/discordjs/builders/commit/5d537593937a8da330153ce4711b7d093a80330e))
- **SlashCommands:** add number option type ([#23](https://github.com/discordjs/builders/issues/23)) ([1563991](https://github.com/discordjs/builders/commit/1563991d421bb07bf7a412c87e7613692d770f04))
# [0.5.0](https://github.com/discordjs/builders/compare/v0.3.0...v0.5.0) (2021-08-10)
## Features
### Features
* **Formatters:** add `formatEmoji` ([#20](https://github.com/discordjs/builders/issues/20)) ([c3d8bb5](https://github.com/discordjs/builders/commit/c3d8bb5363a1d46b45c0def4277da6921e2ba209))
- **Formatters:** add `formatEmoji` ([#20](https://github.com/discordjs/builders/issues/20)) ([c3d8bb5](https://github.com/discordjs/builders/commit/c3d8bb5363a1d46b45c0def4277da6921e2ba209))
# [0.4.0](https://github.com/discordjs/builders/compare/v0.3.0...v0.4.0) (2021-08-05)
### Features
* `sub command` => `subcommand` ([#18](https://github.com/discordjs/builders/pull/18)) ([95599c5](https://github.com/discordjs/builders/commit/95599c5b5366ebd054c4c277c52f1a44cda1209d))
## Features
- `sub command` => `subcommand` ([#18](https://github.com/discordjs/builders/pull/18)) ([95599c5](https://github.com/discordjs/builders/commit/95599c5b5366ebd054c4c277c52f1a44cda1209d))
# [0.3.0](https://github.com/discordjs/builders/compare/v0.2.0...v0.3.0) (2021-08-01)
## Bug Fixes
### Bug Fixes
* **Shrug:** Update comment ([#14](https://github.com/discordjs/builders/issues/14)) ([6fa6c40](https://github.com/discordjs/builders/commit/6fa6c405f2ea733811677d3d1bfb1e2806d504d5))
* shrug face rendering ([#13](https://github.com/discordjs/builders/issues/13)) ([6ad24ec](https://github.com/discordjs/builders/commit/6ad24ecd96c82b0f576e78e9e53fc7bf9c36ef5d))
### Features
* **formatters:** mentions ([#9](https://github.com/discordjs/builders/issues/9)) ([f83fe99](https://github.com/discordjs/builders/commit/f83fe99b83188ed999845751ffb005c687dbd60a))
* **Formatters:** Add a spoiler function ([#16](https://github.com/discordjs/builders/issues/16)) ([c213a6a](https://github.com/discordjs/builders/commit/c213a6abb114f65653017a4edec4bdba2162d771))
* **SlashCommands:** add slash command builders ([#3](https://github.com/discordjs/builders/issues/3)) ([6aa3af0](https://github.com/discordjs/builders/commit/6aa3af07b0ee342fff91f080914bb12b3ab773f8))
* shrug, tableflip and unflip strings ([#5](https://github.com/discordjs/builders/issues/5)) ([de5fa82](https://github.com/discordjs/builders/commit/de5fa823cd6f1feba5b2d0a63b2cb1761dfd1814))
- **Shrug:** Update comment ([#14](https://github.com/discordjs/builders/issues/14)) ([6fa6c40](https://github.com/discordjs/builders/commit/6fa6c405f2ea733811677d3d1bfb1e2806d504d5))
- shrug face rendering ([#13](https://github.com/discordjs/builders/issues/13)) ([6ad24ec](https://github.com/discordjs/builders/commit/6ad24ecd96c82b0f576e78e9e53fc7bf9c36ef5d))
## Features
- **formatters:** mentions ([#9](https://github.com/discordjs/builders/issues/9)) ([f83fe99](https://github.com/discordjs/builders/commit/f83fe99b83188ed999845751ffb005c687dbd60a))
- **Formatters:** Add a spoiler function ([#16](https://github.com/discordjs/builders/issues/16)) ([c213a6a](https://github.com/discordjs/builders/commit/c213a6abb114f65653017a4edec4bdba2162d771))
- **SlashCommands:** add slash command builders ([#3](https://github.com/discordjs/builders/issues/3)) ([6aa3af0](https://github.com/discordjs/builders/commit/6aa3af07b0ee342fff91f080914bb12b3ab773f8))
- shrug, tableflip and unflip strings ([#5](https://github.com/discordjs/builders/issues/5)) ([de5fa82](https://github.com/discordjs/builders/commit/de5fa823cd6f1feba5b2d0a63b2cb1761dfd1814))
# [0.2.0](https://github.com/discordjs/builders/compare/v0.1.1...v0.2.0) (2021-07-03)
## Features
### Features
- **Formatters:** added `hyperlink` and `hideLinkEmbed` ([#4](https://github.com/discordjs/builders/issues/4)) ([c532daf](https://github.com/discordjs/builders/commit/c532daf2ba2feae75bf9668f63462e96a5314cff))
* **Formatters:** added `hyperlink` and `hideLinkEmbed` ([#4](https://github.com/discordjs/builders/issues/4)) ([c532daf](https://github.com/discordjs/builders/commit/c532daf2ba2feae75bf9668f63462e96a5314cff))
## [0.1.1](https://github.com/discordjs/builders/compare/v0.1.0...v0.1.1) (2021-06-30)
### Bug Fixes
* **Deps:** added `tslib` as dependency ([#2](https://github.com/discordjs/builders/issues/2)) ([5576ff3](https://github.com/discordjs/builders/commit/5576ff3b67136b957bed0ab8a4c655d5de322813))
# [0.1.1](https://github.com/discordjs/builders/compare/v0.1.0...v0.1.1) (2021-06-30)
## Bug Fixes
- **Deps:** added `tslib` as dependency ([#2](https://github.com/discordjs/builders/issues/2)) ([5576ff3](https://github.com/discordjs/builders/commit/5576ff3b67136b957bed0ab8a4c655d5de322813))
# 0.1.0 (2021-06-30)
## Features
### Features
* added message formatters ([#1](https://github.com/discordjs/builders/issues/1)) ([765e46d](https://github.com/discordjs/builders/commit/765e46dac96c4e49d350243e5fad34c2bc738a7c))
- added message formatters ([#1](https://github.com/discordjs/builders/issues/1)) ([765e46d](https://github.com/discordjs/builders/commit/765e46dac96c4e49d350243e5fad34c2bc738a7c))

View File

@@ -8,14 +8,14 @@
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/v/@discordjs/builders.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/dt/@discordjs/builders.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/builders/actions"><img src="https://github.com/discordjs/builders/workflows/Tests/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://codecov.io/gh/discordjs/builders"><img src="https://codecov.io/gh/discordjs/builders/branch/main/graph/badge.svg" alt="Code coverage" /></a>
</p>
</div>
## Installation
**Node.js 16.6.0 or newer is required.**
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install @discordjs/builders
@@ -37,7 +37,7 @@ Here are some examples for the builders and utilities you can find in this packa
See also the [Update Guide](https://discordjs.guide/additional-info/changes-in-v13.html), including updated and removed items in the library.
- [discord.js Discord server](https://discord.gg/djs)
- [Discord API Discord server](https://discord.gg/discord-api)
- [GitHub](https://github.com/discordjs/builders)
- [GitHub](https://github.com/discordjs/discord.js/tree/main/packages/builders)
- [npm](https://www.npmjs.com/package/@discordjs/builders)
- [Related libraries](https://discord.com/developers/docs/topics/community-resources#libraries)
@@ -45,7 +45,7 @@ Here are some examples for the builders and utilities you can find in this packa
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation](https://discord.js.org/#/docs/builders).
See [the contribution guide](https://github.com/discordjs/builders/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
See [the contribution guide](https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
## Help

View File

@@ -0,0 +1,96 @@
import { APIActionRowComponent, ButtonStyle, ComponentType } from 'discord-api-types/v9';
import { ActionRow, ButtonComponent, createComponent, SelectMenuComponent, SelectMenuOption } from '../../src';
describe('Action Row Components', () => {
describe('Assertion Tests', () => {
test('GIVEN valid components THEN do not throw', () => {
expect(() => new ActionRow().addComponents(new ButtonComponent())).not.toThrowError();
expect(() => new ActionRow().setComponents([new ButtonComponent()])).not.toThrowError();
});
test('GIVEN valid JSON input THEN valid JSON output is given', () => {
const actionRowData: APIActionRowComponent = {
type: ComponentType.ActionRow,
components: [
{
type: ComponentType.Button,
label: 'button',
style: ButtonStyle.Primary,
custom_id: 'test',
},
{
type: ComponentType.Button,
label: 'link',
style: ButtonStyle.Link,
url: 'https://google.com',
},
{
type: ComponentType.SelectMenu,
placeholder: 'test',
custom_id: 'test',
options: [
{
label: 'option',
value: 'option',
},
],
},
],
};
expect(new ActionRow(actionRowData).toJSON()).toEqual(actionRowData);
expect(new ActionRow().toJSON()).toEqual({ type: ComponentType.ActionRow, components: [] });
expect(() => createComponent({ type: ComponentType.ActionRow, components: [] })).not.toThrowError();
// @ts-expect-error
expect(() => createComponent({ type: 42, components: [] })).toThrowError();
});
test('GIVEN valid builder options THEN valid JSON output is given', () => {
const rowWithButtonData: APIActionRowComponent = {
type: ComponentType.ActionRow,
components: [
{
type: ComponentType.Button,
label: 'test',
custom_id: '123',
style: ButtonStyle.Primary,
},
],
};
const rowWithSelectMenuData: APIActionRowComponent = {
type: ComponentType.ActionRow,
components: [
{
type: ComponentType.SelectMenu,
custom_id: '1234',
options: [
{
label: 'one',
value: 'one',
},
{
label: 'two',
value: 'two',
},
],
max_values: 10,
min_values: 12,
},
],
};
const button = new ButtonComponent().setLabel('test').setStyle(ButtonStyle.Primary).setCustomId('123');
const selectMenu = new SelectMenuComponent()
.setCustomId('1234')
.setMaxValues(10)
.setMinValues(12)
.setOptions([
new SelectMenuOption().setLabel('one').setValue('one'),
new SelectMenuOption().setLabel('two').setValue('two'),
]);
expect(new ActionRow().addComponents(button).toJSON()).toEqual(rowWithButtonData);
expect(new ActionRow().addComponents(selectMenu).toJSON()).toEqual(rowWithSelectMenuData);
});
});
});

View File

@@ -0,0 +1,146 @@
import {
APIButtonComponentWithCustomId,
APIButtonComponentWithURL,
ButtonStyle,
ComponentType,
} from 'discord-api-types/v9';
import { buttonLabelValidator, buttonStyleValidator } from '../../src/components/Assertions';
import { ButtonComponent } from '../../src/components/Button';
const buttonComponent = () => new ButtonComponent();
const longStr =
'looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong';
describe('Button Components', () => {
describe('Assertion Tests', () => {
test('GIVEN valid label THEN validator does not throw', () => {
expect(() => buttonLabelValidator.parse('foobar')).not.toThrowError();
});
test('GIVEN invalid label THEN validator does throw', () => {
expect(() => buttonLabelValidator.parse(null)).toThrowError();
expect(() => buttonLabelValidator.parse('')).toThrowError();
expect(() => buttonLabelValidator.parse(longStr)).toThrowError();
});
test('GIVEN valid style THEN validator does not throw', () => {
expect(() => buttonStyleValidator.parse(3)).not.toThrowError();
expect(() => buttonStyleValidator.parse(ButtonStyle.Secondary)).not.toThrowError();
});
test('GIVEN invalid style THEN validator does not throw', () => {
expect(() => buttonStyleValidator.parse(7)).toThrowError();
});
test('GIVEN valid fields THEN builder does not throw', () => {
expect(() =>
buttonComponent().setCustomId('custom').setStyle(ButtonStyle.Primary).setLabel('test'),
).not.toThrowError();
expect(() => {
const button = buttonComponent()
.setCustomId('custom')
.setStyle(ButtonStyle.Primary)
.setDisabled(true)
.setEmoji({ name: 'test' });
button.toJSON();
}).not.toThrowError();
expect(() => buttonComponent().setURL('https://google.com')).not.toThrowError();
});
test('GIVEN invalid fields THEN build does throw', () => {
expect(() => {
buttonComponent().setCustomId(longStr);
}).toThrowError();
expect(() => {
const button = buttonComponent()
.setCustomId('custom')
.setStyle(ButtonStyle.Primary)
.setDisabled(true)
.setLabel('test')
.setURL('https://google.com')
.setEmoji({ name: 'test' });
button.toJSON();
}).toThrowError();
expect(() => {
// @ts-expect-error
const button = buttonComponent().setEmoji('test');
button.toJSON();
}).toThrowError();
expect(() => {
const button = buttonComponent().setStyle(ButtonStyle.Primary);
button.toJSON();
}).toThrowError();
expect(() => {
const button = buttonComponent().setStyle(ButtonStyle.Primary).setCustomId('test');
button.toJSON();
}).toThrowError();
expect(() => {
const button = buttonComponent().setStyle(ButtonStyle.Link);
button.toJSON();
}).toThrowError();
expect(() => {
const button = buttonComponent().setStyle(ButtonStyle.Primary).setLabel('test').setURL('https://google.com');
button.toJSON();
}).toThrowError();
expect(() => {
const button = buttonComponent().setStyle(ButtonStyle.Link).setLabel('test');
button.toJSON();
}).toThrowError();
expect(() => buttonComponent().setStyle(24)).toThrowError();
expect(() => buttonComponent().setLabel(longStr)).toThrowError();
// @ts-expect-error
expect(() => buttonComponent().setDisabled(0)).toThrowError();
// @ts-expect-error
expect(() => buttonComponent().setEmoji('foo')).toThrowError();
expect(() => buttonComponent().setURL('foobar')).toThrowError();
});
test('GiVEN valid input THEN valid JSON outputs are given', () => {
const interactionData: APIButtonComponentWithCustomId = {
type: ComponentType.Button,
custom_id: 'test',
label: 'test',
style: ButtonStyle.Primary,
disabled: true,
};
expect(new ButtonComponent(interactionData).toJSON()).toEqual(interactionData);
expect(
buttonComponent()
.setCustomId(interactionData.custom_id)
.setLabel(interactionData.label)
.setStyle(interactionData.style)
.setDisabled(interactionData.disabled)
.toJSON(),
).toEqual(interactionData);
const linkData: APIButtonComponentWithURL = {
type: ComponentType.Button,
label: 'test',
style: ButtonStyle.Link,
disabled: true,
url: 'https://google.com',
};
expect(new ButtonComponent(linkData).toJSON()).toEqual(linkData);
expect(buttonComponent().setLabel(linkData.label).setDisabled(true).setURL(linkData.url));
});
});
});

View File

@@ -0,0 +1,72 @@
import { APISelectMenuComponent, APISelectMenuOption, ComponentType } from 'discord-api-types/v9';
import { SelectMenuComponent, SelectMenuOption } from '../../src/index';
const selectMenu = () => new SelectMenuComponent();
const selectMenuOption = () => new SelectMenuOption();
const longStr =
'looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong';
describe('Button Components', () => {
describe('Assertion Tests', () => {
test('GIVEN valid inputs THEN Select Menu does not throw', () => {
expect(() => selectMenu().setCustomId('foo')).not.toThrowError();
expect(() => selectMenu().setMaxValues(10)).not.toThrowError();
expect(() => selectMenu().setMinValues(3)).not.toThrowError();
expect(() => selectMenu().setDisabled(true)).not.toThrowError();
expect(() => selectMenu().setPlaceholder('description')).not.toThrowError();
const option = selectMenuOption()
.setLabel('test')
.setValue('test')
.setDefault(true)
.setEmoji({ name: 'test' })
.setDescription('description');
expect(() => selectMenu().addOptions(option)).not.toThrowError();
expect(() => selectMenu().setOptions([option])).not.toThrowError();
});
test('GIVEN invalid inputs THEN Select Menu does throw', () => {
expect(() => selectMenu().setCustomId(longStr)).toThrowError();
expect(() => selectMenu().setMaxValues(30)).toThrowError();
expect(() => selectMenu().setMinValues(-20)).toThrowError();
// @ts-expect-error
expect(() => selectMenu().setDisabled(0)).toThrowError();
expect(() => selectMenu().setPlaceholder(longStr)).toThrowError();
expect(() => {
selectMenuOption()
.setLabel(longStr)
.setValue(longStr)
// @ts-expect-error
.setDefault(-1)
// @ts-expect-error
.setEmoji({ name: 1 })
.setDescription(longStr);
}).toThrowError();
});
test('GIVEN valid JSON input THEN valid JSON history is correct', () => {
const selectMenuOptionData: APISelectMenuOption = {
label: 'test',
value: 'test',
emoji: { name: 'test' },
default: true,
description: 'test',
};
const selectMenuData: APISelectMenuComponent = {
type: ComponentType.SelectMenu,
custom_id: 'test',
max_values: 10,
min_values: 3,
disabled: true,
options: [selectMenuOptionData],
placeholder: 'test',
};
expect(new SelectMenuComponent(selectMenuData).toJSON()).toEqual(selectMenuData);
expect(new SelectMenuOption(selectMenuOptionData).toJSON()).toEqual(selectMenuOptionData);
});
});
});

View File

@@ -178,14 +178,14 @@ describe('Slash Commands', () => {
expect(() =>
getBuilder().addStringOption(
// @ts-expect-error Checking if check works JS-side too
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
getStringOption().setAutocomplete(true).addChoice('Fancy Pants', 'fp_1'),
),
).toThrowError();
expect(() =>
getBuilder().addStringOption(
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
getStringOption()
.setAutocomplete(true)
// @ts-expect-error Checking if check works JS-side too
@@ -200,7 +200,7 @@ describe('Slash Commands', () => {
expect(() =>
getBuilder().addStringOption(
// @ts-expect-error Checking if check works JS-side too
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call
getStringOption().addChoice('Fancy Pants', 'fp_1').setAutocomplete(true),
),
).toThrowError();
@@ -384,6 +384,7 @@ describe('Slash Commands', () => {
test('GIVEN builder with a subcommand that tries to add an invalid result THEN throw error', () => {
expect(() =>
// @ts-expect-error Checking if check works JS-side too
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
getNamedBuilder().addSubcommand(getSubcommand()).addInteger(getInteger()),
).toThrowError();
});

View File

@@ -0,0 +1,62 @@
[changelog]
header = """
# Changelog
All notable changes to this project will be documented in this file.\n
"""
body = """
{% if version %}\
# [{{ version | trim_start_matches(pat="v") }}]\
{% if previous %}\
{% if previous.version %}\
(https://github.com/discordjs/discord.js/compare/{{ previous.version }}...{{ version }})\
{% else %}
(https://github.com/discordjs/discord.js/tree/{{ version }})\
{% endif %}\
{% endif %} \
- ({{ timestamp | date(format="%Y-%m-%d") }})
{% else %}\
# [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
## {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}\
[**breaking**] \
{% endif %}\
{% if commit.scope %}\
**{{commit.scope}}:** \
{% endif %}\
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/discordjs/discord.js/commit/{{ commit.id }}))\
{% endfor %}
{% endfor %}\n
"""
trim = true
footer = ""
[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^docs", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^refactor", group = "Refactor"},
{ message = "^typings", group = "Typings"},
{ message = "^types", group = "Typings"},
{ message = ".*deprecated", body = ".*deprecated", group = "Deprecation"},
{ message = "^revert", skip = true},
{ message = "^style", group = "Styling"},
{ message = "^test", group = "Testing"},
{ message = "^chore", skip = true},
{ message = "^ci", skip = true},
{ message = "^build", skip = true},
{ body = ".*security", group = "Security"},
]
filter_commits = true
tag_pattern = "@discordjs\\/builders@.*"
skip_tags = "v[0-9]*|11|12"
ignore_tags = ""
topo_order = false
sort_commits = "newest"

View File

@@ -1,16 +1,15 @@
{
"name": "@discordjs/builders",
"version": "0.11.0",
"version": "0.12.0",
"description": "A set of builders that you can use when creating your bot",
"scripts": {
"build": "tsup",
"test": "jest --pass-with-no-tests",
"lint": "eslint src --ext mjs,js,ts",
"lint:fix": "eslint src --ext mjs,js,ts --fix",
"format": "prettier --write **/*.{ts,js,json,yml,yaml}",
"lint": "prettier --check . && eslint src __tests__ --ext mjs,js,ts",
"format": "prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",
"docs": "typedoc --json docs/typedoc-out.json src/index.ts && node scripts/docs.mjs",
"prepublishOnly": "yarn build && yarn lint && yarn test",
"changelog": "git cliff --prepend ./CHANGELOG.md -l -c ../../cliff.toml -r ../../ --include-path './*'"
"changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/builders/*'"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
@@ -30,7 +29,8 @@
"Vlad Frangu <kingdgrizzle@gmail.com>",
"Crawl <icrawltogo@gmail.com>",
"Amish Shah <amishshah.2k@gmail.com>",
"SpaceEEC <spaceeec@yahoo.com>"
"SpaceEEC <spaceeec@yahoo.com>",
"Antonio Roman <kyradiscord@gmail.com>"
],
"license": "Apache-2.0",
"keywords": [
@@ -51,36 +51,36 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@sindresorhus/is": "^4.2.0",
"discord-api-types": "^0.26.0",
"@sindresorhus/is": "^4.3.0",
"discord-api-types": "^0.26.1",
"ts-mixer": "^6.0.0",
"tslib": "^2.3.1",
"zod": "^3.11.6"
},
"devDependencies": {
"@babel/core": "^7.16.5",
"@babel/core": "^7.16.12",
"@babel/plugin-proposal-decorators": "^7.16.5",
"@babel/preset-env": "^7.16.5",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.5",
"@discordjs/ts-docgen": "^0.3.4",
"@types/jest": "^27.0.3",
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.8.0",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"babel-plugin-transform-typescript-metadata": "^0.3.2",
"eslint": "^8.5.0",
"eslint-config-marine": "^9.1.0",
"eslint": "^8.7.0",
"eslint-config-marine": "^9.3.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.4.5",
"jest": "^27.4.7",
"prettier": "^2.5.1",
"standard-version": "^9.3.2",
"tsup": "^5.11.8",
"typedoc": "^0.22.10",
"typescript": "^4.5.4"
"tsup": "^5.11.11",
"typedoc": "^0.22.11",
"typescript": "^4.5.5"
},
"engines": {
"node": ">=16.0.0"
"node": ">=16.9.0"
},
"publishConfig": {
"access": "public"

View File

@@ -0,0 +1,46 @@
import { APIActionRowComponent, ComponentType } from 'discord-api-types/v9';
import type { ButtonComponent, SelectMenuComponent } from '..';
import type { Component } from './Component';
import { createComponent } from './Components';
export type ActionRowComponent = ButtonComponent | SelectMenuComponent;
// TODO: Add valid form component types
/**
* Represents an action row component
*/
export class ActionRow<T extends ActionRowComponent> implements Component {
public readonly components: T[] = [];
public readonly type = ComponentType.ActionRow;
public constructor(data?: APIActionRowComponent) {
this.components = (data?.components.map(createComponent) ?? []) as T[];
}
/**
* Adds components to this action row.
* @param components The components to add to this action row.
* @returns
*/
public addComponents(...components: T[]) {
this.components.push(...components);
return this;
}
/**
* Sets the components in this action row
* @param components The components to set this row to
*/
public setComponents(components: T[]) {
Reflect.set(this, 'components', [...components]);
return this;
}
public toJSON(): APIActionRowComponent {
return {
...this,
components: this.components.map((component) => component.toJSON()),
};
}
}

View File

@@ -0,0 +1,64 @@
import { APIMessageComponentEmoji, ButtonStyle } from 'discord-api-types/v9';
import { z } from 'zod';
import type { SelectMenuOption } from './selectMenu/SelectMenuOption';
export const customIdValidator = z.string().min(1).max(100);
export const emojiValidator = z
.object({
id: z.string(),
name: z.string(),
animated: z.boolean(),
})
.partial()
.strict();
export const disabledValidator = z.boolean();
export const buttonLabelValidator = z.string().nonempty().max(80);
export const buttonStyleValidator = z.number().int().min(ButtonStyle.Primary).max(ButtonStyle.Link);
export const placeholderValidator = z.string().max(100);
export const minMaxValidator = z.number().int().min(0).max(25);
export const optionsValidator = z.object({}).array().nonempty();
export function validateRequiredSelectMenuParameters(options: SelectMenuOption[], customId?: string) {
customIdValidator.parse(customId);
optionsValidator.parse(options);
}
export const labelValueValidator = z.string().min(1).max(100);
export const defaultValidator = z.boolean();
export function validateRequiredSelectMenuOptionParameters(label?: string, value?: string) {
labelValueValidator.parse(label);
labelValueValidator.parse(value);
}
export const urlValidator = z.string().url();
export function validateRequiredButtonParameters(
style: ButtonStyle,
label?: string,
emoji?: APIMessageComponentEmoji,
customId?: string,
url?: string,
) {
if (url && customId) {
throw new RangeError('URL and custom id are mutually exclusive');
}
if (!label && !emoji) {
throw new RangeError('Buttons must have a label and/or an emoji');
}
if (style === ButtonStyle.Link) {
if (!url) {
throw new RangeError('Link buttons must have a url');
}
} else if (url) {
throw new RangeError('Non-link buttons cannot have a url');
}
}

View File

@@ -0,0 +1,105 @@
import { APIButtonComponent, APIMessageComponentEmoji, ButtonStyle, ComponentType } from 'discord-api-types/v9';
import {
buttonLabelValidator,
buttonStyleValidator,
customIdValidator,
disabledValidator,
emojiValidator,
urlValidator,
validateRequiredButtonParameters,
} from './Assertions';
import type { Component } from './Component';
export class ButtonComponent implements Component {
public readonly type = ComponentType.Button as const;
public readonly style!: ButtonStyle;
public readonly label?: string;
public readonly emoji?: APIMessageComponentEmoji;
public readonly disabled?: boolean;
public readonly custom_id!: string;
public readonly url!: string;
public constructor(data?: APIButtonComponent) {
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
this.style = data?.style as ButtonStyle;
this.label = data?.label;
this.emoji = data?.emoji;
this.disabled = data?.disabled;
// This if/else makes typescript happy
if (data?.style === ButtonStyle.Link) {
this.url = data.url;
} else {
this.custom_id = data?.custom_id as string;
}
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
}
/**
* Sets the style of this button
* @param style The style of the button
*/
public setStyle(style: ButtonStyle) {
buttonStyleValidator.parse(style);
Reflect.set(this, 'style', style);
return this;
}
/**
* Sets the URL for this button
* @param url The URL to open when this button is clicked
*/
public setURL(url: string) {
urlValidator.parse(url);
Reflect.set(this, 'url', url);
return this;
}
/**
* Sets the custom Id for this button
* @param customId The custom ID to use for this button
*/
public setCustomId(customId: string) {
customIdValidator.parse(customId);
Reflect.set(this, 'custom_id', customId);
return this;
}
/**
* Sets the emoji to display on this button
* @param emoji The emoji to display on this button
*/
public setEmoji(emoji: APIMessageComponentEmoji) {
emojiValidator.parse(emoji);
Reflect.set(this, 'emoji', emoji);
return this;
}
/**
* Sets whether this button is disable or not
* @param disabled Whether or not to disable this button or not
*/
public setDisabled(disabled: boolean) {
disabledValidator.parse(disabled);
Reflect.set(this, 'disabled', disabled);
return this;
}
/**
* Sets the label for this button
* @param label The label to display on this button
*/
public setLabel(label: string) {
buttonLabelValidator.parse(label);
Reflect.set(this, 'label', label);
return this;
}
public toJSON(): APIButtonComponent {
validateRequiredButtonParameters(this.style, this.label, this.emoji, this.custom_id, this.url);
return {
...this,
};
}
}

View File

@@ -0,0 +1,15 @@
import type { APIMessageComponent, ComponentType } from 'discord-api-types/v9';
/**
* Represents a discord component
*/
export interface Component {
/**
* The type of this component
*/
readonly type: ComponentType;
/**
* Converts this component to an API-compatible JSON object
*/
toJSON: () => APIMessageComponent;
}

View File

@@ -0,0 +1,30 @@
import { APIMessageComponent, ComponentType } from 'discord-api-types/v9';
import { ActionRow, ButtonComponent, Component, SelectMenuComponent } from '../index';
import type { ActionRowComponent } from './ActionRow';
export interface MappedComponentTypes {
[ComponentType.ActionRow]: ActionRow<ActionRowComponent>;
[ComponentType.Button]: ButtonComponent;
[ComponentType.SelectMenu]: SelectMenuComponent;
}
/**
* Factory for creating components from API data
* @param data The api data to transform to a component class
*/
export function createComponent<T extends keyof MappedComponentTypes>(
data: APIMessageComponent & { type: T },
): MappedComponentTypes[T];
export function createComponent(data: APIMessageComponent): Component {
switch (data.type) {
case ComponentType.ActionRow:
return new ActionRow(data);
case ComponentType.Button:
return new ButtonComponent(data);
case ComponentType.SelectMenu:
return new SelectMenuComponent(data);
default:
// @ts-expect-error
throw new Error(`Cannot serialize component type: ${data.type as number}`);
}
}

View File

@@ -0,0 +1,111 @@
import { APISelectMenuComponent, ComponentType } from 'discord-api-types/v9';
import {
customIdValidator,
disabledValidator,
minMaxValidator,
placeholderValidator,
validateRequiredSelectMenuParameters,
} from '../Assertions';
import type { Component } from '../Component';
import { SelectMenuOption } from './SelectMenuOption';
/**
* Represents a select menu component
*/
export class SelectMenuComponent implements Component {
public readonly type = ComponentType.SelectMenu as const;
public readonly options: SelectMenuOption[];
public readonly placeholder?: string;
public readonly min_values?: number;
public readonly max_values?: number;
public readonly custom_id!: string;
public readonly disabled?: boolean;
public constructor(data?: APISelectMenuComponent) {
this.options = data?.options.map((option) => new SelectMenuOption(option)) ?? [];
this.placeholder = data?.placeholder;
this.min_values = data?.min_values;
this.max_values = data?.max_values;
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
this.custom_id = data?.custom_id as string;
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
this.disabled = data?.disabled;
}
/**
* Sets the placeholder for this select menu
* @param placeholder The placeholder to use for this select menu
*/
public setPlaceholder(placeholder: string) {
placeholderValidator.parse(placeholder);
Reflect.set(this, 'placeholder', placeholder);
return this;
}
/**
* Sets thes minimum values that must be selected in the select menu
* @param minValues The minimum values that must be selected
*/
public setMinValues(minValues: number) {
minMaxValidator.parse(minValues);
Reflect.set(this, 'min_values', minValues);
return this;
}
/**
* Sets thes maximum values that must be selected in the select menu
* @param minValues The maximum values that must be selected
*/
public setMaxValues(maxValues: number) {
minMaxValidator.parse(maxValues);
Reflect.set(this, 'max_values', maxValues);
return this;
}
/**
* Sets the custom Id for this select menu
* @param customId The custom ID to use for this select menu
*/
public setCustomId(customId: string) {
customIdValidator.parse(customId);
Reflect.set(this, 'custom_id', customId);
return this;
}
/**
* Sets whether or not this select menu is disabled
* @param disabled Whether or not this select menu is disabled
*/
public setDisabled(disabled: boolean) {
disabledValidator.parse(disabled);
Reflect.set(this, 'disabled', disabled);
return this;
}
/**
* Adds options to this select menu
* @param options The options to add to this select menu
* @returns
*/
public addOptions(...options: SelectMenuOption[]) {
this.options.push(...options);
return this;
}
/**
* Sets the options on this select menu
* @param options The options to set on this select menu
*/
public setOptions(options: SelectMenuOption[]) {
Reflect.set(this, 'options', [...options]);
return this;
}
public toJSON(): APISelectMenuComponent {
validateRequiredSelectMenuParameters(this.options, this.custom_id);
return {
...this,
options: this.options.map((option) => option.toJSON()),
};
}
}

View File

@@ -0,0 +1,83 @@
import type { APIMessageComponentEmoji, APISelectMenuOption } from 'discord-api-types/v9';
import {
defaultValidator,
emojiValidator,
labelValueValidator,
validateRequiredSelectMenuOptionParameters,
} from '../Assertions';
/**
* Represents an option within a select menu component
*/
export class SelectMenuOption {
public readonly label!: string;
public readonly value!: string;
public readonly description?: string;
public readonly emoji?: APIMessageComponentEmoji;
public readonly default?: boolean;
public constructor(data?: APISelectMenuOption) {
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
this.label = data?.label as string;
this.value = data?.value as string;
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
this.description = data?.description;
this.emoji = data?.emoji;
this.default = data?.default;
}
/**
* Sets the label of this option
* @param label The label to show on this option
*/
public setLabel(label: string) {
Reflect.set(this, 'label', label);
return this;
}
/**
* Sets the value of this option
* @param value The value of this option
*/
public setValue(value: string) {
Reflect.set(this, 'value', value);
return this;
}
/**
* Sets the description of this option.
* @param description The description of this option
*/
public setDescription(description: string) {
labelValueValidator.parse(description);
Reflect.set(this, 'description', description);
return this;
}
/**
* Sets whether this option is selected by default
* @param isDefault Whether or not this option is selected by default
*/
public setDefault(isDefault: boolean) {
defaultValidator.parse(isDefault);
Reflect.set(this, 'default', isDefault);
return this;
}
/**
* Sets the emoji to display on this button
* @param emoji The emoji to display on this button
*/
public setEmoji(emoji: APIMessageComponentEmoji) {
emojiValidator.parse(emoji);
Reflect.set(this, 'emoji', emoji);
return this;
}
public toJSON(): APISelectMenuOption {
validateRequiredSelectMenuOptionParameters(this.label, this.value);
return {
...this,
};
}
}

View File

@@ -2,6 +2,14 @@ export * as EmbedAssertions from './messages/embed/Assertions';
export * from './messages/embed/Embed';
export * from './messages/formatters';
export * as ComponentAssertions from './components/Assertions';
export * from './components/ActionRow';
export * from './components/Button';
export * from './components/Component';
export * from './components/Components';
export * from './components/selectMenu/SelectMenu';
export * from './components/selectMenu/SelectMenuOption';
export * as SlashCommandAssertions from './interactions/slashCommands/Assertions';
export * from './interactions/slashCommands/SlashCommandBuilder';
export * from './interactions/slashCommands/SlashCommandSubcommands';

View File

@@ -2,6 +2,28 @@ import { z } from 'zod';
import { ApplicationCommandType } from 'discord-api-types/v9';
import type { ContextMenuCommandType } from './ContextMenuCommandBuilder';
const namePredicate = z
.string()
.min(1)
.max(32)
.regex(/^( *[\p{L}\p{N}_-]+ *)+$/u);
const typePredicate = z.union([z.literal(ApplicationCommandType.User), z.literal(ApplicationCommandType.Message)]);
const booleanPredicate = z.boolean();
export function validateDefaultPermission(value: unknown): asserts value is boolean {
booleanPredicate.parse(value);
}
export function validateName(name: unknown): asserts name is string {
namePredicate.parse(name);
}
export function validateType(type: unknown): asserts type is ContextMenuCommandType {
typePredicate.parse(type);
}
export function validateRequiredParameters(name: string, type: number) {
// Assert name matches all conditions
validateName(name);
@@ -9,25 +31,3 @@ export function validateRequiredParameters(name: string, type: number) {
// Assert type is valid
validateType(type);
}
const namePredicate = z
.string()
.min(1)
.max(32)
.regex(/^( *[\p{L}\p{N}_-]+ *)+$/u);
export function validateName(name: unknown): asserts name is string {
namePredicate.parse(name);
}
const typePredicate = z.union([z.literal(ApplicationCommandType.User), z.literal(ApplicationCommandType.Message)]);
export function validateType(type: unknown): asserts type is ContextMenuCommandType {
typePredicate.parse(type);
}
const booleanPredicate = z.boolean();
export function validateDefaultPermission(value: unknown): asserts value is boolean {
booleanPredicate.parse(value);
}

View File

@@ -5,21 +5,6 @@ import type { ApplicationCommandOptionBase } from './mixins/ApplicationCommandOp
import type { ToAPIApplicationCommandOptions } from './SlashCommandBuilder';
import type { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } from './SlashCommandSubcommands';
export function validateRequiredParameters(
name: string,
description: string,
options: ToAPIApplicationCommandOptions[],
) {
// Assert name matches all conditions
validateName(name);
// Assert description conditions
validateDescription(description);
// Assert options conditions
validateMaxOptionsLength(options);
}
const namePredicate = z
.string()
.min(1)
@@ -36,6 +21,27 @@ export function validateDescription(description: unknown): asserts description i
descriptionPredicate.parse(description);
}
const maxArrayLengthPredicate = z.unknown().array().max(25);
export function validateMaxOptionsLength(options: unknown): asserts options is ToAPIApplicationCommandOptions[] {
maxArrayLengthPredicate.parse(options);
}
export function validateRequiredParameters(
name: string,
description: string,
options: ToAPIApplicationCommandOptions[],
) {
// Assert name matches all conditions
validateName(name);
// Assert description conditions
validateDescription(description);
// Assert options conditions
validateMaxOptionsLength(options);
}
const booleanPredicate = z.boolean();
export function validateDefaultPermission(value: unknown): asserts value is boolean {
@@ -46,12 +52,6 @@ export function validateRequired(required: unknown): asserts required is boolean
booleanPredicate.parse(required);
}
const maxArrayLengthPredicate = z.unknown().array().max(25);
export function validateMaxOptionsLength(options: unknown): asserts options is ToAPIApplicationCommandOptions[] {
maxArrayLengthPredicate.parse(options);
}
export function validateMaxChoicesLength(choices: APIApplicationCommandOptionChoice[]) {
maxArrayLengthPredicate.parse(choices);
}

View File

@@ -133,5 +133,5 @@ export interface SlashCommandOptionsOnlyBuilder
Pick<SlashCommandBuilder, 'toJSON'> {}
export interface ToAPIApplicationCommandOptions {
toJSON(): APIApplicationCommandOption;
toJSON: () => APIApplicationCommandOption;
}

View File

@@ -13,7 +13,7 @@ import type { ToAPIApplicationCommandOptions } from './SlashCommandBuilder';
/**
* Represents a folder for subcommands
*
* For more information, go to https://discord.com/developers/docs/interactions/slash-commands#subcommands-and-subcommand-groups
* For more information, go to https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups
*/
@mix(SharedNameAndDescription)
export class SlashCommandSubcommandGroupBuilder implements ToAPIApplicationCommandOptions {
@@ -48,8 +48,10 @@ export class SlashCommandSubcommandGroupBuilder implements ToAPIApplicationComma
validateMaxOptionsLength(options);
// Get the final result
// eslint-disable-next-line @typescript-eslint/no-use-before-define
const result = typeof input === 'function' ? input(new SlashCommandSubcommandBuilder()) : input;
// eslint-disable-next-line @typescript-eslint/no-use-before-define
assertReturnOfBuilder(result, SlashCommandSubcommandBuilder);
// Push it
@@ -75,7 +77,7 @@ export interface SlashCommandSubcommandGroupBuilder extends SharedNameAndDescrip
/**
* Represents a subcommand
*
* For more information, go to https://discord.com/developers/docs/interactions/slash-commands#subcommands-and-subcommand-groups
* For more information, go to https://discord.com/developers/docs/interactions/application-commands#subcommands-and-subcommand-groups
*/
@mix(SharedNameAndDescription, SharedSlashCommandOptions)
export class SlashCommandSubcommandBuilder implements ToAPIApplicationCommandOptions {

View File

@@ -5,7 +5,7 @@ import { SharedNameAndDescription } from './NameAndDescription';
export abstract class ApplicationCommandOptionBase extends SharedNameAndDescription {
public abstract readonly type: ApplicationCommandOptionType;
public readonly required = false;
public readonly required: boolean = false;
/**
* Marks the option as required

View File

@@ -8,9 +8,5 @@
"ignorePatterns": ["**/dist/*"],
"env": {
"jest": true
},
"rules": {
"no-redeclare": 0,
"@typescript-eslint/naming-convention": 0
}
}

View File

@@ -0,0 +1,8 @@
# Autogenerated
CHANGELOG.md
.turbo
dist/
docs/**/*
!docs/index.yml
!docs/README.md
coverage/

View File

@@ -1,63 +1,47 @@
# Changelog
All notable changes to this project will be documented in this file.
# [0.5.0](https://github.com/discordjs/discord.js/compare/@discordjs/collection@0.4.0...@discordjs/collection@0.5.0) (2021-12-08)
## Refactor
- Make `intersect` perform a true intersection (#7211) ([d8efba2](https://github.com/discordjs/discord.js/commit/d8efba24e09aa2a8dbf028fc57a561a56e7833fd))
## Typings
- Add `ReadonlyCollection` (#7245) ([db25f52](https://github.com/discordjs/discord.js/commit/db25f529b26d7c819c1c42ad3e26c2263ea2da0e))
- **Collection:** Union types on `intersect` and `difference` (#7196) ([1f9b922](https://github.com/discordjs/discord.js/commit/1f9b9225f2066e9cc66c3355417139fd25cc403c))
# [0.4.0](https://github.com/discordjs/collection/compare/v0.3.2...v0.4.0) (2021-12-24)
## Features
### Features
- add #reverse ([#48](https://github.com/discordjs/collection/issues/48)) ([8bcb5e2](https://github.com/discordjs/collection/commit/8bcb5e21bcc15f5b77612d8ff03dec6c37f4d449))
- add Collection#ensure ([#52](https://github.com/discordjs/collection/issues/52)) ([3809eb4](https://github.com/discordjs/collection/commit/3809eb4d18e70459355d310919a3f57747eee3dd))
* add #reverse ([#48](https://github.com/discordjs/collection/issues/48)) ([8bcb5e2](https://github.com/discordjs/collection/commit/8bcb5e21bcc15f5b77612d8ff03dec6c37f4d449))
* add Collection#ensure ([#52](https://github.com/discordjs/collection/issues/52)) ([3809eb4](https://github.com/discordjs/collection/commit/3809eb4d18e70459355d310919a3f57747eee3dd))
## [0.3.2](https://github.com/discordjs/collection/compare/v0.3.1...v0.3.2) (2021-10-29)
### Bug Fixes
* update doc engine ([4c0e24f](https://github.com/discordjs/collection/commit/4c0e24fae0323db9de1991db9cfacc093d529abc))
## [0.3.1](https://github.com/discordjs/collection/compare/v0.3.0...v0.3.1) (2021-10-29)
# [0.3.2](https://github.com/discordjs/collection/compare/v0.3.1...v0.3.2) (2021-10-29)
## Bug Fixes
- update doc engine ([4c0e24f](https://github.com/discordjs/collection/commit/4c0e24fae0323db9de1991db9cfacc093d529abc))
# [0.3.0](https://github.com/discordjs/collection/compare/v0.2.4...v0.3.0) (2021-10-29)
## Features
### Features
- add Collection#at() and Collection#keyAt() ([#46](https://github.com/discordjs/collection/issues/46)) ([66b30b9](https://github.com/discordjs/collection/commit/66b30b91069502493383c059cc38e27c152bf541))
- improve documentation and resolve [#49](https://github.com/discordjs/collection/issues/49) ([aec01c6](https://github.com/discordjs/collection/commit/aec01c6ae3ff50b0b5f7c070bff10f01bf98d803))
- ts-docgen ([463b131](https://github.com/discordjs/collection/commit/463b1314e60f2debc526454a6ccd7ce8a9a4ae8a))
* add Collection#at() and Collection#keyAt() ([#46](https://github.com/discordjs/collection/issues/46)) ([66b30b9](https://github.com/discordjs/collection/commit/66b30b91069502493383c059cc38e27c152bf541))
* improve documentation and resolve [#49](https://github.com/discordjs/collection/issues/49) ([aec01c6](https://github.com/discordjs/collection/commit/aec01c6ae3ff50b0b5f7c070bff10f01bf98d803))
* ts-docgen ([463b131](https://github.com/discordjs/collection/commit/463b1314e60f2debc526454a6ccd7ce8a9a4ae8a))
# [0.2.4](https://github.com/discordjs/collection/compare/v0.2.3...v0.2.4) (2021-10-27)
## Bug Fixes
- minification of names ([bd2fe2a](https://github.com/discordjs/collection/commit/bd2fe2a47c38f634b0334fe6e89f30f6f6a0b1f5))
## [0.2.4](https://github.com/discordjs/collection/compare/v0.2.3...v0.2.4) (2021-10-27)
# [0.2.3](https://github.com/discordjs/collection/compare/v0.2.2...v0.2.3) (2021-10-27)
### Bug Fixes
* minification of names ([bd2fe2a](https://github.com/discordjs/collection/commit/bd2fe2a47c38f634b0334fe6e89f30f6f6a0b1f5))
## [0.2.3](https://github.com/discordjs/collection/compare/v0.2.2...v0.2.3) (2021-10-27)
### Bug Fixes
* building with useDefineForClassFields false ([2a571d5](https://github.com/discordjs/collection/commit/2a571d5a2c90ed8b708c3c5c017e2f225cd494e9))
## [0.2.2](https://github.com/discordjs/collection/compare/v0.2.1...v0.2.2) (2021-10-27)
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
- building with useDefineForClassFields false ([2a571d5](https://github.com/discordjs/collection/commit/2a571d5a2c90ed8b708c3c5c017e2f225cd494e9))

View File

@@ -8,7 +8,7 @@
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/v/@discordjs/collection.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/dt/@discordjs/collection.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/collection/actions"><img src="https://github.com/discordjs/collection/workflows/Tests/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
</p>
</div>
@@ -18,7 +18,7 @@
## Installation
**Node.js 16.0.0 or newer is required.**
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install @discordjs/collection
@@ -31,14 +31,14 @@ pnpm add @discordjs/collection
- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website))
- [Documentation](https://discord.js.org/#/docs/collection)
- [discord.js Discord server](https://discord.gg/djs)
- [GitHub](https://github.com/discordjs/collection)
- [GitHub](https://github.com/discordjs/discord.js/tree/main/packages/collection)
- [npm](https://www.npmjs.com/package/@discordjs/collection)
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation](https://discord.js.org/#/docs/collection).
See [the contribution guide](https://github.com/discordjs/collection/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
See [the contribution guide](https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
## Help

View File

@@ -0,0 +1,62 @@
[changelog]
header = """
# Changelog
All notable changes to this project will be documented in this file.\n
"""
body = """
{% if version %}\
# [{{ version | trim_start_matches(pat="v") }}]\
{% if previous %}\
{% if previous.version %}\
(https://github.com/discordjs/discord.js/compare/{{ previous.version }}...{{ version }})\
{% else %}
(https://github.com/discordjs/discord.js/tree/{{ version }})\
{% endif %}\
{% endif %} \
- ({{ timestamp | date(format="%Y-%m-%d") }})
{% else %}\
# [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
## {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}\
[**breaking**] \
{% endif %}\
{% if commit.scope %}\
**{{commit.scope}}:** \
{% endif %}\
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/discordjs/discord.js/commit/{{ commit.id }}))\
{% endfor %}
{% endfor %}\n
"""
trim = true
footer = ""
[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^docs", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^refactor", group = "Refactor"},
{ message = "^typings", group = "Typings"},
{ message = "^types", group = "Typings"},
{ message = ".*deprecated", body = ".*deprecated", group = "Deprecation"},
{ message = "^revert", skip = true},
{ message = "^style", group = "Styling"},
{ message = "^test", group = "Testing"},
{ message = "^chore", skip = true},
{ message = "^ci", skip = true},
{ message = "^build", skip = true},
{ body = ".*security", group = "Security"},
]
filter_commits = true
tag_pattern = "@discordjs\\/collection@.*"
skip_tags = "v[0-9]*|11|12"
ignore_tags = ""
topo_order = false
sort_commits = "newest"

View File

@@ -1,16 +1,15 @@
{
"name": "@discordjs/collection",
"version": "0.4.0",
"version": "0.5.0",
"description": "Utility data structure used in discord.js",
"scripts": {
"test": "jest --pass-with-no-tests",
"build": "tsup",
"lint": "eslint src --ext mjs,js,ts",
"lint:fix": "eslint src --ext mjs,js,ts --fix",
"format": "prettier --write **/*.{ts,js,json,yml,yaml}",
"lint": "prettier --check . && eslint src __tests__ --ext mjs,js,ts",
"format": "prettier --write . && eslint src __tests__ --ext mjs,js,ts --fix",
"docs": "typedoc --json docs/typedoc-out.json src/index.ts && node scripts/docs.mjs",
"prepublishOnly": "yarn build && yarn lint && yarn test",
"changelog": "git cliff --prepend ./CHANGELOG.md -l -c ../../cliff.toml -r ../../ --include-path './*'"
"changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/collection/*'"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
@@ -30,7 +29,8 @@
"Crawl <icrawltogo@gmail.com>",
"Amish Shah <amishshah.2k@gmail.com>",
"SpaceEEC <spaceeec@yahoo.com>",
"Vlad Frangu <kingdgrizzle@gmail.com>"
"Vlad Frangu <kingdgrizzle@gmail.com>",
"Antonio Roman <kyradiscord@gmail.com>"
],
"license": "Apache-2.0",
"keywords": [
@@ -47,27 +47,27 @@
},
"homepage": "https://discord.js.org",
"devDependencies": {
"@babel/core": "^7.16.5",
"@babel/preset-env": "^7.16.5",
"@babel/core": "^7.16.12",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.5",
"@discordjs/ts-docgen": "^0.3.4",
"@types/jest": "^27.0.3",
"@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "^5.8.0",
"@typescript-eslint/parser": "^5.8.0",
"eslint": "^8.5.0",
"eslint-config-marine": "^9.1.0",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.7.0",
"eslint-config-marine": "^9.3.2",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.4.5",
"jest": "^27.4.7",
"prettier": "^2.5.1",
"standard-version": "^9.3.2",
"tsup": "^5.11.8",
"typedoc": "^0.22.10",
"typescript": "^4.5.4"
"tsup": "^5.11.11",
"typedoc": "^0.22.11",
"typescript": "^4.5.5"
},
"engines": {
"node": ">=16.0.0"
"node": ">=16.9.0"
},
"publishConfig": {
"access": "public"

View File

@@ -9,6 +9,12 @@ export interface CollectionConstructor {
readonly [Symbol.species]: CollectionConstructor;
}
/**
* Represents an immutable version of a collection
*/
export type ReadonlyCollection<K, V> = ReadonlyMap<K, V> &
Omit<Collection<K, V>, 'forEach' | 'ensure' | 'reverse' | 'sweep' | 'sort' | 'get' | 'set' | 'delete'>;
/**
* Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself
*
@@ -73,10 +79,12 @@ export class Collection<K, V> extends Map<K, V> {
public first(): V | undefined;
public first(amount: number): V[];
public first(amount?: number): V | V[] | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
if (typeof amount === 'undefined') return this.values().next().value;
if (amount < 0) return this.last(amount * -1);
amount = Math.min(this.size, amount);
const iter = this.values();
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Array.from({ length: amount }, (): V => iter.next().value);
}
@@ -91,10 +99,12 @@ export class Collection<K, V> extends Map<K, V> {
public firstKey(): K | undefined;
public firstKey(amount: number): K[];
public firstKey(amount?: number): K | K[] | undefined {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
if (typeof amount === 'undefined') return this.keys().next().value;
if (amount < 0) return this.lastKey(amount * -1);
amount = Math.min(this.size, amount);
const iter = this.keys();
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Array.from({ length: amount }, (): K => iter.next().value);
}
@@ -398,6 +408,7 @@ export class Collection<K, V> extends Map<K, V> {
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
const iter = this.entries();
return Array.from({ length: this.size }, (): T => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const [key, value] = iter.next().value;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return fn(value, key, this);
@@ -557,7 +568,7 @@ export class Collection<K, V> extends Map<K, V> {
* @example
* const newColl = someColl.clone();
*/
public clone() {
public clone(): Collection<K, V> {
return new this.constructor[Symbol.species](this);
}
@@ -569,7 +580,7 @@ export class Collection<K, V> extends Map<K, V> {
* @example
* const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl);
*/
public concat(...collections: Collection<K, V>[]) {
public concat(...collections: ReadonlyCollection<K, V>[]) {
const newColl = this.clone();
for (const coll of collections) {
for (const [key, val] of coll) newColl.set(key, val);
@@ -586,7 +597,7 @@ export class Collection<K, V> extends Map<K, V> {
*
* @returns Whether the collections have identical contents
*/
public equals(collection: Collection<K, V>) {
public equals(collection: ReadonlyCollection<K, V>) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!collection) return false; // runtime check
if (this === collection) return true;
@@ -625,14 +636,16 @@ export class Collection<K, V> extends Map<K, V> {
}
/**
* The intersect method returns a new structure containing items where the keys are present in both original structures.
* The intersect method returns a new structure containing items where the keys and values are present in both original structures.
*
* @param other The other Collection to filter against
*/
public intersect(other: Collection<K, V>) {
const coll = new this.constructor[Symbol.species]<K, V>();
public intersect<T>(other: ReadonlyCollection<K, T>): Collection<K, T> {
const coll = new this.constructor[Symbol.species]<K, T>();
for (const [k, v] of other) {
if (this.has(k)) coll.set(k, v);
if (this.has(k) && Object.is(v, this.get(k))) {
coll.set(k, v);
}
}
return coll;
}
@@ -642,8 +655,8 @@ export class Collection<K, V> extends Map<K, V> {
*
* @param other The other Collection to filter against
*/
public difference(other: Collection<K, V>) {
const coll = new this.constructor[Symbol.species]<K, V>();
public difference<T>(other: ReadonlyCollection<K, T>): Collection<K, V | T> {
const coll = new this.constructor[Symbol.species]<K, V | T>();
for (const [k, v] of other) {
if (!this.has(k)) coll.set(k, v);
}

View File

@@ -170,6 +170,7 @@
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
"prefer-object-has-own": "error",
"rest-spread-spacing": "error",
"template-curly-spacing": "error",
"yield-star-spacing": "error",
@@ -195,6 +196,14 @@
{
"name": "setImmediate",
"message": "Import setImmediate from `node:timers` instead"
},
{
"name": "clearTimeout",
"message": "Import clearTimeout from `node:timers` instead"
},
{
"name": "clearInterval",
"message": "Import clearInterval from `node:timers` instead"
}
]
}

View File

@@ -0,0 +1,8 @@
# Autogenerated
CHANGELOG.md
.turbo
dist/
docs/**/*
!docs/index.yml
!docs/README.md
coverage/

View File

@@ -1,6 +1,27 @@
# Changelog
All notable changes to this project will be documented in this file.
# [13.6.0](https://github.com/discordjs/discord.js/compare/13.5.1...13.6.0) - (2022-01-13)
## Documentation
- **interaction:** Add locale list link (#7261) ([1f4e633](https://github.com/discordjs/discord.js/commit/1f4e633ce3bd0a2398e49d3a9f6eb5ddd5e09ab9))
## Features
- Add Locales to Interactions (#7131) ([233084a](https://github.com/discordjs/discord.js/commit/233084a6018e77b7f9d94446683eef38790ed277))
# [13.5.1](https://github.com/discordjs/discord.js/compare/13.5.0...13.5.1) - (2022-01-07)
## Bug Fixes
- **sweepers:** Provide default for object param (#7182) ([2dabd82](https://github.com/discordjs/discord.js/commit/2dabd82e26134b5050f694f3a9f6524cd3d0c75c))
## Documentation
- **Sweepers:** Fix typo (#7165) ([780b7ed](https://github.com/discordjs/discord.js/commit/780b7ed39f173a77fd9eae396133980826926906))
# [13.5.0](https://github.com/discordjs/discord.js/compare/13.4.0...13.5.0) - (2021-12-29)
## Bug Fixes
@@ -192,7 +213,7 @@ All notable changes to this project will be documented in this file.
- **GuildManager:** Remove redundant check (#6859) ([579569a](https://github.com/discordjs/discord.js/commit/579569ae18d5a2dbcb39ad5e5adfe486315467ea))
- Remove redundant user agent parsing (#6820) ([460df9e](https://github.com/discordjs/discord.js/commit/460df9eb4df78b502a1cbbbde65dbdfd3c46f5af))
- Remove unnecessary checks (#6777) ([e24209a](https://github.com/discordjs/discord.js/commit/e24209a8b1f02d64eb2fb2a510be7a0ad24d16a8))
- **Role:** Move initialization of delete prop out of _patch (#6776) ([872e7a5](https://github.com/discordjs/discord.js/commit/872e7a59b2c1b891c4d1c426a4a449a1b9353500))
- **Role:** Move initialization of delete prop out of \_patch (#6776) ([872e7a5](https://github.com/discordjs/discord.js/commit/872e7a59b2c1b891c4d1c426a4a449a1b9353500))
## Typings
@@ -218,7 +239,7 @@ All notable changes to this project will be documented in this file.
- **AllowedImageSizes:** Add new image sizes (#6754) ([d0025be](https://github.com/discordjs/discord.js/commit/d0025beb7b1ee6611f4315be91b38788c428f1c1))
- **User:** Compare flags in #equals (#6750) ([00e1e26](https://github.com/discordjs/discord.js/commit/00e1e2673b86e0041f2bebab7b3ced5722f450bb))
- **VoiceState:** Patch streaming value (#6747) ([7eec061](https://github.com/discordjs/discord.js/commit/7eec06145a141d167afc7814f3cfd9e06eb292e6))
- **Message:** Avoid overwriting properties in _patch (#6738) ([a8c21cd](https://github.com/discordjs/discord.js/commit/a8c21cd754d634b4d40047f85264528681a61b41))
- **Message:** Avoid overwriting properties in \_patch (#6738) ([a8c21cd](https://github.com/discordjs/discord.js/commit/a8c21cd754d634b4d40047f85264528681a61b41))
- **ReactionCollector:** Only call the filter function once (#6734) ([d15dd5f](https://github.com/discordjs/discord.js/commit/d15dd5f07dab00e8a31f0a37b1e60ea4017871d0))
- **Shard:** Use provided timeout when respawning (#6735) ([905d100](https://github.com/discordjs/discord.js/commit/905d100d4def974223a128c6276d4a5833c04955))
- **Role:** ToJSON() throwing due to permission bigints (#6724) ([9e421f6](https://github.com/discordjs/discord.js/commit/9e421f6ccf09230769740e069590fb8937f766b9))
@@ -230,7 +251,7 @@ All notable changes to this project will be documented in this file.
- **CachedManager:** Return updated data when cache is false (#6685) ([8426770](https://github.com/discordjs/discord.js/commit/84267708659e3e9bb2f8eb3b08d8923f235e8953))
- **GuildEmoji:** Cache restricted roles and author data (#6675) ([60b8ba6](https://github.com/discordjs/discord.js/commit/60b8ba6b865ba02428d7926998af72cdaa17ea5d))
- **Constants:** Allow undefined size (#6686) ([d3da833](https://github.com/discordjs/discord.js/commit/d3da83368def207585bce9ea95564d79b5097a55))
- ***RoleManager:** Create set of role ids correctly (#6674) ([f8aa4bd](https://github.com/discordjs/discord.js/commit/f8aa4bd4705ee3bf7892670b944516d01146580f))
- **\*RoleManager:** Create set of role ids correctly (#6674) ([f8aa4bd](https://github.com/discordjs/discord.js/commit/f8aa4bd4705ee3bf7892670b944516d01146580f))
- **Shard:** Eval promise never resolves (#6649) ([5070d23](https://github.com/discordjs/discord.js/commit/5070d23914c13814a98cf8ea560853a82b226f94))
- **xxxable:** Follow more properly with discord behavior (#6551) ([5d87398](https://github.com/discordjs/discord.js/commit/5d87398f9fc57915d5447842b4788f0c80642de0))
- Allow null to be passed in order to reset icon/avatar (#6646) ([6033506](https://github.com/discordjs/discord.js/commit/603350645d0fe9d96b763d169215d15b3f4f71b1))
@@ -243,7 +264,7 @@ All notable changes to this project will be documented in this file.
- **UserUpdateAction:** Rely on client.user when ids match (#6511) ([1418649](https://github.com/discordjs/discord.js/commit/141864917ac920a081df6f6b34c13ba83e660bbf))
- **Util:** Allow empty strings in splitMessage (#6437) ([d6e6244](https://github.com/discordjs/discord.js/commit/d6e6244336ccdcdac9a06ab453debe76b13c9bde))
- **BaseClient:** Remove selfbot ability (#6429) ([9a833b1](https://github.com/discordjs/discord.js/commit/9a833b1e0eb638c60c4abbb9255ed64a170e4679))
- **Sticker:** Rename method correctly to _add (#6421) ([2c449b6](https://github.com/discordjs/discord.js/commit/2c449b6b48f5cbc88e666afa852055b873994ca5))
- **Sticker:** Rename method correctly to \_add (#6421) ([2c449b6](https://github.com/discordjs/discord.js/commit/2c449b6b48f5cbc88e666afa852055b873994ca5))
- **Message:** Fix typo (#6435) ([ecb6e50](https://github.com/discordjs/discord.js/commit/ecb6e50b46e627e3217107d662dd19c64527976d))
## Documentation
@@ -353,7 +374,7 @@ All notable changes to this project will be documented in this file.
- **TextBasedChannelFields:** Add back createMessageCollector (#6616) ([1b016a3](https://github.com/discordjs/discord.js/commit/1b016a30c8f52a123c927c0ba44d985321567703))
- Make `channelId` non-nullable on `MessageComponentInteraction` (#6600) ([8cc3885](https://github.com/discordjs/discord.js/commit/8cc3885739127ebc7023b6358ed0259ba7527250))
- `Message#createMessageComponentCollector` use `MessageComponentInteractionOptions<T>` (#6596) ([c62823e](https://github.com/discordjs/discord.js/commit/c62823e43de50362ff0dabaf3fd53d2d39e5816b))
- **MessagePayload:** Specify typings for `files` and `resolveFile` (#6608) ([ea36955](https://github.com/discordjs/discord.js/commit/ea3695585d59ed295cd0c8565f262ea6cc4fe098))
- **MessagePayload:** Specify typings for `files` and `resolveFile` (#6608) ([ea36955](https://github.com/discordjs/discord.js/commit/ea3695585d59ed295cd0c8565f262ea6cc4fe098))
- Collector filter parameter inference (#6574) ([0841956](https://github.com/discordjs/discord.js/commit/08419561edd710a6574b5e1449bf5dc1040580d5))
- **MessageReference:** Correctly add undefined type (#6563) ([cdb0005](https://github.com/discordjs/discord.js/commit/cdb00053dec5223a929de4eea97a90c84c917408))
- `@typedef` for `StageChannelResolvable` (#6568) ([2c219cb](https://github.com/discordjs/discord.js/commit/2c219cb982f73cda7f7db30af59200c754e75cee))
@@ -366,7 +387,7 @@ All notable changes to this project will be documented in this file.
- **CommandInteractionOptionResolver:** Add missing parameter (#6497) ([656b518](https://github.com/discordjs/discord.js/commit/656b51875f82a82a4429b50157a77d37be211534))
- **ClientPresence:** Add type declarations and docs (#6450) ([6cac03a](https://github.com/discordjs/discord.js/commit/6cac03a39408ef14316a898eb81cc998921a8f0f))
- **GuildChannel:** Added missing typing (#6454) ([f294d1e](https://github.com/discordjs/discord.js/commit/f294d1eff207ded337ccff6413824bb6ea60b4c7))
- Message#_patch typings return type (#6433) ([81bb68d](https://github.com/discordjs/discord.js/commit/81bb68d3beb266fb0b508da959468a3a6f11c24c))
- Message#\_patch typings return type (#6433) ([81bb68d](https://github.com/discordjs/discord.js/commit/81bb68d3beb266fb0b508da959468a3a6f11c24c))
# [13.1.0](https://github.com/discordjs/discord.js/compare/13.0.1...13.1.0) - (2021-08-12)
@@ -505,7 +526,7 @@ All notable changes to this project will be documented in this file.
- **GuildChannel:** Improve empty overwrite handling for permissionsLocked (#5821) ([6df3623](https://github.com/discordjs/discord.js/commit/6df36232a05e396d31461200725755745526d2ed))
- **ApplicationCommands:** Allow managing commands for uncached guilds (#5729) ([24e5868](https://github.com/discordjs/discord.js/commit/24e586881865c187ff0a3044ac37f6e338cc51ee))
- **ClientApplication:** Freeze flags (#5811) ([e990c35](https://github.com/discordjs/discord.js/commit/e990c35476fb6f7e1a5449493833140144e0469c))
- ***:** Typedefs and typings for image & webhook options (#5805) ([a5a6e22](https://github.com/discordjs/discord.js/commit/a5a6e223166cf9af430da9003780e6582ea17b1c))
- **\*:** Typedefs and typings for image & webhook options (#5805) ([a5a6e22](https://github.com/discordjs/discord.js/commit/a5a6e223166cf9af430da9003780e6582ea17b1c))
- **TextBasedChannel:** Allow passing an APIMessage with split (#5815) ([93b0a4e](https://github.com/discordjs/discord.js/commit/93b0a4e005b5b1d371f7936238556db2e36cc982))
- **PermissionOverwrites:** Optional allow/deny OverwriteData (#5810) ([a7ebb21](https://github.com/discordjs/discord.js/commit/a7ebb2145c380214567514906393c4ab87932e95))
- **Typings:** Fix BitField toJSON/valueOf return types (#5806) ([935f819](https://github.com/discordjs/discord.js/commit/935f819207ac4219d37f3b99a2508e368626e6da))
@@ -520,7 +541,7 @@ All notable changes to this project will be documented in this file.
- **ApiMessage:** Only pass objects as options directly (#5793) ([3578159](https://github.com/discordjs/discord.js/commit/35781597d032fa7821e010e483c89f70ec51926c))
- **BitField:** Throw an error if bit to resolve is undefined (#5565) ([0156f69](https://github.com/discordjs/discord.js/commit/0156f693e08fe2ad75133bf67c4aeb3e9c91a02d))
- Remove remnants of awaitMessageComponentInteractions (#5783) ([ae78a33](https://github.com/discordjs/discord.js/commit/ae78a336e1d0d190ec9f525449332dc781e0b3bf))
- ***:** Add missing imports for custom errors (#5767) ([e980948](https://github.com/discordjs/discord.js/commit/e980948de55e91e59c9e3293ac76bc645a058a53))
- **\*:** Add missing imports for custom errors (#5767) ([e980948](https://github.com/discordjs/discord.js/commit/e980948de55e91e59c9e3293ac76bc645a058a53))
- **ShardingManager:** Client error event cannot be emitted (#5559) ([d1c5b6f](https://github.com/discordjs/discord.js/commit/d1c5b6fe9e18b532ad69ed4bd82e1874a6dff4df))
- Add components to MessageOption typedefs (#5768) ([657635c](https://github.com/discordjs/discord.js/commit/657635c1c09aa68211130bc3c56d6e8bb6e8e773))
- **Interaction:** Add missing types and fix docs lists (#5762) ([1d57754](https://github.com/discordjs/discord.js/commit/1d57754d4654c5c95aa14afc13f8abe335314767))
@@ -572,7 +593,7 @@ All notable changes to this project will be documented in this file.
- **GuildChannel:** Regression on default channel type (#5251) ([e7c4f36](https://github.com/discordjs/discord.js/commit/e7c4f3672e7059c264ba67a94b87a655ea6e4da5))
- **Guild/GuildChannel:** Methods reason arg usage (#5419) ([8411b9e](https://github.com/discordjs/discord.js/commit/8411b9e14211f83fddb00f622088979ee6586803))
- **Role:** Pass Permissions class, not the bitfield (#5321) ([d744e51](https://github.com/discordjs/discord.js/commit/d744e51c1bdb4c7a26c0faeea1f2f45baaf5fd3c))
- **WebSocketShard:** Key name in WebSocketShard#_send. (#5304) ([56d8b44](https://github.com/discordjs/discord.js/commit/56d8b445ede6c7915aec173a68905cda3d91f0ca))
- **WebSocketShard:** Key name in WebSocketShard#\_send. (#5304) ([56d8b44](https://github.com/discordjs/discord.js/commit/56d8b445ede6c7915aec173a68905cda3d91f0ca))
- **ApiMessage:** Remove resolve() from typings (#5241) ([a6bc39d](https://github.com/discordjs/discord.js/commit/a6bc39d3c699eec0b7851cda334335baa892c1de))
- **GuildChannel:** Overload permissionsFor and BaseManager#resolve[id] (#5260) ([41bd6c2](https://github.com/discordjs/discord.js/commit/41bd6c2717faeeaa36514d39a4816f7cf65b4c02))
- **GuildEmoji:** Check for cahnges to available in equals (#5201) ([f95f5dc](https://github.com/discordjs/discord.js/commit/f95f5dcd791b39c6a4d60dc8d64b0287e06ed768))
@@ -590,7 +611,7 @@ All notable changes to this project will be documented in this file.
- **Collector:** Throw an error if a non-function was provided as filter (#5034) ([7365f40](https://github.com/discordjs/discord.js/commit/7365f403006eeb28ab10f03cbf85416272678ef7))
- **BaseGuildEmoji:** Typo in requiresColons (#5076) ([e272fd6](https://github.com/discordjs/discord.js/commit/e272fd6909a17941d2d3e4840e75436d98a41198))
- **MessageReaction:** Set MessageReaction#me in patch method (#5047) ([6b322f4](https://github.com/discordjs/discord.js/commit/6b322f47a0f86115dab71c06c7879fe82ea04ec4))
- **Voice*:** Filter out silent audio from video users (#5035) ([4fcb9eb](https://github.com/discordjs/discord.js/commit/4fcb9ebf300633022e2b9867fa06a586307ff17a))
- **Voice\*:** Filter out silent audio from video users (#5035) ([4fcb9eb](https://github.com/discordjs/discord.js/commit/4fcb9ebf300633022e2b9867fa06a586307ff17a))
- **GuildTemplate:** 'guild' getter (#5040) ([53529bd](https://github.com/discordjs/discord.js/commit/53529bd05deb449d5d9bbfa332470c9881d8093c))
- **RoleManager:** Fix ID return value, change return type to collection (#4935) ([12a096b](https://github.com/discordjs/discord.js/commit/12a096b5f1c5ad518e73d1b9f50bb388928117dd))
@@ -601,7 +622,7 @@ All notable changes to this project will be documented in this file.
- General cleanup and improvements (#6299) ([b4afcf8](https://github.com/discordjs/discord.js/commit/b4afcf8236b0fb4979deab0a097656292c59d50b))
- Typo in ClientOptions (#6305) ([dd3a79e](https://github.com/discordjs/discord.js/commit/dd3a79eead4f01094c2c3003de717affc11fdc3c))
- Grammar fix (#6294) ([90c2e07](https://github.com/discordjs/discord.js/commit/90c2e072bf0ab3562bd65e3a9e5e19f5c57fd69a))
- **Client:** Mark _finalize as private (#6281) ([35fa3b3](https://github.com/discordjs/discord.js/commit/35fa3b3103998f93253a97ad1769212d60307b61))
- **Client:** Mark \_finalize as private (#6281) ([35fa3b3](https://github.com/discordjs/discord.js/commit/35fa3b3103998f93253a97ad1769212d60307b61))
- Update link of the guide to v13 changes (#6273) ([6e0ea02](https://github.com/discordjs/discord.js/commit/6e0ea020c0de580911917c4b480c3402619d4341))
- Add missing semicolon to readme (#6270) ([2c452df](https://github.com/discordjs/discord.js/commit/2c452dffb8204868ec4d7126f1345a14edb5c141))
- Change example in readme to slash command (#6250) ([626ff85](https://github.com/discordjs/discord.js/commit/626ff85ae7616a59c95d7338c0df9baead412ce3))
@@ -626,10 +647,10 @@ All notable changes to this project will be documented in this file.
- **MessageManager:** Document options param for #edit as required (#6031) ([db60e36](https://github.com/discordjs/discord.js/commit/db60e367b4a455ae0055f8d25bd8b42139784c55))
- Add Partial typedef (#6029) ([b62d646](https://github.com/discordjs/discord.js/commit/b62d6462711cd6a8fda5cb031d052dd343a2c3c0))
- Fix some missed MessageComponent collector methods (#6023) ([610b0b4](https://github.com/discordjs/discord.js/commit/610b0b4dd6b6e66c05c22eb852d2a752b99d07ba))
- ***:** Wrap optional properties with union types in parentheses (#6021) ([ec06ba7](https://github.com/discordjs/discord.js/commit/ec06ba7ad04d21e61f3e734e489607a1a5ab3568))
- **\*:** Wrap optional properties with union types in parentheses (#6021) ([ec06ba7](https://github.com/discordjs/discord.js/commit/ec06ba7ad04d21e61f3e734e489607a1a5ab3568))
- **Collector:** Properly document endReason (#6016) ([7dd1a8d](https://github.com/discordjs/discord.js/commit/7dd1a8da08830525d292059ee3bd2c86d5f964f6))
- **CreateInviteOptions:** Fix TargetType link (#6017) ([4adfc45](https://github.com/discordjs/discord.js/commit/4adfc45b5a3c916ae44aec5df358f0ca4254f723))
- ***:** Add class links to isX() methods (#6007) ([fbdad6e](https://github.com/discordjs/discord.js/commit/fbdad6eac38e262a7045853174607c408cd6c59c))
- **\*:** Add class links to isX() methods (#6007) ([fbdad6e](https://github.com/discordjs/discord.js/commit/fbdad6eac38e262a7045853174607c408cd6c59c))
- WebSocketShard#send and TextBasedChannel#send (#5998) ([726073f](https://github.com/discordjs/discord.js/commit/726073fef7e0e7bf7d8d5e4a4546d8056719b59f))
- **Util:** Methods removed on the base object (#5990) ([d742814](https://github.com/discordjs/discord.js/commit/d742814686fc2c8dfbdcb582541155cb8df170ac))
- **Partials:** Add link to the guide (#5982) ([58183d4](https://github.com/discordjs/discord.js/commit/58183d425ba5c2cc87f29199e5c3e2ec5a936bd1))
@@ -644,7 +665,7 @@ All notable changes to this project will be documented in this file.
- **Channel:** Make the type news_thread an inline code-block (#5940) ([630432b](https://github.com/discordjs/discord.js/commit/630432b4e2f415b912754962948edf585aebf772))
- **Thread:** Add links to discord api docs (#5919) ([5af2ef5](https://github.com/discordjs/discord.js/commit/5af2ef5fbc7ad11281f38384c360ae79efe63b39))
- **MessageSelectMenu:** Fix options typings (#5922) ([75837a8](https://github.com/discordjs/discord.js/commit/75837a8252246b2bb71b76f5b15b8124cb40f0d8))
- ***:** Add links to Discord's API objects & data (#5862) ([e0efcc6](https://github.com/discordjs/discord.js/commit/e0efcc6ab0e3f060e30438c0d990c9465c6134df))
- **\*:** Add links to Discord's API objects & data (#5862) ([e0efcc6](https://github.com/discordjs/discord.js/commit/e0efcc6ab0e3f060e30438c0d990c9465c6134df))
- Move embeds field into BaseMessageOptions (#5902) ([6cebeae](https://github.com/discordjs/discord.js/commit/6cebeae15e97e29acbdaf95bc7b17a1e346a2c34))
- **Readme:** Remove dependencies badge (#5901) ([edf6f0c](https://github.com/discordjs/discord.js/commit/edf6f0ca7012b6b678367a1b5d716d0b85e23ba3))
- **AnonymousGuild:** Add missing extends tag (#5896) ([3d96a33](https://github.com/discordjs/discord.js/commit/3d96a33bd006d514829648d166e86d15bf0b51c8))
@@ -743,16 +764,16 @@ All notable changes to this project will be documented in this file.
- **WelcomeScreen:** Welcome screens (#5490) ([44e2ee7](https://github.com/discordjs/discord.js/commit/44e2ee7b20dbec79c993dbc1f30ddb643d943347))
- Stage instance invite (#5856) ([2d12db0](https://github.com/discordjs/discord.js/commit/2d12db000f2a0a22a8919d7a63989a6e762ae335))
- **Guild:** Add enum for premium_tier (#5868) ([a3cbcca](https://github.com/discordjs/discord.js/commit/a3cbcca13da1af416c219bd64a0a6e84bb87a057))
- ***:** Use enums for consistency and speed (#5843) ([f7eeccb](https://github.com/discordjs/discord.js/commit/f7eeccba4b7015496df811f10cc2da2b0fab0630))
- **\*:** Use enums for consistency and speed (#5843) ([f7eeccb](https://github.com/discordjs/discord.js/commit/f7eeccba4b7015496df811f10cc2da2b0fab0630))
- **Widget:** Wrapper for widget.json (#5619) ([038ee99](https://github.com/discordjs/discord.js/commit/038ee99604cded41d4c67edf4bd6bc7969712f52))
- Stage instances (#5749) ([918921e](https://github.com/discordjs/discord.js/commit/918921e8211fc16e9b12d2502f3168264246ea22))
- ***:** Document and support embeds field in message create endpoint (#5792) ([99ff715](https://github.com/discordjs/discord.js/commit/99ff7151379fe03a1cfd52f252c0e6fc892d7776))
- **\*:** Document and support embeds field in message create endpoint (#5792) ([99ff715](https://github.com/discordjs/discord.js/commit/99ff7151379fe03a1cfd52f252c0e6fc892d7776))
- **Guild:** Add enum for mfa_level (#5797) ([ffabec3](https://github.com/discordjs/discord.js/commit/ffabec3a5e3651e5a0b8bcac83ee26bb909695fa))
- **RequestHandler:** Emit more info when a rate limit was hit (#5801) ([18ac72e](https://github.com/discordjs/discord.js/commit/18ac72e457fa137d7f7f7bde876436ff643b4a63))
- Add new APIErrors (#5794) ([e0ab836](https://github.com/discordjs/discord.js/commit/e0ab836b2d88caf0d9e1f9eba76ae46be9df0554))
- **Util:** Allow array for StringOptions' char (#5566) ([fbcbb29](https://github.com/discordjs/discord.js/commit/fbcbb29884a35308a7af2169f5f9ae5658c458e8))
- **GuildAuditLogs:** Make #target a channel for channel related logs (#5781) ([eb0291d](https://github.com/discordjs/discord.js/commit/eb0291d9a5078836183c1b63ea96461ec112f96e))
- **Sharding*:** Contexts for broadcastEval (#5756) ([c6aeebb](https://github.com/discordjs/discord.js/commit/c6aeebb18d6b969f7c8bdb1b719883d4384dd03e))
- **Sharding\*:** Contexts for broadcastEval (#5756) ([c6aeebb](https://github.com/discordjs/discord.js/commit/c6aeebb18d6b969f7c8bdb1b719883d4384dd03e))
- **Voice:** Implement support for @discordjs/voice (#5402) ([7b2e12b](https://github.com/discordjs/discord.js/commit/7b2e12b102984abf61132e1057558ef7f04e6d83))
- General component improvements (#5787) ([c4f1c75](https://github.com/discordjs/discord.js/commit/c4f1c75efa1cff1f9c775a266dccbe581305e79d))
- **GuildChannelManager:** Add 'fetch' method (#4966) ([e798fb7](https://github.com/discordjs/discord.js/commit/e798fb720ee5ced008471fe899337f6817936770))
@@ -765,7 +786,7 @@ All notable changes to this project will be documented in this file.
- **Esm:** Use `gen-esm-wrapper` instead of manually making the file (#5700) ([db0d7d4](https://github.com/discordjs/discord.js/commit/db0d7d4ea8e7b2bae4d1548e5617875b5ae0bbd4))
- **Rest:** Show the data that is sent to Discord when an errors occurs (#5701) ([ef92339](https://github.com/discordjs/discord.js/commit/ef92339d073f82cdaa2bc69f7be8443ec16789a7))
- **CommandInteraction:** Make options a collection (#5705) ([fdad140](https://github.com/discordjs/discord.js/commit/fdad14099779e61cb84dcd1cb2497e0e853a6144))
- [**breaking**] ***:** Enforce strings (#4880) ([7b85a72](https://github.com/discordjs/discord.js/commit/7b85a7259f563ab14ae6c0a665a3dd43c486fde4))
- [**breaking**] **\*:** Enforce strings (#4880) ([7b85a72](https://github.com/discordjs/discord.js/commit/7b85a7259f563ab14ae6c0a665a3dd43c486fde4))
- **Message:** Allow editing files into messages (#5718) ([b212b64](https://github.com/discordjs/discord.js/commit/b212b64214ecee4f6118e78f9b90f3d3da574ecc))
- Easier guards for channelUpdate (#5716) ([d52bcd4](https://github.com/discordjs/discord.js/commit/d52bcd46ec5985f9f18da37ba9d7d77209f58337))
- Add support for fetching multiple guilds (#5472) ([48d6850](https://github.com/discordjs/discord.js/commit/48d6850d9a8c34f407a22b6b401f2ed74415acd0))
@@ -813,8 +834,8 @@ All notable changes to this project will be documented in this file.
- Jsdelivr default file support (#5424) ([f469402](https://github.com/discordjs/discord.js/commit/f46940228e9f82db4af09ae2f2dad684db0d74ed))
- **Client:** Add InviteGenerationOptions#additionalScopes (#5215) ([ae3c3d8](https://github.com/discordjs/discord.js/commit/ae3c3d80ee603fc46a28140107cb90c81da0afc9))
- **ReactionCollector:** Event create (#4108) ([09d1f2f](https://github.com/discordjs/discord.js/commit/09d1f2f18f5ec536bb25156553986fee51c80d1e))
- **ShardingManager:** Allow b-Eval/fetchClientValues on a specific shard when not all are ready (#5222) ([001676c](https://github.com/discordjs/discord.js/commit/001676c7a97f4e44c6601dd84aa0354ea94b7c25))
- **GuildChannel:** Support conversion between text and news (#5022) ([5ac3b57](https://github.com/discordjs/discord.js/commit/5ac3b57f9bd53d1c20549a70942b023826f6f726))
- **ShardingManager:** Allow b-Eval/fetchClientValues on a specific shard when not all are ready (#5222) ([001676c](https://github.com/discordjs/discord.js/commit/001676c7a97f4e44c6601dd84aa0354ea94b7c25))
- **GuildChannel:** Support conversion between text and news (#5022) ([5ac3b57](https://github.com/discordjs/discord.js/commit/5ac3b57f9bd53d1c20549a70942b023826f6f726))
- **BitField:** Move problematic bit into the error message (#5228) ([273e955](https://github.com/discordjs/discord.js/commit/273e9557be68eb1c2466f29e1c41e9b146a777c1))
- **ClientEvents:** Add tuple labels to event arguments (#5225) ([764966e](https://github.com/discordjs/discord.js/commit/764966e398e693a5ec868bc22d722f8518656b3a))
- **GuildMember:** #pending (#5121) ([c4c8171](https://github.com/discordjs/discord.js/commit/c4c817116f868cedb4ec20bcbf90b9b3d382621e))
@@ -836,7 +857,7 @@ All notable changes to this project will be documented in this file.
- **Channels:** Fix incorrectly shared properties (#6262) ([5be471b](https://github.com/discordjs/discord.js/commit/5be471b47dd65616e6b3ee8afdc4a395ef60e1cc))
- Added `TextBasedChannels` type (#6286) ([61db5f7](https://github.com/discordjs/discord.js/commit/61db5f7618e30c0502ceb6484a4fe861542088b7))
- **MessageComponents:** Default setDisabled to true (#6279) ([3c7c822](https://github.com/discordjs/discord.js/commit/3c7c82292a914eb9bb9eb77c08a78f0861330687))
- ***:** Use async functions (#6210) ([e2e4f65](https://github.com/discordjs/discord.js/commit/e2e4f6518b3be85b1e05efff108f1459cc3082df))
- **\*:** Use async functions (#6210) ([e2e4f65](https://github.com/discordjs/discord.js/commit/e2e4f6518b3be85b1e05efff108f1459cc3082df))
- **GuildChannel:** Use filter method for #members (#6253) ([7c54076](https://github.com/discordjs/discord.js/commit/7c540764f05cf0a7d312e468f828f427ec0f7541))
- **VoiceState:** Change kick to disconnect (#6251) ([24931d7](https://github.com/discordjs/discord.js/commit/24931d713b947a568bb45a327bd6ba29966266b2))
- Merge collections with keeping entries at max (#6242) ([bb5e648](https://github.com/discordjs/discord.js/commit/bb5e648f3daa4c34ad8379eb095a25d56ebfc242))
@@ -856,7 +877,7 @@ All notable changes to this project will be documented in this file.
- Remove timer utilities from Client (#6113) ([5ca97c9](https://github.com/discordjs/discord.js/commit/5ca97c93515d4dfaa2b4951a020abc000115ed4d))
- Remove typing caching (#6114) ([576eee8](https://github.com/discordjs/discord.js/commit/576eee8de26bf9e62f5487f6e25e9d5f5eaaa882))
- **Channel:** Change channel types to UPPER_CASE (#6035) ([6301728](https://github.com/discordjs/discord.js/commit/6301728d35cfdc8b3ea62db5f73298de99a0902a))
- **Managers:** Rename add to _add (#6060) ([9cd5e7e](https://github.com/discordjs/discord.js/commit/9cd5e7ed6104e40c038d17456abd0cc4a3778b9e))
- **Managers:** Rename add to \_add (#6060) ([9cd5e7e](https://github.com/discordjs/discord.js/commit/9cd5e7ed6104e40c038d17456abd0cc4a3778b9e))
- **ApplicationCommandManager:** Remove unused assignment (#6063) ([98a5b52](https://github.com/discordjs/discord.js/commit/98a5b52d8bb09ccca5c30d6ab583bc72d3f1b6ff))
- Rename `Constants.OPCode` to `Opcode`, moved objects to enums (#6065) ([4eb3a2a](https://github.com/discordjs/discord.js/commit/4eb3a2a885efd480a953a23c5e5289912364ccd4))
- **PresenceManager:** Have Presence extend Base and simplify add (#6056) ([ded93fe](https://github.com/discordjs/discord.js/commit/ded93feb5759ded880ab0f00ffc2ecffa8516bb9))
@@ -876,7 +897,7 @@ All notable changes to this project will be documented in this file.
- Remove exported shortcuts to util methods (#5904) ([1816a93](https://github.com/discordjs/discord.js/commit/1816a93b1b1b2bae47e8651e76fa53699de8421d))
- **Package:** Remove `runkitExampleFilename` (#5866) ([6cceb93](https://github.com/discordjs/discord.js/commit/6cceb936a796e044488e188b5939b81b11e69d23))
- **awaitMessageComponentInteraction:** Use options object for lib consistency (#5852) ([9dda9b7](https://github.com/discordjs/discord.js/commit/9dda9b742f68dae6b2b260edcb1e5f627424693d))
- ***:** Make typedefs for all options params (#5785) ([1ac9a2e](https://github.com/discordjs/discord.js/commit/1ac9a2eb5bfef6d009de7c54d3fac5e3d4a5afdc))
- **\*:** Make typedefs for all options params (#5785) ([1ac9a2e](https://github.com/discordjs/discord.js/commit/1ac9a2eb5bfef6d009de7c54d3fac5e3d4a5afdc))
- **GuildPreviewEmoji:** Make roles an array (#5720) ([4dbcaf7](https://github.com/discordjs/discord.js/commit/4dbcaf76c361b2e63e9deb08556da43ecde7909e))
- **APIMessage:** Remove unused declarations (#5836) ([02693bc](https://github.com/discordjs/discord.js/commit/02693bc02f45980d8165820a103220f0027b96b7))
- Fetch options consistency (#5824) ([7111b4c](https://github.com/discordjs/discord.js/commit/7111b4cd5f2690e7b6c6626025c2a6041bd64db2))
@@ -887,9 +908,9 @@ All notable changes to this project will be documented in this file.
- Enforce single param on sending/editing methods (#5758) ([0467a90](https://github.com/discordjs/discord.js/commit/0467a9075fbba538c56e0cffdd2da11f7867516a))
- GuildAvailable, typingStop from Constants (#4861) ([dda5ee2](https://github.com/discordjs/discord.js/commit/dda5ee2e9f0839d3e42d25114ae1b47355cdfd27))
- **Interactions:** Move Structures import out of switch block (#5763) ([84e5b07](https://github.com/discordjs/discord.js/commit/84e5b075b4214c5432e380840c90091643af07fa))
- Remove _roles from pseudo-managers (#5721) ([53d952a](https://github.com/discordjs/discord.js/commit/53d952a4ce049cd1b88d2ef4dc3dcdae487b8f00))
- Remove \_roles from pseudo-managers (#5721) ([53d952a](https://github.com/discordjs/discord.js/commit/53d952a4ce049cd1b88d2ef4dc3dcdae487b8f00))
- **Deps:** Use async-queue package (#5662) ([14c6802](https://github.com/discordjs/discord.js/commit/14c6802438c47a42ecb5daeb59442361ceb69213))
- ***:** Return the invalid element when erroring from Array (#5314) ([eaf332f](https://github.com/discordjs/discord.js/commit/eaf332f83fd4376f1cee6d2c9f0939395e84740c))
- **\*:** Return the invalid element when erroring from Array (#5314) ([eaf332f](https://github.com/discordjs/discord.js/commit/eaf332f83fd4376f1cee6d2c9f0939395e84740c))
- **MessageOptions:** Move replyTo to reply#messageReference and add failIfNotExists (#5298) ([1ecda83](https://github.com/discordjs/discord.js/commit/1ecda83da7953052977e6297143b82f89adf1058))
- **Sticker:** Rename Snowflake variable (#5575) ([af00ec8](https://github.com/discordjs/discord.js/commit/af00ec8970e77ea8a0afd21571eeeef9c554e1ec))
- **RequestHandler:** Use x-ratelimit-reset-after when present (#5511) ([a5d41c9](https://github.com/discordjs/discord.js/commit/a5d41c9f6c4adc652f56c55da4f05da63873c9ef))
@@ -934,12 +955,12 @@ All notable changes to this project will be documented in this file.
- **GuildInviteManager:** FetchInvitesOptions (#6076) ([c1eaa78](https://github.com/discordjs/discord.js/commit/c1eaa78ab7cef55f2a4dcb36d0876963d42ef1ec))
- Fixed unreachable overloads (#6062) ([7322547](https://github.com/discordjs/discord.js/commit/7322547172e2d34bd04ef131db277801fccf7f99))
- **ApplicationCommand:** Fix option name (#6067) ([58bbcd5](https://github.com/discordjs/discord.js/commit/58bbcd591e01894594dffba8bdafb95c99670fb1))
- ***:** Revert incorrect unknown type changes (#6057) ([2e078e4](https://github.com/discordjs/discord.js/commit/2e078e44883c1ef5f85ef973d61a305ce2a34251))
- **\*:** Revert incorrect unknown type changes (#6057) ([2e078e4](https://github.com/discordjs/discord.js/commit/2e078e44883c1ef5f85ef973d61a305ce2a34251))
- **Options:** Should extend null (#6042) ([c4aa9fe](https://github.com/discordjs/discord.js/commit/c4aa9feee238db453c87cb66e054922a8302c355))
- **Voice:** Move types to the library's definitions (#6041) ([185e376](https://github.com/discordjs/discord.js/commit/185e37602b0fabf6f06a02886128aead9239c5d9))
- Better fullPermissions typings (#6028) ([2ab32e6](https://github.com/discordjs/discord.js/commit/2ab32e6bc62a5326daab6a7472075730830ef109))
- **MessageOptions:** Fix components being optional (#6005) ([56b5b7e](https://github.com/discordjs/discord.js/commit/56b5b7ee820c8be36c6d7de0abedf1753cc591dd))
- ***:** Create mention types (#6003) ([0dc5dd5](https://github.com/discordjs/discord.js/commit/0dc5dd5808af213ac4ede9f1084b522225a5c661))
- **\*:** Create mention types (#6003) ([0dc5dd5](https://github.com/discordjs/discord.js/commit/0dc5dd5808af213ac4ede9f1084b522225a5c661))
- **VoiceState:** Fix optional params (#5993) ([1242c54](https://github.com/discordjs/discord.js/commit/1242c5434d441f3f7e0ed4610a9a0815a70072ba))
- **ClientUser:** Updated `setAFK` signature (#6011) ([c40b06c](https://github.com/discordjs/discord.js/commit/c40b06cac90b02f01e198e42c7a8f38de27f15c8))
- **MessageSelectMenu:** Fix typings (#5995) ([fe6cc0c](https://github.com/discordjs/discord.js/commit/fe6cc0c15dde99caa1049d35f75b9335ace1721d))
@@ -948,7 +969,7 @@ All notable changes to this project will be documented in this file.
- **MessageOptions:** Improved component typings (#5987) ([0eeb277](https://github.com/discordjs/discord.js/commit/0eeb2775a52b0db7f403afb7029d70897fe7d30a))
- **ApplicationCommandPermissionsManager:** Fix types (#5979) ([388e05b](https://github.com/discordjs/discord.js/commit/388e05b4af95cf2581abae90c6d05d59a0cdb4d2))
- **ThreadChannel:** Make locked and archived param optional (#5980) ([a08ce7d](https://github.com/discordjs/discord.js/commit/a08ce7dddb5f056128488392742495398f9e33b5))
- ***:** Make hex color types compatible with ColorResolvable (#5973) ([788d58e](https://github.com/discordjs/discord.js/commit/788d58e5a32956bbcf4768f69ff320b0d7873a6a))
- **\*:** Make hex color types compatible with ColorResolvable (#5973) ([788d58e](https://github.com/discordjs/discord.js/commit/788d58e5a32956bbcf4768f69ff320b0d7873a6a))
- **CommandInteraction:** Readd followUp type (#5974) ([ae37d20](https://github.com/discordjs/discord.js/commit/ae37d202a53a05e8bba4d6df9016d0f0a7682c6b))
- **ThreadManager:** Add type to ThreadManager#create options (#5969) ([3174507](https://github.com/discordjs/discord.js/commit/3174507d57d9f6011e97b4f3209f42179e050f9b))
- **ColorResolvable:** Change `string` to `#${string}` (#5950) ([acdcb90](https://github.com/discordjs/discord.js/commit/acdcb906ae4691374f5d2bda1315a484c8674938))

View File

@@ -8,7 +8,7 @@
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/workflows/Testing/badge.svg" alt="Tests status" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
</p>
</div>
@@ -24,7 +24,7 @@ discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to
## Installation
**Node.js 16.6.0 or newer is required.**
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install discord.js
@@ -38,7 +38,7 @@ pnpm add discord.js
- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`)
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
- [@discordjs/voice](https://github.com/discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
## Example usage

View File

@@ -0,0 +1,62 @@
[changelog]
header = """
# Changelog
All notable changes to this project will be documented in this file.\n
"""
body = """
{% if version %}\
# [{{ version | trim_start_matches(pat="v") }}]\
{% if previous %}\
{% if previous.version %}\
(https://github.com/discordjs/discord.js/compare/{{ previous.version }}...{{ version }})\
{% else %}
(https://github.com/discordjs/discord.js/tree/{{ version }})\
{% endif %}\
{% endif %} \
- ({{ timestamp | date(format="%Y-%m-%d") }})
{% else %}\
# [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
## {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}\
[**breaking**] \
{% endif %}\
{% if commit.scope %}\
**{{commit.scope}}:** \
{% endif %}\
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/discordjs/discord.js/commit/{{ commit.id }}))\
{% endfor %}
{% endfor %}\n
"""
trim = true
footer = ""
[git]
conventional_commits = true
filter_unconventional = true
commit_parsers = [
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^docs", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^refactor", group = "Refactor"},
{ message = "^typings", group = "Typings"},
{ message = "^types", group = "Typings"},
{ message = ".*deprecated", body = ".*deprecated", group = "Deprecation"},
{ message = "^revert", skip = true},
{ message = "^style", group = "Styling"},
{ message = "^test", group = "Testing"},
{ message = "^chore", skip = true},
{ message = "^ci", skip = true},
{ message = "^build", skip = true},
{ body = ".*security", group = "Security"},
]
filter_commits = true
tag_pattern = "[0-9]*"
skip_tags = "v[0-9]*|11|12|@discordjs"
ignore_tags = ""
topo_order = false
sort_commits = "newest"

View File

@@ -3,16 +3,14 @@
"version": "14.0.0-dev",
"description": "A powerful library for interacting with the Discord API",
"scripts": {
"test": "yarn docs:test && yarn lint:typings && yarn test:typescript",
"test": "yarn docs:test && yarn test:typescript",
"test:typescript": "tsc --noEmit && tsd",
"lint": "eslint ./src",
"lint:fix": "eslint ./src --fix",
"lint:typings": "tslint ./typings/index.d.ts",
"format": "prettier --write **/*.{ts,js,json,yml,yaml}",
"lint": "prettier --check . && eslint src && tslint typings/index.d.ts",
"format": "prettier --write . && eslint src --fix",
"docs": "docgen --source ./src --custom ./docs/index.yml --output ./docs/docs.json",
"docs:test": "docgen --source ./src --custom ./docs/index.yml",
"prepublishOnly": "yarn lint && yarn test",
"changelog": "git cliff --prepend ./CHANGELOG.md -l -c ../../cliff.toml -r ../../ --include-path './*'"
"changelog": "git cliff --prepend ./CHANGELOG.md -l -c ./cliff.toml -r ../../ --include-path 'packages/discord.js/*'"
},
"main": "./src/index.js",
"types": "./typings/index.d.ts",
@@ -52,31 +50,31 @@
"@discordjs/builders": "^0.11.0",
"@discordjs/collection": "^0.4.0",
"@sapphire/async-queue": "^1.1.9",
"@sapphire/snowflake": "^3.0.1",
"@types/node-fetch": "^2.5.12",
"@types/ws": "^8.2.2",
"discord-api-types": "^0.26.0",
"discord-api-types": "^0.26.1",
"form-data": "^4.0.0",
"node-fetch": "^2.6.1",
"ws": "^8.4.0"
"ws": "^8.4.2"
},
"devDependencies": {
"@discordjs/docgen": "^0.11.0",
"@types/node": "^16.11.12",
"dtslint": "^4.2.1",
"eslint": "^8.5.0",
"eslint": "^8.7.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.4",
"is-ci": "^3.0.1",
"jest": "^27.4.5",
"lint-staged": "^12.1.4",
"jest": "^27.4.7",
"prettier": "^2.5.1",
"tsd": "^0.19.0",
"tslint": "^6.1.3",
"typescript": "^4.5.4"
"typescript": "^4.5.5"
},
"engines": {
"node": ">=16.6.0"
"node": ">=16.9.0"
}
}

View File

@@ -1,6 +1,8 @@
'use strict';
const EventEmitter = require('node:events');
const { clearInterval } = require('node:timers');
const { TypeError } = require('../errors');
const RESTManager = require('../rest/RESTManager');
const Options = require('../util/Options');
const Util = require('../util/Util');
@@ -11,7 +13,11 @@ const Util = require('../util/Util');
*/
class BaseClient extends EventEmitter {
constructor(options = {}) {
super();
super({ captureRejections: true });
if (typeof options !== 'object' || options === null) {
throw new TypeError('INVALID_TYPE', 'options', 'object', true);
}
/**
* The options the client was instantiated with

View File

@@ -1,7 +1,6 @@
'use strict';
const process = require('node:process');
const { setInterval } = require('node:timers');
const { Collection } = require('@discordjs/collection');
const BaseClient = require('./BaseClient');
const ActionsManager = require('./actions/ActionsManager');
@@ -75,20 +74,6 @@ class Client extends BaseClient {
this._validateOptions();
/**
* Functions called when a cache is garbage collected or the Client is destroyed
* @type {Set<Function>}
* @private
*/
this._cleanups = new Set();
/**
* The finalizers used to cleanup items.
* @type {FinalizationRegistry}
* @private
*/
this._finalizers = new FinalizationRegistry(this._finalize.bind(this));
/**
* The WebSocket manager of the client
* @type {WebSocketManager}
@@ -177,22 +162,10 @@ class Client extends BaseClient {
this.application = null;
/**
* Time at which the client was last regarded as being in the `READY` state
* (each time the client disconnects and successfully reconnects, this will be overwritten)
* @type {?Date}
* Timestamp of the time the client was last `READY` at
* @type {?number}
*/
this.readyAt = null;
if (this.options.messageSweepInterval > 0) {
process.emitWarning(
'The message sweeping client options are deprecated, use the global sweepers instead.',
'DeprecationWarning',
);
this.sweepMessageInterval = setInterval(
this.sweepMessages.bind(this),
this.options.messageSweepInterval * 1_000,
).unref();
}
this.readyTimestamp = null;
}
/**
@@ -209,12 +182,13 @@ class Client extends BaseClient {
}
/**
* Timestamp of the time the client was last `READY` at
* @type {?number}
* Time at which the client was last regarded as being in the `READY` state
* (each time the client disconnects and successfully reconnects, this will be overwritten)
* @type {?Date}
* @readonly
*/
get readyTimestamp() {
return this.readyAt?.getTime() ?? null;
get readyAt() {
return this.readyTimestamp && new Date(this.readyTimestamp);
}
/**
@@ -223,7 +197,7 @@ class Client extends BaseClient {
* @readonly
*/
get uptime() {
return this.readyAt ? Date.now() - this.readyAt : null;
return this.readyTimestamp && Date.now() - this.readyTimestamp;
}
/**
@@ -275,11 +249,6 @@ class Client extends BaseClient {
destroy() {
super.destroy();
for (const fn of this._cleanups) fn();
this._cleanups.clear();
if (this.sweepMessageInterval) clearInterval(this.sweepMessageInterval);
this.sweepers.destroy();
this.ws.destroy();
this.token = null;
@@ -381,50 +350,6 @@ class Client extends BaseClient {
const data = await this.api('sticker-packs').get();
return new Collection(data.sticker_packs.map(p => [p.id, new StickerPack(this, p)]));
}
/**
* A last ditch cleanup function for garbage collection.
* @param {Function} options.cleanup The function called to GC
* @param {string} [options.message] The message to send after a successful GC
* @param {string} [options.name] The name of the item being GCed
* @private
*/
_finalize({ cleanup, message, name }) {
try {
cleanup();
this._cleanups.delete(cleanup);
if (message) {
this.emit(Events.DEBUG, message);
}
} catch {
this.emit(Events.DEBUG, `Garbage collection failed on ${name ?? 'an unknown item'}.`);
}
}
/**
* Sweeps all text-based channels' messages and removes the ones older than the max message lifetime.
* If the message has been edited, the time of the edit is used rather than the time of the original message.
* @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds)
* will be removed from the caches. The default is based on {@link ClientOptions#messageCacheLifetime}
* @returns {number} Amount of messages that were removed from the caches,
* or -1 if the message cache lifetime is unlimited
* @example
* // Remove all messages older than 1800 seconds from the messages cache
* const amount = client.sweepMessages(1800);
* console.log(`Successfully removed ${amount} messages from the cache.`);
*/
sweepMessages(lifetime = this.options.messageCacheLifetime) {
if (typeof lifetime !== 'number' || isNaN(lifetime)) {
throw new TypeError('INVALID_TYPE', 'lifetime', 'number');
}
if (lifetime <= 0) {
this.emit(Events.DEBUG, "Didn't sweep messages - lifetime is unlimited");
return -1;
}
const messages = this.sweepers.sweepMessages(Sweepers.outdatedMessageSweepFilter(lifetime)());
this.emit(Events.DEBUG, `Swept ${messages} messages older than ${lifetime} seconds`);
return messages;
}
/**
* Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds.
@@ -559,12 +484,6 @@ class Client extends BaseClient {
if (typeof options.makeCache !== 'function') {
throw new TypeError('CLIENT_INVALID_OPTION', 'makeCache', 'a function');
}
if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'The messageCacheLifetime', 'a number');
}
if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'messageSweepInterval', 'a number');
}
if (typeof options.sweepers !== 'object' || options.sweepers === null) {
throw new TypeError('CLIENT_INVALID_OPTION', 'sweepers', 'an object');
}
@@ -577,9 +496,6 @@ class Client extends BaseClient {
if (typeof options.waitGuildTimeout !== 'number' || isNaN(options.waitGuildTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'waitGuildTimeout', 'a number');
}
if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restWsBridgeTimeout', 'a number');
}
if (typeof options.restRequestTimeout !== 'number' || isNaN(options.restRequestTimeout)) {
throw new TypeError('CLIENT_INVALID_OPTION', 'restRequestTimeout', 'a number');
}
@@ -609,6 +525,19 @@ class Client extends BaseClient {
module.exports = Client;
/**
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
* except the epoch is 2015-01-01T00:00:00.000Z.
*
* If we have a snowflake '266241948824764416' we can represent it as binary:
* ```
* 64 22 17 12 0
* 000000111011000111100001101001000101000000 00001 00000 000000000000
* number of milliseconds since Discord epoch worker pid increment
* ```
* @typedef {string} Snowflake
*/
/**
* Emitted for general warnings.
* @event Client#warn

View File

@@ -30,7 +30,7 @@ class WebhookClient extends BaseClient {
if ('url' in data) {
const url = data.url.match(
// eslint-disable-next-line no-useless-escape
/^https?:\/\/(?:canary|ptb)?\.?discord\.com\/api\/webhooks(?:\/v[0-9]\d*)?\/([^\/]+)\/([^\/]+)/i,
/https?:\/\/(?:ptb\.|canary\.)?discord\.com\/api(?:\/v\d{1,2})?\/webhooks\/(\d{17,19})\/([\w-]{68})/i,
);
if (!url || url.length <= 1) throw new Error('WEBHOOK_URL_INVALID');

View File

@@ -1,29 +1,15 @@
'use strict';
const Action = require('./Action');
const { deletedChannels } = require('../../structures/Channel');
const DMChannel = require('../../structures/DMChannel');
const { deletedMessages } = require('../../structures/Message');
const { Events } = require('../../util/Constants');
class ChannelDeleteAction extends Action {
constructor(client) {
super(client);
this.deleted = new Map();
}
handle(data) {
const client = this.client;
const channel = client.channels.cache.get(data.id);
if (channel) {
client.channels._remove(channel.id);
deletedChannels.add(channel);
if (channel.messages && !(channel instanceof DMChannel)) {
for (const message of channel.messages.cache.values()) {
deletedMessages.add(message);
}
}
/**
* Emitted whenever a channel is deleted.
* @event Client#channelDelete
@@ -31,8 +17,6 @@ class ChannelDeleteAction extends Action {
*/
client.emit(Events.CHANNEL_DELETE, channel);
}
return { channel };
}
}

View File

@@ -2,7 +2,6 @@
const Action = require('./Action');
const { Channel } = require('../../structures/Channel');
const { ChannelTypes } = require('../../util/Constants');
class ChannelUpdateAction extends Action {
handle(data) {
@@ -12,7 +11,7 @@ class ChannelUpdateAction extends Action {
if (channel) {
const old = channel._update(data);
if (ChannelTypes[channel.type] !== data.type) {
if (channel.type !== data.type) {
const newChannel = Channel.create(this.client, data, channel.guild);
for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message);
channel = newChannel;

View File

@@ -1,16 +1,9 @@
'use strict';
const { setTimeout } = require('node:timers');
const Action = require('./Action');
const { deletedGuilds } = require('../../structures/Guild');
const { Events } = require('../../util/Constants');
class GuildDeleteAction extends Action {
constructor(client) {
super(client);
this.deleted = new Map();
}
handle(data) {
const client = this.client;
@@ -29,9 +22,7 @@ class GuildDeleteAction extends Action {
// Stops the GuildDelete packet thinking a guild was actually deleted,
// handles emitting of event itself
return {
guild: null,
};
return;
}
for (const channel of guild.channels.cache.values()) this.client.channels._remove(channel.id);
@@ -39,7 +30,6 @@ class GuildDeleteAction extends Action {
// Delete guild
client.guilds.cache.delete(guild.id);
deletedGuilds.add(guild);
/**
* Emitted whenever a guild kicks the client or the guild is deleted/left.
@@ -47,18 +37,7 @@ class GuildDeleteAction extends Action {
* @param {Guild} guild The guild that was deleted
*/
client.emit(Events.GUILD_DELETE, guild);
this.deleted.set(guild.id, guild);
this.scheduleForDeletion(guild.id);
} else {
guild = this.deleted.get(data.id) ?? null;
}
return { guild };
}
scheduleForDeletion(id) {
setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout).unref();
}
}

View File

@@ -1,13 +1,11 @@
'use strict';
const Action = require('./Action');
const { deletedEmojis } = require('../../structures/Emoji');
const { Events } = require('../../util/Constants');
class GuildEmojiDeleteAction extends Action {
handle(emoji) {
emoji.guild.emojis.cache.delete(emoji.id);
deletedEmojis.add(emoji);
/**
* Emitted whenever a custom emoji is deleted in a guild.
* @event Client#emojiDelete

View File

@@ -1,7 +1,6 @@
'use strict';
const Action = require('./Action');
const { deletedGuildMembers } = require('../../structures/GuildMember');
const { Events, Status } = require('../../util/Constants');
class GuildMemberRemoveAction extends Action {
@@ -13,7 +12,6 @@ class GuildMemberRemoveAction extends Action {
member = this.getMember({ user: data.user }, guild);
guild.memberCount--;
if (member) {
deletedGuildMembers.add(member);
guild.members.cache.delete(member.id);
/**
* Emitted whenever a member leaves a guild, or is kicked.

View File

@@ -1,7 +1,6 @@
'use strict';
const Action = require('./Action');
const { deletedRoles } = require('../../structures/Role');
const { Events } = require('../../util/Constants');
class GuildRoleDeleteAction extends Action {
@@ -14,7 +13,6 @@ class GuildRoleDeleteAction extends Action {
role = guild.roles.cache.get(data.role_id);
if (role) {
guild.roles.cache.delete(data.role_id);
deletedRoles.add(role);
/**
* Emitted whenever a guild role is deleted.
* @event Client#roleDelete

View File

@@ -1,13 +1,11 @@
'use strict';
const Action = require('./Action');
const { deletedStickers } = require('../../structures/Sticker');
const { Events } = require('../../util/Constants');
class GuildStickerDeleteAction extends Action {
handle(sticker) {
sticker.guild.stickers.cache.delete(sticker.id);
deletedStickers.add(sticker);
/**
* Emitted whenever a custom sticker is deleted in a guild.
* @event Client#stickerDelete

View File

@@ -1,16 +1,14 @@
'use strict';
const process = require('node:process');
const { InteractionType, ComponentType, ApplicationCommandType } = require('discord-api-types/v9');
const Action = require('./Action');
const AutocompleteInteraction = require('../../structures/AutocompleteInteraction');
const ButtonInteraction = require('../../structures/ButtonInteraction');
const CommandInteraction = require('../../structures/CommandInteraction');
const MessageContextMenuInteraction = require('../../structures/MessageContextMenuInteraction');
const ChatInputCommandInteraction = require('../../structures/ChatInputCommandInteraction');
const MessageContextMenuCommandInteraction = require('../../structures/MessageContextMenuCommandInteraction');
const SelectMenuInteraction = require('../../structures/SelectMenuInteraction');
const UserContextMenuInteraction = require('../../structures/UserContextMenuInteraction');
const { Events, InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../../util/Constants');
let deprecationEmitted = false;
const UserContextMenuCommandInteraction = require('../../structures/UserContextMenuCommandInteraction');
const { Events } = require('../../util/Constants');
class InteractionCreateAction extends Action {
handle(data) {
@@ -19,18 +17,18 @@ class InteractionCreateAction extends Action {
// Resolve and cache partial channels for Interaction#channel getter
this.getChannel(data);
let InteractionType;
let InteractionClass;
switch (data.type) {
case InteractionTypes.APPLICATION_COMMAND:
case InteractionType.ApplicationCommand:
switch (data.data.type) {
case ApplicationCommandTypes.CHAT_INPUT:
InteractionType = CommandInteraction;
case ApplicationCommandType.ChatInput:
InteractionClass = ChatInputCommandInteraction;
break;
case ApplicationCommandTypes.USER:
InteractionType = UserContextMenuInteraction;
case ApplicationCommandType.User:
InteractionClass = UserContextMenuCommandInteraction;
break;
case ApplicationCommandTypes.MESSAGE:
InteractionType = MessageContextMenuInteraction;
case ApplicationCommandType.Message:
InteractionClass = MessageContextMenuCommandInteraction;
break;
default:
client.emit(
@@ -40,13 +38,13 @@ class InteractionCreateAction extends Action {
return;
}
break;
case InteractionTypes.MESSAGE_COMPONENT:
case InteractionType.MessageComponent:
switch (data.data.component_type) {
case MessageComponentTypes.BUTTON:
InteractionType = ButtonInteraction;
case ComponentType.Button:
InteractionClass = ButtonInteraction;
break;
case MessageComponentTypes.SELECT_MENU:
InteractionType = SelectMenuInteraction;
case ComponentType.SelectMenu:
InteractionClass = SelectMenuInteraction;
break;
default:
client.emit(
@@ -56,15 +54,15 @@ class InteractionCreateAction extends Action {
return;
}
break;
case InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE:
InteractionType = AutocompleteInteraction;
case InteractionType.ApplicationCommandAutocomplete:
InteractionClass = AutocompleteInteraction;
break;
default:
client.emit(Events.DEBUG, `[INTERACTION] Received interaction with unknown type: ${data.type}`);
return;
}
const interaction = new InteractionType(client, data);
const interaction = new InteractionClass(client, data);
/**
* Emitted when an interaction is created.
@@ -72,17 +70,6 @@ class InteractionCreateAction extends Action {
* @param {Interaction} interaction The interaction which was created
*/
client.emit(Events.INTERACTION_CREATE, interaction);
/**
* Emitted when an interaction is created.
* @event Client#interaction
* @param {Interaction} interaction The interaction which was created
* @deprecated Use {@link Client#event:interactionCreate} instead
*/
if (client.emit('interaction', interaction) && !deprecationEmitted) {
deprecationEmitted = true;
process.emitWarning('The interaction event is deprecated. Use interactionCreate instead', 'DeprecationWarning');
}
}
}

View File

@@ -1,17 +1,14 @@
'use strict';
const process = require('node:process');
const Action = require('./Action');
const { Events } = require('../../util/Constants');
let deprecationEmitted = false;
class MessageCreateAction extends Action {
handle(data) {
const client = this.client;
const channel = this.getChannel(data);
if (channel) {
if (!channel.isText()) return {};
if (!channel.isTextBased()) return {};
const existing = channel.messages.cache.get(data.id);
if (existing) return { message: existing };
@@ -25,17 +22,6 @@ class MessageCreateAction extends Action {
*/
client.emit(Events.MESSAGE_CREATE, message);
/**
* Emitted whenever a message is created.
* @event Client#message
* @param {Message} message The created message
* @deprecated Use {@link Client#event:messageCreate} instead
*/
if (client.emit('message', message) && !deprecationEmitted) {
deprecationEmitted = true;
process.emitWarning('The message event is deprecated. Use messageCreate instead', 'DeprecationWarning');
}
return { message };
}

View File

@@ -1,7 +1,6 @@
'use strict';
const Action = require('./Action');
const { deletedMessages } = require('../../structures/Message');
const { Events } = require('../../util/Constants');
class MessageDeleteAction extends Action {
@@ -10,12 +9,11 @@ class MessageDeleteAction extends Action {
const channel = this.getChannel(data);
let message;
if (channel) {
if (!channel.isText()) return {};
if (!channel.isTextBased()) return {};
message = this.getMessage(data, channel);
if (message) {
channel.messages.cache.delete(message.id);
deletedMessages.add(message);
/**
* Emitted whenever a message is deleted.
* @event Client#messageDelete

View File

@@ -2,7 +2,6 @@
const { Collection } = require('@discordjs/collection');
const Action = require('./Action');
const { deletedMessages } = require('../../structures/Message');
const { Events } = require('../../util/Constants');
class MessageDeleteBulkAction extends Action {
@@ -11,7 +10,7 @@ class MessageDeleteBulkAction extends Action {
const channel = client.channels.cache.get(data.channel_id);
if (channel) {
if (!channel.isText()) return {};
if (!channel.isTextBased()) return {};
const ids = data.ids;
const messages = new Collection();
@@ -25,7 +24,6 @@ class MessageDeleteBulkAction extends Action {
false,
);
if (message) {
deletedMessages.add(message);
messages.set(message.id, message);
channel.messages.cache.delete(id);
}

View File

@@ -23,7 +23,7 @@ class MessageReactionAdd extends Action {
// Verify channel
const channel = this.getChannel(data);
if (!channel || !channel.isText()) return false;
if (!channel || !channel.isTextBased()) return false;
// Verify message
const message = this.getMessage(data, channel);

View File

@@ -20,7 +20,7 @@ class MessageReactionRemove extends Action {
// Verify channel
const channel = this.getChannel(data);
if (!channel || !channel.isText()) return false;
if (!channel || !channel.isTextBased()) return false;
// Verify message
const message = this.getMessage(data, channel);

View File

@@ -7,7 +7,7 @@ class MessageReactionRemoveAll extends Action {
handle(data) {
// Verify channel
const channel = this.getChannel(data);
if (!channel || !channel.isText()) return false;
if (!channel || !channel.isTextBased()) return false;
// Verify message
const message = this.getMessage(data, channel);

View File

@@ -6,7 +6,7 @@ const { Events } = require('../../util/Constants');
class MessageReactionRemoveEmoji extends Action {
handle(data) {
const channel = this.getChannel(data);
if (!channel || !channel.isText()) return false;
if (!channel || !channel.isTextBased()) return false;
const message = this.getMessage(data, channel);
if (!message) return false;

View File

@@ -6,7 +6,7 @@ class MessageUpdateAction extends Action {
handle(data) {
const channel = this.getChannel(data);
if (channel) {
if (!channel.isText()) return {};
if (!channel.isTextBased()) return {};
const { id, channel_id, guild_id, author, timestamp, type } = data;
const message = this.getMessage({ id, channel_id, guild_id, author, timestamp, type }, channel);

View File

@@ -6,10 +6,10 @@ const { Events } = require('../../util/Constants');
class PresenceUpdateAction extends Action {
handle(data) {
let user = this.client.users.cache.get(data.user.id);
if (!user && data.user?.username) user = this.client.users._add(data.user);
if (!user && data.user.username) user = this.client.users._add(data.user);
if (!user) return;
if (data.user?.username) {
if (data.user.username) {
if (!user._equals(data.user)) this.client.actions.UserUpdate.handle(data.user);
}

View File

@@ -1,7 +1,6 @@
'use strict';
const Action = require('./Action');
const { deletedStageInstances } = require('../../structures/StageInstance');
const { Events } = require('../../util/Constants');
class StageInstanceDeleteAction extends Action {
@@ -13,7 +12,6 @@ class StageInstanceDeleteAction extends Action {
const stageInstance = channel.guild.stageInstances._add(data);
if (stageInstance) {
channel.guild.stageInstances.cache.delete(stageInstance.id);
deletedStageInstances.add(stageInstance);
/**
* Emitted whenever a stage instance is deleted.

View File

@@ -1,8 +1,6 @@
'use strict';
const Action = require('./Action');
const { deletedChannels } = require('../../structures/Channel');
const { deletedMessages } = require('../../structures/Message');
const { Events } = require('../../util/Constants');
class ThreadDeleteAction extends Action {
@@ -12,10 +10,6 @@ class ThreadDeleteAction extends Action {
if (thread) {
client.channels._remove(thread.id);
deletedChannels.add(thread);
for (const message of thread.messages.cache.values()) {
deletedMessages.add(message);
}
/**
* Emitted whenever a thread is deleted.

View File

@@ -9,7 +9,7 @@ class TypingStart extends Action {
const channel = this.getChannel(data);
if (!channel) return;
if (!channel.isText()) {
if (!channel.isTextBased()) {
this.client.emit(Events.WARN, `Discord sent a typing packet to a ${channel.type} channel ${channel.id}`);
return;
}

View File

@@ -374,7 +374,7 @@ class WebSocketManager extends EventEmitter {
triggerClientReady() {
this.status = Status.READY;
this.client.readyAt = new Date();
this.client.readyTimestamp = Date.now();
/**
* Emitted when the client becomes ready to start working.

View File

@@ -1,7 +1,7 @@
'use strict';
const EventEmitter = require('node:events');
const { setTimeout, setInterval } = require('node:timers');
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('node:timers');
const WebSocket = require('../../WebSocket');
const { Status, Events, ShardEvents, Opcodes, WSEvents } = require('../../util/Constants');
const Intents = require('../../util/Intents');

View File

@@ -1,18 +0,0 @@
'use strict';
const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => {
const commandManager = data.guild_id ? client.guilds.cache.get(data.guild_id)?.commands : client.application.commands;
if (!commandManager) return;
const command = commandManager._add(data, data.application_id === client.application.id);
/**
* Emitted when a guild application command is created.
* @event Client#applicationCommandCreate
* @param {ApplicationCommand} command The command which was created
* @deprecated See {@link https://github.com/discord/discord-api-docs/issues/3690 this issue} for more information.
*/
client.emit(Events.APPLICATION_COMMAND_CREATE, command);
};

View File

@@ -1,20 +0,0 @@
'use strict';
const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => {
const commandManager = data.guild_id ? client.guilds.cache.get(data.guild_id)?.commands : client.application.commands;
if (!commandManager) return;
const isOwn = data.application_id === client.application.id;
const command = commandManager._add(data, isOwn);
if (isOwn) commandManager.cache.delete(data.id);
/**
* Emitted when a guild application command is deleted.
* @event Client#applicationCommandDelete
* @param {ApplicationCommand} command The command which was deleted
* @deprecated See {@link https://github.com/discord/discord-api-docs/issues/3690 this issue} for more information.
*/
client.emit(Events.APPLICATION_COMMAND_DELETE, command);
};

View File

@@ -1,20 +0,0 @@
'use strict';
const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => {
const commandManager = data.guild_id ? client.guilds.cache.get(data.guild_id)?.commands : client.application.commands;
if (!commandManager) return;
const oldCommand = commandManager.cache.get(data.id)?._clone() ?? null;
const newCommand = commandManager._add(data, data.application_id === client.application.id);
/**
* Emitted when a guild application command is updated.
* @event Client#applicationCommandUpdate
* @param {?ApplicationCommand} oldCommand The command before the update
* @param {ApplicationCommand} newCommand The command after the update
* @deprecated See {@link https://github.com/discord/discord-api-docs/issues/3690 this issue} for more information.
*/
client.emit(Events.APPLICATION_COMMAND_UPDATE, oldCommand, newCommand);
};

View File

@@ -4,7 +4,7 @@ const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => {
const channel = client.channels.cache.get(data.channel_id);
const time = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null;
const time = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null;
if (channel) {
// Discord sends null for last_pin_timestamp if the last pinned message was removed

View File

@@ -3,9 +3,6 @@
const handlers = Object.fromEntries([
['READY', require('./READY')],
['RESUMED', require('./RESUMED')],
['APPLICATION_COMMAND_CREATE', require('./APPLICATION_COMMAND_CREATE')],
['APPLICATION_COMMAND_DELETE', require('./APPLICATION_COMMAND_DELETE')],
['APPLICATION_COMMAND_UPDATE', require('./APPLICATION_COMMAND_UPDATE')],
['GUILD_CREATE', require('./GUILD_CREATE')],
['GUILD_DELETE', require('./GUILD_DELETE')],
['GUILD_UPDATE', require('./GUILD_UPDATE')],

View File

@@ -17,6 +17,7 @@ exports.Collection = require('@discordjs/collection').Collection;
exports.Constants = require('./util/Constants');
exports.DataResolver = require('./util/DataResolver');
exports.DiscordAPIError = require('./rest/DiscordAPIError');
exports.EnumResolvers = require('./util/EnumResolvers');
exports.Formatters = require('./util/Formatters');
exports.HTTPError = require('./rest/HTTPError');
exports.Intents = require('./util/Intents');
@@ -25,7 +26,7 @@ exports.MessageFlags = require('./util/MessageFlags');
exports.Options = require('./util/Options');
exports.Permissions = require('./util/Permissions');
exports.RateLimitError = require('./rest/RateLimitError');
exports.SnowflakeUtil = require('./util/SnowflakeUtil');
exports.SnowflakeUtil = require('@sapphire/snowflake').DiscordSnowflake;
exports.Sweepers = require('./util/Sweepers');
exports.SystemChannelFlags = require('./util/SystemChannelFlags');
exports.ThreadMemberFlags = require('./util/ThreadMemberFlags');
@@ -73,22 +74,21 @@ exports.Application = require('./structures/interfaces/Application');
exports.ApplicationCommand = require('./structures/ApplicationCommand');
exports.AutocompleteInteraction = require('./structures/AutocompleteInteraction');
exports.Base = require('./structures/Base');
exports.BaseCommandInteraction = require('./structures/BaseCommandInteraction');
exports.BaseGuild = require('./structures/BaseGuild');
exports.BaseGuildEmoji = require('./structures/BaseGuildEmoji');
exports.BaseGuildTextChannel = require('./structures/BaseGuildTextChannel');
exports.BaseGuildVoiceChannel = require('./structures/BaseGuildVoiceChannel');
exports.BaseMessageComponent = require('./structures/BaseMessageComponent');
exports.ButtonInteraction = require('./structures/ButtonInteraction');
exports.CategoryChannel = require('./structures/CategoryChannel');
exports.Channel = require('./structures/Channel').Channel;
exports.ChatInputCommandInteraction = require('./structures/ChatInputCommandInteraction');
exports.ClientApplication = require('./structures/ClientApplication');
exports.ClientPresence = require('./structures/ClientPresence');
exports.ClientUser = require('./structures/ClientUser');
exports.Collector = require('./structures/interfaces/Collector');
exports.CommandInteraction = require('./structures/CommandInteraction');
exports.Collector = require('./structures/interfaces/Collector');
exports.CommandInteractionOptionResolver = require('./structures/CommandInteractionOptionResolver');
exports.ContextMenuInteraction = require('./structures/ContextMenuInteraction');
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
exports.DMChannel = require('./structures/DMChannel');
exports.Emoji = require('./structures/Emoji').Emoji;
exports.Guild = require('./structures/Guild').Guild;
@@ -111,17 +111,14 @@ exports.Invite = require('./structures/Invite');
exports.InviteStageInstance = require('./structures/InviteStageInstance');
exports.InviteGuild = require('./structures/InviteGuild');
exports.Message = require('./structures/Message').Message;
exports.MessageActionRow = require('./structures/MessageActionRow');
exports.MessageAttachment = require('./structures/MessageAttachment');
exports.MessageButton = require('./structures/MessageButton');
exports.MessageCollector = require('./structures/MessageCollector');
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');
exports.MessageContextMenuInteraction = require('./structures/MessageContextMenuInteraction');
exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction');
exports.MessageEmbed = require('./structures/MessageEmbed');
exports.MessageMentions = require('./structures/MessageMentions');
exports.MessagePayload = require('./structures/MessagePayload');
exports.MessageReaction = require('./structures/MessageReaction');
exports.MessageSelectMenu = require('./structures/MessageSelectMenu');
exports.NewsChannel = require('./structures/NewsChannel');
exports.OAuth2Guild = require('./structures/OAuth2Guild');
exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel');
@@ -144,7 +141,7 @@ exports.ThreadChannel = require('./structures/ThreadChannel');
exports.ThreadMember = require('./structures/ThreadMember');
exports.Typing = require('./structures/Typing');
exports.User = require('./structures/User');
exports.UserContextMenuInteraction = require('./structures/UserContextMenuInteraction');
exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction');
exports.VoiceChannel = require('./structures/VoiceChannel');
exports.VoiceRegion = require('./structures/VoiceRegion');
exports.VoiceState = require('./structures/VoiceState');
@@ -155,3 +152,32 @@ exports.WelcomeChannel = require('./structures/WelcomeChannel');
exports.WelcomeScreen = require('./structures/WelcomeScreen');
exports.WebSocket = require('./WebSocket');
// External
exports.ActivityType = require('discord-api-types/v9').ActivityType;
exports.ApplicationCommandType = require('discord-api-types/v9').ApplicationCommandType;
exports.ApplicationCommandOptionType = require('discord-api-types/v9').ApplicationCommandOptionType;
exports.ApplicationCommandPermissionType = require('discord-api-types/v9').ApplicationCommandPermissionType;
exports.ButtonStyle = require('discord-api-types/v9').ButtonStyle;
exports.ChannelType = require('discord-api-types/v9').ChannelType;
exports.ComponentType = require('discord-api-types/v9').ComponentType;
exports.GuildMFALevel = require('discord-api-types/v9').GuildMFALevel;
exports.GuildNSFWLevel = require('discord-api-types/v9').GuildNSFWLevel;
exports.GuildPremiumTier = require('discord-api-types/v9').GuildPremiumTier;
exports.GuildScheduledEventEntityType = require('discord-api-types/v9').GuildScheduledEventEntityType;
exports.GuildScheduledEventPrivacyLevel = require('discord-api-types/v9').GuildScheduledEventPrivacyLevel;
exports.GuildScheduledEventStatus = require('discord-api-types/v9').GuildScheduledEventStatus;
exports.GuildVerificationLevel = require('discord-api-types/v9').GuildVerificationLevel;
exports.InteractionType = require('discord-api-types/v9').InteractionType;
exports.InteractionResponseType = require('discord-api-types/v9').InteractionResponseType;
exports.InviteTargetType = require('discord-api-types/v9').InviteTargetType;
exports.MessageType = require('discord-api-types/v9').MessageType;
exports.RESTJSONErrorCodes = require('discord-api-types/v9').RESTJSONErrorCodes;
exports.StageInstancePrivacyLevel = require('discord-api-types/v9').StageInstancePrivacyLevel;
exports.StickerType = require('discord-api-types/v9').StickerType;
exports.StickerFormatType = require('discord-api-types/v9').StickerFormatType;
exports.WebhookType = require('discord-api-types/v9').WebhookType;
exports.ActionRow = require('@discordjs/builders').ActionRow;
exports.ButtonComponent = require('@discordjs/builders').ButtonComponent;
exports.SelectMenuComponent = require('@discordjs/builders').SelectMenuComponent;
exports.SelectMenuOption = require('@discordjs/builders').SelectMenuOption;

View File

@@ -5,7 +5,6 @@ const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermis
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const ApplicationCommand = require('../structures/ApplicationCommand');
const { ApplicationCommandTypes } = require('../util/Constants');
/**
* Manages API methods for application commands and stores their cache.
@@ -207,7 +206,7 @@ class ApplicationCommandManager extends CachedManager {
return {
name: command.name,
description: command.description,
type: typeof command.type === 'number' ? command.type : ApplicationCommandTypes[command.type],
type: command.type,
options: command.options?.map(o => ApplicationCommand.transformOption(o)),
default_permission: command.defaultPermission ?? command.default_permission,
};

View File

@@ -1,9 +1,9 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { RESTJSONErrorCodes } = require('discord-api-types/v9');
const BaseManager = require('./BaseManager');
const { Error, TypeError } = require('../errors');
const { ApplicationCommandPermissionTypes, APIErrors } = require('../util/Constants');
/**
* Manages API methods for permissions of Application Commands.
@@ -96,18 +96,11 @@ class ApplicationCommandPermissionsManager extends BaseManager {
const { guildId, commandId } = this._validateOptions(guild, command);
if (commandId) {
const data = await this.permissionsPath(guildId, commandId).get();
return data.permissions.map(perm => this.constructor.transformPermissions(perm, true));
return data.permissions;
}
const data = await this.permissionsPath(guildId).get();
return data.reduce(
(coll, perm) =>
coll.set(
perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)),
),
new Collection(),
);
return data.reduce((coll, perm) => coll.set(perm.id, perm.permissions), new Collection());
}
/**
@@ -137,7 +130,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* permissions: [
* {
* id: '876543210987654321',
* type: 'USER',
* type: ApplicationCommandOptionType.User,
* permission: false,
* },
* ]})
@@ -150,7 +143,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* id: '123456789012345678',
* permissions: [{
* id: '876543210987654321',
* type: 'USER',
* type: ApplicationCommandOptionType.User,
* permission: false,
* }],
* },
@@ -165,35 +158,16 @@ class ApplicationCommandPermissionsManager extends BaseManager {
if (!Array.isArray(permissions)) {
throw new TypeError('INVALID_TYPE', 'permissions', 'Array of ApplicationCommandPermissionData', true);
}
const data = await this.permissionsPath(guildId, commandId).put({
data: { permissions: permissions.map(perm => this.constructor.transformPermissions(perm)) },
});
return data.permissions.map(perm => this.constructor.transformPermissions(perm, true));
const data = await this.permissionsPath(guildId, commandId).put({ data: { permissions } });
return data.permissions;
}
if (!Array.isArray(fullPermissions)) {
throw new TypeError('INVALID_TYPE', 'fullPermissions', 'Array of GuildApplicationCommandPermissionData', true);
}
const APIPermissions = [];
for (const perm of fullPermissions) {
if (!Array.isArray(perm.permissions)) throw new TypeError('INVALID_ELEMENT', 'Array', 'fullPermissions', perm);
APIPermissions.push({
id: perm.id,
permissions: perm.permissions.map(p => this.constructor.transformPermissions(p)),
});
}
const data = await this.permissionsPath(guildId).put({
data: APIPermissions,
});
return data.reduce(
(coll, perm) =>
coll.set(
perm.id,
perm.permissions.map(p => this.constructor.transformPermissions(p, true)),
),
new Collection(),
);
const data = await this.permissionsPath(guildId).put({ data: fullPermissions });
return data.reduce((coll, perm) => coll.set(perm.id, perm.permissions), new Collection());
}
/**
@@ -212,7 +186,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
* guild.commands.permissions.add({ command: '123456789012345678', permissions: [
* {
* id: '876543211234567890',
* type: 'ROLE',
* type: ApplicationCommandPermissionType.Role,
* permission: false
* },
* ]})
@@ -230,7 +204,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
}
const newPermissions = permissions.slice();
@@ -319,7 +293,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
}
const permissions = existing.filter(perm => !resolvedIds.includes(perm.id));
@@ -366,7 +340,7 @@ class ApplicationCommandPermissionsManager extends BaseManager {
try {
existing = await this.fetch({ guild: guildId, command: commandId });
} catch (error) {
if (error.code !== APIErrors.UNKNOWN_APPLICATION_COMMAND_PERMISSIONS) throw error;
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
}
return existing.some(perm => perm.id === resolvedId);
@@ -388,24 +362,6 @@ class ApplicationCommandPermissionsManager extends BaseManager {
}
return { guildId, commandId };
}
/**
* Transforms an {@link ApplicationCommandPermissionData} object into something that can be used with the API.
* @param {ApplicationCommandPermissionData} permissions The permissions to transform
* @param {boolean} [received] Whether these permissions have been received from Discord
* @returns {APIApplicationCommandPermissions}
* @private
*/
static transformPermissions(permissions, received) {
return {
id: permissions.id,
permission: permissions.permission,
type:
typeof permissions.type === 'number' && !received
? permissions.type
: ApplicationCommandPermissionTypes[permissions.type],
};
}
}
module.exports = ApplicationCommandPermissionsManager;

View File

@@ -1,7 +1,6 @@
'use strict';
const DataManager = require('./DataManager');
const { _cleanupSymbol } = require('../util/Constants');
/**
* Manages the API methods of a data model with a mutable cache of instances.
@@ -14,19 +13,6 @@ class CachedManager extends DataManager {
Object.defineProperty(this, '_cache', { value: this.client.options.makeCache(this.constructor, this.holds) });
let cleanup = this._cache[_cleanupSymbol]?.();
if (cleanup) {
cleanup = cleanup.bind(this._cache);
client._cleanups.add(cleanup);
client._finalizers.register(this, {
cleanup,
message:
`Garbage collection completed on ${this.constructor.name}, ` +
`which had a ${this._cache.constructor.name} of ${this.holds.name}.`,
name: this.constructor.name,
});
}
if (iterable) {
for (const item of iterable) {
this._add(item);

View File

@@ -16,8 +16,8 @@ class ChannelManager extends CachedManager {
super(client, Channel, iterable);
const defaultCaching =
this._cache.constructor.name === 'Collection' ||
((this._cache.maxSize === undefined || this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined || this._cache.sweepFilter.isDefault));
this._cache.maxSize === undefined ||
this._cache.maxSize === Infinity;
if (!cacheWarningEmitted && !defaultCaching) {
cacheWarningEmitted = true;
process.emitWarning(

View File

@@ -2,13 +2,14 @@
const process = require('node:process');
const { Collection } = require('@discordjs/collection');
const { ChannelType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const ThreadManager = require('./ThreadManager');
const { Error } = require('../errors');
const GuildChannel = require('../structures/GuildChannel');
const PermissionOverwrites = require('../structures/PermissionOverwrites');
const ThreadChannel = require('../structures/ThreadChannel');
const { ChannelTypes, ThreadChannelTypes } = require('../util/Constants');
const { ThreadChannelTypes } = require('../util/Constants');
let cacheWarningEmitted = false;
let storeChannelDeprecationEmitted = false;
@@ -22,8 +23,8 @@ class GuildChannelManager extends CachedManager {
super(guild.client, GuildChannel, iterable);
const defaultCaching =
this._cache.constructor.name === 'Collection' ||
((this._cache.maxSize === undefined || this._cache.maxSize === Infinity) &&
(this._cache.sweepFilter === undefined || this._cache.sweepFilter.isDefault));
this._cache.maxSize === undefined ||
this._cache.maxSize === Infinity;
if (!cacheWarningEmitted && !defaultCaching) {
cacheWarningEmitted = true;
process.emitWarning(
@@ -112,7 +113,7 @@ class GuildChannelManager extends CachedManager {
* @example
* // Create a new channel with permission overwrites
* guild.channels.create('new-voice', {
* type: 'GUILD_VOICE',
* type: ChannelType.GuildVoice,
* permissionOverwrites: [
* {
* id: message.author.id,
@@ -139,9 +140,8 @@ class GuildChannelManager extends CachedManager {
) {
parent &&= this.client.channels.resolveId(parent);
permissionOverwrites &&= permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
const intType = typeof type === 'number' ? type : ChannelTypes[type] ?? ChannelTypes.GUILD_TEXT;
if (intType === ChannelTypes.GUILD_STORE && !storeChannelDeprecationEmitted) {
if (type === ChannelType.GuildStore && !storeChannelDeprecationEmitted) {
storeChannelDeprecationEmitted = true;
process.emitWarning(
// eslint-disable-next-line max-len
@@ -154,7 +154,7 @@ class GuildChannelManager extends CachedManager {
data: {
name,
topic,
type: intType,
type,
nsfw,
bitrate,
user_limit: userLimit,
@@ -204,6 +204,22 @@ class GuildChannelManager extends CachedManager {
return channels;
}
/**
* Data that can be resolved to give a Category Channel object. This can be:
* * A CategoryChannel object
* * A Snowflake
* @typedef {CategoryChannel|Snowflake} CategoryChannelResolvable
*/
/**
* The data needed for updating a channel's position.
* @typedef {Object} ChannelPosition
* @property {GuildChannel|Snowflake} channel Channel to update
* @property {number} [position] New position for the channel
* @property {CategoryChannelResolvable} [parent] Parent channel for this channel
* @property {boolean} [lockPermissions] If the overwrites should be locked to the parents overwrites
*/
/**
* Batch-updates the guild's channels' positions.
* <info>Only one channel's parent can be changed at a time</info>

View File

@@ -100,6 +100,48 @@ class GuildEmojiManager extends BaseGuildEmojiManager {
for (const emoji of data) emojis.set(emoji.id, this._add(emoji, cache));
return emojis;
}
/**
* Deletes an emoji.
* @param {EmojiResolvable} emoji The Emoji resolvable to delete
* @param {string} [reason] Reason for deleting the emoji
* @returns {Promise<void>}
*/
async delete(emoji, reason) {
const id = this.resolveId(emoji);
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
await this.client.api.guilds(this.guild.id).emojis(id).delete({ reason });
}
/**
* Edits an emoji.
* @param {EmojiResolvable} emoji The Emoji resolvable to edit
* @param {GuildEmojiEditData} data The new data for the emoji
* @param {string} [reason] Reason for editing this emoji
* @returns {Promise<GuildEmoji>}
*/
async edit(emoji, data, reason) {
const id = this.resolveId(emoji);
if (!id) throw new TypeError('INVALID_TYPE', 'emoji', 'EmojiResolvable', true);
const roles = data.roles?.map(r => this.guild.roles.resolveId(r));
const newData = await this.client.api
.guilds(this.guild.id)
.emojis(id)
.patch({
data: {
name: data.name,
roles,
},
reason,
});
const existing = this.cache.get(id);
if (existing) {
const clone = existing._clone();
clone._patch(newData);
return clone;
}
return this._add(newData);
}
}
module.exports = GuildEmojiManager;

View File

@@ -1,6 +1,7 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { InviteTargetType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { Error } = require('../errors');
const Invite = require('../structures/Invite');
@@ -190,7 +191,7 @@ class GuildInviteManager extends CachedManager {
unique,
target_user_id: this.client.users.resolveId(targetUser),
target_application_id: targetApplication?.id ?? targetApplication?.applicationId ?? targetApplication,
target_type: targetType,
target_type: InviteTargetType[targetType],
},
reason,
});

View File

@@ -1,7 +1,7 @@
'use strict';
const process = require('node:process');
const { setTimeout } = require('node:timers');
const { setTimeout, clearTimeout } = require('node:timers');
const { Collection } = require('@discordjs/collection');
const CachedManager = require('./CachedManager');
const { Guild } = require('../structures/Guild');
@@ -11,14 +11,7 @@ const { GuildMember } = require('../structures/GuildMember');
const Invite = require('../structures/Invite');
const OAuth2Guild = require('../structures/OAuth2Guild');
const { Role } = require('../structures/Role');
const {
ChannelTypes,
Events,
OverwriteTypes,
VerificationLevels,
DefaultMessageNotificationLevels,
ExplicitContentFilterLevels,
} = require('../util/Constants');
const { Events } = require('../util/Constants');
const DataResolver = require('../util/DataResolver');
const Permissions = require('../util/Permissions');
const SystemChannelFlags = require('../util/SystemChannelFlags');
@@ -181,17 +174,8 @@ class GuildManager extends CachedManager {
} = {},
) {
icon = await DataResolver.resolveImage(icon);
if (typeof verificationLevel === 'string') {
verificationLevel = VerificationLevels[verificationLevel];
}
if (typeof defaultMessageNotifications === 'string') {
defaultMessageNotifications = DefaultMessageNotificationLevels[defaultMessageNotifications];
}
if (typeof explicitContentFilter === 'string') {
explicitContentFilter = ExplicitContentFilterLevels[explicitContentFilter];
}
for (const channel of channels) {
channel.type &&= typeof channel.type === 'number' ? channel.type : ChannelTypes[channel.type];
channel.parent_id = channel.parentId;
delete channel.parentId;
channel.user_limit = channel.userLimit;
@@ -203,9 +187,6 @@ class GuildManager extends CachedManager {
if (!channel.permissionOverwrites) continue;
for (const overwrite of channel.permissionOverwrites) {
if (typeof overwrite.type === 'string') {
overwrite.type = OverwriteTypes[overwrite.type];
}
overwrite.allow &&= Permissions.resolve(overwrite.allow).toString();
overwrite.deny &&= Permissions.resolve(overwrite.deny).toString();
}

View File

@@ -1,15 +1,15 @@
'use strict';
const { Buffer } = require('node:buffer');
const { setTimeout } = require('node:timers');
const { setTimeout, clearTimeout } = require('node:timers');
const { Collection } = require('@discordjs/collection');
const { DiscordSnowflake } = require('@sapphire/snowflake');
const CachedManager = require('./CachedManager');
const { Error, TypeError, RangeError } = require('../errors');
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
const { GuildMember } = require('../structures/GuildMember');
const { Role } = require('../structures/Role');
const { Events, Opcodes } = require('../util/Constants');
const SnowflakeUtil = require('../util/SnowflakeUtil');
/**
* Manages API methods for GuildMembers and stores their cache.
@@ -266,7 +266,10 @@ class GuildMemberManager extends CachedManager {
_data.roles &&= _data.roles.map(role => (role instanceof Role ? role.id : role));
_data.communication_disabled_until =
_data.communicationDisabledUntil && new Date(_data.communicationDisabledUntil).toISOString();
// eslint-disable-next-line eqeqeq
_data.communicationDisabledUntil != null
? new Date(_data.communicationDisabledUntil).toISOString()
: _data.communicationDisabledUntil;
let endpoint = this.client.api.guilds(this.guild.id);
if (id === this.client.user.id) {
@@ -353,7 +356,7 @@ class GuildMemberManager extends CachedManager {
* @example
* // Kick a user by id (or with a user/guild member object)
* guild.members.kick('84484653687267328')
* .then(banInfo => console.log(`Kicked ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
* .then(kickInfo => console.log(`Kicked ${kickInfo.user?.tag ?? kickInfo.tag ?? kickInfo}`))
* .catch(console.error);
*/
async kick(user, reason) {
@@ -376,7 +379,7 @@ class GuildMemberManager extends CachedManager {
* @example
* // Ban a user by id (or with a user/guild member object)
* guild.members.ban('84484653687267328')
* .then(kickInfo => console.log(`Banned ${kickInfo.user?.tag ?? kickInfo.tag ?? kickInfo}`))
* .then(banInfo => console.log(`Banned ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
* .catch(console.error);
*/
ban(user, options = { days: 0 }) {
@@ -414,7 +417,7 @@ class GuildMemberManager extends CachedManager {
user: user_ids,
query,
time = 120e3,
nonce = SnowflakeUtil.generate(),
nonce = DiscordSnowflake.generate().toString(),
} = {}) {
return new Promise((resolve, reject) => {
if (!query && !user_ids) query = '';

View File

@@ -1,10 +1,14 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const {
GuildScheduledEventPrivacyLevel,
GuildScheduledEventEntityType,
GuildScheduledEventStatus,
} = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { TypeError, Error } = require('../errors');
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
const { PrivacyLevels, GuildScheduledEventEntityTypes, GuildScheduledEventStatuses } = require('../util/Constants');
/**
* Manages API methods for GuildScheduledEvents and stores their cache.
@@ -40,15 +44,16 @@ class GuildScheduledEventManager extends CachedManager {
* @property {string} name The name of the guild scheduled event
* @property {DateResolvable} scheduledStartTime The time to schedule the event at
* @property {DateResolvable} [scheduledEndTime] The time to end the event at
* <warn>This is required if `entityType` is 'EXTERNAL'</warn>
* <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
* @property {PrivacyLevel|number} privacyLevel The privacy level of the guild scheduled event
* @property {GuildScheduledEventEntityType|number} entityType The scheduled entity type of the event
* @property {string} [description] The description of the guild scheduled event
* @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event
* <warn>This is required if `entityType` is 'STAGE_INSTANCE' or `VOICE`</warn>
* <warn>This is required if `entityType` is `GuildScheduledEventEntityType.StageInstance` or
* `GuildScheduledEventEntityType.Voice`</warn>
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
* guild scheduled event
* <warn>This is required if `entityType` is 'EXTERNAL'</warn>
* <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
* @property {string} [reason] The reason for creating the guild scheduled event
*/
@@ -56,7 +61,7 @@ class GuildScheduledEventManager extends CachedManager {
* Options used to set entity metadata of a guild scheduled event.
* @typedef {Object} GuildScheduledEventEntityMetadataOptions
* @property {string} [location] The location of the guild scheduled event
* <warn>This is required if `entityType` is 'EXTERNAL'</warn>
* <warn>This is required if `entityType` is `GuildScheduledEventEntityType.External`</warn>
*/
/**
@@ -78,11 +83,11 @@ class GuildScheduledEventManager extends CachedManager {
reason,
} = options;
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityTypes[entityType];
if (typeof privacyLevel === 'string') privacyLevel = GuildScheduledEventPrivacyLevel[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityType[entityType];
let entity_metadata, channel_id;
if (entityType === GuildScheduledEventEntityTypes.EXTERNAL) {
if (entityType === GuildScheduledEventEntityType.External) {
channel_id = typeof channel === 'undefined' ? channel : null;
entity_metadata = { location: entityMetadata?.location };
} else {
@@ -171,7 +176,8 @@ class GuildScheduledEventManager extends CachedManager {
* @property {GuildScheduledEventStatus|number} [status] The status of the guild scheduled event
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
* guild scheduled event
* <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is 'EXTERNAL'</warn>
* <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is
* `GuildScheduledEventEntityType.External`</warn>
* @property {string} [reason] The reason for editing the guild scheduled event
*/
@@ -199,9 +205,9 @@ class GuildScheduledEventManager extends CachedManager {
reason,
} = options;
if (typeof privacyLevel === 'string') privacyLevel = PrivacyLevels[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityTypes[entityType];
if (typeof status === 'string') status = GuildScheduledEventStatuses[status];
if (typeof privacyLevel === 'string') privacyLevel = GuildScheduledEventPrivacyLevel[privacyLevel];
if (typeof entityType === 'string') entityType = GuildScheduledEventEntityType[entityType];
if (typeof status === 'string') status = GuildScheduledEventStatus[status];
let entity_metadata;
if (entityMetadata) {

View File

@@ -2,11 +2,11 @@
const process = require('node:process');
const { Collection } = require('@discordjs/collection');
const { OverwriteType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const PermissionOverwrites = require('../structures/PermissionOverwrites');
const { Role } = require('../structures/Role');
const { OverwriteTypes } = require('../util/Constants');
let cacheWarningEmitted = false;
@@ -94,7 +94,7 @@ class PermissionOverwriteManager extends CachedManager {
if (typeof type !== 'number') {
userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole);
if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role');
type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member;
type = userOrRole instanceof Role ? OverwriteType.Role : OverwriteType.Member;
}
const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options, existing);

View File

@@ -7,7 +7,7 @@ const { TypeError } = require('../errors');
const { Role } = require('../structures/Role');
const DataResolver = require('../util/DataResolver');
const Permissions = require('../util/Permissions');
const { resolveColor, setPosition } = require('../util/Util');
const { resolveColor } = require('../util/Util');
let cacheWarningEmitted = false;
@@ -180,19 +180,7 @@ class RoleManager extends CachedManager {
if (!role) throw new TypeError('INVALID_TYPE', 'role', 'RoleResolvable');
if (typeof data.position === 'number') {
const updatedRoles = await setPosition(
role,
data.position,
false,
this.guild._sortedRoles(),
this.client.api.guilds(this.guild.id).roles,
reason,
);
this.client.actions.GuildRolesPositionUpdate.handle({
guild_id: this.guild.id,
roles: updatedRoles,
});
await role.setPosition(data.position, { reason });
}
let icon = data.icon;
@@ -227,7 +215,7 @@ class RoleManager extends CachedManager {
* @example
* // Delete a role
* guild.roles.delete('222079219327434752', 'The role needed to go')
* .then(deleted => console.log(`Deleted role ${deleted.name}`))
* .then(() => console.log('Deleted the role'))
* .catch(console.error);
*/
async delete(role, reason) {
@@ -236,6 +224,13 @@ class RoleManager extends CachedManager {
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: id });
}
/*
* The data needed for updating a guild role's position
* @typedef {Object} GuildRolePosition
* @property {RoleResolvable} role The role's id
* @property {number} position The position to update
*/
/**
* Batch-updates the guild's role positions
* @param {GuildRolePosition[]} rolePositions Role positions to update

View File

@@ -1,9 +1,9 @@
'use strict';
const { GuildScheduledEventPrivacyLevel } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { TypeError, Error } = require('../errors');
const { StageInstance } = require('../structures/StageInstance');
const { PrivacyLevels } = require('../util/Constants');
/**
* Manages API methods for {@link StageInstance} objects and holds their cache.
@@ -49,7 +49,7 @@ class StageInstanceManager extends CachedManager {
* // Create a stage instance
* guild.stageInstances.create('1234567890123456789', {
* topic: 'A very creative topic',
* privacyLevel: 'GUILD_ONLY'
* privacyLevel: GuildPrivacyLevel.GuildOnly
* })
* .then(stageInstance => console.log(stageInstance))
* .catch(console.error);
@@ -60,7 +60,7 @@ class StageInstanceManager extends CachedManager {
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
let { topic, privacyLevel } = options;
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : PrivacyLevels[privacyLevel];
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : GuildScheduledEventPrivacyLevel[privacyLevel];
const data = await this.client.api['stage-instances'].post({
data: {
@@ -122,7 +122,7 @@ class StageInstanceManager extends CachedManager {
let { topic, privacyLevel } = options;
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : PrivacyLevels[privacyLevel];
privacyLevel &&= typeof privacyLevel === 'number' ? privacyLevel : GuildScheduledEventPrivacyLevel[privacyLevel];
const data = await this.client.api('stage-instances', channelId).patch({
data: {

View File

@@ -1,10 +1,10 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { ChannelType } = require('discord-api-types/v9');
const CachedManager = require('./CachedManager');
const { TypeError } = require('../errors');
const ThreadChannel = require('../structures/ThreadChannel');
const { ChannelTypes } = require('../util/Constants');
/**
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
@@ -92,7 +92,7 @@ class ThreadManager extends CachedManager {
* .create({
* name: 'mod-talk',
* autoArchiveDuration: 60,
* type: 'GUILD_PRIVATE_THREAD',
* type: ChannelType.GuildPrivateThread,
* reason: 'Needed a separate thread for moderation',
* })
* .then(threadChannel => console.log(threadChannel))
@@ -112,13 +112,13 @@ class ThreadManager extends CachedManager {
throw new TypeError('INVALID_TYPE', 'type', 'ThreadChannelType or Number');
}
let resolvedType =
this.channel.type === 'GUILD_NEWS' ? ChannelTypes.GUILD_NEWS_THREAD : ChannelTypes.GUILD_PUBLIC_THREAD;
this.channel.type === ChannelType.GuildNews ? ChannelType.GuildNewsThread : ChannelType.GuildPublicThread;
if (startMessage) {
const startMessageId = this.channel.messages.resolveId(startMessage);
if (!startMessageId) throw new TypeError('INVALID_TYPE', 'startMessage', 'MessageResolvable');
path = path.messages(startMessageId);
} else if (this.channel.type !== 'GUILD_NEWS') {
resolvedType = typeof type === 'string' ? ChannelTypes[type] : type ?? resolvedType;
} else if (this.channel.type !== ChannelType.GuildNews) {
resolvedType = type ?? resolvedType;
}
if (autoArchiveDuration === 'MAX') {
autoArchiveDuration = 1440;
@@ -134,7 +134,7 @@ class ThreadManager extends CachedManager {
name,
auto_archive_duration: autoArchiveDuration,
type: resolvedType,
invitable: resolvedType === ChannelTypes.GUILD_PRIVATE_THREAD ? invitable : undefined,
invitable: resolvedType === ChannelType.GuildPrivateThread ? invitable : undefined,
rate_limit_per_user: rateLimitPerUser,
},
reason,

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