commit
This commit is contained in:
parent
a15c733e45
commit
2a5130cbda
2838 changed files with 288613 additions and 0 deletions
164
node_modules/@discordjs/rest/CHANGELOG.md
generated
vendored
Normal file
164
node_modules/@discordjs/rest/CHANGELOG.md
generated
vendored
Normal file
|
@ -0,0 +1,164 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [@discordjs/rest@1.5.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.4.0...@discordjs/rest@1.5.0) - (2022-12-16)
|
||||
|
||||
## Features
|
||||
|
||||
- **core:** Add support for role connections (#8930) ([3d6fa24](https://github.com/discordjs/discord.js/commit/3d6fa248c07b2278504bbe8bafa17a3294971fd9))
|
||||
|
||||
# [@discordjs/rest@1.4.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.3.0...@discordjs/rest@1.4.0) - (2022-11-28)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **SequentialHandler:** Downlevel ECONNRESET errors (#8785) ([5a70057](https://github.com/discordjs/discord.js/commit/5a70057826b47fb8251f3d836a536de689444ca1))
|
||||
- Make ratelimit timeout require event loop to be active (#8779) ([68d5712](https://github.com/discordjs/discord.js/commit/68d5712deae85532604d93b4505f0953d664cde7))
|
||||
- Pin @types/node version ([9d8179c](https://github.com/discordjs/discord.js/commit/9d8179c6a78e1c7f9976f852804055964d5385d4))
|
||||
|
||||
## Features
|
||||
|
||||
- Add `@discordjs/core` (#8736) ([2127b32](https://github.com/discordjs/discord.js/commit/2127b32d26dedeb44ec43d16ec2e2046919f9bb0))
|
||||
- New select menus (#8793) ([5152abf](https://github.com/discordjs/discord.js/commit/5152abf7285581abf7689e9050fdc56c4abb1e2b))
|
||||
|
||||
## Refactor
|
||||
|
||||
- Update `makeURLSearchParams` to accept readonly non-`Record`s (#8868) ([8376e2d](https://github.com/discordjs/discord.js/commit/8376e2dbcd38697ce62615d9a539fd198fbc4713))
|
||||
|
||||
# [@discordjs/rest@1.3.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.2.0...@discordjs/rest@1.3.0) - (2022-10-08)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **SequentialHandler:** Throw http error with proper name and more useful message (#8694) ([3f86561](https://github.com/discordjs/discord.js/commit/3f8656115bf9df0dbf8391de68a3401535325895))
|
||||
|
||||
## Features
|
||||
|
||||
- Web-components (#8715) ([0ac3e76](https://github.com/discordjs/discord.js/commit/0ac3e766bd9dbdeb106483fa4bb085d74de346a2))
|
||||
- Add `@discordjs/util` (#8591) ([b2ec865](https://github.com/discordjs/discord.js/commit/b2ec865765bf94181473864a627fb63ea8173fd3))
|
||||
- Add `AbortSignal` support (#8672) ([3c231ae](https://github.com/discordjs/discord.js/commit/3c231ae81a52b66940ba495f35fd59a76c65e306))
|
||||
|
||||
# [@discordjs/rest@1.2.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.1.0...@discordjs/rest@1.2.0) - (2022-09-25)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Footer / sidebar / deprecation alert ([ba3e0ed](https://github.com/discordjs/discord.js/commit/ba3e0ed348258fe8e51eefb4aa7379a1230616a9))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Change name (#8604) ([dd5a089](https://github.com/discordjs/discord.js/commit/dd5a08944c258a847fc4377f1d5e953264ab47d0))
|
||||
|
||||
## Features
|
||||
|
||||
- **rest:** Use Agent with higher connect timeout (#8679) ([64cd53c](https://github.com/discordjs/discord.js/commit/64cd53c4c23dd9c9503fd0887ac5c542137c57e8))
|
||||
|
||||
## Refactor
|
||||
|
||||
- Website components (#8600) ([c334157](https://github.com/discordjs/discord.js/commit/c3341570d983aea9ecc419979d5a01de658c9d67))
|
||||
- Use `eslint-config-neon` for packages. (#8579) ([edadb9f](https://github.com/discordjs/discord.js/commit/edadb9fe5dfd9ff51a3cfc9b25cb242d3f9f5241))
|
||||
|
||||
# [@discordjs/rest@1.1.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@1.0.1...@discordjs/rest@1.1.0) - (2022-08-22)
|
||||
|
||||
## Features
|
||||
|
||||
- **website:** Show `constructor` information (#8540) ([e42fd16](https://github.com/discordjs/discord.js/commit/e42fd1636973b10dd7ed6fb4280ee1a4a8f82007))
|
||||
- **website:** Render `@defaultValue` blocks (#8527) ([8028813](https://github.com/discordjs/discord.js/commit/8028813825e7708915ea892760c1003afd60df2f))
|
||||
- **WebSocketShard:** Support new resume url (#8480) ([bc06cc6](https://github.com/discordjs/discord.js/commit/bc06cc638d2f57ab5c600e8cdb6afc8eb2180166))
|
||||
|
||||
## Refactor
|
||||
|
||||
- Docs design (#8487) ([4ab1d09](https://github.com/discordjs/discord.js/commit/4ab1d09997a18879a9eb9bda39df6f15aa22557e))
|
||||
|
||||
# [@discordjs/rest@0.6.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@0.5.0...@discordjs/rest@0.6.0) - (2022-07-17)
|
||||
|
||||
## Documentation
|
||||
|
||||
- Add codecov coverage badge to readmes (#8226) ([f6db285](https://github.com/discordjs/discord.js/commit/f6db285c073898a749fe4591cbd4463d1896daf5))
|
||||
|
||||
## Features
|
||||
|
||||
- **builder:** Add max min length in string option (#8214) ([96c8d21](https://github.com/discordjs/discord.js/commit/96c8d21f95eb366c46ae23505ba9054f44821b25))
|
||||
- Codecov (#8219) ([f10f4cd](https://github.com/discordjs/discord.js/commit/f10f4cdcd88ca6be7ec735ed3a415ba13da83db0))
|
||||
- **docgen:** Update typedoc ([b3346f4](https://github.com/discordjs/discord.js/commit/b3346f4b9b3d4f96443506643d4631dc1c6d7b21))
|
||||
- Website (#8043) ([127931d](https://github.com/discordjs/discord.js/commit/127931d1df7a2a5c27923c2f2151dbf3824e50cc))
|
||||
- **docgen:** Typescript support ([3279b40](https://github.com/discordjs/discord.js/commit/3279b40912e6aa61507bedb7db15a2b8668de44b))
|
||||
- Docgen package (#8029) ([8b979c0](https://github.com/discordjs/discord.js/commit/8b979c0245c42fd824d8e98745ee869f5360fc86))
|
||||
- Use vitest instead of jest for more speed ([8d8e6c0](https://github.com/discordjs/discord.js/commit/8d8e6c03decd7352a2aa180f6e5bc1a13602539b))
|
||||
- Add scripts package for locally used scripts ([f2ae1f9](https://github.com/discordjs/discord.js/commit/f2ae1f9348bfd893332a9060f71a8a5f272a1b8b))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **rest:** Add content-type(s) to uploads (#8290) ([103a358](https://github.com/discordjs/discord.js/commit/103a3584c95a7b7f57fa62d47b86520d5ec32303))
|
||||
- **collection:** Remove default export (#8053) ([16810f3](https://github.com/discordjs/discord.js/commit/16810f3e410bf35ed7e6e7412d517ea74c792c5d))
|
||||
- Move all the config files to root (#8033) ([769ea0b](https://github.com/discordjs/discord.js/commit/769ea0bfe78c4f1d413c6b397c604ffe91e39c6a))
|
||||
|
||||
# [@discordjs/rest@0.5.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@0.4.0...@discordjs/rest@0.5.0) - (2022-06-04)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **REST:** Remove dom types (#7922) ([e92b17d](https://github.com/discordjs/discord.js/commit/e92b17d8555164ff259e524efc6a26675660e5c2))
|
||||
- Ok statusCode can be 200..299 (#7919) ([d1504f2](https://github.com/discordjs/discord.js/commit/d1504f2ae19816b3fadcdb3ad17facc863ed7529))
|
||||
|
||||
## Features
|
||||
|
||||
- **rest:** Add guild member banner cdn url (#7973) ([97eaab3](https://github.com/discordjs/discord.js/commit/97eaab35d7383ecbbd93dc623ceda969286c1554))
|
||||
- REST#raw (#7929) ([dfe449c](https://github.com/discordjs/discord.js/commit/dfe449c253b617e8f92c720a2f71135aa1601a65))
|
||||
- **rest:** Use undici (#7747) ([d1ec8c3](https://github.com/discordjs/discord.js/commit/d1ec8c37ffb7fe3b63eaa8c382f22ca1fb348c9b))
|
||||
- **REST:** Enable setting default authPrefix (#7853) ([679dcda](https://github.com/discordjs/discord.js/commit/679dcda9709376f37cc58a60f74d12d324d93e4e))
|
||||
|
||||
## Styling
|
||||
|
||||
- Cleanup tests and tsup configs ([6b8ef20](https://github.com/discordjs/discord.js/commit/6b8ef20cb3af5b5cfd176dd0aa0a1a1e98551629))
|
||||
|
||||
# [@discordjs/rest@0.4.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@0.3.0...@discordjs/rest@0.4.0) - (2022-04-17)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **gateway:** Use version 10 (#7689) ([8880de0](https://github.com/discordjs/discord.js/commit/8880de0cecdf273fd6df23988e4cb77774a75390))
|
||||
- **RequestHandler:** Only reset tokens for authenticated 401s (#7508) ([b9ff7b0](https://github.com/discordjs/discord.js/commit/b9ff7b057379a47ce13265f78e21bf0d55feaf0a))
|
||||
- **ci:** Ci error (#7454) ([0af9bc8](https://github.com/discordjs/discord.js/commit/0af9bc841ffe1a297d308500d696bad4b85abda9))
|
||||
- Use png as extension for defaultAvatarURL (#7414) ([538e9ce](https://github.com/discordjs/discord.js/commit/538e9cef459d00d74b9bd6852da3ce2acac9bae5))
|
||||
- **rest:** Sublimit all requests on unhandled routes (#7366) ([733ac82](https://github.com/discordjs/discord.js/commit/733ac82d5dffabc622fb59e06d06e83396734dc6))
|
||||
- Fix some typos (#7393) ([92a04f4](https://github.com/discordjs/discord.js/commit/92a04f4d98f6c6760214034cc8f5a1eaa78893c7))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Enhance /rest README (#7757) ([a1329bd](https://github.com/discordjs/discord.js/commit/a1329bd3ebafc6d5b5e2788ff082674f01b726f3))
|
||||
|
||||
## Features
|
||||
|
||||
- Add `makeURLSearchParams` utility function (#7744) ([8eaec11](https://github.com/discordjs/discord.js/commit/8eaec114a98026024c21545988860c123948c55d))
|
||||
- Add API v10 support (#7477) ([72577c4](https://github.com/discordjs/discord.js/commit/72577c4bfd02524a27afb6ff4aebba9301a690d3))
|
||||
- Add support for module: NodeNext in TS and ESM (#7598) ([8f1986a](https://github.com/discordjs/discord.js/commit/8f1986a6aa98365e09b00e84ad5f9f354ab61f3d))
|
||||
- **builders:** Add attachment command option type (#7203) ([ae0f35f](https://github.com/discordjs/discord.js/commit/ae0f35f51d68dfa5a7dc43d161ef9365171debdb))
|
||||
- **cdn:** Add support for scheduled event image covers (#7335) ([ac26d9b](https://github.com/discordjs/discord.js/commit/ac26d9b1307d63e116b043505e5f925db7ed01aa))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **requestmanager:** Use timestampfrom (#7459) ([3298510](https://github.com/discordjs/discord.js/commit/32985109c3b7614d364007608f8c5af4bed753ae))
|
||||
- **files:** Remove redundant file property names (#7340) ([6725038](https://github.com/discordjs/discord.js/commit/67250382f99872a9edff99ebaa482ffa895b0c37))
|
||||
|
||||
# [@discordjs/rest@0.3.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@0.2.0...@discordjs/rest@0.3.0) - (2022-01-24)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **rest:** Don't add empty query (#7308) ([d0fa5aa](https://github.com/discordjs/discord.js/commit/d0fa5aaa26d316608120bca3050e14eefbe2f93b))
|
||||
- **rest:** Use http agent when protocol is not https (#7309) ([d8ea572](https://github.com/discordjs/discord.js/commit/d8ea572fb8a51f2f6a902c4926e814017d115708))
|
||||
- `ref` delay for rate limited requests (#7239) ([ed0cfd9](https://github.com/discordjs/discord.js/commit/ed0cfd91edc3a2b23a34a8ecd9db38baa12b52fa))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Fix a typo and use milliseconds instead of ms (#7251) ([0dd56af](https://github.com/discordjs/discord.js/commit/0dd56afe1cdf16f1e7d9afe1f8c29c31d1833a25))
|
||||
|
||||
## Features
|
||||
|
||||
- Rest hash and handler sweeping (#7255) ([3bb4829](https://github.com/discordjs/discord.js/commit/3bb48298004d292214c6cb8f927c2fea78a42952))
|
||||
- Rest docs (#7281) ([9054f2f](https://github.com/discordjs/discord.js/commit/9054f2f7ad7f246431e5f53403535bf301c27a80))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **files:** File data can be much more than buffer (#7238) ([86ab526](https://github.com/discordjs/discord.js/commit/86ab526d493415b14b79b51d08c3677897d219ee))
|
||||
- **rest:** Rename attachment to file (#7199) ([c969cbf](https://github.com/discordjs/discord.js/commit/c969cbf6524093757d47108b6a55e62dcb210e8b))
|
||||
|
||||
## Testing
|
||||
|
||||
- **voice:** Fix tests ([62c74b8](https://github.com/discordjs/discord.js/commit/62c74b8333066465e5bd295b8b102b35a506751d))
|
192
node_modules/@discordjs/rest/LICENSE
generated
vendored
Normal file
192
node_modules/@discordjs/rest/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,192 @@
|
|||
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
|
||||
Copyright 2021 Aura Román
|
||||
|
||||
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.
|
112
node_modules/@discordjs/rest/README.md
generated
vendored
Normal file
112
node_modules/@discordjs/rest/README.md
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
<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/rest"><img src="https://img.shields.io/npm/v/@discordjs/rest.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/@discordjs/rest"><img src="https://img.shields.io/npm/dt/@discordjs/rest.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=rest" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
## Installation
|
||||
|
||||
**Node.js 16.9.0 or newer is required.**
|
||||
|
||||
```sh-session
|
||||
npm install @discordjs/rest
|
||||
yarn add @discordjs/rest
|
||||
pnpm add @discordjs/rest
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Install all required dependencies:
|
||||
|
||||
```sh-session
|
||||
npm install @discordjs/rest discord-api-types
|
||||
yarn add @discordjs/rest discord-api-types
|
||||
pnpm add @discordjs/rest discord-api-types
|
||||
```
|
||||
|
||||
Send a basic message:
|
||||
|
||||
```js
|
||||
import { REST } from '@discordjs/rest';
|
||||
import { Routes } from 'discord-api-types/v10';
|
||||
|
||||
const rest = new REST({ version: '10' }).setToken(TOKEN);
|
||||
|
||||
try {
|
||||
await rest.post(Routes.channelMessages(CHANNEL_ID), {
|
||||
body: {
|
||||
content: 'A message via REST!',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
```
|
||||
|
||||
Create a thread from an existing message to be archived after 60 minutes of inactivity:
|
||||
|
||||
```js
|
||||
import { REST } from '@discordjs/rest';
|
||||
import { Routes } from 'discord-api-types/v10';
|
||||
|
||||
const rest = new REST({ version: '10' }).setToken(TOKEN);
|
||||
|
||||
try {
|
||||
await rest.post(Routes.threads(CHANNEL_ID, MESSAGE_ID), {
|
||||
body: {
|
||||
name: 'Thread',
|
||||
auto_archive_duration: 60,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
```
|
||||
|
||||
## Links
|
||||
|
||||
- [Website][website] ([source][website-source])
|
||||
- [Documentation][documentation]
|
||||
- [Guide][guide] ([source][guide-source])
|
||||
See also the [Update Guide][guide-update], including updated and removed items in the library.
|
||||
- [discord.js Discord server][discord]
|
||||
- [Discord API Discord server][discord-api]
|
||||
- [GitHub][source]
|
||||
- [npm][npm]
|
||||
- [Related libraries][related-libs]
|
||||
|
||||
## Contributing
|
||||
|
||||
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
|
||||
[documentation][documentation].
|
||||
See [the contribution guide][contributing] 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][discord].
|
||||
|
||||
[website]: https://discord.js.org/
|
||||
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
|
||||
[documentation]: https://discord.js.org/#/docs/rest
|
||||
[guide]: https://discordjs.guide/
|
||||
[guide-source]: https://github.com/discordjs/guide
|
||||
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
|
||||
[discord]: https://discord.gg/djs
|
||||
[discord-api]: https://discord.gg/discord-api
|
||||
[source]: https://github.com/discordjs/discord.js/tree/main/packages/rest
|
||||
[npm]: https://www.npmjs.com/package/@discordjs/rest
|
||||
[related-libs]: https://discord.com/developers/docs/topics/community-resources#libraries
|
||||
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
|
865
node_modules/@discordjs/rest/dist/index.d.ts
generated
vendored
Normal file
865
node_modules/@discordjs/rest/dist/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,865 @@
|
|||
import { Agent, Dispatcher, request, BodyInit } from 'undici';
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { URLSearchParams } from 'node:url';
|
||||
import { Collection } from '@discordjs/collection';
|
||||
|
||||
declare const DefaultUserAgent = "DiscordBot (https://discord.js.org, [VI]{{inject}}[/VI])";
|
||||
declare const DefaultRestOptions: {
|
||||
readonly agent: Agent;
|
||||
readonly api: "https://discord.com/api";
|
||||
readonly authPrefix: "Bot";
|
||||
readonly cdn: "https://cdn.discordapp.com";
|
||||
readonly headers: {};
|
||||
readonly invalidRequestWarningInterval: 0;
|
||||
readonly globalRequestsPerSecond: 50;
|
||||
readonly offset: 50;
|
||||
readonly rejectOnRateLimit: null;
|
||||
readonly retries: 3;
|
||||
readonly timeout: 15000;
|
||||
readonly userAgentAppendix: `Node.js ${string}`;
|
||||
readonly version: "10";
|
||||
readonly hashSweepInterval: 14400000;
|
||||
readonly hashLifetime: 86400000;
|
||||
readonly handlerSweepInterval: 3600000;
|
||||
};
|
||||
/**
|
||||
* The events that the REST manager emits
|
||||
*/
|
||||
declare const enum RESTEvents {
|
||||
Debug = "restDebug",
|
||||
HandlerSweep = "handlerSweep",
|
||||
HashSweep = "hashSweep",
|
||||
InvalidRequestWarning = "invalidRequestWarning",
|
||||
RateLimited = "rateLimited",
|
||||
Response = "response"
|
||||
}
|
||||
declare const ALLOWED_EXTENSIONS: readonly ["webp", "png", "jpg", "jpeg", "gif"];
|
||||
declare const ALLOWED_STICKER_EXTENSIONS: readonly ["png", "json"];
|
||||
declare const ALLOWED_SIZES: readonly [16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
|
||||
type ImageExtension = typeof ALLOWED_EXTENSIONS[number];
|
||||
type StickerExtension = typeof ALLOWED_STICKER_EXTENSIONS[number];
|
||||
type ImageSize = typeof ALLOWED_SIZES[number];
|
||||
|
||||
/**
|
||||
* The options used for image URLs
|
||||
*/
|
||||
interface BaseImageURLOptions {
|
||||
/**
|
||||
* The extension to use for the image URL
|
||||
*
|
||||
* @defaultValue `'webp'`
|
||||
*/
|
||||
extension?: ImageExtension;
|
||||
/**
|
||||
* The size specified in the image URL
|
||||
*/
|
||||
size?: ImageSize;
|
||||
}
|
||||
/**
|
||||
* The options used for image URLs with animated content
|
||||
*/
|
||||
interface ImageURLOptions extends BaseImageURLOptions {
|
||||
/**
|
||||
* Whether or not to prefer the static version of an image asset.
|
||||
*/
|
||||
forceStatic?: boolean;
|
||||
}
|
||||
/**
|
||||
* The options to use when making a CDN URL
|
||||
*/
|
||||
interface MakeURLOptions {
|
||||
/**
|
||||
* The allowed extensions that can be used
|
||||
*/
|
||||
allowedExtensions?: readonly string[];
|
||||
/**
|
||||
* The extension to use for the image URL
|
||||
*
|
||||
* @defaultValue `'webp'`
|
||||
*/
|
||||
extension?: string | undefined;
|
||||
/**
|
||||
* The size specified in the image URL
|
||||
*/
|
||||
size?: ImageSize;
|
||||
}
|
||||
/**
|
||||
* The CDN link builder
|
||||
*/
|
||||
declare class CDN {
|
||||
private readonly base;
|
||||
constructor(base?: string);
|
||||
/**
|
||||
* Generates an app asset URL for a client's asset.
|
||||
*
|
||||
* @param clientId - The client id that has the asset
|
||||
* @param assetHash - The hash provided by Discord for this asset
|
||||
* @param options - Optional options for the asset
|
||||
*/
|
||||
appAsset(clientId: string, assetHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates an app icon URL for a client's icon.
|
||||
*
|
||||
* @param clientId - The client id that has the icon
|
||||
* @param iconHash - The hash provided by Discord for this icon
|
||||
* @param options - Optional options for the icon
|
||||
*/
|
||||
appIcon(clientId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates an avatar URL, e.g. for a user or a webhook.
|
||||
*
|
||||
* @param id - The id that has the icon
|
||||
* @param avatarHash - The hash provided by Discord for this avatar
|
||||
* @param options - Optional options for the avatar
|
||||
*/
|
||||
avatar(id: string, avatarHash: string, options?: Readonly<ImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a banner URL, e.g. for a user or a guild.
|
||||
*
|
||||
* @param id - The id that has the banner splash
|
||||
* @param bannerHash - The hash provided by Discord for this banner
|
||||
* @param options - Optional options for the banner
|
||||
*/
|
||||
banner(id: string, bannerHash: string, options?: Readonly<ImageURLOptions>): string;
|
||||
/**
|
||||
* Generates an icon URL for a channel, e.g. a group DM.
|
||||
*
|
||||
* @param channelId - The channel id that has the icon
|
||||
* @param iconHash - The hash provided by Discord for this channel
|
||||
* @param options - Optional options for the icon
|
||||
*/
|
||||
channelIcon(channelId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates the default avatar URL for a discriminator.
|
||||
*
|
||||
* @param discriminator - The discriminator modulo 5
|
||||
*/
|
||||
defaultAvatar(discriminator: number): string;
|
||||
/**
|
||||
* Generates a discovery splash URL for a guild's discovery splash.
|
||||
*
|
||||
* @param guildId - The guild id that has the discovery splash
|
||||
* @param splashHash - The hash provided by Discord for this splash
|
||||
* @param options - Optional options for the splash
|
||||
*/
|
||||
discoverySplash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates an emoji's URL for an emoji.
|
||||
*
|
||||
* @param emojiId - The emoji id
|
||||
* @param extension - The extension of the emoji
|
||||
*/
|
||||
emoji(emojiId: string, extension?: ImageExtension): string;
|
||||
/**
|
||||
* Generates a guild member avatar URL.
|
||||
*
|
||||
* @param guildId - The id of the guild
|
||||
* @param userId - The id of the user
|
||||
* @param avatarHash - The hash provided by Discord for this avatar
|
||||
* @param options - Optional options for the avatar
|
||||
*/
|
||||
guildMemberAvatar(guildId: string, userId: string, avatarHash: string, options?: Readonly<ImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a guild member banner URL.
|
||||
*
|
||||
* @param guildId - The id of the guild
|
||||
* @param userId - The id of the user
|
||||
* @param bannerHash - The hash provided by Discord for this banner
|
||||
* @param options - Optional options for the banner
|
||||
*/
|
||||
guildMemberBanner(guildId: string, userId: string, bannerHash: string, options?: Readonly<ImageURLOptions>): string;
|
||||
/**
|
||||
* Generates an icon URL, e.g. for a guild.
|
||||
*
|
||||
* @param id - The id that has the icon splash
|
||||
* @param iconHash - The hash provided by Discord for this icon
|
||||
* @param options - Optional options for the icon
|
||||
*/
|
||||
icon(id: string, iconHash: string, options?: Readonly<ImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a URL for the icon of a role
|
||||
*
|
||||
* @param roleId - The id of the role that has the icon
|
||||
* @param roleIconHash - The hash provided by Discord for this role icon
|
||||
* @param options - Optional options for the role icon
|
||||
*/
|
||||
roleIcon(roleId: string, roleIconHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a guild invite splash URL for a guild's invite splash.
|
||||
*
|
||||
* @param guildId - The guild id that has the invite splash
|
||||
* @param splashHash - The hash provided by Discord for this splash
|
||||
* @param options - Optional options for the splash
|
||||
*/
|
||||
splash(guildId: string, splashHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a sticker URL.
|
||||
*
|
||||
* @param stickerId - The sticker id
|
||||
* @param extension - The extension of the sticker
|
||||
*/
|
||||
sticker(stickerId: string, extension?: StickerExtension): string;
|
||||
/**
|
||||
* Generates a sticker pack banner URL.
|
||||
*
|
||||
* @param bannerId - The banner id
|
||||
* @param options - Optional options for the banner
|
||||
*/
|
||||
stickerPackBanner(bannerId: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a team icon URL for a team's icon.
|
||||
*
|
||||
* @param teamId - The team id that has the icon
|
||||
* @param iconHash - The hash provided by Discord for this icon
|
||||
* @param options - Optional options for the icon
|
||||
*/
|
||||
teamIcon(teamId: string, iconHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Generates a cover image for a guild scheduled event.
|
||||
*
|
||||
* @param scheduledEventId - The scheduled event id
|
||||
* @param coverHash - The hash provided by discord for this cover image
|
||||
* @param options - Optional options for the cover image
|
||||
*/
|
||||
guildScheduledEventCover(scheduledEventId: string, coverHash: string, options?: Readonly<BaseImageURLOptions>): string;
|
||||
/**
|
||||
* Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
|
||||
*
|
||||
* @param route - The base cdn route
|
||||
* @param hash - The hash provided by Discord for this icon
|
||||
* @param options - Optional options for the link
|
||||
*/
|
||||
private dynamicMakeURL;
|
||||
/**
|
||||
* Constructs the URL for the resource
|
||||
*
|
||||
* @param route - The base cdn route
|
||||
* @param options - The extension/size options for the link
|
||||
*/
|
||||
private makeURL;
|
||||
}
|
||||
|
||||
interface IHandler {
|
||||
/**
|
||||
* The unique id of the handler
|
||||
*/
|
||||
readonly id: string;
|
||||
/**
|
||||
* If the bucket is currently inactive (no pending requests)
|
||||
*/
|
||||
get inactive(): boolean;
|
||||
/**
|
||||
* Queues a request to be sent
|
||||
*
|
||||
* @param routeId - The generalized api route with literal ids for major parameters
|
||||
* @param url - The url to do the request on
|
||||
* @param options - All the information needed to make a request
|
||||
* @param requestData - Extra data from the user's request needed for errors and additional processing
|
||||
*/
|
||||
queueRequest(routeId: RouteData, url: string, options: RequestOptions, requestData: HandlerRequestData): Promise<Dispatcher.ResponseData>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to be passed when creating the REST instance
|
||||
*/
|
||||
interface RESTOptions {
|
||||
/**
|
||||
* The agent to set globally
|
||||
*/
|
||||
agent: Dispatcher;
|
||||
/**
|
||||
* The base api path, without version
|
||||
*
|
||||
* @defaultValue `'https://discord.com/api'`
|
||||
*/
|
||||
api: string;
|
||||
/**
|
||||
* The authorization prefix to use for requests, useful if you want to use
|
||||
* bearer tokens
|
||||
*
|
||||
* @defaultValue `'Bot'`
|
||||
*/
|
||||
authPrefix: 'Bearer' | 'Bot';
|
||||
/**
|
||||
* The cdn path
|
||||
*
|
||||
* @defaultValue 'https://cdn.discordapp.com'
|
||||
*/
|
||||
cdn: string;
|
||||
/**
|
||||
* How many requests to allow sending per second (Infinity for unlimited, 50 for the standard global limit used by Discord)
|
||||
*
|
||||
* @defaultValue `50`
|
||||
*/
|
||||
globalRequestsPerSecond: number;
|
||||
/**
|
||||
* The amount of time in milliseconds that passes between each hash sweep. (defaults to 1h)
|
||||
*
|
||||
* @defaultValue `3_600_000`
|
||||
*/
|
||||
handlerSweepInterval: number;
|
||||
/**
|
||||
* The maximum amount of time a hash can exist in milliseconds without being hit with a request (defaults to 24h)
|
||||
*
|
||||
* @defaultValue `86_400_000`
|
||||
*/
|
||||
hashLifetime: number;
|
||||
/**
|
||||
* The amount of time in milliseconds that passes between each hash sweep. (defaults to 4h)
|
||||
*
|
||||
* @defaultValue `14_400_000`
|
||||
*/
|
||||
hashSweepInterval: number;
|
||||
/**
|
||||
* Additional headers to send for all API requests
|
||||
*
|
||||
* @defaultValue `{}`
|
||||
*/
|
||||
headers: Record<string, string>;
|
||||
/**
|
||||
* The number of invalid REST requests (those that return 401, 403, or 429) in a 10 minute window between emitted warnings (0 for no warnings).
|
||||
* That is, if set to 500, warnings will be emitted at invalid request number 500, 1000, 1500, and so on.
|
||||
*
|
||||
* @defaultValue `0`
|
||||
*/
|
||||
invalidRequestWarningInterval: number;
|
||||
/**
|
||||
* The extra offset to add to rate limits in milliseconds
|
||||
*
|
||||
* @defaultValue `50`
|
||||
*/
|
||||
offset: number;
|
||||
/**
|
||||
* Determines how rate limiting and pre-emptive throttling should be handled.
|
||||
* When an array of strings, each element is treated as a prefix for the request route
|
||||
* (e.g. `/channels` to match any route starting with `/channels` such as `/channels/:id/messages`)
|
||||
* for which to throw {@link RateLimitError}s. All other request routes will be queued normally
|
||||
*
|
||||
* @defaultValue `null`
|
||||
*/
|
||||
rejectOnRateLimit: RateLimitQueueFilter | string[] | null;
|
||||
/**
|
||||
* The number of retries for errors with the 500 code, or errors
|
||||
* that timeout
|
||||
*
|
||||
* @defaultValue `3`
|
||||
*/
|
||||
retries: number;
|
||||
/**
|
||||
* The time to wait in milliseconds before a request is aborted
|
||||
*
|
||||
* @defaultValue `15_000`
|
||||
*/
|
||||
timeout: number;
|
||||
/**
|
||||
* Extra information to add to the user agent
|
||||
*
|
||||
* @defaultValue `Node.js ${process.version}`
|
||||
*/
|
||||
userAgentAppendix: string;
|
||||
/**
|
||||
* The version of the API to use
|
||||
*
|
||||
* @defaultValue `'10'`
|
||||
*/
|
||||
version: string;
|
||||
}
|
||||
/**
|
||||
* Data emitted on `RESTEvents.RateLimited`
|
||||
*/
|
||||
interface RateLimitData {
|
||||
/**
|
||||
* Whether the rate limit that was reached was the global limit
|
||||
*/
|
||||
global: boolean;
|
||||
/**
|
||||
* The bucket hash for this request
|
||||
*/
|
||||
hash: string;
|
||||
/**
|
||||
* The amount of requests we can perform before locking requests
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* The major parameter of the route
|
||||
*
|
||||
* For example, in `/channels/x`, this will be `x`.
|
||||
* If there is no major parameter (e.g: `/bot/gateway`) this will be `global`.
|
||||
*/
|
||||
majorParameter: string;
|
||||
/**
|
||||
* The HTTP method being performed
|
||||
*/
|
||||
method: string;
|
||||
/**
|
||||
* The route being hit in this request
|
||||
*/
|
||||
route: string;
|
||||
/**
|
||||
* The time, in milliseconds, until the request-lock is reset
|
||||
*/
|
||||
timeToReset: number;
|
||||
/**
|
||||
* The full URL for this request
|
||||
*/
|
||||
url: string;
|
||||
}
|
||||
/**
|
||||
* A function that determines whether the rate limit hit should throw an Error
|
||||
*/
|
||||
type RateLimitQueueFilter = (rateLimitData: RateLimitData) => Promise<boolean> | boolean;
|
||||
interface APIRequest {
|
||||
/**
|
||||
* The data that was used to form the body of this request
|
||||
*/
|
||||
data: HandlerRequestData;
|
||||
/**
|
||||
* The HTTP method used in this request
|
||||
*/
|
||||
method: string;
|
||||
/**
|
||||
* Additional HTTP options for this request
|
||||
*/
|
||||
options: RequestOptions;
|
||||
/**
|
||||
* The full path used to make the request
|
||||
*/
|
||||
path: RouteLike;
|
||||
/**
|
||||
* The number of times this request has been attempted
|
||||
*/
|
||||
retries: number;
|
||||
/**
|
||||
* The API route identifying the ratelimit for this request
|
||||
*/
|
||||
route: string;
|
||||
}
|
||||
interface InvalidRequestWarningData {
|
||||
/**
|
||||
* Number of invalid requests that have been made in the window
|
||||
*/
|
||||
count: number;
|
||||
/**
|
||||
* Time in milliseconds remaining before the count resets
|
||||
*/
|
||||
remainingTime: number;
|
||||
}
|
||||
interface RestEvents {
|
||||
handlerSweep: [sweptHandlers: Collection<string, IHandler>];
|
||||
hashSweep: [sweptHashes: Collection<string, HashData>];
|
||||
invalidRequestWarning: [invalidRequestInfo: InvalidRequestWarningData];
|
||||
newListener: [name: string, listener: (...args: any) => void];
|
||||
rateLimited: [rateLimitInfo: RateLimitData];
|
||||
removeListener: [name: string, listener: (...args: any) => void];
|
||||
response: [request: APIRequest, response: Dispatcher.ResponseData];
|
||||
restDebug: [info: string];
|
||||
}
|
||||
type RequestOptions = Exclude<Parameters<typeof request>[1], undefined>;
|
||||
interface REST {
|
||||
emit: (<K extends keyof RestEvents>(event: K, ...args: RestEvents[K]) => boolean) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, ...args: any[]) => boolean);
|
||||
off: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
on: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
once: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
removeAllListeners: (<K extends keyof RestEvents>(event?: K) => this) & (<S extends string | symbol>(event?: Exclude<S, keyof RestEvents>) => this);
|
||||
}
|
||||
declare class REST extends EventEmitter {
|
||||
readonly cdn: CDN;
|
||||
readonly requestManager: RequestManager;
|
||||
constructor(options?: Partial<RESTOptions>);
|
||||
/**
|
||||
* Gets the agent set for this instance
|
||||
*/
|
||||
getAgent(): Dispatcher | null;
|
||||
/**
|
||||
* Sets the default agent to use for requests performed by this instance
|
||||
*
|
||||
* @param agent - Sets the agent to use
|
||||
*/
|
||||
setAgent(agent: Dispatcher): this;
|
||||
/**
|
||||
* Sets the authorization token that should be used for requests
|
||||
*
|
||||
* @param token - The authorization token to use
|
||||
*/
|
||||
setToken(token: string): this;
|
||||
/**
|
||||
* Runs a get request from the api
|
||||
*
|
||||
* @param fullRoute - The full route to query
|
||||
* @param options - Optional request options
|
||||
*/
|
||||
get(fullRoute: RouteLike, options?: RequestData): Promise<unknown>;
|
||||
/**
|
||||
* Runs a delete request from the api
|
||||
*
|
||||
* @param fullRoute - The full route to query
|
||||
* @param options - Optional request options
|
||||
*/
|
||||
delete(fullRoute: RouteLike, options?: RequestData): Promise<unknown>;
|
||||
/**
|
||||
* Runs a post request from the api
|
||||
*
|
||||
* @param fullRoute - The full route to query
|
||||
* @param options - Optional request options
|
||||
*/
|
||||
post(fullRoute: RouteLike, options?: RequestData): Promise<unknown>;
|
||||
/**
|
||||
* Runs a put request from the api
|
||||
*
|
||||
* @param fullRoute - The full route to query
|
||||
* @param options - Optional request options
|
||||
*/
|
||||
put(fullRoute: RouteLike, options?: RequestData): Promise<unknown>;
|
||||
/**
|
||||
* Runs a patch request from the api
|
||||
*
|
||||
* @param fullRoute - The full route to query
|
||||
* @param options - Optional request options
|
||||
*/
|
||||
patch(fullRoute: RouteLike, options?: RequestData): Promise<unknown>;
|
||||
/**
|
||||
* Runs a request from the api
|
||||
*
|
||||
* @param options - Request options
|
||||
*/
|
||||
request(options: InternalRequest): Promise<unknown>;
|
||||
/**
|
||||
* Runs a request from the API, yielding the raw Response object
|
||||
*
|
||||
* @param options - Request options
|
||||
*/
|
||||
raw(options: InternalRequest): Promise<Dispatcher.ResponseData>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a file to be added to the request
|
||||
*/
|
||||
interface RawFile {
|
||||
/**
|
||||
* Content-Type of the file
|
||||
*/
|
||||
contentType?: string;
|
||||
/**
|
||||
* The actual data for the file
|
||||
*/
|
||||
data: Buffer | boolean | number | string;
|
||||
/**
|
||||
* An explicit key to use for key of the formdata field for this file.
|
||||
* When not provided, the index of the file in the files array is used in the form `files[${index}]`.
|
||||
* If you wish to alter the placeholder snowflake, you must provide this property in the same form (`files[${placeholder}]`)
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* The name of the file
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
/**
|
||||
* Represents possible data to be given to an endpoint
|
||||
*/
|
||||
interface RequestData {
|
||||
/**
|
||||
* Whether to append JSON data to form data instead of `payload_json` when sending files
|
||||
*/
|
||||
appendToFormData?: boolean;
|
||||
/**
|
||||
* If this request needs the `Authorization` header
|
||||
*
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
auth?: boolean;
|
||||
/**
|
||||
* The authorization prefix to use for this request, useful if you use this with bearer tokens
|
||||
*
|
||||
* @defaultValue `'Bot'`
|
||||
*/
|
||||
authPrefix?: 'Bearer' | 'Bot';
|
||||
/**
|
||||
* The body to send to this request.
|
||||
* If providing as BodyInit, set `passThroughBody: true`
|
||||
*/
|
||||
body?: BodyInit | unknown;
|
||||
/**
|
||||
* The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} to use for the request.
|
||||
*/
|
||||
dispatcher?: Agent;
|
||||
/**
|
||||
* Files to be attached to this request
|
||||
*/
|
||||
files?: RawFile[] | undefined;
|
||||
/**
|
||||
* Additional headers to add to this request
|
||||
*/
|
||||
headers?: Record<string, string>;
|
||||
/**
|
||||
* Whether to pass-through the body property directly to `fetch()`.
|
||||
* <warn>This only applies when files is NOT present</warn>
|
||||
*/
|
||||
passThroughBody?: boolean;
|
||||
/**
|
||||
* Query string parameters to append to the called endpoint
|
||||
*/
|
||||
query?: URLSearchParams;
|
||||
/**
|
||||
* Reason to show in the audit logs
|
||||
*/
|
||||
reason?: string | undefined;
|
||||
/**
|
||||
* The signal to abort the queue entry or the REST call, where applicable
|
||||
*/
|
||||
signal?: AbortSignal | undefined;
|
||||
/**
|
||||
* If this request should be versioned
|
||||
*
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
versioned?: boolean;
|
||||
}
|
||||
/**
|
||||
* Possible headers for an API call
|
||||
*/
|
||||
interface RequestHeaders {
|
||||
Authorization?: string;
|
||||
'User-Agent': string;
|
||||
'X-Audit-Log-Reason'?: string;
|
||||
}
|
||||
/**
|
||||
* Possible API methods to be used when doing requests
|
||||
*/
|
||||
declare const enum RequestMethod {
|
||||
Delete = "DELETE",
|
||||
Get = "GET",
|
||||
Patch = "PATCH",
|
||||
Post = "POST",
|
||||
Put = "PUT"
|
||||
}
|
||||
type RouteLike = `/${string}`;
|
||||
/**
|
||||
* Internal request options
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface InternalRequest extends RequestData {
|
||||
fullRoute: RouteLike;
|
||||
method: RequestMethod;
|
||||
}
|
||||
type HandlerRequestData = Pick<InternalRequest, 'auth' | 'body' | 'files' | 'signal'>;
|
||||
/**
|
||||
* Parsed route data for an endpoint
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface RouteData {
|
||||
bucketRoute: string;
|
||||
majorParameter: string;
|
||||
original: RouteLike;
|
||||
}
|
||||
/**
|
||||
* Represents a hash and its associated fields
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface HashData {
|
||||
lastAccess: number;
|
||||
value: string;
|
||||
}
|
||||
interface RequestManager {
|
||||
emit: (<K extends keyof RestEvents>(event: K, ...args: RestEvents[K]) => boolean) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, ...args: any[]) => boolean);
|
||||
off: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
on: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
once: (<K extends keyof RestEvents>(event: K, listener: (...args: RestEvents[K]) => void) => this) & (<S extends string | symbol>(event: Exclude<S, keyof RestEvents>, listener: (...args: any[]) => void) => this);
|
||||
removeAllListeners: (<K extends keyof RestEvents>(event?: K) => this) & (<S extends string | symbol>(event?: Exclude<S, keyof RestEvents>) => this);
|
||||
}
|
||||
/**
|
||||
* Represents the class that manages handlers for endpoints
|
||||
*/
|
||||
declare class RequestManager extends EventEmitter {
|
||||
#private;
|
||||
/**
|
||||
* The {@link https://undici.nodejs.org/#/docs/api/Agent | Agent} for all requests
|
||||
* performed by this manager.
|
||||
*/
|
||||
agent: Dispatcher | null;
|
||||
/**
|
||||
* The number of requests remaining in the global bucket
|
||||
*/
|
||||
globalRemaining: number;
|
||||
/**
|
||||
* The promise used to wait out the global rate limit
|
||||
*/
|
||||
globalDelay: Promise<void> | null;
|
||||
/**
|
||||
* The timestamp at which the global bucket resets
|
||||
*/
|
||||
globalReset: number;
|
||||
/**
|
||||
* API bucket hashes that are cached from provided routes
|
||||
*/
|
||||
readonly hashes: Collection<string, HashData>;
|
||||
/**
|
||||
* Request handlers created from the bucket hash and the major parameters
|
||||
*/
|
||||
readonly handlers: Collection<string, IHandler>;
|
||||
private hashTimer;
|
||||
private handlerTimer;
|
||||
readonly options: RESTOptions;
|
||||
constructor(options: Partial<RESTOptions>);
|
||||
private setupSweepers;
|
||||
/**
|
||||
* Sets the default agent to use for requests performed by this manager
|
||||
*
|
||||
* @param agent - The agent to use
|
||||
*/
|
||||
setAgent(agent: Dispatcher): this;
|
||||
/**
|
||||
* Sets the authorization token that should be used for requests
|
||||
*
|
||||
* @param token - The authorization token to use
|
||||
*/
|
||||
setToken(token: string): this;
|
||||
/**
|
||||
* Queues a request to be sent
|
||||
*
|
||||
* @param request - All the information needed to make a request
|
||||
* @returns The response from the api request
|
||||
*/
|
||||
queueRequest(request: InternalRequest): Promise<Dispatcher.ResponseData>;
|
||||
/**
|
||||
* Creates a new rate limit handler from a hash, based on the hash and the major parameter
|
||||
*
|
||||
* @param hash - The hash for the route
|
||||
* @param majorParameter - The major parameter for this handler
|
||||
* @internal
|
||||
*/
|
||||
private createHandler;
|
||||
/**
|
||||
* Formats the request data to a usable format for fetch
|
||||
*
|
||||
* @param request - The request data
|
||||
*/
|
||||
private resolveRequest;
|
||||
/**
|
||||
* Stops the hash sweeping interval
|
||||
*/
|
||||
clearHashSweeper(): void;
|
||||
/**
|
||||
* Stops the request handler sweeping interval
|
||||
*/
|
||||
clearHandlerSweeper(): void;
|
||||
/**
|
||||
* Generates route data for an endpoint:method
|
||||
*
|
||||
* @param endpoint - The raw endpoint to generalize
|
||||
* @param method - The HTTP method this endpoint is called without
|
||||
* @internal
|
||||
*/
|
||||
private static generateRouteData;
|
||||
}
|
||||
|
||||
interface DiscordErrorFieldInformation {
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
interface DiscordErrorGroupWrapper {
|
||||
_errors: DiscordError[];
|
||||
}
|
||||
type DiscordError = DiscordErrorFieldInformation | DiscordErrorGroupWrapper | string | {
|
||||
[k: string]: DiscordError;
|
||||
};
|
||||
interface DiscordErrorData {
|
||||
code: number;
|
||||
errors?: DiscordError;
|
||||
message: string;
|
||||
}
|
||||
interface OAuthErrorData {
|
||||
error: string;
|
||||
error_description?: string;
|
||||
}
|
||||
interface RequestBody {
|
||||
files: RawFile[] | undefined;
|
||||
json: unknown | undefined;
|
||||
}
|
||||
/**
|
||||
* Represents an API error returned by Discord
|
||||
*/
|
||||
declare class DiscordAPIError extends Error {
|
||||
rawError: DiscordErrorData | OAuthErrorData;
|
||||
code: number | string;
|
||||
status: number;
|
||||
method: string;
|
||||
url: string;
|
||||
requestBody: RequestBody;
|
||||
/**
|
||||
* @param rawError - The error reported by Discord
|
||||
* @param code - The error code reported by Discord
|
||||
* @param status - The status code of the response
|
||||
* @param method - The method of the request that erred
|
||||
* @param url - The url of the request that erred
|
||||
* @param bodyData - The unparsed data for the request that errored
|
||||
*/
|
||||
constructor(rawError: DiscordErrorData | OAuthErrorData, code: number | string, status: number, method: string, url: string, bodyData: Pick<InternalRequest, 'body' | 'files'>);
|
||||
/**
|
||||
* The name of the error
|
||||
*/
|
||||
get name(): string;
|
||||
private static getMessage;
|
||||
private static flattenDiscordError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a HTTP error
|
||||
*/
|
||||
declare class HTTPError extends Error {
|
||||
status: number;
|
||||
method: string;
|
||||
url: string;
|
||||
requestBody: RequestBody;
|
||||
name: string;
|
||||
/**
|
||||
* @param status - The status code of the response
|
||||
* @param method - The method of the request that erred
|
||||
* @param url - The url of the request that erred
|
||||
* @param bodyData - The unparsed data for the request that errored
|
||||
*/
|
||||
constructor(status: number, method: string, url: string, bodyData: Pick<InternalRequest, 'body' | 'files'>);
|
||||
}
|
||||
|
||||
declare class RateLimitError extends Error implements RateLimitData {
|
||||
timeToReset: number;
|
||||
limit: number;
|
||||
method: string;
|
||||
hash: string;
|
||||
url: string;
|
||||
route: string;
|
||||
majorParameter: string;
|
||||
global: boolean;
|
||||
constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }: RateLimitData);
|
||||
/**
|
||||
* The name of the error
|
||||
*/
|
||||
get name(): string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and populates an URLSearchParams instance from an object, stripping
|
||||
* out null and undefined values, while also coercing non-strings to strings.
|
||||
*
|
||||
* @param options - The options to use
|
||||
* @returns A populated URLSearchParams instance
|
||||
*/
|
||||
declare function makeURLSearchParams<T extends object>(options?: Readonly<T>): URLSearchParams;
|
||||
/**
|
||||
* Converts the response to usable data
|
||||
*
|
||||
* @param res - The fetch response
|
||||
*/
|
||||
declare function parseResponse(res: Dispatcher.ResponseData): Promise<unknown>;
|
||||
|
||||
/**
|
||||
* The {@link https://github.com/discordjs/discord.js/blob/main/packages/rest/#readme | @discordjs/rest} version
|
||||
* that you are currently using.
|
||||
*/
|
||||
declare const version: string;
|
||||
|
||||
export { ALLOWED_EXTENSIONS, ALLOWED_SIZES, ALLOWED_STICKER_EXTENSIONS, APIRequest, BaseImageURLOptions, CDN, DefaultRestOptions, DefaultUserAgent, DiscordAPIError, DiscordErrorData, HTTPError, HandlerRequestData, HashData, ImageExtension, ImageSize, ImageURLOptions, InternalRequest, InvalidRequestWarningData, MakeURLOptions, OAuthErrorData, REST, RESTEvents, RESTOptions, RateLimitData, RateLimitError, RateLimitQueueFilter, RawFile, RequestBody, RequestData, RequestHeaders, RequestManager, RequestMethod, RequestOptions, RestEvents, RouteData, RouteLike, StickerExtension, makeURLSearchParams, parseResponse, version };
|
940
node_modules/@discordjs/rest/dist/index.js
generated
vendored
Normal file
940
node_modules/@discordjs/rest/dist/index.js
generated
vendored
Normal file
|
@ -0,0 +1,940 @@
|
|||
"use strict";
|
||||
var __create = Object.create;
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __getProtoOf = Object.getPrototypeOf;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// src/index.ts
|
||||
var src_exports = {};
|
||||
__export(src_exports, {
|
||||
ALLOWED_EXTENSIONS: () => ALLOWED_EXTENSIONS,
|
||||
ALLOWED_SIZES: () => ALLOWED_SIZES,
|
||||
ALLOWED_STICKER_EXTENSIONS: () => ALLOWED_STICKER_EXTENSIONS,
|
||||
CDN: () => CDN,
|
||||
DefaultRestOptions: () => DefaultRestOptions,
|
||||
DefaultUserAgent: () => DefaultUserAgent,
|
||||
DiscordAPIError: () => DiscordAPIError,
|
||||
HTTPError: () => HTTPError,
|
||||
REST: () => REST,
|
||||
RESTEvents: () => RESTEvents,
|
||||
RateLimitError: () => RateLimitError,
|
||||
RequestManager: () => RequestManager,
|
||||
RequestMethod: () => RequestMethod,
|
||||
makeURLSearchParams: () => makeURLSearchParams,
|
||||
parseResponse: () => parseResponse,
|
||||
version: () => version
|
||||
});
|
||||
module.exports = __toCommonJS(src_exports);
|
||||
|
||||
// src/lib/CDN.ts
|
||||
var import_node_url = require("url");
|
||||
|
||||
// src/lib/utils/constants.ts
|
||||
var import_node_process = __toESM(require("process"));
|
||||
var import_v10 = require("discord-api-types/v10");
|
||||
var import_undici = require("undici");
|
||||
var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.5.0)`;
|
||||
var DefaultRestOptions = {
|
||||
get agent() {
|
||||
return new import_undici.Agent({
|
||||
connect: {
|
||||
timeout: 3e4
|
||||
}
|
||||
});
|
||||
},
|
||||
api: "https://discord.com/api",
|
||||
authPrefix: "Bot",
|
||||
cdn: "https://cdn.discordapp.com",
|
||||
headers: {},
|
||||
invalidRequestWarningInterval: 0,
|
||||
globalRequestsPerSecond: 50,
|
||||
offset: 50,
|
||||
rejectOnRateLimit: null,
|
||||
retries: 3,
|
||||
timeout: 15e3,
|
||||
userAgentAppendix: `Node.js ${import_node_process.default.version}`,
|
||||
version: import_v10.APIVersion,
|
||||
hashSweepInterval: 144e5,
|
||||
hashLifetime: 864e5,
|
||||
handlerSweepInterval: 36e5
|
||||
};
|
||||
var RESTEvents = /* @__PURE__ */ ((RESTEvents2) => {
|
||||
RESTEvents2["Debug"] = "restDebug";
|
||||
RESTEvents2["HandlerSweep"] = "handlerSweep";
|
||||
RESTEvents2["HashSweep"] = "hashSweep";
|
||||
RESTEvents2["InvalidRequestWarning"] = "invalidRequestWarning";
|
||||
RESTEvents2["RateLimited"] = "rateLimited";
|
||||
RESTEvents2["Response"] = "response";
|
||||
return RESTEvents2;
|
||||
})(RESTEvents || {});
|
||||
var ALLOWED_EXTENSIONS = ["webp", "png", "jpg", "jpeg", "gif"];
|
||||
var ALLOWED_STICKER_EXTENSIONS = ["png", "json"];
|
||||
var ALLOWED_SIZES = [16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
|
||||
|
||||
// src/lib/CDN.ts
|
||||
var CDN = class {
|
||||
constructor(base = DefaultRestOptions.cdn) {
|
||||
this.base = base;
|
||||
}
|
||||
appAsset(clientId, assetHash, options) {
|
||||
return this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);
|
||||
}
|
||||
appIcon(clientId, iconHash, options) {
|
||||
return this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);
|
||||
}
|
||||
avatar(id, avatarHash, options) {
|
||||
return this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);
|
||||
}
|
||||
banner(id, bannerHash, options) {
|
||||
return this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);
|
||||
}
|
||||
channelIcon(channelId, iconHash, options) {
|
||||
return this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);
|
||||
}
|
||||
defaultAvatar(discriminator) {
|
||||
return this.makeURL(`/embed/avatars/${discriminator}`, { extension: "png" });
|
||||
}
|
||||
discoverySplash(guildId, splashHash, options) {
|
||||
return this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);
|
||||
}
|
||||
emoji(emojiId, extension) {
|
||||
return this.makeURL(`/emojis/${emojiId}`, { extension });
|
||||
}
|
||||
guildMemberAvatar(guildId, userId, avatarHash, options) {
|
||||
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);
|
||||
}
|
||||
guildMemberBanner(guildId, userId, bannerHash, options) {
|
||||
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);
|
||||
}
|
||||
icon(id, iconHash, options) {
|
||||
return this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);
|
||||
}
|
||||
roleIcon(roleId, roleIconHash, options) {
|
||||
return this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);
|
||||
}
|
||||
splash(guildId, splashHash, options) {
|
||||
return this.makeURL(`/splashes/${guildId}/${splashHash}`, options);
|
||||
}
|
||||
sticker(stickerId, extension) {
|
||||
return this.makeURL(`/stickers/${stickerId}`, {
|
||||
allowedExtensions: ALLOWED_STICKER_EXTENSIONS,
|
||||
extension: extension ?? "png"
|
||||
});
|
||||
}
|
||||
stickerPackBanner(bannerId, options) {
|
||||
return this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);
|
||||
}
|
||||
teamIcon(teamId, iconHash, options) {
|
||||
return this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);
|
||||
}
|
||||
guildScheduledEventCover(scheduledEventId, coverHash, options) {
|
||||
return this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);
|
||||
}
|
||||
dynamicMakeURL(route, hash, { forceStatic = false, ...options } = {}) {
|
||||
return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? { ...options, extension: "gif" } : options);
|
||||
}
|
||||
makeURL(route, { allowedExtensions = ALLOWED_EXTENSIONS, extension = "webp", size } = {}) {
|
||||
extension = String(extension).toLowerCase();
|
||||
if (!allowedExtensions.includes(extension)) {
|
||||
throw new RangeError(`Invalid extension provided: ${extension}
|
||||
Must be one of: ${allowedExtensions.join(", ")}`);
|
||||
}
|
||||
if (size && !ALLOWED_SIZES.includes(size)) {
|
||||
throw new RangeError(`Invalid size provided: ${size}
|
||||
Must be one of: ${ALLOWED_SIZES.join(", ")}`);
|
||||
}
|
||||
const url = new import_node_url.URL(`${this.base}${route}.${extension}`);
|
||||
if (size) {
|
||||
url.searchParams.set("size", String(size));
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
};
|
||||
__name(CDN, "CDN");
|
||||
|
||||
// src/lib/errors/DiscordAPIError.ts
|
||||
function isErrorGroupWrapper(error) {
|
||||
return Reflect.has(error, "_errors");
|
||||
}
|
||||
__name(isErrorGroupWrapper, "isErrorGroupWrapper");
|
||||
function isErrorResponse(error) {
|
||||
return typeof Reflect.get(error, "message") === "string";
|
||||
}
|
||||
__name(isErrorResponse, "isErrorResponse");
|
||||
var DiscordAPIError = class extends Error {
|
||||
constructor(rawError, code, status, method, url, bodyData) {
|
||||
super(DiscordAPIError.getMessage(rawError));
|
||||
this.rawError = rawError;
|
||||
this.code = code;
|
||||
this.status = status;
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.requestBody = { files: bodyData.files, json: bodyData.body };
|
||||
}
|
||||
requestBody;
|
||||
get name() {
|
||||
return `${DiscordAPIError.name}[${this.code}]`;
|
||||
}
|
||||
static getMessage(error) {
|
||||
let flattened = "";
|
||||
if ("code" in error) {
|
||||
if (error.errors) {
|
||||
flattened = [...this.flattenDiscordError(error.errors)].join("\n");
|
||||
}
|
||||
return error.message && flattened ? `${error.message}
|
||||
${flattened}` : error.message || flattened || "Unknown Error";
|
||||
}
|
||||
return error.error_description ?? "No Description";
|
||||
}
|
||||
static *flattenDiscordError(obj, key = "") {
|
||||
if (isErrorResponse(obj)) {
|
||||
return yield `${key.length ? `${key}[${obj.code}]` : `${obj.code}`}: ${obj.message}`.trim();
|
||||
}
|
||||
for (const [otherKey, val] of Object.entries(obj)) {
|
||||
const nextKey = otherKey.startsWith("_") ? key : key ? Number.isNaN(Number(otherKey)) ? `${key}.${otherKey}` : `${key}[${otherKey}]` : otherKey;
|
||||
if (typeof val === "string") {
|
||||
yield val;
|
||||
} else if (isErrorGroupWrapper(val)) {
|
||||
for (const error of val._errors) {
|
||||
yield* this.flattenDiscordError(error, nextKey);
|
||||
}
|
||||
} else {
|
||||
yield* this.flattenDiscordError(val, nextKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
__name(DiscordAPIError, "DiscordAPIError");
|
||||
|
||||
// src/lib/errors/HTTPError.ts
|
||||
var import_node_http = require("http");
|
||||
var HTTPError = class extends Error {
|
||||
constructor(status, method, url, bodyData) {
|
||||
super(import_node_http.STATUS_CODES[status]);
|
||||
this.status = status;
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.requestBody = { files: bodyData.files, json: bodyData.body };
|
||||
}
|
||||
requestBody;
|
||||
name = HTTPError.name;
|
||||
};
|
||||
__name(HTTPError, "HTTPError");
|
||||
|
||||
// src/lib/errors/RateLimitError.ts
|
||||
var RateLimitError = class extends Error {
|
||||
timeToReset;
|
||||
limit;
|
||||
method;
|
||||
hash;
|
||||
url;
|
||||
route;
|
||||
majorParameter;
|
||||
global;
|
||||
constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }) {
|
||||
super();
|
||||
this.timeToReset = timeToReset;
|
||||
this.limit = limit;
|
||||
this.method = method;
|
||||
this.hash = hash;
|
||||
this.url = url;
|
||||
this.route = route;
|
||||
this.majorParameter = majorParameter;
|
||||
this.global = global;
|
||||
}
|
||||
get name() {
|
||||
return `${RateLimitError.name}[${this.route}]`;
|
||||
}
|
||||
};
|
||||
__name(RateLimitError, "RateLimitError");
|
||||
|
||||
// src/lib/RequestManager.ts
|
||||
var import_node_buffer2 = require("buffer");
|
||||
var import_node_events = require("events");
|
||||
var import_node_timers2 = require("timers");
|
||||
var import_collection = require("@discordjs/collection");
|
||||
var import_util = require("@discordjs/util");
|
||||
var import_snowflake = require("@sapphire/snowflake");
|
||||
var import_undici4 = require("undici");
|
||||
|
||||
// src/lib/handlers/SequentialHandler.ts
|
||||
var import_node_timers = require("timers");
|
||||
var import_promises = require("timers/promises");
|
||||
var import_async_queue = require("@sapphire/async-queue");
|
||||
var import_undici3 = require("undici");
|
||||
|
||||
// src/lib/utils/utils.ts
|
||||
var import_node_buffer = require("buffer");
|
||||
var import_node_url2 = require("url");
|
||||
var import_node_util = require("util");
|
||||
var import_undici2 = require("undici");
|
||||
function parseHeader(header) {
|
||||
if (header === void 0 || typeof header === "string") {
|
||||
return header;
|
||||
}
|
||||
return header.join(";");
|
||||
}
|
||||
__name(parseHeader, "parseHeader");
|
||||
function serializeSearchParam(value) {
|
||||
switch (typeof value) {
|
||||
case "string":
|
||||
return value;
|
||||
case "number":
|
||||
case "bigint":
|
||||
case "boolean":
|
||||
return value.toString();
|
||||
case "object":
|
||||
if (value === null)
|
||||
return null;
|
||||
if (value instanceof Date) {
|
||||
return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
||||
}
|
||||
if (typeof value.toString === "function" && value.toString !== Object.prototype.toString)
|
||||
return value.toString();
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
__name(serializeSearchParam, "serializeSearchParam");
|
||||
function makeURLSearchParams(options) {
|
||||
const params = new import_node_url2.URLSearchParams();
|
||||
if (!options)
|
||||
return params;
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
const serialized = serializeSearchParam(value);
|
||||
if (serialized !== null)
|
||||
params.append(key, serialized);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
__name(makeURLSearchParams, "makeURLSearchParams");
|
||||
async function parseResponse(res) {
|
||||
const header = parseHeader(res.headers["content-type"]);
|
||||
if (header?.startsWith("application/json")) {
|
||||
return res.body.json();
|
||||
}
|
||||
return res.body.arrayBuffer();
|
||||
}
|
||||
__name(parseResponse, "parseResponse");
|
||||
function hasSublimit(bucketRoute, body, method) {
|
||||
if (bucketRoute === "/channels/:id") {
|
||||
if (typeof body !== "object" || body === null)
|
||||
return false;
|
||||
if (method !== "PATCH" /* Patch */)
|
||||
return false;
|
||||
const castedBody = body;
|
||||
return ["name", "topic"].some((key) => Reflect.has(castedBody, key));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
__name(hasSublimit, "hasSublimit");
|
||||
async function resolveBody(body) {
|
||||
if (body == null) {
|
||||
return null;
|
||||
} else if (typeof body === "string") {
|
||||
return body;
|
||||
} else if (import_node_util.types.isUint8Array(body)) {
|
||||
return body;
|
||||
} else if (import_node_util.types.isArrayBuffer(body)) {
|
||||
return new Uint8Array(body);
|
||||
} else if (body instanceof import_node_url2.URLSearchParams) {
|
||||
return body.toString();
|
||||
} else if (body instanceof DataView) {
|
||||
return new Uint8Array(body.buffer);
|
||||
} else if (body instanceof import_node_buffer.Blob) {
|
||||
return new Uint8Array(await body.arrayBuffer());
|
||||
} else if (body instanceof import_undici2.FormData) {
|
||||
return body;
|
||||
} else if (body[Symbol.iterator]) {
|
||||
const chunks = [...body];
|
||||
const length = chunks.reduce((a, b) => a + b.length, 0);
|
||||
const uint8 = new Uint8Array(length);
|
||||
let lengthUsed = 0;
|
||||
return chunks.reduce((a, b) => {
|
||||
a.set(b, lengthUsed);
|
||||
lengthUsed += b.length;
|
||||
return a;
|
||||
}, uint8);
|
||||
} else if (body[Symbol.asyncIterator]) {
|
||||
const chunks = [];
|
||||
for await (const chunk of body) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
return import_node_buffer.Buffer.concat(chunks);
|
||||
}
|
||||
throw new TypeError(`Unable to resolve body.`);
|
||||
}
|
||||
__name(resolveBody, "resolveBody");
|
||||
function shouldRetry(error) {
|
||||
if (error.name === "AbortError")
|
||||
return true;
|
||||
return "code" in error && error.code === "ECONNRESET" || error.message.includes("ECONNRESET");
|
||||
}
|
||||
__name(shouldRetry, "shouldRetry");
|
||||
|
||||
// src/lib/handlers/SequentialHandler.ts
|
||||
var invalidCount = 0;
|
||||
var invalidCountResetTime = null;
|
||||
var SequentialHandler = class {
|
||||
constructor(manager, hash, majorParameter) {
|
||||
this.manager = manager;
|
||||
this.hash = hash;
|
||||
this.majorParameter = majorParameter;
|
||||
this.id = `${hash}:${majorParameter}`;
|
||||
}
|
||||
id;
|
||||
reset = -1;
|
||||
remaining = 1;
|
||||
limit = Number.POSITIVE_INFINITY;
|
||||
#asyncQueue = new import_async_queue.AsyncQueue();
|
||||
#sublimitedQueue = null;
|
||||
#sublimitPromise = null;
|
||||
#shiftSublimit = false;
|
||||
get inactive() {
|
||||
return this.#asyncQueue.remaining === 0 && (this.#sublimitedQueue === null || this.#sublimitedQueue.remaining === 0) && !this.limited;
|
||||
}
|
||||
get globalLimited() {
|
||||
return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;
|
||||
}
|
||||
get localLimited() {
|
||||
return this.remaining <= 0 && Date.now() < this.reset;
|
||||
}
|
||||
get limited() {
|
||||
return this.globalLimited || this.localLimited;
|
||||
}
|
||||
get timeToReset() {
|
||||
return this.reset + this.manager.options.offset - Date.now();
|
||||
}
|
||||
debug(message) {
|
||||
this.manager.emit("restDebug" /* Debug */, `[REST ${this.id}] ${message}`);
|
||||
}
|
||||
async globalDelayFor(time) {
|
||||
await (0, import_promises.setTimeout)(time);
|
||||
this.manager.globalDelay = null;
|
||||
}
|
||||
async onRateLimit(rateLimitData) {
|
||||
const { options } = this.manager;
|
||||
if (!options.rejectOnRateLimit)
|
||||
return;
|
||||
const shouldThrow = typeof options.rejectOnRateLimit === "function" ? await options.rejectOnRateLimit(rateLimitData) : options.rejectOnRateLimit.some((route) => rateLimitData.route.startsWith(route.toLowerCase()));
|
||||
if (shouldThrow) {
|
||||
throw new RateLimitError(rateLimitData);
|
||||
}
|
||||
}
|
||||
async queueRequest(routeId, url, options, requestData) {
|
||||
let queue = this.#asyncQueue;
|
||||
let queueType = 0 /* Standard */;
|
||||
if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
|
||||
queue = this.#sublimitedQueue;
|
||||
queueType = 1 /* Sublimit */;
|
||||
}
|
||||
await queue.wait({ signal: requestData.signal });
|
||||
if (queueType === 0 /* Standard */) {
|
||||
if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
|
||||
queue = this.#sublimitedQueue;
|
||||
const wait = queue.wait();
|
||||
this.#asyncQueue.shift();
|
||||
await wait;
|
||||
} else if (this.#sublimitPromise) {
|
||||
await this.#sublimitPromise.promise;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return await this.runRequest(routeId, url, options, requestData);
|
||||
} finally {
|
||||
queue.shift();
|
||||
if (this.#shiftSublimit) {
|
||||
this.#shiftSublimit = false;
|
||||
this.#sublimitedQueue?.shift();
|
||||
}
|
||||
if (this.#sublimitedQueue?.remaining === 0) {
|
||||
this.#sublimitPromise?.resolve();
|
||||
this.#sublimitedQueue = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
async runRequest(routeId, url, options, requestData, retries = 0) {
|
||||
while (this.limited) {
|
||||
const isGlobal = this.globalLimited;
|
||||
let limit2;
|
||||
let timeout2;
|
||||
let delay;
|
||||
if (isGlobal) {
|
||||
limit2 = this.manager.options.globalRequestsPerSecond;
|
||||
timeout2 = this.manager.globalReset + this.manager.options.offset - Date.now();
|
||||
if (!this.manager.globalDelay) {
|
||||
this.manager.globalDelay = this.globalDelayFor(timeout2);
|
||||
}
|
||||
delay = this.manager.globalDelay;
|
||||
} else {
|
||||
limit2 = this.limit;
|
||||
timeout2 = this.timeToReset;
|
||||
delay = (0, import_promises.setTimeout)(timeout2);
|
||||
}
|
||||
const rateLimitData = {
|
||||
timeToReset: timeout2,
|
||||
limit: limit2,
|
||||
method: options.method ?? "get",
|
||||
hash: this.hash,
|
||||
url,
|
||||
route: routeId.bucketRoute,
|
||||
majorParameter: this.majorParameter,
|
||||
global: isGlobal
|
||||
};
|
||||
this.manager.emit("rateLimited" /* RateLimited */, rateLimitData);
|
||||
await this.onRateLimit(rateLimitData);
|
||||
if (isGlobal) {
|
||||
this.debug(`Global rate limit hit, blocking all requests for ${timeout2}ms`);
|
||||
} else {
|
||||
this.debug(`Waiting ${timeout2}ms for rate limit to pass`);
|
||||
}
|
||||
await delay;
|
||||
}
|
||||
if (!this.manager.globalReset || this.manager.globalReset < Date.now()) {
|
||||
this.manager.globalReset = Date.now() + 1e3;
|
||||
this.manager.globalRemaining = this.manager.options.globalRequestsPerSecond;
|
||||
}
|
||||
this.manager.globalRemaining--;
|
||||
const method = options.method ?? "get";
|
||||
const controller = new AbortController();
|
||||
const timeout = (0, import_node_timers.setTimeout)(() => controller.abort(), this.manager.options.timeout).unref();
|
||||
if (requestData.signal) {
|
||||
const signal = requestData.signal;
|
||||
if (signal.aborted)
|
||||
controller.abort();
|
||||
else
|
||||
signal.addEventListener("abort", () => controller.abort());
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = await (0, import_undici3.request)(url, { ...options, signal: controller.signal });
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error))
|
||||
throw error;
|
||||
if (shouldRetry(error) && retries !== this.manager.options.retries) {
|
||||
return await this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
(0, import_node_timers.clearTimeout)(timeout);
|
||||
}
|
||||
if (this.manager.listenerCount("response" /* Response */)) {
|
||||
this.manager.emit(
|
||||
"response" /* Response */,
|
||||
{
|
||||
method,
|
||||
path: routeId.original,
|
||||
route: routeId.bucketRoute,
|
||||
options,
|
||||
data: requestData,
|
||||
retries
|
||||
},
|
||||
{ ...res }
|
||||
);
|
||||
}
|
||||
const status = res.statusCode;
|
||||
let retryAfter = 0;
|
||||
const limit = parseHeader(res.headers["x-ratelimit-limit"]);
|
||||
const remaining = parseHeader(res.headers["x-ratelimit-remaining"]);
|
||||
const reset = parseHeader(res.headers["x-ratelimit-reset-after"]);
|
||||
const hash = parseHeader(res.headers["x-ratelimit-bucket"]);
|
||||
const retry = parseHeader(res.headers["retry-after"]);
|
||||
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
|
||||
this.remaining = remaining ? Number(remaining) : 1;
|
||||
this.reset = reset ? Number(reset) * 1e3 + Date.now() + this.manager.options.offset : Date.now();
|
||||
if (retry)
|
||||
retryAfter = Number(retry) * 1e3 + this.manager.options.offset;
|
||||
if (hash && hash !== this.hash) {
|
||||
this.debug(["Received bucket hash update", ` Old Hash : ${this.hash}`, ` New Hash : ${hash}`].join("\n"));
|
||||
this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, { value: hash, lastAccess: Date.now() });
|
||||
} else if (hash) {
|
||||
const hashData = this.manager.hashes.get(`${method}:${routeId.bucketRoute}`);
|
||||
if (hashData) {
|
||||
hashData.lastAccess = Date.now();
|
||||
}
|
||||
}
|
||||
let sublimitTimeout = null;
|
||||
if (retryAfter > 0) {
|
||||
if (res.headers["x-ratelimit-global"] !== void 0) {
|
||||
this.manager.globalRemaining = 0;
|
||||
this.manager.globalReset = Date.now() + retryAfter;
|
||||
} else if (!this.localLimited) {
|
||||
sublimitTimeout = retryAfter;
|
||||
}
|
||||
}
|
||||
if (status === 401 || status === 403 || status === 429) {
|
||||
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
|
||||
invalidCountResetTime = Date.now() + 1e3 * 60 * 10;
|
||||
invalidCount = 0;
|
||||
}
|
||||
invalidCount++;
|
||||
const emitInvalid = this.manager.options.invalidRequestWarningInterval > 0 && invalidCount % this.manager.options.invalidRequestWarningInterval === 0;
|
||||
if (emitInvalid) {
|
||||
this.manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
|
||||
count: invalidCount,
|
||||
remainingTime: invalidCountResetTime - Date.now()
|
||||
});
|
||||
}
|
||||
}
|
||||
if (status >= 200 && status < 300) {
|
||||
return res;
|
||||
} else if (status === 429) {
|
||||
const isGlobal = this.globalLimited;
|
||||
let limit2;
|
||||
let timeout2;
|
||||
if (isGlobal) {
|
||||
limit2 = this.manager.options.globalRequestsPerSecond;
|
||||
timeout2 = this.manager.globalReset + this.manager.options.offset - Date.now();
|
||||
} else {
|
||||
limit2 = this.limit;
|
||||
timeout2 = this.timeToReset;
|
||||
}
|
||||
await this.onRateLimit({
|
||||
timeToReset: timeout2,
|
||||
limit: limit2,
|
||||
method,
|
||||
hash: this.hash,
|
||||
url,
|
||||
route: routeId.bucketRoute,
|
||||
majorParameter: this.majorParameter,
|
||||
global: isGlobal
|
||||
});
|
||||
this.debug(
|
||||
[
|
||||
"Encountered unexpected 429 rate limit",
|
||||
` Global : ${isGlobal.toString()}`,
|
||||
` Method : ${method}`,
|
||||
` URL : ${url}`,
|
||||
` Bucket : ${routeId.bucketRoute}`,
|
||||
` Major parameter: ${routeId.majorParameter}`,
|
||||
` Hash : ${this.hash}`,
|
||||
` Limit : ${limit2}`,
|
||||
` Retry After : ${retryAfter}ms`,
|
||||
` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
|
||||
].join("\n")
|
||||
);
|
||||
if (sublimitTimeout) {
|
||||
const firstSublimit = !this.#sublimitedQueue;
|
||||
if (firstSublimit) {
|
||||
this.#sublimitedQueue = new import_async_queue.AsyncQueue();
|
||||
void this.#sublimitedQueue.wait();
|
||||
this.#asyncQueue.shift();
|
||||
}
|
||||
this.#sublimitPromise?.resolve();
|
||||
this.#sublimitPromise = null;
|
||||
await (0, import_promises.setTimeout)(sublimitTimeout);
|
||||
let resolve;
|
||||
const promise = new Promise((res2) => resolve = res2);
|
||||
this.#sublimitPromise = { promise, resolve };
|
||||
if (firstSublimit) {
|
||||
await this.#asyncQueue.wait();
|
||||
this.#shiftSublimit = true;
|
||||
}
|
||||
}
|
||||
return this.runRequest(routeId, url, options, requestData, retries);
|
||||
} else if (status >= 500 && status < 600) {
|
||||
if (retries !== this.manager.options.retries) {
|
||||
return this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
throw new HTTPError(status, method, url, requestData);
|
||||
} else {
|
||||
if (status >= 400 && status < 500) {
|
||||
if (status === 401 && requestData.auth) {
|
||||
this.manager.setToken(null);
|
||||
}
|
||||
const data = await parseResponse(res);
|
||||
throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
};
|
||||
__name(SequentialHandler, "SequentialHandler");
|
||||
|
||||
// src/lib/RequestManager.ts
|
||||
var getFileType = (0, import_util.lazy)(async () => import("file-type"));
|
||||
var RequestMethod = /* @__PURE__ */ ((RequestMethod2) => {
|
||||
RequestMethod2["Delete"] = "DELETE";
|
||||
RequestMethod2["Get"] = "GET";
|
||||
RequestMethod2["Patch"] = "PATCH";
|
||||
RequestMethod2["Post"] = "POST";
|
||||
RequestMethod2["Put"] = "PUT";
|
||||
return RequestMethod2;
|
||||
})(RequestMethod || {});
|
||||
var RequestManager = class extends import_node_events.EventEmitter {
|
||||
agent = null;
|
||||
globalRemaining;
|
||||
globalDelay = null;
|
||||
globalReset = -1;
|
||||
hashes = new import_collection.Collection();
|
||||
handlers = new import_collection.Collection();
|
||||
#token = null;
|
||||
hashTimer;
|
||||
handlerTimer;
|
||||
options;
|
||||
constructor(options) {
|
||||
super();
|
||||
this.options = { ...DefaultRestOptions, ...options };
|
||||
this.options.offset = Math.max(0, this.options.offset);
|
||||
this.globalRemaining = this.options.globalRequestsPerSecond;
|
||||
this.agent = options.agent ?? null;
|
||||
this.setupSweepers();
|
||||
}
|
||||
setupSweepers() {
|
||||
const validateMaxInterval = /* @__PURE__ */ __name((interval) => {
|
||||
if (interval > 144e5) {
|
||||
throw new Error("Cannot set an interval greater than 4 hours");
|
||||
}
|
||||
}, "validateMaxInterval");
|
||||
if (this.options.hashSweepInterval !== 0 && this.options.hashSweepInterval !== Number.POSITIVE_INFINITY) {
|
||||
validateMaxInterval(this.options.hashSweepInterval);
|
||||
this.hashTimer = (0, import_node_timers2.setInterval)(() => {
|
||||
const sweptHashes = new import_collection.Collection();
|
||||
const currentDate = Date.now();
|
||||
this.hashes.sweep((val, key) => {
|
||||
if (val.lastAccess === -1)
|
||||
return false;
|
||||
const shouldSweep = Math.floor(currentDate - val.lastAccess) > this.options.hashLifetime;
|
||||
if (shouldSweep) {
|
||||
sweptHashes.set(key, val);
|
||||
}
|
||||
this.emit("restDebug" /* Debug */, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
|
||||
return shouldSweep;
|
||||
});
|
||||
this.emit("hashSweep" /* HashSweep */, sweptHashes);
|
||||
}, this.options.hashSweepInterval).unref();
|
||||
}
|
||||
if (this.options.handlerSweepInterval !== 0 && this.options.handlerSweepInterval !== Number.POSITIVE_INFINITY) {
|
||||
validateMaxInterval(this.options.handlerSweepInterval);
|
||||
this.handlerTimer = (0, import_node_timers2.setInterval)(() => {
|
||||
const sweptHandlers = new import_collection.Collection();
|
||||
this.handlers.sweep((val, key) => {
|
||||
const { inactive } = val;
|
||||
if (inactive) {
|
||||
sweptHandlers.set(key, val);
|
||||
}
|
||||
this.emit("restDebug" /* Debug */, `Handler ${val.id} for ${key} swept due to being inactive`);
|
||||
return inactive;
|
||||
});
|
||||
this.emit("handlerSweep" /* HandlerSweep */, sweptHandlers);
|
||||
}, this.options.handlerSweepInterval).unref();
|
||||
}
|
||||
}
|
||||
setAgent(agent) {
|
||||
this.agent = agent;
|
||||
return this;
|
||||
}
|
||||
setToken(token) {
|
||||
this.#token = token;
|
||||
return this;
|
||||
}
|
||||
async queueRequest(request2) {
|
||||
const routeId = RequestManager.generateRouteData(request2.fullRoute, request2.method);
|
||||
const hash = this.hashes.get(`${request2.method}:${routeId.bucketRoute}`) ?? {
|
||||
value: `Global(${request2.method}:${routeId.bucketRoute})`,
|
||||
lastAccess: -1
|
||||
};
|
||||
const handler = this.handlers.get(`${hash.value}:${routeId.majorParameter}`) ?? this.createHandler(hash.value, routeId.majorParameter);
|
||||
const { url, fetchOptions } = await this.resolveRequest(request2);
|
||||
return handler.queueRequest(routeId, url, fetchOptions, {
|
||||
body: request2.body,
|
||||
files: request2.files,
|
||||
auth: request2.auth !== false,
|
||||
signal: request2.signal
|
||||
});
|
||||
}
|
||||
createHandler(hash, majorParameter) {
|
||||
const queue = new SequentialHandler(this, hash, majorParameter);
|
||||
this.handlers.set(queue.id, queue);
|
||||
return queue;
|
||||
}
|
||||
async resolveRequest(request2) {
|
||||
const { options } = this;
|
||||
let query = "";
|
||||
if (request2.query) {
|
||||
const resolvedQuery = request2.query.toString();
|
||||
if (resolvedQuery !== "") {
|
||||
query = `?${resolvedQuery}`;
|
||||
}
|
||||
}
|
||||
const headers = {
|
||||
...this.options.headers,
|
||||
"User-Agent": `${DefaultUserAgent} ${options.userAgentAppendix}`.trim()
|
||||
};
|
||||
if (request2.auth !== false) {
|
||||
if (!this.#token) {
|
||||
throw new Error("Expected token to be set for this request, but none was present");
|
||||
}
|
||||
headers.Authorization = `${request2.authPrefix ?? this.options.authPrefix} ${this.#token}`;
|
||||
}
|
||||
if (request2.reason?.length) {
|
||||
headers["X-Audit-Log-Reason"] = encodeURIComponent(request2.reason);
|
||||
}
|
||||
const url = `${options.api}${request2.versioned === false ? "" : `/v${options.version}`}${request2.fullRoute}${query}`;
|
||||
let finalBody;
|
||||
let additionalHeaders = {};
|
||||
if (request2.files?.length) {
|
||||
const formData = new import_undici4.FormData();
|
||||
for (const [index, file] of request2.files.entries()) {
|
||||
const fileKey = file.key ?? `files[${index}]`;
|
||||
if (import_node_buffer2.Buffer.isBuffer(file.data)) {
|
||||
const { fileTypeFromBuffer } = await getFileType();
|
||||
const contentType = file.contentType ?? (await fileTypeFromBuffer(file.data))?.mime;
|
||||
formData.append(fileKey, new import_node_buffer2.Blob([file.data], { type: contentType }), file.name);
|
||||
} else {
|
||||
formData.append(fileKey, new import_node_buffer2.Blob([`${file.data}`], { type: file.contentType }), file.name);
|
||||
}
|
||||
}
|
||||
if (request2.body != null) {
|
||||
if (request2.appendToFormData) {
|
||||
for (const [key, value] of Object.entries(request2.body)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
} else {
|
||||
formData.append("payload_json", JSON.stringify(request2.body));
|
||||
}
|
||||
}
|
||||
finalBody = formData;
|
||||
} else if (request2.body != null) {
|
||||
if (request2.passThroughBody) {
|
||||
finalBody = request2.body;
|
||||
} else {
|
||||
finalBody = JSON.stringify(request2.body);
|
||||
additionalHeaders = { "Content-Type": "application/json" };
|
||||
}
|
||||
}
|
||||
finalBody = await resolveBody(finalBody);
|
||||
const fetchOptions = {
|
||||
headers: { ...request2.headers, ...additionalHeaders, ...headers },
|
||||
method: request2.method.toUpperCase()
|
||||
};
|
||||
if (finalBody !== void 0) {
|
||||
fetchOptions.body = finalBody;
|
||||
}
|
||||
fetchOptions.dispatcher = request2.dispatcher ?? this.agent ?? void 0;
|
||||
return { url, fetchOptions };
|
||||
}
|
||||
clearHashSweeper() {
|
||||
(0, import_node_timers2.clearInterval)(this.hashTimer);
|
||||
}
|
||||
clearHandlerSweeper() {
|
||||
(0, import_node_timers2.clearInterval)(this.handlerTimer);
|
||||
}
|
||||
static generateRouteData(endpoint, method) {
|
||||
const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{16,19})/.exec(endpoint);
|
||||
const majorId = majorIdMatch?.[1] ?? "global";
|
||||
const baseRoute = endpoint.replaceAll(/\d{16,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
|
||||
let exceptions = "";
|
||||
if (method === "DELETE" /* Delete */ && baseRoute === "/channels/:id/messages/:id") {
|
||||
const id = /\d{16,19}$/.exec(endpoint)[0];
|
||||
const timestamp = import_snowflake.DiscordSnowflake.timestampFrom(id);
|
||||
if (Date.now() - timestamp > 1e3 * 60 * 60 * 24 * 14) {
|
||||
exceptions += "/Delete Old Message";
|
||||
}
|
||||
}
|
||||
return {
|
||||
majorParameter: majorId,
|
||||
bucketRoute: baseRoute + exceptions,
|
||||
original: endpoint
|
||||
};
|
||||
}
|
||||
};
|
||||
__name(RequestManager, "RequestManager");
|
||||
|
||||
// src/lib/REST.ts
|
||||
var import_node_events2 = require("events");
|
||||
var REST = class extends import_node_events2.EventEmitter {
|
||||
cdn;
|
||||
requestManager;
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
this.cdn = new CDN(options.cdn ?? DefaultRestOptions.cdn);
|
||||
this.requestManager = new RequestManager(options).on("restDebug" /* Debug */, this.emit.bind(this, "restDebug" /* Debug */)).on("rateLimited" /* RateLimited */, this.emit.bind(this, "rateLimited" /* RateLimited */)).on("invalidRequestWarning" /* InvalidRequestWarning */, this.emit.bind(this, "invalidRequestWarning" /* InvalidRequestWarning */)).on("hashSweep" /* HashSweep */, this.emit.bind(this, "hashSweep" /* HashSweep */));
|
||||
this.on("newListener", (name, listener) => {
|
||||
if (name === "response" /* Response */)
|
||||
this.requestManager.on(name, listener);
|
||||
});
|
||||
this.on("removeListener", (name, listener) => {
|
||||
if (name === "response" /* Response */)
|
||||
this.requestManager.off(name, listener);
|
||||
});
|
||||
}
|
||||
getAgent() {
|
||||
return this.requestManager.agent;
|
||||
}
|
||||
setAgent(agent) {
|
||||
this.requestManager.setAgent(agent);
|
||||
return this;
|
||||
}
|
||||
setToken(token) {
|
||||
this.requestManager.setToken(token);
|
||||
return this;
|
||||
}
|
||||
async get(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "GET" /* Get */ });
|
||||
}
|
||||
async delete(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "DELETE" /* Delete */ });
|
||||
}
|
||||
async post(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "POST" /* Post */ });
|
||||
}
|
||||
async put(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "PUT" /* Put */ });
|
||||
}
|
||||
async patch(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "PATCH" /* Patch */ });
|
||||
}
|
||||
async request(options) {
|
||||
const response = await this.raw(options);
|
||||
return parseResponse(response);
|
||||
}
|
||||
async raw(options) {
|
||||
return this.requestManager.queueRequest(options);
|
||||
}
|
||||
};
|
||||
__name(REST, "REST");
|
||||
|
||||
// src/index.ts
|
||||
var version = "1.5.0";
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
ALLOWED_EXTENSIONS,
|
||||
ALLOWED_SIZES,
|
||||
ALLOWED_STICKER_EXTENSIONS,
|
||||
CDN,
|
||||
DefaultRestOptions,
|
||||
DefaultUserAgent,
|
||||
DiscordAPIError,
|
||||
HTTPError,
|
||||
REST,
|
||||
RESTEvents,
|
||||
RateLimitError,
|
||||
RequestManager,
|
||||
RequestMethod,
|
||||
makeURLSearchParams,
|
||||
parseResponse,
|
||||
version
|
||||
});
|
||||
//# sourceMappingURL=index.js.map
|
1
node_modules/@discordjs/rest/dist/index.js.map
generated
vendored
Normal file
1
node_modules/@discordjs/rest/dist/index.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
894
node_modules/@discordjs/rest/dist/index.mjs
generated
vendored
Normal file
894
node_modules/@discordjs/rest/dist/index.mjs
generated
vendored
Normal file
|
@ -0,0 +1,894 @@
|
|||
var __defProp = Object.defineProperty;
|
||||
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
||||
|
||||
// src/lib/CDN.ts
|
||||
import { URL } from "node:url";
|
||||
|
||||
// src/lib/utils/constants.ts
|
||||
import process from "node:process";
|
||||
import { APIVersion } from "discord-api-types/v10";
|
||||
import { Agent } from "undici";
|
||||
var DefaultUserAgent = `DiscordBot (https://discord.js.org, 1.5.0)`;
|
||||
var DefaultRestOptions = {
|
||||
get agent() {
|
||||
return new Agent({
|
||||
connect: {
|
||||
timeout: 3e4
|
||||
}
|
||||
});
|
||||
},
|
||||
api: "https://discord.com/api",
|
||||
authPrefix: "Bot",
|
||||
cdn: "https://cdn.discordapp.com",
|
||||
headers: {},
|
||||
invalidRequestWarningInterval: 0,
|
||||
globalRequestsPerSecond: 50,
|
||||
offset: 50,
|
||||
rejectOnRateLimit: null,
|
||||
retries: 3,
|
||||
timeout: 15e3,
|
||||
userAgentAppendix: `Node.js ${process.version}`,
|
||||
version: APIVersion,
|
||||
hashSweepInterval: 144e5,
|
||||
hashLifetime: 864e5,
|
||||
handlerSweepInterval: 36e5
|
||||
};
|
||||
var RESTEvents = /* @__PURE__ */ ((RESTEvents2) => {
|
||||
RESTEvents2["Debug"] = "restDebug";
|
||||
RESTEvents2["HandlerSweep"] = "handlerSweep";
|
||||
RESTEvents2["HashSweep"] = "hashSweep";
|
||||
RESTEvents2["InvalidRequestWarning"] = "invalidRequestWarning";
|
||||
RESTEvents2["RateLimited"] = "rateLimited";
|
||||
RESTEvents2["Response"] = "response";
|
||||
return RESTEvents2;
|
||||
})(RESTEvents || {});
|
||||
var ALLOWED_EXTENSIONS = ["webp", "png", "jpg", "jpeg", "gif"];
|
||||
var ALLOWED_STICKER_EXTENSIONS = ["png", "json"];
|
||||
var ALLOWED_SIZES = [16, 32, 64, 128, 256, 512, 1024, 2048, 4096];
|
||||
|
||||
// src/lib/CDN.ts
|
||||
var CDN = class {
|
||||
constructor(base = DefaultRestOptions.cdn) {
|
||||
this.base = base;
|
||||
}
|
||||
appAsset(clientId, assetHash, options) {
|
||||
return this.makeURL(`/app-assets/${clientId}/${assetHash}`, options);
|
||||
}
|
||||
appIcon(clientId, iconHash, options) {
|
||||
return this.makeURL(`/app-icons/${clientId}/${iconHash}`, options);
|
||||
}
|
||||
avatar(id, avatarHash, options) {
|
||||
return this.dynamicMakeURL(`/avatars/${id}/${avatarHash}`, avatarHash, options);
|
||||
}
|
||||
banner(id, bannerHash, options) {
|
||||
return this.dynamicMakeURL(`/banners/${id}/${bannerHash}`, bannerHash, options);
|
||||
}
|
||||
channelIcon(channelId, iconHash, options) {
|
||||
return this.makeURL(`/channel-icons/${channelId}/${iconHash}`, options);
|
||||
}
|
||||
defaultAvatar(discriminator) {
|
||||
return this.makeURL(`/embed/avatars/${discriminator}`, { extension: "png" });
|
||||
}
|
||||
discoverySplash(guildId, splashHash, options) {
|
||||
return this.makeURL(`/discovery-splashes/${guildId}/${splashHash}`, options);
|
||||
}
|
||||
emoji(emojiId, extension) {
|
||||
return this.makeURL(`/emojis/${emojiId}`, { extension });
|
||||
}
|
||||
guildMemberAvatar(guildId, userId, avatarHash, options) {
|
||||
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/avatars/${avatarHash}`, avatarHash, options);
|
||||
}
|
||||
guildMemberBanner(guildId, userId, bannerHash, options) {
|
||||
return this.dynamicMakeURL(`/guilds/${guildId}/users/${userId}/banner`, bannerHash, options);
|
||||
}
|
||||
icon(id, iconHash, options) {
|
||||
return this.dynamicMakeURL(`/icons/${id}/${iconHash}`, iconHash, options);
|
||||
}
|
||||
roleIcon(roleId, roleIconHash, options) {
|
||||
return this.makeURL(`/role-icons/${roleId}/${roleIconHash}`, options);
|
||||
}
|
||||
splash(guildId, splashHash, options) {
|
||||
return this.makeURL(`/splashes/${guildId}/${splashHash}`, options);
|
||||
}
|
||||
sticker(stickerId, extension) {
|
||||
return this.makeURL(`/stickers/${stickerId}`, {
|
||||
allowedExtensions: ALLOWED_STICKER_EXTENSIONS,
|
||||
extension: extension ?? "png"
|
||||
});
|
||||
}
|
||||
stickerPackBanner(bannerId, options) {
|
||||
return this.makeURL(`/app-assets/710982414301790216/store/${bannerId}`, options);
|
||||
}
|
||||
teamIcon(teamId, iconHash, options) {
|
||||
return this.makeURL(`/team-icons/${teamId}/${iconHash}`, options);
|
||||
}
|
||||
guildScheduledEventCover(scheduledEventId, coverHash, options) {
|
||||
return this.makeURL(`/guild-events/${scheduledEventId}/${coverHash}`, options);
|
||||
}
|
||||
dynamicMakeURL(route, hash, { forceStatic = false, ...options } = {}) {
|
||||
return this.makeURL(route, !forceStatic && hash.startsWith("a_") ? { ...options, extension: "gif" } : options);
|
||||
}
|
||||
makeURL(route, { allowedExtensions = ALLOWED_EXTENSIONS, extension = "webp", size } = {}) {
|
||||
extension = String(extension).toLowerCase();
|
||||
if (!allowedExtensions.includes(extension)) {
|
||||
throw new RangeError(`Invalid extension provided: ${extension}
|
||||
Must be one of: ${allowedExtensions.join(", ")}`);
|
||||
}
|
||||
if (size && !ALLOWED_SIZES.includes(size)) {
|
||||
throw new RangeError(`Invalid size provided: ${size}
|
||||
Must be one of: ${ALLOWED_SIZES.join(", ")}`);
|
||||
}
|
||||
const url = new URL(`${this.base}${route}.${extension}`);
|
||||
if (size) {
|
||||
url.searchParams.set("size", String(size));
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
};
|
||||
__name(CDN, "CDN");
|
||||
|
||||
// src/lib/errors/DiscordAPIError.ts
|
||||
function isErrorGroupWrapper(error) {
|
||||
return Reflect.has(error, "_errors");
|
||||
}
|
||||
__name(isErrorGroupWrapper, "isErrorGroupWrapper");
|
||||
function isErrorResponse(error) {
|
||||
return typeof Reflect.get(error, "message") === "string";
|
||||
}
|
||||
__name(isErrorResponse, "isErrorResponse");
|
||||
var DiscordAPIError = class extends Error {
|
||||
constructor(rawError, code, status, method, url, bodyData) {
|
||||
super(DiscordAPIError.getMessage(rawError));
|
||||
this.rawError = rawError;
|
||||
this.code = code;
|
||||
this.status = status;
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.requestBody = { files: bodyData.files, json: bodyData.body };
|
||||
}
|
||||
requestBody;
|
||||
get name() {
|
||||
return `${DiscordAPIError.name}[${this.code}]`;
|
||||
}
|
||||
static getMessage(error) {
|
||||
let flattened = "";
|
||||
if ("code" in error) {
|
||||
if (error.errors) {
|
||||
flattened = [...this.flattenDiscordError(error.errors)].join("\n");
|
||||
}
|
||||
return error.message && flattened ? `${error.message}
|
||||
${flattened}` : error.message || flattened || "Unknown Error";
|
||||
}
|
||||
return error.error_description ?? "No Description";
|
||||
}
|
||||
static *flattenDiscordError(obj, key = "") {
|
||||
if (isErrorResponse(obj)) {
|
||||
return yield `${key.length ? `${key}[${obj.code}]` : `${obj.code}`}: ${obj.message}`.trim();
|
||||
}
|
||||
for (const [otherKey, val] of Object.entries(obj)) {
|
||||
const nextKey = otherKey.startsWith("_") ? key : key ? Number.isNaN(Number(otherKey)) ? `${key}.${otherKey}` : `${key}[${otherKey}]` : otherKey;
|
||||
if (typeof val === "string") {
|
||||
yield val;
|
||||
} else if (isErrorGroupWrapper(val)) {
|
||||
for (const error of val._errors) {
|
||||
yield* this.flattenDiscordError(error, nextKey);
|
||||
}
|
||||
} else {
|
||||
yield* this.flattenDiscordError(val, nextKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
__name(DiscordAPIError, "DiscordAPIError");
|
||||
|
||||
// src/lib/errors/HTTPError.ts
|
||||
import { STATUS_CODES } from "node:http";
|
||||
var HTTPError = class extends Error {
|
||||
constructor(status, method, url, bodyData) {
|
||||
super(STATUS_CODES[status]);
|
||||
this.status = status;
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.requestBody = { files: bodyData.files, json: bodyData.body };
|
||||
}
|
||||
requestBody;
|
||||
name = HTTPError.name;
|
||||
};
|
||||
__name(HTTPError, "HTTPError");
|
||||
|
||||
// src/lib/errors/RateLimitError.ts
|
||||
var RateLimitError = class extends Error {
|
||||
timeToReset;
|
||||
limit;
|
||||
method;
|
||||
hash;
|
||||
url;
|
||||
route;
|
||||
majorParameter;
|
||||
global;
|
||||
constructor({ timeToReset, limit, method, hash, url, route, majorParameter, global }) {
|
||||
super();
|
||||
this.timeToReset = timeToReset;
|
||||
this.limit = limit;
|
||||
this.method = method;
|
||||
this.hash = hash;
|
||||
this.url = url;
|
||||
this.route = route;
|
||||
this.majorParameter = majorParameter;
|
||||
this.global = global;
|
||||
}
|
||||
get name() {
|
||||
return `${RateLimitError.name}[${this.route}]`;
|
||||
}
|
||||
};
|
||||
__name(RateLimitError, "RateLimitError");
|
||||
|
||||
// src/lib/RequestManager.ts
|
||||
import { Blob as Blob2, Buffer as Buffer3 } from "node:buffer";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { setInterval, clearInterval } from "node:timers";
|
||||
import { Collection } from "@discordjs/collection";
|
||||
import { lazy } from "@discordjs/util";
|
||||
import { DiscordSnowflake } from "@sapphire/snowflake";
|
||||
import { FormData as FormData2 } from "undici";
|
||||
|
||||
// src/lib/handlers/SequentialHandler.ts
|
||||
import { setTimeout, clearTimeout } from "node:timers";
|
||||
import { setTimeout as sleep } from "node:timers/promises";
|
||||
import { AsyncQueue } from "@sapphire/async-queue";
|
||||
import { request } from "undici";
|
||||
|
||||
// src/lib/utils/utils.ts
|
||||
import { Blob, Buffer as Buffer2 } from "node:buffer";
|
||||
import { URLSearchParams } from "node:url";
|
||||
import { types } from "node:util";
|
||||
import { FormData } from "undici";
|
||||
function parseHeader(header) {
|
||||
if (header === void 0 || typeof header === "string") {
|
||||
return header;
|
||||
}
|
||||
return header.join(";");
|
||||
}
|
||||
__name(parseHeader, "parseHeader");
|
||||
function serializeSearchParam(value) {
|
||||
switch (typeof value) {
|
||||
case "string":
|
||||
return value;
|
||||
case "number":
|
||||
case "bigint":
|
||||
case "boolean":
|
||||
return value.toString();
|
||||
case "object":
|
||||
if (value === null)
|
||||
return null;
|
||||
if (value instanceof Date) {
|
||||
return Number.isNaN(value.getTime()) ? null : value.toISOString();
|
||||
}
|
||||
if (typeof value.toString === "function" && value.toString !== Object.prototype.toString)
|
||||
return value.toString();
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
__name(serializeSearchParam, "serializeSearchParam");
|
||||
function makeURLSearchParams(options) {
|
||||
const params = new URLSearchParams();
|
||||
if (!options)
|
||||
return params;
|
||||
for (const [key, value] of Object.entries(options)) {
|
||||
const serialized = serializeSearchParam(value);
|
||||
if (serialized !== null)
|
||||
params.append(key, serialized);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
__name(makeURLSearchParams, "makeURLSearchParams");
|
||||
async function parseResponse(res) {
|
||||
const header = parseHeader(res.headers["content-type"]);
|
||||
if (header?.startsWith("application/json")) {
|
||||
return res.body.json();
|
||||
}
|
||||
return res.body.arrayBuffer();
|
||||
}
|
||||
__name(parseResponse, "parseResponse");
|
||||
function hasSublimit(bucketRoute, body, method) {
|
||||
if (bucketRoute === "/channels/:id") {
|
||||
if (typeof body !== "object" || body === null)
|
||||
return false;
|
||||
if (method !== "PATCH" /* Patch */)
|
||||
return false;
|
||||
const castedBody = body;
|
||||
return ["name", "topic"].some((key) => Reflect.has(castedBody, key));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
__name(hasSublimit, "hasSublimit");
|
||||
async function resolveBody(body) {
|
||||
if (body == null) {
|
||||
return null;
|
||||
} else if (typeof body === "string") {
|
||||
return body;
|
||||
} else if (types.isUint8Array(body)) {
|
||||
return body;
|
||||
} else if (types.isArrayBuffer(body)) {
|
||||
return new Uint8Array(body);
|
||||
} else if (body instanceof URLSearchParams) {
|
||||
return body.toString();
|
||||
} else if (body instanceof DataView) {
|
||||
return new Uint8Array(body.buffer);
|
||||
} else if (body instanceof Blob) {
|
||||
return new Uint8Array(await body.arrayBuffer());
|
||||
} else if (body instanceof FormData) {
|
||||
return body;
|
||||
} else if (body[Symbol.iterator]) {
|
||||
const chunks = [...body];
|
||||
const length = chunks.reduce((a, b) => a + b.length, 0);
|
||||
const uint8 = new Uint8Array(length);
|
||||
let lengthUsed = 0;
|
||||
return chunks.reduce((a, b) => {
|
||||
a.set(b, lengthUsed);
|
||||
lengthUsed += b.length;
|
||||
return a;
|
||||
}, uint8);
|
||||
} else if (body[Symbol.asyncIterator]) {
|
||||
const chunks = [];
|
||||
for await (const chunk of body) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
return Buffer2.concat(chunks);
|
||||
}
|
||||
throw new TypeError(`Unable to resolve body.`);
|
||||
}
|
||||
__name(resolveBody, "resolveBody");
|
||||
function shouldRetry(error) {
|
||||
if (error.name === "AbortError")
|
||||
return true;
|
||||
return "code" in error && error.code === "ECONNRESET" || error.message.includes("ECONNRESET");
|
||||
}
|
||||
__name(shouldRetry, "shouldRetry");
|
||||
|
||||
// src/lib/handlers/SequentialHandler.ts
|
||||
var invalidCount = 0;
|
||||
var invalidCountResetTime = null;
|
||||
var SequentialHandler = class {
|
||||
constructor(manager, hash, majorParameter) {
|
||||
this.manager = manager;
|
||||
this.hash = hash;
|
||||
this.majorParameter = majorParameter;
|
||||
this.id = `${hash}:${majorParameter}`;
|
||||
}
|
||||
id;
|
||||
reset = -1;
|
||||
remaining = 1;
|
||||
limit = Number.POSITIVE_INFINITY;
|
||||
#asyncQueue = new AsyncQueue();
|
||||
#sublimitedQueue = null;
|
||||
#sublimitPromise = null;
|
||||
#shiftSublimit = false;
|
||||
get inactive() {
|
||||
return this.#asyncQueue.remaining === 0 && (this.#sublimitedQueue === null || this.#sublimitedQueue.remaining === 0) && !this.limited;
|
||||
}
|
||||
get globalLimited() {
|
||||
return this.manager.globalRemaining <= 0 && Date.now() < this.manager.globalReset;
|
||||
}
|
||||
get localLimited() {
|
||||
return this.remaining <= 0 && Date.now() < this.reset;
|
||||
}
|
||||
get limited() {
|
||||
return this.globalLimited || this.localLimited;
|
||||
}
|
||||
get timeToReset() {
|
||||
return this.reset + this.manager.options.offset - Date.now();
|
||||
}
|
||||
debug(message) {
|
||||
this.manager.emit("restDebug" /* Debug */, `[REST ${this.id}] ${message}`);
|
||||
}
|
||||
async globalDelayFor(time) {
|
||||
await sleep(time);
|
||||
this.manager.globalDelay = null;
|
||||
}
|
||||
async onRateLimit(rateLimitData) {
|
||||
const { options } = this.manager;
|
||||
if (!options.rejectOnRateLimit)
|
||||
return;
|
||||
const shouldThrow = typeof options.rejectOnRateLimit === "function" ? await options.rejectOnRateLimit(rateLimitData) : options.rejectOnRateLimit.some((route) => rateLimitData.route.startsWith(route.toLowerCase()));
|
||||
if (shouldThrow) {
|
||||
throw new RateLimitError(rateLimitData);
|
||||
}
|
||||
}
|
||||
async queueRequest(routeId, url, options, requestData) {
|
||||
let queue = this.#asyncQueue;
|
||||
let queueType = 0 /* Standard */;
|
||||
if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
|
||||
queue = this.#sublimitedQueue;
|
||||
queueType = 1 /* Sublimit */;
|
||||
}
|
||||
await queue.wait({ signal: requestData.signal });
|
||||
if (queueType === 0 /* Standard */) {
|
||||
if (this.#sublimitedQueue && hasSublimit(routeId.bucketRoute, requestData.body, options.method)) {
|
||||
queue = this.#sublimitedQueue;
|
||||
const wait = queue.wait();
|
||||
this.#asyncQueue.shift();
|
||||
await wait;
|
||||
} else if (this.#sublimitPromise) {
|
||||
await this.#sublimitPromise.promise;
|
||||
}
|
||||
}
|
||||
try {
|
||||
return await this.runRequest(routeId, url, options, requestData);
|
||||
} finally {
|
||||
queue.shift();
|
||||
if (this.#shiftSublimit) {
|
||||
this.#shiftSublimit = false;
|
||||
this.#sublimitedQueue?.shift();
|
||||
}
|
||||
if (this.#sublimitedQueue?.remaining === 0) {
|
||||
this.#sublimitPromise?.resolve();
|
||||
this.#sublimitedQueue = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
async runRequest(routeId, url, options, requestData, retries = 0) {
|
||||
while (this.limited) {
|
||||
const isGlobal = this.globalLimited;
|
||||
let limit2;
|
||||
let timeout2;
|
||||
let delay;
|
||||
if (isGlobal) {
|
||||
limit2 = this.manager.options.globalRequestsPerSecond;
|
||||
timeout2 = this.manager.globalReset + this.manager.options.offset - Date.now();
|
||||
if (!this.manager.globalDelay) {
|
||||
this.manager.globalDelay = this.globalDelayFor(timeout2);
|
||||
}
|
||||
delay = this.manager.globalDelay;
|
||||
} else {
|
||||
limit2 = this.limit;
|
||||
timeout2 = this.timeToReset;
|
||||
delay = sleep(timeout2);
|
||||
}
|
||||
const rateLimitData = {
|
||||
timeToReset: timeout2,
|
||||
limit: limit2,
|
||||
method: options.method ?? "get",
|
||||
hash: this.hash,
|
||||
url,
|
||||
route: routeId.bucketRoute,
|
||||
majorParameter: this.majorParameter,
|
||||
global: isGlobal
|
||||
};
|
||||
this.manager.emit("rateLimited" /* RateLimited */, rateLimitData);
|
||||
await this.onRateLimit(rateLimitData);
|
||||
if (isGlobal) {
|
||||
this.debug(`Global rate limit hit, blocking all requests for ${timeout2}ms`);
|
||||
} else {
|
||||
this.debug(`Waiting ${timeout2}ms for rate limit to pass`);
|
||||
}
|
||||
await delay;
|
||||
}
|
||||
if (!this.manager.globalReset || this.manager.globalReset < Date.now()) {
|
||||
this.manager.globalReset = Date.now() + 1e3;
|
||||
this.manager.globalRemaining = this.manager.options.globalRequestsPerSecond;
|
||||
}
|
||||
this.manager.globalRemaining--;
|
||||
const method = options.method ?? "get";
|
||||
const controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller.abort(), this.manager.options.timeout).unref();
|
||||
if (requestData.signal) {
|
||||
const signal = requestData.signal;
|
||||
if (signal.aborted)
|
||||
controller.abort();
|
||||
else
|
||||
signal.addEventListener("abort", () => controller.abort());
|
||||
}
|
||||
let res;
|
||||
try {
|
||||
res = await request(url, { ...options, signal: controller.signal });
|
||||
} catch (error) {
|
||||
if (!(error instanceof Error))
|
||||
throw error;
|
||||
if (shouldRetry(error) && retries !== this.manager.options.retries) {
|
||||
return await this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
if (this.manager.listenerCount("response" /* Response */)) {
|
||||
this.manager.emit(
|
||||
"response" /* Response */,
|
||||
{
|
||||
method,
|
||||
path: routeId.original,
|
||||
route: routeId.bucketRoute,
|
||||
options,
|
||||
data: requestData,
|
||||
retries
|
||||
},
|
||||
{ ...res }
|
||||
);
|
||||
}
|
||||
const status = res.statusCode;
|
||||
let retryAfter = 0;
|
||||
const limit = parseHeader(res.headers["x-ratelimit-limit"]);
|
||||
const remaining = parseHeader(res.headers["x-ratelimit-remaining"]);
|
||||
const reset = parseHeader(res.headers["x-ratelimit-reset-after"]);
|
||||
const hash = parseHeader(res.headers["x-ratelimit-bucket"]);
|
||||
const retry = parseHeader(res.headers["retry-after"]);
|
||||
this.limit = limit ? Number(limit) : Number.POSITIVE_INFINITY;
|
||||
this.remaining = remaining ? Number(remaining) : 1;
|
||||
this.reset = reset ? Number(reset) * 1e3 + Date.now() + this.manager.options.offset : Date.now();
|
||||
if (retry)
|
||||
retryAfter = Number(retry) * 1e3 + this.manager.options.offset;
|
||||
if (hash && hash !== this.hash) {
|
||||
this.debug(["Received bucket hash update", ` Old Hash : ${this.hash}`, ` New Hash : ${hash}`].join("\n"));
|
||||
this.manager.hashes.set(`${method}:${routeId.bucketRoute}`, { value: hash, lastAccess: Date.now() });
|
||||
} else if (hash) {
|
||||
const hashData = this.manager.hashes.get(`${method}:${routeId.bucketRoute}`);
|
||||
if (hashData) {
|
||||
hashData.lastAccess = Date.now();
|
||||
}
|
||||
}
|
||||
let sublimitTimeout = null;
|
||||
if (retryAfter > 0) {
|
||||
if (res.headers["x-ratelimit-global"] !== void 0) {
|
||||
this.manager.globalRemaining = 0;
|
||||
this.manager.globalReset = Date.now() + retryAfter;
|
||||
} else if (!this.localLimited) {
|
||||
sublimitTimeout = retryAfter;
|
||||
}
|
||||
}
|
||||
if (status === 401 || status === 403 || status === 429) {
|
||||
if (!invalidCountResetTime || invalidCountResetTime < Date.now()) {
|
||||
invalidCountResetTime = Date.now() + 1e3 * 60 * 10;
|
||||
invalidCount = 0;
|
||||
}
|
||||
invalidCount++;
|
||||
const emitInvalid = this.manager.options.invalidRequestWarningInterval > 0 && invalidCount % this.manager.options.invalidRequestWarningInterval === 0;
|
||||
if (emitInvalid) {
|
||||
this.manager.emit("invalidRequestWarning" /* InvalidRequestWarning */, {
|
||||
count: invalidCount,
|
||||
remainingTime: invalidCountResetTime - Date.now()
|
||||
});
|
||||
}
|
||||
}
|
||||
if (status >= 200 && status < 300) {
|
||||
return res;
|
||||
} else if (status === 429) {
|
||||
const isGlobal = this.globalLimited;
|
||||
let limit2;
|
||||
let timeout2;
|
||||
if (isGlobal) {
|
||||
limit2 = this.manager.options.globalRequestsPerSecond;
|
||||
timeout2 = this.manager.globalReset + this.manager.options.offset - Date.now();
|
||||
} else {
|
||||
limit2 = this.limit;
|
||||
timeout2 = this.timeToReset;
|
||||
}
|
||||
await this.onRateLimit({
|
||||
timeToReset: timeout2,
|
||||
limit: limit2,
|
||||
method,
|
||||
hash: this.hash,
|
||||
url,
|
||||
route: routeId.bucketRoute,
|
||||
majorParameter: this.majorParameter,
|
||||
global: isGlobal
|
||||
});
|
||||
this.debug(
|
||||
[
|
||||
"Encountered unexpected 429 rate limit",
|
||||
` Global : ${isGlobal.toString()}`,
|
||||
` Method : ${method}`,
|
||||
` URL : ${url}`,
|
||||
` Bucket : ${routeId.bucketRoute}`,
|
||||
` Major parameter: ${routeId.majorParameter}`,
|
||||
` Hash : ${this.hash}`,
|
||||
` Limit : ${limit2}`,
|
||||
` Retry After : ${retryAfter}ms`,
|
||||
` Sublimit : ${sublimitTimeout ? `${sublimitTimeout}ms` : "None"}`
|
||||
].join("\n")
|
||||
);
|
||||
if (sublimitTimeout) {
|
||||
const firstSublimit = !this.#sublimitedQueue;
|
||||
if (firstSublimit) {
|
||||
this.#sublimitedQueue = new AsyncQueue();
|
||||
void this.#sublimitedQueue.wait();
|
||||
this.#asyncQueue.shift();
|
||||
}
|
||||
this.#sublimitPromise?.resolve();
|
||||
this.#sublimitPromise = null;
|
||||
await sleep(sublimitTimeout);
|
||||
let resolve;
|
||||
const promise = new Promise((res2) => resolve = res2);
|
||||
this.#sublimitPromise = { promise, resolve };
|
||||
if (firstSublimit) {
|
||||
await this.#asyncQueue.wait();
|
||||
this.#shiftSublimit = true;
|
||||
}
|
||||
}
|
||||
return this.runRequest(routeId, url, options, requestData, retries);
|
||||
} else if (status >= 500 && status < 600) {
|
||||
if (retries !== this.manager.options.retries) {
|
||||
return this.runRequest(routeId, url, options, requestData, ++retries);
|
||||
}
|
||||
throw new HTTPError(status, method, url, requestData);
|
||||
} else {
|
||||
if (status >= 400 && status < 500) {
|
||||
if (status === 401 && requestData.auth) {
|
||||
this.manager.setToken(null);
|
||||
}
|
||||
const data = await parseResponse(res);
|
||||
throw new DiscordAPIError(data, "code" in data ? data.code : data.error, status, method, url, requestData);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
};
|
||||
__name(SequentialHandler, "SequentialHandler");
|
||||
|
||||
// src/lib/RequestManager.ts
|
||||
var getFileType = lazy(async () => import("file-type"));
|
||||
var RequestMethod = /* @__PURE__ */ ((RequestMethod2) => {
|
||||
RequestMethod2["Delete"] = "DELETE";
|
||||
RequestMethod2["Get"] = "GET";
|
||||
RequestMethod2["Patch"] = "PATCH";
|
||||
RequestMethod2["Post"] = "POST";
|
||||
RequestMethod2["Put"] = "PUT";
|
||||
return RequestMethod2;
|
||||
})(RequestMethod || {});
|
||||
var RequestManager = class extends EventEmitter {
|
||||
agent = null;
|
||||
globalRemaining;
|
||||
globalDelay = null;
|
||||
globalReset = -1;
|
||||
hashes = new Collection();
|
||||
handlers = new Collection();
|
||||
#token = null;
|
||||
hashTimer;
|
||||
handlerTimer;
|
||||
options;
|
||||
constructor(options) {
|
||||
super();
|
||||
this.options = { ...DefaultRestOptions, ...options };
|
||||
this.options.offset = Math.max(0, this.options.offset);
|
||||
this.globalRemaining = this.options.globalRequestsPerSecond;
|
||||
this.agent = options.agent ?? null;
|
||||
this.setupSweepers();
|
||||
}
|
||||
setupSweepers() {
|
||||
const validateMaxInterval = /* @__PURE__ */ __name((interval) => {
|
||||
if (interval > 144e5) {
|
||||
throw new Error("Cannot set an interval greater than 4 hours");
|
||||
}
|
||||
}, "validateMaxInterval");
|
||||
if (this.options.hashSweepInterval !== 0 && this.options.hashSweepInterval !== Number.POSITIVE_INFINITY) {
|
||||
validateMaxInterval(this.options.hashSweepInterval);
|
||||
this.hashTimer = setInterval(() => {
|
||||
const sweptHashes = new Collection();
|
||||
const currentDate = Date.now();
|
||||
this.hashes.sweep((val, key) => {
|
||||
if (val.lastAccess === -1)
|
||||
return false;
|
||||
const shouldSweep = Math.floor(currentDate - val.lastAccess) > this.options.hashLifetime;
|
||||
if (shouldSweep) {
|
||||
sweptHashes.set(key, val);
|
||||
}
|
||||
this.emit("restDebug" /* Debug */, `Hash ${val.value} for ${key} swept due to lifetime being exceeded`);
|
||||
return shouldSweep;
|
||||
});
|
||||
this.emit("hashSweep" /* HashSweep */, sweptHashes);
|
||||
}, this.options.hashSweepInterval).unref();
|
||||
}
|
||||
if (this.options.handlerSweepInterval !== 0 && this.options.handlerSweepInterval !== Number.POSITIVE_INFINITY) {
|
||||
validateMaxInterval(this.options.handlerSweepInterval);
|
||||
this.handlerTimer = setInterval(() => {
|
||||
const sweptHandlers = new Collection();
|
||||
this.handlers.sweep((val, key) => {
|
||||
const { inactive } = val;
|
||||
if (inactive) {
|
||||
sweptHandlers.set(key, val);
|
||||
}
|
||||
this.emit("restDebug" /* Debug */, `Handler ${val.id} for ${key} swept due to being inactive`);
|
||||
return inactive;
|
||||
});
|
||||
this.emit("handlerSweep" /* HandlerSweep */, sweptHandlers);
|
||||
}, this.options.handlerSweepInterval).unref();
|
||||
}
|
||||
}
|
||||
setAgent(agent) {
|
||||
this.agent = agent;
|
||||
return this;
|
||||
}
|
||||
setToken(token) {
|
||||
this.#token = token;
|
||||
return this;
|
||||
}
|
||||
async queueRequest(request2) {
|
||||
const routeId = RequestManager.generateRouteData(request2.fullRoute, request2.method);
|
||||
const hash = this.hashes.get(`${request2.method}:${routeId.bucketRoute}`) ?? {
|
||||
value: `Global(${request2.method}:${routeId.bucketRoute})`,
|
||||
lastAccess: -1
|
||||
};
|
||||
const handler = this.handlers.get(`${hash.value}:${routeId.majorParameter}`) ?? this.createHandler(hash.value, routeId.majorParameter);
|
||||
const { url, fetchOptions } = await this.resolveRequest(request2);
|
||||
return handler.queueRequest(routeId, url, fetchOptions, {
|
||||
body: request2.body,
|
||||
files: request2.files,
|
||||
auth: request2.auth !== false,
|
||||
signal: request2.signal
|
||||
});
|
||||
}
|
||||
createHandler(hash, majorParameter) {
|
||||
const queue = new SequentialHandler(this, hash, majorParameter);
|
||||
this.handlers.set(queue.id, queue);
|
||||
return queue;
|
||||
}
|
||||
async resolveRequest(request2) {
|
||||
const { options } = this;
|
||||
let query = "";
|
||||
if (request2.query) {
|
||||
const resolvedQuery = request2.query.toString();
|
||||
if (resolvedQuery !== "") {
|
||||
query = `?${resolvedQuery}`;
|
||||
}
|
||||
}
|
||||
const headers = {
|
||||
...this.options.headers,
|
||||
"User-Agent": `${DefaultUserAgent} ${options.userAgentAppendix}`.trim()
|
||||
};
|
||||
if (request2.auth !== false) {
|
||||
if (!this.#token) {
|
||||
throw new Error("Expected token to be set for this request, but none was present");
|
||||
}
|
||||
headers.Authorization = `${request2.authPrefix ?? this.options.authPrefix} ${this.#token}`;
|
||||
}
|
||||
if (request2.reason?.length) {
|
||||
headers["X-Audit-Log-Reason"] = encodeURIComponent(request2.reason);
|
||||
}
|
||||
const url = `${options.api}${request2.versioned === false ? "" : `/v${options.version}`}${request2.fullRoute}${query}`;
|
||||
let finalBody;
|
||||
let additionalHeaders = {};
|
||||
if (request2.files?.length) {
|
||||
const formData = new FormData2();
|
||||
for (const [index, file] of request2.files.entries()) {
|
||||
const fileKey = file.key ?? `files[${index}]`;
|
||||
if (Buffer3.isBuffer(file.data)) {
|
||||
const { fileTypeFromBuffer } = await getFileType();
|
||||
const contentType = file.contentType ?? (await fileTypeFromBuffer(file.data))?.mime;
|
||||
formData.append(fileKey, new Blob2([file.data], { type: contentType }), file.name);
|
||||
} else {
|
||||
formData.append(fileKey, new Blob2([`${file.data}`], { type: file.contentType }), file.name);
|
||||
}
|
||||
}
|
||||
if (request2.body != null) {
|
||||
if (request2.appendToFormData) {
|
||||
for (const [key, value] of Object.entries(request2.body)) {
|
||||
formData.append(key, value);
|
||||
}
|
||||
} else {
|
||||
formData.append("payload_json", JSON.stringify(request2.body));
|
||||
}
|
||||
}
|
||||
finalBody = formData;
|
||||
} else if (request2.body != null) {
|
||||
if (request2.passThroughBody) {
|
||||
finalBody = request2.body;
|
||||
} else {
|
||||
finalBody = JSON.stringify(request2.body);
|
||||
additionalHeaders = { "Content-Type": "application/json" };
|
||||
}
|
||||
}
|
||||
finalBody = await resolveBody(finalBody);
|
||||
const fetchOptions = {
|
||||
headers: { ...request2.headers, ...additionalHeaders, ...headers },
|
||||
method: request2.method.toUpperCase()
|
||||
};
|
||||
if (finalBody !== void 0) {
|
||||
fetchOptions.body = finalBody;
|
||||
}
|
||||
fetchOptions.dispatcher = request2.dispatcher ?? this.agent ?? void 0;
|
||||
return { url, fetchOptions };
|
||||
}
|
||||
clearHashSweeper() {
|
||||
clearInterval(this.hashTimer);
|
||||
}
|
||||
clearHandlerSweeper() {
|
||||
clearInterval(this.handlerTimer);
|
||||
}
|
||||
static generateRouteData(endpoint, method) {
|
||||
const majorIdMatch = /^\/(?:channels|guilds|webhooks)\/(\d{16,19})/.exec(endpoint);
|
||||
const majorId = majorIdMatch?.[1] ?? "global";
|
||||
const baseRoute = endpoint.replaceAll(/\d{16,19}/g, ":id").replace(/\/reactions\/(.*)/, "/reactions/:reaction");
|
||||
let exceptions = "";
|
||||
if (method === "DELETE" /* Delete */ && baseRoute === "/channels/:id/messages/:id") {
|
||||
const id = /\d{16,19}$/.exec(endpoint)[0];
|
||||
const timestamp = DiscordSnowflake.timestampFrom(id);
|
||||
if (Date.now() - timestamp > 1e3 * 60 * 60 * 24 * 14) {
|
||||
exceptions += "/Delete Old Message";
|
||||
}
|
||||
}
|
||||
return {
|
||||
majorParameter: majorId,
|
||||
bucketRoute: baseRoute + exceptions,
|
||||
original: endpoint
|
||||
};
|
||||
}
|
||||
};
|
||||
__name(RequestManager, "RequestManager");
|
||||
|
||||
// src/lib/REST.ts
|
||||
import { EventEmitter as EventEmitter2 } from "node:events";
|
||||
var REST = class extends EventEmitter2 {
|
||||
cdn;
|
||||
requestManager;
|
||||
constructor(options = {}) {
|
||||
super();
|
||||
this.cdn = new CDN(options.cdn ?? DefaultRestOptions.cdn);
|
||||
this.requestManager = new RequestManager(options).on("restDebug" /* Debug */, this.emit.bind(this, "restDebug" /* Debug */)).on("rateLimited" /* RateLimited */, this.emit.bind(this, "rateLimited" /* RateLimited */)).on("invalidRequestWarning" /* InvalidRequestWarning */, this.emit.bind(this, "invalidRequestWarning" /* InvalidRequestWarning */)).on("hashSweep" /* HashSweep */, this.emit.bind(this, "hashSweep" /* HashSweep */));
|
||||
this.on("newListener", (name, listener) => {
|
||||
if (name === "response" /* Response */)
|
||||
this.requestManager.on(name, listener);
|
||||
});
|
||||
this.on("removeListener", (name, listener) => {
|
||||
if (name === "response" /* Response */)
|
||||
this.requestManager.off(name, listener);
|
||||
});
|
||||
}
|
||||
getAgent() {
|
||||
return this.requestManager.agent;
|
||||
}
|
||||
setAgent(agent) {
|
||||
this.requestManager.setAgent(agent);
|
||||
return this;
|
||||
}
|
||||
setToken(token) {
|
||||
this.requestManager.setToken(token);
|
||||
return this;
|
||||
}
|
||||
async get(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "GET" /* Get */ });
|
||||
}
|
||||
async delete(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "DELETE" /* Delete */ });
|
||||
}
|
||||
async post(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "POST" /* Post */ });
|
||||
}
|
||||
async put(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "PUT" /* Put */ });
|
||||
}
|
||||
async patch(fullRoute, options = {}) {
|
||||
return this.request({ ...options, fullRoute, method: "PATCH" /* Patch */ });
|
||||
}
|
||||
async request(options) {
|
||||
const response = await this.raw(options);
|
||||
return parseResponse(response);
|
||||
}
|
||||
async raw(options) {
|
||||
return this.requestManager.queueRequest(options);
|
||||
}
|
||||
};
|
||||
__name(REST, "REST");
|
||||
|
||||
// src/index.ts
|
||||
var version = "1.5.0";
|
||||
export {
|
||||
ALLOWED_EXTENSIONS,
|
||||
ALLOWED_SIZES,
|
||||
ALLOWED_STICKER_EXTENSIONS,
|
||||
CDN,
|
||||
DefaultRestOptions,
|
||||
DefaultUserAgent,
|
||||
DiscordAPIError,
|
||||
HTTPError,
|
||||
REST,
|
||||
RESTEvents,
|
||||
RateLimitError,
|
||||
RequestManager,
|
||||
RequestMethod,
|
||||
makeURLSearchParams,
|
||||
parseResponse,
|
||||
version
|
||||
};
|
||||
//# sourceMappingURL=index.mjs.map
|
1
node_modules/@discordjs/rest/dist/index.mjs.map
generated
vendored
Normal file
1
node_modules/@discordjs/rest/dist/index.mjs.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
85
node_modules/@discordjs/rest/package.json
generated
vendored
Normal file
85
node_modules/@discordjs/rest/package.json
generated
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
{
|
||||
"name": "@discordjs/rest",
|
||||
"version": "1.5.0",
|
||||
"description": "The REST API for discord.js",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
"build": "tsup",
|
||||
"lint": "prettier --check . && cross-env TIMING=1 eslint src __tests__ --ext .mjs,.js,.ts --format=pretty",
|
||||
"format": "prettier --write . && cross-env TIMING=1 eslint src __tests__ --ext .mjs,.js,.ts --fix --format=pretty",
|
||||
"fmt": "yarn format",
|
||||
"docs": "api-extractor run --local",
|
||||
"prepack": "yarn lint && yarn test && yarn build",
|
||||
"changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r ../../ --include-path 'packages/rest/*'",
|
||||
"release": "cliff-jumper"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/index.mjs",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"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>",
|
||||
"Aura Román <kyradiscord@gmail.com>"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [
|
||||
"discord",
|
||||
"api",
|
||||
"rest",
|
||||
"discordapp",
|
||||
"discordjs"
|
||||
],
|
||||
"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",
|
||||
"dependencies": {
|
||||
"@discordjs/collection": "^1.3.0",
|
||||
"@discordjs/util": "^0.1.0",
|
||||
"@sapphire/async-queue": "^1.5.0",
|
||||
"@sapphire/snowflake": "^3.2.2",
|
||||
"discord-api-types": "^0.37.23",
|
||||
"file-type": "^18.0.0",
|
||||
"tslib": "^2.4.1",
|
||||
"undici": "^5.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@favware/cliff-jumper": "^1.9.0",
|
||||
"@microsoft/api-extractor": "^7.33.6",
|
||||
"@types/node": "16.18.4",
|
||||
"@vitest/coverage-c8": "^0.25.3",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild-plugin-version-injector": "^1.0.2",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-neon": "^0.1.40",
|
||||
"eslint-formatter-pretty": "^4.1.0",
|
||||
"prettier": "^2.8.0",
|
||||
"tsup": "^6.5.0",
|
||||
"typescript": "^4.9.3",
|
||||
"vitest": "^0.25.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue