mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
chore: monorepo setup (#7175)
This commit is contained in:
16
packages/builders/.eslintrc.json
Normal file
16
packages/builders/.eslintrc.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "marine/prettier/node",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.eslint.json",
|
||||
"extraFileExtensions": [".mjs"]
|
||||
},
|
||||
"ignorePatterns": ["**/dist/*"],
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
"rules": {
|
||||
"no-redeclare": 0,
|
||||
"@typescript-eslint/naming-convention": 0
|
||||
}
|
||||
}
|
||||
26
packages/builders/.gitignore
vendored
Normal file
26
packages/builders/.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Packages
|
||||
node_modules/
|
||||
|
||||
# Log files
|
||||
logs/
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Env
|
||||
.env
|
||||
|
||||
# Dist
|
||||
dist/
|
||||
typings/
|
||||
docs/**/*
|
||||
!docs/index.yml
|
||||
!docs/README.md
|
||||
|
||||
# Miscellaneous
|
||||
.tmp/
|
||||
coverage/
|
||||
8
packages/builders/.prettierrc.json
Normal file
8
packages/builders/.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
3
packages/builders/.versionrc
Normal file
3
packages/builders/.versionrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"releaseCommitMessageFormat": "chore(Release): publish"
|
||||
}
|
||||
153
packages/builders/CHANGELOG.md
Normal file
153
packages/builders/CHANGELOG.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
|
||||
# [0.11.0](https://github.com/discordjs/builders/compare/v0.10.0...v0.11.0) (2021-12-29)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
# [0.10.0](https://github.com/discordjs/builders/compare/v0.9.0...v0.10.0) (2021-12-24)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
# [0.9.0](https://github.com/discordjs/builders/compare/v0.8.2...v0.9.0) (2021-12-02)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
## [0.8.2](https://github.com/discordjs/builders/compare/v0.8.1...v0.8.2) (2021-10-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 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
|
||||
|
||||
* 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)
|
||||
|
||||
|
||||
|
||||
# [0.7.0](https://github.com/discordjs/builders/compare/v0.6.0...v0.7.0) (2021-10-18)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
# [0.6.0](https://github.com/discordjs/builders/compare/v0.5.0...v0.6.0) (2021-08-24)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
# [0.5.0](https://github.com/discordjs/builders/compare/v0.3.0...v0.5.0) (2021-08-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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))
|
||||
|
||||
|
||||
|
||||
# [0.3.0](https://github.com/discordjs/builders/compare/v0.2.0...v0.3.0) (2021-08-01)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
# [0.2.0](https://github.com/discordjs/builders/compare/v0.1.1...v0.2.0) (2021-07-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **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.0 (2021-06-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added message formatters ([#1](https://github.com/discordjs/builders/issues/1)) ([765e46d](https://github.com/discordjs/builders/commit/765e46dac96c4e49d350243e5fad34c2bc738a7c))
|
||||
191
packages/builders/LICENSE
Normal file
191
packages/builders/LICENSE
Normal file
@@ -0,0 +1,191 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2021 Noel Buechler
|
||||
Copyright 2021 Vlad Frangu
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
53
packages/builders/README.md
Normal file
53
packages/builders/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
<div align="center">
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.js.org"><img src="https://discord.js.org/static/logo.svg" width="546" alt="discord.js" /></a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
|
||||
<a href="https://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://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.**
|
||||
|
||||
```sh-session
|
||||
npm install @discordjs/builders
|
||||
yarn add @discordjs/builders
|
||||
pnpm add @discordjs/builders
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Here are some examples for the builders and utilities you can find in this package:
|
||||
|
||||
- [Slash Command Builders](./docs/examples/Slash%20Command%20Builders.md)
|
||||
|
||||
## Links
|
||||
|
||||
- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website))
|
||||
- [Documentation](https://discord.js.org/#/docs/builders)
|
||||
- [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide))
|
||||
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)
|
||||
- [npm](https://www.npmjs.com/package/@discordjs/builders)
|
||||
- [Related libraries](https://discord.com/developers/docs/topics/community-resources#libraries)
|
||||
|
||||
## 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/builders).
|
||||
See [the contribution guide](https://github.com/discordjs/builders/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
|
||||
|
||||
## Help
|
||||
|
||||
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
|
||||
nudge in the right direction, please don't hesitate to join our official [discord.js Server](https://discord.gg/djs).
|
||||
@@ -0,0 +1,89 @@
|
||||
import { ContextMenuCommandAssertions, ContextMenuCommandBuilder } from '../../src/index';
|
||||
|
||||
const getBuilder = () => new ContextMenuCommandBuilder();
|
||||
|
||||
describe('Context Menu Commands', () => {
|
||||
describe('Assertions tests', () => {
|
||||
test('GIVEN valid name THEN does not throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateName('ping')).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid name THEN throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateName(null)).toThrowError();
|
||||
|
||||
// Too short of a name
|
||||
expect(() => ContextMenuCommandAssertions.validateName('')).toThrowError();
|
||||
|
||||
// Invalid characters used
|
||||
expect(() => ContextMenuCommandAssertions.validateName('ABC123$%^&')).toThrowError();
|
||||
|
||||
// Too long of a name
|
||||
expect(() =>
|
||||
ContextMenuCommandAssertions.validateName('qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm'),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid type THEN does not throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateType(3)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid type THEN throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateType(null)).toThrowError();
|
||||
|
||||
// Out of range
|
||||
expect(() => ContextMenuCommandAssertions.validateType(1)).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid required parameters THEN does not throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateRequiredParameters('owo', 2)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid default_permission THEN does not throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateDefaultPermission(true)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid default_permission THEN throw error', () => {
|
||||
expect(() => ContextMenuCommandAssertions.validateDefaultPermission(null)).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('ContextMenuCommandBuilder', () => {
|
||||
describe('Builder tests', () => {
|
||||
test('GIVEN empty builder THEN throw error when calling toJSON', () => {
|
||||
expect(() => getBuilder().toJSON()).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid builder THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('example').setType(3).toJSON()).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid name THEN throw error', () => {
|
||||
expect(() => getBuilder().setName('$$$')).toThrowError();
|
||||
|
||||
expect(() => getBuilder().setName(' ')).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid names THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('hi_there')).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().setName('A COMMAND')).not.toThrowError();
|
||||
|
||||
// Translation: a_command
|
||||
expect(() => getBuilder().setName('o_comandă')).not.toThrowError();
|
||||
|
||||
// Translation: thx (according to GTranslate)
|
||||
expect(() => getBuilder().setName('どうも')).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid types THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setType(2)).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().setType(3)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid builder with defaultPermission false THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('foo').setDefaultPermission(false)).not.toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,201 @@
|
||||
import {
|
||||
APIApplicationCommandBooleanOption,
|
||||
APIApplicationCommandChannelOption,
|
||||
APIApplicationCommandIntegerOption,
|
||||
APIApplicationCommandMentionableOption,
|
||||
APIApplicationCommandNumberOption,
|
||||
APIApplicationCommandRoleOption,
|
||||
APIApplicationCommandStringOption,
|
||||
APIApplicationCommandUserOption,
|
||||
ApplicationCommandOptionType,
|
||||
ChannelType,
|
||||
} from 'discord-api-types/v9';
|
||||
import {
|
||||
SlashCommandBooleanOption,
|
||||
SlashCommandChannelOption,
|
||||
SlashCommandIntegerOption,
|
||||
SlashCommandMentionableOption,
|
||||
SlashCommandNumberOption,
|
||||
SlashCommandRoleOption,
|
||||
SlashCommandStringOption,
|
||||
SlashCommandUserOption,
|
||||
} from '../../../src/index';
|
||||
|
||||
const getBooleanOption = () =>
|
||||
new SlashCommandBooleanOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
const getChannelOption = () =>
|
||||
new SlashCommandChannelOption()
|
||||
.setName('owo')
|
||||
.setDescription('Testing 123')
|
||||
.setRequired(true)
|
||||
.addChannelType(ChannelType.GuildText);
|
||||
|
||||
const getStringOption = () =>
|
||||
new SlashCommandStringOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
const getIntegerOption = () =>
|
||||
new SlashCommandIntegerOption()
|
||||
.setName('owo')
|
||||
.setDescription('Testing 123')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(10);
|
||||
|
||||
const getNumberOption = () =>
|
||||
new SlashCommandNumberOption()
|
||||
.setName('owo')
|
||||
.setDescription('Testing 123')
|
||||
.setRequired(true)
|
||||
.setMinValue(1)
|
||||
.setMaxValue(10);
|
||||
|
||||
const getUserOption = () => new SlashCommandUserOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
const getRoleOption = () => new SlashCommandRoleOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
const getMentionableOption = () =>
|
||||
new SlashCommandMentionableOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
describe('Application Command toJSON() results', () => {
|
||||
test('GIVEN a boolean option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getBooleanOption().toJSON()).toEqual<APIApplicationCommandBooleanOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Boolean,
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a channel option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getChannelOption().toJSON()).toEqual<APIApplicationCommandChannelOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
required: true,
|
||||
channel_types: [ChannelType.GuildText],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a integer option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getIntegerOption().toJSON()).toEqual<APIApplicationCommandIntegerOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
});
|
||||
|
||||
expect(
|
||||
getIntegerOption().setAutocomplete(true).setChoices([]).toJSON(),
|
||||
).toEqual<APIApplicationCommandIntegerOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
autocomplete: true,
|
||||
// @ts-expect-error TODO: you *can* send an empty array with autocomplete: true, should correct that in types
|
||||
choices: [],
|
||||
});
|
||||
|
||||
expect(getIntegerOption().addChoice('uwu', 1).toJSON()).toEqual<APIApplicationCommandIntegerOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
choices: [{ name: 'uwu', value: 1 }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a mentionable option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getMentionableOption().toJSON()).toEqual<APIApplicationCommandMentionableOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Mentionable,
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a number option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getNumberOption().toJSON()).toEqual<APIApplicationCommandNumberOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Number,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
});
|
||||
|
||||
expect(getNumberOption().setAutocomplete(true).setChoices([]).toJSON()).toEqual<APIApplicationCommandNumberOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Number,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
autocomplete: true,
|
||||
// @ts-expect-error TODO: you *can* send an empty array with autocomplete: true, should correct that in types
|
||||
choices: [],
|
||||
});
|
||||
|
||||
expect(getNumberOption().addChoice('uwu', 1).toJSON()).toEqual<APIApplicationCommandNumberOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Number,
|
||||
required: true,
|
||||
max_value: 10,
|
||||
min_value: 1,
|
||||
choices: [{ name: 'uwu', value: 1 }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a role option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getRoleOption().toJSON()).toEqual<APIApplicationCommandRoleOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.Role,
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a string option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getStringOption().toJSON()).toEqual<APIApplicationCommandStringOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true,
|
||||
});
|
||||
|
||||
expect(getStringOption().setAutocomplete(true).setChoices([]).toJSON()).toEqual<APIApplicationCommandStringOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true,
|
||||
autocomplete: true,
|
||||
// @ts-expect-error TODO: you *can* send an empty array with autocomplete: true, should correct that in types
|
||||
choices: [],
|
||||
});
|
||||
|
||||
expect(getStringOption().addChoice('uwu', '1').toJSON()).toEqual<APIApplicationCommandStringOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.String,
|
||||
required: true,
|
||||
choices: [{ name: 'uwu', value: '1' }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN a user option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getUserOption().toJSON()).toEqual<APIApplicationCommandUserOption>({
|
||||
name: 'owo',
|
||||
description: 'Testing 123',
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,427 @@
|
||||
import { APIApplicationCommandOptionChoice, ChannelType } from 'discord-api-types/v9';
|
||||
import {
|
||||
SlashCommandAssertions,
|
||||
SlashCommandBooleanOption,
|
||||
SlashCommandBuilder,
|
||||
SlashCommandChannelOption,
|
||||
SlashCommandIntegerOption,
|
||||
SlashCommandMentionableOption,
|
||||
SlashCommandNumberOption,
|
||||
SlashCommandRoleOption,
|
||||
SlashCommandStringOption,
|
||||
SlashCommandSubcommandBuilder,
|
||||
SlashCommandSubcommandGroupBuilder,
|
||||
SlashCommandUserOption,
|
||||
} from '../../../src/index';
|
||||
|
||||
const largeArray = Array.from({ length: 26 }, () => 1 as unknown as APIApplicationCommandOptionChoice);
|
||||
|
||||
const getBuilder = () => new SlashCommandBuilder();
|
||||
const getNamedBuilder = () => getBuilder().setName('example').setDescription('Example command');
|
||||
const getStringOption = () => new SlashCommandStringOption().setName('owo').setDescription('Testing 123');
|
||||
const getIntegerOption = () => new SlashCommandIntegerOption().setName('owo').setDescription('Testing 123');
|
||||
const getNumberOption = () => new SlashCommandNumberOption().setName('owo').setDescription('Testing 123');
|
||||
const getBooleanOption = () => new SlashCommandBooleanOption().setName('owo').setDescription('Testing 123');
|
||||
const getUserOption = () => new SlashCommandUserOption().setName('owo').setDescription('Testing 123');
|
||||
const getChannelOption = () => new SlashCommandChannelOption().setName('owo').setDescription('Testing 123');
|
||||
const getRoleOption = () => new SlashCommandRoleOption().setName('owo').setDescription('Testing 123');
|
||||
const getMentionableOption = () => new SlashCommandMentionableOption().setName('owo').setDescription('Testing 123');
|
||||
const getSubcommandGroup = () => new SlashCommandSubcommandGroupBuilder().setName('owo').setDescription('Testing 123');
|
||||
const getSubcommand = () => new SlashCommandSubcommandBuilder().setName('owo').setDescription('Testing 123');
|
||||
|
||||
class Collection {
|
||||
public get [Symbol.toStringTag]() {
|
||||
return 'Map';
|
||||
}
|
||||
}
|
||||
|
||||
describe('Slash Commands', () => {
|
||||
describe('Assertions tests', () => {
|
||||
test('GIVEN valid name THEN does not throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateName('ping')).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid name THEN throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateName(null)).toThrowError();
|
||||
|
||||
// Too short of a name
|
||||
expect(() => SlashCommandAssertions.validateName('')).toThrowError();
|
||||
|
||||
// Invalid characters used
|
||||
expect(() => SlashCommandAssertions.validateName('ABC123$%^&')).toThrowError();
|
||||
|
||||
// Too long of a name
|
||||
expect(() =>
|
||||
SlashCommandAssertions.validateName('qwertyuiopasdfghjklzxcvbnmqwertyuiopasdfghjklzxcvbnm'),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid description THEN does not throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateDescription('This is an OwO moment fur sure!~')).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid description THEN throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateDescription(null)).toThrowError();
|
||||
|
||||
// Too short of a description
|
||||
expect(() => SlashCommandAssertions.validateDescription('')).toThrowError();
|
||||
|
||||
// Too long of a description
|
||||
expect(() =>
|
||||
SlashCommandAssertions.validateDescription(
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Magnam autem libero expedita vitae accusamus nostrum ipsam tempore repudiandae deserunt ipsum facilis, velit fugiat facere accusantium, explicabo corporis aliquam non quos.',
|
||||
),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid default_permission THEN does not throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateDefaultPermission(true)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid default_permission THEN throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateDefaultPermission(null)).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid array of options or choices THEN does not throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateMaxOptionsLength([])).not.toThrowError();
|
||||
|
||||
expect(() => SlashCommandAssertions.validateMaxChoicesLength([])).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid options or choices THEN throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateMaxOptionsLength(null)).toThrowError();
|
||||
|
||||
expect(() => SlashCommandAssertions.validateMaxChoicesLength(null)).toThrowError();
|
||||
|
||||
// Given an array that's too big
|
||||
expect(() => SlashCommandAssertions.validateMaxOptionsLength(largeArray)).toThrowError();
|
||||
|
||||
expect(() => SlashCommandAssertions.validateMaxChoicesLength(largeArray)).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid required parameters THEN does not throw error', () => {
|
||||
expect(() =>
|
||||
SlashCommandAssertions.validateRequiredParameters(
|
||||
'owo',
|
||||
'My fancy command that totally exists, to test assertions',
|
||||
[],
|
||||
),
|
||||
).not.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('SlashCommandBuilder', () => {
|
||||
describe('Builder with no options', () => {
|
||||
test('GIVEN empty builder THEN throw error when calling toJSON', () => {
|
||||
expect(() => getBuilder().toJSON()).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid builder THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('example').setDescription('Example command').toJSON()).not.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Builder with simple options', () => {
|
||||
test('GIVEN valid builder with options THEN does not throw error', () => {
|
||||
expect(() =>
|
||||
getBuilder()
|
||||
.setName('example')
|
||||
.setDescription('Example command')
|
||||
.addBooleanOption((boolean) =>
|
||||
boolean.setName('iscool').setDescription('Are we cool or what?').setRequired(true),
|
||||
)
|
||||
.addChannelOption((channel) => channel.setName('iscool').setDescription('Are we cool or what?'))
|
||||
.addMentionableOption((mentionable) => mentionable.setName('iscool').setDescription('Are we cool or what?'))
|
||||
.addRoleOption((role) => role.setName('iscool').setDescription('Are we cool or what?'))
|
||||
.addUserOption((user) => user.setName('iscool').setDescription('Are we cool or what?'))
|
||||
.addIntegerOption((integer) =>
|
||||
integer
|
||||
.setName('iscool')
|
||||
.setDescription('Are we cool or what?')
|
||||
.addChoices([['Very cool', 1_000]]),
|
||||
)
|
||||
.addNumberOption((number) =>
|
||||
number
|
||||
.setName('iscool')
|
||||
.setDescription('Are we cool or what?')
|
||||
.addChoices([['Very cool', 1.5]]),
|
||||
)
|
||||
.addStringOption((string) =>
|
||||
string
|
||||
.setName('iscool')
|
||||
.setDescription('Are we cool or what?')
|
||||
.addChoices([
|
||||
['Fancy Pants', 'fp_1'],
|
||||
['Fancy Shoes', 'fs_1'],
|
||||
['The Whole shebang', 'all'],
|
||||
]),
|
||||
)
|
||||
.addIntegerOption((integer) =>
|
||||
integer.setName('iscool').setDescription('Are we cool or what?').setAutocomplete(true),
|
||||
)
|
||||
.addNumberOption((number) =>
|
||||
number.setName('iscool').setDescription('Are we cool or what?').setAutocomplete(true),
|
||||
)
|
||||
.addStringOption((string) =>
|
||||
string.setName('iscool').setDescription('Are we cool or what?').setAutocomplete(true),
|
||||
)
|
||||
.toJSON(),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with invalid autocomplete THEN does throw an error', () => {
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addStringOption(getStringOption().setAutocomplete('not a boolean'))).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with both choices and autocomplete THEN does throw an error', () => {
|
||||
expect(() =>
|
||||
getBuilder().addStringOption(
|
||||
// @ts-expect-error Checking if check works JS-side too
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
getStringOption().setAutocomplete(true).addChoice('Fancy Pants', 'fp_1'),
|
||||
),
|
||||
).toThrowError();
|
||||
|
||||
expect(() =>
|
||||
getBuilder().addStringOption(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
getStringOption()
|
||||
.setAutocomplete(true)
|
||||
// @ts-expect-error Checking if check works JS-side too
|
||||
.addChoices([
|
||||
['Fancy Pants', 'fp_1'],
|
||||
['Fancy Shoes', 'fs_1'],
|
||||
['The Whole shebang', 'all'],
|
||||
]),
|
||||
),
|
||||
).toThrowError();
|
||||
|
||||
expect(() =>
|
||||
getBuilder().addStringOption(
|
||||
// @ts-expect-error Checking if check works JS-side too
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
getStringOption().addChoice('Fancy Pants', 'fp_1').setAutocomplete(true),
|
||||
),
|
||||
).toThrowError();
|
||||
|
||||
expect(() => {
|
||||
const option = getStringOption();
|
||||
Reflect.set(option, 'autocomplete', true);
|
||||
Reflect.set(option, 'choices', [{ name: 'Fancy Pants', value: 'fp_1' }]);
|
||||
return option.toJSON();
|
||||
}).toThrowError();
|
||||
|
||||
expect(() => {
|
||||
const option = getNumberOption();
|
||||
Reflect.set(option, 'autocomplete', true);
|
||||
Reflect.set(option, 'choices', [{ name: 'Fancy Pants', value: 'fp_1' }]);
|
||||
return option.toJSON();
|
||||
}).toThrowError();
|
||||
|
||||
expect(() => {
|
||||
const option = getIntegerOption();
|
||||
Reflect.set(option, 'autocomplete', true);
|
||||
Reflect.set(option, 'choices', [{ name: 'Fancy Pants', value: 'fp_1' }]);
|
||||
return option.toJSON();
|
||||
}).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with valid channel options and channel_types THEN does not throw an error', () => {
|
||||
expect(() =>
|
||||
getBuilder().addChannelOption(getChannelOption().addChannelType(ChannelType.GuildText)),
|
||||
).not.toThrowError();
|
||||
|
||||
expect(() => {
|
||||
getBuilder().addChannelOption(
|
||||
getChannelOption().addChannelTypes([ChannelType.GuildNews, ChannelType.GuildText]),
|
||||
);
|
||||
}).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with valid channel options and channel_types THEN does throw an error', () => {
|
||||
expect(() => getBuilder().addChannelOption(getChannelOption().addChannelType(100))).toThrowError();
|
||||
|
||||
expect(() => getBuilder().addChannelOption(getChannelOption().addChannelTypes([100, 200]))).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with invalid number min/max options THEN does throw an error', () => {
|
||||
// @ts-expect-error
|
||||
expect(() => getBuilder().addNumberOption(getNumberOption().setMaxValue('test'))).toThrowError();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption().setMaxValue('test'))).toThrowError();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => getBuilder().addNumberOption(getNumberOption().setMinValue('test'))).toThrowError();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption().setMinValue('test'))).toThrowError();
|
||||
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption().setMinValue(1.5))).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a builder with valid number min/max options THEN does not throw an error', () => {
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption().setMinValue(1))).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addNumberOption(getNumberOption().setMinValue(1.5))).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption().setMaxValue(1))).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addNumberOption(getNumberOption().setMaxValue(1.5))).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN an already built builder THEN does not throw an error', () => {
|
||||
expect(() => getBuilder().addStringOption(getStringOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addIntegerOption(getIntegerOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addNumberOption(getNumberOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addBooleanOption(getBooleanOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addUserOption(getUserOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addChannelOption(getChannelOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addRoleOption(getRoleOption())).not.toThrowError();
|
||||
|
||||
expect(() => getBuilder().addMentionableOption(getMentionableOption())).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN no valid return for an addOption method THEN throw error', () => {
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addBooleanOption()).toThrowError();
|
||||
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addBooleanOption(getRoleOption())).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid name THEN throw error', () => {
|
||||
expect(() => getBuilder().setName('TEST_COMMAND')).toThrowError();
|
||||
|
||||
expect(() => getBuilder().setName('ĂĂĂĂĂĂ')).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid names THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('hi_there')).not.toThrowError();
|
||||
|
||||
// Translation: a_command
|
||||
expect(() => getBuilder().setName('o_comandă')).not.toThrowError();
|
||||
|
||||
// Translation: thx (according to GTranslate)
|
||||
expect(() => getBuilder().setName('どうも')).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid returns for builder THEN throw error', () => {
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addBooleanOption(true)).toThrowError();
|
||||
|
||||
expect(() => getBuilder().addBooleanOption(null)).toThrowError();
|
||||
|
||||
expect(() => getBuilder().addBooleanOption(undefined)).toThrowError();
|
||||
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addBooleanOption(() => SlashCommandStringOption)).toThrowError();
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addBooleanOption(() => new Collection())).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid builder with defaultPermission false THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('foo').setDescription('foo').setDefaultPermission(false)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN an option that is autocompletable and has choices, THEN setting choices to an empty array should not throw an error', () => {
|
||||
expect(() =>
|
||||
getBuilder().addStringOption(getStringOption().setAutocomplete(true).setChoices([])),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN an option that is autocompletable, THEN setting choices should throw an error', () => {
|
||||
expect(() =>
|
||||
getBuilder().addStringOption(
|
||||
getStringOption()
|
||||
.setAutocomplete(true)
|
||||
.setChoices([['owo', 'uwu']]),
|
||||
),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN an option, THEN setting choices should not throw an error', () => {
|
||||
expect(() => getBuilder().addStringOption(getStringOption().setChoices([['owo', 'uwu']]))).not.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Builder with subcommand (group) options', () => {
|
||||
test('GIVEN builder with subcommand group THEN does not throw error', () => {
|
||||
expect(() =>
|
||||
getNamedBuilder().addSubcommandGroup((group) => group.setName('group').setDescription('Group us together!')),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN builder with subcommand THEN does not throw error', () => {
|
||||
expect(() =>
|
||||
getNamedBuilder().addSubcommand((subcommand) =>
|
||||
subcommand.setName('boop').setDescription('Boops a fellow nerd (you)'),
|
||||
),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN builder with already built subcommand group THEN does not throw error', () => {
|
||||
expect(() => getNamedBuilder().addSubcommandGroup(getSubcommandGroup())).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN builder with already built subcommand THEN does not throw error', () => {
|
||||
expect(() => getNamedBuilder().addSubcommand(getSubcommand())).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN builder with already built subcommand with options THEN does not throw error', () => {
|
||||
expect(() =>
|
||||
getNamedBuilder().addSubcommand(getSubcommand().addBooleanOption(getBooleanOption())),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
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
|
||||
getNamedBuilder().addSubcommand(getSubcommand()).addInteger(getInteger()),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN no valid return for an addSubcommand(Group) method THEN throw error', () => {
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addSubcommandGroup()).toThrowError();
|
||||
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addSubcommand()).toThrowError();
|
||||
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getBuilder().addSubcommand(getSubcommandGroup())).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Subcommand group builder', () => {
|
||||
test('GIVEN no valid subcommand THEN throw error', () => {
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getSubcommandGroup().addSubcommand()).toThrowError();
|
||||
|
||||
// @ts-expect-error Checking if not providing anything, or an invalid return type causes an error
|
||||
expect(() => getSubcommandGroup().addSubcommand(getSubcommandGroup())).toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN a valid subcommand THEN does not throw an error', () => {
|
||||
expect(() =>
|
||||
getSubcommandGroup()
|
||||
.addSubcommand((sub) => sub.setName('sub').setDescription('Testing 123'))
|
||||
.toJSON(),
|
||||
).not.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Subcommand builder', () => {
|
||||
test('GIVEN a valid subcommand with options THEN does not throw error', () => {
|
||||
expect(() => getSubcommand().addBooleanOption(getBooleanOption()).toJSON()).not.toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
428
packages/builders/__tests__/messages/embed.test.ts
Normal file
428
packages/builders/__tests__/messages/embed.test.ts
Normal file
@@ -0,0 +1,428 @@
|
||||
import { Embed } from '../../src';
|
||||
import type { APIEmbed } from 'discord-api-types/v9';
|
||||
|
||||
const emptyEmbed: APIEmbed = {
|
||||
author: undefined,
|
||||
color: undefined,
|
||||
description: undefined,
|
||||
fields: [],
|
||||
footer: undefined,
|
||||
image: undefined,
|
||||
provider: undefined,
|
||||
thumbnail: undefined,
|
||||
title: undefined,
|
||||
url: undefined,
|
||||
video: undefined,
|
||||
};
|
||||
|
||||
const alpha = 'abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
describe('Embed', () => {
|
||||
describe('Embed getters', () => {
|
||||
test('GIVEN an embed with specific amount of characters THEN returns amount of characters', () => {
|
||||
const embed = new Embed({
|
||||
title: alpha,
|
||||
description: alpha,
|
||||
fields: [{ name: alpha, value: alpha }],
|
||||
author: { name: alpha },
|
||||
footer: { text: alpha },
|
||||
});
|
||||
|
||||
expect(embed.length).toBe(alpha.length * 6);
|
||||
});
|
||||
|
||||
test('GIVEN an embed with zero characters THEN returns amount of characters', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(embed.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed title', () => {
|
||||
test('GIVEN an embed with a pre-defined title THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ title: 'foo' });
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, title: 'foo' });
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setTitle THEN return valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setTitle('foo');
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, title: 'foo' });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined title THEN unset title THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ title: 'foo' });
|
||||
embed.setTitle(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid title THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setTitle('a'.repeat(257))).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed description', () => {
|
||||
test('GIVEN an embed with a pre-defined description THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ ...emptyEmbed, description: 'foo' });
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, description: 'foo' });
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setDescription THEN return valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setDescription('foo');
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, description: 'foo' });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined description THEN unset description THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ description: 'foo' });
|
||||
embed.setDescription(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid description THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setDescription('a'.repeat(4097))).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed URL', () => {
|
||||
test('GIVEN an embed with a pre-defined url THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({ url: 'https://discord.js.org/' });
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
url: 'https://discord.js.org/',
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setURL THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setURL('https://discord.js.org/');
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
url: 'https://discord.js.org/',
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined title THEN unset title THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ url: 'https://discord.js.org' });
|
||||
embed.setURL(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid URL THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setURL('owo')).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Color', () => {
|
||||
test('GIVEN an embed with a pre-defined color THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({ color: 0xff0000 });
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, color: 0xff0000 });
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setColor THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setColor(0xff0000);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, color: 0xff0000 });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined color THEN unset color THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ color: 0xff0000 });
|
||||
embed.setColor(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid color THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => embed.setColor('RED')).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Timestamp', () => {
|
||||
const now = new Date();
|
||||
|
||||
test('GIVEN an embed with a pre-defined timestamp THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({ timestamp: now.toISOString() });
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, timestamp: now.toISOString() });
|
||||
});
|
||||
|
||||
test('given an embed using Embed#setTimestamp (with Date) THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setTimestamp(now);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, timestamp: now.toISOString() });
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setTimestamp (with int) THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setTimestamp(now.getTime());
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, timestamp: now.toISOString() });
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setTimestamp (default) THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setTimestamp();
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, timestamp: embed.timestamp });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined timestamp THEN unset timestamp THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ timestamp: now.toISOString() });
|
||||
embed.setTimestamp(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed, timestamp: undefined });
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Thumbnail', () => {
|
||||
test('GIVEN an embed with a pre-defined thumbnail THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({ thumbnail: { url: 'https://discord.js.org/static/logo.svg' } });
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
thumbnail: { url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setThumbnail THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setThumbnail('https://discord.js.org/static/logo.svg');
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
thumbnail: { url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined thumbnail THEN unset thumbnail THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ thumbnail: { url: 'https://discord.js.org/static/logo.svg' } });
|
||||
embed.setThumbnail(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid thumbnail THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setThumbnail('owo')).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Image', () => {
|
||||
test('GIVEN an embed with a pre-defined image THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({ image: { url: 'https://discord.js.org/static/logo.svg' } });
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
image: { url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setImage THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setImage('https://discord.js.org/static/logo.svg');
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
image: { url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined image THEN unset image THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ image: { url: 'https://discord.js/org/static/logo.svg' } });
|
||||
embed.setImage(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid image THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setImage('owo')).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Author', () => {
|
||||
test('GIVEN an embed with a pre-defined author THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({
|
||||
author: { name: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg', url: 'https://discord.js.org' },
|
||||
});
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
author: { name: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg', url: 'https://discord.js.org' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setAuthor THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setAuthor({
|
||||
name: 'Wumpus',
|
||||
iconURL: 'https://discord.js.org/static/logo.svg',
|
||||
url: 'https://discord.js.org',
|
||||
});
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
author: { name: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg', url: 'https://discord.js.org' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined author THEN unset author THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({
|
||||
author: { name: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg', url: 'https://discord.js.org' },
|
||||
});
|
||||
embed.setAuthor(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with an invalid author name THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setAuthor({ name: 'a'.repeat(257) })).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Footer', () => {
|
||||
test('GIVEN an embed with a pre-defined footer THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({
|
||||
footer: { text: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
footer: { text: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#setAuthor THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.setFooter({ text: 'Wumpus', iconURL: 'https://discord.js.org/static/logo.svg' });
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
footer: { text: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg' },
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed with a pre-defined footer THEN unset footer THEN return valid toJSON data', () => {
|
||||
const embed = new Embed({ footer: { text: 'Wumpus', icon_url: 'https://discord.js.org/static/logo.svg' } });
|
||||
embed.setFooter(null);
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({ ...emptyEmbed });
|
||||
});
|
||||
|
||||
test('GIVEN an embed with invalid footer text THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.setFooter({ text: 'a'.repeat(2049) })).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Embed Fields', () => {
|
||||
test('GIVEN an embed with a pre-defined field THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed({
|
||||
fields: [{ name: 'foo', value: 'bar', inline: undefined }],
|
||||
});
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
fields: [{ name: 'foo', value: 'bar', inline: undefined }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#addField THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.addField({ name: 'foo', value: 'bar' });
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
fields: [{ name: 'foo', value: 'bar', inline: undefined }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#addFields THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.addFields({ name: 'foo', value: 'bar' });
|
||||
|
||||
expect(embed.toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
fields: [{ name: 'foo', value: 'bar', inline: undefined }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#spliceFields THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.addFields({ name: 'foo', value: 'bar' }, { name: 'foo', value: 'baz' });
|
||||
|
||||
expect(embed.spliceFields(0, 1).toJSON()).toStrictEqual({
|
||||
...emptyEmbed,
|
||||
fields: [{ name: 'foo', value: 'baz', inline: undefined }],
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#spliceFields THEN returns valid toJSON data', () => {
|
||||
const embed = new Embed();
|
||||
embed.addFields(...Array.from({ length: 23 }, () => ({ name: 'foo', value: 'bar' })));
|
||||
|
||||
expect(() =>
|
||||
embed.spliceFields(0, 3, ...Array.from({ length: 5 }, () => ({ name: 'foo', value: 'bar' }))),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN an embed using Embed#spliceFields that adds additional fields resulting in fields > 25 THEN throws error', () => {
|
||||
const embed = new Embed();
|
||||
embed.addFields(...Array.from({ length: 23 }, () => ({ name: 'foo', value: 'bar' })));
|
||||
|
||||
expect(() =>
|
||||
embed.spliceFields(0, 3, ...Array.from({ length: 8 }, () => ({ name: 'foo', value: 'bar' }))),
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
describe('GIVEN invalid field amount THEN throws error', () => {
|
||||
test('', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() =>
|
||||
embed.addFields(...Array.from({ length: 26 }, () => ({ name: 'foo', value: 'bar' }))),
|
||||
).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GIVEN invalid field name THEN throws error', () => {
|
||||
test('', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.addFields({ name: '', value: 'bar' })).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GIVEN invalid field name length THEN throws error', () => {
|
||||
test('', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.addFields({ name: 'a'.repeat(257), value: 'bar' })).toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GIVEN invalid field value length THEN throws error', () => {
|
||||
test('', () => {
|
||||
const embed = new Embed();
|
||||
|
||||
expect(() => embed.addFields({ name: '', value: 'a'.repeat(1025) })).toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
206
packages/builders/__tests__/messages/formatters.test.ts
Normal file
206
packages/builders/__tests__/messages/formatters.test.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
import {
|
||||
blockQuote,
|
||||
bold,
|
||||
channelMention,
|
||||
codeBlock,
|
||||
Faces,
|
||||
formatEmoji,
|
||||
hideLinkEmbed,
|
||||
hyperlink,
|
||||
inlineCode,
|
||||
italic,
|
||||
memberNicknameMention,
|
||||
quote,
|
||||
roleMention,
|
||||
spoiler,
|
||||
strikethrough,
|
||||
time,
|
||||
TimestampStyles,
|
||||
underscore,
|
||||
userMention,
|
||||
} from '../../src';
|
||||
|
||||
describe('Message formatters', () => {
|
||||
describe('codeBlock', () => {
|
||||
test('GIVEN "discord.js" with no language THEN returns "```\\ndiscord.js```"', () => {
|
||||
expect<'```\ndiscord.js```'>(codeBlock('discord.js')).toBe('```\ndiscord.js```');
|
||||
});
|
||||
|
||||
test('GIVEN "discord.js" with "js" as language THEN returns "```js\\ndiscord.js```"', () => {
|
||||
expect<'```js\ndiscord.js```'>(codeBlock('js', 'discord.js')).toBe('```js\ndiscord.js```');
|
||||
});
|
||||
});
|
||||
|
||||
describe('inlineCode', () => {
|
||||
test('GIVEN "discord.js" THEN returns "`discord.js`"', () => {
|
||||
expect<'`discord.js`'>(inlineCode('discord.js')).toBe('`discord.js`');
|
||||
});
|
||||
});
|
||||
|
||||
describe('italic', () => {
|
||||
test('GIVEN "discord.js" THEN returns "_discord.js_"', () => {
|
||||
expect<'_discord.js_'>(italic('discord.js')).toBe('_discord.js_');
|
||||
});
|
||||
});
|
||||
|
||||
describe('bold', () => {
|
||||
test('GIVEN "discord.js" THEN returns "**discord.js**"', () => {
|
||||
expect<'**discord.js**'>(bold('discord.js')).toBe('**discord.js**');
|
||||
});
|
||||
});
|
||||
|
||||
describe('underscore', () => {
|
||||
test('GIVEN "discord.js" THEN returns "__discord.js__"', () => {
|
||||
expect<'__discord.js__'>(underscore('discord.js')).toBe('__discord.js__');
|
||||
});
|
||||
});
|
||||
|
||||
describe('strikethrough', () => {
|
||||
test('GIVEN "discord.js" THEN returns "~~discord.js~~"', () => {
|
||||
expect<'~~discord.js~~'>(strikethrough('discord.js')).toBe('~~discord.js~~');
|
||||
});
|
||||
});
|
||||
|
||||
describe('quote', () => {
|
||||
test('GIVEN "discord.js" THEN returns "> discord.js"', () => {
|
||||
expect<'> discord.js'>(quote('discord.js')).toBe('> discord.js');
|
||||
});
|
||||
});
|
||||
|
||||
describe('blockQuote', () => {
|
||||
test('GIVEN "discord.js" THEN returns ">>> discord.js"', () => {
|
||||
expect<'>>> discord.js'>(blockQuote('discord.js')).toBe('>>> discord.js');
|
||||
});
|
||||
});
|
||||
|
||||
describe('hideLinkEmbed', () => {
|
||||
test('GIVEN "https://discord.js.org" THEN returns "<https://discord.js.org>"', () => {
|
||||
expect<'<https://discord.js.org>'>(hideLinkEmbed('https://discord.js.org')).toBe('<https://discord.js.org>');
|
||||
});
|
||||
|
||||
test('GIVEN new URL("https://discord.js.org") THEN returns "<https://discord.js.org>"', () => {
|
||||
expect<`<${string}>`>(hideLinkEmbed(new URL('https://discord.js.org/'))).toBe('<https://discord.js.org/>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('hyperlink', () => {
|
||||
test('GIVEN content and string URL THEN returns "[content](url)"', () => {
|
||||
expect<'[discord.js](https://discord.js.org)'>(hyperlink('discord.js', 'https://discord.js.org')).toBe(
|
||||
'[discord.js](https://discord.js.org)',
|
||||
);
|
||||
});
|
||||
|
||||
test('GIVEN content and URL THEN returns "[content](url)"', () => {
|
||||
expect<`[discord.js](${string})`>(hyperlink('discord.js', new URL('https://discord.js.org'))).toBe(
|
||||
'[discord.js](https://discord.js.org/)',
|
||||
);
|
||||
});
|
||||
|
||||
test('GIVEN content, string URL, and title THEN returns "[content](url "title")"', () => {
|
||||
expect<'[discord.js](https://discord.js.org "Official Documentation")'>(
|
||||
hyperlink('discord.js', 'https://discord.js.org', 'Official Documentation'),
|
||||
).toBe('[discord.js](https://discord.js.org "Official Documentation")');
|
||||
});
|
||||
|
||||
test('GIVEN content, URL, and title THEN returns "[content](url "title")"', () => {
|
||||
expect<`[discord.js](${string} "Official Documentation")`>(
|
||||
hyperlink('discord.js', new URL('https://discord.js.org'), 'Official Documentation'),
|
||||
).toBe('[discord.js](https://discord.js.org/ "Official Documentation")');
|
||||
});
|
||||
});
|
||||
|
||||
describe('spoiler', () => {
|
||||
test('GIVEN "discord.js" THEN returns "||discord.js||"', () => {
|
||||
expect<'||discord.js||'>(spoiler('discord.js')).toBe('||discord.js||');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mentions', () => {
|
||||
describe('userMention', () => {
|
||||
test('GIVEN userId THEN returns "<@[userId]>"', () => {
|
||||
expect(userMention('139836912335716352')).toBe('<@139836912335716352>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('memberNicknameMention', () => {
|
||||
test('GIVEN memberId THEN returns "<@![memberId]>"', () => {
|
||||
expect(memberNicknameMention('139836912335716352')).toBe('<@!139836912335716352>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('channelMention', () => {
|
||||
test('GIVEN channelId THEN returns "<#[channelId]>"', () => {
|
||||
expect(channelMention('829924760309334087')).toBe('<#829924760309334087>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('roleMention', () => {
|
||||
test('GIVEN roleId THEN returns "<&[roleId]>"', () => {
|
||||
expect(roleMention('815434166602170409')).toBe('<@&815434166602170409>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatEmoji', () => {
|
||||
test('GIVEN static emojiId THEN returns "<:_:${emojiId}>"', () => {
|
||||
expect<`<:_:851461487498493952>`>(formatEmoji('851461487498493952')).toBe('<:_:851461487498493952>');
|
||||
});
|
||||
|
||||
test('GIVEN static emojiId WITH animated explicitly false THEN returns "<:_:[emojiId]>"', () => {
|
||||
expect<`<:_:851461487498493952>`>(formatEmoji('851461487498493952', false)).toBe('<:_:851461487498493952>');
|
||||
});
|
||||
|
||||
test('GIVEN animated emojiId THEN returns "<a:_:${emojiId}>"', () => {
|
||||
expect<`<a:_:827220205352255549>`>(formatEmoji('827220205352255549', true)).toBe('<a:_:827220205352255549>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('time', () => {
|
||||
test('GIVEN no arguments THEN returns "<t:${bigint}>"', () => {
|
||||
jest.useFakeTimers('modern');
|
||||
jest.setSystemTime(1566424897579);
|
||||
|
||||
expect<`<t:${bigint}>`>(time()).toBe('<t:1566424897>');
|
||||
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
test('GIVEN a date THEN returns "<t:${bigint}>"', () => {
|
||||
expect<`<t:${bigint}>`>(time(new Date(1867424897579))).toBe('<t:1867424897>');
|
||||
});
|
||||
|
||||
test('GIVEN a date and a style from string THEN returns "<t:${bigint}:${style}>"', () => {
|
||||
expect<`<t:${bigint}:d>`>(time(new Date(1867424897579), 'd')).toBe('<t:1867424897:d>');
|
||||
});
|
||||
|
||||
test('GIVEN a date and a format from enum THEN returns "<t:${bigint}:${style}>"', () => {
|
||||
expect<`<t:${bigint}:R>`>(time(new Date(1867424897579), TimestampStyles.RelativeTime)).toBe('<t:1867424897:R>');
|
||||
});
|
||||
|
||||
test('GIVEN a date THEN returns "<t:${time}>"', () => {
|
||||
expect<'<t:1867424897>'>(time(1867424897)).toBe('<t:1867424897>');
|
||||
});
|
||||
|
||||
test('GIVEN a date and a style from string THEN returns "<t:${time}:${style}>"', () => {
|
||||
expect<'<t:1867424897:d>'>(time(1867424897, 'd')).toBe('<t:1867424897:d>');
|
||||
});
|
||||
|
||||
test('GIVEN a date and a format from enum THEN returns "<t:${time}:${style}>"', () => {
|
||||
expect<'<t:1867424897:R>'>(time(1867424897, TimestampStyles.RelativeTime)).toBe('<t:1867424897:R>');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Faces', () => {
|
||||
test('GIVEN Faces.Shrug THEN returns "¯\\_(ツ)\\_/¯"', () => {
|
||||
expect<'¯\\_(ツ)\\_/¯'>(Faces.Shrug).toBe('¯\\_(ツ)\\_/¯');
|
||||
});
|
||||
|
||||
test('GIVEN Faces.Tableflip THEN returns "(╯°□°)╯︵ ┻━┻"', () => {
|
||||
expect<'(╯°□°)╯︵ ┻━┻'>(Faces.Tableflip).toBe('(╯°□°)╯︵ ┻━┻');
|
||||
});
|
||||
|
||||
test('GIVEN Faces.Unflip THEN returns "┬─┬ ノ( ゜-゜ノ)"', () => {
|
||||
expect<'┬─┬ ノ( ゜-゜ノ)'>(Faces.Unflip).toBe('┬─┬ ノ( ゜-゜ノ)');
|
||||
});
|
||||
});
|
||||
});
|
||||
18
packages/builders/babel.config.js
Normal file
18
packages/builders/babel.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @type {import('@babel/core').TransformOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
parserOpts: { strictMode: true },
|
||||
sourceMaps: 'inline',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: { node: 'current' },
|
||||
modules: 'commonjs',
|
||||
},
|
||||
],
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
plugins: ['babel-plugin-transform-typescript-metadata', ['@babel/plugin-proposal-decorators', { legacy: true }]],
|
||||
};
|
||||
10
packages/builders/codecov.yml
Normal file
10
packages/builders/codecov.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 70%
|
||||
threshold: 5%
|
||||
patch:
|
||||
default:
|
||||
target: 70%
|
||||
threshold: 5%
|
||||
1
packages/builders/docs/README.md
Normal file
1
packages/builders/docs/README.md
Normal file
@@ -0,0 +1 @@
|
||||
## [View the documentation here.](https://discord.js.org/#/docs/builders)
|
||||
5
packages/builders/docs/index.yml
Normal file
5
packages/builders/docs/index.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: General
|
||||
files:
|
||||
- name: Welcome
|
||||
id: welcome
|
||||
path: ../../README.md
|
||||
19
packages/builders/jest.config.js
Normal file
19
packages/builders/jest.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @type {import('@jest/types').Config.InitialOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
|
||||
testEnvironment: 'node',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
coverageDirectory: 'coverage',
|
||||
coverageReporters: ['text', 'lcov', 'clover'],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 70,
|
||||
lines: 70,
|
||||
statements: 70,
|
||||
},
|
||||
},
|
||||
coveragePathIgnorePatterns: ['src/index.ts'],
|
||||
};
|
||||
88
packages/builders/package.json
Normal file
88
packages/builders/package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "@discordjs/builders",
|
||||
"version": "0.11.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}",
|
||||
"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 './*'"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.js"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "src",
|
||||
"test": "__tests__"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"contributors": [
|
||||
"Vlad Frangu <kingdgrizzle@gmail.com>",
|
||||
"Crawl <icrawltogo@gmail.com>",
|
||||
"Amish Shah <amishshah.2k@gmail.com>",
|
||||
"SpaceEEC <spaceeec@yahoo.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"discord",
|
||||
"api",
|
||||
"bot",
|
||||
"client",
|
||||
"node",
|
||||
"discordapp",
|
||||
"discordjs"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/discordjs/discord.js.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/discordjs/discord.js/issues"
|
||||
},
|
||||
"homepage": "https://discord.js.org",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.2.0",
|
||||
"discord-api-types": "^0.26.0",
|
||||
"ts-mixer": "^6.0.0",
|
||||
"tslib": "^2.3.1",
|
||||
"zod": "^3.11.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.5",
|
||||
"@babel/plugin-proposal-decorators": "^7.16.5",
|
||||
"@babel/preset-env": "^7.16.5",
|
||||
"@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",
|
||||
"babel-plugin-transform-typescript-metadata": "^0.3.2",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-config-marine": "^9.1.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.4.5",
|
||||
"prettier": "^2.5.1",
|
||||
"standard-version": "^9.3.2",
|
||||
"tsup": "^5.11.8",
|
||||
"typedoc": "^0.22.10",
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
7
packages/builders/scripts/docs.mjs
Normal file
7
packages/builders/scripts/docs.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
import { runGenerator } from '@discordjs/ts-docgen';
|
||||
|
||||
runGenerator({
|
||||
existingOutput: 'docs/typedoc-out.json',
|
||||
custom: 'docs/index.yml',
|
||||
output: 'docs/docs.json',
|
||||
});
|
||||
18
packages/builders/src/index.ts
Normal file
18
packages/builders/src/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export * as EmbedAssertions from './messages/embed/Assertions';
|
||||
export * from './messages/embed/Embed';
|
||||
export * from './messages/formatters';
|
||||
|
||||
export * as SlashCommandAssertions from './interactions/slashCommands/Assertions';
|
||||
export * from './interactions/slashCommands/SlashCommandBuilder';
|
||||
export * from './interactions/slashCommands/SlashCommandSubcommands';
|
||||
export * from './interactions/slashCommands/options/boolean';
|
||||
export * from './interactions/slashCommands/options/channel';
|
||||
export * from './interactions/slashCommands/options/integer';
|
||||
export * from './interactions/slashCommands/options/mentionable';
|
||||
export * from './interactions/slashCommands/options/number';
|
||||
export * from './interactions/slashCommands/options/role';
|
||||
export * from './interactions/slashCommands/options/string';
|
||||
export * from './interactions/slashCommands/options/user';
|
||||
|
||||
export * as ContextMenuCommandAssertions from './interactions/contextMenuCommands/Assertions';
|
||||
export * from './interactions/contextMenuCommands/ContextMenuCommandBuilder';
|
||||
@@ -0,0 +1,33 @@
|
||||
import { z } from 'zod';
|
||||
import { ApplicationCommandType } from 'discord-api-types/v9';
|
||||
import type { ContextMenuCommandType } from './ContextMenuCommandBuilder';
|
||||
|
||||
export function validateRequiredParameters(name: string, type: number) {
|
||||
// Assert name matches all conditions
|
||||
validateName(name);
|
||||
|
||||
// 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);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { validateRequiredParameters, validateName, validateType, validateDefaultPermission } from './Assertions';
|
||||
import type { ApplicationCommandType, RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v9';
|
||||
|
||||
export class ContextMenuCommandBuilder {
|
||||
/**
|
||||
* The name of this context menu command
|
||||
*/
|
||||
public readonly name: string = undefined!;
|
||||
|
||||
/**
|
||||
* The type of this context menu command
|
||||
*/
|
||||
public readonly type: ContextMenuCommandType = undefined!;
|
||||
|
||||
/**
|
||||
* Whether the command is enabled by default when the app is added to a guild
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
public readonly defaultPermission: boolean | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Sets the name
|
||||
*
|
||||
* @param name The name
|
||||
*/
|
||||
public setName(name: string) {
|
||||
// Assert the name matches the conditions
|
||||
validateName(name);
|
||||
|
||||
Reflect.set(this, 'name', name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type
|
||||
*
|
||||
* @param type The type
|
||||
*/
|
||||
public setType(type: ContextMenuCommandType) {
|
||||
// Assert the type is valid
|
||||
validateType(type);
|
||||
|
||||
Reflect.set(this, 'type', type);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the command is enabled by default when the application is added to a guild.
|
||||
*
|
||||
* **Note**: If set to `false`, you will have to later `PUT` the permissions for this command.
|
||||
*
|
||||
* @param value Whether or not to enable this command by default
|
||||
*
|
||||
* @see https://discord.com/developers/docs/interactions/application-commands#permissions
|
||||
*/
|
||||
public setDefaultPermission(value: boolean) {
|
||||
// Assert the value matches the conditions
|
||||
validateDefaultPermission(value);
|
||||
|
||||
Reflect.set(this, 'defaultPermission', value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the final data that should be sent to Discord.
|
||||
*
|
||||
* **Note:** Calling this function will validate required properties based on their conditions.
|
||||
*/
|
||||
public toJSON(): RESTPostAPIApplicationCommandsJSONBody {
|
||||
validateRequiredParameters(this.name, this.type);
|
||||
return {
|
||||
name: this.name,
|
||||
type: this.type,
|
||||
default_permission: this.defaultPermission,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export type ContextMenuCommandType = ApplicationCommandType.User | ApplicationCommandType.Message;
|
||||
@@ -0,0 +1,84 @@
|
||||
import is from '@sindresorhus/is';
|
||||
import type { APIApplicationCommandOptionChoice } from 'discord-api-types/v9';
|
||||
import { z } from 'zod';
|
||||
import type { ApplicationCommandOptionBase } from './mixins/ApplicationCommandOptionBase';
|
||||
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)
|
||||
.max(32)
|
||||
.regex(/^[\P{Lu}\p{N}_-]+$/u);
|
||||
|
||||
export function validateName(name: unknown): asserts name is string {
|
||||
namePredicate.parse(name);
|
||||
}
|
||||
|
||||
const descriptionPredicate = z.string().min(1).max(100);
|
||||
|
||||
export function validateDescription(description: unknown): asserts description is string {
|
||||
descriptionPredicate.parse(description);
|
||||
}
|
||||
|
||||
const booleanPredicate = z.boolean();
|
||||
|
||||
export function validateDefaultPermission(value: unknown): asserts value is boolean {
|
||||
booleanPredicate.parse(value);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
export function assertReturnOfBuilder<
|
||||
T extends ApplicationCommandOptionBase | SlashCommandSubcommandBuilder | SlashCommandSubcommandGroupBuilder,
|
||||
>(input: unknown, ExpectedInstanceOf: new () => T): asserts input is T {
|
||||
const instanceName = ExpectedInstanceOf.name;
|
||||
|
||||
if (is.nullOrUndefined(input)) {
|
||||
throw new TypeError(
|
||||
`Expected to receive a ${instanceName} builder, got ${input === null ? 'null' : 'undefined'} instead.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (is.primitive(input)) {
|
||||
throw new TypeError(`Expected to receive a ${instanceName} builder, got a primitive (${typeof input}) instead.`);
|
||||
}
|
||||
|
||||
if (!(input instanceof ExpectedInstanceOf)) {
|
||||
const casted = input as Record<PropertyKey, unknown>;
|
||||
|
||||
const constructorName = is.function_(input) ? input.name : casted.constructor.name;
|
||||
const stringTag = Reflect.get(casted, Symbol.toStringTag) as string | undefined;
|
||||
|
||||
const fullResultName = stringTag ? `${constructorName} [${stringTag}]` : constructorName;
|
||||
|
||||
throw new TypeError(`Expected to receive a ${instanceName} builder, got ${fullResultName} instead.`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import type { APIApplicationCommandOption, RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import {
|
||||
assertReturnOfBuilder,
|
||||
validateDefaultPermission,
|
||||
validateMaxOptionsLength,
|
||||
validateRequiredParameters,
|
||||
} from './Assertions';
|
||||
import { SharedSlashCommandOptions } from './mixins/SharedSlashCommandOptions';
|
||||
import { SharedNameAndDescription } from './mixins/NameAndDescription';
|
||||
import { SlashCommandSubcommandBuilder, SlashCommandSubcommandGroupBuilder } from './SlashCommandSubcommands';
|
||||
|
||||
@mix(SharedSlashCommandOptions, SharedNameAndDescription)
|
||||
export class SlashCommandBuilder {
|
||||
/**
|
||||
* The name of this slash command
|
||||
*/
|
||||
public readonly name: string = undefined!;
|
||||
|
||||
/**
|
||||
* The description of this slash command
|
||||
*/
|
||||
public readonly description: string = undefined!;
|
||||
|
||||
/**
|
||||
* The options of this slash command
|
||||
*/
|
||||
public readonly options: ToAPIApplicationCommandOptions[] = [];
|
||||
|
||||
/**
|
||||
* Whether the command is enabled by default when the app is added to a guild
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
public readonly defaultPermission: boolean | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Returns the final data that should be sent to Discord.
|
||||
*
|
||||
* **Note:** Calling this function will validate required properties based on their conditions.
|
||||
*/
|
||||
public toJSON(): RESTPostAPIApplicationCommandsJSONBody {
|
||||
validateRequiredParameters(this.name, this.description, this.options);
|
||||
|
||||
return {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: this.options.map((option) => option.toJSON()),
|
||||
default_permission: this.defaultPermission,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the command is enabled by default when the application is added to a guild.
|
||||
*
|
||||
* **Note**: If set to `false`, you will have to later `PUT` the permissions for this command.
|
||||
*
|
||||
* @param value Whether or not to enable this command by default
|
||||
*
|
||||
* @see https://discord.com/developers/docs/interactions/application-commands#permissions
|
||||
*/
|
||||
public setDefaultPermission(value: boolean) {
|
||||
// Assert the value matches the conditions
|
||||
validateDefaultPermission(value);
|
||||
|
||||
Reflect.set(this, 'defaultPermission', value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new subcommand group to this command
|
||||
*
|
||||
* @param input A function that returns a subcommand group builder, or an already built builder
|
||||
*/
|
||||
public addSubcommandGroup(
|
||||
input:
|
||||
| SlashCommandSubcommandGroupBuilder
|
||||
| ((subcommandGroup: SlashCommandSubcommandGroupBuilder) => SlashCommandSubcommandGroupBuilder),
|
||||
): SlashCommandSubcommandsOnlyBuilder {
|
||||
const { options } = this;
|
||||
|
||||
// First, assert options conditions - we cannot have more than 25 options
|
||||
validateMaxOptionsLength(options);
|
||||
|
||||
// Get the final result
|
||||
const result = typeof input === 'function' ? input(new SlashCommandSubcommandGroupBuilder()) : input;
|
||||
|
||||
assertReturnOfBuilder(result, SlashCommandSubcommandGroupBuilder);
|
||||
|
||||
// Push it
|
||||
options.push(result);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new subcommand to this command
|
||||
*
|
||||
* @param input A function that returns a subcommand builder, or an already built builder
|
||||
*/
|
||||
public addSubcommand(
|
||||
input:
|
||||
| SlashCommandSubcommandBuilder
|
||||
| ((subcommandGroup: SlashCommandSubcommandBuilder) => SlashCommandSubcommandBuilder),
|
||||
): SlashCommandSubcommandsOnlyBuilder {
|
||||
const { options } = this;
|
||||
|
||||
// First, assert options conditions - we cannot have more than 25 options
|
||||
validateMaxOptionsLength(options);
|
||||
|
||||
// Get the final result
|
||||
const result = typeof input === 'function' ? input(new SlashCommandSubcommandBuilder()) : input;
|
||||
|
||||
assertReturnOfBuilder(result, SlashCommandSubcommandBuilder);
|
||||
|
||||
// Push it
|
||||
options.push(result);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandBuilder extends SharedNameAndDescription, SharedSlashCommandOptions {}
|
||||
|
||||
export interface SlashCommandSubcommandsOnlyBuilder
|
||||
extends SharedNameAndDescription,
|
||||
Pick<SlashCommandBuilder, 'toJSON' | 'addSubcommand' | 'addSubcommandGroup'> {}
|
||||
|
||||
export interface SlashCommandOptionsOnlyBuilder
|
||||
extends SharedNameAndDescription,
|
||||
SharedSlashCommandOptions,
|
||||
Pick<SlashCommandBuilder, 'toJSON'> {}
|
||||
|
||||
export interface ToAPIApplicationCommandOptions {
|
||||
toJSON(): APIApplicationCommandOption;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
APIApplicationCommandSubcommandGroupOption,
|
||||
APIApplicationCommandSubcommandOption,
|
||||
ApplicationCommandOptionType,
|
||||
} from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import { assertReturnOfBuilder, validateMaxOptionsLength, validateRequiredParameters } from './Assertions';
|
||||
import type { ApplicationCommandOptionBase } from './mixins/ApplicationCommandOptionBase';
|
||||
import { SharedNameAndDescription } from './mixins/NameAndDescription';
|
||||
import { SharedSlashCommandOptions } from './mixins/SharedSlashCommandOptions';
|
||||
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
|
||||
*/
|
||||
@mix(SharedNameAndDescription)
|
||||
export class SlashCommandSubcommandGroupBuilder implements ToAPIApplicationCommandOptions {
|
||||
/**
|
||||
* The name of this subcommand group
|
||||
*/
|
||||
public readonly name: string = undefined!;
|
||||
|
||||
/**
|
||||
* The description of this subcommand group
|
||||
*/
|
||||
public readonly description: string = undefined!;
|
||||
|
||||
/**
|
||||
* The subcommands part of this subcommand group
|
||||
*/
|
||||
public readonly options: SlashCommandSubcommandBuilder[] = [];
|
||||
|
||||
/**
|
||||
* Adds a new subcommand to this group
|
||||
*
|
||||
* @param input A function that returns a subcommand builder, or an already built builder
|
||||
*/
|
||||
public addSubcommand(
|
||||
input:
|
||||
| SlashCommandSubcommandBuilder
|
||||
| ((subcommandGroup: SlashCommandSubcommandBuilder) => SlashCommandSubcommandBuilder),
|
||||
) {
|
||||
const { options } = this;
|
||||
|
||||
// First, assert options conditions - we cannot have more than 25 options
|
||||
validateMaxOptionsLength(options);
|
||||
|
||||
// Get the final result
|
||||
const result = typeof input === 'function' ? input(new SlashCommandSubcommandBuilder()) : input;
|
||||
|
||||
assertReturnOfBuilder(result, SlashCommandSubcommandBuilder);
|
||||
|
||||
// Push it
|
||||
options.push(result);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public toJSON(): APIApplicationCommandSubcommandGroupOption {
|
||||
validateRequiredParameters(this.name, this.description, this.options);
|
||||
|
||||
return {
|
||||
type: ApplicationCommandOptionType.SubcommandGroup,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: this.options.map((option) => option.toJSON()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandSubcommandGroupBuilder extends SharedNameAndDescription {}
|
||||
|
||||
/**
|
||||
* Represents a subcommand
|
||||
*
|
||||
* For more information, go to https://discord.com/developers/docs/interactions/slash-commands#subcommands-and-subcommand-groups
|
||||
*/
|
||||
@mix(SharedNameAndDescription, SharedSlashCommandOptions)
|
||||
export class SlashCommandSubcommandBuilder implements ToAPIApplicationCommandOptions {
|
||||
/**
|
||||
* The name of this subcommand
|
||||
*/
|
||||
public readonly name: string = undefined!;
|
||||
|
||||
/**
|
||||
* The description of this subcommand
|
||||
*/
|
||||
public readonly description: string = undefined!;
|
||||
|
||||
/**
|
||||
* The options of this subcommand
|
||||
*/
|
||||
public readonly options: ApplicationCommandOptionBase[] = [];
|
||||
|
||||
public toJSON(): APIApplicationCommandSubcommandOption {
|
||||
validateRequiredParameters(this.name, this.description, this.options);
|
||||
|
||||
return {
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: this.options.map((option) => option.toJSON()),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandSubcommandBuilder extends SharedNameAndDescription, SharedSlashCommandOptions<false> {}
|
||||
@@ -0,0 +1,16 @@
|
||||
export abstract class ApplicationCommandNumericOptionMinMaxValueMixin {
|
||||
public readonly max_value?: number;
|
||||
public readonly min_value?: number;
|
||||
|
||||
/**
|
||||
* Sets the maximum number value of this option
|
||||
* @param max The maximum value this option can be
|
||||
*/
|
||||
public abstract setMaxValue(max: number): this;
|
||||
|
||||
/**
|
||||
* Sets the minimum number value of this option
|
||||
* @param min The minimum value this option can be
|
||||
*/
|
||||
public abstract setMinValue(min: number): this;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { APIApplicationCommandBasicOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { validateRequiredParameters, validateRequired } from '../Assertions';
|
||||
import { SharedNameAndDescription } from './NameAndDescription';
|
||||
|
||||
export abstract class ApplicationCommandOptionBase extends SharedNameAndDescription {
|
||||
public abstract readonly type: ApplicationCommandOptionType;
|
||||
|
||||
public readonly required = false;
|
||||
|
||||
/**
|
||||
* Marks the option as required
|
||||
*
|
||||
* @param required If this option should be required
|
||||
*/
|
||||
public setRequired(required: boolean) {
|
||||
// Assert that you actually passed a boolean
|
||||
validateRequired(required);
|
||||
|
||||
Reflect.set(this, 'required', required);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract toJSON(): APIApplicationCommandBasicOption;
|
||||
|
||||
protected runRequiredValidations() {
|
||||
validateRequiredParameters(this.name, this.description, []);
|
||||
|
||||
// Assert that you actually passed a boolean
|
||||
validateRequired(this.required);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { ChannelType } from 'discord-api-types/v9';
|
||||
import { z, ZodLiteral } from 'zod';
|
||||
|
||||
// Only allow valid channel types to be used. (This can't be dynamic because const enums are erased at runtime)
|
||||
const allowedChannelTypes = [
|
||||
ChannelType.GuildText,
|
||||
ChannelType.GuildVoice,
|
||||
ChannelType.GuildCategory,
|
||||
ChannelType.GuildNews,
|
||||
ChannelType.GuildStore,
|
||||
ChannelType.GuildNewsThread,
|
||||
ChannelType.GuildPublicThread,
|
||||
ChannelType.GuildPrivateThread,
|
||||
ChannelType.GuildStageVoice,
|
||||
] as const;
|
||||
|
||||
export type ApplicationCommandOptionAllowedChannelTypes = typeof allowedChannelTypes[number];
|
||||
|
||||
const channelTypePredicate = z.union(
|
||||
allowedChannelTypes.map((type) => z.literal(type)) as [
|
||||
ZodLiteral<ChannelType>,
|
||||
ZodLiteral<ChannelType>,
|
||||
...ZodLiteral<ChannelType>[]
|
||||
],
|
||||
);
|
||||
|
||||
export class ApplicationCommandOptionChannelTypesMixin {
|
||||
public readonly channel_types?: ApplicationCommandOptionAllowedChannelTypes[];
|
||||
|
||||
/**
|
||||
* Adds a channel type to this option
|
||||
*
|
||||
* @param channelType The type of channel to allow
|
||||
*/
|
||||
public addChannelType(channelType: ApplicationCommandOptionAllowedChannelTypes) {
|
||||
if (this.channel_types === undefined) {
|
||||
Reflect.set(this, 'channel_types', []);
|
||||
}
|
||||
|
||||
channelTypePredicate.parse(channelType);
|
||||
this.channel_types!.push(channelType);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds channel types to this option
|
||||
*
|
||||
* @param channelTypes The channel types to add
|
||||
*/
|
||||
public addChannelTypes(channelTypes: ApplicationCommandOptionAllowedChannelTypes[]) {
|
||||
channelTypes.forEach((channelType) => this.addChannelType(channelType));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { APIApplicationCommandOptionChoice, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { z } from 'zod';
|
||||
import { validateMaxChoicesLength } from '../Assertions';
|
||||
|
||||
const stringPredicate = z.string().min(1).max(100);
|
||||
const numberPredicate = z.number().gt(-Infinity).lt(Infinity);
|
||||
const choicesPredicate = z.tuple([stringPredicate, z.union([stringPredicate, numberPredicate])]).array();
|
||||
const booleanPredicate = z.boolean();
|
||||
|
||||
export class ApplicationCommandOptionWithChoicesAndAutocompleteMixin<T extends string | number> {
|
||||
public readonly choices?: APIApplicationCommandOptionChoice<T>[];
|
||||
public readonly autocomplete?: boolean;
|
||||
|
||||
// Since this is present and this is a mixin, this is needed
|
||||
public readonly type!: ApplicationCommandOptionType;
|
||||
|
||||
/**
|
||||
* Adds a choice for this option
|
||||
*
|
||||
* @param name The name of the choice
|
||||
* @param value The value of the choice
|
||||
*/
|
||||
public addChoice(name: string, value: T): Omit<this, 'setAutocomplete'> {
|
||||
if (this.autocomplete) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
if (this.choices === undefined) {
|
||||
Reflect.set(this, 'choices', []);
|
||||
}
|
||||
|
||||
validateMaxChoicesLength(this.choices!);
|
||||
|
||||
// Validate name
|
||||
stringPredicate.parse(name);
|
||||
|
||||
// Validate the value
|
||||
if (this.type === ApplicationCommandOptionType.String) {
|
||||
stringPredicate.parse(value);
|
||||
} else {
|
||||
numberPredicate.parse(value);
|
||||
}
|
||||
|
||||
this.choices!.push({ name, value });
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple choices for this option
|
||||
*
|
||||
* @param choices The choices to add
|
||||
*/
|
||||
public addChoices(choices: [name: string, value: T][]): Omit<this, 'setAutocomplete'> {
|
||||
if (this.autocomplete) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
choicesPredicate.parse(choices);
|
||||
|
||||
for (const [label, value] of choices) this.addChoice(label, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public setChoices<Input extends [name: string, value: T][]>(
|
||||
choices: Input,
|
||||
): Input extends []
|
||||
? this & Pick<ApplicationCommandOptionWithChoicesAndAutocompleteMixin<T>, 'setAutocomplete'>
|
||||
: Omit<this, 'setAutocomplete'> {
|
||||
if (choices.length > 0 && this.autocomplete) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
choicesPredicate.parse(choices);
|
||||
|
||||
Reflect.set(this, 'choices', []);
|
||||
for (const [label, value] of choices) this.addChoice(label, value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the option as autocompletable
|
||||
* @param autocomplete If this option should be autocompletable
|
||||
*/
|
||||
public setAutocomplete<U extends boolean>(
|
||||
autocomplete: U,
|
||||
): U extends true
|
||||
? Omit<this, 'addChoice' | 'addChoices'>
|
||||
: this & Pick<ApplicationCommandOptionWithChoicesAndAutocompleteMixin<T>, 'addChoice' | 'addChoices'> {
|
||||
// Assert that you actually passed a boolean
|
||||
booleanPredicate.parse(autocomplete);
|
||||
|
||||
if (autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
Reflect.set(this, 'autocomplete', autocomplete);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { validateDescription, validateName } from '../Assertions';
|
||||
|
||||
export class SharedNameAndDescription {
|
||||
public readonly name!: string;
|
||||
public readonly description!: string;
|
||||
|
||||
/**
|
||||
* Sets the name
|
||||
*
|
||||
* @param name The name
|
||||
*/
|
||||
public setName(name: string): this {
|
||||
// Assert the name matches the conditions
|
||||
validateName(name);
|
||||
|
||||
Reflect.set(this, 'name', name);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description
|
||||
*
|
||||
* @param description The description
|
||||
*/
|
||||
public setDescription(description: string) {
|
||||
// Assert the description matches the conditions
|
||||
validateDescription(description);
|
||||
|
||||
Reflect.set(this, 'description', description);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
import { assertReturnOfBuilder, validateMaxOptionsLength } from '../Assertions';
|
||||
import type { ApplicationCommandOptionBase } from './ApplicationCommandOptionBase';
|
||||
import { SlashCommandBooleanOption } from '../options/boolean';
|
||||
import { SlashCommandChannelOption } from '../options/channel';
|
||||
import { SlashCommandIntegerOption } from '../options/integer';
|
||||
import { SlashCommandMentionableOption } from '../options/mentionable';
|
||||
import { SlashCommandNumberOption } from '../options/number';
|
||||
import { SlashCommandRoleOption } from '../options/role';
|
||||
import { SlashCommandStringOption } from '../options/string';
|
||||
import { SlashCommandUserOption } from '../options/user';
|
||||
import type { ToAPIApplicationCommandOptions } from '../SlashCommandBuilder';
|
||||
|
||||
export class SharedSlashCommandOptions<ShouldOmitSubcommandFunctions = true> {
|
||||
public readonly options!: ToAPIApplicationCommandOptions[];
|
||||
|
||||
/**
|
||||
* Adds a boolean option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addBooleanOption(
|
||||
input: SlashCommandBooleanOption | ((builder: SlashCommandBooleanOption) => SlashCommandBooleanOption),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandBooleanOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a user option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addUserOption(input: SlashCommandUserOption | ((builder: SlashCommandUserOption) => SlashCommandUserOption)) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandUserOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a channel option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addChannelOption(
|
||||
input: SlashCommandChannelOption | ((builder: SlashCommandChannelOption) => SlashCommandChannelOption),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandChannelOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a role option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addRoleOption(input: SlashCommandRoleOption | ((builder: SlashCommandRoleOption) => SlashCommandRoleOption)) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandRoleOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a mentionable option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addMentionableOption(
|
||||
input: SlashCommandMentionableOption | ((builder: SlashCommandMentionableOption) => SlashCommandMentionableOption),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandMentionableOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a string option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addStringOption(
|
||||
input:
|
||||
| SlashCommandStringOption
|
||||
| Omit<SlashCommandStringOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandStringOption, 'addChoice' | 'addChoices'>
|
||||
| ((
|
||||
builder: SlashCommandStringOption,
|
||||
) =>
|
||||
| SlashCommandStringOption
|
||||
| Omit<SlashCommandStringOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandStringOption, 'addChoice' | 'addChoices'>),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandStringOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an integer option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addIntegerOption(
|
||||
input:
|
||||
| SlashCommandIntegerOption
|
||||
| Omit<SlashCommandIntegerOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandIntegerOption, 'addChoice' | 'addChoices'>
|
||||
| ((
|
||||
builder: SlashCommandIntegerOption,
|
||||
) =>
|
||||
| SlashCommandIntegerOption
|
||||
| Omit<SlashCommandIntegerOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandIntegerOption, 'addChoice' | 'addChoices'>),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandIntegerOption);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a number option
|
||||
*
|
||||
* @param input A function that returns an option builder, or an already built builder
|
||||
*/
|
||||
public addNumberOption(
|
||||
input:
|
||||
| SlashCommandNumberOption
|
||||
| Omit<SlashCommandNumberOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandNumberOption, 'addChoice' | 'addChoices'>
|
||||
| ((
|
||||
builder: SlashCommandNumberOption,
|
||||
) =>
|
||||
| SlashCommandNumberOption
|
||||
| Omit<SlashCommandNumberOption, 'setAutocomplete'>
|
||||
| Omit<SlashCommandNumberOption, 'addChoice' | 'addChoices'>),
|
||||
) {
|
||||
return this._sharedAddOptionMethod(input, SlashCommandNumberOption);
|
||||
}
|
||||
|
||||
private _sharedAddOptionMethod<T extends ApplicationCommandOptionBase>(
|
||||
input:
|
||||
| T
|
||||
| Omit<T, 'setAutocomplete'>
|
||||
| Omit<T, 'addChoice' | 'addChoices'>
|
||||
| ((builder: T) => T | Omit<T, 'setAutocomplete'> | Omit<T, 'addChoice' | 'addChoices'>),
|
||||
Instance: new () => T,
|
||||
): ShouldOmitSubcommandFunctions extends true ? Omit<this, 'addSubcommand' | 'addSubcommandGroup'> : this {
|
||||
const { options } = this;
|
||||
|
||||
// First, assert options conditions - we cannot have more than 25 options
|
||||
validateMaxOptionsLength(options);
|
||||
|
||||
// Get the final result
|
||||
const result = typeof input === 'function' ? input(new Instance()) : input;
|
||||
|
||||
assertReturnOfBuilder(result, Instance);
|
||||
|
||||
// Push it
|
||||
options.push(result);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { APIApplicationCommandBooleanOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
|
||||
export class SlashCommandBooleanOption extends ApplicationCommandOptionBase {
|
||||
public readonly type = ApplicationCommandOptionType.Boolean as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandBooleanOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { APIApplicationCommandChannelOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
import { ApplicationCommandOptionChannelTypesMixin } from '../mixins/ApplicationCommandOptionChannelTypesMixin';
|
||||
|
||||
@mix(ApplicationCommandOptionChannelTypesMixin)
|
||||
export class SlashCommandChannelOption extends ApplicationCommandOptionBase {
|
||||
public override readonly type = ApplicationCommandOptionType.Channel as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandChannelOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandChannelOption extends ApplicationCommandOptionChannelTypesMixin {}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { APIApplicationCommandIntegerOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import { z } from 'zod';
|
||||
import { ApplicationCommandNumericOptionMinMaxValueMixin } from '../mixins/ApplicationCommandNumericOptionMinMaxValueMixin';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
import { ApplicationCommandOptionWithChoicesAndAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin';
|
||||
|
||||
const numberValidator = z.number().int().nonnegative();
|
||||
|
||||
@mix(ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin)
|
||||
export class SlashCommandIntegerOption
|
||||
extends ApplicationCommandOptionBase
|
||||
implements ApplicationCommandNumericOptionMinMaxValueMixin
|
||||
{
|
||||
public readonly type = ApplicationCommandOptionType.Integer as const;
|
||||
|
||||
public setMaxValue(max: number): this {
|
||||
numberValidator.parse(max);
|
||||
|
||||
Reflect.set(this, 'max_value', max);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public setMinValue(min: number): this {
|
||||
numberValidator.parse(min);
|
||||
|
||||
Reflect.set(this, 'min_value', min);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public toJSON(): APIApplicationCommandIntegerOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandIntegerOption
|
||||
extends ApplicationCommandNumericOptionMinMaxValueMixin,
|
||||
ApplicationCommandOptionWithChoicesAndAutocompleteMixin<number> {}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { APIApplicationCommandMentionableOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
|
||||
export class SlashCommandMentionableOption extends ApplicationCommandOptionBase {
|
||||
public readonly type = ApplicationCommandOptionType.Mentionable as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandMentionableOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { APIApplicationCommandNumberOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import { z } from 'zod';
|
||||
import { ApplicationCommandNumericOptionMinMaxValueMixin } from '../mixins/ApplicationCommandNumericOptionMinMaxValueMixin';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
import { ApplicationCommandOptionWithChoicesAndAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin';
|
||||
|
||||
const numberValidator = z.number().nonnegative();
|
||||
|
||||
@mix(ApplicationCommandNumericOptionMinMaxValueMixin, ApplicationCommandOptionWithChoicesAndAutocompleteMixin)
|
||||
export class SlashCommandNumberOption
|
||||
extends ApplicationCommandOptionBase
|
||||
implements ApplicationCommandNumericOptionMinMaxValueMixin
|
||||
{
|
||||
public readonly type = ApplicationCommandOptionType.Number as const;
|
||||
|
||||
public setMaxValue(max: number): this {
|
||||
numberValidator.parse(max);
|
||||
|
||||
Reflect.set(this, 'max_value', max);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public setMinValue(min: number): this {
|
||||
numberValidator.parse(min);
|
||||
|
||||
Reflect.set(this, 'min_value', min);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public toJSON(): APIApplicationCommandNumberOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandNumberOption
|
||||
extends ApplicationCommandNumericOptionMinMaxValueMixin,
|
||||
ApplicationCommandOptionWithChoicesAndAutocompleteMixin<number> {}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { APIApplicationCommandRoleOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
|
||||
export class SlashCommandRoleOption extends ApplicationCommandOptionBase {
|
||||
public override readonly type = ApplicationCommandOptionType.Role as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandRoleOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { APIApplicationCommandStringOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { mix } from 'ts-mixer';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
import { ApplicationCommandOptionWithChoicesAndAutocompleteMixin } from '../mixins/ApplicationCommandOptionWithChoicesAndAutocompleteMixin';
|
||||
|
||||
@mix(ApplicationCommandOptionWithChoicesAndAutocompleteMixin)
|
||||
export class SlashCommandStringOption extends ApplicationCommandOptionBase {
|
||||
public readonly type = ApplicationCommandOptionType.String as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandStringOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
if (this.autocomplete && Array.isArray(this.choices) && this.choices.length > 0) {
|
||||
throw new RangeError('Autocomplete and choices are mutually exclusive to each other.');
|
||||
}
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlashCommandStringOption extends ApplicationCommandOptionWithChoicesAndAutocompleteMixin<string> {}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { APIApplicationCommandUserOption, ApplicationCommandOptionType } from 'discord-api-types/v9';
|
||||
import { ApplicationCommandOptionBase } from '../mixins/ApplicationCommandOptionBase';
|
||||
|
||||
export class SlashCommandUserOption extends ApplicationCommandOptionBase {
|
||||
public readonly type = ApplicationCommandOptionType.User as const;
|
||||
|
||||
public toJSON(): APIApplicationCommandUserOption {
|
||||
this.runRequiredValidations();
|
||||
|
||||
return { ...this };
|
||||
}
|
||||
}
|
||||
36
packages/builders/src/messages/embed/Assertions.ts
Normal file
36
packages/builders/src/messages/embed/Assertions.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { APIEmbedField } from 'discord-api-types/v9';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const fieldNamePredicate = z.string().min(1).max(256);
|
||||
|
||||
export const fieldValuePredicate = z.string().min(1).max(1024);
|
||||
|
||||
export const fieldInlinePredicate = z.boolean().optional();
|
||||
|
||||
export const embedFieldPredicate = z.object({
|
||||
name: fieldNamePredicate,
|
||||
value: fieldValuePredicate,
|
||||
inline: fieldInlinePredicate,
|
||||
});
|
||||
|
||||
export const embedFieldsArrayPredicate = embedFieldPredicate.array();
|
||||
|
||||
export const fieldLengthPredicate = z.number().lte(25);
|
||||
|
||||
export function validateFieldLength(fields: APIEmbedField[], amountAdding: number): void {
|
||||
fieldLengthPredicate.parse(fields.length + amountAdding);
|
||||
}
|
||||
|
||||
export const authorNamePredicate = fieldNamePredicate.nullable();
|
||||
|
||||
export const urlPredicate = z.string().url().nullish();
|
||||
|
||||
export const colorPredicate = z.number().gte(0).lte(0xffffff).nullable();
|
||||
|
||||
export const descriptionPredicate = z.string().min(1).max(4096).nullable();
|
||||
|
||||
export const footerTextPredicate = z.string().min(1).max(2048).nullable();
|
||||
|
||||
export const timestampPredicate = z.union([z.number(), z.date()]).nullable();
|
||||
|
||||
export const titlePredicate = fieldNamePredicate.nullable();
|
||||
326
packages/builders/src/messages/embed/Embed.ts
Normal file
326
packages/builders/src/messages/embed/Embed.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
import type {
|
||||
APIEmbed,
|
||||
APIEmbedAuthor,
|
||||
APIEmbedField,
|
||||
APIEmbedFooter,
|
||||
APIEmbedImage,
|
||||
APIEmbedProvider,
|
||||
APIEmbedThumbnail,
|
||||
APIEmbedVideo,
|
||||
} from 'discord-api-types/v9';
|
||||
import {
|
||||
authorNamePredicate,
|
||||
colorPredicate,
|
||||
descriptionPredicate,
|
||||
embedFieldsArrayPredicate,
|
||||
fieldInlinePredicate,
|
||||
fieldNamePredicate,
|
||||
fieldValuePredicate,
|
||||
footerTextPredicate,
|
||||
timestampPredicate,
|
||||
titlePredicate,
|
||||
urlPredicate,
|
||||
validateFieldLength,
|
||||
} from './Assertions';
|
||||
|
||||
export interface AuthorOptions {
|
||||
name: string;
|
||||
url?: string;
|
||||
iconURL?: string;
|
||||
}
|
||||
|
||||
export interface FooterOptions {
|
||||
text: string;
|
||||
iconURL?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an embed in a message (image/video preview, rich embed, etc.)
|
||||
*/
|
||||
export class Embed implements APIEmbed {
|
||||
/**
|
||||
* An array of fields of this embed
|
||||
*/
|
||||
public fields: APIEmbedField[];
|
||||
|
||||
/**
|
||||
* The embed title
|
||||
*/
|
||||
public title?: string;
|
||||
|
||||
/**
|
||||
* The embed description
|
||||
*/
|
||||
public description?: string;
|
||||
|
||||
/**
|
||||
* The embed url
|
||||
*/
|
||||
public url?: string;
|
||||
|
||||
/**
|
||||
* The embed color
|
||||
*/
|
||||
public color?: number;
|
||||
|
||||
/**
|
||||
* The timestamp of the embed in the ISO format
|
||||
*/
|
||||
public timestamp?: string;
|
||||
|
||||
/**
|
||||
* The embed thumbnail data
|
||||
*/
|
||||
public thumbnail?: APIEmbedThumbnail;
|
||||
|
||||
/**
|
||||
* The embed image data
|
||||
*/
|
||||
public image?: APIEmbedImage;
|
||||
|
||||
/**
|
||||
* Received video data
|
||||
*/
|
||||
public video?: APIEmbedVideo;
|
||||
|
||||
/**
|
||||
* The embed author data
|
||||
*/
|
||||
public author?: APIEmbedAuthor;
|
||||
|
||||
/**
|
||||
* Received data about the embed provider
|
||||
*/
|
||||
public provider?: APIEmbedProvider;
|
||||
|
||||
/**
|
||||
* The embed footer data
|
||||
*/
|
||||
public footer?: APIEmbedFooter;
|
||||
|
||||
public constructor(data: APIEmbed = {}) {
|
||||
this.title = data.title;
|
||||
this.description = data.description;
|
||||
this.url = data.url;
|
||||
this.color = data.color;
|
||||
this.thumbnail = data.thumbnail;
|
||||
this.image = data.image;
|
||||
this.video = data.video;
|
||||
this.author = data.author;
|
||||
this.provider = data.provider;
|
||||
this.footer = data.footer;
|
||||
this.fields = data.fields ?? [];
|
||||
|
||||
if (data.timestamp) this.timestamp = new Date(data.timestamp).toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* The accumulated length for the embed title, description, fields, footer text, and author name
|
||||
*/
|
||||
public get length(): number {
|
||||
return (
|
||||
(this.title?.length ?? 0) +
|
||||
(this.description?.length ?? 0) +
|
||||
this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0) +
|
||||
(this.footer?.text.length ?? 0) +
|
||||
(this.author?.name.length ?? 0)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to the embed (max 25)
|
||||
*
|
||||
* @param field The field to add.
|
||||
*/
|
||||
public addField(field: APIEmbedField): this {
|
||||
return this.addFields(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds fields to the embed (max 25)
|
||||
*
|
||||
* @param fields The fields to add
|
||||
*/
|
||||
public addFields(...fields: APIEmbedField[]): this {
|
||||
// Data assertions
|
||||
embedFieldsArrayPredicate.parse(fields);
|
||||
|
||||
// Ensure adding these fields won't exceed the 25 field limit
|
||||
validateFieldLength(this.fields, fields.length);
|
||||
|
||||
this.fields.push(...Embed.normalizeFields(...fields));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes, replaces, or inserts fields in the embed (max 25)
|
||||
*
|
||||
* @param index The index to start at
|
||||
* @param deleteCount The number of fields to remove
|
||||
* @param fields The replacing field objects
|
||||
*/
|
||||
public spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this {
|
||||
// Data assertions
|
||||
embedFieldsArrayPredicate.parse(fields);
|
||||
|
||||
// Ensure adding these fields won't exceed the 25 field limit
|
||||
validateFieldLength(this.fields, fields.length - deleteCount);
|
||||
|
||||
this.fields.splice(index, deleteCount, ...Embed.normalizeFields(...fields));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this embed
|
||||
*
|
||||
* @param options The options for the author
|
||||
*/
|
||||
public setAuthor(options: AuthorOptions | null): this {
|
||||
if (options === null) {
|
||||
this.author = undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
const { name, iconURL, url } = options;
|
||||
// Data assertions
|
||||
authorNamePredicate.parse(name);
|
||||
urlPredicate.parse(iconURL);
|
||||
urlPredicate.parse(url);
|
||||
|
||||
this.author = { name, url, icon_url: iconURL };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this embed
|
||||
*
|
||||
* @param color The color of the embed
|
||||
*/
|
||||
public setColor(color: number | null): this {
|
||||
// Data assertions
|
||||
colorPredicate.parse(color);
|
||||
|
||||
this.color = color ?? undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this embed
|
||||
*
|
||||
* @param description The description
|
||||
*/
|
||||
public setDescription(description: string | null): this {
|
||||
// Data assertions
|
||||
descriptionPredicate.parse(description);
|
||||
|
||||
this.description = description ?? undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the footer of this embed
|
||||
*
|
||||
* @param options The options for the footer
|
||||
*/
|
||||
public setFooter(options: FooterOptions | null): this {
|
||||
if (options === null) {
|
||||
this.footer = undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
const { text, iconURL } = options;
|
||||
// Data assertions
|
||||
footerTextPredicate.parse(text);
|
||||
urlPredicate.parse(iconURL);
|
||||
|
||||
this.footer = { text, icon_url: iconURL };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the image of this embed
|
||||
*
|
||||
* @param url The URL of the image
|
||||
*/
|
||||
public setImage(url: string | null): this {
|
||||
// Data assertions
|
||||
urlPredicate.parse(url);
|
||||
|
||||
this.image = url ? { url } : undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the thumbnail of this embed
|
||||
*
|
||||
* @param url The URL of the thumbnail
|
||||
*/
|
||||
public setThumbnail(url: string | null): this {
|
||||
// Data assertions
|
||||
urlPredicate.parse(url);
|
||||
|
||||
this.thumbnail = url ? { url } : undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timestamp of this embed
|
||||
*
|
||||
* @param timestamp The timestamp or date
|
||||
*/
|
||||
public setTimestamp(timestamp: number | Date | null = Date.now()): this {
|
||||
// Data assertions
|
||||
timestampPredicate.parse(timestamp);
|
||||
|
||||
this.timestamp = timestamp ? new Date(timestamp).toISOString() : undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this embed
|
||||
*
|
||||
* @param title The title
|
||||
*/
|
||||
public setTitle(title: string | null): this {
|
||||
// Data assertions
|
||||
titlePredicate.parse(title);
|
||||
|
||||
this.title = title ?? undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of this embed
|
||||
*
|
||||
* @param url The URL
|
||||
*/
|
||||
public setURL(url: string | null): this {
|
||||
// Data assertions
|
||||
urlPredicate.parse(url);
|
||||
|
||||
this.url = url ?? undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the embed to a plain object
|
||||
*/
|
||||
public toJSON(): APIEmbed {
|
||||
return { ...this };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes field input and resolves strings
|
||||
*
|
||||
* @param fields Fields to normalize
|
||||
*/
|
||||
public static normalizeFields(...fields: APIEmbedField[]): APIEmbedField[] {
|
||||
return fields.flat(Infinity).map((field) => {
|
||||
fieldNamePredicate.parse(field.name);
|
||||
fieldValuePredicate.parse(field.value);
|
||||
fieldInlinePredicate.parse(field.inline);
|
||||
|
||||
return { name: field.name, value: field.value, inline: field.inline ?? undefined };
|
||||
});
|
||||
}
|
||||
}
|
||||
319
packages/builders/src/messages/formatters.ts
Normal file
319
packages/builders/src/messages/formatters.ts
Normal file
@@ -0,0 +1,319 @@
|
||||
import type { Snowflake } from 'discord-api-types/globals';
|
||||
import type { URL } from 'url';
|
||||
|
||||
/**
|
||||
* Wraps the content inside a codeblock with no language
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function codeBlock<C extends string>(content: C): `\`\`\`\n${C}\`\`\``;
|
||||
|
||||
/**
|
||||
* Wraps the content inside a codeblock with the specified language
|
||||
*
|
||||
* @param language The language for the codeblock
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function codeBlock<L extends string, C extends string>(language: L, content: C): `\`\`\`${L}\n${C}\`\`\``;
|
||||
export function codeBlock(language: string, content?: string): string {
|
||||
return typeof content === 'undefined' ? `\`\`\`\n${language}\`\`\`` : `\`\`\`${language}\n${content}\`\`\``;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the content inside \`backticks\`, which formats it as inline code
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function inlineCode<C extends string>(content: C): `\`${C}\`` {
|
||||
return `\`${content}\``;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into italic text
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function italic<C extends string>(content: C): `_${C}_` {
|
||||
return `_${content}_`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into bold text
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function bold<C extends string>(content: C): `**${C}**` {
|
||||
return `**${content}**`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into underscored text
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function underscore<C extends string>(content: C): `__${C}__` {
|
||||
return `__${content}__`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into strike-through text
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function strikethrough<C extends string>(content: C): `~~${C}~~` {
|
||||
return `~~${content}~~`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into a quote. This needs to be at the start of the line for Discord to format it
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function quote<C extends string>(content: C): `> ${C}` {
|
||||
return `> ${content}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content into a block quote. This needs to be at the start of the line for Discord to format it
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function blockQuote<C extends string>(content: C): `>>> ${C}` {
|
||||
return `>>> ${content}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the URL into `<>`, which stops it from embedding
|
||||
*
|
||||
* @param url The URL to wrap
|
||||
*/
|
||||
export function hideLinkEmbed<C extends string>(url: C): `<${C}>`;
|
||||
|
||||
/**
|
||||
* Wraps the URL into `<>`, which stops it from embedding
|
||||
*
|
||||
* @param url The URL to wrap
|
||||
*/
|
||||
export function hideLinkEmbed(url: URL): `<${string}>`;
|
||||
export function hideLinkEmbed(url: string | URL) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
return `<${url}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the content and the URL into a masked URL
|
||||
*
|
||||
* @param content The content to display
|
||||
* @param url The URL the content links to
|
||||
*/
|
||||
export function hyperlink<C extends string>(content: C, url: URL): `[${C}](${string})`;
|
||||
|
||||
/**
|
||||
* Formats the content and the URL into a masked URL
|
||||
*
|
||||
* @param content The content to display
|
||||
* @param url The URL the content links to
|
||||
*/
|
||||
export function hyperlink<C extends string, U extends string>(content: C, url: U): `[${C}](${U})`;
|
||||
|
||||
/**
|
||||
* Formats the content and the URL into a masked URL
|
||||
*
|
||||
* @param content The content to display
|
||||
* @param url The URL the content links to
|
||||
* @param title The title shown when hovering on the masked link
|
||||
*/
|
||||
export function hyperlink<C extends string, T extends string>(
|
||||
content: C,
|
||||
url: URL,
|
||||
title: T,
|
||||
): `[${C}](${string} "${T}")`;
|
||||
|
||||
/**
|
||||
* Formats the content and the URL into a masked URL
|
||||
*
|
||||
* @param content The content to display
|
||||
* @param url The URL the content links to
|
||||
* @param title The title shown when hovering on the masked link
|
||||
*/
|
||||
export function hyperlink<C extends string, U extends string, T extends string>(
|
||||
content: C,
|
||||
url: U,
|
||||
title: T,
|
||||
): `[${C}](${U} "${T}")`;
|
||||
export function hyperlink(content: string, url: string | URL, title?: string) {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
return title ? `[${content}](${url} "${title}")` : `[${content}](${url})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the content inside spoiler (hidden text)
|
||||
*
|
||||
* @param content The content to wrap
|
||||
*/
|
||||
export function spoiler<C extends string>(content: C): `||${C}||` {
|
||||
return `||${content}||`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a user ID into a user mention
|
||||
*
|
||||
* @param userId The user ID to format
|
||||
*/
|
||||
export function userMention<C extends Snowflake>(userId: C): `<@${C}>` {
|
||||
return `<@${userId}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a user ID into a member-nickname mention
|
||||
*
|
||||
* @param memberId The user ID to format
|
||||
*/
|
||||
export function memberNicknameMention<C extends Snowflake>(memberId: C): `<@!${C}>` {
|
||||
return `<@!${memberId}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a channel ID into a channel mention
|
||||
*
|
||||
* @param channelId The channel ID to format
|
||||
*/
|
||||
export function channelMention<C extends Snowflake>(channelId: C): `<#${C}>` {
|
||||
return `<#${channelId}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a role ID into a role mention
|
||||
*
|
||||
* @param roleId The role ID to format
|
||||
*/
|
||||
export function roleMention<C extends Snowflake>(roleId: C): `<@&${C}>` {
|
||||
return `<@&${roleId}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an emoji ID into a fully qualified emoji identifier
|
||||
*
|
||||
* @param emojiId The emoji ID to format
|
||||
*/
|
||||
export function formatEmoji<C extends Snowflake>(emojiId: C, animated?: false): `<:_:${C}>`;
|
||||
|
||||
/**
|
||||
* Formats an emoji ID into a fully qualified emoji identifier
|
||||
*
|
||||
* @param emojiId The emoji ID to format
|
||||
* @param animated Whether the emoji is animated or not. Defaults to `false`
|
||||
*/
|
||||
export function formatEmoji<C extends Snowflake>(emojiId: C, animated?: true): `<a:_:${C}>`;
|
||||
|
||||
/**
|
||||
* Formats an emoji ID into a fully qualified emoji identifier
|
||||
*
|
||||
* @param emojiId The emoji ID to format
|
||||
* @param animated Whether the emoji is animated or not. Defaults to `false`
|
||||
*/
|
||||
export function formatEmoji<C extends Snowflake>(emojiId: C, animated = false): `<a:_:${C}>` | `<:_:${C}>` {
|
||||
return `<${animated ? 'a' : ''}:_:${emojiId}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a date into a short date-time string
|
||||
*
|
||||
* @param date The date to format, defaults to the current time
|
||||
*/
|
||||
export function time(date?: Date): `<t:${bigint}>`;
|
||||
|
||||
/**
|
||||
* Formats a date given a format style
|
||||
*
|
||||
* @param date The date to format
|
||||
* @param style The style to use
|
||||
*/
|
||||
export function time<S extends TimestampStylesString>(date: Date, style: S): `<t:${bigint}:${S}>`;
|
||||
|
||||
/**
|
||||
* Formats the given timestamp into a short date-time string
|
||||
*
|
||||
* @param seconds The time to format, represents an UNIX timestamp in seconds
|
||||
*/
|
||||
export function time<C extends number>(seconds: C): `<t:${C}>`;
|
||||
|
||||
/**
|
||||
* Formats the given timestamp into a short date-time string
|
||||
*
|
||||
* @param seconds The time to format, represents an UNIX timestamp in seconds
|
||||
* @param style The style to use
|
||||
*/
|
||||
export function time<C extends number, S extends TimestampStylesString>(seconds: C, style: S): `<t:${C}:${S}>`;
|
||||
export function time(timeOrSeconds?: number | Date, style?: TimestampStylesString): string {
|
||||
if (typeof timeOrSeconds !== 'number') {
|
||||
timeOrSeconds = Math.floor((timeOrSeconds?.getTime() ?? Date.now()) / 1000);
|
||||
}
|
||||
|
||||
return typeof style === 'string' ? `<t:${timeOrSeconds}:${style}>` : `<t:${timeOrSeconds}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The [message formatting timestamp styles](https://discord.com/developers/docs/reference#message-formatting-timestamp-styles) supported by Discord
|
||||
*/
|
||||
export const TimestampStyles = {
|
||||
/**
|
||||
* Short time format, consisting of hours and minutes, e.g. 16:20
|
||||
*/
|
||||
ShortTime: 't',
|
||||
|
||||
/**
|
||||
* Long time format, consisting of hours, minutes, and seconds, e.g. 16:20:30
|
||||
*/
|
||||
LongTime: 'T',
|
||||
|
||||
/**
|
||||
* Short date format, consisting of day, month, and year, e.g. 20/04/2021
|
||||
*/
|
||||
ShortDate: 'd',
|
||||
|
||||
/**
|
||||
* Long date format, consisting of day, month, and year, e.g. 20 April 2021
|
||||
*/
|
||||
LongDate: 'D',
|
||||
|
||||
/**
|
||||
* Short date-time format, consisting of short date and short time formats, e.g. 20 April 2021 16:20
|
||||
*/
|
||||
ShortDateTime: 'f',
|
||||
|
||||
/**
|
||||
* Long date-time format, consisting of long date and short time formats, e.g. Tuesday, 20 April 2021 16:20
|
||||
*/
|
||||
LongDateTime: 'F',
|
||||
|
||||
/**
|
||||
* Relative time format, consisting of a relative duration format, e.g. 2 months ago
|
||||
*/
|
||||
RelativeTime: 'R',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* The possible values, see {@link TimestampStyles} for more information
|
||||
*/
|
||||
export type TimestampStylesString = typeof TimestampStyles[keyof typeof TimestampStyles];
|
||||
|
||||
/**
|
||||
* An enum with all the available faces from Discord's native slash commands
|
||||
*/
|
||||
export enum Faces {
|
||||
/**
|
||||
* ¯\\_(ツ)\\_/¯
|
||||
*/
|
||||
Shrug = '¯\\_(ツ)\\_/¯',
|
||||
|
||||
/**
|
||||
* (╯°□°)╯︵ ┻━┻
|
||||
*/
|
||||
Tableflip = '(╯°□°)╯︵ ┻━┻',
|
||||
|
||||
/**
|
||||
* ┬─┬ ノ( ゜-゜ノ)
|
||||
*/
|
||||
Unflip = '┬─┬ ノ( ゜-゜ノ)',
|
||||
}
|
||||
20
packages/builders/tsconfig.eslint.json
Normal file
20
packages/builders/tsconfig.eslint.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.js",
|
||||
"**/*.mjs",
|
||||
"**/*.jsx",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.js",
|
||||
"**/*.test.mjs",
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.js",
|
||||
"**/*.spec.mjs"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
||||
4
packages/builders/tsconfig.json
Normal file
4
packages/builders/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
12
packages/builders/tsup.config.ts
Normal file
12
packages/builders/tsup.config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { Options } from 'tsup';
|
||||
|
||||
export const tsup: Options = {
|
||||
clean: true,
|
||||
dts: true,
|
||||
entryPoints: ['src/index.ts'],
|
||||
format: ['esm', 'cjs'],
|
||||
minify: true,
|
||||
skipNodeModulesBundle: true,
|
||||
sourcemap: true,
|
||||
target: 'es2021',
|
||||
};
|
||||
16
packages/collection/.eslintrc.json
Normal file
16
packages/collection/.eslintrc.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "marine/prettier/node",
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.eslint.json",
|
||||
"extraFileExtensions": [".mjs"]
|
||||
},
|
||||
"ignorePatterns": ["**/dist/*"],
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
"rules": {
|
||||
"no-redeclare": 0,
|
||||
"@typescript-eslint/naming-convention": 0
|
||||
}
|
||||
}
|
||||
27
packages/collection/.gitignore
vendored
Normal file
27
packages/collection/.gitignore
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# Packages
|
||||
node_modules/
|
||||
|
||||
# Log files
|
||||
logs/
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Env
|
||||
.env
|
||||
|
||||
# Dist
|
||||
dist/
|
||||
typings/
|
||||
docs/**/*
|
||||
!docs/index.yml
|
||||
!docs/README.md
|
||||
|
||||
# Miscellaneous
|
||||
.tmp/
|
||||
coverage/
|
||||
tsconfig.tsbuildinfo
|
||||
8
packages/collection/.prettierrc.json
Normal file
8
packages/collection/.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
3
packages/collection/.versionrc
Normal file
3
packages/collection/.versionrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"releaseCommitMessageFormat": "chore(Release): publish"
|
||||
}
|
||||
63
packages/collection/CHANGELOG.md
Normal file
63
packages/collection/CHANGELOG.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
|
||||
# [0.4.0](https://github.com/discordjs/collection/compare/v0.3.2...v0.4.0) (2021-12-24)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
## [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.0](https://github.com/discordjs/collection/compare/v0.2.4...v0.3.0) (2021-10-29)
|
||||
|
||||
|
||||
### 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))
|
||||
|
||||
|
||||
|
||||
## [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.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.
|
||||
191
packages/collection/LICENSE
Normal file
191
packages/collection/LICENSE
Normal file
@@ -0,0 +1,191 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2015 - 2021 Noel Buechler
|
||||
Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
46
packages/collection/README.md
Normal file
46
packages/collection/README.md
Normal file
@@ -0,0 +1,46 @@
|
||||
<div align="center">
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.js.org"><img src="https://discord.js.org/static/logo.svg" width="546" alt="discord.js" /></a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
|
||||
<a href="https://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>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
`@discordjs/collection` is a powerful utility data structure used in discord.js.
|
||||
|
||||
## Installation
|
||||
|
||||
**Node.js 16.0.0 or newer is required.**
|
||||
|
||||
```sh-session
|
||||
npm install @discordjs/collection
|
||||
yarn add @discordjs/collection
|
||||
pnpm add @discordjs/collection
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- [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)
|
||||
- [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.
|
||||
|
||||
## Help
|
||||
|
||||
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
|
||||
nudge in the right direction, please don't hesitate to join our official [discord.js Server](https://discord.gg/djs).
|
||||
462
packages/collection/__tests__/collection.test.ts
Normal file
462
packages/collection/__tests__/collection.test.ts
Normal file
@@ -0,0 +1,462 @@
|
||||
import Collection from '../src';
|
||||
|
||||
type TestCollection = Collection<string, number>;
|
||||
|
||||
test('do basic map operations', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
expect(coll.size).toEqual(1);
|
||||
expect(coll.has('a')).toBeTruthy();
|
||||
expect(coll.get('a')).toStrictEqual(1);
|
||||
coll.delete('a');
|
||||
expect(coll.has('a')).toBeFalsy();
|
||||
expect(coll.get('a')).toStrictEqual(undefined);
|
||||
coll.clear();
|
||||
expect(coll.size).toStrictEqual(0);
|
||||
});
|
||||
|
||||
test('get the first item of the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
expect(coll.first()).toStrictEqual(1);
|
||||
});
|
||||
|
||||
test('get the first 3 items of the collection where size equals', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
expect(coll.first(3)).toStrictEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('get the first 3 items of the collection where size is less', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
expect(coll.first(3)).toStrictEqual([1, 2]);
|
||||
});
|
||||
|
||||
test('get the last item of the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
expect(coll.last()).toStrictEqual(2);
|
||||
});
|
||||
|
||||
test('get the last 3 items of the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
expect(coll.last(3)).toStrictEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('get the last 3 items of the collection where size is less', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
expect(coll.last(3)).toStrictEqual([1, 2]);
|
||||
});
|
||||
|
||||
test('find an item in the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
expect(coll.find((x) => x === 1)).toStrictEqual(1);
|
||||
expect(coll.find((x) => x === 10)).toStrictEqual(undefined);
|
||||
});
|
||||
|
||||
test('sweep items from the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const n1 = coll.sweep((x) => x === 2);
|
||||
expect(n1).toStrictEqual(1);
|
||||
expect([...coll.values()]).toStrictEqual([1, 3]);
|
||||
const n2 = coll.sweep((x) => x === 4);
|
||||
expect(n2).toStrictEqual(0);
|
||||
expect([...coll.values()]).toStrictEqual([1, 3]);
|
||||
});
|
||||
|
||||
test('filter items from the collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const filtered = coll.filter((x) => x % 2 === 1);
|
||||
expect(coll.size).toStrictEqual(3);
|
||||
expect(filtered.size).toStrictEqual(2);
|
||||
expect([...filtered.values()]).toStrictEqual([1, 3]);
|
||||
});
|
||||
|
||||
test('partition a collection into two collections', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
coll.set('d', 4);
|
||||
coll.set('e', 5);
|
||||
coll.set('f', 6);
|
||||
const [even, odd] = coll.partition((x) => x % 2 === 0);
|
||||
expect([...even.values()]).toStrictEqual([2, 4, 6]);
|
||||
expect([...odd.values()]).toStrictEqual([1, 3, 5]);
|
||||
});
|
||||
|
||||
test('map items in a collection into an array', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const mapped = coll.map((x) => x + 1);
|
||||
expect(mapped).toStrictEqual([2, 3, 4]);
|
||||
});
|
||||
|
||||
test('map items in a collection into a collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const mapped = coll.mapValues((x) => x + 1);
|
||||
expect([...mapped.values()]).toStrictEqual([2, 3, 4]);
|
||||
});
|
||||
|
||||
test('flatMap items in a collection into a single collection', () => {
|
||||
const coll = new Collection<string, { a: Collection<string, number> }>();
|
||||
const coll1 = new Collection<string, number>();
|
||||
const coll2 = new Collection<string, number>();
|
||||
coll1.set('z', 1);
|
||||
coll1.set('x', 2);
|
||||
coll2.set('c', 3);
|
||||
coll2.set('v', 4);
|
||||
coll.set('a', { a: coll1 });
|
||||
coll.set('b', { a: coll2 });
|
||||
const mapped = coll.flatMap((x) => x.a);
|
||||
expect([...mapped.values()]).toStrictEqual([1, 2, 3, 4]);
|
||||
});
|
||||
|
||||
test('check if some items pass a predicate', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
expect(coll.some((x) => x === 2)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('check if every items pass a predicate', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
expect(!coll.every((x) => x === 2)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('reduce collection into a single value with initial value', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const sum = coll.reduce((a, x) => a + x, 0);
|
||||
expect(sum).toStrictEqual(6);
|
||||
});
|
||||
|
||||
test('reduce collection into a single value without initial value', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const sum = coll.reduce((a, x) => a + x, 0);
|
||||
expect(sum).toStrictEqual(6);
|
||||
});
|
||||
|
||||
test('reduce empty collection without initial value', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
expect(() => coll.reduce((a: number, x) => a + x)).toThrowError(
|
||||
new TypeError('Reduce of empty collection with no initial value'),
|
||||
);
|
||||
});
|
||||
|
||||
test('iterate over each item', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const a: [string, number][] = [];
|
||||
coll.each((v, k) => a.push([k, v]));
|
||||
expect(a).toStrictEqual([
|
||||
['a', 1],
|
||||
['b', 2],
|
||||
['c', 3],
|
||||
]);
|
||||
});
|
||||
|
||||
test('tap the collection', () => {
|
||||
const coll = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
coll.tap((c) => expect(c).toStrictEqual(coll));
|
||||
});
|
||||
|
||||
test('shallow clone the collection', () => {
|
||||
const coll = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
const clone = coll.clone();
|
||||
expect([...coll.values()]).toStrictEqual([...clone.values()]);
|
||||
});
|
||||
|
||||
test('merge multiple collections', () => {
|
||||
const coll1 = new Collection();
|
||||
coll1.set('a', 1);
|
||||
const coll2 = new Collection();
|
||||
coll2.set('b', 2);
|
||||
const coll3 = new Collection();
|
||||
coll3.set('c', 3);
|
||||
const merged = coll1.concat(coll2, coll3);
|
||||
expect([...merged.values()]).toStrictEqual([1, 2, 3]);
|
||||
expect(coll1 !== merged).toBeTruthy();
|
||||
});
|
||||
|
||||
test('check equality of two collections', () => {
|
||||
const coll1 = new Collection<string, number>();
|
||||
coll1.set('a', 1);
|
||||
const coll2 = new Collection<string, number>();
|
||||
coll2.set('a', 1);
|
||||
expect(coll1.equals(coll2)).toBeTruthy();
|
||||
coll2.set('b', 2);
|
||||
expect(!coll1.equals(coll2)).toBeTruthy();
|
||||
coll2.clear();
|
||||
expect(!coll1.equals(coll2)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('sort a collection in place', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 3);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 1);
|
||||
expect([...coll.values()]).toStrictEqual([3, 2, 1]);
|
||||
coll.sort((a, b) => a - b);
|
||||
expect([...coll.values()]).toStrictEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('random select from a collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
const chars = 'abcdefghijklmnopqrstuvwxyz';
|
||||
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26];
|
||||
|
||||
for (let i = 0; i < chars.length; i++) coll.set(chars[i], numbers[i]);
|
||||
|
||||
const random = coll.random(5);
|
||||
expect(random.length === 5).toBeTruthy();
|
||||
|
||||
const set = new Set(random);
|
||||
expect(set.size === random.length).toBeTruthy();
|
||||
});
|
||||
|
||||
test('when random param > collection size', () => {
|
||||
const coll = new Collection();
|
||||
coll.set('a', 3);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 1);
|
||||
|
||||
const random = coll.random(5);
|
||||
expect(random.length).toEqual(coll.size);
|
||||
});
|
||||
|
||||
test('sort a collection', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 3);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 1);
|
||||
expect([...coll.values()]).toStrictEqual([3, 2, 1]);
|
||||
const sorted = coll.sorted((a, b) => a - b);
|
||||
expect([...coll.values()]).toStrictEqual([3, 2, 1]);
|
||||
expect([...sorted.values()]).toStrictEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
describe('at() tests', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
|
||||
test('Positive index', () => {
|
||||
expect(coll.at(0)).toStrictEqual(1);
|
||||
});
|
||||
|
||||
test('Negative index', () => {
|
||||
expect(coll.at(-1)).toStrictEqual(2);
|
||||
});
|
||||
|
||||
test('Invalid positive index', () => {
|
||||
expect(coll.at(3)).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Invalid negative index', () => {
|
||||
expect(coll.at(-3)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('keyAt() tests', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
|
||||
test('Positive index', () => {
|
||||
expect(coll.keyAt(0)).toStrictEqual('a');
|
||||
});
|
||||
|
||||
test('Negative index', () => {
|
||||
expect(coll.keyAt(-1)).toStrictEqual('b');
|
||||
});
|
||||
|
||||
test('Invalid positive index', () => {
|
||||
expect(coll.keyAt(3)).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Invalid negative index', () => {
|
||||
expect(coll.keyAt(-3)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasAll() tests', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
|
||||
test('All keys exist in the collection', () => {
|
||||
expect(coll.hasAll('a', 'b')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('Some keys exist in the collection', () => {
|
||||
expect(coll.hasAll('b', 'c')).toBeFalsy();
|
||||
});
|
||||
|
||||
test('No keys exist in the collection', () => {
|
||||
expect(coll.hasAll('c', 'd')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasAny() tests', () => {
|
||||
const coll: TestCollection = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
|
||||
test('All keys exist in the collection', () => {
|
||||
expect(coll.hasAny('a', 'b')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('Some keys exist in the collection', () => {
|
||||
expect(coll.hasAny('b', 'c')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('No keys exist in the collection', () => {
|
||||
expect(coll.hasAny('c', 'd')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('reverse() tests', () => {
|
||||
const coll = new Collection();
|
||||
coll.set('a', 1);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 3);
|
||||
|
||||
coll.reverse();
|
||||
|
||||
expect([...coll.values()]).toStrictEqual([3, 2, 1]);
|
||||
expect([...coll.keys()]).toStrictEqual(['c', 'b', 'a']);
|
||||
});
|
||||
|
||||
describe('random thisArg tests', () => {
|
||||
const coll = new Collection();
|
||||
coll.set('a', 3);
|
||||
coll.set('b', 2);
|
||||
coll.set('c', 1);
|
||||
|
||||
const object = {};
|
||||
const string = 'Hi';
|
||||
const boolean = false;
|
||||
const symbol = Symbol('testArg');
|
||||
const array = [1, 2, 3];
|
||||
|
||||
coll.set('d', object);
|
||||
coll.set('e', string);
|
||||
coll.set('f', boolean);
|
||||
coll.set('g', symbol);
|
||||
coll.set('h', array);
|
||||
|
||||
test('thisArg test: number', () => {
|
||||
coll.some(function thisArgTest1(value) {
|
||||
expect(this.valueOf()).toStrictEqual(1);
|
||||
expect(typeof this).toEqual('number');
|
||||
return value === this;
|
||||
}, 1);
|
||||
});
|
||||
|
||||
test('thisArg test: object', () => {
|
||||
coll.some(function thisArgTest2(value) {
|
||||
expect(this).toStrictEqual(object);
|
||||
expect(this.constructor === Object).toBeTruthy();
|
||||
return value === this;
|
||||
}, object);
|
||||
});
|
||||
|
||||
test('thisArg test: string', () => {
|
||||
coll.some(function thisArgTest3(value) {
|
||||
expect(this.valueOf()).toStrictEqual(string);
|
||||
expect(typeof this).toEqual('string');
|
||||
return value === this;
|
||||
}, string);
|
||||
});
|
||||
|
||||
test('thisArg test: boolean', () => {
|
||||
coll.some(function thisArgTest4(value) {
|
||||
expect(this.valueOf()).toStrictEqual(boolean);
|
||||
expect(typeof this).toEqual('boolean');
|
||||
return value === this;
|
||||
}, boolean);
|
||||
});
|
||||
|
||||
test('thisArg test: symbol', () => {
|
||||
coll.some(function thisArgTest5(value) {
|
||||
expect(this.valueOf()).toStrictEqual(symbol);
|
||||
expect(typeof this).toEqual('symbol');
|
||||
return value === this;
|
||||
}, symbol);
|
||||
});
|
||||
|
||||
test('thisArg test: array', () => {
|
||||
coll.some(function thisArgTest6(value) {
|
||||
expect(this).toStrictEqual(array);
|
||||
expect(Array.isArray(this)).toBeTruthy();
|
||||
return value === this;
|
||||
}, array);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ensure() tests', () => {
|
||||
function createTestCollection() {
|
||||
return new Collection([
|
||||
['a', 1],
|
||||
['b', 2],
|
||||
]);
|
||||
}
|
||||
|
||||
test('set new value if key does not exist', () => {
|
||||
const coll = createTestCollection();
|
||||
coll.ensure('c', () => 3);
|
||||
expect(coll.size).toStrictEqual(3);
|
||||
expect(coll.get('c')).toStrictEqual(3);
|
||||
});
|
||||
|
||||
test('return existing value if key exists', () => {
|
||||
const coll = createTestCollection();
|
||||
const ensureB = coll.ensure('b', () => 3);
|
||||
const getB = coll.get('b');
|
||||
expect(ensureB).toStrictEqual(2);
|
||||
expect(getB).toStrictEqual(2);
|
||||
expect(coll.size).toStrictEqual(2);
|
||||
});
|
||||
});
|
||||
17
packages/collection/babel.config.js
Normal file
17
packages/collection/babel.config.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @type {import('@babel/core').TransformOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
parserOpts: { strictMode: true },
|
||||
sourceMaps: 'inline',
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets: { node: 'current' },
|
||||
modules: 'commonjs',
|
||||
},
|
||||
],
|
||||
'@babel/preset-typescript',
|
||||
],
|
||||
};
|
||||
1
packages/collection/docs/README.md
Normal file
1
packages/collection/docs/README.md
Normal file
@@ -0,0 +1 @@
|
||||
## [View the documentation here.](https://discord.js.org/#/docs/collection)
|
||||
5
packages/collection/docs/index.yml
Normal file
5
packages/collection/docs/index.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: General
|
||||
files:
|
||||
- name: Welcome
|
||||
id: welcome
|
||||
path: ../../README.md
|
||||
11
packages/collection/jest.config.js
Normal file
11
packages/collection/jest.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* @type {import('@jest/types').Config.InitialOptions}
|
||||
*/
|
||||
module.exports = {
|
||||
testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
|
||||
testEnvironment: 'node',
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.ts'],
|
||||
coverageDirectory: 'coverage',
|
||||
coverageReporters: ['text', 'lcov', 'clover'],
|
||||
};
|
||||
75
packages/collection/package.json
Normal file
75
packages/collection/package.json
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "@discordjs/collection",
|
||||
"version": "0.4.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}",
|
||||
"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 './*'"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.js"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "src",
|
||||
"test": "__tests__"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"contributors": [
|
||||
"Crawl <icrawltogo@gmail.com>",
|
||||
"Amish Shah <amishshah.2k@gmail.com>",
|
||||
"SpaceEEC <spaceeec@yahoo.com>",
|
||||
"Vlad Frangu <kingdgrizzle@gmail.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"map",
|
||||
"collection",
|
||||
"utility"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/discordjs/discord.js.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/discordjs/discord.js/issues"
|
||||
},
|
||||
"homepage": "https://discord.js.org",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.16.5",
|
||||
"@babel/preset-env": "^7.16.5",
|
||||
"@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",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.4.5",
|
||||
"prettier": "^2.5.1",
|
||||
"standard-version": "^9.3.2",
|
||||
"tsup": "^5.11.8",
|
||||
"typedoc": "^0.22.10",
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
7
packages/collection/scripts/docs.mjs
Normal file
7
packages/collection/scripts/docs.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
import { runGenerator } from '@discordjs/ts-docgen';
|
||||
|
||||
runGenerator({
|
||||
existingOutput: 'docs/typedoc-out.json',
|
||||
custom: 'docs/index.yml',
|
||||
output: 'docs/docs.json',
|
||||
});
|
||||
687
packages/collection/src/index.ts
Normal file
687
packages/collection/src/index.ts
Normal file
@@ -0,0 +1,687 @@
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface CollectionConstructor {
|
||||
new (): Collection<unknown, unknown>;
|
||||
new <K, V>(entries?: ReadonlyArray<readonly [K, V]> | null): Collection<K, V>;
|
||||
new <K, V>(iterable: Iterable<readonly [K, V]>): Collection<K, V>;
|
||||
readonly prototype: Collection<unknown, unknown>;
|
||||
readonly [Symbol.species]: CollectionConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export interface Collection<K, V> extends Map<K, V> {
|
||||
constructor: CollectionConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has
|
||||
* an ID, for significantly improved performance and ease-of-use.
|
||||
*/
|
||||
export class Collection<K, V> extends Map<K, V> {
|
||||
public static readonly default: typeof Collection = Collection;
|
||||
|
||||
/**
|
||||
* Obtains the value of the given key if it exists, otherwise sets and returns the value provided by the default value generator.
|
||||
*
|
||||
* @param key The key to get if it exists, or set otherwise
|
||||
* @param defaultValueGenerator A function that generates the default value
|
||||
*
|
||||
* @example
|
||||
* collection.ensure(guildId, () => defaultGuildConfig);
|
||||
*/
|
||||
public ensure(key: K, defaultValueGenerator: (key: K, collection: this) => V): V {
|
||||
if (this.has(key)) return this.get(key)!;
|
||||
const defaultValue = defaultValueGenerator(key, this);
|
||||
this.set(key, defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all of the elements exist in the collection.
|
||||
*
|
||||
* @param keys - The keys of the elements to check for
|
||||
*
|
||||
* @returns `true` if all of the elements exist, `false` if at least one does not exist.
|
||||
*/
|
||||
public hasAll(...keys: K[]) {
|
||||
return keys.every((k) => super.has(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any of the elements exist in the collection.
|
||||
*
|
||||
* @param keys - The keys of the elements to check for
|
||||
*
|
||||
* @returns `true` if any of the elements exist, `false` if none exist.
|
||||
*/
|
||||
public hasAny(...keys: K[]) {
|
||||
return keys.some((k) => super.has(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the first value(s) in this collection.
|
||||
*
|
||||
* @param amount Amount of values to obtain from the beginning
|
||||
*
|
||||
* @returns A single value if no amount is provided or an array of values, starting from the end if amount is negative
|
||||
*/
|
||||
public first(): V | undefined;
|
||||
public first(amount: number): V[];
|
||||
public first(amount?: number): V | V[] | undefined {
|
||||
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();
|
||||
return Array.from({ length: amount }, (): V => iter.next().value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the first key(s) in this collection.
|
||||
*
|
||||
* @param amount Amount of keys to obtain from the beginning
|
||||
*
|
||||
* @returns A single key if no amount is provided or an array of keys, starting from the end if
|
||||
* amount is negative
|
||||
*/
|
||||
public firstKey(): K | undefined;
|
||||
public firstKey(amount: number): K[];
|
||||
public firstKey(amount?: number): K | K[] | undefined {
|
||||
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();
|
||||
return Array.from({ length: amount }, (): K => iter.next().value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the last value(s) in this collection.
|
||||
*
|
||||
* @param amount Amount of values to obtain from the end
|
||||
*
|
||||
* @returns A single value if no amount is provided or an array of values, starting from the start if
|
||||
* amount is negative
|
||||
*/
|
||||
public last(): V | undefined;
|
||||
public last(amount: number): V[];
|
||||
public last(amount?: number): V | V[] | undefined {
|
||||
const arr = [...this.values()];
|
||||
if (typeof amount === 'undefined') return arr[arr.length - 1];
|
||||
if (amount < 0) return this.first(amount * -1);
|
||||
if (!amount) return [];
|
||||
return arr.slice(-amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the last key(s) in this collection.
|
||||
*
|
||||
* @param amount Amount of keys to obtain from the end
|
||||
*
|
||||
* @returns A single key if no amount is provided or an array of keys, starting from the start if
|
||||
* amount is negative
|
||||
*/
|
||||
public lastKey(): K | undefined;
|
||||
public lastKey(amount: number): K[];
|
||||
public lastKey(amount?: number): K | K[] | undefined {
|
||||
const arr = [...this.keys()];
|
||||
if (typeof amount === 'undefined') return arr[arr.length - 1];
|
||||
if (amount < 0) return this.firstKey(amount * -1);
|
||||
if (!amount) return [];
|
||||
return arr.slice(-amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to [Array.at()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at).
|
||||
* Returns the item at a given index, allowing for positive and negative integers.
|
||||
* Negative integers count back from the last item in the collection.
|
||||
*
|
||||
* @param index The index of the element to obtain
|
||||
*/
|
||||
public at(index: number) {
|
||||
index = Math.floor(index);
|
||||
const arr = [...this.values()];
|
||||
return arr.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to [Array.at()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at).
|
||||
* Returns the key at a given index, allowing for positive and negative integers.
|
||||
* Negative integers count back from the last item in the collection.
|
||||
*
|
||||
* @param index The index of the key to obtain
|
||||
*/
|
||||
public keyAt(index: number) {
|
||||
index = Math.floor(index);
|
||||
const arr = [...this.keys()];
|
||||
return arr.at(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains unique random value(s) from this collection.
|
||||
*
|
||||
* @param amount Amount of values to obtain randomly
|
||||
*
|
||||
* @returns A single value if no amount is provided or an array of values
|
||||
*/
|
||||
public random(): V | undefined;
|
||||
public random(amount: number): V[];
|
||||
public random(amount?: number): V | V[] | undefined {
|
||||
const arr = [...this.values()];
|
||||
if (typeof amount === 'undefined') return arr[Math.floor(Math.random() * arr.length)];
|
||||
if (!arr.length || !amount) return [];
|
||||
return Array.from(
|
||||
{ length: Math.min(amount, arr.length) },
|
||||
(): V => arr.splice(Math.floor(Math.random() * arr.length), 1)[0],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains unique random key(s) from this collection.
|
||||
*
|
||||
* @param amount Amount of keys to obtain randomly
|
||||
*
|
||||
* @returns A single key if no amount is provided or an array
|
||||
*/
|
||||
public randomKey(): K | undefined;
|
||||
public randomKey(amount: number): K[];
|
||||
public randomKey(amount?: number): K | K[] | undefined {
|
||||
const arr = [...this.keys()];
|
||||
if (typeof amount === 'undefined') return arr[Math.floor(Math.random() * arr.length)];
|
||||
if (!arr.length || !amount) return [];
|
||||
return Array.from(
|
||||
{ length: Math.min(amount, arr.length) },
|
||||
(): K => arr.splice(Math.floor(Math.random() * arr.length), 1)[0],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to [Array.reverse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)
|
||||
* but returns a Collection instead of an Array.
|
||||
*/
|
||||
public reverse() {
|
||||
const entries = [...this.entries()].reverse();
|
||||
this.clear();
|
||||
for (const [key, value] of entries) this.set(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a single item where the given function returns a truthy value. This behaves like
|
||||
* [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find).
|
||||
* <warn>All collections used in Discord.js are mapped using their `id` property, and if you want to find by id you
|
||||
* should use the `get` method. See
|
||||
* [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) for details.</warn>
|
||||
*
|
||||
* @param fn The function to test with (should return boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.find(user => user.username === 'Bob');
|
||||
*/
|
||||
public find<V2 extends V>(fn: (value: V, key: K, collection: this) => value is V2): V2 | undefined;
|
||||
public find(fn: (value: V, key: K, collection: this) => boolean): V | undefined;
|
||||
public find<This, V2 extends V>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => value is V2,
|
||||
thisArg: This,
|
||||
): V2 | undefined;
|
||||
public find<This>(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): V | undefined;
|
||||
public find(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): V | undefined {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) return val;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for the key of a single item where the given function returns a truthy value. This behaves like
|
||||
* [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex),
|
||||
* but returns the key rather than the positional index.
|
||||
*
|
||||
* @param fn The function to test with (should return boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.findKey(user => user.username === 'Bob');
|
||||
*/
|
||||
public findKey<K2 extends K>(fn: (value: V, key: K, collection: this) => key is K2): K2 | undefined;
|
||||
public findKey(fn: (value: V, key: K, collection: this) => boolean): K | undefined;
|
||||
public findKey<This, K2 extends K>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => key is K2,
|
||||
thisArg: This,
|
||||
): K2 | undefined;
|
||||
public findKey<This>(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): K | undefined;
|
||||
public findKey(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): K | undefined {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) return key;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes items that satisfy the provided filter function.
|
||||
*
|
||||
* @param fn Function used to test (should return a boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @returns The number of removed entries
|
||||
*/
|
||||
public sweep(fn: (value: V, key: K, collection: this) => boolean): number;
|
||||
public sweep<T>(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): number;
|
||||
public sweep(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): number {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
const previousSize = this.size;
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) this.delete(key);
|
||||
}
|
||||
return previousSize - this.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to
|
||||
* [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter),
|
||||
* but returns a Collection instead of an Array.
|
||||
*
|
||||
* @param fn The function to test with (should return boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.filter(user => user.username === 'Bob');
|
||||
*/
|
||||
public filter<K2 extends K>(fn: (value: V, key: K, collection: this) => key is K2): Collection<K2, V>;
|
||||
public filter<V2 extends V>(fn: (value: V, key: K, collection: this) => value is V2): Collection<K, V2>;
|
||||
public filter(fn: (value: V, key: K, collection: this) => boolean): Collection<K, V>;
|
||||
public filter<This, K2 extends K>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => key is K2,
|
||||
thisArg: This,
|
||||
): Collection<K2, V>;
|
||||
public filter<This, V2 extends V>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => value is V2,
|
||||
thisArg: This,
|
||||
): Collection<K, V2>;
|
||||
public filter<This>(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): Collection<K, V>;
|
||||
public filter(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): Collection<K, V> {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
const results = new this.constructor[Symbol.species]<K, V>();
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) results.set(key, val);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partitions the collection into two collections where the first collection
|
||||
* contains the items that passed and the second contains the items that failed.
|
||||
*
|
||||
* @param fn Function used to test (should return a boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* const [big, small] = collection.partition(guild => guild.memberCount > 250);
|
||||
*/
|
||||
public partition<K2 extends K>(
|
||||
fn: (value: V, key: K, collection: this) => key is K2,
|
||||
): [Collection<K2, V>, Collection<Exclude<K, K2>, V>];
|
||||
public partition<V2 extends V>(
|
||||
fn: (value: V, key: K, collection: this) => value is V2,
|
||||
): [Collection<K, V2>, Collection<K, Exclude<V, V2>>];
|
||||
public partition(fn: (value: V, key: K, collection: this) => boolean): [Collection<K, V>, Collection<K, V>];
|
||||
public partition<This, K2 extends K>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => key is K2,
|
||||
thisArg: This,
|
||||
): [Collection<K2, V>, Collection<Exclude<K, K2>, V>];
|
||||
public partition<This, V2 extends V>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => value is V2,
|
||||
thisArg: This,
|
||||
): [Collection<K, V2>, Collection<K, Exclude<V, V2>>];
|
||||
public partition<This>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => boolean,
|
||||
thisArg: This,
|
||||
): [Collection<K, V>, Collection<K, V>];
|
||||
public partition(
|
||||
fn: (value: V, key: K, collection: this) => boolean,
|
||||
thisArg?: unknown,
|
||||
): [Collection<K, V>, Collection<K, V>] {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
const results: [Collection<K, V>, Collection<K, V>] = [
|
||||
new this.constructor[Symbol.species]<K, V>(),
|
||||
new this.constructor[Symbol.species]<K, V>(),
|
||||
];
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) {
|
||||
results[0].set(key, val);
|
||||
} else {
|
||||
results[1].set(key, val);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps each item into a Collection, then joins the results into a single Collection. Identical in behavior to
|
||||
* [Array.flatMap()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap).
|
||||
*
|
||||
* @param fn Function that produces a new Collection
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.flatMap(guild => guild.members.cache);
|
||||
*/
|
||||
public flatMap<T>(fn: (value: V, key: K, collection: this) => Collection<K, T>): Collection<K, T>;
|
||||
public flatMap<T, This>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => Collection<K, T>,
|
||||
thisArg: This,
|
||||
): Collection<K, T>;
|
||||
public flatMap<T>(fn: (value: V, key: K, collection: this) => Collection<K, T>, thisArg?: unknown): Collection<K, T> {
|
||||
const collections = this.map(fn, thisArg);
|
||||
return new this.constructor[Symbol.species]<K, T>().concat(...collections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps each item to another value into an array. Identical in behavior to
|
||||
* [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
|
||||
*
|
||||
* @param fn Function that produces an element of the new array, taking three arguments
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.map(user => user.tag);
|
||||
*/
|
||||
public map<T>(fn: (value: V, key: K, collection: this) => T): T[];
|
||||
public map<This, T>(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): T[];
|
||||
public map<T>(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): T[] {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
const iter = this.entries();
|
||||
return Array.from({ length: this.size }, (): T => {
|
||||
const [key, value] = iter.next().value;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return fn(value, key, this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps each item to another value into a collection. Identical in behavior to
|
||||
* [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map).
|
||||
*
|
||||
* @param fn Function that produces an element of the new collection, taking three arguments
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.mapValues(user => user.tag);
|
||||
*/
|
||||
public mapValues<T>(fn: (value: V, key: K, collection: this) => T): Collection<K, T>;
|
||||
public mapValues<This, T>(fn: (this: This, value: V, key: K, collection: this) => T, thisArg: This): Collection<K, T>;
|
||||
public mapValues<T>(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): Collection<K, T> {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
const coll = new this.constructor[Symbol.species]<K, T>();
|
||||
for (const [key, val] of this) coll.set(key, fn(val, key, this));
|
||||
return coll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there exists an item that passes a test. Identical in behavior to
|
||||
* [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
|
||||
*
|
||||
* @param fn Function used to test (should return a boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.some(user => user.discriminator === '0000');
|
||||
*/
|
||||
public some(fn: (value: V, key: K, collection: this) => boolean): boolean;
|
||||
public some<T>(fn: (this: T, value: V, key: K, collection: this) => boolean, thisArg: T): boolean;
|
||||
public some(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): boolean {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
for (const [key, val] of this) {
|
||||
if (fn(val, key, this)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all items passes a test. Identical in behavior to
|
||||
* [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every).
|
||||
*
|
||||
* @param fn Function used to test (should return a boolean)
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection.every(user => !user.bot);
|
||||
*/
|
||||
public every<K2 extends K>(fn: (value: V, key: K, collection: this) => key is K2): this is Collection<K2, V>;
|
||||
public every<V2 extends V>(fn: (value: V, key: K, collection: this) => value is V2): this is Collection<K, V2>;
|
||||
public every(fn: (value: V, key: K, collection: this) => boolean): boolean;
|
||||
public every<This, K2 extends K>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => key is K2,
|
||||
thisArg: This,
|
||||
): this is Collection<K2, V>;
|
||||
public every<This, V2 extends V>(
|
||||
fn: (this: This, value: V, key: K, collection: this) => value is V2,
|
||||
thisArg: This,
|
||||
): this is Collection<K, V2>;
|
||||
public every<This>(fn: (this: This, value: V, key: K, collection: this) => boolean, thisArg: This): boolean;
|
||||
public every(fn: (value: V, key: K, collection: this) => boolean, thisArg?: unknown): boolean {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
for (const [key, val] of this) {
|
||||
if (!fn(val, key, this)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a function to produce a single value. Identical in behavior to
|
||||
* [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce).
|
||||
*
|
||||
* @param fn Function used to reduce, taking four arguments; `accumulator`, `currentValue`, `currentKey`,
|
||||
* and `collection`
|
||||
* @param initialValue Starting value for the accumulator
|
||||
*
|
||||
* @example
|
||||
* collection.reduce((acc, guild) => acc + guild.memberCount, 0);
|
||||
*/
|
||||
public reduce<T>(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T {
|
||||
let accumulator!: T;
|
||||
|
||||
if (typeof initialValue !== 'undefined') {
|
||||
accumulator = initialValue;
|
||||
for (const [key, val] of this) accumulator = fn(accumulator, val, key, this);
|
||||
return accumulator;
|
||||
}
|
||||
let first = true;
|
||||
for (const [key, val] of this) {
|
||||
if (first) {
|
||||
accumulator = val as unknown as T;
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
accumulator = fn(accumulator, val, key, this);
|
||||
}
|
||||
|
||||
// No items iterated.
|
||||
if (first) {
|
||||
throw new TypeError('Reduce of empty collection with no initial value');
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identical to
|
||||
* [Map.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach),
|
||||
* but returns the collection instead of undefined.
|
||||
*
|
||||
* @param fn Function to execute for each element
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection
|
||||
* .each(user => console.log(user.username))
|
||||
* .filter(user => user.bot)
|
||||
* .each(user => console.log(user.username));
|
||||
*/
|
||||
public each(fn: (value: V, key: K, collection: this) => void): this;
|
||||
public each<T>(fn: (this: T, value: V, key: K, collection: this) => void, thisArg: T): this;
|
||||
public each(fn: (value: V, key: K, collection: this) => void, thisArg?: unknown): this {
|
||||
this.forEach(fn as (value: V, key: K, map: Map<K, V>) => void, thisArg);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a function on the collection and returns the collection.
|
||||
*
|
||||
* @param fn Function to execute
|
||||
* @param thisArg Value to use as `this` when executing function
|
||||
*
|
||||
* @example
|
||||
* collection
|
||||
* .tap(coll => console.log(coll.size))
|
||||
* .filter(user => user.bot)
|
||||
* .tap(coll => console.log(coll.size))
|
||||
*/
|
||||
public tap(fn: (collection: this) => void): this;
|
||||
public tap<T>(fn: (this: T, collection: this) => void, thisArg: T): this;
|
||||
public tap(fn: (collection: this) => void, thisArg?: unknown): this {
|
||||
if (typeof thisArg !== 'undefined') fn = fn.bind(thisArg);
|
||||
fn(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an identical shallow copy of this collection.
|
||||
*
|
||||
* @example
|
||||
* const newColl = someColl.clone();
|
||||
*/
|
||||
public clone() {
|
||||
return new this.constructor[Symbol.species](this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this collection with others into a new collection. None of the source collections are modified.
|
||||
*
|
||||
* @param collections Collections to merge
|
||||
*
|
||||
* @example
|
||||
* const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl);
|
||||
*/
|
||||
public concat(...collections: Collection<K, V>[]) {
|
||||
const newColl = this.clone();
|
||||
for (const coll of collections) {
|
||||
for (const [key, val] of coll) newColl.set(key, val);
|
||||
}
|
||||
return newColl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this collection shares identical items with another.
|
||||
* This is different to checking for equality using equal-signs, because
|
||||
* the collections may be different objects, but contain the same data.
|
||||
*
|
||||
* @param collection Collection to compare with
|
||||
*
|
||||
* @returns Whether the collections have identical contents
|
||||
*/
|
||||
public equals(collection: Collection<K, V>) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!collection) return false; // runtime check
|
||||
if (this === collection) return true;
|
||||
if (this.size !== collection.size) return false;
|
||||
for (const [key, value] of this) {
|
||||
if (!collection.has(key) || value !== collection.get(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sort method sorts the items of a collection in place and returns it.
|
||||
* The sort is not necessarily stable in Node 10 or older.
|
||||
* The default sort order is according to string Unicode code points.
|
||||
*
|
||||
* @param compareFunction Specifies a function that defines the sort order.
|
||||
* If omitted, the collection is sorted according to each character's Unicode code point value, according to the string conversion of each element.
|
||||
*
|
||||
* @example
|
||||
* collection.sort((userA, userB) => userA.createdTimestamp - userB.createdTimestamp);
|
||||
*/
|
||||
public sort(compareFunction: Comparator<K, V> = Collection.defaultSort) {
|
||||
const entries = [...this.entries()];
|
||||
entries.sort((a, b): number => compareFunction(a[1], b[1], a[0], b[0]));
|
||||
|
||||
// Perform clean-up
|
||||
super.clear();
|
||||
|
||||
// Set the new entries
|
||||
for (const [k, v] of entries) {
|
||||
super.set(k, v);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The intersect method returns a new structure containing items where the keys 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>();
|
||||
for (const [k, v] of other) {
|
||||
if (this.has(k)) coll.set(k, v);
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
/**
|
||||
* The difference method returns a new structure containing items where the key is present in one of the original structures but not the other.
|
||||
*
|
||||
* @param other The other Collection to filter against
|
||||
*/
|
||||
public difference(other: Collection<K, V>) {
|
||||
const coll = new this.constructor[Symbol.species]<K, V>();
|
||||
for (const [k, v] of other) {
|
||||
if (!this.has(k)) coll.set(k, v);
|
||||
}
|
||||
for (const [k, v] of this) {
|
||||
if (!other.has(k)) coll.set(k, v);
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
/**
|
||||
* The sorted method sorts the items of a collection and returns it.
|
||||
* The sort is not necessarily stable in Node 10 or older.
|
||||
* The default sort order is according to string Unicode code points.
|
||||
*
|
||||
* @param compareFunction Specifies a function that defines the sort order.
|
||||
* If omitted, the collection is sorted according to each character's Unicode code point value,
|
||||
* according to the string conversion of each element.
|
||||
*
|
||||
* @example
|
||||
* collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp);
|
||||
*/
|
||||
public sorted(compareFunction: Comparator<K, V> = Collection.defaultSort) {
|
||||
return new this.constructor[Symbol.species](this).sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk));
|
||||
}
|
||||
|
||||
public toJSON() {
|
||||
// toJSON is called recursively by JSON.stringify.
|
||||
return [...this.values()];
|
||||
}
|
||||
|
||||
private static defaultSort<V>(firstValue: V, secondValue: V): number {
|
||||
return Number(firstValue > secondValue) || Number(firstValue === secondValue) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type Comparator<K, V> = (firstValue: V, secondValue: V, firstKey: K, secondKey: K) => number;
|
||||
|
||||
export default Collection;
|
||||
20
packages/collection/tsconfig.eslint.json
Normal file
20
packages/collection/tsconfig.eslint.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"**/*.js",
|
||||
"**/*.mjs",
|
||||
"**/*.jsx",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.js",
|
||||
"**/*.test.mjs",
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.js",
|
||||
"**/*.spec.mjs"
|
||||
],
|
||||
"exclude": []
|
||||
}
|
||||
4
packages/collection/tsconfig.json
Normal file
4
packages/collection/tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
14
packages/collection/tsup.config.ts
Normal file
14
packages/collection/tsup.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { Options } from 'tsup';
|
||||
|
||||
export const tsup: Options = {
|
||||
clean: true,
|
||||
dts: true,
|
||||
entryPoints: ['src/index.ts'],
|
||||
format: ['esm', 'cjs'],
|
||||
minify: true,
|
||||
// if false: causes Collection.constructor to be a minified value like: 'o'
|
||||
keepNames: true,
|
||||
skipNodeModulesBundle: true,
|
||||
sourcemap: true,
|
||||
target: 'es2021',
|
||||
};
|
||||
1
packages/discord.js/.eslintignore
Normal file
1
packages/discord.js/.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
/typings/**/*
|
||||
201
packages/discord.js/.eslintrc.json
Normal file
201
packages/discord.js/.eslintrc.json
Normal file
@@ -0,0 +1,201 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
||||
"plugins": ["import"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2021
|
||||
},
|
||||
"env": {
|
||||
"es2021": true,
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": ["builtin", "external", "internal", "index", "sibling", "parent"],
|
||||
"alphabetize": {
|
||||
"order": "asc"
|
||||
}
|
||||
}
|
||||
],
|
||||
"prettier/prettier": [
|
||||
2,
|
||||
{
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "as-needed",
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
],
|
||||
"strict": ["error", "global"],
|
||||
"no-await-in-loop": "warn",
|
||||
"no-compare-neg-zero": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-unsafe-negation": "error",
|
||||
"valid-jsdoc": [
|
||||
"error",
|
||||
{
|
||||
"requireReturn": false,
|
||||
"requireReturnDescription": false,
|
||||
"prefer": {
|
||||
"return": "returns",
|
||||
"arg": "param"
|
||||
},
|
||||
"preferType": {
|
||||
"String": "string",
|
||||
"Number": "number",
|
||||
"Boolean": "boolean",
|
||||
"Symbol": "symbol",
|
||||
"object": "Object",
|
||||
"function": "Function",
|
||||
"array": "Array",
|
||||
"date": "Date",
|
||||
"error": "Error",
|
||||
"null": "void"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"accessor-pairs": "warn",
|
||||
"array-callback-return": "error",
|
||||
"consistent-return": "error",
|
||||
"curly": ["error", "multi-line", "consistent"],
|
||||
"dot-location": ["error", "property"],
|
||||
"dot-notation": "error",
|
||||
"eqeqeq": "error",
|
||||
"no-empty-function": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-multi-spaces": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-new": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-return-await": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-useless-return": "error",
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "warn",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"require-await": "warn",
|
||||
"wrap-iife": "error",
|
||||
"yoda": "error",
|
||||
|
||||
"no-label-var": "error",
|
||||
"no-shadow": "error",
|
||||
"no-undef-init": "error",
|
||||
|
||||
"callback-return": "error",
|
||||
"getter-return": "off",
|
||||
"handle-callback-err": "error",
|
||||
"no-mixed-requires": "error",
|
||||
"no-new-require": "error",
|
||||
"no-path-concat": "error",
|
||||
|
||||
"array-bracket-spacing": "error",
|
||||
"block-spacing": "error",
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"capitalized-comments": ["error", "always", { "ignoreConsecutiveComments": true }],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"comma-spacing": "error",
|
||||
"comma-style": "error",
|
||||
"computed-property-spacing": "error",
|
||||
"consistent-this": ["error", "$this"],
|
||||
"eol-last": "error",
|
||||
"func-names": "error",
|
||||
"func-name-matching": "error",
|
||||
"func-style": ["error", "declaration", { "allowArrowFunctions": true }],
|
||||
"key-spacing": "error",
|
||||
"keyword-spacing": "error",
|
||||
"max-depth": "error",
|
||||
"max-len": ["error", 120, 2],
|
||||
"max-nested-callbacks": ["error", { "max": 4 }],
|
||||
"max-statements-per-line": ["error", { "max": 2 }],
|
||||
"new-cap": "off",
|
||||
"newline-per-chained-call": ["error", { "ignoreChainWithDepth": 3 }],
|
||||
"no-array-constructor": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
|
||||
"no-new-object": "error",
|
||||
"no-spaced-func": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"no-whitespace-before-property": "error",
|
||||
"nonblock-statement-body-position": "error",
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"operator-assignment": "error",
|
||||
"padded-blocks": ["error", "never"],
|
||||
"quote-props": ["error", "as-needed"],
|
||||
"quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }],
|
||||
"semi-spacing": "error",
|
||||
"semi": "error",
|
||||
"space-before-blocks": "error",
|
||||
"space-before-function-paren": [
|
||||
"error",
|
||||
{
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}
|
||||
],
|
||||
"space-in-parens": "error",
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": "error",
|
||||
"spaced-comment": "error",
|
||||
"template-tag-spacing": "error",
|
||||
"unicode-bom": "error",
|
||||
|
||||
"arrow-body-style": "error",
|
||||
"arrow-parens": ["error", "as-needed"],
|
||||
"arrow-spacing": "error",
|
||||
"no-duplicate-imports": "error",
|
||||
"no-useless-computed-key": "error",
|
||||
"no-useless-constructor": "error",
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-numeric-literals": "error",
|
||||
"prefer-rest-params": "error",
|
||||
"prefer-spread": "error",
|
||||
"prefer-template": "error",
|
||||
"rest-spread-spacing": "error",
|
||||
"template-curly-spacing": "error",
|
||||
"yield-star-spacing": "error",
|
||||
|
||||
"no-restricted-globals": [
|
||||
"error",
|
||||
{
|
||||
"name": "Buffer",
|
||||
"message": "Import Buffer from `node:buffer` instead"
|
||||
},
|
||||
{
|
||||
"name": "process",
|
||||
"message": "Import process from `node:process` instead"
|
||||
},
|
||||
{
|
||||
"name": "setTimeout",
|
||||
"message": "Import setTimeout from `node:timers` instead"
|
||||
},
|
||||
{
|
||||
"name": "setInterval",
|
||||
"message": "Import setInterval from `node:timers` instead"
|
||||
},
|
||||
{
|
||||
"name": "setImmediate",
|
||||
"message": "Import setImmediate from `node:timers` instead"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
25
packages/discord.js/.gitignore
vendored
Normal file
25
packages/discord.js/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Packages
|
||||
node_modules/
|
||||
|
||||
# Log files
|
||||
logs/
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
|
||||
# Env
|
||||
.env
|
||||
test/auth.json
|
||||
test/auth.js
|
||||
docs/deploy/deploy_key
|
||||
docs/deploy/deploy_key.pub
|
||||
deploy/deploy_key
|
||||
deploy/deploy_key.pub
|
||||
|
||||
# Dist
|
||||
dist/
|
||||
docs/docs.json
|
||||
7
packages/discord.js/.prettierrc.json
Normal file
7
packages/discord.js/.prettierrc.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 120,
|
||||
"trailingComma": "all",
|
||||
"endOfLine": "lf",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
978
packages/discord.js/CHANGELOG.md
Normal file
978
packages/discord.js/CHANGELOG.md
Normal file
@@ -0,0 +1,978 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [13.5.0](https://github.com/discordjs/discord.js/compare/13.4.0...13.5.0) - (2021-12-29)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **GuildMemberManager:** Nick endpoint (#7151) ([d0c3961](https://github.com/discordjs/discord.js/commit/d0c3961aef41f17773fb14d06213df3fcb7fc8d2))
|
||||
- **Permissions:** ToArray shouldn't check admin (#7144) ([fc4292e](https://github.com/discordjs/discord.js/commit/fc4292e2e9ad381eb0ed07ef5e80a4251a5c4e9d))
|
||||
- Remove deprecation warning on `Message#cleanContent` (#7143) ([7e5f16b](https://github.com/discordjs/discord.js/commit/7e5f16b6b3060820446a325f4eb06dd60faee5a9))
|
||||
|
||||
## Features
|
||||
|
||||
- **GuildMember:** Add method to check timeout (#7146) ([baacd6b](https://github.com/discordjs/discord.js/commit/baacd6ba6979f11e1af38804df15468c29ec09e3))
|
||||
- **ClientOptions:** WaitGuildTimeout amount client option (#6576) ([2bfc638](https://github.com/discordjs/discord.js/commit/2bfc638a5cd0e4c0b2e69971d30828b51ab3c563))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **MessageEmbed:** Deprecate strings for `setAuthor()` (completely) and `setFooter()` (#7153) ([3496516](https://github.com/discordjs/discord.js/commit/3496516dc99149705754ed56f3e9dfe711d3926d))
|
||||
- Import timers, `process`, and `Buffer` from `node:` (#7157) ([3c62bd2](https://github.com/discordjs/discord.js/commit/3c62bd2d47dbd52b6b431014be87f584ae3d5309))
|
||||
|
||||
# [13.4.0](https://github.com/discordjs/discord.js/compare/13.3.1...13.4.0) - (2021-12-24)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **BaseMessageComponent:** Don't create new class instances (#7140) ([e6f41b5](https://github.com/discordjs/discord.js/commit/e6f41b578a62dba4a4941c342f7b9fd01b2d6254))
|
||||
- Make the followUp function error more clear (#7129) ([b763dab](https://github.com/discordjs/discord.js/commit/b763dabaa941826e635e630526ef227a16d69eec))
|
||||
- **StickerPack:** Nullify `bannerId` (#7119) ([6bb03f2](https://github.com/discordjs/discord.js/commit/6bb03f2c3450261e6c5330a9abede1bb1d33e84d))
|
||||
- Webhook typeguards should use string comparisons (#7127) ([645b3f8](https://github.com/discordjs/discord.js/commit/645b3f84f47f966e4c314bf6a9fcb216a503e6f8))
|
||||
- **Message:** Remove usage of `.deleted` (#7109) ([a0fe0ac](https://github.com/discordjs/discord.js/commit/a0fe0acbf1c0134d88d9fc519506cf33116288cc))
|
||||
- **GuildAuditLog:** Remove `Promise`s in constructor (#7089) ([9cf44d1](https://github.com/discordjs/discord.js/commit/9cf44d1c0e2cffdf285c73d151e7d8e0f5dbbb9a))
|
||||
- **ShardingManager:** Fix respawnAll not passing delay correctly (#7084) ([de61fe4](https://github.com/discordjs/discord.js/commit/de61fe485476102c106eb455d0c5e1f36fbf07df))
|
||||
- **StoreChannel:** Mark as deprecated (#7072) ([5ec542d](https://github.com/discordjs/discord.js/commit/5ec542d61fc47e6f150d96f5f4578ae2901d1cc7))
|
||||
- **InteractionCollector:** Handle thread (and parent) deletion (#7070) ([b5cd288](https://github.com/discordjs/discord.js/commit/b5cd2884b6277ac48c6d0663cf4916b249cda15b))
|
||||
- **ReactionCollector:** Check for channel.threads (#7069) ([3846f0d](https://github.com/discordjs/discord.js/commit/3846f0d97cf3ef81c578c0544e00dae3d1a5d994))
|
||||
- **GuildChannel:** Default to `this.rawPosition` in `clone()` (#7057) ([5fcda73](https://github.com/discordjs/discord.js/commit/5fcda73d9f383bb27f8b9f141921b6f0b7e25b4d))
|
||||
- Interaction channel type should be `GuildTextBasedChannels` when in guild (#6998) ([da86bd4](https://github.com/discordjs/discord.js/commit/da86bd4fa309bbf47e3b39d6669bf746cecf94da))
|
||||
- **Util:** Fix sorting for GuildChannels (#7002) ([c07207f](https://github.com/discordjs/discord.js/commit/c07207f219268010ace0dc6c35b518e990b2865b))
|
||||
- **MessageManager:** Do not use `client.emojis` (#7039) ([fd63139](https://github.com/discordjs/discord.js/commit/fd63139b41a7e97ecd633c36162c0e591df972bc))
|
||||
- **ActionsManager:** Revert to manual requires (#7034) ([0193efa](https://github.com/discordjs/discord.js/commit/0193efae714c7c8f5b6a52b27277cb65cae9971e))
|
||||
- **MessagePayload:** Prevent spread of `undefined` (#7029) ([fabd343](https://github.com/discordjs/discord.js/commit/fabd34381ce14a399204b0bf8fd1dde4bcb8628e))
|
||||
- **MessageManager:** Allow a string for `edit()` (#7033) ([54f937d](https://github.com/discordjs/discord.js/commit/54f937d82c4159d85e348dfb63b28f9f0c554805))
|
||||
- Avoid sending bot auth on token endpoints (#7022) ([7efeff4](https://github.com/discordjs/discord.js/commit/7efeff461fd542fcd50a5615320be680a2e72026))
|
||||
- **Sharding:** Properly handle errors in fetchClientValues (#6990) ([c0ba2d4](https://github.com/discordjs/discord.js/commit/c0ba2d46d0796c95598673f77f04b180280afb57))
|
||||
- **VoiceState:** Set streaming to false when the stream ended (#6992) ([fdb09cb](https://github.com/discordjs/discord.js/commit/fdb09cbe03d45f72fe3413fde0debf5a79c69824))
|
||||
- **MessageReaction:** Cache myself when `MessageReaction#me` is `true`. (#6956) ([b001e19](https://github.com/discordjs/discord.js/commit/b001e194f117ca8cfc9bcc9eb62dd7aab07988f7))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Deprecate `.deleted` getters (#7107) ([d43f684](https://github.com/discordjs/discord.js/commit/d43f68488e8d388fb7b2d3e49c1bf1b9721a1295))
|
||||
- **Sticker:** Fix typo (#7085) ([ee91f5a](https://github.com/discordjs/discord.js/commit/ee91f5a19cdcf15f17a80fc9a25a382b7cbcde9f))
|
||||
- **Constants:** Document missing errors (#7086) ([6e57b65](https://github.com/discordjs/discord.js/commit/6e57b65e99389eb8cbc8c2112281a9c1b7d3783a))
|
||||
- **Constants:** Adjust `GUILD_STORE` warning placement (#7083) ([23513d1](https://github.com/discordjs/discord.js/commit/23513d191727ad6c5b03ac2fd37b75db872b9792))
|
||||
- **StoreChannel:** Add deprecation warnings (#7080) ([fdba146](https://github.com/discordjs/discord.js/commit/fdba146f9bd9f2743041f6302ca5e38e26c8dc44))
|
||||
- **GuildStickerManager:** Fix create() example (#7060) ([6f58e81](https://github.com/discordjs/discord.js/commit/6f58e8122da1fe2dabc53c94cf12d65b9a414551))
|
||||
- **Invite:** Add info blocks for missing props (#7014) ([b183a8e](https://github.com/discordjs/discord.js/commit/b183a8eece6006950dd0aaf143b544be1ae500b1))
|
||||
- **MessageReference:** Fix static link (#7041) ([85e6812](https://github.com/discordjs/discord.js/commit/85e6812ce2077a8c82a600a6709ec6bc904f4285))
|
||||
- **Constants:** Fix typo "announcement" (#7016) ([a1a8ca4](https://github.com/discordjs/discord.js/commit/a1a8ca4814dc35766b897f2d825212faf088621a))
|
||||
- **README:** Add installation instruction on @discordjs/voice (#6964) ([3c857a6](https://github.com/discordjs/discord.js/commit/3c857a63632ef11a1f7aae00c98e1f1b9909bc87))
|
||||
- **Guild:** Fix setOwner() example (#6929) ([dc64541](https://github.com/discordjs/discord.js/commit/dc6454104f70e5a83518e102b448418615b184c3))
|
||||
|
||||
## Features
|
||||
|
||||
- Add support for GuildScheduledEvent (#6493) ([1316fd4](https://github.com/discordjs/discord.js/commit/1316fd4c6ad47729f566d3dd088bb3c144f4bf8e))
|
||||
- **GuildMember:** Add timeouts (#7104) ([aa7c1b2](https://github.com/discordjs/discord.js/commit/aa7c1b2081eb77659afd65c2f917afbcab3a162f))
|
||||
- Export Sweepers (#7117) ([b9b60a3](https://github.com/discordjs/discord.js/commit/b9b60a37b33aed2f85ef1e6cb6ae54481e946b92))
|
||||
- Add API error code 50109 (#7112) ([55960cc](https://github.com/discordjs/discord.js/commit/55960cc77827dfd4b95b91ad1259bedd69f092ea))
|
||||
- **Client:** Add global sweepers (#6825) ([d1ef2f5](https://github.com/discordjs/discord.js/commit/d1ef2f5e8b02d9a1a9051c08c181a8ac82ec616f))
|
||||
- Add API error code 20029 (#7078) ([f410536](https://github.com/discordjs/discord.js/commit/f410536c515ed3cf5ca9b528a302dd68a0ea22f8))
|
||||
- **ApplicationCommand:** Add setX methods for easier editing (#7063) ([7f980e3](https://github.com/discordjs/discord.js/commit/7f980e38b6838eaa0537d11e4d0848660c784a0c))
|
||||
- Add API error code 50055 (#7068) ([f028aea](https://github.com/discordjs/discord.js/commit/f028aea33317b845ace2c2079ed9e8dbd4aad09c))
|
||||
- **SnowflakeUtil:** Add `timestampFrom` (#7058) ([8b200c0](https://github.com/discordjs/discord.js/commit/8b200c0fee0cadf65244b1a84ccb6f244b9bfc7e))
|
||||
- **Guild:** Add premiumProgressbarEnabled (#6887) ([552d89f](https://github.com/discordjs/discord.js/commit/552d89fd4e536745bb51ade13cf500e94b871b9f))
|
||||
- Add `UserContextMenuInteraction` and `MessageContextMenuInteraction` (#7003) ([4fe063f](https://github.com/discordjs/discord.js/commit/4fe063f0d00562b5987447a6b2b5900b64faec96))
|
||||
- **Shard:** Add eval context (#7011) ([77aff08](https://github.com/discordjs/discord.js/commit/77aff08345cd2b76ca350ba8086717623f028534))
|
||||
- **ThreadChannel:** Add `ThreadChannel#viewable` (#6975) ([db09d79](https://github.com/discordjs/discord.js/commit/db09d7942333dffad4fba875567758550d65bfef))
|
||||
- **ThreadManager:** Add slowmode option on thread creation (#6989) ([493e4f9](https://github.com/discordjs/discord.js/commit/493e4f9350a53f005416ce3d1552d3e776e42854))
|
||||
- **MessageAttachment:** Description (alt text) support (#6871) ([5e0a7d5](https://github.com/discordjs/discord.js/commit/5e0a7d51fce3b67ba5a0e573fdc00a83693ad008))
|
||||
- **ApplicationCommand:** Add support for min and max values (#6855) ([c30a818](https://github.com/discordjs/discord.js/commit/c30a818ca9cf93b5e6157d8a5caca4576eeb3222))
|
||||
- **SystemChannelFlags:** Add new flag (#6870) ([49e3ce2](https://github.com/discordjs/discord.js/commit/49e3ce21339e19912ba853f00bc2d68ab117f29f))
|
||||
- **UserFlags:** Add BOT_HTTP_INTERACTIONS (#6733) ([f43140a](https://github.com/discordjs/discord.js/commit/f43140abaceffb46bd69c487d61f71d3078649b7))
|
||||
- Add new activity flags (#6699) ([47d74eb](https://github.com/discordjs/discord.js/commit/47d74ebf810fbf07cf79fde193a77171be24e74b))
|
||||
- **ApplicationFlags:** Add message content intent flags (#6888) ([e94073a](https://github.com/discordjs/discord.js/commit/e94073a6ab6630d4b1c582b456e8118f5fdaf866))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **UserManager:** Move methods to the manager (#7087) ([2ed02f7](https://github.com/discordjs/discord.js/commit/2ed02f7fc773a4d44ce1ec7763ae76ab86175495))
|
||||
- **RoleManager:** Move some methods over from Role (#7096) ([1e00fc2](https://github.com/discordjs/discord.js/commit/1e00fc200173686f7fdc50405e63c894077e9d59))
|
||||
- **Guild:** Remove duplicate methods (#7100) ([717e0e9](https://github.com/discordjs/discord.js/commit/717e0e963f35b9294bc9093a42104babfd22f6fb))
|
||||
- **Util:** Replace `Util.delayFor` with `tp.setTimeout` (#7082) ([25b8491](https://github.com/discordjs/discord.js/commit/25b84912351617f42de055ff0351286a0c9425da))
|
||||
- Make `Structure#deleted` a getter to a WeakSet (#7074) ([b093750](https://github.com/discordjs/discord.js/commit/b0937502d35a6519948b7320a0cc361acf1a1755))
|
||||
- **SnowflakeUtil:** Clean up utils and improve perf (#7036) ([e59fac3](https://github.com/discordjs/discord.js/commit/e59fac3fe3ab8dac73becd6b4094ed1e0484f3e6))
|
||||
- **MessageEmbed:** Utilise an object approach for `.setAuthor()` (#6966) ([73854ee](https://github.com/discordjs/discord.js/commit/73854ee8521fe7149a72aafcba815c6efc5939d6))
|
||||
- Deprecate application command events (#6937) ([28688e2](https://github.com/discordjs/discord.js/commit/28688e27d53986478696a74fabd587268b1db5bf))
|
||||
|
||||
## Typings
|
||||
|
||||
- **CategoryChannel:** Fix createChannel return type (#7138) ([1626dde](https://github.com/discordjs/discord.js/commit/1626dded5b1f7345371fe6001ddbb45d41031635))
|
||||
- **CategoryChannel:** `createChannel` should default to a text channel (#7132) ([a0a5b0e](https://github.com/discordjs/discord.js/commit/a0a5b0e4fad66833854a5e73b587022490eb52b6))
|
||||
- Make channel types a lot stricter (#7120) ([7b65a04](https://github.com/discordjs/discord.js/commit/7b65a04cb12a501628621553baa4de2486be1aab))
|
||||
- Forward cache types to collector filters (#7126) ([77489b9](https://github.com/discordjs/discord.js/commit/77489b90fcc471b809f48fe30398d2df0b416686))
|
||||
- Fix possibly `null` message properties (#7111) ([bc6a6c5](https://github.com/discordjs/discord.js/commit/bc6a6c539f6d2ae86f73c64b4c8b962d8f208063))
|
||||
- Use mapped enums instead of overloads (#7088) ([49f9a18](https://github.com/discordjs/discord.js/commit/49f9a1802023d89fc16c7f7f521742f952cfa095))
|
||||
- **MessageComponentInteraction:** Ensure `component` is not `null` (#7099) ([2ce244b](https://github.com/discordjs/discord.js/commit/2ce244b502293c07ff1c3e929b2afb861e341d88))
|
||||
- **GuildAuditLog:** Strengthen types (#7090) ([5a5c045](https://github.com/discordjs/discord.js/commit/5a5c045534cb1b79a5b1165eb13ecf7b9585c808))
|
||||
- **Message:** `guild` should be non-null when message is in guild (#6933) ([1230bee](https://github.com/discordjs/discord.js/commit/1230bee9bc81041eb4c034c99b3ab9904143a125))
|
||||
- Improve audit logs' typings (#6647) ([b6b4570](https://github.com/discordjs/discord.js/commit/b6b45704829c1439557409a5e1935b856e76326e))
|
||||
- **Interaction:** Narrow `memberPermissions` (#7054) ([01f8d1b](https://github.com/discordjs/discord.js/commit/01f8d1bed564a07d40b184dc7ff686a895ddda31))
|
||||
- **ApplicationCommandManager:** Deprecate old `*Data` type usages and allow camel cased dapi types to be used (#6959) ([2c91c48](https://github.com/discordjs/discord.js/commit/2c91c488e8d00444ec0a14049654cdb496f2e757))
|
||||
- **WebhookMessageOptions:** Disallow stickers (#7012) ([099536e](https://github.com/discordjs/discord.js/commit/099536ee600f84e1734443b7d12dbd7474432dcd))
|
||||
- Remove unneeded collector types (#7008) ([c1f2fe2](https://github.com/discordjs/discord.js/commit/c1f2fe29efc7f025c01fcb0d5f123be766778569))
|
||||
- Make event emitters use mapped event types (#7019) ([48555cb](https://github.com/discordjs/discord.js/commit/48555cb8ebb151c1c336849eef638b5d31783b0a))
|
||||
- **ApplicationSubcommandData:** Allow `autocomplete` to be `true` (#6981) ([ecc61f3](https://github.com/discordjs/discord.js/commit/ecc61f3c7469cc9e6be0512dc889871335269c72))
|
||||
- Fix interaction typeguards (#6976) ([06cd16f](https://github.com/discordjs/discord.js/commit/06cd16fe970543473fdf139e9e7cf061d3ee5bf7))
|
||||
- Strengthen autocomplete option types (#6950) ([7630158](https://github.com/discordjs/discord.js/commit/7630158f598716cbcc8d5a8abf084c20e2c30928))
|
||||
- Fix cache type fallback types (#6961) ([9f240ea](https://github.com/discordjs/discord.js/commit/9f240ea0d14aea50b97ee59440721359226da4cd))
|
||||
- Unify ApplicationCommandManager#create overloads (#6970) ([8e881d2](https://github.com/discordjs/discord.js/commit/8e881d2b9611a3786db6f5e95f25439e0a82f22c))
|
||||
- **Events:** Rest events can be emitted on BaseClient (#6936) ([c297829](https://github.com/discordjs/discord.js/commit/c297829d54a801fdb1a4cb3350e223f3c6a5e9e9))
|
||||
|
||||
# [13.3.1](https://github.com/discordjs/discord.js/compare/13.3.0...13.3.1) - (2021-11-01)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Assert channel types in message actions (#6919) ([9bd3689](https://github.com/discordjs/discord.js/commit/9bd3689fb1273956533a2d110cfc72407c58b832))
|
||||
- **MessageEmbed:** Only compare image urls in #equals (#6926) ([95d2a4d](https://github.com/discordjs/discord.js/commit/95d2a4d35ef30d83a2e9ca82b88c978f35c5e1e0))
|
||||
- Correctly access guild IDs inside managers (#6927) ([2d9ffb8](https://github.com/discordjs/discord.js/commit/2d9ffb8c5b1aa4f510b3448ea0eb1400ad6b85b9))
|
||||
|
||||
## Documentation
|
||||
|
||||
- **README:** Use correct capitalization of npm (#6930) ([bb245b7](https://github.com/discordjs/discord.js/commit/bb245b7b35f9614944969d98d3f115ebba8b1b1e))
|
||||
|
||||
## Typings
|
||||
|
||||
- Improve toJSON methods for message components & embeds (#6925) ([204aee7](https://github.com/discordjs/discord.js/commit/204aee799acf08ac5b5c782a7a602c25db19354d))
|
||||
|
||||
# [13.3.0](https://github.com/discordjs/discord.js/compare/13.2.0...13.3.0) - (2021-10-29)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Handle message bulk delete and thread delete in collectors (#6902) ([d6685b1](https://github.com/discordjs/discord.js/commit/d6685b1c5097377b8228b32ff05f1e5553051417))
|
||||
- **ApplicationCommandManager:** Update guild command cache on c/u/d (#6841) ([f169c8f](https://github.com/discordjs/discord.js/commit/f169c8fe460ef2be6f38d6ee73c55d8b4182e3b7))
|
||||
- **TextBasedChannel:** Return the cached message instead of clone it (#6877) ([ceaf738](https://github.com/discordjs/discord.js/commit/ceaf738d2efc4b482c8a1fc5b486df99b1d0f037))
|
||||
- **MessageComponentInteraction:** Component getter is not null anymore (#6835) ([7621e9d](https://github.com/discordjs/discord.js/commit/7621e9da4c9c5f501131d64aaa1a3a16c3b985db))
|
||||
- `PartialGuildMember#id` is not null (#6840) ([4dff279](https://github.com/discordjs/discord.js/commit/4dff279a6f88612db9283851fba8850a2d6c65fe))
|
||||
- **Webhook:** Resolve source guild only if cached (#6834) ([d193d04](https://github.com/discordjs/discord.js/commit/d193d04cea862e2db84ac40226cfdbdb39be46d5))
|
||||
- **AllowedImageSizes:** Add new image sizes (#6844) ([ef01b84](https://github.com/discordjs/discord.js/commit/ef01b84fa8c8933a496528da8eeeb346cbf41ea4))
|
||||
- **MessageReaction:** Prevent event double fire from uncached messages (#6818) ([267a4b3](https://github.com/discordjs/discord.js/commit/267a4b3f68fa81629a083ebf04f7e49b5579ae86))
|
||||
- **Guild:** Guild.available is never set on new joins (#6769) ([29667c9](https://github.com/discordjs/discord.js/commit/29667c96e52a9f0b1e499fa6c21d9fe80e06bb37))
|
||||
- **Types:** Export more types (#6808) ([b474677](https://github.com/discordjs/discord.js/commit/b47467755cb5d1dd779d79ad86eb678bb13541e9))
|
||||
- **GuildBanManager:** Send reason in the headers instead of json body (#6800) ([bfb89de](https://github.com/discordjs/discord.js/commit/bfb89de864fd5dc4cbb654f6259f802ee21c9a0e))
|
||||
- **User:** Don't generate the banner URL when not cached (#6783) ([0d599a1](https://github.com/discordjs/discord.js/commit/0d599a1a7680fc4a35b5f44ba0c3b9aeccccbfaf))
|
||||
- **GuildMember:** More explicit partial check (#6760) ([b1656bf](https://github.com/discordjs/discord.js/commit/b1656bfb4f72819512fc75d5c052d2982f0b9683))
|
||||
- **Role:** Check for presence of icon and unicode_emoji before patching (#6780) ([e31c5ca](https://github.com/discordjs/discord.js/commit/e31c5ca1a88a32e425f9e28abbdfd66d4309c5c6))
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Constants:** Document missing autocomplete interaction constants (#6916) ([aa4d055](https://github.com/discordjs/discord.js/commit/aa4d05504f2532f946e83bf06f4527bbc0e54a89))
|
||||
- **InteractionCollector:** Add info block about being prone to always running (#6906) ([5d987ee](https://github.com/discordjs/discord.js/commit/5d987ee56ebe4839cd5737001030ef6321d9dd26))
|
||||
- **GuildStickerManager:** Fix create() example (#6900) ([bdd841a](https://github.com/discordjs/discord.js/commit/bdd841a1e7989769804f61ef000ffce8b4beb088))
|
||||
- **InteractionResponses:** Move embed var position in example (#6896) ([8806039](https://github.com/discordjs/discord.js/commit/88060395d198cd4f43de434aea6efb7ca93ea221))
|
||||
- **Application:** Rename Oauth2Application to Application (#6891) ([76856b9](https://github.com/discordjs/discord.js/commit/76856b967af1f9d467451b229822b8a03d76e29f))
|
||||
- **Util:** Deprecate `.removeMentions()` (#6866) ([b6c9fd6](https://github.com/discordjs/discord.js/commit/b6c9fd691f5e11012e2a75079abe5961c8cc89cd))
|
||||
- Correct tags used for objects (#6846) ([f7b7aac](https://github.com/discordjs/discord.js/commit/f7b7aac8b6fdd0ff66801ebc4de7773db4737523))
|
||||
- Redirect to events correctly (#6845) ([38cc89e](https://github.com/discordjs/discord.js/commit/38cc89e5ae02b4a2fae51d3df96f7bbb48754755))
|
||||
- Typos, consistency and grammar fixes (#6811) ([c44ea50](https://github.com/discordjs/discord.js/commit/c44ea50157cecc9495df44a952fc0400a6f56e26))
|
||||
- **Message:** Specify `Snowflake` in return type of `awaitReactions()` (#6822) ([4354c37](https://github.com/discordjs/discord.js/commit/4354c37762663e135e7088d405989542200829dc))
|
||||
- Replace `FetchOwnerOptions` type definition (#6814) ([b030130](https://github.com/discordjs/discord.js/commit/b030130df179cb68749905248f280108c6a2956a))
|
||||
- Remove dangling reference (#6810) ([d57ec7a](https://github.com/discordjs/discord.js/commit/d57ec7ab68a7ef62f0410888bac8d57bfa490a8b))
|
||||
- **InteractionCollector:** Remove repeated "the" (#6802) ([b1b9c83](https://github.com/discordjs/discord.js/commit/b1b9c83df0683ac3780316ec62b9621571102613))
|
||||
- **MessagePayload:** Change the typo of "wether" to "whether" (#6771) ([d32956c](https://github.com/discordjs/discord.js/commit/d32956c6b70a3a03c431d5f761c058072999289a))
|
||||
|
||||
## Features
|
||||
|
||||
- **ThreadMemberManager:** Allow individual members to be fetched (#6889) ([14716df](https://github.com/discordjs/discord.js/commit/14716df6b62b35f3a09243ba12242db9dc798aa7))
|
||||
- Add support for autocomplete interactions (#6672) ([ddf759c](https://github.com/discordjs/discord.js/commit/ddf759c8117e7a00702d444f5b5f0c2257189b09))
|
||||
- **MessageEmbed:** Add #equals (#6885) ([fae4abf](https://github.com/discordjs/discord.js/commit/fae4abf2f7071425639e8d1ea1a8598403fa2a07))
|
||||
- **StartThreadOptions:** Default autoArchiveDuration to channel's defaultAutoArchiveDuration (#6278) ([740d3f0](https://github.com/discordjs/discord.js/commit/740d3f006ef637709e3026f90fe72f93b8397229))
|
||||
- Add `rtcRegion` to `GuildManager#create()` (#6858) ([399e720](https://github.com/discordjs/discord.js/commit/399e720b92c11539f4d16a13e1b8190f136da6cc))
|
||||
- Add typeguards to webhooks (#6850) ([e0afcad](https://github.com/discordjs/discord.js/commit/e0afcadda4bf70497b327cd3b3372688ba03422a))
|
||||
- **GuildChannelManager:** Add 'rtcRegion' option to 'create' method (#6849) ([487d32d](https://github.com/discordjs/discord.js/commit/487d32d303c340b1609b0fe6b829a5f4fe001ef0))
|
||||
- **Permissions:** Add checkAdmin to permission overwrite checks (#6847) ([7513b45](https://github.com/discordjs/discord.js/commit/7513b4528ca1b6cf03b8af147feb73ea42a4f8e6))
|
||||
- **Interaction:** Add `isApplicationCommand` check (#6801) ([6898fa3](https://github.com/discordjs/discord.js/commit/6898fa3b37bf5248c85417f145dc377b4c0ebc82))
|
||||
- **CommandInteraction:** Add toString method (#6793) ([bd48e6d](https://github.com/discordjs/discord.js/commit/bd48e6df844fd535949937c3603629413d422526))
|
||||
- **Client:** Add apiResponse and apiRequest events (#6739) ([26f927b](https://github.com/discordjs/discord.js/commit/26f927b9fe338f2f3dc413f46122532608a5a080))
|
||||
- **ModuleImporter:** Implement import module compatible with bundlers (#6709) ([d399a28](https://github.com/discordjs/discord.js/commit/d399a28323fbcdc8c3e94f10b97f47e0dfc61f7a))
|
||||
|
||||
## Refactor
|
||||
|
||||
- Move Guild setPositions methods to managers (#6875) ([e12a5b6](https://github.com/discordjs/discord.js/commit/e12a5b6a0cfb4987cc504369a648e3f81ce8257e))
|
||||
- Remove gen-esm-wrapper dependency (#6884) ([b278884](https://github.com/discordjs/discord.js/commit/b27888455f811891ec652936b9b3292abdc05955))
|
||||
- Fix typos (#6852) ([672baa4](https://github.com/discordjs/discord.js/commit/672baa49e66bb1a6e757ec839cccc1c982063679))
|
||||
- **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))
|
||||
|
||||
## Typings
|
||||
|
||||
- **fix:** BaseCommandInteractionOptionResolver and CommandInteraction (#6910) ([673c03f](https://github.com/discordjs/discord.js/commit/673c03f7cf55379ed1cf7fafed3b81dbdde3a343))
|
||||
- **Constants:** Remove deleted properties from Package (#6908) ([7be9170](https://github.com/discordjs/discord.js/commit/7be9170659d73685455f0f942733737305217797))
|
||||
- **Shard:** Eval returns a promise resolving with T instead of T[] (#6901) ([14d9a99](https://github.com/discordjs/discord.js/commit/14d9a9901bc03873560d729e7789ac043891c2f0))
|
||||
- **ApplicationCommandManager:** Add missing overload for `fetch` (#6904) ([ee93a27](https://github.com/discordjs/discord.js/commit/ee93a27e15058a4366dda18e7befcd2f6dd7aa91))
|
||||
- **TextBasedChannel:** Text channel interaction collectors should have `message` option (#6903) ([91a432e](https://github.com/discordjs/discord.js/commit/91a432e49d4d431583de15ad49f5c48c1f88f4ce))
|
||||
- Cache types cleanup (#6867) ([b2836da](https://github.com/discordjs/discord.js/commit/b2836daafeac0da908c72938e7e8a79629569a69))
|
||||
- Allow message cached props to be narrowed (#6838) ([c3948f8](https://github.com/discordjs/discord.js/commit/c3948f82532fe3d03bb0fa205a0a9a0afdadcfac))
|
||||
- **CommandInteractionOptionResolver:** Allow narrowing of `getMember()` (#6831) ([e8b6997](https://github.com/discordjs/discord.js/commit/e8b69974dcb0e97773679eac04ed0d8918d0c451))
|
||||
- **BaseMessageComponent:** Remove third parameter of `create()` (#6833) ([d27fddb](https://github.com/discordjs/discord.js/commit/d27fddbf9a39c530cee123a08c8946429578f7e2))
|
||||
- Message component cached props narrowing (#6809) ([b541d0a](https://github.com/discordjs/discord.js/commit/b541d0a524ea7a8a6d2ab16c92f8ec5d4b100ca6))
|
||||
- **ApplicationCommandOptionData:** Remove required on subcommands (#6790) ([5566404](https://github.com/discordjs/discord.js/commit/5566404850029cc6e17d96695ee4ff8f3614e143))
|
||||
- **Integration:** Add `IntegrationType` values (#6815) ([187581d](https://github.com/discordjs/discord.js/commit/187581dd84a9a33662902b0ee12e63b0f16c4cc4))
|
||||
- **WelcomeChannelData:** Allow store channels (#6778) ([45ebea3](https://github.com/discordjs/discord.js/commit/45ebea3216b8013969b74ecfbb06de3d43c09385))
|
||||
- Make embed author and footer props `name` and `text` required (#6779) ([a84e51b](https://github.com/discordjs/discord.js/commit/a84e51b767c47ea06bd30fb490931f700c810952))
|
||||
|
||||
# [13.2.0](https://github.com/discordjs/discord.js/compare/13.1.0...13.2.0) - (2021-10-05)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **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))
|
||||
- **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))
|
||||
- Don't patch set data with undefined (#6694) ([9eb9591](https://github.com/discordjs/discord.js/commit/9eb9591473902a7608aed9c1927690c4445a6fb9))
|
||||
- **Invite:** #guild never resolving into a Guild (#6742) ([b76bb8a](https://github.com/discordjs/discord.js/commit/b76bb8a409c63aef9279acf5c1f60e846131f755))
|
||||
- **GuildManager:** Add missing types and converts (#6683) ([cdf65f7](https://github.com/discordjs/discord.js/commit/cdf65f74e1e9d22d405617521d1e6711493ca120))
|
||||
- **Util:** Default `animated` to false when omitted on resolvePartialEmoji (#6725) ([8d80fec](https://github.com/discordjs/discord.js/commit/8d80fec86d39fc640fd746cc03e6270cd574c0cf))
|
||||
- **Message:** Throw error on missing channel (#6581) ([60aa9ae](https://github.com/discordjs/discord.js/commit/60aa9ae478597caf66d5891ff6ca4d7b4336bcba))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Message:** Pinnable returning false in non-DEFAULT messages (#6585) ([3183b11](https://github.com/discordjs/discord.js/commit/3183b1166a8c96f8864f7307710f88193217a773))
|
||||
- **threadMembersUpdate:** Fixed typo (#6589) ([8826e9f](https://github.com/discordjs/discord.js/commit/8826e9ffbcc8990dbebe3ccdf6e65241ab4c863c))
|
||||
- **ThreadChannel:** FetchStarterMessage bug (#6584) ([08edc0b](https://github.com/discordjs/discord.js/commit/08edc0b1db52992b2a2f8f6012a6001fb4336f38))
|
||||
- Await message component collectors should return component interactions not collectors (#6562) ([f49f70a](https://github.com/discordjs/discord.js/commit/f49f70a4ebacf657f22d73043e3a504710821249))
|
||||
- **GuildChannel:** Fix manageable method for voice-channels (#6447) ([9301c9b](https://github.com/discordjs/discord.js/commit/9301c9b42085e860f49a322879b21b923e23a4d7))
|
||||
- **MessageAttachment:** Re-assign name (#6518) ([8a8c69a](https://github.com/discordjs/discord.js/commit/8a8c69a2575b9afc18fdb46a03424e7029499d17))
|
||||
- **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))
|
||||
- **Message:** Fix typo (#6435) ([ecb6e50](https://github.com/discordjs/discord.js/commit/ecb6e50b46e627e3217107d662dd19c64527976d))
|
||||
|
||||
## Documentation
|
||||
|
||||
- FetchReply info + example (#6753) ([8bc1ece](https://github.com/discordjs/discord.js/commit/8bc1ece98ea59c90cd40b4935bafb3a523d3eef5))
|
||||
- **GuildMemberUpdateAction:** Event doesn't get emitted on user update (#6752) ([1db3e76](https://github.com/discordjs/discord.js/commit/1db3e760544ff0ac01bb53a7ae5d55013367402f))
|
||||
- Better links for `.toJSON()` of button and select menu (#6745) ([6e5c768](https://github.com/discordjs/discord.js/commit/6e5c768379c7f573aac412c6a3140649d03c1540))
|
||||
- Undocument private constructors (#6732) ([34b2ad0](https://github.com/discordjs/discord.js/commit/34b2ad0d8ee39eb9cc964a4334a803b2ab48cae5))
|
||||
- **Message:** Fix return type for `reply` (#6720) ([3f11009](https://github.com/discordjs/discord.js/commit/3f1100976f8790ffd1a92c78554111cf4a9bd09f))
|
||||
- **CommandInteractionResolvedData:** Fix key type (#6729) ([466e796](https://github.com/discordjs/discord.js/commit/466e796a1d2a9e2d3d8bb1a5820cf35eda0a1c40))
|
||||
- **EmojiResolvable:** Update description of typedef to remove ambiguity (#6708) ([7cba676](https://github.com/discordjs/discord.js/commit/7cba67620ebba8457863bdea473ee5df7c15e6b6))
|
||||
- **ApplicationCommandPermissionsManager:** Fix example set method (#6658) ([839974c](https://github.com/discordjs/discord.js/commit/839974ca432c70d57e82e9b47334f743e0c20281))
|
||||
- **Shard:** Point to correct events (#6641) ([b9a4899](https://github.com/discordjs/discord.js/commit/b9a489949166775fe5ccc72e73beae37f6d7e886))
|
||||
- **VoiceChannel:** Deprecate editable (#6613) ([88e2622](https://github.com/discordjs/discord.js/commit/88e2622ddebb8cacd264833ceb371e2fdbe512d5))
|
||||
- **PermissionOverwriteManager:** Correct `@returns` of delete (#6632) ([3c3522a](https://github.com/discordjs/discord.js/commit/3c3522ae8a73c6e516294114187f26bd06f98fc7))
|
||||
- **MessagePayload:** Correct return type of `resolveFile()` (#6605) ([ea6a57e](https://github.com/discordjs/discord.js/commit/ea6a57e927189b75d647f252f05efd4ac4d87ffa))
|
||||
- **MessageButton:** Fix info tag (#6590) ([db73cf9](https://github.com/discordjs/discord.js/commit/db73cf925546cfe5da7cfe1eaa904341734491c5))
|
||||
- **WidgetMember:** Fix typo for deaf (#6564) ([33f6f82](https://github.com/discordjs/discord.js/commit/33f6f8211f4c2b52a396f9f6b23d1ee0b253f808))
|
||||
- **Constants:** Fix interaction type link (#6558) ([29d5fd1](https://github.com/discordjs/discord.js/commit/29d5fd163c62ff03aa642f111972914fdeed3669))
|
||||
- Fix JSDoc for `ClientUser#edit` (#6554) ([34024f5](https://github.com/discordjs/discord.js/commit/34024f5ef6192fa0da5b7d6aa7e2d219066ad9b0))
|
||||
- **Util:** Correct `@param` for `cleanContent()` (#6531) ([b89280a](https://github.com/discordjs/discord.js/commit/b89280a1dd19513b06991aae1d3b720aa3a1c542))
|
||||
- **Formatters:** Fix typo of TimestampStyles (#6523) ([7d4a40a](https://github.com/discordjs/discord.js/commit/7d4a40a26d1ecbebfd654fb74e99214c46dbbced))
|
||||
- **GuildChannelCreateOptions:** Fix #type type (#6502) ([4bfd5d3](https://github.com/discordjs/discord.js/commit/4bfd5d3e74e61ae65e7e0e66abdb1365f3a5ee72))
|
||||
- **ThreadManager:** Fix typo (#6485) ([8a95211](https://github.com/discordjs/discord.js/commit/8a9521123086e072c664512128b46209b2f00e06))
|
||||
- Fix wrong type being displayed in docs (#6504) ([9ca10cc](https://github.com/discordjs/discord.js/commit/9ca10cce06d86680236bc74367f524bb3708d8e6))
|
||||
- **MessageManager:** Fix typo (#6482) ([70cc029](https://github.com/discordjs/discord.js/commit/70cc0295f833cd988ea627b37d20536f73e21630))
|
||||
- **MessageReference:** Add possible message types (#6464) ([93a83c2](https://github.com/discordjs/discord.js/commit/93a83c2cf7c8f973b62242f8440fa0527b73c027))
|
||||
- **ApplicationCommandType:** Add DAPI link (#6463) ([17b4079](https://github.com/discordjs/discord.js/commit/17b407935bcb66881433fc528bc85379bf17ca81))
|
||||
- **BufferResolvable:** Add warning for URL input (#6451) ([16493e6](https://github.com/discordjs/discord.js/commit/16493e65fd3e2b9a49afbdd58603bd43f3a4005a))
|
||||
- **Formatters:** Use id over ID (#6439) ([84bb4f4](https://github.com/discordjs/discord.js/commit/84bb4f415313282d606b853abda8e0dc698e8f7b))
|
||||
- **RoleManager:** Error in examples (#6416) ([759faa4](https://github.com/discordjs/discord.js/commit/759faa4174b82cadc4ff7138a53b10143485e7e3))
|
||||
- Rename implementation of deferReply (#6412) ([615afab](https://github.com/discordjs/discord.js/commit/615afab8bba40efef88d232c9da8397d66fb5f17))
|
||||
|
||||
## Features
|
||||
|
||||
- Add support for role icons (#6633) ([7129965](https://github.com/discordjs/discord.js/commit/7129965423e9fb333ca93cecba54b588073873fd))
|
||||
- **Interaction:** Add memberPermissions (#6741) ([28d96e3](https://github.com/discordjs/discord.js/commit/28d96e344bb4b4d9dfb7c9b41a04c95c1eecbd25))
|
||||
- **CategoryChannel:** Add createChannel shortcut method (#6614) ([3eacf7a](https://github.com/discordjs/discord.js/commit/3eacf7a58785db0639aa38ac4fd455f3b318d4f5))
|
||||
- Allow webhooks to fetch, edit and delete messages in threads (#6695) ([107822d](https://github.com/discordjs/discord.js/commit/107822d28d9de04f6c14fea74647c46fe2fd1016))
|
||||
- **Threads:** Update permissions and fix getters (#6466) ([10478ad](https://github.com/discordjs/discord.js/commit/10478ad14850123625a551b5c26143aa32313ab8))
|
||||
- **PartialGroupDMChannel:** Add recipients & fix name (#6713) ([2803db6](https://github.com/discordjs/discord.js/commit/2803db683defe73a8b24a9f3c98d7f90d9605e5c))
|
||||
- **GuildMember:** Add guild avatars (#5696) ([dfd7b40](https://github.com/discordjs/discord.js/commit/dfd7b403a932b2e779b0b1619ebd701a86f70d00))
|
||||
- **MessageAttachment:** Add support for ephemeral property (#6652) ([c5db0ff](https://github.com/discordjs/discord.js/commit/c5db0ff60600875534b8bd04666ec99770497870))
|
||||
- **ApplicationCommand:** Add support for channel_types (#6640) ([3b14883](https://github.com/discordjs/discord.js/commit/3b14883e349c23a15aec225bb133ce49ed440817))
|
||||
- **UserManager:** Allow #fetch to take UserResolvable (#6677) ([a06a87a](https://github.com/discordjs/discord.js/commit/a06a87a7c49db29b108b77db82cf8e6f4346ef19))
|
||||
- Add api error code 50101 (#6663) ([42fdcaa](https://github.com/discordjs/discord.js/commit/42fdcaa1da65f097ef441beee5062f78ae03dfda))
|
||||
- Add support for API command types in `ApplicationCommandManager` (#6621) ([ecd637f](https://github.com/discordjs/discord.js/commit/ecd637f7d6174d4c8e86c8eb8e782eb6a197dd6e))
|
||||
- **Permissions:** Add `START_EMBEDDED_ACTIVITIES` (#6622) ([66a90d3](https://github.com/discordjs/discord.js/commit/66a90d3f8903c7dbe17851f7120a06f0e1f2ee96))
|
||||
- **Integration:** Add missing props and fix docs/types (#6623) ([caa3b60](https://github.com/discordjs/discord.js/commit/caa3b60c30a8ab13d195e084331889aed820a389))
|
||||
- Default values for setX boolean methods (#6619) ([8add4b0](https://github.com/discordjs/discord.js/commit/8add4b08f5e93ff690454b8f9673f2ad4a678841))
|
||||
- Add api error code 30042 (#6635) ([183dbd7](https://github.com/discordjs/discord.js/commit/183dbd7e533f17ae3375f42fd95cbaf3ea06bffd))
|
||||
- Give removed `MessageReaction`s on `messageReactionRemoveAll` event (#6607) ([be8912a](https://github.com/discordjs/discord.js/commit/be8912a4219d1c1aa59a8060707973e567b7b5a3))
|
||||
- **ApplicationCommand:** Add version property (#6603) ([f866512](https://github.com/discordjs/discord.js/commit/f866512e8435e03012222298af09addefb605451))
|
||||
- **MessageTypes:** Add CONTEXT_MENU_COMMAND (23) (#6425) ([d81590d](https://github.com/discordjs/discord.js/commit/d81590d566f7252832acfa97976343f551405848))
|
||||
- Add api error code 160002 (#6566) ([d16ada9](https://github.com/discordjs/discord.js/commit/d16ada97087e0324134484c9c0724b52a2839bdf))
|
||||
- **ApplicationCommand:** Add #equals (#6414) ([581921f](https://github.com/discordjs/discord.js/commit/581921f8b7152a009cb3bd0496627665b7e3442b))
|
||||
- **Threads:** Add support for invitable in private threads (#6501) ([a693254](https://github.com/discordjs/discord.js/commit/a6932546e2ed919bf130a919a597b4f31ef35307))
|
||||
- **BaseGuildTextChannel:** Export `BaseGuildTextChannel` (#6527) ([fc51f61](https://github.com/discordjs/discord.js/commit/fc51f61f0cdc66087e918165646aee4be74e6e56))
|
||||
- **User:** Banners and accent colors (#6117) ([839c6da](https://github.com/discordjs/discord.js/commit/839c6da03d0cc24b9023d807ba53c81704b9cb72))
|
||||
- **MessageAttachment:** Allow files to be marked as spoilers (#6509) ([96e26c4](https://github.com/discordjs/discord.js/commit/96e26c428d7745b14908d56a96b635226471d699))
|
||||
- **ThreadChannel:** Add fetchStarterMessage (#6488) ([705c5a1](https://github.com/discordjs/discord.js/commit/705c5a1c17bc3ba31f03f7bd6831e4c50dcbddd0))
|
||||
- **Message:** Add method to resolve a component by id (#6484) ([57b94b9](https://github.com/discordjs/discord.js/commit/57b94b9adf0d7444f494190fc2c8a29d44f1c5eb))
|
||||
- Set methods for MessageActionRow and MessageSelectMenu (#6490) ([fb50dd9](https://github.com/discordjs/discord.js/commit/fb50dd984178b21375928431fb106f3ba5ed91ee))
|
||||
- Export BaseCommandInteraction (#6478) ([c14e594](https://github.com/discordjs/discord.js/commit/c14e594d8a905d5559aa1f6ce013d245552295fd))
|
||||
- **Guild:** Add `Guild#maximumBitrate` getter. (#6455) ([21983de](https://github.com/discordjs/discord.js/commit/21983de3e00b6ae72bb8a41359209f77025a7808))
|
||||
- **Message:** Prevent fetching an interaction webhook. (#6468) ([f39b597](https://github.com/discordjs/discord.js/commit/f39b597e3120701287e86acdb247b4815f693c91))
|
||||
- Add maximum prune requests reached api error (#6427) ([a4b8623](https://github.com/discordjs/discord.js/commit/a4b8623b60150b3d9e3d2d54a2ef07e240e3c5c7))
|
||||
- **Rest:** Expose https.Agent options (#6177) ([5eb3553](https://github.com/discordjs/discord.js/commit/5eb3553fd1d7bcd88f2ddbccb452a470eb853ecb))
|
||||
- **InteractionReponses:** Allow fetching of ephemeral messages (#6426) ([d289d5c](https://github.com/discordjs/discord.js/commit/d289d5ccb7153df4656f071c69f41efe74754362))
|
||||
- Export ContextMenuInteraction (#6434) ([170c0c4](https://github.com/discordjs/discord.js/commit/170c0c4985595f77555c07747e72ae381d98a4d4))
|
||||
|
||||
## Performance
|
||||
|
||||
- Use logical assignments instead of if statements (#6693) ([e9daa31](https://github.com/discordjs/discord.js/commit/e9daa31eaf73c90daee667fb89542bd0e5e763ad))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **User:** Set accentColor and banner to undefined when not yet received (#6721) ([ba93e85](https://github.com/discordjs/discord.js/commit/ba93e85d0da6dc8e30e7a23e1936f605c9ce21d1))
|
||||
- Use optional chaining (#6757) ([a194d9c](https://github.com/discordjs/discord.js/commit/a194d9c37fa05152738efe26a5e698cf7716d282))
|
||||
- Use the `node:` protocol (#6710) ([531b46c](https://github.com/discordjs/discord.js/commit/531b46c60d022f0814c6528abc922d40e4ad3476))
|
||||
- **VoiceState:** Use manager edit method to remove error (#6631) ([29dd319](https://github.com/discordjs/discord.js/commit/29dd319b6818329ed91df7c6380dfdb0fa354548))
|
||||
- **Constants:** Better type error in cdn endpoints (#6637) ([124e177](https://github.com/discordjs/discord.js/commit/124e177e91d1cee3566c784ab8efad2a0c6a9519))
|
||||
- ES2021 features (#6540) ([00bd92a](https://github.com/discordjs/discord.js/commit/00bd92a45172852c9dd20550eb916c101668071c))
|
||||
- **Channel:** Make delete async (#6417) ([71fdf6f](https://github.com/discordjs/discord.js/commit/71fdf6fae0457bc5f2900a37cc2d28c587e7e54a))
|
||||
|
||||
## Typings
|
||||
|
||||
- **Interaction:** Allow `Interaction` cached properties to be type narrowed (#6668) ([d873a19](https://github.com/discordjs/discord.js/commit/d873a19d34ed7d98c497d9523b33306d4a078521))
|
||||
- Rename `Awaited<T>` to `Awaitable<T>` (#6756) ([f88f4cc](https://github.com/discordjs/discord.js/commit/f88f4cca641935cfe64caf870ef11034b70bc947))
|
||||
- **GuildBanManager:** Remove can return null (#6748) ([c3f4de4](https://github.com/discordjs/discord.js/commit/c3f4de4801ae1910c20dccf5ce0fc2987a67d41e))
|
||||
- Add ExcludeEnum utility for easier typings (#6746) ([42acc6e](https://github.com/discordjs/discord.js/commit/42acc6eef9c76cdb698208ddacce64eed25f1396))
|
||||
- **Webhook:** More accurate type for `sourceChannel` (#6751) ([32b5c2e](https://github.com/discordjs/discord.js/commit/32b5c2e617ab091adb4697859330a793e8f30598))
|
||||
- **WebhooksUpdate:** Allow `NewsChannel`s (#6749) ([abf158d](https://github.com/discordjs/discord.js/commit/abf158dc94555d34b041865ebcb456449f503038))
|
||||
- More accurate types instead of `GuildChannelResolvable` (#6744) ([a8e6010](https://github.com/discordjs/discord.js/commit/a8e60105fb18b8a3de064898db76560907f12a67))
|
||||
- **ChannelTypes:** Remove unknown from CHANNEL options (#6701) ([8b4456e](https://github.com/discordjs/discord.js/commit/8b4456e0aa215a56d34ca471319f6c768346c5ba))
|
||||
- **TextBasedChannels:** Fix awaitMessageComponent return type (#6723) ([a7cb314](https://github.com/discordjs/discord.js/commit/a7cb314e0709438c8212ff4a8a897bcf0771a067))
|
||||
- **Vanity:** Make `uses` non-nullable (#6715) ([3a978f3](https://github.com/discordjs/discord.js/commit/3a978f347cee027dd50862542c358ab9301b09be))
|
||||
- **Role:** Role#comparePositionTo accepts RoleResolvable (#6722) ([7c4d1df](https://github.com/discordjs/discord.js/commit/7c4d1dffb4e61c573ad1694f9b88ca9cca68522c))
|
||||
- **Presence:** Fix ActivityOptions#type and Activity#id types (#6696) ([fe95005](https://github.com/discordjs/discord.js/commit/fe9500538e76423e49e16a1e1756eb04b5f40531))
|
||||
- Fix missing channel type in subcommand options (#6706) ([da3ae48](https://github.com/discordjs/discord.js/commit/da3ae4854e5448a9726cb027f9d27f85935fb49b))
|
||||
- Add GuildEmojiManager to Caches (#6671) ([1ca8d2c](https://github.com/discordjs/discord.js/commit/1ca8d2c8e8d6f7a6529aaa637e01ac61fed5ce19))
|
||||
- **VoiceState:** Allow moving members to stage channels (#6684) ([94ca0f5](https://github.com/discordjs/discord.js/commit/94ca0f599d01d39f06cb46f1d3fdda21b9109b53))
|
||||
- **Interaction:** Improve type guard for inGuild() (#6644) ([0347826](https://github.com/discordjs/discord.js/commit/034782641a2e558d50a7645081c1c7a4f18bb04a))
|
||||
- **MessageOptions:** Allow APIEmbed (#6656) ([92f6471](https://github.com/discordjs/discord.js/commit/92f6471e8e37e5f852d2c310e7c1b43cd42bc44d))
|
||||
- **WelcomeChannel:** Allow store channels (#6615) ([75d85f7](https://github.com/discordjs/discord.js/commit/75d85f7838eb3fffe9c6a2c02667a14b77940de7))
|
||||
- **MessageEmbed:** Allow APIEmbed type (#6629) ([256fb90](https://github.com/discordjs/discord.js/commit/256fb905feca370ec7e6e25e5467f64db43fae3e))
|
||||
- **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))
|
||||
- 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))
|
||||
- Allow message component interaction collectors to infer collected interaction types (#6476) ([03d5549](https://github.com/discordjs/discord.js/commit/03d5549461ef29a191f9a32d4a2f45ac3c58f0cd))
|
||||
- **CommandInteractionOptionResolver:** Document & type thread channels (#6521) ([774e960](https://github.com/discordjs/discord.js/commit/774e9609d27f8b7c195af34b4b48846ddbafea78))
|
||||
- **MessageComponentInteraction:** Fix componentType (#6536) ([0fe5f88](https://github.com/discordjs/discord.js/commit/0fe5f8831662a8ba074c4d2e4dea851bed755841))
|
||||
- Mark enums as const enums (#6394) ([5c27639](https://github.com/discordjs/discord.js/commit/5c276398d6c6e90a44e7db575264bc9d935b3f9d))
|
||||
- **MessageEmbed:** Allow `null` for `setTimestamp` (#6514) ([7aff15a](https://github.com/discordjs/discord.js/commit/7aff15a05534ce11c76494cc15d63e06fb5a9816))
|
||||
- Require component type in raw object formats (#6452) ([c232baa](https://github.com/discordjs/discord.js/commit/c232baa7154a4f07904ad5b0b8557ebb452bfb66))
|
||||
- **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))
|
||||
|
||||
# [13.1.0](https://github.com/discordjs/discord.js/compare/13.0.1...13.1.0) - (2021-08-12)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **StageInstance:** Ensure `discoverableDisabled` is not `undefined` (#6395) ([dce8fc7](https://github.com/discordjs/discord.js/commit/dce8fc7b9d4603de26b1118058322aaa96ea699a))
|
||||
- **WidgetMember:** Default to `null` and not `undefined` (#6399) ([44bbfa5](https://github.com/discordjs/discord.js/commit/44bbfa5c46a4bb35777aec8681f18590dec9aea4))
|
||||
- **Guild:** `preferredLocale` to always be a string (#6402) ([4a64662](https://github.com/discordjs/discord.js/commit/4a64662a7d5526817ad52fa3d2206dc11f38cb29))
|
||||
- **ContextMenuInteractin:** Store message as raw value (#6400) ([d9456a1](https://github.com/discordjs/discord.js/commit/d9456a1a76e66bc2bfffa4a4b1dd228132056e9f))
|
||||
- **Util:** Remove truthy check before isNaN check (#6358) ([3c17939](https://github.com/discordjs/discord.js/commit/3c17939fd53a1f139d95bd36dfdab85b46538a73))
|
||||
- **Constants:** Fix CDN endpoint typings (#6332) ([47d2ef3](https://github.com/discordjs/discord.js/commit/47d2ef3e40165d846b5a901709b26dfffea46ef2))
|
||||
- **Managers:** Fix typo in unsupported warning (#6338) ([917e71a](https://github.com/discordjs/discord.js/commit/917e71a9ee7d8bd76d8dbea40b40a4fb28276f60))
|
||||
- **GuildMemberRoleManager:** Typo (#6335) ([d87299b](https://github.com/discordjs/discord.js/commit/d87299ba2036ee19da22b5c8abfae3f9d355ea1e))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Remove unparsed examples (#6404) ([e6f48d8](https://github.com/discordjs/discord.js/commit/e6f48d849f0439bdafe5677648f2c9e5c69bda35))
|
||||
- **GuildManager:** Increase fetch limit to 200 (#6406) ([933d2c5](https://github.com/discordjs/discord.js/commit/933d2c5eb77e4e2e15a771a88039555182818965))
|
||||
- **ApplicationCommandData:** Fix type property (#6385) ([de3c86f](https://github.com/discordjs/discord.js/commit/de3c86f804dd1b2a8b1b8fe102ea721cc4e73db5))
|
||||
- Update links for api-docs (#6380) ([779e14e](https://github.com/discordjs/discord.js/commit/779e14ef6172749ee688fc9cef80bd767b7823d7))
|
||||
- Switch urls from upstream rearranging (#6378) ([4c8dc4c](https://github.com/discordjs/discord.js/commit/4c8dc4cda6f598dc26275c9f291222c7c75cfcda))
|
||||
- Correct wrong interaction links (#6274) ([49d3c0b](https://github.com/discordjs/discord.js/commit/49d3c0bf8737fd02623761474f1a32a51861750d))
|
||||
- **Invite:** `MANAGE_CHANNELS` instead of `MANAGE_CHANNEL` (#6361) ([0062aa6](https://github.com/discordjs/discord.js/commit/0062aa6f72f1f6695a6b52a4623fc65aa9a09667))
|
||||
- **Options:** DefaultMakeCacheSettings typo (#6365) ([ea8d77e](https://github.com/discordjs/discord.js/commit/ea8d77ea6236c03747fd30ee8f9357acf257f817))
|
||||
- Grammar fixes (#6345) ([f13d27c](https://github.com/discordjs/discord.js/commit/f13d27ca2e6873f1cc18feb6bb9102ca80ce04cf))
|
||||
|
||||
## Features
|
||||
|
||||
- **GuildMemberManager:** Add 'list' method (#6403) ([2bf0970](https://github.com/discordjs/discord.js/commit/2bf09703c13afe7481071ae1b064dbc3513468e1))
|
||||
- **GuildManager:** Allow setting with_counts to false (#6407) ([14aea12](https://github.com/discordjs/discord.js/commit/14aea1290061c225feb9d9f5378508d937e34a69))
|
||||
- **CommandInteractionResolvedData:** Access to "raw" resolved data (#6384) ([fff887b](https://github.com/discordjs/discord.js/commit/fff887b2f43d19164dbf2878b00abead90a0703f))
|
||||
- **Utils:** Add additional formatters (#6388) ([cd40292](https://github.com/discordjs/discord.js/commit/cd4029218fc8b67c395b3cd49a121b1bfa38f021))
|
||||
- Right-clickybois (context menu support for ApplicationCommand and CommandInteraction) (#6176) ([0266f28](https://github.com/discordjs/discord.js/commit/0266f280960729b27bf65ba0ee7b7bd8659f304d))
|
||||
- **Threads:** Max autoArchiveDuration option (#6304) ([394d486](https://github.com/discordjs/discord.js/commit/394d48649fe4faef8c6b30d5c04962588f86261e))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **Options:** Separate default settings for make cache (#6330) ([d14a6bf](https://github.com/discordjs/discord.js/commit/d14a6bfe1d00511e43d0eba4fe225f829d3e0057))
|
||||
|
||||
## Typings
|
||||
|
||||
- **ApplicationCommandData:** Make `type` field optional (#6405) ([dcc556c](https://github.com/discordjs/discord.js/commit/dcc556c311871ef72fed506a3917d9cf39186250))
|
||||
- **Constants:** Add `ApplicationCommandTypes` to `Constants` (#6398) ([6342430](https://github.com/discordjs/discord.js/commit/63424300731334cdbfb6230e7356491277c86b03))
|
||||
- **ApplicationCommandOptionData:** Align command data options types more with discord API (#6247) ([297a911](https://github.com/discordjs/discord.js/commit/297a9118e7fbbc477eb514c857224da178cceea9))
|
||||
- **ApplicationCommandData:** Stronger typings for `ApplicationCommandData` variants. (#6382) ([75b48d8](https://github.com/discordjs/discord.js/commit/75b48d8d0f70338c75721df3dbd8fc37866383bc))
|
||||
- **Options:** CreateDefaultOptions => createDefault (#6376) ([2a3e819](https://github.com/discordjs/discord.js/commit/2a3e819fcfb364725ebd2daa051c0544adf40b0d))
|
||||
- **Events:** Renamed `messageReactionAdd`'s reaction parameter (#6371) ([006edca](https://github.com/discordjs/discord.js/commit/006edca410f5df53f3272f7a402f2305f73ad14b))
|
||||
- **ImageURLOptions:** Allow 'gif' format (#6342) ([5f1def3](https://github.com/discordjs/discord.js/commit/5f1def37930605bea47e2cc50eff3d134b9c0c66))
|
||||
|
||||
# [13.0.1](https://github.com/discordjs/discord.js/compare/13.0.0...13.0.1) - (2021-08-07)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **GuildMemberManager:** Refactor fetchMany (#6328) ([909c873](https://github.com/discordjs/discord.js/commit/909c87353e24eb7947d1cabc78d9c0ee97c3902d))
|
||||
- **Message:** Handle fetched messages (#6325) ([ceae596](https://github.com/discordjs/discord.js/commit/ceae5960edefc63be5f16a52e286e390c14e0d29))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Fix bad indentation (#6316) ([cd1aefb](https://github.com/discordjs/discord.js/commit/cd1aefb46c6a6bcb4b943262c16dc4ad62430978))
|
||||
|
||||
## Typings
|
||||
|
||||
- **Util:** Fix cleanContent parameter type (#6321) ([60ace9a](https://github.com/discordjs/discord.js/commit/60ace9a2d4cd2844a862f03f33d3be81b56f352b))
|
||||
|
||||
# [13.0.0] - (2021-08-06)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **MessageMentions:** Check guild exists before adding roles (#6313) ([1200bba](https://github.com/discordjs/discord.js/commit/1200bba7bcc48dab6a454925e533528a7e3c0cf7))
|
||||
- **GuildMemberManager:** FetchMany fixes (#6314) ([52817fc](https://github.com/discordjs/discord.js/commit/52817fc414eef5220043e055a740e4ad0f8287a0))
|
||||
- **Caching:** Sweep archived threads in all channel caches (#6312) ([3725dca](https://github.com/discordjs/discord.js/commit/3725dcafc0cbb4a40d3ff66d2a9718e986f47c5b))
|
||||
- **Message:** Fix thread getter (#6309) ([913c9fa](https://github.com/discordjs/discord.js/commit/913c9fa17672fa914776beb556edcee5cd2d2dc8))
|
||||
- **BaseGuildTextChannel:** Call patch (#6298) ([3eb4140](https://github.com/discordjs/discord.js/commit/3eb41405f412ee2b2d05c4245c4ebb80adfcec6b))
|
||||
- Remove support for overriding caches that break functionality (#6282) ([a6d4035](https://github.com/discordjs/discord.js/commit/a6d4035176ca784e75bd1cbdf30e039658c62fd4))
|
||||
- **Message:** Make #channel and #guild getters (#6271) ([6e3236a](https://github.com/discordjs/discord.js/commit/6e3236ab64549d27445c631cbb3d88c2bb9bf289))
|
||||
- **WebSocketShard:** Mark shard ready if no guilds intent (#6284) ([09471be](https://github.com/discordjs/discord.js/commit/09471be30eea2540999c3d5a2b001a985a0d27cc))
|
||||
- **Action:** GetChannel interaction DM (#6280) ([a72b5a3](https://github.com/discordjs/discord.js/commit/a72b5a355e443f17edf1b348f63d314c743093b9))
|
||||
- **GuildChannel:** SetParent not working (#6276) ([7e0618f](https://github.com/discordjs/discord.js/commit/7e0618f17a786708093bc532501b261191e85561))
|
||||
- **ChannelUpdate:** Restore accidentally removed line (#6263) ([774f5b7](https://github.com/discordjs/discord.js/commit/774f5b77ec6218c30360c773b5fe6185d1efd146))
|
||||
- **Util:** Fix collection import (#6256) ([93e0239](https://github.com/discordjs/discord.js/commit/93e0239c8054293eac63338819a10490dbd49ff1))
|
||||
- Array/keyArray removed (#6245) ([bf221f2](https://github.com/discordjs/discord.js/commit/bf221f2bef2871f019aa4a6978deb8460fff85b9))
|
||||
- **TextBasedChannel:** Fix MessageCreate handling (#6217) ([6b85f90](https://github.com/discordjs/discord.js/commit/6b85f900fa8e6cc01f7ee14ae730950cf1635dd5))
|
||||
- **PermissionOverwrites:** Throw better error if resolving option fails (#6219) ([42a0313](https://github.com/discordjs/discord.js/commit/42a03130345d3a3841f5271d82a2cb8725b6fa0e))
|
||||
- **Channel:** Add default for destructured options (#6203) ([6872547](https://github.com/discordjs/discord.js/commit/68725476b39d5ef5793ccf62cfb468073e7d9cb2))
|
||||
- Use `string` instead of `Snowflake` for invites (#6202) ([f060a3f](https://github.com/discordjs/discord.js/commit/f060a3fcd7e1ad30789d582e8baf28dbdddf8063))
|
||||
- **ThreadChannel:** Better property handling (#6172) ([9679b90](https://github.com/discordjs/discord.js/commit/9679b9087200e29d2f488d84d115465449021b51))
|
||||
- Export various classes that are exported in the typings (#6166) ([30a58dc](https://github.com/discordjs/discord.js/commit/30a58dc80130d334bf8c85e7b37513c109beda1b))
|
||||
- **Typings:** Type attachments to InteractionUpdateOptions (#6162) ([4f8ca29](https://github.com/discordjs/discord.js/commit/4f8ca2936a85109757fb3225e9d6cf9aae9714e2))
|
||||
- **GuildAuditLog:** Assert `target` to null upon not finding invite codes (#6171) ([c8ca7bf](https://github.com/discordjs/discord.js/commit/c8ca7bfd2c5e7b29e54987a78301e9bdfa4a717b))
|
||||
- **Message:** Fix typo in sticker_items (#6173) ([870a0de](https://github.com/discordjs/discord.js/commit/870a0de53c01331c9357df4808fc0979ff17b9a4))
|
||||
- **Sticker:** Replace 'this.guildID' (undefined) by 'this.guildId' in fetchUser (#6160) ([07017a9](https://github.com/discordjs/discord.js/commit/07017a9699eecc4af7824ace39dd91e8b689f3c6))
|
||||
- **CommandInteractionOptionResolver:** Type should be USER (#6148) ([02f55f0](https://github.com/discordjs/discord.js/commit/02f55f09712af5d6a6f67b5ac369b1969801e23f))
|
||||
- **CommandInteractionOptionResolver:** Export CommandInteractionOptio… (#6146) ([8ccfd6e](https://github.com/discordjs/discord.js/commit/8ccfd6e07b3208568c495110c80990366637818e))
|
||||
- **CommandInteraction:** Change options type from Collection to array (#6139) ([77784ac](https://github.com/discordjs/discord.js/commit/77784aca431709ff3c17095bd06f9e4016fbd11d))
|
||||
- **GuildChannel:** Only fetch invites for the specific channel (#6132) ([c40c0f9](https://github.com/discordjs/discord.js/commit/c40c0f934a571c100e4b3aa633a80fe48661d836))
|
||||
- **PermissionsOverwrites:** Only convert type if number (#6092) ([dee5c83](https://github.com/discordjs/discord.js/commit/dee5c83fc0d1147d5b65151a8f91a4a089687a73))
|
||||
- Channel type check in actions (#6086) ([d433fe8](https://github.com/discordjs/discord.js/commit/d433fe8a0827e6275e2a7ceed537be38411f4f67))
|
||||
- **GuildChannel:** Clone its PermissionOverwriteManager too (#6083) ([f72ce7c](https://github.com/discordjs/discord.js/commit/f72ce7c136cf2dfe31a67b190c00e30ba7d70bfa))
|
||||
- **PresenceUpdate:** Use added presence over nullable getter (#6077) ([637c8e0](https://github.com/discordjs/discord.js/commit/637c8e0fdfb4ce15361646017718c72c3d6af538))
|
||||
- **InviteScope:** Added missing 'bot' scope (#6052) ([93e2c04](https://github.com/discordjs/discord.js/commit/93e2c04ec27c44a8c955e576944023dc25075647))
|
||||
- **SelectMenuInteraction:** Set values to empty array if not provided (#6045) ([34708d6](https://github.com/discordjs/discord.js/commit/34708d6d18f94b5c8d9c582973d057e1f89bfe1f))
|
||||
- **Guild:** Add invite manager property, extend CachedManager (#6049) ([e3d877d](https://github.com/discordjs/discord.js/commit/e3d877d542518d0f82c476d921968338a859722b))
|
||||
- **TeamMember:** Fixed incorrect return types. (#6044) ([fe5d56c](https://github.com/discordjs/discord.js/commit/fe5d56c9b11b3e5f05933c6d746237b9f353b392))
|
||||
- **Structures:** Remove Structures (#6027) ([ab0b3b9](https://github.com/discordjs/discord.js/commit/ab0b3b9a07f5e4987e4f25e41b2a007f2db06322))
|
||||
- **GuildChannel:** Use map method on cache not its manager (#6032) ([d58f0d2](https://github.com/discordjs/discord.js/commit/d58f0d243c9bbd803cff7b8da2056c11e0416bef))
|
||||
- **PermissionOverwriteManager:** Pass ID to API correctly (#6026) ([8077e4f](https://github.com/discordjs/discord.js/commit/8077e4f4f132f95c4fa21e9fc7313b93a2c4b9d7))
|
||||
- **GuildChannel:** Add missing 'cache' property (#6019) ([7e30011](https://github.com/discordjs/discord.js/commit/7e3001191c1529b9db09b6168ddd0c09931598f5))
|
||||
- Remove `connection.url` from open debug message (#6018) ([39db953](https://github.com/discordjs/discord.js/commit/39db95352c91faf175c2fd8ed365f293f965a0e4))
|
||||
- **Util:** SplitMessage not working with array (#6008) ([bd25ff5](https://github.com/discordjs/discord.js/commit/bd25ff59133ba31713647d3e6a5ef66abc4d54fb))
|
||||
- Correct permissions checks and cache on update (#6015) ([568691c](https://github.com/discordjs/discord.js/commit/568691ce6a7994adc85db2b2a5b2227ece8c8358))
|
||||
- **ThreadManager:** Fixed wrong private and fetchAll check (#6012) ([e4be666](https://github.com/discordjs/discord.js/commit/e4be666c2c273c56f04b8f965efc88bb9aff0032))
|
||||
- **Typings:** Improve components typings in MessageEditOptions (#6002) ([3a718d8](https://github.com/discordjs/discord.js/commit/3a718d8c625ab45bc9f4dfcd9d6bbdef67ae75b4))
|
||||
- **ApplicationCommand:** Fix typo in JSDoc (#5994) ([6edf55c](https://github.com/discordjs/discord.js/commit/6edf55c04b970235fdc92c00808ee86002e589b6))
|
||||
- **ThreadChannel:** Check for existence of properties when patching (#5961) ([9ac6867](https://github.com/discordjs/discord.js/commit/9ac68670d782fc81e266784e790af699f280eb0e))
|
||||
- **Typings:** Erronous RawMessage ([5842e35](https://github.com/discordjs/discord.js/commit/5842e35881755350764b557d66b475c2c03f249a))
|
||||
- **Thread:** Make archive_timestamp not nullable (#5965) ([edab5af](https://github.com/discordjs/discord.js/commit/edab5afff9a4c79e5965c7c52b0a0d5ebb9ba35a))
|
||||
- **Sharding:** Strict type context and return (#5933) ([1925d01](https://github.com/discordjs/discord.js/commit/1925d01d8f05ca10b2a39b91f25ffcabe363874b))
|
||||
- **Webhook:** Return void from #delete for consistency. (#5954) ([5ad83a6](https://github.com/discordjs/discord.js/commit/5ad83a6a65e5944ceb3a41fee2df40ba1f5b03e4))
|
||||
- **Collector:** Docs and types (#5937) ([6c447b1](https://github.com/discordjs/discord.js/commit/6c447b12e3f978328cb2577ea3f81a5ab1531bbf))
|
||||
- **Message:** Make author of referenced message nullable (#5929) ([dc671c8](https://github.com/discordjs/discord.js/commit/dc671c8ac418c1f932034e82f38def28575a4b65))
|
||||
- **User:** Fix bot and system properties being incorrect in some cases (#5923) ([e44ae96](https://github.com/discordjs/discord.js/commit/e44ae961005358dac7032c75bfc74be3b719e5a1))
|
||||
- **ThreadMemberManager:** Fix ThreadMemberManager#add and ThreadMemberManager#fetch (#5927) ([adecead](https://github.com/discordjs/discord.js/commit/adecead716670278516fd031f240e05792420c75))
|
||||
- **Webhook:** Resolve non-string avatars too (#5914) ([4714a96](https://github.com/discordjs/discord.js/commit/4714a961b87746b0f85214c756614d276666f285))
|
||||
- **ApplicationCommand:** StringType isn't supposed to be sent to the API (#5916) ([ca2a36b](https://github.com/discordjs/discord.js/commit/ca2a36b1d713a743045b15adf99eda69a6fdbec7))
|
||||
- **Permissions:** Allow admin to override in the missing method (#5911) ([ee025b0](https://github.com/discordjs/discord.js/commit/ee025b05588493b55057b237ca96f88ecc5f0b02))
|
||||
- **InteractionResponses:** Set replied status on editReply (#5899) ([6d3d00b](https://github.com/discordjs/discord.js/commit/6d3d00b44577a70e840f0187d6894043677c5329))
|
||||
- **Message:** Flags not being parsed on some edits (#5886) ([2d7c12b](https://github.com/discordjs/discord.js/commit/2d7c12b0e9387f56f1809822bc2c8c4ee52a00e9))
|
||||
- **Guild:** Don't patch before instance properties (#5885) ([174b7a7](https://github.com/discordjs/discord.js/commit/174b7a7f9c5f95ab182a2c90dae43ccd4f55357b))
|
||||
- **presenceUpdate:** Fire when only state/details change on an activity (#5846) ([1f8f3ab](https://github.com/discordjs/discord.js/commit/1f8f3ab0f8dbd346154bbfa14a98726b8df25d57))
|
||||
- **Message:** EditedTimestamp defaulting to 0 (#5847) ([671436c](https://github.com/discordjs/discord.js/commit/671436cbb89f7f48bd9ae0ccb9dd75a376cc5281))
|
||||
- **ApplicationCommand:** Default option.required fix (#5848) ([a1f94f6](https://github.com/discordjs/discord.js/commit/a1f94f670e5b6009b9c33932ce06ed512447b953))
|
||||
- **Guild:** SetChannelPositions null parenting (#5841) ([01a1fd6](https://github.com/discordjs/discord.js/commit/01a1fd615bbf017e18bbffe8e97336345f42564a))
|
||||
- **ApplicationCommand:** Default option.required to false (#5838) ([77c1f15](https://github.com/discordjs/discord.js/commit/77c1f15c9f7562465c07727602c3213ddcf02778))
|
||||
- **GuildManager:** #create throws when systemChannelFlags is undefined (#5832) ([29173bf](https://github.com/discordjs/discord.js/commit/29173bf814e2cd795467b9b3814f0eaf0773e9ae))
|
||||
- **GuildChannel:** Don't force parentID/permissionOverwrites to empty on create (#5823) ([c585933](https://github.com/discordjs/discord.js/commit/c5859337b616c1fe2a60884595d27db4f13d8fee))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Hooks:** Make husky hooks executable (#5812) ([77e28cf](https://github.com/discordjs/discord.js/commit/77e28cf65b0fb3fc2fb7ab07fc7bb0f2f5a400b5))
|
||||
- **GuildChannel:** Clone errors when options.name isn't provided (#5804) ([41673b7](https://github.com/discordjs/discord.js/commit/41673b738232f64da2ded3b15be0f798135ae351))
|
||||
- **WebSocketShard:** Don't catch errors thrown in event handlers (#5803) ([53d8e49](https://github.com/discordjs/discord.js/commit/53d8e49dca2d83fe2e066fb0b3d10418acbbc244))
|
||||
- Don't patch missing properties from partial payloads (#5796) ([097c7b9](https://github.com/discordjs/discord.js/commit/097c7b9cdd5e1bb52b037272eed19f556800ccff))
|
||||
- **GuildChannel:** Spread clone options to avoid infinite recursion (#5800) ([2f5424b](https://github.com/discordjs/discord.js/commit/2f5424bdac7c97d0a371dd72084ac02d5e774f1a))
|
||||
- **Webhook:** Throw an error if no token is available when it's required (#5798) ([eb98e33](https://github.com/discordjs/discord.js/commit/eb98e33a85cc9bb235ceb509ed01218bae44ba73))
|
||||
- **ClientPresence:** Produce valid activities for set presences (#5799) ([ea0e06f](https://github.com/discordjs/discord.js/commit/ea0e06f9802fb57b41f471413b39ccd09546bb67))
|
||||
- **BitField:** Ensure missing returns an array of strings (#5795) ([68f7aeb](https://github.com/discordjs/discord.js/commit/68f7aebcafcfd62bef02de855ca0c304a54e8d4c))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Webhook:** #editMessage throws error when content is null (#5757) ([2901fd5](https://github.com/discordjs/discord.js/commit/2901fd595be847a0e6c86155b3229d3341cfad32))
|
||||
- **MessageComponentInteraction:** Correctly type defer method (#5760) ([f0dad26](https://github.com/discordjs/discord.js/commit/f0dad26a5b8c3139b2519d1895df2fe23352b102))
|
||||
- **RoleManager:** Bug in #create (#5730) ([cf22456](https://github.com/discordjs/discord.js/commit/cf224560bc59c05f7801088b0db2ec76c5369302))
|
||||
- **Message:** Update typings and docs related to #edit (#5745) ([a2f0c11](https://github.com/discordjs/discord.js/commit/a2f0c11474826bfd5b770d2a6990b6bd41c89451))
|
||||
- **Typings:** Add missing typings for `HttpError` -> `requestData` (#5742) ([3e9ce35](https://github.com/discordjs/discord.js/commit/3e9ce35023e71ffda1f4eaca6f109b0422ec7d29))
|
||||
- **MessageEmbed:** Import custom RangeError class (#5740) ([bfe01b5](https://github.com/discordjs/discord.js/commit/bfe01b52ab29df1bb26fc2d385f63fb5adbb12b2))
|
||||
- **CommandInteraction:** Cmds with no options throw error (#5734) ([af2fad9](https://github.com/discordjs/discord.js/commit/af2fad94732eeb620fe17d9b537c279471c567c0))
|
||||
- **CommandInteraction:** Channel type should be text based channels (#5690) ([5141ea4](https://github.com/discordjs/discord.js/commit/5141ea4f0694a60375d8bc0801b1225928bb3bd1))
|
||||
- **GuildMemberManager:** Allow moving members to any non-text channel (#5681) ([d21e6af](https://github.com/discordjs/discord.js/commit/d21e6af1d2b81db9847336b3f964f9d2693394e6))
|
||||
- Interfaces not importing due to re-export of Snowflake (#5723) ([086c3f0](https://github.com/discordjs/discord.js/commit/086c3f0799d65c64c4e60d6370246a37a27a1eab))
|
||||
- **PermissionOverwrites:** Fix typo in typedef jsdoc (#5704) ([6567ba8](https://github.com/discordjs/discord.js/commit/6567ba821a54d3dc97d07ce8ac55335fef2f346b))
|
||||
- **Types:** Make event listeners accept async callbacks (#5602) ([a73a5cf](https://github.com/discordjs/discord.js/commit/a73a5cf91498cf7b08cea85753ad481c194ec089))
|
||||
- **GuildEmojiRoleManager:** Bug in #remove (#5666) ([c89bdd7](https://github.com/discordjs/discord.js/commit/c89bdd7566599a95a404b0f9e4b0828a866d0a71))
|
||||
- **ApplicationCommandOptionData:** Options property should be itself (#5679) ([b90b0c3](https://github.com/discordjs/discord.js/commit/b90b0c3cfa2278caa38d1ff41eef2ccf4428b99e))
|
||||
- **APIMessage:** Document Interaction as valid MessageTarget (#5678) ([9f491ff](https://github.com/discordjs/discord.js/commit/9f491ffeb96ff380f2ab5ab2f86201d58be64c41))
|
||||
- **Message:** Bug in #suppressEmbeds due to #5612 (#5644) ([840ad0a](https://github.com/discordjs/discord.js/commit/840ad0a35a344a19c5bb84c421f80802fb186d0b))
|
||||
- Lint-staged for typescript files ([5f6ec22](https://github.com/discordjs/discord.js/commit/5f6ec2211d1e6555ab2d501579e4a1d97023c647))
|
||||
- **DataResolver:** Fix circular dependency error with GuildTemplate (#5622) ([b376f31](https://github.com/discordjs/discord.js/commit/b376f31af9881b9cd3f82ac4a42a468947cce482))
|
||||
- **ApplicationCommandManager:** Limit permission methods to guilds (#5613) ([03256bd](https://github.com/discordjs/discord.js/commit/03256bd9f88c63dc5c2169e2c09ac8078ea84992))
|
||||
- **CommandInteraction:** Update typings and docs for #editReply (#5630) ([56d44fb](https://github.com/discordjs/discord.js/commit/56d44fbf1c922260c497350e8829d7151eb7a331))
|
||||
- **ApplicationCommand:** Return string equivalent of ApplicationCommandOptionType (#5617) ([a6079bc](https://github.com/discordjs/discord.js/commit/a6079bc9ce40ecbb4adace033dbf201897b5459f))
|
||||
- Resolve emoji in Message#react (#5614) ([c733436](https://github.com/discordjs/discord.js/commit/c7334363b36c5f7f1c7880fe77a2e9b2eb1a6442))
|
||||
- Typo in GuildMemberManager (#5616) ([73f4114](https://github.com/discordjs/discord.js/commit/73f4114f59fc2f514d570ac8df3eac7d328cca3c))
|
||||
- **Message:** Editing with MessageEmbed or APIMessage (#5612) ([74e97ef](https://github.com/discordjs/discord.js/commit/74e97ef91b413300c83f163bc3914eaf8bd45d89))
|
||||
- **VoiceReceiver:** Fix memory leak (#5609) ([2eac842](https://github.com/discordjs/discord.js/commit/2eac84296b448907213680690ec766bb5fbe5990))
|
||||
- **ApplicationCommandManager:** Fix typo in JSDoc (#5603) ([3392eb7](https://github.com/discordjs/discord.js/commit/3392eb7de270842dbf5a54d19aa3e703dd445ba0))
|
||||
- **Sticker:** File renamed to SnowflakeUtil (#5573) ([f830eb7](https://github.com/discordjs/discord.js/commit/f830eb7101d05f90bbbf44ff750e4012ecb72449))
|
||||
- **Emoji:** Name can be null (#5513) ([5397021](https://github.com/discordjs/discord.js/commit/5397021efb1f9883cf4b48a0ca78d12b713a61fd))
|
||||
- **GuildMemberRoleManager:** Unable to remove roles when passed an array (#5556) ([9572521](https://github.com/discordjs/discord.js/commit/9572521e3c390e610de8e4dc79e4086b3b1d6e44))
|
||||
- Typings for 'Message' (#5518) ([0d68ca8](https://github.com/discordjs/discord.js/commit/0d68ca8eb9abdb517acee562fe01374416d225ed))
|
||||
- **HTTPOptions:** Change default value in jsdoc to 8 (#5547) ([cb50241](https://github.com/discordjs/discord.js/commit/cb50241e6fa7c95891925c8b18840c17df078620))
|
||||
- **GuildAuditLogsEntry:** Executor can be missing (#5500) ([e9bf206](https://github.com/discordjs/discord.js/commit/e9bf206d88b9307e4098b7f89178105d08b07544))
|
||||
- **typings:** Update GuildMemberRoleManager typings to match implementation (#5497) ([900e576](https://github.com/discordjs/discord.js/commit/900e57657e80833df2557c60862fcd71b35d0df1))
|
||||
- **MessageMentions#channels:** Fix type of channels of mentions (#5370) ([565d7b3](https://github.com/discordjs/discord.js/commit/565d7b3747d59ceeb01e2d88b20d761a99927a12))
|
||||
- **Resolvables:** Valid resolvables throw error when uncached (#5495) ([fa5a37e](https://github.com/discordjs/discord.js/commit/fa5a37e51a14fdd95420092fb8c2acffad132c3b))
|
||||
- **GuildChannel:** Check for community required channels in GuildChannel#deletable (#5170) ([b710a43](https://github.com/discordjs/discord.js/commit/b710a432326be823beb10f5f06f2a1e3fcd7c0ee))
|
||||
- **GuildMember:** Correctly check for premium_since (#5312) ([aff3625](https://github.com/discordjs/discord.js/commit/aff3625d4fc3c738d77325f8492b72077e6345e7))
|
||||
- **Voice:** Only skip undocumented voice packet byte if present (#5309) ([2b52cdc](https://github.com/discordjs/discord.js/commit/2b52cdc915146c6775bc7565e5ecf31e7c9880e7))
|
||||
- Typings for 'WebhookMessageOptions' (#5476) ([67025e6](https://github.com/discordjs/discord.js/commit/67025e63e4e8306a2b3ff62ae1067acf4b468a6a))
|
||||
- **IntegrationApplication:** Add missing export to index.js (#5475) ([8023250](https://github.com/discordjs/discord.js/commit/8023250ee7bb79a5e3f12d7297c29589f91d6b81))
|
||||
- **ApplicationFlags:** Export class (#5465) ([404ce57](https://github.com/discordjs/discord.js/commit/404ce57bcc3ce39c807457f25a5679a80e69d1bb))
|
||||
- **Voice:** Disconnect if voice channel not cached (#5467) ([3af8179](https://github.com/discordjs/discord.js/commit/3af8179878c093985c8a94ee2fd7e99d45243bda))
|
||||
- **InviteDelete:** Guild can be missing (#5457) ([6c6b105](https://github.com/discordjs/discord.js/commit/6c6b1053b7a6778a5d0402941a13258ca13378f8))
|
||||
- **ReactionUserManager:** Remove before query option (#5281) ([43bd568](https://github.com/discordjs/discord.js/commit/43bd568f1c38a6df38f56a8d607375ccc9da026a))
|
||||
- **GuildManager:** Add missing toString() on Permission#resolve fns (#5324) ([0778926](https://github.com/discordjs/discord.js/commit/077892645bd59d1b5c50e3291701cb4241c0bbdf))
|
||||
- **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))
|
||||
- **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))
|
||||
- **VoiceConnection:** Make #dispatcher nullable (#5217) ([0d5de43](https://github.com/discordjs/discord.js/commit/0d5de4333d8afa57826aa75475fc4e3dfe8978c4))
|
||||
- **Message:** Update getters to take null permissions into account (#5066) ([98b1c58](https://github.com/discordjs/discord.js/commit/98b1c582189faee9ac40d81963008d94801f3837))
|
||||
- **typings:** Return types for 'Webhook(Client)#send()' (#4876) ([eb28ee7](https://github.com/discordjs/discord.js/commit/eb28ee7905eee248b9ccd248f7d8275933dd0637))
|
||||
- **MessageEmbed:** Include `author.name` in length getter (#5167) ([e37160f](https://github.com/discordjs/discord.js/commit/e37160f4e3d647e8e33b5b03d5f9e6c98b065499))
|
||||
- **Collection:** ToJSON() errors if the collection includes empty values (#5129) ([2c2249e](https://github.com/discordjs/discord.js/commit/2c2249ee7314401b65be677c233370657e1d4695))
|
||||
- Implement valueOf on pseudomanagers (#4595) ([8883a01](https://github.com/discordjs/discord.js/commit/8883a0144b02e76c767c21ecf28fb430b7223c7f))
|
||||
- Add presence to ClientPresence from ClientOptions (#5041) ([9c7fe34](https://github.com/discordjs/discord.js/commit/9c7fe34c50808ba080527a1919b1846ed6585d4d))
|
||||
- Filtering of string forms of null and undefined (#5075) ([9042d19](https://github.com/discordjs/discord.js/commit/9042d19c4ef54d9976776f41336610ab0a24db27))
|
||||
- **ChannelManager:** Avoid crash in remove method with uncached channel (#4937) ([12c909e](https://github.com/discordjs/discord.js/commit/12c909eeccb9ed6ab205d314ac8d63fc58713ae6))
|
||||
- **Message:** #system non-zero message types are not guaranteed to be system (#5108) ([bb78120](https://github.com/discordjs/discord.js/commit/bb78120283b671d1926c8707a17a9d4d515aafdd))
|
||||
- **UserFlags:** Correct early bot dev name, remove deprecated aliases (#5104) ([b509862](https://github.com/discordjs/discord.js/commit/b509862bfa924494824af5e7729bd545315d2c67))
|
||||
- **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))
|
||||
- **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))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Grammatical fix (#6311) ([7787a76](https://github.com/discordjs/discord.js/commit/7787a7695a3733f28b629e6a8892566cce66e6ed))
|
||||
- Grammar fixes (#6308) ([0664477](https://github.com/discordjs/discord.js/commit/06644770c8254b105d9ac1b978797d2a93cbdb83))
|
||||
- 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))
|
||||
- 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))
|
||||
- **InteractionResponses:** Correct `@returns` on responses (#6257) ([bb56f17](https://github.com/discordjs/discord.js/commit/bb56f1776039cf4ac4d3f0e137af50ab1892853e))
|
||||
- Refactor a few `@returns` descriptions (#6228) ([82daee5](https://github.com/discordjs/discord.js/commit/82daee576a05d5ae41364bc7e528816bbf4be808))
|
||||
- **Widget:** Add the typedef WidgetChannel (#6182) ([8b52d06](https://github.com/discordjs/discord.js/commit/8b52d06ca9a2a0ea0c7de33b2e5a95223a8b4feb))
|
||||
- Update readme node version requirement (#6241) ([797727a](https://github.com/discordjs/discord.js/commit/797727ab6e5fc9e4e8aa6b0befd1a2e5ffa66f6a))
|
||||
- **GuildManager:** Correct `GuildCreateOptions` typo (#6224) ([2675b08](https://github.com/discordjs/discord.js/commit/2675b0866c70f4050ef5f60b5652ea2f108f29bd))
|
||||
- **Constants:** Document the Constants object for enum-like usage (#6208) ([cc5f1ce](https://github.com/discordjs/discord.js/commit/cc5f1ce75e48ee791d0d11262285e46e695fa19e))
|
||||
- **Guild:** Correct `GuildRolePosition` typo (#6223) ([40b127e](https://github.com/discordjs/discord.js/commit/40b127ee1eef80e52a12d5cd5f390db259000824))
|
||||
- **WelcomeChannel:** Correct guild return type (#6222) ([d310e4f](https://github.com/discordjs/discord.js/commit/d310e4fc2824aa4c4dcaaa8b93b6b45e6a8fa699))
|
||||
- **Constants:** Fix StickerTypes typedef (#6218) ([105a194](https://github.com/discordjs/discord.js/commit/105a1945468b2610cd44c3a451a798fdd6aea1b7))
|
||||
- **MessageMentions:** Fix documentation for members property (#6206) ([f44bfc4](https://github.com/discordjs/discord.js/commit/f44bfc47c7a56afd75b273659df77fad3e3e5059))
|
||||
- **Guild:** Add GuildTextChannelResolvable type definition (#6221) ([1009ce1](https://github.com/discordjs/discord.js/commit/1009ce169b33424b379d734d1ac5c80e7d2b257c))
|
||||
- **InteractionResponses:** Document missing properties (#6178) ([5e433b5](https://github.com/discordjs/discord.js/commit/5e433b599522265f7257bdd6b58f69dd23311b79))
|
||||
- **CommandInteraction:** Correct type definition of `CommandInteractionOption` (#6169) ([5e70694](https://github.com/discordjs/discord.js/commit/5e706941fcf2977ac73ed42d3207abe2364f64b1))
|
||||
- **InteractionResponses:** Reply docs example (#6079) ([b170fb5](https://github.com/discordjs/discord.js/commit/b170fb5ce8a487c385b75b92082dff25207832bc))
|
||||
- **InteractionResponses:** Generalize wording in update to fit other component interaction types (#6074) ([67e9ce4](https://github.com/discordjs/discord.js/commit/67e9ce46933c6471fad60d38255f19ce4318c7d2))
|
||||
- **ClientUser:** Fix shardId nullable (#6072) ([28b5ffb](https://github.com/discordjs/discord.js/commit/28b5ffb4d67d9b8bae25fc8adfcea7c186ad7e76))
|
||||
- Fixed several typings and MessagePayload#create JSDoc (#6059) ([4c0426c](https://github.com/discordjs/discord.js/commit/4c0426c469304d7ce8886ee9397153468fcf6274))
|
||||
- **ThreadChannel:** Fix documentation for setLocked method (#6053) ([8d9ab74](https://github.com/discordjs/discord.js/commit/8d9ab741c8037c2f6ca708e1afdc047ae4eb9eba))
|
||||
- **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))
|
||||
- **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))
|
||||
- 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))
|
||||
- **MessageSelectMenu:** Add link to Discord docs (#5984) ([f819416](https://github.com/discordjs/discord.js/commit/f819416bac4b84c87271a7ca2126b16c887f7410))
|
||||
- **ThreadManager:** Fix FetchedThreads typedef and startMessage (#5971) ([f108746](https://github.com/discordjs/discord.js/commit/f108746c15bf4db9a887efe373ebd4906fba0889))
|
||||
- **Message:** Add ThreadChannel as a channel type (#5972) ([58bc145](https://github.com/discordjs/discord.js/commit/58bc1458d04284390d39bbf32ad5817ed7281bb7))
|
||||
- **ThreadManager:** Fix reason prop of ThreadCreateOptions (#5970) ([5dfd7dd](https://github.com/discordjs/discord.js/commit/5dfd7dd1bf367013ab12e3f56b502ae832d30a97))
|
||||
- **Channel:** Fix description of thread channel types (#5968) ([853be62](https://github.com/discordjs/discord.js/commit/853be621ac5c9a0f4d85a4bcb990b05853f8b6d6))
|
||||
- Drop string from MessageButtonStyleResolvable (#5944) ([41f718f](https://github.com/discordjs/discord.js/commit/41f718f77957e146074d36bab8b7c2eef6702db6))
|
||||
- **Features:** Resolved typo in `FATEWAY_PRESENCE_LIMITED` (#5952) ([d38b347](https://github.com/discordjs/discord.js/commit/d38b34756bbab4fdce9649c7514faa6cad080e06))
|
||||
- **Webhook:** Fix thread example in send method (#5953) ([d3d19ce](https://github.com/discordjs/discord.js/commit/d3d19ce49ba809d6d6e3ce9c9cc8188a58aeb0b7))
|
||||
- **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))
|
||||
- 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))
|
||||
- **VoiceState:** Channel can be null (#5872) ([807ea2d](https://github.com/discordjs/discord.js/commit/807ea2d3c197c7c6556bd1c894114932f6657d49))
|
||||
- **ReplyMessageOptions,MessageEditOptions:** Replaced `embed` with `embeds` (#5860) ([e3ed74a](https://github.com/discordjs/discord.js/commit/e3ed74a5e875ecd841dc1f6f1b1e78741864f980))
|
||||
- Consistent application name usage (#5853) ([96a4e7b](https://github.com/discordjs/discord.js/commit/96a4e7b86e736ddfdbcb5935f3ad02e658f221ae))
|
||||
- **TextBasedChannel#send:** Update embeds example (#5857) ([a6dae75](https://github.com/discordjs/discord.js/commit/a6dae75d3ac088e9057969e5334e993b72ad464f))
|
||||
- **ButtonInteraction:** Fix typo (#5835) ([9376ee4](https://github.com/discordjs/discord.js/commit/9376ee42f4ceb1e328cc7d299ffdce2b597c299b))
|
||||
- Removed topics and FAQ from the repository (#5820) ([9e5106d](https://github.com/discordjs/discord.js/commit/9e5106d90ec90728d688431047bf0e8cf464f24c))
|
||||
- **README:** Re-add install command, remove voice remnants (#5817) ([55ad6f0](https://github.com/discordjs/discord.js/commit/55ad6f0e23363f5b43d9ede28ba662e22c37fbf1))
|
||||
- **MessageEmbed:** Deprecation advisory for type (#5774) ([f5f3f77](https://github.com/discordjs/discord.js/commit/f5f3f772865ee98bbb44df938e0e71f9f8865c10))
|
||||
- **Messages:** Fix examples in messages after changes in #5758 (#5791) ([35c2225](https://github.com/discordjs/discord.js/commit/35c2225f5035fce47b0defc12754bda5901a453c))
|
||||
- **ApplicationCommand:** Typos in ApplicationCommandPermissionData (#5789) ([4511624](https://github.com/discordjs/discord.js/commit/4511624e790e2d02292505acb531cc9662c12c33))
|
||||
- **GuildMemberManager:** Fix docs for #search() (#5784) ([0139e10](https://github.com/discordjs/discord.js/commit/0139e102e34017f1f48d4b302edb387004ab9db1))
|
||||
- CommandInteraction#channelID is type of Snowflake (#5776) ([32d8c8b](https://github.com/discordjs/discord.js/commit/32d8c8ba940b31ab577c3de518fef382fe33a60d))
|
||||
- **InteractionDeferOptions:** Correctly define the typedef (#5769) ([4567cd4](https://github.com/discordjs/discord.js/commit/4567cd4ca23bed175da687b8cba7abd045065fa0))
|
||||
- Add new guild features (#5755) ([f7e420b](https://github.com/discordjs/discord.js/commit/f7e420bf290f5404e8b99b8896c63e178f77bbfc))
|
||||
- **Message:** Fix content param in #edit not showing as nullable (#5748) ([df9b678](https://github.com/discordjs/discord.js/commit/df9b67894ae62720e45be5d3ec99c98f8cb35601))
|
||||
- All the missing object -> Object changes (#5738) ([b317d86](https://github.com/discordjs/discord.js/commit/b317d86a931fe9edd0c8227b89c428e1256bb147))
|
||||
- Remove traces of StringResolvable (#5727) ([678b7da](https://github.com/discordjs/discord.js/commit/678b7da5b327b4a92add55ae05bf7b5b7c85c6a8))
|
||||
- **Webhook:** Update typings and docs for #editMessage (#5713) ([256d1b0](https://github.com/discordjs/discord.js/commit/256d1b0dfc8134aa8ccfb7d38ada8336e431050f))
|
||||
- **Message:** Add example for message.reply (#5332) ([7d7d2a5](https://github.com/discordjs/discord.js/commit/7d7d2a53b12617aca63211018fe5817c30dad26e))
|
||||
- **TextChannel:** Warning about setRateLimitPerUser NewsChannel (#5403) ([47bbdf4](https://github.com/discordjs/discord.js/commit/47bbdf415cd03145b16740ab88c7cca33bd7bcf5))
|
||||
- Fix InteractionDeferOptions typedef (#5694) ([add924c](https://github.com/discordjs/discord.js/commit/add924cdb20da648dd9601ff08f77b5befb4d70e))
|
||||
- **ColorResolvable:** Add Fuchsia to ColorResolvable typedef (#5676) ([7d9818e](https://github.com/discordjs/discord.js/commit/7d9818e21a1c4d65ae6a092f4e566b8d9f354ecf))
|
||||
- Add new typedef to properly doc InteractionReplyOptions (#5632) ([3589e0f](https://github.com/discordjs/discord.js/commit/3589e0f442bbe88769a3eb49cedf2dff096cf54d))
|
||||
- **Guild:** Add proper punctuation to #fetchOwner jsdoc (#5645) ([c8d20a4](https://github.com/discordjs/discord.js/commit/c8d20a456b635ce6081ed8ad17315a9a0c0244bc))
|
||||
- Correct casing of `object` -> `Object` in AuditLogChange (#5636) ([ab82caf](https://github.com/discordjs/discord.js/commit/ab82cafcde0ee259a32ef14303c1b4a64dea8fae))
|
||||
- **GuildChannelManager:** Add stage option (#5608) ([d219ecd](https://github.com/discordjs/discord.js/commit/d219ecd05c8f1f5517b511eea78d6cd3462b98ee))
|
||||
- **MessageEmbed:** MessageEmbedOptions typedef (#5466) ([4a06dd1](https://github.com/discordjs/discord.js/commit/4a06dd1295c44c519493b3734a7571a52c90e54c))
|
||||
- Update invite link, change version in the intro (#5592) ([533c247](https://github.com/discordjs/discord.js/commit/533c2471c2e73f0fb444a69e6b5ab6d12a570504))
|
||||
- **VoiceState:** `#setRequestToSpeak` and `#setSuppressed` returns a `Promise` instead of `void` (#5558) ([705d7b3](https://github.com/discordjs/discord.js/commit/705d7b36af313245d027cb12ba21c2fae7d948c1))
|
||||
- **GuildChannelManager:** Fix type options in description (#5440) ([936516c](https://github.com/discordjs/discord.js/commit/936516cb9c110ac9d41f847ef692001acd5677c3))
|
||||
- **ClientUser:** #setPresence does not return a promise (#5485) ([599f0f5](https://github.com/discordjs/discord.js/commit/599f0f5cef3fc3038db4de654f8035976df3c991))
|
||||
- **GuildChannel:** #members add cached spec, include voice (#5385) ([e848d25](https://github.com/discordjs/discord.js/commit/e848d25c86fcd4a11a7879f7dcd55d0bc93faa6d))
|
||||
- **BanOptions:** Make days description more clear (#5327) ([dedf432](https://github.com/discordjs/discord.js/commit/dedf43288ed280bbdb74927d116437ae4bf1b77d))
|
||||
- Update docs and examples for #4879 (#5323) ([685b260](https://github.com/discordjs/discord.js/commit/685b2604e481cbcc5dd77aac21bbec9599aab0a5))
|
||||
- **GuildMember:** Document owner override in permissions getter (#5320) ([62ba249](https://github.com/discordjs/discord.js/commit/62ba2499e02db6b6c5900689d149904aca9f4b22))
|
||||
- **ChannelManager:** Fetch can return Promise<null> (#5422) ([1c8b109](https://github.com/discordjs/discord.js/commit/1c8b1096c61db84aa9b6c172164fcead34bd156a))
|
||||
- **Guild:** Clarified description of guild.features (#5352) ([941e36f](https://github.com/discordjs/discord.js/commit/941e36f48a08446a86fce9f2f167709145ab2d92))
|
||||
- **BaseManager:** Fix a typo in #resolveID description (#5180) ([640a663](https://github.com/discordjs/discord.js/commit/640a6633b10471867c1808eca40bd6c359219230))
|
||||
- **BitFields:** Remove string from BitFieldResolvable (#5122) ([9ffcd83](https://github.com/discordjs/discord.js/commit/9ffcd83027f0fc06d69df21475865ad55138de01))
|
||||
- **MessageEditOptions:** Add the flags parameter (#5126) ([2aea7dd](https://github.com/discordjs/discord.js/commit/2aea7dd9214cd2db27e18a7f48b61bd6d54753c8))
|
||||
- **RoleManager:** Fetch description (#4920) ([be0f383](https://github.com/discordjs/discord.js/commit/be0f3835683733d21dd11a039a5f18fd48a8e774))
|
||||
- **TextBasedChannel:** Indicate that replyTo cannot be system (#5115) ([5c4547e](https://github.com/discordjs/discord.js/commit/5c4547e84dc05dae865ddf60becffc3218c0ba08))
|
||||
- Permission overwrite methods descriptions (#5079) ([77d4237](https://github.com/discordjs/discord.js/commit/77d42373a119284a7bfaa98575f6d93949521364))
|
||||
- **Client:** #emojis is a BaseGuildEmojiManager (#5048) ([2685b96](https://github.com/discordjs/discord.js/commit/2685b960d7bbf47d7884545ad06aec8160907342))
|
||||
- **User:** Fix typos in jsdoc (#5060) ([09d0755](https://github.com/discordjs/discord.js/commit/09d07553ab5f4fa8643862129c17550a21e1c081))
|
||||
- **WebSocketManager:** Fix type of status (#5059) ([9f3c3e0](https://github.com/discordjs/discord.js/commit/9f3c3e091844d22793cfd2880ffc2936ce41feab))
|
||||
|
||||
## Features
|
||||
|
||||
- **Collector:** Return a boolean on checkEnd (#6289) ([f473f43](https://github.com/discordjs/discord.js/commit/f473f43d081c8c703a0888acaf3fdbaf4bb20c6d))
|
||||
- **Channel:** Add isVoice() (#6297) ([5b4efd1](https://github.com/discordjs/discord.js/commit/5b4efd13c9eced97f4160f9c4c19d1c843360943))
|
||||
- **Constants:** Added more error codes (#6234) ([6b2098f](https://github.com/discordjs/discord.js/commit/6b2098f7c7592eee2aedbf19e62d3c262e159cba))
|
||||
- **MessageEmbed:** Add setFields method (#6186) ([a25e165](https://github.com/discordjs/discord.js/commit/a25e16599a2b3d82aabebcaeaef663680f2982a8))
|
||||
- **ThreadChannel:** Add fetchOwner() method (#6207) ([331a9d3](https://github.com/discordjs/discord.js/commit/331a9d3ffc6e45c068bfb454e05b863130559d42))
|
||||
- **Util:** Add SweptCollection for auto sweeping of caches (#6110) ([dbb59ba](https://github.com/discordjs/discord.js/commit/dbb59ba1b29b2f75dd8faab5c3004ade51598abc))
|
||||
- **WebhookClient:** Allow creation of clients via URLs (#6192) ([e000af5](https://github.com/discordjs/discord.js/commit/e000af5c98483046db25a46e905ed244bdcfe262))
|
||||
- **FetchRecommendedShardsOptions:** Account for large bot sharding (#6184) ([19b242a](https://github.com/discordjs/discord.js/commit/19b242ac10aa9b32c1a45a9178c97481d62a9400))
|
||||
- **GuildAuditLogs:** Add threads (#6195) ([26ba0e1](https://github.com/discordjs/discord.js/commit/26ba0e10368ff7c4b7a79a37450c8c0784185fb7))
|
||||
- **Guild:** Add fetchWidget() for getting widget data (#6180) ([b22272f](https://github.com/discordjs/discord.js/commit/b22272f86075ac5585abf05f54cf05187c4eabf9))
|
||||
- **ApplicationCommandOptionType:** Add NUMBER (10) (#6128) ([2f1cc1f](https://github.com/discordjs/discord.js/commit/2f1cc1fc27f5af6d9b88cdc353605a3ddf76e579))
|
||||
- **CommandInteractionOptionResolver:** Add sub-command required option (#6165) ([690c121](https://github.com/discordjs/discord.js/commit/690c121aa9575f7b878030229b0fedd56c3a1a87))
|
||||
- **Sticker:** Updates, sticker packs, and guild stickers (#5867) ([54d6a3a](https://github.com/discordjs/discord.js/commit/54d6a3a0708105acd6a3a709a8e1636d00c81fc8))
|
||||
- **GuildPreview:** Add createdAt & createdTimestamp (#6130) ([9f039a8](https://github.com/discordjs/discord.js/commit/9f039a86798352e360d7e47d62d1b9c011c2ec71))
|
||||
- **CommandInteraction:** Add CommandInteractionOptionResolver (#6107) ([f293132](https://github.com/discordjs/discord.js/commit/f293132345294e33e80866272feaedf2e4a70d45))
|
||||
- Make Instance#fetch force true by default, and fix force parameter (#6116) ([366f3c9](https://github.com/discordjs/discord.js/commit/366f3c910a370ff1e184afae054f957db9a98293))
|
||||
- **REST:** Append additional information to the required User Agent (#6112) ([f200f14](https://github.com/discordjs/discord.js/commit/f200f14a409a56df5efe788de0ae45fc061bb46d))
|
||||
- **Client:** Add conditional ready typings (#6073) ([4206e35](https://github.com/discordjs/discord.js/commit/4206e35b2316431c1a009664636dcda85d39fff8))
|
||||
- Allow channels from uncached guilds to be returned from fetch (#6034) ([755c180](https://github.com/discordjs/discord.js/commit/755c180659c125532fe6f8e33e6c3b56e275311b))
|
||||
- **Collector:** Better types for events (#6058) ([c0a814f](https://github.com/discordjs/discord.js/commit/c0a814fdb35cb1fa7418bb3bdd3cec0a8a130bf5))
|
||||
- **Message:** Add 'failIfNotExists' to ClientOptions (#6038) ([28c5724](https://github.com/discordjs/discord.js/commit/28c57246d1d3cd7a22384ddc7970ab5263a4ace0))
|
||||
- **LimitedCollection:** Export LimitedCollection (#6043) ([31d3129](https://github.com/discordjs/discord.js/commit/31d31293d314492562104f02511d4d1e117711f3))
|
||||
- **Client:** Enforce passing scopes to generateInvite (#6024) ([c6e5521](https://github.com/discordjs/discord.js/commit/c6e55216874f1892727db927f55db3de6a1712d8))
|
||||
- **Managers:** ✨ Add GuildInviteManager (#5889) ([9e08b02](https://github.com/discordjs/discord.js/commit/9e08b02df2c9b31cfd91eac3ad008dab94855a59))
|
||||
- **Managers:** Add customizable caching for managers (#6013) ([8c7cb0e](https://github.com/discordjs/discord.js/commit/8c7cb0eff8e169836decf3c9843d7fa0998a5e84))
|
||||
- **InteractionCollector:** Reworked to be more generic (#5999) ([374c779](https://github.com/discordjs/discord.js/commit/374c779f7f8bbaa9bf06fa2b5b16f60da5095b5c))
|
||||
- PermissionOverwriteManager (#5318) ([e7ad2fe](https://github.com/discordjs/discord.js/commit/e7ad2fe20772915dcf3e9c4ae92a072b9c918a07))
|
||||
- **Formatters:** Added new URL utilities and docs (#6014) ([98e45a5](https://github.com/discordjs/discord.js/commit/98e45a59957842fd1ee55d59e30ee868f985e15d))
|
||||
- **RoleManager:** Added `edit` method, alias `Role#edit` (#5983) ([1e73c25](https://github.com/discordjs/discord.js/commit/1e73c25fbfc9b3cb62bed719dc79de25f67707ee))
|
||||
- **StageChannel:** Add createStageInstance method & use better naming convention (#5951) ([71fb33a](https://github.com/discordjs/discord.js/commit/71fb33a5fea7398598b603a888e07519fddd56a9))
|
||||
- **Channel:** Add isThread typeguard for better TS support (#5978) ([b7ed675](https://github.com/discordjs/discord.js/commit/b7ed6752ac98e56e79b6fd9fd3a5e47572454d85))
|
||||
- **Util:** Added formatters (#5976) ([8c7a28f](https://github.com/discordjs/discord.js/commit/8c7a28f211dd05ec67cbce667b1d591ed59a40c6))
|
||||
- **Interactions:** Option to auto-fetch replies (#5831) ([5e28ff8](https://github.com/discordjs/discord.js/commit/5e28ff83cbc04850077cc2f97bb2039c55b3b8ea))
|
||||
- **Interaction:** Add guild guard (#5955) ([87e8cdd](https://github.com/discordjs/discord.js/commit/87e8cdd3eba29ae1d741aa86572f1731b05c12fb))
|
||||
- **Managers:** New ApplicationCommandPermissionsManager (#5897) ([6264c60](https://github.com/discordjs/discord.js/commit/6264c60e97da93b311a7a9fd92e16e59de94104a))
|
||||
- **MessageComponentInteraction:** Component getter (#5840) ([1439183](https://github.com/discordjs/discord.js/commit/1439183ad3f84b2b7500aaead2cf8779199b47d4))
|
||||
- **MessageMentions:** Add repliedUser (#5905) ([2616125](https://github.com/discordjs/discord.js/commit/261612596d37aa6fb48ae070d358b3fde953c769))
|
||||
- **MessageSelectMenu:** Droppybois (#5692) ([e5fcf0b](https://github.com/discordjs/discord.js/commit/e5fcf0bee53a15d7a87d4a5cf4e206823d6e7d87))
|
||||
- Api v9 and threads (#5570) ([7346621](https://github.com/discordjs/discord.js/commit/7346621d15c96906d5b848c483669750ff9c6e12))
|
||||
- **InteractionCreate:** Move to an Action handler (#5906) ([ea49f7c](https://github.com/discordjs/discord.js/commit/ea49f7ca74892495dd53f8d315086035c1814149))
|
||||
- Add missing APIError codes (#5898) ([d930c81](https://github.com/discordjs/discord.js/commit/d930c812bb4511a688b76d9bf1ac66e28bff033e))
|
||||
- **Interactions:** Improve error handling for ephemeral responses (#5892) ([bd9f56a](https://github.com/discordjs/discord.js/commit/bd9f56af9a0a1fb12cfa30d9e2e0ad680eb80949))
|
||||
- Add APIError codes for stage instance (#5888) ([c850ae1](https://github.com/discordjs/discord.js/commit/c850ae10270076c4b2e10b130dd8f88eed4ed201))
|
||||
- **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))
|
||||
- **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))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Rest:** Optional ratelimit errors (#5659) ([16f261e](https://github.com/discordjs/discord.js/commit/16f261e773a353c54a75f38008f9b28435ae6603))
|
||||
- Promisified single interaction collection (#5770) ([c2b3ed0](https://github.com/discordjs/discord.js/commit/c2b3ed09a0ec7f9b7453d0bcf9f2900e408f5001))
|
||||
- **Message:** ApplicationID for interaction responses (#5765) ([65dc00f](https://github.com/discordjs/discord.js/commit/65dc00f3210065015684b6d585f6747bd5ebadf1))
|
||||
- **Client:** Make use of with_expiration in #fetchInvite (#5764) ([bf191df](https://github.com/discordjs/discord.js/commit/bf191df9c033404da3e717f73306cdb3f659fafc))
|
||||
- **Interactions:** Add InteractionWebhook for better internals (#5712) ([dec191a](https://github.com/discordjs/discord.js/commit/dec191aa1e4f22690285ca06c6eee7e6086b2930))
|
||||
- **MessageComponents:** Clickybois (MessageButton, MessageActionRow, associated Collectors) (#5674) ([cbd7f2b](https://github.com/discordjs/discord.js/commit/cbd7f2b9aa44a9240947ed716d0e72257ac499f7))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Guild:** Add the new nsfw_level property (#5660) ([3fe7add](https://github.com/discordjs/discord.js/commit/3fe7add2c5c07023d3cc83c06bba846c1328e446))
|
||||
- InteractionDeferOptions (#5641) ([ed593c9](https://github.com/discordjs/discord.js/commit/ed593c91fb7b87ae8b512c6f127e12f33c9631b6))
|
||||
- **CommandInteraction:** Ephemeral followup messages (#5618) ([68b40dd](https://github.com/discordjs/discord.js/commit/68b40dd91df70593c8271bd455fd0b3c6d19d334))
|
||||
- **GuildChannel:** CreateInvite target options (#5514) ([f831872](https://github.com/discordjs/discord.js/commit/f831872125214e39c8866ce1cf7c63159a3dba39))
|
||||
- **MessageEmbed:** Remove normalizeField validation (#5459) ([ff2f737](https://github.com/discordjs/discord.js/commit/ff2f7372f23f901620d3afff215f33be487521d5))
|
||||
- **GuildMemberManager:** Extend API coverage (#4872) ([2e2464b](https://github.com/discordjs/discord.js/commit/2e2464bf07c2b2e08d396b093126f887d19aec57))
|
||||
- **GuildChannel:** Make createOverwrite and updateOverwrite not dependent on cache (#5489) ([58763b0](https://github.com/discordjs/discord.js/commit/58763b0e91b78d068121521ea3e853627b3ea325))
|
||||
- **MessageManager:** Extend API coverage (#4869) ([c56c4a8](https://github.com/discordjs/discord.js/commit/c56c4a8dc86b0f37dd7c9ee9a4d422a52070b50c))
|
||||
- **Message:** Add ReplyMessageOptions for #reply (#5296) ([7ce741d](https://github.com/discordjs/discord.js/commit/7ce741dacd06fd8af0ab501e38be08cf6b506a62))
|
||||
- **ShardingManager:** Add options typings (#5583) ([31b4390](https://github.com/discordjs/discord.js/commit/31b4390042e6557f7f9d2f258c79ea50ba4929e2))
|
||||
- **GuildChannel#clone:** Support for position property (#5236) ([d455cb6](https://github.com/discordjs/discord.js/commit/d455cb65a6188e7d7b6720848b5ce37dbf8b5dff))
|
||||
- GuildBanManager (#5276) ([6d09160](https://github.com/discordjs/discord.js/commit/6d09160f5ba878fcd1f8bae88b5e6347e632cd2c))
|
||||
- **APIRequest:** Support setting global headers in HTTPOptions (#5586) ([135abcc](https://github.com/discordjs/discord.js/commit/135abccd9c75c33c8510cdcbe33b0dea4198fe33))
|
||||
- **Message:** Replace referencedMessage with fetchReference (#5577) ([1398431](https://github.com/discordjs/discord.js/commit/1398431bca9a3743758295f1effa2e7f6c35093e))
|
||||
- **Message:** Allow removing attachments (#5557) ([ca9e5a0](https://github.com/discordjs/discord.js/commit/ca9e5a0ee1afca544192df1daef744d5a35f1727))
|
||||
- Add support for application command events (#5596) ([9f74f95](https://github.com/discordjs/discord.js/commit/9f74f95f69f4aa8a9a23c160e25dc61010c0a8e0))
|
||||
- Interactions (#5448) ([f7643f7](https://github.com/discordjs/discord.js/commit/f7643f7bbe64003ad8b221006190dd15529651e9))
|
||||
- **Sticker:** Added Sticker (#4909) ([026afc2](https://github.com/discordjs/discord.js/commit/026afc2c1a88bc210c973bcf235fef3484571111))
|
||||
- **Webhook:** Add 'fetchMessage' method (#5530) ([63398d6](https://github.com/discordjs/discord.js/commit/63398d6ae46f0487c4d5d8bfe823952a803e4a5a))
|
||||
- **GuildManager:** Allow system channel flags in create (#5504) ([d9fa180](https://github.com/discordjs/discord.js/commit/d9fa180cf93f1a339192ae95dfb512482bd0ed0b))
|
||||
- **Guild:** SetChannelPositions parent, lockPermissions keys (#5507) ([4866e26](https://github.com/discordjs/discord.js/commit/4866e2672f28bfc481cf03533f7ba259050c80f4))
|
||||
- **Webhook:** SourceGuild, sourceChannel, improve owner (#5508) ([116ecf2](https://github.com/discordjs/discord.js/commit/116ecf246e89db4d629a13877a440260c7504e30))
|
||||
- **Guild:** Allow description and features in edit (#5505) ([8a059cc](https://github.com/discordjs/discord.js/commit/8a059cccb8ecbd0bf60d2ed395a8de0806b3395a))
|
||||
- **Util:** Make `cleanContent` take a channel instead of a message (#5535) ([f1c0c04](https://github.com/discordjs/discord.js/commit/f1c0c043b516f4158ab9d473419e3b5e125a4c03))
|
||||
- **Guild:** Nsfw guilds (#5525) ([5968323](https://github.com/discordjs/discord.js/commit/596832371cefef7739e8d714248d1c6d438eb8df))
|
||||
- **Guild:** Replace `owner` with `fetchOwner` (#5480) ([1be67b8](https://github.com/discordjs/discord.js/commit/1be67b88516b104073e46574a180498bad2aa02b))
|
||||
- **GuildFeatures:** Added the new screening features (#5328) ([3c175cb](https://github.com/discordjs/discord.js/commit/3c175cb5116fe50ba3084163565dd244a25b657f))
|
||||
- **MessageAttachment:** Support for #contentType (#5481) ([7b161f9](https://github.com/discordjs/discord.js/commit/7b161f93a040a6bdce6e7e26d7a3c3b6c61a04fd))
|
||||
- **SysChanFlags:** New flag and rename in sync with client (#5506) ([fe93a7e](https://github.com/discordjs/discord.js/commit/fe93a7e084189b54b8af82461809dee1da112b75))
|
||||
- Move internal regular expressions to static properties (#5384) ([207735c](https://github.com/discordjs/discord.js/commit/207735cedcf9a998571a328c7c7b2414d3ebe9d5))
|
||||
- **typings:** Add ShardingManager.shardList to type definitions (#5446) ([32b0d71](https://github.com/discordjs/discord.js/commit/32b0d71af7e3afc401898753b1e8cb1e991b70e7))
|
||||
- **typings:** Explicitly type PremiumTier and Collectors (#5458) ([7c49612](https://github.com/discordjs/discord.js/commit/7c49612d4bedfe13f7ed676c125cc7f7f33596df))
|
||||
- Make changes to PresenceData typings and docs (#5317) ([eb43ce4](https://github.com/discordjs/discord.js/commit/eb43ce4d4fb4d634696c5b0f026174dc0e435fe3))
|
||||
- **MessageTypes:** Add 16 and 17 (#4685) ([c9107e3](https://github.com/discordjs/discord.js/commit/c9107e35fa8b74f8ad7a7d3ee7d7178a35790e18))
|
||||
- **GuildMemberManager:** Add 'search' method (#4154) ([0ba2bcb](https://github.com/discordjs/discord.js/commit/0ba2bcb54582b38ee8eec8d1547b979bf1b7c755))
|
||||
- Stage channels (#5456) ([eec7cf7](https://github.com/discordjs/discord.js/commit/eec7cf7634653fc02ee4f94e970960174a0e6d1b))
|
||||
- **Activity:** Add missing fields (#4984) ([63ff6a0](https://github.com/discordjs/discord.js/commit/63ff6a07ebcba7e9134e3902e338e8dc6564ee63))
|
||||
- **Webhook:** Add '(edit|delete)Message' methods (#5223) ([7cabc1c](https://github.com/discordjs/discord.js/commit/7cabc1c490ddd9518528e12a58a746d65e43d4eb))
|
||||
- **Rest:** Better handling of global rate limit and invalid request tracking (#4711) ([9d2d606](https://github.com/discordjs/discord.js/commit/9d2d60691eb4bde729f40fb633ae257cf5bc6545))
|
||||
- **Application:** Application flags (#5147) ([06e9d86](https://github.com/discordjs/discord.js/commit/06e9d86cb3dd11708c9cdd81f15970979e5b090d))
|
||||
- **WebSocketManager:** Let identify throw on depleted limits (#5283) ([624a446](https://github.com/discordjs/discord.js/commit/624a4464ca86bfa0b095ecb2cdaac2e8030cc413))
|
||||
- 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))
|
||||
- **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))
|
||||
- **GuildEmojiManager:** Implement GuildEmojiManager#fetch (#4933) ([ffe3140](https://github.com/discordjs/discord.js/commit/ffe31405ff559202be55473db7e8b34894fbf4a7))
|
||||
- **Browser:** Remove browser <20> (#5113) ([0a591a9](https://github.com/discordjs/discord.js/commit/0a591a96974ab8b2aef7d7b9b64ec63d0fbe4ec4))
|
||||
- **Role:** Role tags (#4628) ([d6234b7](https://github.com/discordjs/discord.js/commit/d6234b764ecbf12ebc0a795429a6aa3a650f5a6c))
|
||||
- **APIMessage:** Remove disableMentions (#4836) ([4107899](https://github.com/discordjs/discord.js/commit/41078997aefce2a9e683b9805aad6436612a3aa7))
|
||||
- **GuildMember:** Make GuildMember#setNickname first param nullable (#5070) ([d70127c](https://github.com/discordjs/discord.js/commit/d70127cee69e66e87702a6db4b58ad12aa85f96c))
|
||||
- **Message|TextChannel:** Inline replies (#4874) ([60e5a0e](https://github.com/discordjs/discord.js/commit/60e5a0e46f57cf297b66f1a940d24a20f46b5319))
|
||||
- BaseGuildEmojiManager (#4934) ([8d650a7](https://github.com/discordjs/discord.js/commit/8d650a72509a3f369ae31ec421d1892d182175e4))
|
||||
- **Message:** Added string type for message nonce (#4782) ([4b555fd](https://github.com/discordjs/discord.js/commit/4b555fdf4c3b35fa0ea284f9cd56765ecb608b89))
|
||||
- **GuildMemberManager:** Throw TypeError on incorrect GuildMemberManager#ban params (#4816) ([863734a](https://github.com/discordjs/discord.js/commit/863734aba46c5e0d04fbc83d2ed314726bddcbc2))
|
||||
|
||||
## Refactor
|
||||
|
||||
- Replace dependency with initial implementation (#6310) ([d5e28c2](https://github.com/discordjs/discord.js/commit/d5e28c22988376825d5e11fbdcf2e99ba8ebc2f4))
|
||||
- **Interaction:** Rename defer to deferReply (#6306) ([4241feb](https://github.com/discordjs/discord.js/commit/4241febe24e6b552083b3d0ee1a086409b900714))
|
||||
- **InteractionCollector:** Only keep Ids of objects (#6084) ([b639b6c](https://github.com/discordjs/discord.js/commit/b639b6c6533bde64f795b1171263961fa7abd3af))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Message:** Accept a single object instead of 3 arguments (#6244) ([434e330](https://github.com/discordjs/discord.js/commit/434e3307540111ec82e1234656f359188e843320))
|
||||
- Move member adding to manager (#6231) ([198a5c4](https://github.com/discordjs/discord.js/commit/198a5c490d6d60316f3201ad2c84654e05d43aff))
|
||||
- Use guild-wide route for fetching active threads (#6193) ([2a07055](https://github.com/discordjs/discord.js/commit/2a07055cc0bd9d7e1ac2e36066d08f15ebd9414b))
|
||||
- Remove extended collection (#6246) ([00bae4f](https://github.com/discordjs/discord.js/commit/00bae4fe6b9ecf18a87ea622f6a2c646031daca7))
|
||||
- Strengthen channel typings in appropriate places (#6232) ([65ae064](https://github.com/discordjs/discord.js/commit/65ae06429d595bcd60dfc5642e7839840c484e3c))
|
||||
- **Message:** Make thread a getter for accuracy (#6215) ([5f710ae](https://github.com/discordjs/discord.js/commit/5f710ae5597808f770e113152fcae39d40294a00))
|
||||
- Match subcommand (group) name casing with Discord's (#6204) ([a69e2f7](https://github.com/discordjs/discord.js/commit/a69e2f79043117eb1ce52b98e4c0a5c58f18d6ea))
|
||||
- Only cache commands from own user (#6161) ([4886ae2](https://github.com/discordjs/discord.js/commit/4886ae23abaff1f4f1e7f5d15c4f2670a9de54be))
|
||||
- **Message:** Combine patch methods (#6071) ([cd47a52](https://github.com/discordjs/discord.js/commit/cd47a524afa9cd5af0dfe05d98fa7ab473192bcc))
|
||||
- **CommandInteractionOptionResolver:** Add readonly data property (#6156) ([328501b](https://github.com/discordjs/discord.js/commit/328501bd8ee343edfd3492f8ba81d5c57006d496))
|
||||
- **OptionResolver:** Accept single type instead of an array (#6154) ([5addcd1](https://github.com/discordjs/discord.js/commit/5addcd15d8e6e151a3c4ad05d0fc567ab6bd6bfd))
|
||||
- Change const enums to interfaces (#6078) ([63ce065](https://github.com/discordjs/discord.js/commit/63ce065fc3cee478a593cc278e40775dbbcdc6a6))
|
||||
- **ActionsManager:** Less complex code (#6102) ([4d53d0f](https://github.com/discordjs/discord.js/commit/4d53d0fd115e3a31e7a431c5dece8fc251c2115d))
|
||||
- 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))
|
||||
- **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))
|
||||
- **Presences:** Remove from User, nullable on GuildMember (#6055) ([afbd5db](https://github.com/discordjs/discord.js/commit/afbd5db404c711fd966122a97ecf63493b35ff15))
|
||||
- **Intents:** Remove computed shorts (#6050) ([3022b0f](https://github.com/discordjs/discord.js/commit/3022b0f5b1bcdd069d52a68994b2befa18d749e4))
|
||||
- Remove `lastMessage` properties from `User` and `GuildMember` (#6046) ([1a27f57](https://github.com/discordjs/discord.js/commit/1a27f57950d51597f5c642a8c2a680a47df8c7a5))
|
||||
- **typings:** General cleanup (#6047) ([676118a](https://github.com/discordjs/discord.js/commit/676118ab0f5cc36cf0fdd7cb897ae68020394778))
|
||||
- Change `xID` to `xId` (#6036) ([a7c6678](https://github.com/discordjs/discord.js/commit/a7c6678c7246025c4b358a5396dbacf4a73148ee))
|
||||
- Improve typings and docs related to threads (#5991) ([4bf4980](https://github.com/discordjs/discord.js/commit/4bf49809f240430987f28795124e7dbbe5cbba8e))
|
||||
- **Util:** Make class extend `null` (#6000) ([2446ff5](https://github.com/discordjs/discord.js/commit/2446ff525145afa3d5b4b5e822c3e7d8b010a4c0))
|
||||
- Rename events to be consistent with WS names (#6010) ([a11a105](https://github.com/discordjs/discord.js/commit/a11a10525b39fb057e50ac311450ea43acdbfb5b))
|
||||
- New node features (#5132) ([1e8f012](https://github.com/discordjs/discord.js/commit/1e8f01253e85891b78c2b4ae866ce5ae56add413))
|
||||
- **Presence:** Remove second assignment of `syncID` (#5956) ([fb8d516](https://github.com/discordjs/discord.js/commit/fb8d5166a8b2264b69bfd39e95798d984f971155))
|
||||
- **MessagePayload:** Rename APIMessage (#5921) ([b15d825](https://github.com/discordjs/discord.js/commit/b15d825bb3acdf432b94d8413a7a964ccc8734bc))
|
||||
- Removed `code` and `split` options (#5918) ([985d4d6](https://github.com/discordjs/discord.js/commit/985d4d6a438fc9123264f6a1c600f34fccc1825f))
|
||||
- **Collector:** Make filter an option (#5903) ([0d0c8f0](https://github.com/discordjs/discord.js/commit/0d0c8f07f2535dd315ca95abe35e848c13d0ddf5))
|
||||
- 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))
|
||||
- **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))
|
||||
- **GuildChannel:** Use Permissions.defaultBit over 0n (#5822) ([19d0405](https://github.com/discordjs/discord.js/commit/19d0405aa5566f41028da83446e3bd22329d742f))
|
||||
- Remove all voice code (#5818) ([fdef940](https://github.com/discordjs/discord.js/commit/fdef9401274601f6a8def4322aa4f0bb3a278890))
|
||||
- **MessageEmbed:** Remove files (#5813) ([e3e466d](https://github.com/discordjs/discord.js/commit/e3e466d3e56145110ba0cfcba7b3c594267d36fb))
|
||||
- **Guild:** Remove region from guild and manager methods (#5766) ([a1f763e](https://github.com/discordjs/discord.js/commit/a1f763ee75a7d906bbe727f616e33206dcc6792c))
|
||||
- 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))
|
||||
- **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))
|
||||
- **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))
|
||||
- Remove error-silencing try/catch on event handler imports (#5542) ([cdcc50f](https://github.com/discordjs/discord.js/commit/cdcc50f365c6afa44fecb1653b77945112a32960))
|
||||
- **Sharding:** Use options objects (#5510) ([c9b5353](https://github.com/discordjs/discord.js/commit/c9b53539d59cb956e1125581331eadb1e092c986))
|
||||
- Add discord-api-types as a dependency (#5539) ([1b827fe](https://github.com/discordjs/discord.js/commit/1b827fe13638279fe57c7a4f897b38e749ac06f6))
|
||||
- Rename Snowflake to SnowflakeUtil (#5502) ([164ddf6](https://github.com/discordjs/discord.js/commit/164ddf668f06214ae327b4527a787a05e12cbeb1))
|
||||
- **Guild:** Remove fetchVanityCode() (#5471) ([0a2e0c0](https://github.com/discordjs/discord.js/commit/0a2e0c0e3e06dc63359c4f69d74df3365e413f76))
|
||||
- **Collector:** Make endReason a getter (#5271) ([8d14ee3](https://github.com/discordjs/discord.js/commit/8d14ee35400ef0bdb92148d3cd582155171f2238))
|
||||
- Switch api and gateway to V8 (#4879) ([ee5bc1a](https://github.com/discordjs/discord.js/commit/ee5bc1a5c4e218ea1f16992694a2bff86c86d2d2))
|
||||
- **Client:** Remove fetchAllMembers option (#5257) ([aaed72b](https://github.com/discordjs/discord.js/commit/aaed72b723b6069d6f57c8eb84cb580b90f42809))
|
||||
- **GuildMember:** Remove GuildMember#hasPermission (#5152) ([5401b92](https://github.com/discordjs/discord.js/commit/5401b92aac72db3a60e4cd6f61f180294ca9c929))
|
||||
- **Util:** Remove convertToBuffer (#5237) ([a33eed7](https://github.com/discordjs/discord.js/commit/a33eed71af136d35d805b9414e284d178c48790f))
|
||||
- **Message:** Remove stored edit history (#5155) ([8c2e6b7](https://github.com/discordjs/discord.js/commit/8c2e6b70b84ff597d15aa99712db5d719fd5a0af))
|
||||
- RoleManager (#5131) ([2a0dcc5](https://github.com/discordjs/discord.js/commit/2a0dcc5cae30b4091274096ab6f5910f55ec92c1))
|
||||
- **Message:** Remove options for Message#delete (#4999) ([75e6dfb](https://github.com/discordjs/discord.js/commit/75e6dfbfd3b351a2378c182a27a2e7e072d6977e))
|
||||
- **Client:** Improve generateInvite() (#5065) ([5b51392](https://github.com/discordjs/discord.js/commit/5b51392724f7b41d2276824672bc7365e952fb83))
|
||||
|
||||
## Testing
|
||||
|
||||
- **Types:** Add `notPropertyOf` type-only utility (#6051) ([03fe6ee](https://github.com/discordjs/discord.js/commit/03fe6ee4e4daabebf1bc18be544f482c2a91b0e1))
|
||||
- Client should destroy (#5353) ([4099c28](https://github.com/discordjs/discord.js/commit/4099c28776ff154fbcda4e257bbecf40c1c1cf78))
|
||||
|
||||
## Typings
|
||||
|
||||
- **MessageButtonOptions:** Clean up and export some button option type definitions (#6291) ([ae6200e](https://github.com/discordjs/discord.js/commit/ae6200e58e6062372d5c526f028d0c9c17adf8e2))
|
||||
- Make MessageTarget extend on TextBasedChannels (#6296) ([5b0621f](https://github.com/discordjs/discord.js/commit/5b0621fb3a8ecefcd8ab0031662a337116929d01))
|
||||
- **Caches:** Add GuildStickerManager and GuildInviteManager (#6268) ([15aea68](https://github.com/discordjs/discord.js/commit/15aea68946f4d35a416c2fd5291584481d5132da))
|
||||
- Use api-types for stricter typings (#6230) ([00c2bf8](https://github.com/discordjs/discord.js/commit/00c2bf81cdca751928d65a9e9a0645c5fd6e4ce9))
|
||||
- **ButtonMessageOptions:** Make button/link button typings more specific (#6212) ([77c72e6](https://github.com/discordjs/discord.js/commit/77c72e625f316aa7d12ca20936439ee967306752))
|
||||
- **WsEvents:** Add thread ws events (#6194) ([4f1f32f](https://github.com/discordjs/discord.js/commit/4f1f32f2a52832e1dc06a9dca14f331479f6bf8a))
|
||||
- **DataManager:** Add 'K' to type parameter of 'resolveId' (#6152) ([8586505](https://github.com/discordjs/discord.js/commit/85865058ed3ab13e3850908a44f9ca81a1c027b9))
|
||||
- **ColorResolvable:** Readonly tuple (#6153) ([1e90be8](https://github.com/discordjs/discord.js/commit/1e90be8f7a7290886cbbebc0e6cbe15075dd2fd9))
|
||||
- **Message:** Mark `#thread` as nullable (#6129) ([ef5ba05](https://github.com/discordjs/discord.js/commit/ef5ba05996ba45b56dde0f1f624347777b1de0ae))
|
||||
- **Options:** Add types for cacheWithLimits (#6095) ([8db6df3](https://github.com/discordjs/discord.js/commit/8db6df3d1eb58c542624e875f7da2a848153d11c))
|
||||
- **Interaction:** Change inGuild return type (#6094) ([60148c6](https://github.com/discordjs/discord.js/commit/60148c6a78d905719bdd864bee1869dc4bbb041d))
|
||||
- **PartialWebhookFields:** Add APIMessage to deleteMessage union (#6085) ([a9e7ebd](https://github.com/discordjs/discord.js/commit/a9e7ebd94fa430bfcccdb9fb5250784aee163e31))
|
||||
- **Interactions:** Fix function overloads (#6109) ([98c6078](https://github.com/discordjs/discord.js/commit/98c60789a2bc38a9939b2493c3e9346eb0a0446e))
|
||||
- **Guild:** Remove fetchVoiceRegions (#6099) ([a8984bc](https://github.com/discordjs/discord.js/commit/a8984bc68c8ac6be615b8fd50eac667879720ab5))
|
||||
- **Partial:** Add partial reactions (#6066) ([d6c43a5](https://github.com/discordjs/discord.js/commit/d6c43a50bd608c233919e6386683c126cf821346))
|
||||
- **Test:** Fix overloads for channel create ([5b6be0c](https://github.com/discordjs/discord.js/commit/5b6be0cebc4aefd936781dde3c627edfdecebea7))
|
||||
- **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))
|
||||
- **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))
|
||||
- **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))
|
||||
- **Interactions:** Fix function overload types (#5989) ([521d26c](https://github.com/discordjs/discord.js/commit/521d26c57f3f615e5355ba3c78d2ffea14e685a3))
|
||||
- Few missing thread channels (#5988) ([941cd86](https://github.com/discordjs/discord.js/commit/941cd86881c8205fbbb6a8579e41b006bcf72c2c))
|
||||
- **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))
|
||||
- **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))
|
||||
- Define ApplicationCommand enums in lib (#5947) ([e37ef3a](https://github.com/discordjs/discord.js/commit/e37ef3af2151e556527ccd8e98ec531bdcc0ed70))
|
||||
- Fix remaining Raw type references, update discord-api-types dep (#5942) ([03d3a5c](https://github.com/discordjs/discord.js/commit/03d3a5cdde5492433d27bbfe46afe0ebf2de5904))
|
||||
- **ThreadMemberManager:** Fix incorrect usage (#5928) ([6065b11](https://github.com/discordjs/discord.js/commit/6065b11634c17fdacb49127a15eb9dbd9657bef7))
|
||||
- **MessageReactionResolvable:** Add string (#5863) ([a0b7d95](https://github.com/discordjs/discord.js/commit/a0b7d95e3627c7a0725231575667287ebbc87258))
|
||||
- **GuildApplicationCommandManager:** Allow undefined command (#5837) ([d5bb758](https://github.com/discordjs/discord.js/commit/d5bb7585da03a2503c4497fb26051920944ebede))
|
||||
- Corrected shard broadcastEval (#5834) ([a0a56e2](https://github.com/discordjs/discord.js/commit/a0a56e2cb30c6b631aa73ffc66752b68da74e299))
|
||||
- **MessageComponentInteraction:** Update should return Promise<void> (#5829) ([08cffd6](https://github.com/discordjs/discord.js/commit/08cffd6a3036a93d7524336faa1fdb287ccb3833))
|
||||
- **Extendable:** Add ButtonInteraction (#5802) ([19fd162](https://github.com/discordjs/discord.js/commit/19fd1622f59e6bf86513ddfd07da8cc616d410ea))
|
||||
- Extend MessageComponentInteractionCollector correctly (#5752) ([c6696d8](https://github.com/discordjs/discord.js/commit/c6696d839913a95663e68cd185eb5001174ad456))
|
||||
- Fix awaitReactions typings for returned collection ([43fc40e](https://github.com/discordjs/discord.js/commit/43fc40e9b4250990649c7dc8e46f475c05a29032))
|
||||
- Change remaining string IDs to Snowflakes (#5737) ([ff4d6dd](https://github.com/discordjs/discord.js/commit/ff4d6dded52771788619df395df016279909ba3c))
|
||||
- **Snowflake:** Export the type (#5722) ([66a6a1f](https://github.com/discordjs/discord.js/commit/66a6a1fcedc8c35b75a89dbb26edc01317bdd7e2))
|
||||
- Use Snowflake type (#5717) ([76db642](https://github.com/discordjs/discord.js/commit/76db6425439f41d13abf803ff5ab15a472da261d))
|
||||
- **PermissionOverwriteOptions:** Remove unused interface (#5651) ([b40027b](https://github.com/discordjs/discord.js/commit/b40027beb9e0b9d11312dbda293ec7ecd4e84fa9))
|
||||
- **WebhookMessageOptions:** Omit reply instead of replyTo (#5610) ([2345c6d](https://github.com/discordjs/discord.js/commit/2345c6db0c726713aafe10912303796a653a867f))
|
||||
- Remove typings for Client#disconnect event (#5469) ([a4d09ab](https://github.com/discordjs/discord.js/commit/a4d09ab0a8c39d743673d9d6ae93b3898e7af0b1))
|
||||
- **PermissionOverwrites:** Use correct parameter type for resolveOverwriteOptions (#5302) ([ca5f371](https://github.com/discordjs/discord.js/commit/ca5f371f1ad0ffa6b57def34d9f50dc29c149e10))
|
||||
- **MessageReaction:** Allow message to be partial (#5303) ([aac6275](https://github.com/discordjs/discord.js/commit/aac6275300a1511d2a30f0fc27999381fad4f7d9))
|
||||
- **RateLimitData:** Remove timeDifference property (#5208) ([80e1afb](https://github.com/discordjs/discord.js/commit/80e1afb65447e1d66429ddda36902d871920fdc3))
|
||||
- Make Client#voice non-nullable (#5148) ([40d77ba](https://github.com/discordjs/discord.js/commit/40d77bacc3dfdd5e9dd9f3ddff0751fe8470ddc8))
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
For breaking changes please reference: <https://discordjs.guide/additional-info/changes-in-v13.html>
|
||||
191
packages/discord.js/LICENSE
Normal file
191
packages/discord.js/LICENSE
Normal file
@@ -0,0 +1,191 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2015 - 2021 Noel Buechler
|
||||
Copyright 2015 - 2021 Amish Shah
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
127
packages/discord.js/README.md
Normal file
127
packages/discord.js/README.md
Normal file
@@ -0,0 +1,127 @@
|
||||
<div align="center">
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.js.org"><img src="https://discord.js.org/static/logo.svg" width="546" alt="discord.js" /></a>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
|
||||
<a href="https://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>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the
|
||||
[Discord API](https://discord.com/developers/docs/intro).
|
||||
|
||||
- Object-oriented
|
||||
- Predictable abstractions
|
||||
- Performant
|
||||
- 100% coverage of the Discord API
|
||||
|
||||
## Installation
|
||||
|
||||
**Node.js 16.6.0 or newer is required.**
|
||||
|
||||
```sh-session
|
||||
npm install discord.js
|
||||
yarn add discord.js
|
||||
pnpm add discord.js
|
||||
```
|
||||
|
||||
### Optional packages
|
||||
|
||||
- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
|
||||
- [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`)
|
||||
|
||||
## Example usage
|
||||
|
||||
Install all required dependencies:
|
||||
|
||||
```sh-session
|
||||
npm install discord.js @discordjs/rest discord-api-types
|
||||
yarn add discord.js @discordjs/rest discord-api-types
|
||||
pnpm add discord.js @discordjs/rest discord-api-types
|
||||
```
|
||||
|
||||
Register a slash command against the Discord API:
|
||||
|
||||
```js
|
||||
const { REST } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v9');
|
||||
|
||||
const commands = [
|
||||
{
|
||||
name: 'ping',
|
||||
description: 'Replies with Pong!',
|
||||
},
|
||||
];
|
||||
|
||||
const rest = new REST({ version: '9' }).setToken('token');
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
console.log('Started refreshing application (/) commands.');
|
||||
|
||||
await rest.put(Routes.applicationGuildCommands(CLIENT_ID, GUILD_ID), { body: commands });
|
||||
|
||||
console.log('Successfully reloaded application (/) commands.');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
})();
|
||||
```
|
||||
|
||||
Afterwards we can create a quite simple example bot:
|
||||
|
||||
```js
|
||||
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');
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website))
|
||||
- [Documentation](https://discord.js.org/#/docs)
|
||||
- [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide))
|
||||
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/discord.js)
|
||||
- [npm](https://www.npmjs.com/package/discord.js)
|
||||
- [Related libraries](https://discord.com/developers/docs/topics/community-resources#libraries)
|
||||
|
||||
### Extensions
|
||||
|
||||
- [RPC](https://www.npmjs.com/package/discord-rpc) ([source](https://github.com/discordjs/RPC))
|
||||
|
||||
## 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).
|
||||
See [the contribution guide](https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md) if you'd like to submit a PR.
|
||||
|
||||
## Help
|
||||
|
||||
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
|
||||
nudge in the right direction, please don't hesitate to join our official [discord.js Server](https://discord.gg/djs).
|
||||
1
packages/discord.js/docs/README.md
Normal file
1
packages/discord.js/docs/README.md
Normal file
@@ -0,0 +1 @@
|
||||
## [View the documentation here.](https://discord.js.org/#/docs)
|
||||
5
packages/discord.js/docs/index.yml
Normal file
5
packages/discord.js/docs/index.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
- name: General
|
||||
files:
|
||||
- name: Welcome
|
||||
id: welcome
|
||||
path: ../../README.md
|
||||
19
packages/discord.js/docs/logo.svg
Normal file
19
packages/discord.js/docs/logo.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100%" width="100%" viewBox="0 0 6111.4378 1102.9827">
|
||||
<g transform="translate(2539.6 -107.66)">
|
||||
<g id="logo-discord" fill="#3d3f42" transform="translate(-44.194 1175.6)">
|
||||
<path d="m-2495.4-1051.4v453.6 453.6l145.75-.37695c127.36-.3288 147.71-.58582 161.25-2.041 45.045-4.8398 76.353-11.233 111.79-22.826 44.217-14.465 83.672-35.567 118.71-63.49 13.615-10.851 40.444-37.567 50.889-50.674 37.186-46.665 61.816-98.191 78.01-163.2 23.57-94.614 23.154-219.66-1.0469-313.5-41.72-161.77-155.27-260-329.35-284.92-38.756-5.5479-34.464-5.4161-190.75-5.8086l-145.25-.3652zm161 130.09 41.75.0156c55.334.0205 78.397 1.6295 108.25 7.5566 105.75 20.995 171.57 87.554 196.39 198.59 12.878 57.6 14.716 139.6 4.5469 202.81-7.3952 45.963-21.469 87.286-40.711 119.53-12.041 20.179-33.82 45.681-51 59.719-38.627 31.563-87.98 50.255-148.73 56.326-9.5463.9541-32.361 1.7291-62.75 2.1328l-47.75.63477v-323.66-323.66z"/>
|
||||
<path d="m-1631.4-597.85v-453.5h80.5 80.5v453.5 453.5h-80.5-80.5v-453.5z"/>
|
||||
<path d="m-1008.4-128.41c-96.325-5.9603-189.36-41.918-264.54-102.25-15.565-12.49-33-28.526-33-30.352 0-.7224 20.622-25.63 45.826-55.351l45.826-54.038 3.8214 3.2697c17.83 15.256 22.538 19.151 29.616 24.501 48.673 36.79 103.35 61.169 158.92 70.862 18.387 3.2073 54.666 4.419 74.088 2.4745 41.751-4.1802 74.798-17.199 96.864-38.16 10.213-9.7012 15.896-17.429 21.626-29.408 17.4-36.376 13.152-81.77-10.39-111-16.357-20.31-45.054-37.907-98.696-60.521-41.654-17.56-164.15-71.537-176.19-77.638-85.541-43.335-134.63-104.27-148.9-184.84-2.6851-15.162-3.7276-49.931-1.9989-66.666 7.4631-72.25 48.261-136.63 113.09-178.46 41.81-26.976 88.546-43.103 144.99-50.03 20.52-2.5182 67.722-2.5268 88-.016 74.352 9.2063 141.74 36.296 199 79.999 18.772 14.327 37.632 31.435 36.864 33.44-.2001.52235-18.812 23.693-41.361 51.49l-40.997 50.54-3.503-2.9264c-1.9267-1.6095-9.4625-7.4505-16.746-12.98-44.158-33.522-88.429-52.307-140.26-59.513-17.665-2.4562-54.274-2.4782-70-.042-35.82 5.5488-61.303 16.869-80.113 35.588-17.506 17.422-26.238 37.587-27.528 63.576-1.3118 26.419 6.521 48.306 24.066 67.249 17.834 19.254 45.314 35.115 99.448 57.398 32.211 13.259 137.3 57.517 151.65 63.864 47.003 20.795 80.577 42.726 108.49 70.87 43.959 44.316 64.938 98.562 65.021 168.13.053 44.646-7.8058 78.816-26.734 116.23-12.46 24.632-27.741 45.114-49.45 66.28-51.458 50.172-122.59 79.937-208.86 87.392-17.502 1.5126-51.786 2.0335-67.962 1.0326z"/>
|
||||
<path d="m-155.84-128.44c-100.7-5.7557-190.26-44.562-257.1-111.4-58.171-58.171-98.098-136.72-116.41-229.01-13.522-68.153-15.549-148.4-5.5195-218.5 13.11-91.624 47.506-173.73 99.29-237 11.342-13.858 35.64-38.591 49.282-50.164 54.726-46.425 120.9-76.546 193.88-88.256 25.873-4.1511 37.999-5.0552 67.977-5.0681 28.858-.013 38.31.6981 60.5 4.5485 70.566 12.245 140.29 49.396 192.89 102.78l6.8911 6.9936-2.8911 3.4607c-1.59 1.9034-21.52 24.408-44.288 50.011l-41.397 46.551-10.103-9.0797c-40.998-36.846-79.308-56.146-125.89-63.421-13.826-2.1591-48.594-2.4422-62.711-.51067-51.945 7.1074-94.856 27.696-131.17 62.933-64.806 62.887-97.854 165.12-92.829 287.16 2.697 65.505 14.091 119.1 35.16 165.38 30.027 65.96 77.365 110.94 138.03 131.16 24.572 8.1885 46.583 11.525 76.026 11.525 45.839 0 83.431-9.665 120.81-31.062 19.559-11.195 45.837-32.314 63.267-50.848 3.7379-3.9745 7.1554-7.0833 7.5942-6.9085 1.3142.5236 88.109 97.158 88.109 98.098 0 2.0843-41.684 42.322-54 52.126-73.043 58.146-157.48 84.1-255.41 78.503z"/>
|
||||
<path d="m610.07-1067.8c-34.898-.056-47.464.862-75.232 5.4922-188.34 31.405-308.9 182.45-325.21 407.46-2.8044 38.675-2.2536 84.125 1.4941 123.38 9.2582 96.975 39.751 184.31 87.494 250.58 57.015 79.142 139.29 130.29 236.46 147 14.533 2.4988 40.496 5.3373 53.5 5.8496 147.12 5.7956 267.7-55.193 342.98-173.48 10.897-17.122 28.991-52.974 36.758-72.828 27.4-70.046 39.498-139.21 39.617-226.5.062-45.479-1.9339-73.343-7.9121-110.4-31.164-193.18-145.75-321-314.25-350.53-27.838-4.8789-41.445-5.9606-75.699-6.0156zm-1.4395 139.59c2.8062.0114 5.6199.0752 8.4395.19336 49.33 2.0671 91.449 18.361 127.46 49.305 12.954 11.133 20.363 19.102 31.482 33.861 40.99 54.409 62.709 125.93 66.582 219.25 4.5628 109.93-19.826 208.09-67.676 272.39-33.936 45.599-76.643 72.514-130.84 82.459-10.577 1.9408-50.92 2.8029-62 1.3242-74.694-9.9681-131.62-54.014-168.58-130.43-24.356-50.365-36.989-106.85-39.92-178.5-5.9652-145.81 37.791-262.31 118.61-315.79 33.933-22.452 74.357-34.245 116.45-34.074z"/>
|
||||
<path d="m1187.6-1051.4v453.54 453.54h80.5 80.5v-177.51-177.51l68.717.25585 68.719.25782 97.531 177.22 97.533 177.22 90.285.0273c85.686.0268 90.237-.0599 89.336-1.7207-.5222-.9625-49.147-86.08-108.05-189.15-58.906-103.07-106.98-187.52-106.83-187.67.1497-.14971 5.5455-2.31 11.99-4.8008 92.947-35.923 149.28-103.8 164.7-198.43 3.4973-21.47 4.3763-36.845 3.7539-65.688-.8444-39.124-4.5518-62.293-14.883-93.008-29.696-88.286-106.44-143.03-224.91-160.44-38.597-5.6719-28.81-5.4157-221.14-5.7871l-177.75-.3438zm161 128.95 84.25.37695c91.298.40795 95.375.61732 123.75 6.3809 23.495 4.7723 45.38 13.215 61 23.533 15.167 10.019 29.716 27.182 37.475 44.207 14.573 31.978 16.395 82.735 4.3301 120.62-6.6274 20.814-16.172 36.615-31.18 51.625-27.567 27.57-66.814 42.804-121.93 47.324-7.3903.60617-43.437 1.0508-85.25 1.0508h-72.445v-147.56-147.56z"/>
|
||||
<path d="m2014.6-1051.4v453.6 453.6l145.75-.37695c156.69-.4046 153.13-.29648 191.25-5.8008 38.321-5.5332 77.017-15.82 109.08-28.998 17.362-7.137 22.208-9.743 21.508-11.566-.3206-.8355-1.452-4.9721-2.5156-9.1914-3.4865-13.831-4.3718-23.482-3.7617-41.053.63-18.145 2.2913-27.3 7.7285-42.617 17.594-49.562 60.836-85.599 112.95-94.131 16.457-2.6941 38.955-1.8474 57.701 2.1719 3.6928.79178 3.1565 1.7476 11.26-20.041 27.066-72.775 38.169-169.68 30.476-265.97-14.239-178.25-95.276-299.81-236.97-355.47-33.122-13.01-69.539-22.404-108.45-27.975-38.756-5.5479-34.464-5.4161-190.75-5.8086l-145.25-.3652zm161 130.09 41.75.0156c55.334.0205 78.397 1.6295 108.25 7.5566 105.75 20.995 171.57 87.554 196.39 198.59 12.878 57.6 14.716 139.6 4.5469 202.81-7.3952 45.963-21.469 87.286-40.711 119.53-12.041 20.179-33.82 45.681-51 59.719-38.627 31.563-87.98 50.255-148.73 56.326-9.5463.9541-32.361 1.7291-62.75 2.1328l-47.75.63477v-323.66-323.66z"/>
|
||||
</g>
|
||||
<circle id="logo-dot" cx="2575.3" cy="939.96" r="125.4" fill="#499a6c"/>
|
||||
<g id="logo-js" fill="#33b5e5" transform="translate(-44.194 1175.6)">
|
||||
<path d="m2602.1 34.57c-57.094-4.6075-113.49-28.558-158.26-67.213-27.741-23.949-51.228-55.235-63.883-85.094-5.4804-12.93-5.926-15.992-2.3882-16.406 8.1404-.953 38.073-7.05 53.318-10.86 20.337-5.0831 29.827-8.2686 48.112-16.15 12.138-5.2318 12.996-5.46 14-3.7198 14.778 25.613 36.757 46.236 62.906 59.024 21.609 10.567 39.696 14.761 63.664 14.761 23.073 0 41.694-4.1466 61.73-13.746 36.584-17.528 62.542-46.884 75.844-85.772 2.3995-7.0151 7.5664-31.714 9.361-44.747 2.8753-20.881 3.0454-40.134 3.0555-345.75l.01-314.25h78 78v318.25c0 209.58-.3574 323.03-1.0389 332.25-4.4405 60.076-22.061 115.17-51.016 159.5-11.306 17.311-21.135 29.375-35.857 44.012-44.122 43.866-101.51 69.204-169.58 74.876-17.815 1.4842-53.463 2.0433-65.964 1.0344z"/>
|
||||
<path d="m3256.6 33.535c-103.92-8.2588-202.14-50.771-278.59-120.57l-11.459-10.464 4.7737-5.6963c2.6255-3.133 23.371-27.615 46.101-54.405l41.327-48.709 11.068 9.6086c54.856 47.624 120.13 79.074 185.78 89.508 19.275 3.0634 60.816 3.3389 79 .5237 56.007-8.6707 91.978-30.946 109.48-67.793 5.7814-12.174 8.6772-25.17 9.2639-41.574 1.8511-51.755-20.009-81.836-81.241-111.79-10.45-5.1123-25.75-12.128-34-15.591-32.568-13.67-168.23-73.282-178.56-78.459-84.895-42.577-136.19-105.76-149.34-183.97-24.654-146.62 80.068-271.29 246.91-293.93 39.105-5.3065 82.999-4.2183 122.48 3.0365 76.174 13.996 145.21 48.561 201.87 101.07l7.367 6.8275-39.699 49c-21.834 26.95-40.537 49.863-41.563 50.918-1.8327 1.8856-1.9536 1.8424-7.1685-2.562-25.013-21.126-59.394-41.952-87.804-53.188-33.742-13.345-63.677-18.968-101.5-19.066-28.062-.0727-45.321 2.2-65.5 8.6248-40.117 12.773-65.445 37.309-74.612 72.282-3.4331 13.097-3.8978 33.664-1.0368 45.883 7.6067 32.488 29.949 55.7 75.674 78.622 15.123 7.5809 24.021 11.522 52.974 23.46 125.45 51.728 173.58 73.274 198.67 88.935 70.314 43.888 106.41 97.76 116.97 174.59 2.1563 15.683 2.4444 55.002.5056 69-7.9359 57.297-31.186 104.9-70.626 144.6-53.439 53.792-126.37 84.242-218.91 91.402-14.98 1.1588-53.385 1.0944-68.605-.1152z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
82
packages/discord.js/package.json
Normal file
82
packages/discord.js/package.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"name": "discord.js",
|
||||
"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: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}",
|
||||
"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 './*'"
|
||||
},
|
||||
"main": "./src/index.js",
|
||||
"types": "./typings/index.d.ts",
|
||||
"directories": {
|
||||
"lib": "src",
|
||||
"test": "test"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"typings"
|
||||
],
|
||||
"contributors": [
|
||||
"Crawl <icrawltogo@gmail.com>",
|
||||
"Amish Shah <amishshah.2k@gmail.com>",
|
||||
"Vlad Frangu <kingdgrizzle@gmail.com>",
|
||||
"SpaceEEC <spaceeec@yahoo.com>",
|
||||
"Antonio Roman <kyradiscord@gmail.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"discord",
|
||||
"api",
|
||||
"bot",
|
||||
"client",
|
||||
"node",
|
||||
"discordapp"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/discordjs/discord.js.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/discordjs/discord.js/issues"
|
||||
},
|
||||
"homepage": "https://discord.js.org",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.11.0",
|
||||
"@discordjs/collection": "^0.4.0",
|
||||
"@sapphire/async-queue": "^1.1.9",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"@types/ws": "^8.2.2",
|
||||
"discord-api-types": "^0.26.0",
|
||||
"form-data": "^4.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"ws": "^8.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordjs/docgen": "^0.11.0",
|
||||
"@types/node": "^16.11.12",
|
||||
"dtslint": "^4.2.1",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"husky": "^7.0.4",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest": "^27.4.5",
|
||||
"lint-staged": "^12.1.4",
|
||||
"prettier": "^2.5.1",
|
||||
"tsd": "^0.19.0",
|
||||
"tslint": "^6.1.3",
|
||||
"typescript": "^4.5.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.6.0"
|
||||
}
|
||||
}
|
||||
6
packages/discord.js/scripts/.eslintrc.json
Normal file
6
packages/discord.js/scripts/.eslintrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../.eslintrc.json",
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
}
|
||||
}
|
||||
41
packages/discord.js/scripts/generateRequires.mjs
Normal file
41
packages/discord.js/scripts/generateRequires.mjs
Normal file
@@ -0,0 +1,41 @@
|
||||
import { readdir, writeFile } from 'node:fs/promises';
|
||||
import { Constants } from '../src/index.js';
|
||||
|
||||
async function writeWebsocketHandlerImports() {
|
||||
const lines = ["'use strict';\n", 'const handlers = Object.fromEntries(['];
|
||||
|
||||
for (const name of Object.keys(Constants.WSEvents)) {
|
||||
lines.push(` ['${name}', require('./${name}')],`);
|
||||
}
|
||||
|
||||
lines.push(']);\n\nmodule.exports = handlers;\n');
|
||||
|
||||
const outputFile = new URL('../src/client/websocket/handlers/index.js', import.meta.url);
|
||||
|
||||
await writeFile(outputFile, lines.join('\n'));
|
||||
}
|
||||
|
||||
async function writeClientActionImports() {
|
||||
const lines = ["'use strict';\n", 'class ActionsManager {', ' constructor(client) {', ' this.client = client;\n'];
|
||||
|
||||
const actionsDirectory = new URL('../src/client/actions', import.meta.url);
|
||||
for (const file of (await readdir(actionsDirectory)).sort()) {
|
||||
if (file === 'Action.js' || file === 'ActionsManager.js') continue;
|
||||
|
||||
lines.push(` this.register(require('./${file.slice(0, -3)}'));`);
|
||||
}
|
||||
|
||||
lines.push(' }\n');
|
||||
lines.push(' register(Action) {');
|
||||
lines.push(" this[Action.name.replace(/Action$/, '')] = new Action(this.client);");
|
||||
lines.push(' }');
|
||||
lines.push('}\n');
|
||||
lines.push('module.exports = ActionsManager;\n');
|
||||
|
||||
const outputFile = new URL('../src/client/actions/ActionsManager.js', import.meta.url);
|
||||
|
||||
await writeFile(outputFile, lines.join('\n'));
|
||||
}
|
||||
|
||||
writeWebsocketHandlerImports();
|
||||
writeClientActionImports();
|
||||
39
packages/discord.js/src/WebSocket.js
Normal file
39
packages/discord.js/src/WebSocket.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
let erlpack;
|
||||
const { Buffer } = require('node:buffer');
|
||||
|
||||
try {
|
||||
erlpack = require('erlpack');
|
||||
if (!erlpack.pack) erlpack = null;
|
||||
} catch {} // eslint-disable-line no-empty
|
||||
|
||||
exports.WebSocket = require('ws');
|
||||
|
||||
const ab = new TextDecoder();
|
||||
|
||||
exports.encoding = erlpack ? 'etf' : 'json';
|
||||
|
||||
exports.pack = erlpack ? erlpack.pack : JSON.stringify;
|
||||
|
||||
exports.unpack = (data, type) => {
|
||||
if (exports.encoding === 'json' || type === 'json') {
|
||||
if (typeof data !== 'string') {
|
||||
data = ab.decode(data);
|
||||
}
|
||||
return JSON.parse(data);
|
||||
}
|
||||
if (!Buffer.isBuffer(data)) data = Buffer.from(new Uint8Array(data));
|
||||
return erlpack.unpack(data);
|
||||
};
|
||||
|
||||
exports.create = (gateway, query = {}, ...args) => {
|
||||
const [g, q] = gateway.split('?');
|
||||
query.encoding = exports.encoding;
|
||||
query = new URLSearchParams(query);
|
||||
if (q) new URLSearchParams(q).forEach((v, k) => query.set(k, v));
|
||||
const ws = new exports.WebSocket(`${g}?${query}`, ...args);
|
||||
return ws;
|
||||
};
|
||||
|
||||
for (const state of ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']) exports[state] = exports.WebSocket[state];
|
||||
81
packages/discord.js/src/client/BaseClient.js
Normal file
81
packages/discord.js/src/client/BaseClient.js
Normal file
@@ -0,0 +1,81 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('node:events');
|
||||
const RESTManager = require('../rest/RESTManager');
|
||||
const Options = require('../util/Options');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* The base class for all clients.
|
||||
* @extends {EventEmitter}
|
||||
*/
|
||||
class BaseClient extends EventEmitter {
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* The options the client was instantiated with
|
||||
* @type {ClientOptions}
|
||||
*/
|
||||
this.options = Util.mergeDefault(Options.createDefault(), options);
|
||||
|
||||
/**
|
||||
* The REST manager of the client
|
||||
* @type {RESTManager}
|
||||
* @private
|
||||
*/
|
||||
this.rest = new RESTManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* API shortcut
|
||||
* @type {Object}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
get api() {
|
||||
return this.rest.api;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys all assets used by the base client.
|
||||
* @returns {void}
|
||||
*/
|
||||
destroy() {
|
||||
if (this.rest.sweepInterval) clearInterval(this.rest.sweepInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments max listeners by one, if they are not zero.
|
||||
* @private
|
||||
*/
|
||||
incrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements max listeners by one, if they are not zero.
|
||||
* @private
|
||||
*/
|
||||
decrementMaxListeners() {
|
||||
const maxListeners = this.getMaxListeners();
|
||||
if (maxListeners !== 0) {
|
||||
this.setMaxListeners(maxListeners - 1);
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(...props) {
|
||||
return Util.flatten(this, { domain: false }, ...props);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseClient;
|
||||
|
||||
/**
|
||||
* Emitted for general debugging information.
|
||||
* @event BaseClient#debug
|
||||
* @param {string} info The debug information
|
||||
*/
|
||||
621
packages/discord.js/src/client/Client.js
Normal file
621
packages/discord.js/src/client/Client.js
Normal file
@@ -0,0 +1,621 @@
|
||||
'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');
|
||||
const ClientVoiceManager = require('./voice/ClientVoiceManager');
|
||||
const WebSocketManager = require('./websocket/WebSocketManager');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
const BaseGuildEmojiManager = require('../managers/BaseGuildEmojiManager');
|
||||
const ChannelManager = require('../managers/ChannelManager');
|
||||
const GuildManager = require('../managers/GuildManager');
|
||||
const UserManager = require('../managers/UserManager');
|
||||
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
||||
const ClientPresence = require('../structures/ClientPresence');
|
||||
const GuildPreview = require('../structures/GuildPreview');
|
||||
const GuildTemplate = require('../structures/GuildTemplate');
|
||||
const Invite = require('../structures/Invite');
|
||||
const { Sticker } = require('../structures/Sticker');
|
||||
const StickerPack = require('../structures/StickerPack');
|
||||
const VoiceRegion = require('../structures/VoiceRegion');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const Widget = require('../structures/Widget');
|
||||
const { Events, InviteScopes, Status } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Intents = require('../util/Intents');
|
||||
const Options = require('../util/Options');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Sweepers = require('../util/Sweepers');
|
||||
|
||||
/**
|
||||
* The main hub for interacting with the Discord API, and the starting point for any bot.
|
||||
* @extends {BaseClient}
|
||||
*/
|
||||
class Client extends BaseClient {
|
||||
/**
|
||||
* @param {ClientOptions} options Options for the client
|
||||
*/
|
||||
constructor(options) {
|
||||
super(options);
|
||||
|
||||
const data = require('node:worker_threads').workerData ?? process.env;
|
||||
const defaults = Options.createDefault();
|
||||
|
||||
if (this.options.shards === defaults.shards) {
|
||||
if ('SHARDS' in data) {
|
||||
this.options.shards = JSON.parse(data.SHARDS);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.shardCount === defaults.shardCount) {
|
||||
if ('SHARD_COUNT' in data) {
|
||||
this.options.shardCount = Number(data.SHARD_COUNT);
|
||||
} else if (Array.isArray(this.options.shards)) {
|
||||
this.options.shardCount = this.options.shards.length;
|
||||
}
|
||||
}
|
||||
|
||||
const typeofShards = typeof this.options.shards;
|
||||
|
||||
if (typeofShards === 'undefined' && typeof this.options.shardCount === 'number') {
|
||||
this.options.shards = Array.from({ length: this.options.shardCount }, (_, i) => i);
|
||||
}
|
||||
|
||||
if (typeofShards === 'number') this.options.shards = [this.options.shards];
|
||||
|
||||
if (Array.isArray(this.options.shards)) {
|
||||
this.options.shards = [
|
||||
...new Set(
|
||||
this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
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}
|
||||
*/
|
||||
this.ws = new WebSocketManager(this);
|
||||
|
||||
/**
|
||||
* The action manager of the client
|
||||
* @type {ActionsManager}
|
||||
* @private
|
||||
*/
|
||||
this.actions = new ActionsManager(this);
|
||||
|
||||
/**
|
||||
* The voice manager of the client
|
||||
* @type {ClientVoiceManager}
|
||||
*/
|
||||
this.voice = new ClientVoiceManager(this);
|
||||
|
||||
/**
|
||||
* Shard helpers for the client (only if the process was spawned from a {@link ShardingManager})
|
||||
* @type {?ShardClientUtil}
|
||||
*/
|
||||
this.shard = process.env.SHARDING_MANAGER
|
||||
? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* All of the {@link User} objects that have been cached at any point, mapped by their ids
|
||||
* @type {UserManager}
|
||||
*/
|
||||
this.users = new UserManager(this);
|
||||
|
||||
/**
|
||||
* All of the guilds the client is currently handling, mapped by their ids -
|
||||
* as long as sharding isn't being used, this will be *every* guild the bot is a member of
|
||||
* @type {GuildManager}
|
||||
*/
|
||||
this.guilds = new GuildManager(this);
|
||||
|
||||
/**
|
||||
* All of the {@link Channel}s that the client is currently handling, mapped by their ids -
|
||||
* as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
|
||||
* is a member of. Note that DM channels will not be initially cached, and thus not be present
|
||||
* in the Manager without their explicit fetching or use.
|
||||
* @type {ChannelManager}
|
||||
*/
|
||||
this.channels = new ChannelManager(this);
|
||||
|
||||
/**
|
||||
* The sweeping functions and their intervals used to periodically sweep caches
|
||||
* @type {Sweepers}
|
||||
*/
|
||||
this.sweepers = new Sweepers(this, this.options.sweepers);
|
||||
|
||||
/**
|
||||
* The presence of the Client
|
||||
* @private
|
||||
* @type {ClientPresence}
|
||||
*/
|
||||
this.presence = new ClientPresence(this, this.options.presence);
|
||||
|
||||
Object.defineProperty(this, 'token', { writable: true });
|
||||
if (!this.token && 'DISCORD_TOKEN' in process.env) {
|
||||
/**
|
||||
* Authorization token for the logged in bot.
|
||||
* If present, this defaults to `process.env.DISCORD_TOKEN` when instantiating the client
|
||||
* <warn>This should be kept private at all times.</warn>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.token = process.env.DISCORD_TOKEN;
|
||||
} else {
|
||||
this.token = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* User that the client is logged in as
|
||||
* @type {?ClientUser}
|
||||
*/
|
||||
this.user = null;
|
||||
|
||||
/**
|
||||
* The application of this bot
|
||||
* @type {?ClientApplication}
|
||||
*/
|
||||
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}
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All custom emojis that the client has access to, mapped by their ids
|
||||
* @type {BaseGuildEmojiManager}
|
||||
* @readonly
|
||||
*/
|
||||
get emojis() {
|
||||
const emojis = new BaseGuildEmojiManager(this);
|
||||
for (const guild of this.guilds.cache.values()) {
|
||||
if (guild.available) for (const emoji of guild.emojis.cache.values()) emojis.cache.set(emoji.id, emoji);
|
||||
}
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp of the time the client was last `READY` at
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get readyTimestamp() {
|
||||
return this.readyAt?.getTime() ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* How long it has been since the client last entered the `READY` state in milliseconds
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get uptime() {
|
||||
return this.readyAt ? Date.now() - this.readyAt : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the client in, establishing a WebSocket connection to Discord.
|
||||
* @param {string} [token=this.token] Token of the account to log in with
|
||||
* @returns {Promise<string>} Token of the account used
|
||||
* @example
|
||||
* client.login('my token');
|
||||
*/
|
||||
async login(token = this.token) {
|
||||
if (!token || typeof token !== 'string') throw new Error('TOKEN_INVALID');
|
||||
this.token = token = token.replace(/^(Bot|Bearer)\s*/i, '');
|
||||
this.emit(
|
||||
Events.DEBUG,
|
||||
`Provided token: ${token
|
||||
.split('.')
|
||||
.map((val, i) => (i > 1 ? val.replace(/./g, '*') : val))
|
||||
.join('.')}`,
|
||||
);
|
||||
|
||||
if (this.options.presence) {
|
||||
this.options.ws.presence = this.presence._parse(this.options.presence);
|
||||
}
|
||||
|
||||
this.emit(Events.DEBUG, 'Preparing to connect to the gateway...');
|
||||
|
||||
try {
|
||||
await this.ws.connect();
|
||||
return this.token;
|
||||
} catch (error) {
|
||||
this.destroy();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the client has logged in, indicative of being able to access
|
||||
* properties such as `user` and `application`.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isReady() {
|
||||
return this.ws.status === Status.READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out, terminates the connection to Discord, and destroys the client.
|
||||
* @returns {void}
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used when fetching an invite from Discord.
|
||||
* @typedef {Object} ClientFetchInviteOptions
|
||||
* @property {Snowflake} [guildScheduledEventId] The id of the guild scheduled event to include with
|
||||
* the invite
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains an invite from Discord.
|
||||
* @param {InviteResolvable} invite Invite code or URL
|
||||
* @param {ClientFetchInviteOptions} [options] Options for fetching the invite
|
||||
* @returns {Promise<Invite>}
|
||||
* @example
|
||||
* client.fetchInvite('https://discord.gg/djs')
|
||||
* .then(invite => console.log(`Obtained invite with code: ${invite.code}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchInvite(invite, options) {
|
||||
const code = DataResolver.resolveInviteCode(invite);
|
||||
const data = await this.api.invites(code).get({
|
||||
query: { with_counts: true, with_expiration: true, guild_scheduled_event_id: options?.guildScheduledEventId },
|
||||
});
|
||||
return new Invite(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a template from Discord.
|
||||
* @param {GuildTemplateResolvable} template Template code or URL
|
||||
* @returns {Promise<GuildTemplate>}
|
||||
* @example
|
||||
* client.fetchGuildTemplate('https://discord.new/FKvmczH2HyUf')
|
||||
* .then(template => console.log(`Obtained template with code: ${template.code}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchGuildTemplate(template) {
|
||||
const code = DataResolver.resolveGuildTemplateCode(template);
|
||||
const data = await this.api.guilds.templates(code).get();
|
||||
return new GuildTemplate(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a webhook from Discord.
|
||||
* @param {Snowflake} id The webhook's id
|
||||
* @param {string} [token] Token for the webhook
|
||||
* @returns {Promise<Webhook>}
|
||||
* @example
|
||||
* client.fetchWebhook('id', 'token')
|
||||
* .then(webhook => console.log(`Obtained webhook with name: ${webhook.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchWebhook(id, token) {
|
||||
const data = await this.api.webhooks(id, token).get();
|
||||
return new Webhook(this, { token, ...data });
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the available voice regions from Discord.
|
||||
* @returns {Promise<Collection<string, VoiceRegion>>}
|
||||
* @example
|
||||
* client.fetchVoiceRegions()
|
||||
* .then(regions => console.log(`Available regions are: ${regions.map(region => region.name).join(', ')}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchVoiceRegions() {
|
||||
const apiRegions = await this.api.voice.regions.get();
|
||||
const regions = new Collection();
|
||||
for (const region of apiRegions) regions.set(region.id, new VoiceRegion(region));
|
||||
return regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a sticker from Discord.
|
||||
* @param {Snowflake} id The sticker's id
|
||||
* @returns {Promise<Sticker>}
|
||||
* @example
|
||||
* client.fetchSticker('id')
|
||||
* .then(sticker => console.log(`Obtained sticker with name: ${sticker.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchSticker(id) {
|
||||
const data = await this.api.stickers(id).get();
|
||||
return new Sticker(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the list of sticker packs available to Nitro subscribers from Discord.
|
||||
* @returns {Promise<Collection<Snowflake, StickerPack>>}
|
||||
* @example
|
||||
* client.fetchPremiumStickerPacks()
|
||||
* .then(packs => console.log(`Available sticker packs are: ${packs.map(pack => pack.name).join(', ')}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchPremiumStickerPacks() {
|
||||
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.
|
||||
* @param {GuildResolvable} guild The guild to fetch the preview for
|
||||
* @returns {Promise<GuildPreview>}
|
||||
*/
|
||||
async fetchGuildPreview(guild) {
|
||||
const id = this.guilds.resolveId(guild);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable');
|
||||
const data = await this.api.guilds(id).preview.get();
|
||||
return new GuildPreview(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the widget data of a guild from Discord, available for guilds with the widget enabled.
|
||||
* @param {GuildResolvable} guild The guild to fetch the widget data for
|
||||
* @returns {Promise<Widget>}
|
||||
*/
|
||||
async fetchGuildWidget(guild) {
|
||||
const id = this.guilds.resolveId(guild);
|
||||
if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable');
|
||||
const data = await this.api.guilds(id, 'widget.json').get();
|
||||
return new Widget(this, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for {@link Client#generateInvite}.
|
||||
* @typedef {Object} InviteGenerationOptions
|
||||
* @property {InviteScope[]} scopes Scopes that should be requested
|
||||
* @property {PermissionResolvable} [permissions] Permissions to request
|
||||
* @property {GuildResolvable} [guild] Guild to preselect
|
||||
* @property {boolean} [disableGuildSelect] Whether to disable the guild selection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates a link that can be used to invite the bot to a guild.
|
||||
* @param {InviteGenerationOptions} [options={}] Options for the invite
|
||||
* @returns {string}
|
||||
* @example
|
||||
* const link = client.generateInvite({
|
||||
* scopes: ['applications.commands'],
|
||||
* });
|
||||
* console.log(`Generated application invite link: ${link}`);
|
||||
* @example
|
||||
* const link = client.generateInvite({
|
||||
* permissions: [
|
||||
* Permissions.FLAGS.SEND_MESSAGES,
|
||||
* Permissions.FLAGS.MANAGE_GUILD,
|
||||
* Permissions.FLAGS.MENTION_EVERYONE,
|
||||
* ],
|
||||
* scopes: ['bot'],
|
||||
* });
|
||||
* console.log(`Generated bot invite link: ${link}`);
|
||||
*/
|
||||
generateInvite(options = {}) {
|
||||
if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
|
||||
if (!this.application) throw new Error('CLIENT_NOT_READY', 'generate an invite link');
|
||||
|
||||
const query = new URLSearchParams({
|
||||
client_id: this.application.id,
|
||||
});
|
||||
|
||||
const { scopes } = options;
|
||||
if (typeof scopes === 'undefined') {
|
||||
throw new TypeError('INVITE_MISSING_SCOPES');
|
||||
}
|
||||
if (!Array.isArray(scopes)) {
|
||||
throw new TypeError('INVALID_TYPE', 'scopes', 'Array of Invite Scopes', true);
|
||||
}
|
||||
if (!scopes.some(scope => ['bot', 'applications.commands'].includes(scope))) {
|
||||
throw new TypeError('INVITE_MISSING_SCOPES');
|
||||
}
|
||||
const invalidScope = scopes.find(scope => !InviteScopes.includes(scope));
|
||||
if (invalidScope) {
|
||||
throw new TypeError('INVALID_ELEMENT', 'Array', 'scopes', invalidScope);
|
||||
}
|
||||
query.set('scope', scopes.join(' '));
|
||||
|
||||
if (options.permissions) {
|
||||
const permissions = Permissions.resolve(options.permissions);
|
||||
if (permissions) query.set('permissions', permissions);
|
||||
}
|
||||
|
||||
if (options.disableGuildSelect) {
|
||||
query.set('disable_guild_select', true);
|
||||
}
|
||||
|
||||
if (options.guild) {
|
||||
const guildId = this.guilds.resolveId(options.guild);
|
||||
if (!guildId) throw new TypeError('INVALID_TYPE', 'options.guild', 'GuildResolvable');
|
||||
query.set('guild_id', guildId);
|
||||
}
|
||||
|
||||
return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({
|
||||
readyAt: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
|
||||
* with the client as `this`.
|
||||
* @param {string} script Script to eval
|
||||
* @returns {*}
|
||||
* @private
|
||||
*/
|
||||
_eval(script) {
|
||||
return eval(script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the client options.
|
||||
* @param {ClientOptions} [options=this.options] Options to validate
|
||||
* @private
|
||||
*/
|
||||
_validateOptions(options = this.options) {
|
||||
if (typeof options.intents === 'undefined') {
|
||||
throw new TypeError('CLIENT_MISSING_INTENTS');
|
||||
} else {
|
||||
options.intents = Intents.resolve(options.intents);
|
||||
}
|
||||
if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1');
|
||||
}
|
||||
if (options.shards && !(options.shards === 'auto' || Array.isArray(options.shards))) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers");
|
||||
}
|
||||
if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS');
|
||||
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');
|
||||
}
|
||||
if (typeof options.invalidRequestWarningInterval !== 'number' || isNaN(options.invalidRequestWarningInterval)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'invalidRequestWarningInterval', 'a number');
|
||||
}
|
||||
if (!Array.isArray(options.partials)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array');
|
||||
}
|
||||
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');
|
||||
}
|
||||
if (typeof options.restGlobalRateLimit !== 'number' || isNaN(options.restGlobalRateLimit)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'restGlobalRateLimit', 'a number');
|
||||
}
|
||||
if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number');
|
||||
}
|
||||
if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number');
|
||||
}
|
||||
if (typeof options.failIfNotExists !== 'boolean') {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'failIfNotExists', 'a boolean');
|
||||
}
|
||||
if (!Array.isArray(options.userAgentSuffix)) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'userAgentSuffix', 'an array of strings');
|
||||
}
|
||||
if (
|
||||
typeof options.rejectOnRateLimit !== 'undefined' &&
|
||||
!(typeof options.rejectOnRateLimit === 'function' || Array.isArray(options.rejectOnRateLimit))
|
||||
) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'rejectOnRateLimit', 'an array or a function');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Client;
|
||||
|
||||
/**
|
||||
* Emitted for general warnings.
|
||||
* @event Client#warn
|
||||
* @param {string} info The warning
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Collection
|
||||
* @see {@link https://discord.js.org/#/docs/collection/main/class/Collection}
|
||||
*/
|
||||
61
packages/discord.js/src/client/WebhookClient.js
Normal file
61
packages/discord.js/src/client/WebhookClient.js
Normal file
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
const BaseClient = require('./BaseClient');
|
||||
const { Error } = require('../errors');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
|
||||
/**
|
||||
* The webhook client.
|
||||
* @implements {Webhook}
|
||||
* @extends {BaseClient}
|
||||
*/
|
||||
class WebhookClient extends BaseClient {
|
||||
/**
|
||||
* The data for the webhook client containing either an id and token or just a URL
|
||||
* @typedef {Object} WebhookClientData
|
||||
* @property {Snowflake} [id] The id of the webhook
|
||||
* @property {string} [token] The token of the webhook
|
||||
* @property {string} [url] The full URL for the webhook client
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {WebhookClientData} data The data of the webhook
|
||||
* @param {ClientOptions} [options] Options for the client
|
||||
*/
|
||||
constructor(data, options) {
|
||||
super(options);
|
||||
Object.defineProperty(this, 'client', { value: this });
|
||||
let { id, token } = data;
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
if (!url || url.length <= 1) throw new Error('WEBHOOK_URL_INVALID');
|
||||
|
||||
[, id, token] = url;
|
||||
}
|
||||
|
||||
this.id = id;
|
||||
Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by Webhook
|
||||
/* eslint-disable no-empty-function */
|
||||
send() {}
|
||||
sendSlackMessage() {}
|
||||
fetchMessage() {}
|
||||
edit() {}
|
||||
editMessage() {}
|
||||
delete() {}
|
||||
deleteMessage() {}
|
||||
get createdTimestamp() {}
|
||||
get createdAt() {}
|
||||
get url() {}
|
||||
}
|
||||
|
||||
Webhook.applyToClass(WebhookClient);
|
||||
|
||||
module.exports = WebhookClient;
|
||||
115
packages/discord.js/src/client/actions/Action.js
Normal file
115
packages/discord.js/src/client/actions/Action.js
Normal file
@@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
const { PartialTypes } = require('../../util/Constants');
|
||||
|
||||
/*
|
||||
|
||||
ABOUT ACTIONS
|
||||
|
||||
Actions are similar to WebSocket Packet Handlers, but since introducing
|
||||
the REST API methods, in order to prevent rewriting code to handle data,
|
||||
"actions" have been introduced. They're basically what Packet Handlers
|
||||
used to be but they're strictly for manipulating data and making sure
|
||||
that WebSocket events don't clash with REST methods.
|
||||
|
||||
*/
|
||||
|
||||
class GenericAction {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
handle(data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
getPayload(data, manager, id, partialType, cache) {
|
||||
const existing = manager.cache.get(id);
|
||||
if (!existing && this.client.options.partials.includes(partialType)) {
|
||||
return manager._add(data, cache);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
getChannel(data) {
|
||||
const id = data.channel_id ?? data.id;
|
||||
return (
|
||||
data.channel ??
|
||||
this.getPayload(
|
||||
{
|
||||
id,
|
||||
guild_id: data.guild_id,
|
||||
recipients: [data.author ?? data.user ?? { id: data.user_id }],
|
||||
},
|
||||
this.client.channels,
|
||||
id,
|
||||
PartialTypes.CHANNEL,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getMessage(data, channel, cache) {
|
||||
const id = data.message_id ?? data.id;
|
||||
return (
|
||||
data.message ??
|
||||
this.getPayload(
|
||||
{
|
||||
id,
|
||||
channel_id: channel.id,
|
||||
guild_id: data.guild_id ?? channel.guild?.id,
|
||||
},
|
||||
channel.messages,
|
||||
id,
|
||||
PartialTypes.MESSAGE,
|
||||
cache,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getReaction(data, message, user) {
|
||||
const id = data.emoji.id ?? decodeURIComponent(data.emoji.name);
|
||||
return this.getPayload(
|
||||
{
|
||||
emoji: data.emoji,
|
||||
count: message.partial ? null : 0,
|
||||
me: user?.id === this.client.user.id,
|
||||
},
|
||||
message.reactions,
|
||||
id,
|
||||
PartialTypes.REACTION,
|
||||
);
|
||||
}
|
||||
|
||||
getMember(data, guild) {
|
||||
return this.getPayload(data, guild.members, data.user.id, PartialTypes.GUILD_MEMBER);
|
||||
}
|
||||
|
||||
getUser(data) {
|
||||
const id = data.user_id;
|
||||
return data.user ?? this.getPayload({ id }, this.client.users, id, PartialTypes.USER);
|
||||
}
|
||||
|
||||
getUserFromMember(data) {
|
||||
if (data.guild_id && data.member?.user) {
|
||||
const guild = this.client.guilds.cache.get(data.guild_id);
|
||||
if (guild) {
|
||||
return guild.members._add(data.member).user;
|
||||
} else {
|
||||
return this.client.users._add(data.member.user);
|
||||
}
|
||||
}
|
||||
return this.getUser(data);
|
||||
}
|
||||
|
||||
getScheduledEvent(data, guild) {
|
||||
const id = data.guild_scheduled_event_id ?? data.id;
|
||||
return this.getPayload(
|
||||
{ id, guild_id: data.guild_id ?? guild.id },
|
||||
guild.scheduledEvents,
|
||||
id,
|
||||
PartialTypes.GUILD_SCHEDULED_EVENT,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GenericAction;
|
||||
66
packages/discord.js/src/client/actions/ActionsManager.js
Normal file
66
packages/discord.js/src/client/actions/ActionsManager.js
Normal file
@@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
class ActionsManager {
|
||||
constructor(client) {
|
||||
this.client = client;
|
||||
|
||||
this.register(require('./ChannelCreate'));
|
||||
this.register(require('./ChannelDelete'));
|
||||
this.register(require('./ChannelUpdate'));
|
||||
this.register(require('./GuildBanAdd'));
|
||||
this.register(require('./GuildBanRemove'));
|
||||
this.register(require('./GuildChannelsPositionUpdate'));
|
||||
this.register(require('./GuildDelete'));
|
||||
this.register(require('./GuildEmojiCreate'));
|
||||
this.register(require('./GuildEmojiDelete'));
|
||||
this.register(require('./GuildEmojiUpdate'));
|
||||
this.register(require('./GuildEmojisUpdate'));
|
||||
this.register(require('./GuildIntegrationsUpdate'));
|
||||
this.register(require('./GuildMemberRemove'));
|
||||
this.register(require('./GuildMemberUpdate'));
|
||||
this.register(require('./GuildRoleCreate'));
|
||||
this.register(require('./GuildRoleDelete'));
|
||||
this.register(require('./GuildRoleUpdate'));
|
||||
this.register(require('./GuildRolesPositionUpdate'));
|
||||
this.register(require('./GuildScheduledEventCreate'));
|
||||
this.register(require('./GuildScheduledEventDelete'));
|
||||
this.register(require('./GuildScheduledEventUpdate'));
|
||||
this.register(require('./GuildScheduledEventUserAdd'));
|
||||
this.register(require('./GuildScheduledEventUserRemove'));
|
||||
this.register(require('./GuildStickerCreate'));
|
||||
this.register(require('./GuildStickerDelete'));
|
||||
this.register(require('./GuildStickerUpdate'));
|
||||
this.register(require('./GuildStickersUpdate'));
|
||||
this.register(require('./GuildUpdate'));
|
||||
this.register(require('./InteractionCreate'));
|
||||
this.register(require('./InviteCreate'));
|
||||
this.register(require('./InviteDelete'));
|
||||
this.register(require('./MessageCreate'));
|
||||
this.register(require('./MessageDelete'));
|
||||
this.register(require('./MessageDeleteBulk'));
|
||||
this.register(require('./MessageReactionAdd'));
|
||||
this.register(require('./MessageReactionRemove'));
|
||||
this.register(require('./MessageReactionRemoveAll'));
|
||||
this.register(require('./MessageReactionRemoveEmoji'));
|
||||
this.register(require('./MessageUpdate'));
|
||||
this.register(require('./PresenceUpdate'));
|
||||
this.register(require('./StageInstanceCreate'));
|
||||
this.register(require('./StageInstanceDelete'));
|
||||
this.register(require('./StageInstanceUpdate'));
|
||||
this.register(require('./ThreadCreate'));
|
||||
this.register(require('./ThreadDelete'));
|
||||
this.register(require('./ThreadListSync'));
|
||||
this.register(require('./ThreadMemberUpdate'));
|
||||
this.register(require('./ThreadMembersUpdate'));
|
||||
this.register(require('./TypingStart'));
|
||||
this.register(require('./UserUpdate'));
|
||||
this.register(require('./VoiceStateUpdate'));
|
||||
this.register(require('./WebhooksUpdate'));
|
||||
}
|
||||
|
||||
register(Action) {
|
||||
this[Action.name.replace(/Action$/, '')] = new Action(this.client);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ActionsManager;
|
||||
23
packages/discord.js/src/client/actions/ChannelCreate.js
Normal file
23
packages/discord.js/src/client/actions/ChannelCreate.js
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class ChannelCreateAction extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const existing = client.channels.cache.has(data.id);
|
||||
const channel = client.channels._add(data);
|
||||
if (!existing && channel) {
|
||||
/**
|
||||
* Emitted whenever a guild channel is created.
|
||||
* @event Client#channelCreate
|
||||
* @param {GuildChannel} channel The channel that was created
|
||||
*/
|
||||
client.emit(Events.CHANNEL_CREATE, channel);
|
||||
}
|
||||
return { channel };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelCreateAction;
|
||||
39
packages/discord.js/src/client/actions/ChannelDelete.js
Normal file
39
packages/discord.js/src/client/actions/ChannelDelete.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'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
|
||||
* @param {DMChannel|GuildChannel} channel The channel that was deleted
|
||||
*/
|
||||
client.emit(Events.CHANNEL_DELETE, channel);
|
||||
}
|
||||
|
||||
return { channel };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelDeleteAction;
|
||||
34
packages/discord.js/src/client/actions/ChannelUpdate.js
Normal file
34
packages/discord.js/src/client/actions/ChannelUpdate.js
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Channel } = require('../../structures/Channel');
|
||||
const { ChannelTypes } = require('../../util/Constants');
|
||||
|
||||
class ChannelUpdateAction extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
|
||||
let channel = client.channels.cache.get(data.id);
|
||||
if (channel) {
|
||||
const old = channel._update(data);
|
||||
|
||||
if (ChannelTypes[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;
|
||||
this.client.channels.cache.set(channel.id, channel);
|
||||
}
|
||||
|
||||
return {
|
||||
old,
|
||||
updated: channel,
|
||||
};
|
||||
} else {
|
||||
client.channels._add(data);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelUpdateAction;
|
||||
20
packages/discord.js/src/client/actions/GuildBanAdd.js
Normal file
20
packages/discord.js/src/client/actions/GuildBanAdd.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildBanAdd extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
|
||||
/**
|
||||
* Emitted whenever a member is banned from a guild.
|
||||
* @event Client#guildBanAdd
|
||||
* @param {GuildBan} ban The ban that occurred
|
||||
*/
|
||||
if (guild) client.emit(Events.GUILD_BAN_ADD, guild.bans._add(data));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildBanAdd;
|
||||
25
packages/discord.js/src/client/actions/GuildBanRemove.js
Normal file
25
packages/discord.js/src/client/actions/GuildBanRemove.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const GuildBan = require('../../structures/GuildBan');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildBanRemove extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
|
||||
/**
|
||||
* Emitted whenever a member is unbanned from a guild.
|
||||
* @event Client#guildBanRemove
|
||||
* @param {GuildBan} ban The ban that was removed
|
||||
*/
|
||||
if (guild) {
|
||||
const ban = guild.bans.cache.get(data.user.id) ?? new GuildBan(client, data, guild);
|
||||
guild.bans.cache.delete(ban.user.id);
|
||||
client.emit(Events.GUILD_BAN_REMOVE, ban);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildBanRemove;
|
||||
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
|
||||
class GuildChannelsPositionUpdate extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
if (guild) {
|
||||
for (const partialChannel of data.channels) {
|
||||
const channel = guild.channels.cache.get(partialChannel.id);
|
||||
if (channel) channel.rawPosition = partialChannel.position;
|
||||
}
|
||||
}
|
||||
|
||||
return { guild };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannelsPositionUpdate;
|
||||
65
packages/discord.js/src/client/actions/GuildDelete.js
Normal file
65
packages/discord.js/src/client/actions/GuildDelete.js
Normal file
@@ -0,0 +1,65 @@
|
||||
'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;
|
||||
|
||||
let guild = client.guilds.cache.get(data.id);
|
||||
if (guild) {
|
||||
if (data.unavailable) {
|
||||
// Guild is unavailable
|
||||
guild.available = false;
|
||||
|
||||
/**
|
||||
* Emitted whenever a guild becomes unavailable, likely due to a server outage.
|
||||
* @event Client#guildUnavailable
|
||||
* @param {Guild} guild The guild that has become unavailable
|
||||
*/
|
||||
client.emit(Events.GUILD_UNAVAILABLE, guild);
|
||||
|
||||
// Stops the GuildDelete packet thinking a guild was actually deleted,
|
||||
// handles emitting of event itself
|
||||
return {
|
||||
guild: null,
|
||||
};
|
||||
}
|
||||
|
||||
for (const channel of guild.channels.cache.values()) this.client.channels._remove(channel.id);
|
||||
client.voice.adapters.get(data.id)?.destroy();
|
||||
|
||||
// Delete guild
|
||||
client.guilds.cache.delete(guild.id);
|
||||
deletedGuilds.add(guild);
|
||||
|
||||
/**
|
||||
* Emitted whenever a guild kicks the client or the guild is deleted/left.
|
||||
* @event Client#guildDelete
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildDeleteAction;
|
||||
20
packages/discord.js/src/client/actions/GuildEmojiCreate.js
Normal file
20
packages/discord.js/src/client/actions/GuildEmojiCreate.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildEmojiCreateAction extends Action {
|
||||
handle(guild, createdEmoji) {
|
||||
const already = guild.emojis.cache.has(createdEmoji.id);
|
||||
const emoji = guild.emojis._add(createdEmoji);
|
||||
/**
|
||||
* Emitted whenever a custom emoji is created in a guild.
|
||||
* @event Client#emojiCreate
|
||||
* @param {GuildEmoji} emoji The emoji that was created
|
||||
*/
|
||||
if (!already) this.client.emit(Events.GUILD_EMOJI_CREATE, emoji);
|
||||
return { emoji };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiCreateAction;
|
||||
21
packages/discord.js/src/client/actions/GuildEmojiDelete.js
Normal file
21
packages/discord.js/src/client/actions/GuildEmojiDelete.js
Normal file
@@ -0,0 +1,21 @@
|
||||
'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
|
||||
* @param {GuildEmoji} emoji The emoji that was deleted
|
||||
*/
|
||||
this.client.emit(Events.GUILD_EMOJI_DELETE, emoji);
|
||||
return { emoji };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiDeleteAction;
|
||||
20
packages/discord.js/src/client/actions/GuildEmojiUpdate.js
Normal file
20
packages/discord.js/src/client/actions/GuildEmojiUpdate.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildEmojiUpdateAction extends Action {
|
||||
handle(current, data) {
|
||||
const old = current._update(data);
|
||||
/**
|
||||
* Emitted whenever a custom emoji is updated in a guild.
|
||||
* @event Client#emojiUpdate
|
||||
* @param {GuildEmoji} oldEmoji The old emoji
|
||||
* @param {GuildEmoji} newEmoji The new emoji
|
||||
*/
|
||||
this.client.emit(Events.GUILD_EMOJI_UPDATE, old, current);
|
||||
return { emoji: current };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiUpdateAction;
|
||||
34
packages/discord.js/src/client/actions/GuildEmojisUpdate.js
Normal file
34
packages/discord.js/src/client/actions/GuildEmojisUpdate.js
Normal file
@@ -0,0 +1,34 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
|
||||
class GuildEmojisUpdateAction extends Action {
|
||||
handle(data) {
|
||||
const guild = this.client.guilds.cache.get(data.guild_id);
|
||||
if (!guild?.emojis) return;
|
||||
|
||||
const deletions = new Map(guild.emojis.cache);
|
||||
|
||||
for (const emoji of data.emojis) {
|
||||
// Determine type of emoji event
|
||||
const cachedEmoji = guild.emojis.cache.get(emoji.id);
|
||||
if (cachedEmoji) {
|
||||
deletions.delete(emoji.id);
|
||||
if (!cachedEmoji.equals(emoji)) {
|
||||
// Emoji updated
|
||||
this.client.actions.GuildEmojiUpdate.handle(cachedEmoji, emoji);
|
||||
}
|
||||
} else {
|
||||
// Emoji added
|
||||
this.client.actions.GuildEmojiCreate.handle(guild, emoji);
|
||||
}
|
||||
}
|
||||
|
||||
for (const emoji of deletions.values()) {
|
||||
// Emoji deleted
|
||||
this.client.actions.GuildEmojiDelete.handle(emoji);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojisUpdateAction;
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildIntegrationsUpdate extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
/**
|
||||
* Emitted whenever a guild integration is updated
|
||||
* @event Client#guildIntegrationsUpdate
|
||||
* @param {Guild} guild The guild whose integrations were updated
|
||||
*/
|
||||
if (guild) client.emit(Events.GUILD_INTEGRATIONS_UPDATE, guild);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildIntegrationsUpdate;
|
||||
31
packages/discord.js/src/client/actions/GuildMemberRemove.js
Normal file
31
packages/discord.js/src/client/actions/GuildMemberRemove.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { deletedGuildMembers } = require('../../structures/GuildMember');
|
||||
const { Events, Status } = require('../../util/Constants');
|
||||
|
||||
class GuildMemberRemoveAction extends Action {
|
||||
handle(data, shard) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
let member = null;
|
||||
if (guild) {
|
||||
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.
|
||||
* @event Client#guildMemberRemove
|
||||
* @param {GuildMember} member The member that has left/been kicked from the guild
|
||||
*/
|
||||
if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_REMOVE, member);
|
||||
}
|
||||
guild.voiceStates.cache.delete(data.user.id);
|
||||
}
|
||||
return { guild, member };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberRemoveAction;
|
||||
43
packages/discord.js/src/client/actions/GuildMemberUpdate.js
Normal file
43
packages/discord.js/src/client/actions/GuildMemberUpdate.js
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Status, Events } = require('../../util/Constants');
|
||||
|
||||
class GuildMemberUpdateAction extends Action {
|
||||
handle(data, shard) {
|
||||
const { client } = this;
|
||||
if (data.user.username) {
|
||||
const user = client.users.cache.get(data.user.id);
|
||||
if (!user) {
|
||||
client.users._add(data.user);
|
||||
} else if (!user._equals(data.user)) {
|
||||
client.actions.UserUpdate.handle(data.user);
|
||||
}
|
||||
}
|
||||
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
if (guild) {
|
||||
const member = this.getMember({ user: data.user }, guild);
|
||||
if (member) {
|
||||
const old = member._update(data);
|
||||
/**
|
||||
* Emitted whenever a guild member changes - i.e. new role, removed role, nickname.
|
||||
* @event Client#guildMemberUpdate
|
||||
* @param {GuildMember} oldMember The member before the update
|
||||
* @param {GuildMember} newMember The member after the update
|
||||
*/
|
||||
if (shard.status === Status.READY && !member.equals(old)) client.emit(Events.GUILD_MEMBER_UPDATE, old, member);
|
||||
} else {
|
||||
const newMember = guild.members._add(data);
|
||||
/**
|
||||
* Emitted whenever a member becomes available in a large guild.
|
||||
* @event Client#guildMemberAvailable
|
||||
* @param {GuildMember} member The member that became available
|
||||
*/
|
||||
this.client.emit(Events.GUILD_MEMBER_AVAILABLE, newMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberUpdateAction;
|
||||
25
packages/discord.js/src/client/actions/GuildRoleCreate.js
Normal file
25
packages/discord.js/src/client/actions/GuildRoleCreate.js
Normal file
@@ -0,0 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildRoleCreate extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
let role;
|
||||
if (guild) {
|
||||
const already = guild.roles.cache.has(data.role.id);
|
||||
role = guild.roles._add(data.role);
|
||||
/**
|
||||
* Emitted whenever a role is created.
|
||||
* @event Client#roleCreate
|
||||
* @param {Role} role The role that was created
|
||||
*/
|
||||
if (!already) client.emit(Events.GUILD_ROLE_CREATE, role);
|
||||
}
|
||||
return { role };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildRoleCreate;
|
||||
31
packages/discord.js/src/client/actions/GuildRoleDelete.js
Normal file
31
packages/discord.js/src/client/actions/GuildRoleDelete.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { deletedRoles } = require('../../structures/Role');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildRoleDeleteAction extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
let role;
|
||||
|
||||
if (guild) {
|
||||
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
|
||||
* @param {Role} role The role that was deleted
|
||||
*/
|
||||
client.emit(Events.GUILD_ROLE_DELETE, role);
|
||||
}
|
||||
}
|
||||
|
||||
return { role };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildRoleDeleteAction;
|
||||
39
packages/discord.js/src/client/actions/GuildRoleUpdate.js
Normal file
39
packages/discord.js/src/client/actions/GuildRoleUpdate.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class GuildRoleUpdateAction extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
|
||||
if (guild) {
|
||||
let old = null;
|
||||
|
||||
const role = guild.roles.cache.get(data.role.id);
|
||||
if (role) {
|
||||
old = role._update(data.role);
|
||||
/**
|
||||
* Emitted whenever a guild role is updated.
|
||||
* @event Client#roleUpdate
|
||||
* @param {Role} oldRole The role before the update
|
||||
* @param {Role} newRole The role after the update
|
||||
*/
|
||||
client.emit(Events.GUILD_ROLE_UPDATE, old, role);
|
||||
}
|
||||
|
||||
return {
|
||||
old,
|
||||
updated: role,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
old: null,
|
||||
updated: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildRoleUpdateAction;
|
||||
@@ -0,0 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
|
||||
class GuildRolesPositionUpdate extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
if (guild) {
|
||||
for (const partialRole of data.roles) {
|
||||
const role = guild.roles.cache.get(partialRole.id);
|
||||
if (role) role.rawPosition = partialRole.position;
|
||||
}
|
||||
}
|
||||
|
||||
return { guild };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildRolesPositionUpdate;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user