summaryrefslogtreecommitdiff
path: root/node_modules/discord.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/discord.js')
-rw-r--r--node_modules/discord.js/.tern-project17
-rw-r--r--node_modules/discord.js/LICENSE190
-rw-r--r--node_modules/discord.js/README.md111
-rw-r--r--node_modules/discord.js/esm/discord.mjs89
-rw-r--r--node_modules/discord.js/jsdoc.json3
-rw-r--r--node_modules/discord.js/package.json213
-rw-r--r--node_modules/discord.js/src/WebSocket.js49
-rw-r--r--node_modules/discord.js/src/client/BaseClient.js147
-rw-r--r--node_modules/discord.js/src/client/Client.js455
-rw-r--r--node_modules/discord.js/src/client/WebhookClient.js31
-rw-r--r--node_modules/discord.js/src/client/actions/Action.js103
-rw-r--r--node_modules/discord.js/src/client/actions/ActionsManager.js45
-rw-r--r--node_modules/discord.js/src/client/actions/ChannelCreate.js23
-rw-r--r--node_modules/discord.js/src/client/actions/ChannelDelete.js37
-rw-r--r--node_modules/discord.js/src/client/actions/ChannelUpdate.js33
-rw-r--r--node_modules/discord.js/src/client/actions/GuildBanRemove.js21
-rw-r--r--node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js21
-rw-r--r--node_modules/discord.js/src/client/actions/GuildDelete.js67
-rw-r--r--node_modules/discord.js/src/client/actions/GuildEmojiCreate.js19
-rw-r--r--node_modules/discord.js/src/client/actions/GuildEmojiDelete.js20
-rw-r--r--node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js20
-rw-r--r--node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js34
-rw-r--r--node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js19
-rw-r--r--node_modules/discord.js/src/client/actions/GuildMemberRemove.js30
-rw-r--r--node_modules/discord.js/src/client/actions/GuildRoleCreate.js25
-rw-r--r--node_modules/discord.js/src/client/actions/GuildRoleDelete.js30
-rw-r--r--node_modules/discord.js/src/client/actions/GuildRoleUpdate.js39
-rw-r--r--node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js21
-rw-r--r--node_modules/discord.js/src/client/actions/GuildUpdate.js33
-rw-r--r--node_modules/discord.js/src/client/actions/InviteCreate.js28
-rw-r--r--node_modules/discord.js/src/client/actions/InviteDelete.js29
-rw-r--r--node_modules/discord.js/src/client/actions/MessageCreate.js39
-rw-r--r--node_modules/discord.js/src/client/actions/MessageDelete.js29
-rw-r--r--node_modules/discord.js/src/client/actions/MessageDeleteBulk.js43
-rw-r--r--node_modules/discord.js/src/client/actions/MessageReactionAdd.js50
-rw-r--r--node_modules/discord.js/src/client/actions/MessageReactionRemove.js44
-rw-r--r--node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js29
-rw-r--r--node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js28
-rw-r--r--node_modules/discord.js/src/client/actions/MessageUpdate.js24
-rw-r--r--node_modules/discord.js/src/client/actions/PresenceUpdate.js44
-rw-r--r--node_modules/discord.js/src/client/actions/UserUpdate.js34
-rw-r--r--node_modules/discord.js/src/client/actions/VoiceStateUpdate.js44
-rw-r--r--node_modules/discord.js/src/client/actions/WebhooksUpdate.js19
-rw-r--r--node_modules/discord.js/src/client/voice/ClientVoiceManager.js110
-rw-r--r--node_modules/discord.js/src/client/voice/VoiceBroadcast.js111
-rw-r--r--node_modules/discord.js/src/client/voice/VoiceConnection.js523
-rw-r--r--node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js46
-rw-r--r--node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js354
-rw-r--r--node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js154
-rw-r--r--node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js264
-rw-r--r--node_modules/discord.js/src/client/voice/player/AudioPlayer.js27
-rw-r--r--node_modules/discord.js/src/client/voice/player/BasePlayer.js92
-rw-r--r--node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js28
-rw-r--r--node_modules/discord.js/src/client/voice/receiver/PacketHandler.js116
-rw-r--r--node_modules/discord.js/src/client/voice/receiver/Receiver.js58
-rw-r--r--node_modules/discord.js/src/client/voice/util/PlayInterface.js94
-rw-r--r--node_modules/discord.js/src/client/voice/util/Secretbox.js32
-rw-r--r--node_modules/discord.js/src/client/voice/util/Silence.js13
-rw-r--r--node_modules/discord.js/src/client/voice/util/VolumeInterface.js103
-rw-r--r--node_modules/discord.js/src/client/websocket/WebSocketManager.js439
-rw-r--r--node_modules/discord.js/src/client/websocket/WebSocketShard.js763
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js22
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js16
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js16
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js36
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js22
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js19
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js22
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js16
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/READY.js21
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/RESUMED.js14
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js49
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js6
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js5
-rw-r--r--node_modules/discord.js/src/client/websocket/handlers/index.js13
-rw-r--r--node_modules/discord.js/src/errors/DJSError.js61
-rw-r--r--node_modules/discord.js/src/errors/Messages.js104
-rw-r--r--node_modules/discord.js/src/errors/index.js4
-rw-r--r--node_modules/discord.js/src/index.js105
-rw-r--r--node_modules/discord.js/src/managers/BaseManager.js81
-rw-r--r--node_modules/discord.js/src/managers/ChannelManager.js93
-rw-r--r--node_modules/discord.js/src/managers/GuildChannelManager.js131
-rw-r--r--node_modules/discord.js/src/managers/GuildEmojiManager.js129
-rw-r--r--node_modules/discord.js/src/managers/GuildEmojiRoleManager.js119
-rw-r--r--node_modules/discord.js/src/managers/GuildManager.js216
-rw-r--r--node_modules/discord.js/src/managers/GuildMemberManager.js272
-rw-r--r--node_modules/discord.js/src/managers/GuildMemberRoleManager.js166
-rw-r--r--node_modules/discord.js/src/managers/MessageManager.js145
-rw-r--r--node_modules/discord.js/src/managers/PresenceManager.js59
-rw-r--r--node_modules/discord.js/src/managers/ReactionManager.js69
-rw-r--r--node_modules/discord.js/src/managers/ReactionUserManager.js66
-rw-r--r--node_modules/discord.js/src/managers/RoleManager.js145
-rw-r--r--node_modules/discord.js/src/managers/UserManager.js68
-rw-r--r--node_modules/discord.js/src/managers/VoiceStateManager.js36
-rw-r--r--node_modules/discord.js/src/rest/APIRequest.js65
-rw-r--r--node_modules/discord.js/src/rest/APIRouter.js53
-rw-r--r--node_modules/discord.js/src/rest/DiscordAPIError.js68
-rw-r--r--node_modules/discord.js/src/rest/HTTPError.js37
-rw-r--r--node_modules/discord.js/src/rest/RESTManager.js68
-rw-r--r--node_modules/discord.js/src/rest/RequestHandler.js180
-rw-r--r--node_modules/discord.js/src/sharding/Shard.js383
-rw-r--r--node_modules/discord.js/src/sharding/ShardClientUtil.js229
-rw-r--r--node_modules/discord.js/src/sharding/ShardingManager.js274
-rw-r--r--node_modules/discord.js/src/structures/APIMessage.js379
-rw-r--r--node_modules/discord.js/src/structures/Base.js42
-rw-r--r--node_modules/discord.js/src/structures/BaseGuildEmoji.js58
-rw-r--r--node_modules/discord.js/src/structures/CategoryChannel.js33
-rw-r--r--node_modules/discord.js/src/structures/Channel.js151
-rw-r--r--node_modules/discord.js/src/structures/ClientApplication.js156
-rw-r--r--node_modules/discord.js/src/structures/ClientPresence.js87
-rw-r--r--node_modules/discord.js/src/structures/ClientUser.js180
-rw-r--r--node_modules/discord.js/src/structures/DMChannel.js98
-rw-r--r--node_modules/discord.js/src/structures/Emoji.js104
-rw-r--r--node_modules/discord.js/src/structures/Guild.js1349
-rw-r--r--node_modules/discord.js/src/structures/GuildAuditLogs.js509
-rw-r--r--node_modules/discord.js/src/structures/GuildChannel.js609
-rw-r--r--node_modules/discord.js/src/structures/GuildEmoji.js159
-rw-r--r--node_modules/discord.js/src/structures/GuildMember.js410
-rw-r--r--node_modules/discord.js/src/structures/GuildPreview.js157
-rw-r--r--node_modules/discord.js/src/structures/GuildPreviewEmoji.js26
-rw-r--r--node_modules/discord.js/src/structures/Integration.js167
-rw-r--r--node_modules/discord.js/src/structures/Invite.js194
-rw-r--r--node_modules/discord.js/src/structures/Message.js623
-rw-r--r--node_modules/discord.js/src/structures/MessageAttachment.js98
-rw-r--r--node_modules/discord.js/src/structures/MessageCollector.js129
-rw-r--r--node_modules/discord.js/src/structures/MessageEmbed.js454
-rw-r--r--node_modules/discord.js/src/structures/MessageMentions.js221
-rw-r--r--node_modules/discord.js/src/structures/MessageReaction.js135
-rw-r--r--node_modules/discord.js/src/structures/NewsChannel.js18
-rw-r--r--node_modules/discord.js/src/structures/PartialGroupDMChannel.js46
-rw-r--r--node_modules/discord.js/src/structures/PermissionOverwrites.js189
-rw-r--r--node_modules/discord.js/src/structures/Presence.js336
-rw-r--r--node_modules/discord.js/src/structures/ReactionCollector.js190
-rw-r--r--node_modules/discord.js/src/structures/ReactionEmoji.js31
-rw-r--r--node_modules/discord.js/src/structures/Role.js403
-rw-r--r--node_modules/discord.js/src/structures/StoreChannel.js22
-rw-r--r--node_modules/discord.js/src/structures/Team.js109
-rw-r--r--node_modules/discord.js/src/structures/TeamMember.js65
-rw-r--r--node_modules/discord.js/src/structures/TextChannel.js151
-rw-r--r--node_modules/discord.js/src/structures/User.js318
-rw-r--r--node_modules/discord.js/src/structures/VoiceChannel.js151
-rw-r--r--node_modules/discord.js/src/structures/VoiceRegion.js52
-rw-r--r--node_modules/discord.js/src/structures/VoiceState.js208
-rw-r--r--node_modules/discord.js/src/structures/Webhook.js273
-rw-r--r--node_modules/discord.js/src/structures/interfaces/Collector.js281
-rw-r--r--node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js396
-rw-r--r--node_modules/discord.js/src/util/ActivityFlags.js38
-rw-r--r--node_modules/discord.js/src/util/BitField.js162
-rw-r--r--node_modules/discord.js/src/util/Collection.js17
-rw-r--r--node_modules/discord.js/src/util/Constants.js650
-rw-r--r--node_modules/discord.js/src/util/DataResolver.js127
-rw-r--r--node_modules/discord.js/src/util/Intents.js83
-rw-r--r--node_modules/discord.js/src/util/LimitedCollection.js34
-rw-r--r--node_modules/discord.js/src/util/MessageFlags.js36
-rw-r--r--node_modules/discord.js/src/util/Permissions.js131
-rw-r--r--node_modules/discord.js/src/util/Snowflake.js87
-rw-r--r--node_modules/discord.js/src/util/Speaking.js33
-rw-r--r--node_modules/discord.js/src/util/Structures.js112
-rw-r--r--node_modules/discord.js/src/util/SystemChannelFlags.js40
-rw-r--r--node_modules/discord.js/src/util/UserFlags.js51
-rw-r--r--node_modules/discord.js/src/util/Util.js621
-rw-r--r--node_modules/discord.js/typings/index.d.ts3080
-rw-r--r--node_modules/discord.js/typings/index.ts28
-rw-r--r--node_modules/discord.js/webpack/discord.min.js1
187 files changed, 24672 insertions, 0 deletions
diff --git a/node_modules/discord.js/.tern-project b/node_modules/discord.js/.tern-project
new file mode 100644
index 0000000..f5ce948
--- /dev/null
+++ b/node_modules/discord.js/.tern-project
@@ -0,0 +1,17 @@
+{
+ "ecmaVersion": 7,
+ "libs": [],
+ "loadEagerly": ["./src/*.js"],
+ "dontLoad": ["node_modules/**"],
+ "plugins": {
+ "es_modules": {},
+ "node": {},
+ "doc_comment": {
+ "fullDocs": true,
+ "strong": true
+ },
+ "webpack": {
+ "configPath": "./webpack.config.js"
+ }
+ }
+}
diff --git a/node_modules/discord.js/LICENSE b/node_modules/discord.js/LICENSE
new file mode 100644
index 0000000..9997d13
--- /dev/null
+++ b/node_modules/discord.js/LICENSE
@@ -0,0 +1,190 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ Copyright 2015 - 2020 Amish Shah
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/node_modules/discord.js/README.md b/node_modules/discord.js/README.md
new file mode 100644
index 0000000..b6d86a4
--- /dev/null
+++ b/node_modules/discord.js/README.md
@@ -0,0 +1,111 @@
+<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/bRCvFy9"><img src="https://discordapp.com/api/guilds/222078108977594368/embed.png" alt="Discord server" /></a>
+ <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="NPM version" /></a>
+ <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="NPM downloads" /></a>
+ <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/workflows/Testing/badge.svg" alt="Build status" /></a>
+ <a href="https://david-dm.org/discordjs/discord.js"><img src="https://img.shields.io/david/discordjs/discord.js.svg?maxAge=3600" alt="Dependencies" /></a>
+ <a href="https://www.patreon.com/discordjs"><img src="https://img.shields.io/badge/donate-patreon-F96854.svg" alt="Patreon" /></a>
+ </p>
+ <p>
+ <a href="https://nodei.co/npm/discord.js/"><img src="https://nodei.co/npm/discord.js.png?downloads=true&stars=true" alt="npm installnfo" /></a>
+ </p>
+</div>
+
+## Table of contents
+
+- [About](#about)
+- [Installation](#installation)
+ - [Audio engines](#audio-engines)
+ - [Optional packages](#optional-packages)
+- [Example Usage](#example-usage)
+- [Links](#links)
+ - [Extensions](#extensions)
+- [Contributing](#contributing)
+- [Help](#help)
+
+## About
+
+discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the
+[Discord API](https://discordapp.com/developers/docs/intro).
+
+- Object-oriented
+- Predictable abstractions
+- Performant
+- 100% coverage of the Discord API
+
+## Installation
+
+**Node.js 12.0.0 or newer is required.**
+Ignore any warnings about unmet peer dependencies, as they're all optional.
+
+Without voice support: `npm install discord.js`
+With voice support ([@discordjs/opus](https://www.npmjs.com/package/@discordjs/opus)): `npm install discord.js @discordjs/opus`
+With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript`
+
+### Audio engines
+
+The preferred audio engine is @discordjs/opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose @discordjs/opus.
+Using opusscript is only recommended for development environments where @discordjs/opus is tough to get working.
+For production bots, using @discordjs/opus should be considered a necessity, especially if they're going to be running on multiple servers.
+
+### Optional packages
+
+- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
+- [erlpack](https://github.com/discordapp/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discordapp/erlpack`)
+- One of the following packages can be installed for faster voice packet encryption and decryption:
+ - [sodium](https://www.npmjs.com/package/sodium) (`npm install sodium`)
+ - [libsodium.js](https://www.npmjs.com/package/libsodium-wrappers) (`npm install libsodium-wrappers`)
+- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
+- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
+
+## Example usage
+
+```js
+const Discord = require('discord.js');
+const client = new Discord.Client();
+
+client.on('ready', () => {
+ console.log(`Logged in as ${client.user.tag}!`);
+});
+
+client.on('message', msg => {
+ if (msg.content === 'ping') {
+ msg.reply('pong');
+ }
+});
+
+client.login('token');
+```
+
+## Links
+
+- [Website](https://discord.js.org/) ([source](https://github.com/discordjs/website))
+- [Documentation](https://discord.js.org/#/docs/main/master/general/welcome)
+- [Guide](https://discordjs.guide/) ([source](https://github.com/discordjs/guide)) - this is still for stable
+ See also the [Update Guide](https://discordjs.guide/additional-info/changes-in-v12.html), including updated and removed items in the library.
+- [Discord.js Discord server](https://discord.gg/bRCvFy9)
+- [Discord API Discord server](https://discord.gg/discord-api)
+- [GitHub](https://github.com/discordjs/discord.js)
+- [NPM](https://www.npmjs.com/package/discord.js)
+- [Related libraries](https://discordapi.com/unofficial/libs.html)
+
+### Extensions
+
+- [RPC](https://www.npmjs.com/package/discord-rpc) ([source](https://github.com/discordjs/RPC))
+
+## Contributing
+
+Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
+[documentation](https://discord.js.org/#/docs).
+See [the contribution guide](https://github.com/discordjs/discord.js/blob/master/.github/CONTRIBUTING.md) if you'd like to submit a PR.
+
+## Help
+
+If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
+nudge in the right direction, please don't hesitate to join our official [Discord.js Server](https://discord.gg/bRCvFy9).
diff --git a/node_modules/discord.js/esm/discord.mjs b/node_modules/discord.js/esm/discord.mjs
new file mode 100644
index 0000000..29062fb
--- /dev/null
+++ b/node_modules/discord.js/esm/discord.mjs
@@ -0,0 +1,89 @@
+import Discord from '../src/index.js';
+
+export default Discord;
+
+export const {
+ BaseClient,
+ Client,
+ Shard,
+ ShardClientUtil,
+ ShardingManager,
+ WebhookClient,
+ ActivityFlags,
+ BitField,
+ Collection,
+ Constants,
+ DataResolver,
+ BaseManager,
+ DiscordAPIError,
+ HTTPError,
+ MessageFlags,
+ Intents,
+ Permissions,
+ Speaking,
+ Snowflake,
+ SnowflakeUtil,
+ Structures,
+ SystemChannelFlags,
+ Util,
+ version,
+ ChannelManager,
+ GuildChannelManager,
+ GuildEmojiManager,
+ GuildEmojiRoleManager,
+ GuildMemberManager,
+ GuildMemberRoleManager,
+ GuildManager,
+ ReactionUserManager,
+ MessageManager,
+ PresenceManager,
+ RoleManager,
+ UserManager,
+ discordSort,
+ escapeMarkdown,
+ fetchRecommendedShards,
+ resolveColor,
+ resolveString,
+ splitMessage,
+ Base,
+ Activity,
+ APIMessage,
+ CategoryChannel,
+ Channel,
+ ClientApplication,
+ ClientUser,
+ Collector,
+ DMChannel,
+ Emoji,
+ Guild,
+ GuildAuditLogs,
+ GuildChannel,
+ GuildEmoji,
+ GuildMember,
+ Integration,
+ Invite,
+ Message,
+ MessageAttachment,
+ MessageCollector,
+ MessageEmbed,
+ MessageMentions,
+ MessageReaction,
+ NewsChannel,
+ PermissionOverwrites,
+ Presence,
+ ClientPresence,
+ ReactionCollector,
+ ReactionEmoji,
+ RichPresenceAssets,
+ Role,
+ StoreChannel,
+ Team,
+ TeamMember,
+ TextChannel,
+ User,
+ VoiceChannel,
+ VoiceRegion,
+ VoiceState,
+ Webhook,
+ WebSocket
+} = Discord;
diff --git a/node_modules/discord.js/jsdoc.json b/node_modules/discord.js/jsdoc.json
new file mode 100644
index 0000000..3bf2d09
--- /dev/null
+++ b/node_modules/discord.js/jsdoc.json
@@ -0,0 +1,3 @@
+{
+ "plugins": ["node_modules/jsdoc-strip-async-await"]
+}
diff --git a/node_modules/discord.js/package.json b/node_modules/discord.js/package.json
new file mode 100644
index 0000000..03095ee
--- /dev/null
+++ b/node_modules/discord.js/package.json
@@ -0,0 +1,213 @@
+{
+ "_from": "discord.js",
+ "_id": "[email protected]",
+ "_inBundle": false,
+ "_integrity": "sha512-Ueb/0SOsxXyqwvwFYFe0msMrGqH1OMqpp2Dpbplnlr4MzcRrFWwsBM9gKNZXPVBHWUKiQkwU8AihXBXIvTTSvg==",
+ "_location": "/discord.js",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "tag",
+ "registry": true,
+ "raw": "discord.js",
+ "name": "discord.js",
+ "escapedName": "discord.js",
+ "rawSpec": "",
+ "saveSpec": null,
+ "fetchSpec": "latest"
+ },
+ "_requiredBy": [
+ "#USER",
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.2.0.tgz",
+ "_shasum": "31018732e42a495c92655055192221eab2ad11a9",
+ "_spec": "discord.js",
+ "_where": "E:\\Documents\\GitHub\\uppity",
+ "author": {
+ "name": "Amish Shah",
+ "email": "[email protected]"
+ },
+ "browser": {
+ "@discordjs/opus": false,
+ "https": false,
+ "ws": false,
+ "erlpack": false,
+ "prism-media": false,
+ "opusscript": false,
+ "node-opus": false,
+ "tweetnacl": false,
+ "sodium": false,
+ "worker_threads": false,
+ "zlib-sync": false,
+ "src/sharding/Shard.js": false,
+ "src/sharding/ShardClientUtil.js": false,
+ "src/sharding/ShardingManager.js": false,
+ "src/client/voice/ClientVoiceManager.js": false,
+ "src/client/voice/VoiceBroadcast.js": false,
+ "src/client/voice/VoiceConnection.js": false,
+ "src/client/voice/dispatcher/BroadcastDispatcher.js": false,
+ "src/client/voice/dispatcher/StreamDispatcher.js": false,
+ "src/client/voice/networking/VoiceUDPClient.js": false,
+ "src/client/voice/networking/VoiceWebSocket.js": false,
+ "src/client/voice/player/AudioPlayer.js": false,
+ "src/client/voice/player/BasePlayer.js": false,
+ "src/client/voice/player/BroadcastAudioPlayer.js": false,
+ "src/client/voice/receiver/PacketHandler.js": false,
+ "src/client/voice/receiver/Receiver.js": false,
+ "src/client/voice/util/PlayInterface.js": false,
+ "src/client/voice/util/Secretbox.js": false,
+ "src/client/voice/util/Silence.js": false,
+ "src/client/voice/util/VolumeInterface.js": false
+ },
+ "bugs": {
+ "url": "https://github.com/discordjs/discord.js/issues"
+ },
+ "bundleDependencies": false,
+ "commitlint": {
+ "extends": [
+ "@commitlint/config-angular"
+ ],
+ "rules": {
+ "scope-case": [
+ 2,
+ "always",
+ "pascal-case"
+ ],
+ "type-enum": [
+ 2,
+ "always",
+ [
+ "chore",
+ "build",
+ "ci",
+ "docs",
+ "feat",
+ "fix",
+ "perf",
+ "refactor",
+ "revert",
+ "style",
+ "test"
+ ]
+ ]
+ }
+ },
+ "dependencies": {
+ "@discordjs/collection": "^0.1.5",
+ "@discordjs/form-data": "^3.0.1",
+ "abort-controller": "^3.0.0",
+ "node-fetch": "^2.6.0",
+ "prism-media": "^1.2.0",
+ "setimmediate": "^1.0.5",
+ "tweetnacl": "^1.0.3",
+ "ws": "^7.2.1"
+ },
+ "deprecated": false,
+ "description": "A powerful library for interacting with the Discord API",
+ "devDependencies": {
+ "@commitlint/cli": "^8.3.5",
+ "@commitlint/config-angular": "^8.3.4",
+ "@types/node": "^10.12.24",
+ "@types/ws": "^7.2.1",
+ "cross-env": "^7.0.2",
+ "discord.js-docgen": "github:discordjs/docgen",
+ "dtslint": "^3.0.0",
+ "eslint": "^6.8.0",
+ "eslint-config-prettier": "^6.10.0",
+ "eslint-plugin-import": "^2.20.1",
+ "eslint-plugin-prettier": "^3.1.2",
+ "husky": "^4.2.3",
+ "jest": "^25.1.0",
+ "json-filter-loader": "^1.0.0",
+ "lint-staged": "^10.0.8",
+ "prettier": "^1.19.1",
+ "terser-webpack-plugin": "^1.2.2",
+ "tslint": "^6.0.0",
+ "typescript": "^3.8.2",
+ "webpack": "^4.41.6",
+ "webpack-cli": "^3.3.11"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "exports": {
+ ".": [
+ {
+ "require": "./src/index.js",
+ "import": "./esm/discord.mjs"
+ },
+ "./src/index.js"
+ ],
+ "./esm": "./esm/discord.mjs"
+ },
+ "homepage": "https://github.com/discordjs/discord.js#readme",
+ "husky": {
+ "hooks": {
+ "pre-commit": "lint-staged",
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
+ }
+ },
+ "keywords": [
+ "discord",
+ "api",
+ "bot",
+ "client",
+ "node",
+ "discordapp"
+ ],
+ "license": "Apache-2.0",
+ "lint-staged": {
+ "*.js": "eslint --fix",
+ "*.ts": "prettier --write --single-quote --print-width 120 --trailing-comma all --end-of-line lf"
+ },
+ "main": "./src/index",
+ "name": "discord.js",
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "erlpack": "discordapp/erlpack",
+ "libsodium-wrappers": "^0.7.6",
+ "sodium": "^3.0.2",
+ "utf-8-validate": "^5.0.2",
+ "zlib-sync": "^0.1.6"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "erlpack": {
+ "optional": true
+ },
+ "libsodium-wrappers": {
+ "optional": true
+ },
+ "sodium": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ },
+ "zlib-sync": {
+ "optional": true
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/discordjs/discord.js.git"
+ },
+ "runkitExampleFilename": "./docs/examples/ping.js",
+ "scripts": {
+ "build:browser": "webpack",
+ "docs": "docgen --source src --custom docs/index.yml --output docs/docs.json",
+ "docs:test": "docgen --source src --custom docs/index.yml",
+ "lint": "eslint src",
+ "lint:fix": "eslint src --fix",
+ "lint:typings": "tslint typings/index.d.ts",
+ "prepublishOnly": "npm run test && cross-env NODE_ENV=production npm run build:browser",
+ "prettier": "prettier --write --single-quote --print-width 120 --trailing-comma all --end-of-line lf src/**/*.js typings/**/*.ts",
+ "test": "npm run lint && npm run docs:test && npm run lint:typings",
+ "test:typescript": "tsc"
+ },
+ "types": "./typings/index.d.ts",
+ "unpkg": "./webpack/discord.min.js",
+ "version": "12.2.0"
+}
diff --git a/node_modules/discord.js/src/WebSocket.js b/node_modules/discord.js/src/WebSocket.js
new file mode 100644
index 0000000..90dd51b
--- /dev/null
+++ b/node_modules/discord.js/src/WebSocket.js
@@ -0,0 +1,49 @@
+'use strict';
+
+const { browser } = require('./util/Constants');
+
+let erlpack;
+
+try {
+ erlpack = require('erlpack');
+ if (!erlpack.pack) erlpack = null;
+} catch {} // eslint-disable-line no-empty
+
+let TextDecoder;
+
+if (browser) {
+ TextDecoder = window.TextDecoder; // eslint-disable-line no-undef
+ exports.WebSocket = window.WebSocket; // eslint-disable-line no-undef
+} else {
+ TextDecoder = require('util').TextDecoder;
+ exports.WebSocket = require('ws');
+}
+
+const ab = new TextDecoder();
+
+exports.encoding = erlpack ? 'etf' : 'json';
+
+exports.pack = erlpack ? erlpack.pack : JSON.stringify;
+
+exports.unpack = (data, type) => {
+ if (exports.encoding === 'json' || type === 'json') {
+ if (typeof data !== 'string') {
+ data = ab.decode(data);
+ }
+ return JSON.parse(data);
+ }
+ if (!Buffer.isBuffer(data)) data = Buffer.from(new Uint8Array(data));
+ return erlpack.unpack(data);
+};
+
+exports.create = (gateway, query = {}, ...args) => {
+ const [g, q] = gateway.split('?');
+ query.encoding = exports.encoding;
+ query = new URLSearchParams(query);
+ if (q) new URLSearchParams(q).forEach((v, k) => query.set(k, v));
+ const ws = new exports.WebSocket(`${g}?${query}`, ...args);
+ if (browser) ws.binaryType = 'arraybuffer';
+ return ws;
+};
+
+for (const state of ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']) exports[state] = exports.WebSocket[state];
diff --git a/node_modules/discord.js/src/client/BaseClient.js b/node_modules/discord.js/src/client/BaseClient.js
new file mode 100644
index 0000000..a381e1a
--- /dev/null
+++ b/node_modules/discord.js/src/client/BaseClient.js
@@ -0,0 +1,147 @@
+'use strict';
+
+require('setimmediate');
+const EventEmitter = require('events');
+const RESTManager = require('../rest/RESTManager');
+const { DefaultOptions } = require('../util/Constants');
+const Util = require('../util/Util');
+
+/**
+ * The base class for all clients.
+ * @extends {EventEmitter}
+ */
+class BaseClient extends EventEmitter {
+ constructor(options = {}) {
+ super();
+
+ /**
+ * Timeouts set by {@link BaseClient#setTimeout} that are still active
+ * @type {Set<Timeout>}
+ * @private
+ */
+ this._timeouts = new Set();
+
+ /**
+ * Intervals set by {@link BaseClient#setInterval} that are still active
+ * @type {Set<Timeout>}
+ * @private
+ */
+ this._intervals = new Set();
+
+ /**
+ * Intervals set by {@link BaseClient#setImmediate} that are still active
+ * @type {Set<Immediate>}
+ * @private
+ */
+ this._immediates = new Set();
+
+ /**
+ * The options the client was instantiated with
+ * @type {ClientOptions}
+ */
+ this.options = Util.mergeDefault(DefaultOptions, options);
+
+ /**
+ * The REST manager of the client
+ * @type {RESTManager}
+ * @private
+ */
+ this.rest = new RESTManager(this, options._tokenType);
+ }
+
+ /**
+ * API shortcut
+ * @type {Object}
+ * @readonly
+ * @private
+ */
+ get api() {
+ return this.rest.api;
+ }
+
+ /**
+ * Destroys all assets used by the base client.
+ */
+ destroy() {
+ for (const t of this._timeouts) this.clearTimeout(t);
+ for (const i of this._intervals) this.clearInterval(i);
+ for (const i of this._immediates) this.clearImmediate(i);
+ this._timeouts.clear();
+ this._intervals.clear();
+ this._immediates.clear();
+ }
+
+ /**
+ * Sets a timeout that will be automatically cancelled if the client is destroyed.
+ * @param {Function} fn Function to execute
+ * @param {number} delay Time to wait before executing (in milliseconds)
+ * @param {...*} args Arguments for the function
+ * @returns {Timeout}
+ */
+ setTimeout(fn, delay, ...args) {
+ const timeout = setTimeout(() => {
+ fn(...args);
+ this._timeouts.delete(timeout);
+ }, delay);
+ this._timeouts.add(timeout);
+ return timeout;
+ }
+
+ /**
+ * Clears a timeout.
+ * @param {Timeout} timeout Timeout to cancel
+ */
+ clearTimeout(timeout) {
+ clearTimeout(timeout);
+ this._timeouts.delete(timeout);
+ }
+
+ /**
+ * Sets an interval that will be automatically cancelled if the client is destroyed.
+ * @param {Function} fn Function to execute
+ * @param {number} delay Time to wait between executions (in milliseconds)
+ * @param {...*} args Arguments for the function
+ * @returns {Timeout}
+ */
+ setInterval(fn, delay, ...args) {
+ const interval = setInterval(fn, delay, ...args);
+ this._intervals.add(interval);
+ return interval;
+ }
+
+ /**
+ * Clears an interval.
+ * @param {Timeout} interval Interval to cancel
+ */
+ clearInterval(interval) {
+ clearInterval(interval);
+ this._intervals.delete(interval);
+ }
+
+ /**
+ * Sets an immediate that will be automatically cancelled if the client is destroyed.
+ * @param {Function} fn Function to execute
+ * @param {...*} args Arguments for the function
+ * @returns {Immediate}
+ */
+ setImmediate(fn, ...args) {
+ const immediate = setImmediate(fn, ...args);
+ this._immediates.add(immediate);
+ return immediate;
+ }
+
+ /**
+ * Clears an immediate.
+ * @param {Immediate} immediate Immediate to cancel
+ */
+ clearImmediate(immediate) {
+ clearImmediate(immediate);
+ this._immediates.delete(immediate);
+ }
+
+ toJSON(...props) {
+ return Util.flatten(this, { domain: false }, ...props);
+ }
+}
+
+module.exports = BaseClient;
diff --git a/node_modules/discord.js/src/client/Client.js b/node_modules/discord.js/src/client/Client.js
new file mode 100644
index 0000000..4a12e85
--- /dev/null
+++ b/node_modules/discord.js/src/client/Client.js
@@ -0,0 +1,455 @@
+'use strict';
+
+const BaseClient = require('./BaseClient');
+const ActionsManager = require('./actions/ActionsManager');
+const ClientVoiceManager = require('./voice/ClientVoiceManager');
+const WebSocketManager = require('./websocket/WebSocketManager');
+const { Error, TypeError, RangeError } = require('../errors');
+const ChannelManager = require('../managers/ChannelManager');
+const GuildEmojiManager = require('../managers/GuildEmojiManager');
+const GuildManager = require('../managers/GuildManager');
+const UserManager = require('../managers/UserManager');
+const ShardClientUtil = require('../sharding/ShardClientUtil');
+const ClientApplication = require('../structures/ClientApplication');
+const GuildPreview = require('../structures/GuildPreview');
+const Invite = require('../structures/Invite');
+const VoiceRegion = require('../structures/VoiceRegion');
+const Webhook = require('../structures/Webhook');
+const Collection = require('../util/Collection');
+const { Events, browser, DefaultOptions } = require('../util/Constants');
+const DataResolver = require('../util/DataResolver');
+const Intents = require('../util/Intents');
+const Permissions = require('../util/Permissions');
+const Structures = require('../util/Structures');
+
+/**
+ * The main hub for interacting with the Discord API, and the starting point for any bot.
+ * @extends {BaseClient}
+ */
+class Client extends BaseClient {
+ /**
+ * @param {ClientOptions} [options] Options for the client
+ */
+ constructor(options = {}) {
+ super(Object.assign({ _tokenType: 'Bot' }, options));
+
+ // Obtain shard details from environment or if present, worker threads
+ let data = process.env;
+ try {
+ // Test if worker threads module is present and used
+ data = require('worker_threads').workerData || data;
+ } catch {
+ // Do nothing
+ }
+
+ if (this.options.shards === DefaultOptions.shards) {
+ if ('SHARDS' in data) {
+ this.options.shards = JSON.parse(data.SHARDS);
+ }
+ }
+
+ if (this.options.shardCount === DefaultOptions.shardCount) {
+ if ('SHARD_COUNT' in data) {
+ this.options.shardCount = Number(data.SHARD_COUNT);
+ } else if (Array.isArray(this.options.shards)) {
+ this.options.shardCount = this.options.shards.length;
+ }
+ }
+
+ const typeofShards = typeof this.options.shards;
+
+ if (typeofShards === 'undefined' && typeof this.options.shardCount === 'number') {
+ this.options.shards = Array.from({ length: this.options.shardCount }, (_, i) => i);
+ }
+
+ if (typeofShards === 'number') this.options.shards = [this.options.shards];
+
+ if (Array.isArray(this.options.shards)) {
+ this.options.shards = [
+ ...new Set(
+ this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)),
+ ),
+ ];
+ }
+
+ this._validateOptions();
+
+ /**
+ * The WebSocket manager of the client
+ * @type {WebSocketManager}
+ */
+ this.ws = new WebSocketManager(this);
+
+ /**
+ * The action manager of the client
+ * @type {ActionsManager}
+ * @private
+ */
+ this.actions = new ActionsManager(this);
+
+ /**
+ * The voice manager of the client (`null` in browsers)
+ * @type {?ClientVoiceManager}
+ */
+ this.voice = !browser ? new ClientVoiceManager(this) : null;
+
+ /**
+ * Shard helpers for the client (only if the process was spawned from a {@link ShardingManager})
+ * @type {?ShardClientUtil}
+ */
+ this.shard =
+ !browser && process.env.SHARDING_MANAGER
+ ? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE)
+ : null;
+
+ /**
+ * All of the {@link User} objects that have been cached at any point, mapped by their IDs
+ * @type {UserManager}
+ */
+ this.users = new UserManager(this);
+
+ /**
+ * All of the guilds the client is currently handling, mapped by their IDs -
+ * as long as sharding isn't being used, this will be *every* guild the bot is a member of
+ * @type {GuildManager}
+ */
+ this.guilds = new GuildManager(this);
+
+ /**
+ * All of the {@link Channel}s that the client is currently handling, mapped by their IDs -
+ * as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
+ * is a member of. Note that DM channels will not be initially cached, and thus not be present
+ * in the Manager without their explicit fetching or use.
+ * @type {ChannelManager}
+ */
+ this.channels = new ChannelManager(this);
+
+ const ClientPresence = Structures.get('ClientPresence');
+ /**
+ * The presence of the Client
+ * @private
+ * @type {ClientPresence}
+ */
+ this.presence = new ClientPresence(this);
+
+ Object.defineProperty(this, 'token', { writable: true });
+ if (!browser && !this.token && 'DISCORD_TOKEN' in process.env) {
+ /**
+ * Authorization token for the logged in bot
+ * <warn>This should be kept private at all times.</warn>
+ * @type {?string}
+ */
+ this.token = process.env.DISCORD_TOKEN;
+ } else {
+ this.token = null;
+ }
+
+ /**
+ * User that the client is logged in as
+ * @type {?ClientUser}
+ */
+ this.user = null;
+
+ /**
+ * Time at which the client was last regarded as being in the `READY` state
+ * (each time the client disconnects and successfully reconnects, this will be overwritten)
+ * @type {?Date}
+ */
+ this.readyAt = null;
+
+ if (this.options.messageSweepInterval > 0) {
+ this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000);
+ }
+ }
+
+ /**
+ * All custom emojis that the client has access to, mapped by their IDs
+ * @type {GuildEmojiManager}
+ * @readonly
+ */
+ get emojis() {
+ const emojis = new GuildEmojiManager({ client: this });
+ for (const guild of this.guilds.cache.values()) {
+ if (guild.available) for (const emoji of guild.emojis.cache.values()) emojis.cache.set(emoji.id, emoji);
+ }
+ return emojis;
+ }
+
+ /**
+ * Timestamp of the time the client was last `READY` at
+ * @type {?number}
+ * @readonly
+ */
+ get readyTimestamp() {
+ return this.readyAt ? this.readyAt.getTime() : null;
+ }
+
+ /**
+ * How long it has been since the client last entered the `READY` state in milliseconds
+ * @type {?number}
+ * @readonly
+ */
+ get uptime() {
+ return this.readyAt ? Date.now() - this.readyAt : null;
+ }
+
+ /**
+ * Logs the client in, establishing a websocket connection to Discord.
+ * @param {string} token Token of the account to log in with
+ * @returns {Promise<string>} Token of the account used
+ * @example
+ * client.login('my token');
+ */
+ async login(token = this.token) {
+ if (!token || typeof token !== 'string') throw new Error('TOKEN_INVALID');
+ this.token = token = token.replace(/^(Bot|Bearer)\s*/i, '');
+ this.emit(
+ Events.DEBUG,
+ `Provided token: ${token
+ .split('.')
+ .map((val, i) => (i > 1 ? val.replace(/./g, '*') : val))
+ .join('.')}`,
+ );
+
+ if (this.options.presence) {
+ this.options.ws.presence = await this.presence._parse(this.options.presence);
+ }
+
+ this.emit(Events.DEBUG, 'Preparing to connect to the gateway...');
+
+ try {
+ await this.ws.connect();
+ return this.token;
+ } catch (error) {
+ this.destroy();
+ throw error;
+ }
+ }
+
+ /**
+ * Logs out, terminates the connection to Discord, and destroys the client.
+ * @returns {void}
+ */
+ destroy() {
+ super.destroy();
+ this.ws.destroy();
+ this.token = null;
+ }
+
+ /**
+ * Obtains an invite from Discord.
+ * @param {InviteResolvable} invite Invite code or URL
+ * @returns {Promise<Invite>}
+ * @example
+ * client.fetchInvite('https://discord.gg/bRCvFy9')
+ * .then(invite => console.log(`Obtained invite with code: ${invite.code}`))
+ * .catch(console.error);
+ */
+ fetchInvite(invite) {
+ const code = DataResolver.resolveInviteCode(invite);
+ return this.api
+ .invites(code)
+ .get({ query: { with_counts: true } })
+ .then(data => new Invite(this, data));
+ }
+
+ /**
+ * Obtains a webhook from Discord.
+ * @param {Snowflake} id ID of the webhook
+ * @param {string} [token] Token for the webhook
+ * @returns {Promise<Webhook>}
+ * @example
+ * client.fetchWebhook('id', 'token')
+ * .then(webhook => console.log(`Obtained webhook with name: ${webhook.name}`))
+ * .catch(console.error);
+ */
+ fetchWebhook(id, token) {
+ return this.api
+ .webhooks(id, token)
+ .get()
+ .then(data => new Webhook(this, data));
+ }
+
+ /**
+ * Obtains the available voice regions from Discord.
+ * @returns {Promise<Collection<string, VoiceRegion>>}
+ * @example
+ * client.fetchVoiceRegions()
+ * .then(regions => console.log(`Available regions are: ${regions.map(region => region.name).join(', ')}`))
+ * .catch(console.error);
+ */
+ fetchVoiceRegions() {
+ return this.api.voice.regions.get().then(res => {
+ const regions = new Collection();
+ for (const region of res) regions.set(region.id, new VoiceRegion(region));
+ return regions;
+ });
+ }
+
+ /**
+ * Sweeps all text-based channels' messages and removes the ones older than the max message lifetime.
+ * If the message has been edited, the time of the edit is used rather than the time of the original message.
+ * @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds)
+ * will be removed from the caches. The default is based on {@link ClientOptions#messageCacheLifetime}
+ * @returns {number} Amount of messages that were removed from the caches,
+ * or -1 if the message cache lifetime is unlimited
+ * @example
+ * // Remove all messages older than 1800 seconds from the messages cache
+ * const amount = client.sweepMessages(1800);
+ * console.log(`Successfully removed ${amount} messages from the cache.`);
+ */
+ sweepMessages(lifetime = this.options.messageCacheLifetime) {
+ if (typeof lifetime !== 'number' || isNaN(lifetime)) {
+ throw new TypeError('INVALID_TYPE', 'lifetime', 'number');
+ }
+ if (lifetime <= 0) {
+ this.emit(Events.DEBUG, "Didn't sweep messages - lifetime is unlimited");
+ return -1;
+ }
+
+ const lifetimeMs = lifetime * 1000;
+ const now = Date.now();
+ let channels = 0;
+ let messages = 0;
+
+ for (const channel of this.channels.cache.values()) {
+ if (!channel.messages) continue;
+ channels++;
+
+ messages += channel.messages.cache.sweep(
+ message => now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs,
+ );
+ }
+
+ this.emit(
+ Events.DEBUG,
+ `Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`,
+ );
+ return messages;
+ }
+
+ /**
+ * Obtains the OAuth Application of this bot from Discord.
+ * @returns {Promise<ClientApplication>}
+ */
+ fetchApplication() {
+ return this.api.oauth2
+ .applications('@me')
+ .get()
+ .then(app => new ClientApplication(this, app));
+ }
+
+ /**
+ * Obtains a guild preview from Discord, only available for public guilds.
+ * @param {GuildResolvable} guild The guild to fetch the preview for
+ * @returns {Promise<GuildPreview>}
+ */
+ fetchGuildPreview(guild) {
+ const id = this.guilds.resolveID(guild);
+ if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable');
+ return this.api
+ .guilds(id)
+ .preview.get()
+ .then(data => new GuildPreview(this, data));
+ }
+
+ /**
+ * Generates a link that can be used to invite the bot to a guild.
+ * @param {PermissionResolvable} [permissions] Permissions to request
+ * @returns {Promise<string>}
+ * @example
+ * client.generateInvite(['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE'])
+ * .then(link => console.log(`Generated bot invite link: ${link}`))
+ * .catch(console.error);
+ */
+ async generateInvite(permissions) {
+ permissions = Permissions.resolve(permissions);
+ const application = await this.fetchApplication();
+ const query = new URLSearchParams({
+ client_id: application.id,
+ permissions: permissions,
+ scope: 'bot',
+ });
+ return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ readyAt: false,
+ presences: false,
+ });
+ }
+
+ /**
+ * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
+ * with the client as `this`.
+ * @param {string} script Script to eval
+ * @returns {*}
+ * @private
+ */
+ _eval(script) {
+ return eval(script);
+ }
+
+ /**
+ * Validates the client options.
+ * @param {ClientOptions} [options=this.options] Options to validate
+ * @private
+ */
+ _validateOptions(options = this.options) {
+ if (typeof options.ws.intents !== 'undefined') {
+ options.ws.intents = Intents.resolve(options.ws.intents);
+ }
+ if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1');
+ }
+ if (options.shards && !(options.shards === 'auto' || Array.isArray(options.shards))) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers");
+ }
+ if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS');
+ if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'messageCacheMaxSize', 'a number');
+ }
+ if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'The messageCacheLifetime', 'a number');
+ }
+ if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'messageSweepInterval', 'a number');
+ }
+ if (typeof options.fetchAllMembers !== 'boolean') {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'fetchAllMembers', 'a boolean');
+ }
+ if (typeof options.disableMentions !== 'string') {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'disableMentions', 'a string');
+ }
+ if (!Array.isArray(options.partials)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'partials', 'an Array');
+ }
+ if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'restWsBridgeTimeout', 'a number');
+ }
+ if (typeof options.restRequestTimeout !== 'number' || isNaN(options.restRequestTimeout)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'restRequestTimeout', 'a number');
+ }
+ if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number');
+ }
+ if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number');
+ }
+ }
+}
+
+module.exports = Client;
+
+/**
+ * Emitted for general warnings.
+ * @event Client#warn
+ * @param {string} info The warning
+ */
+
+/**
+ * Emitted for general debugging information.
+ * @event Client#debug
+ * @param {string} info The debug information
+ */
diff --git a/node_modules/discord.js/src/client/WebhookClient.js b/node_modules/discord.js/src/client/WebhookClient.js
new file mode 100644
index 0000000..cea6631
--- /dev/null
+++ b/node_modules/discord.js/src/client/WebhookClient.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const BaseClient = require('./BaseClient');
+const Webhook = require('../structures/Webhook');
+
+/**
+ * The webhook client.
+ * @implements {Webhook}
+ * @extends {BaseClient}
+ */
+class WebhookClient extends BaseClient {
+ /**
+ * @param {Snowflake} id ID of the webhook
+ * @param {string} token Token of the webhook
+ * @param {ClientOptions} [options] Options for the client
+ * @example
+ * // Create a new webhook and send a message
+ * const hook = new Discord.WebhookClient('1234', 'abcdef');
+ * hook.send('This will send a message').catch(console.error);
+ */
+ constructor(id, token, options) {
+ super(options);
+ Object.defineProperty(this, 'client', { value: this });
+ this.id = id;
+ Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
+ }
+}
+
+Webhook.applyToClass(WebhookClient);
+
+module.exports = WebhookClient;
diff --git a/node_modules/discord.js/src/client/actions/Action.js b/node_modules/discord.js/src/client/actions/Action.js
new file mode 100644
index 0000000..d9519b5
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/Action.js
@@ -0,0 +1,103 @@
+'use strict';
+
+const { PartialTypes } = require('../../util/Constants');
+
+/*
+
+ABOUT ACTIONS
+
+Actions are similar to WebSocket Packet Handlers, but since introducing
+the REST API methods, in order to prevent rewriting code to handle data,
+"actions" have been introduced. They're basically what Packet Handlers
+used to be but they're strictly for manipulating data and making sure
+that WebSocket events don't clash with REST methods.
+
+*/
+
+class GenericAction {
+ constructor(client) {
+ this.client = client;
+ }
+
+ handle(data) {
+ return data;
+ }
+
+ getPayload(data, manager, id, partialType, cache) {
+ const existing = manager.cache.get(id);
+ if (!existing && this.client.options.partials.includes(partialType)) {
+ return manager.add(data, cache);
+ }
+ return existing;
+ }
+
+ getChannel(data) {
+ const id = data.channel_id || data.id;
+ return (
+ data.channel ||
+ this.getPayload(
+ {
+ id,
+ guild_id: data.guild_id,
+ recipients: [data.author || { id: data.user_id }],
+ },
+ this.client.channels,
+ id,
+ PartialTypes.CHANNEL,
+ )
+ );
+ }
+
+ getMessage(data, channel, cache) {
+ const id = data.message_id || data.id;
+ return (
+ data.message ||
+ this.getPayload(
+ {
+ id,
+ channel_id: channel.id,
+ guild_id: data.guild_id || (channel.guild ? channel.guild.id : null),
+ },
+ channel.messages,
+ id,
+ PartialTypes.MESSAGE,
+ cache,
+ )
+ );
+ }
+
+ getReaction(data, message, user) {
+ const id = data.emoji.id || decodeURIComponent(data.emoji.name);
+ return this.getPayload(
+ {
+ emoji: data.emoji,
+ count: message.partial ? null : 0,
+ me: user ? user.id === this.client.user.id : false,
+ },
+ message.reactions,
+ id,
+ PartialTypes.REACTION,
+ );
+ }
+
+ getMember(data, guild) {
+ const id = data.user.id;
+ return this.getPayload(
+ {
+ user: {
+ id,
+ },
+ },
+ guild.members,
+ id,
+ PartialTypes.GUILD_MEMBER,
+ );
+ }
+
+ getUser(data) {
+ const id = data.user_id;
+ return data.user || this.getPayload({ id }, this.client.users, id, PartialTypes.USER);
+ }
+}
+
+module.exports = GenericAction;
diff --git a/node_modules/discord.js/src/client/actions/ActionsManager.js b/node_modules/discord.js/src/client/actions/ActionsManager.js
new file mode 100644
index 0000000..7e1df12
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/ActionsManager.js
@@ -0,0 +1,45 @@
+'use strict';
+
+class ActionsManager {
+ constructor(client) {
+ this.client = client;
+
+ this.register(require('./MessageCreate'));
+ this.register(require('./MessageDelete'));
+ this.register(require('./MessageDeleteBulk'));
+ this.register(require('./MessageUpdate'));
+ this.register(require('./MessageReactionAdd'));
+ this.register(require('./MessageReactionRemove'));
+ this.register(require('./MessageReactionRemoveAll'));
+ this.register(require('./MessageReactionRemoveEmoji'));
+ this.register(require('./ChannelCreate'));
+ this.register(require('./ChannelDelete'));
+ this.register(require('./ChannelUpdate'));
+ this.register(require('./GuildDelete'));
+ this.register(require('./GuildUpdate'));
+ this.register(require('./InviteCreate'));
+ this.register(require('./InviteDelete'));
+ this.register(require('./GuildMemberRemove'));
+ this.register(require('./GuildBanRemove'));
+ this.register(require('./GuildRoleCreate'));
+ this.register(require('./GuildRoleDelete'));
+ this.register(require('./GuildRoleUpdate'));
+ this.register(require('./PresenceUpdate'));
+ this.register(require('./UserUpdate'));
+ this.register(require('./VoiceStateUpdate'));
+ this.register(require('./GuildEmojiCreate'));
+ this.register(require('./GuildEmojiDelete'));
+ this.register(require('./GuildEmojiUpdate'));
+ this.register(require('./GuildEmojisUpdate'));
+ this.register(require('./GuildRolesPositionUpdate'));
+ this.register(require('./GuildChannelsPositionUpdate'));
+ this.register(require('./GuildIntegrationsUpdate'));
+ this.register(require('./WebhooksUpdate'));
+ }
+
+ register(Action) {
+ this[Action.name.replace(/Action$/, '')] = new Action(this.client);
+ }
+}
+
+module.exports = ActionsManager;
diff --git a/node_modules/discord.js/src/client/actions/ChannelCreate.js b/node_modules/discord.js/src/client/actions/ChannelCreate.js
new file mode 100644
index 0000000..fa60a0b
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/ChannelCreate.js
@@ -0,0 +1,23 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class ChannelCreateAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const existing = client.channels.cache.has(data.id);
+ const channel = client.channels.add(data);
+ if (!existing && channel) {
+ /**
+ * Emitted whenever a channel is created.
+ * @event Client#channelCreate
+ * @param {DMChannel|GuildChannel} channel The channel that was created
+ */
+ client.emit(Events.CHANNEL_CREATE, channel);
+ }
+ return { channel };
+ }
+}
+
+module.exports = ChannelCreateAction;
diff --git a/node_modules/discord.js/src/client/actions/ChannelDelete.js b/node_modules/discord.js/src/client/actions/ChannelDelete.js
new file mode 100644
index 0000000..2956d72
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/ChannelDelete.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const Action = require('./Action');
+const DMChannel = require('../../structures/DMChannel');
+const { Events } = require('../../util/Constants');
+
+class ChannelDeleteAction extends Action {
+ constructor(client) {
+ super(client);
+ this.deleted = new Map();
+ }
+
+ handle(data) {
+ const client = this.client;
+ let channel = client.channels.cache.get(data.id);
+
+ if (channel) {
+ client.channels.remove(channel.id);
+ channel.deleted = true;
+ if (channel.messages && !(channel instanceof DMChannel)) {
+ for (const message of channel.messages.cache.values()) {
+ message.deleted = true;
+ }
+ }
+ /**
+ * Emitted whenever a channel is deleted.
+ * @event Client#channelDelete
+ * @param {DMChannel|GuildChannel} channel The channel that was deleted
+ */
+ client.emit(Events.CHANNEL_DELETE, channel);
+ }
+
+ return { channel };
+ }
+}
+
+module.exports = ChannelDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/ChannelUpdate.js b/node_modules/discord.js/src/client/actions/ChannelUpdate.js
new file mode 100644
index 0000000..06bb71b
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/ChannelUpdate.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const Action = require('./Action');
+const Channel = require('../../structures/Channel');
+const { ChannelTypes } = require('../../util/Constants');
+
+class ChannelUpdateAction extends Action {
+ handle(data) {
+ const client = this.client;
+
+ let channel = client.channels.cache.get(data.id);
+ if (channel) {
+ const old = channel._update(data);
+
+ if (ChannelTypes[channel.type.toUpperCase()] !== data.type) {
+ const newChannel = Channel.create(this.client, data, channel.guild);
+ for (const [id, message] of channel.messages.cache) newChannel.messages.cache.set(id, message);
+ newChannel._typing = new Map(channel._typing);
+ channel = newChannel;
+ this.client.channels.cache.set(channel.id, channel);
+ }
+
+ return {
+ old,
+ updated: channel,
+ };
+ }
+
+ return {};
+ }
+}
+
+module.exports = ChannelUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildBanRemove.js b/node_modules/discord.js/src/client/actions/GuildBanRemove.js
new file mode 100644
index 0000000..fc28e11
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildBanRemove.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildBanRemove extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ const user = client.users.add(data.user);
+ /**
+ * Emitted whenever a member is unbanned from a guild.
+ * @event Client#guildBanRemove
+ * @param {Guild} guild The guild that the unban occurred in
+ * @param {User} user The user that was unbanned
+ */
+ if (guild && user) client.emit(Events.GUILD_BAN_REMOVE, guild, user);
+ }
+}
+
+module.exports = GuildBanRemove;
diff --git a/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js b/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js
new file mode 100644
index 0000000..a393167
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildChannelsPositionUpdate.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const Action = require('./Action');
+
+class GuildChannelsPositionUpdate extends Action {
+ handle(data) {
+ const client = this.client;
+
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ for (const partialChannel of data.channels) {
+ const channel = guild.channels.cache.get(partialChannel.id);
+ if (channel) channel.rawPosition = partialChannel.position;
+ }
+ }
+
+ return { guild };
+ }
+}
+
+module.exports = GuildChannelsPositionUpdate;
diff --git a/node_modules/discord.js/src/client/actions/GuildDelete.js b/node_modules/discord.js/src/client/actions/GuildDelete.js
new file mode 100644
index 0000000..8bb630f
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildDelete.js
@@ -0,0 +1,67 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildDeleteAction extends Action {
+ constructor(client) {
+ super(client);
+ this.deleted = new Map();
+ }
+
+ handle(data) {
+ const client = this.client;
+
+ let guild = client.guilds.cache.get(data.id);
+ if (guild) {
+ for (const channel of guild.channels.cache.values()) {
+ if (channel.type === 'text') channel.stopTyping(true);
+ }
+
+ if (data.unavailable) {
+ // Guild is unavailable
+ guild.available = false;
+
+ /**
+ * Emitted whenever a guild becomes unavailable, likely due to a server outage.
+ * @event Client#guildUnavailable
+ * @param {Guild} guild The guild that has become unavailable
+ */
+ client.emit(Events.GUILD_UNAVAILABLE, guild);
+
+ // Stops the GuildDelete packet thinking a guild was actually deleted,
+ // handles emitting of event itself
+ return {
+ guild: null,
+ };
+ }
+
+ for (const channel of guild.channels.cache.values()) this.client.channels.remove(channel.id);
+ if (guild.voice && guild.voice.connection) guild.voice.connection.disconnect();
+
+ // Delete guild
+ client.guilds.cache.delete(guild.id);
+ guild.deleted = true;
+
+ /**
+ * Emitted whenever a guild kicks the client or the guild is deleted/left.
+ * @event Client#guildDelete
+ * @param {Guild} guild The guild that was deleted
+ */
+ client.emit(Events.GUILD_DELETE, guild);
+
+ this.deleted.set(guild.id, guild);
+ this.scheduleForDeletion(guild.id);
+ } else {
+ guild = this.deleted.get(data.id) || null;
+ }
+
+ return { guild };
+ }
+
+ scheduleForDeletion(id) {
+ this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout);
+ }
+}
+
+module.exports = GuildDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js
new file mode 100644
index 0000000..379c62e
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildEmojiCreate.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildEmojiCreateAction extends Action {
+ handle(guild, createdEmoji) {
+ const emoji = guild.emojis.add(createdEmoji);
+ /**
+ * Emitted whenever a custom emoji is created in a guild.
+ * @event Client#emojiCreate
+ * @param {GuildEmoji} emoji The emoji that was created
+ */
+ this.client.emit(Events.GUILD_EMOJI_CREATE, emoji);
+ return { emoji };
+ }
+}
+
+module.exports = GuildEmojiCreateAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js b/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js
new file mode 100644
index 0000000..42af70c
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildEmojiDelete.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildEmojiDeleteAction extends Action {
+ handle(emoji) {
+ emoji.guild.emojis.cache.delete(emoji.id);
+ emoji.deleted = true;
+ /**
+ * Emitted whenever a custom emoji is deleted in a guild.
+ * @event Client#emojiDelete
+ * @param {GuildEmoji} emoji The emoji that was deleted
+ */
+ this.client.emit(Events.GUILD_EMOJI_DELETE, emoji);
+ return { emoji };
+ }
+}
+
+module.exports = GuildEmojiDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js b/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js
new file mode 100644
index 0000000..9fa59c9
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildEmojiUpdate.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildEmojiUpdateAction extends Action {
+ handle(current, data) {
+ const old = current._update(data);
+ /**
+ * Emitted whenever a custom emoji is updated in a guild.
+ * @event Client#emojiUpdate
+ * @param {GuildEmoji} oldEmoji The old emoji
+ * @param {GuildEmoji} newEmoji The new emoji
+ */
+ this.client.emit(Events.GUILD_EMOJI_UPDATE, old, current);
+ return { emoji: current };
+ }
+}
+
+module.exports = GuildEmojiUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js
new file mode 100644
index 0000000..7711933
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildEmojisUpdate.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const Action = require('./Action');
+
+class GuildEmojisUpdateAction extends Action {
+ handle(data) {
+ const guild = this.client.guilds.cache.get(data.guild_id);
+ if (!guild || !guild.emojis) return;
+
+ const deletions = new Map(guild.emojis.cache);
+
+ for (const emoji of data.emojis) {
+ // Determine type of emoji event
+ const cachedEmoji = guild.emojis.cache.get(emoji.id);
+ if (cachedEmoji) {
+ deletions.delete(emoji.id);
+ if (!cachedEmoji.equals(emoji)) {
+ // Emoji updated
+ this.client.actions.GuildEmojiUpdate.handle(cachedEmoji, emoji);
+ }
+ } else {
+ // Emoji added
+ this.client.actions.GuildEmojiCreate.handle(guild, emoji);
+ }
+ }
+
+ for (const emoji of deletions.values()) {
+ // Emoji deleted
+ this.client.actions.GuildEmojiDelete.handle(emoji);
+ }
+ }
+}
+
+module.exports = GuildEmojisUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js b/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js
new file mode 100644
index 0000000..bbce076
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildIntegrationsUpdate.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildIntegrationsUpdate extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ /**
+ * Emitted whenever a guild integration is updated
+ * @event Client#guildIntegrationsUpdate
+ * @param {Guild} guild The guild whose integrations were updated
+ */
+ if (guild) client.emit(Events.GUILD_INTEGRATIONS_UPDATE, guild);
+ }
+}
+
+module.exports = GuildIntegrationsUpdate;
diff --git a/node_modules/discord.js/src/client/actions/GuildMemberRemove.js b/node_modules/discord.js/src/client/actions/GuildMemberRemove.js
new file mode 100644
index 0000000..f0fe3b3
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildMemberRemove.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events, Status } = require('../../util/Constants');
+
+class GuildMemberRemoveAction extends Action {
+ handle(data, shard) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ let member = null;
+ if (guild) {
+ member = this.getMember(data, guild);
+ guild.memberCount--;
+ if (member) {
+ member.deleted = true;
+ guild.members.cache.delete(member.id);
+ /**
+ * Emitted whenever a member leaves a guild, or is kicked.
+ * @event Client#guildMemberRemove
+ * @param {GuildMember} member The member that has left/been kicked from the guild
+ */
+ if (shard.status === Status.READY) client.emit(Events.GUILD_MEMBER_REMOVE, member);
+ }
+ guild.voiceStates.cache.delete(data.user.id);
+ }
+ return { guild, member };
+ }
+}
+
+module.exports = GuildMemberRemoveAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildRoleCreate.js b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js
new file mode 100644
index 0000000..d7d5214
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildRoleCreate.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildRoleCreate extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ let role;
+ if (guild) {
+ const already = guild.roles.cache.has(data.role.id);
+ role = guild.roles.add(data.role);
+ /**
+ * Emitted whenever a role is created.
+ * @event Client#roleCreate
+ * @param {Role} role The role that was created
+ */
+ if (!already) client.emit(Events.GUILD_ROLE_CREATE, role);
+ }
+ return { role };
+ }
+}
+
+module.exports = GuildRoleCreate;
diff --git a/node_modules/discord.js/src/client/actions/GuildRoleDelete.js b/node_modules/discord.js/src/client/actions/GuildRoleDelete.js
new file mode 100644
index 0000000..51754b3
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildRoleDelete.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildRoleDeleteAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ let role;
+
+ if (guild) {
+ role = guild.roles.cache.get(data.role_id);
+ if (role) {
+ guild.roles.cache.delete(data.role_id);
+ role.deleted = true;
+ /**
+ * Emitted whenever a guild role is deleted.
+ * @event Client#roleDelete
+ * @param {Role} role The role that was deleted
+ */
+ client.emit(Events.GUILD_ROLE_DELETE, role);
+ }
+ }
+
+ return { role };
+ }
+}
+
+module.exports = GuildRoleDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js b/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js
new file mode 100644
index 0000000..faea120
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildRoleUpdate.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildRoleUpdateAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+
+ if (guild) {
+ let old = null;
+
+ const role = guild.roles.cache.get(data.role.id);
+ if (role) {
+ old = role._update(data.role);
+ /**
+ * Emitted whenever a guild role is updated.
+ * @event Client#roleUpdate
+ * @param {Role} oldRole The role before the update
+ * @param {Role} newRole The role after the update
+ */
+ client.emit(Events.GUILD_ROLE_UPDATE, old, role);
+ }
+
+ return {
+ old,
+ updated: role,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
+
+module.exports = GuildRoleUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js b/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js
new file mode 100644
index 0000000..d7abca9
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildRolesPositionUpdate.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const Action = require('./Action');
+
+class GuildRolesPositionUpdate extends Action {
+ handle(data) {
+ const client = this.client;
+
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ for (const partialRole of data.roles) {
+ const role = guild.roles.cache.get(partialRole.id);
+ if (role) role.rawPosition = partialRole.position;
+ }
+ }
+
+ return { guild };
+ }
+}
+
+module.exports = GuildRolesPositionUpdate;
diff --git a/node_modules/discord.js/src/client/actions/GuildUpdate.js b/node_modules/discord.js/src/client/actions/GuildUpdate.js
new file mode 100644
index 0000000..78a8afb
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/GuildUpdate.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class GuildUpdateAction extends Action {
+ handle(data) {
+ const client = this.client;
+
+ const guild = client.guilds.cache.get(data.id);
+ if (guild) {
+ const old = guild._update(data);
+ /**
+ * Emitted whenever a guild is updated - e.g. name change.
+ * @event Client#guildUpdate
+ * @param {Guild} oldGuild The guild before the update
+ * @param {Guild} newGuild The guild after the update
+ */
+ client.emit(Events.GUILD_UPDATE, old, guild);
+ return {
+ old,
+ updated: guild,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
+
+module.exports = GuildUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/InviteCreate.js b/node_modules/discord.js/src/client/actions/InviteCreate.js
new file mode 100644
index 0000000..6381331
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/InviteCreate.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const Action = require('./Action');
+const Invite = require('../../structures/Invite');
+const { Events } = require('../../util/Constants');
+
+class InviteCreateAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = client.channels.cache.get(data.channel_id);
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (!channel && !guild) return false;
+
+ const inviteData = Object.assign(data, { channel, guild });
+ const invite = new Invite(client, inviteData);
+ /**
+ * Emitted when an invite is created.
+ * <info> This event only triggers if the client has `MANAGE_GUILD` permissions for the guild,
+ * or `MANAGE_CHANNEL` permissions for the channel.</info>
+ * @event Client#inviteCreate
+ * @param {Invite} invite The invite that was created
+ */
+ client.emit(Events.INVITE_CREATE, invite);
+ return { invite };
+ }
+}
+
+module.exports = InviteCreateAction;
diff --git a/node_modules/discord.js/src/client/actions/InviteDelete.js b/node_modules/discord.js/src/client/actions/InviteDelete.js
new file mode 100644
index 0000000..92692c3
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/InviteDelete.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const Action = require('./Action');
+const Invite = require('../../structures/Invite');
+const { Events } = require('../../util/Constants');
+
+class InviteDeleteAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = client.channels.cache.get(data.channel_id);
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (!channel && !guild) return false;
+
+ const inviteData = Object.assign(data, { channel, guild });
+ const invite = new Invite(client, inviteData);
+
+ /**
+ * Emitted when an invite is deleted.
+ * <info> This event only triggers if the client has `MANAGE_GUILD` permissions for the guild,
+ * or `MANAGE_CHANNEL` permissions for the channel.</info>
+ * @event Client#inviteDelete
+ * @param {Invite} invite The invite that was deleted
+ */
+ client.emit(Events.INVITE_DELETE, invite);
+ return { invite };
+ }
+}
+
+module.exports = InviteDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/MessageCreate.js b/node_modules/discord.js/src/client/actions/MessageCreate.js
new file mode 100644
index 0000000..7138707
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageCreate.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class MessageCreateAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = client.channels.cache.get(data.channel_id);
+ if (channel) {
+ const existing = channel.messages.cache.get(data.id);
+ if (existing) return { message: existing };
+ const message = channel.messages.add(data);
+ const user = message.author;
+ let member = message.member;
+ channel.lastMessageID = data.id;
+ if (user) {
+ user.lastMessageID = data.id;
+ user.lastMessageChannelID = channel.id;
+ }
+ if (member) {
+ member.lastMessageID = data.id;
+ member.lastMessageChannelID = channel.id;
+ }
+
+ /**
+ * Emitted whenever a message is created.
+ * @event Client#message
+ * @param {Message} message The created message
+ */
+ client.emit(Events.MESSAGE_CREATE, message);
+ return { message };
+ }
+
+ return {};
+ }
+}
+
+module.exports = MessageCreateAction;
diff --git a/node_modules/discord.js/src/client/actions/MessageDelete.js b/node_modules/discord.js/src/client/actions/MessageDelete.js
new file mode 100644
index 0000000..0210625
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageDelete.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class MessageDeleteAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = this.getChannel(data);
+ let message;
+ if (channel) {
+ message = this.getMessage(data, channel);
+ if (message) {
+ channel.messages.cache.delete(message.id);
+ message.deleted = true;
+ /**
+ * Emitted whenever a message is deleted.
+ * @event Client#messageDelete
+ * @param {Message} message The deleted message
+ */
+ client.emit(Events.MESSAGE_DELETE, message);
+ }
+ }
+
+ return { message };
+ }
+}
+
+module.exports = MessageDeleteAction;
diff --git a/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js
new file mode 100644
index 0000000..8686b1d
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageDeleteBulk.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const Action = require('./Action');
+const Collection = require('../../util/Collection');
+const { Events } = require('../../util/Constants');
+
+class MessageDeleteBulkAction extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = client.channels.cache.get(data.channel_id);
+
+ if (channel) {
+ const ids = data.ids;
+ const messages = new Collection();
+ for (const id of ids) {
+ const message = this.getMessage(
+ {
+ id,
+ guild_id: data.guild_id,
+ },
+ channel,
+ false,
+ );
+ if (message) {
+ message.deleted = true;
+ messages.set(message.id, message);
+ channel.messages.cache.delete(id);
+ }
+ }
+
+ /**
+ * Emitted whenever messages are deleted in bulk.
+ * @event Client#messageDeleteBulk
+ * @param {Collection<Snowflake, Message>} messages The deleted messages, mapped by their ID
+ */
+ if (messages.size > 0) client.emit(Events.MESSAGE_BULK_DELETE, messages);
+ return { messages };
+ }
+ return {};
+ }
+}
+
+module.exports = MessageDeleteBulkAction;
diff --git a/node_modules/discord.js/src/client/actions/MessageReactionAdd.js b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js
new file mode 100644
index 0000000..22287db
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageReactionAdd.js
@@ -0,0 +1,50 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+const { PartialTypes } = require('../../util/Constants');
+
+/*
+{ user_id: 'id',
+ message_id: 'id',
+ emoji: { name: '�', id: null },
+ channel_id: 'id' } }
+*/
+
+class MessageReactionAdd extends Action {
+ handle(data) {
+ if (!data.emoji) return false;
+
+ const user = this.getUser(data);
+ if (!user) return false;
+
+ // Verify channel
+ const channel = this.getChannel(data);
+ if (!channel || channel.type === 'voice') return false;
+
+ // Verify message
+ const message = this.getMessage(data, channel);
+ if (!message) return false;
+
+ // Verify reaction
+ if (message.partial && !this.client.options.partials.includes(PartialTypes.REACTION)) return false;
+ const reaction = message.reactions.add({
+ emoji: data.emoji,
+ count: message.partial ? null : 0,
+ me: user.id === this.client.user.id,
+ });
+ if (!reaction) return false;
+ reaction._add(user);
+ /**
+ * Emitted whenever a reaction is added to a cached message.
+ * @event Client#messageReactionAdd
+ * @param {MessageReaction} messageReaction The reaction object
+ * @param {User} user The user that applied the guild or reaction emoji
+ */
+ this.client.emit(Events.MESSAGE_REACTION_ADD, reaction, user);
+
+ return { message, reaction, user };
+ }
+}
+
+module.exports = MessageReactionAdd;
diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemove.js b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js
new file mode 100644
index 0000000..a40aa75
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageReactionRemove.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+/*
+{ user_id: 'id',
+ message_id: 'id',
+ emoji: { name: '�', id: null },
+ channel_id: 'id' } }
+*/
+
+class MessageReactionRemove extends Action {
+ handle(data) {
+ if (!data.emoji) return false;
+
+ const user = this.getUser(data);
+ if (!user) return false;
+
+ // Verify channel
+ const channel = this.getChannel(data);
+ if (!channel || channel.type === 'voice') return false;
+
+ // Verify message
+ const message = this.getMessage(data, channel);
+ if (!message) return false;
+
+ // Verify reaction
+ const reaction = this.getReaction(data, message, user);
+ if (!reaction) return false;
+ reaction._remove(user);
+ /**
+ * Emitted whenever a reaction is removed from a cached message.
+ * @event Client#messageReactionRemove
+ * @param {MessageReaction} messageReaction The reaction object
+ * @param {User} user The user whose emoji or reaction emoji was removed
+ */
+ this.client.emit(Events.MESSAGE_REACTION_REMOVE, reaction, user);
+
+ return { message, reaction, user };
+ }
+}
+
+module.exports = MessageReactionRemove;
diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js
new file mode 100644
index 0000000..14b79bf
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveAll.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class MessageReactionRemoveAll extends Action {
+ handle(data) {
+ // Verify channel
+ const channel = this.getChannel(data);
+ if (!channel || channel.type === 'voice') return false;
+
+ // Verify message
+ const message = this.getMessage(data, channel);
+ if (!message) return false;
+
+ message.reactions.cache.clear();
+ this.client.emit(Events.MESSAGE_REACTION_REMOVE_ALL, message);
+
+ return { message };
+ }
+}
+
+/**
+ * Emitted whenever all reactions are removed from a cached message.
+ * @event Client#messageReactionRemoveAll
+ * @param {Message} message The message the reactions were removed from
+ */
+
+module.exports = MessageReactionRemoveAll;
diff --git a/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js
new file mode 100644
index 0000000..143702c
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageReactionRemoveEmoji.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class MessageReactionRemoveEmoji extends Action {
+ handle(data) {
+ const channel = this.getChannel(data);
+ if (!channel || channel.type === 'voice') return false;
+
+ const message = this.getMessage(data, channel);
+ if (!message) return false;
+
+ const reaction = this.getReaction(data, message);
+ if (!reaction) return false;
+ if (!message.partial) message.reactions.cache.delete(reaction.emoji.id || reaction.emoji.name);
+
+ /**
+ * Emitted when a bot removes an emoji reaction from a cached message.
+ * @event Client#messageReactionRemoveEmoji
+ * @param {MessageReaction} reaction The reaction that was removed
+ */
+ this.client.emit(Events.MESSAGE_REACTION_REMOVE_EMOJI, reaction);
+ return { reaction };
+ }
+}
+
+module.exports = MessageReactionRemoveEmoji;
diff --git a/node_modules/discord.js/src/client/actions/MessageUpdate.js b/node_modules/discord.js/src/client/actions/MessageUpdate.js
new file mode 100644
index 0000000..07e2aac
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/MessageUpdate.js
@@ -0,0 +1,24 @@
+'use strict';
+
+const Action = require('./Action');
+
+class MessageUpdateAction extends Action {
+ handle(data) {
+ const channel = this.getChannel(data);
+ if (channel) {
+ const { id, channel_id, guild_id, author, timestamp, type } = data;
+ const message = this.getMessage({ id, channel_id, guild_id, author, timestamp, type }, channel);
+ if (message) {
+ message.patch(data);
+ return {
+ old: message._edits[0],
+ updated: message,
+ };
+ }
+ }
+
+ return {};
+ }
+}
+
+module.exports = MessageUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/PresenceUpdate.js b/node_modules/discord.js/src/client/actions/PresenceUpdate.js
new file mode 100644
index 0000000..f74fbeb
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/PresenceUpdate.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class PresenceUpdateAction extends Action {
+ handle(data) {
+ let user = this.client.users.cache.get(data.user.id);
+ if (!user && data.user.username) user = this.client.users.add(data.user);
+ if (!user) return;
+
+ if (data.user && data.user.username) {
+ if (!user.equals(data.user)) this.client.actions.UserUpdate.handle(data.user);
+ }
+
+ const guild = this.client.guilds.cache.get(data.guild_id);
+ if (!guild) return;
+
+ let oldPresence = guild.presences.cache.get(user.id);
+ if (oldPresence) oldPresence = oldPresence._clone();
+ let member = guild.members.cache.get(user.id);
+ if (!member && data.status !== 'offline') {
+ member = guild.members.add({
+ user,
+ roles: data.roles,
+ deaf: false,
+ mute: false,
+ });
+ this.client.emit(Events.GUILD_MEMBER_AVAILABLE, member);
+ }
+ guild.presences.add(Object.assign(data, { guild }));
+ if (member && this.client.listenerCount(Events.PRESENCE_UPDATE)) {
+ /**
+ * Emitted whenever a guild member's presence (e.g. status, activity) is changed.
+ * @event Client#presenceUpdate
+ * @param {?Presence} oldPresence The presence before the update, if one at all
+ * @param {Presence} newPresence The presence after the update
+ */
+ this.client.emit(Events.PRESENCE_UPDATE, oldPresence, member.presence);
+ }
+ }
+}
+
+module.exports = PresenceUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/UserUpdate.js b/node_modules/discord.js/src/client/actions/UserUpdate.js
new file mode 100644
index 0000000..7279ca7
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/UserUpdate.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class UserUpdateAction extends Action {
+ handle(data) {
+ const client = this.client;
+
+ const newUser = client.users.cache.get(data.id);
+ const oldUser = newUser._update(data);
+
+ if (!oldUser.equals(newUser)) {
+ /**
+ * Emitted whenever a user's details (e.g. username) are changed.
+ * @event Client#userUpdate
+ * @param {User} oldUser The user before the update
+ * @param {User} newUser The user after the update
+ */
+ client.emit(Events.USER_UPDATE, oldUser, newUser);
+ return {
+ old: oldUser,
+ updated: newUser,
+ };
+ }
+
+ return {
+ old: null,
+ updated: null,
+ };
+ }
+}
+
+module.exports = UserUpdateAction;
diff --git a/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js
new file mode 100644
index 0000000..6f2ee9d
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/VoiceStateUpdate.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const Action = require('./Action');
+const VoiceState = require('../../structures/VoiceState');
+const { Events } = require('../../util/Constants');
+
+class VoiceStateUpdate extends Action {
+ handle(data) {
+ const client = this.client;
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ // Update the state
+ const oldState = guild.voiceStates.cache.has(data.user_id)
+ ? guild.voiceStates.cache.get(data.user_id)._clone()
+ : new VoiceState(guild, { user_id: data.user_id });
+
+ const newState = guild.voiceStates.add(data);
+
+ // Get the member
+ let member = guild.members.cache.get(data.user_id);
+ if (member && data.member) {
+ member._patch(data.member);
+ } else if (data.member && data.member.user && data.member.joined_at) {
+ member = guild.members.add(data.member);
+ }
+
+ // Emit event
+ if (member && member.user.id === client.user.id) {
+ client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`);
+ client.voice.onVoiceStateUpdate(data);
+ }
+
+ /**
+ * Emitted whenever a member changes voice state - e.g. joins/leaves a channel, mutes/unmutes.
+ * @event Client#voiceStateUpdate
+ * @param {VoiceState} oldState The voice state before the update
+ * @param {VoiceState} newState The voice state after the update
+ */
+ client.emit(Events.VOICE_STATE_UPDATE, oldState, newState);
+ }
+ }
+}
+
+module.exports = VoiceStateUpdate;
diff --git a/node_modules/discord.js/src/client/actions/WebhooksUpdate.js b/node_modules/discord.js/src/client/actions/WebhooksUpdate.js
new file mode 100644
index 0000000..fdf9c56
--- /dev/null
+++ b/node_modules/discord.js/src/client/actions/WebhooksUpdate.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const Action = require('./Action');
+const { Events } = require('../../util/Constants');
+
+class WebhooksUpdate extends Action {
+ handle(data) {
+ const client = this.client;
+ const channel = client.channels.cache.get(data.channel_id);
+ /**
+ * Emitted whenever a guild text channel has its webhooks changed.
+ * @event Client#webhookUpdate
+ * @param {TextChannel} channel The channel that had a webhook update
+ */
+ if (channel) client.emit(Events.WEBHOOKS_UPDATE, channel);
+ }
+}
+
+module.exports = WebhooksUpdate;
diff --git a/node_modules/discord.js/src/client/voice/ClientVoiceManager.js b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js
new file mode 100644
index 0000000..1eab808
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/ClientVoiceManager.js
@@ -0,0 +1,110 @@
+'use strict';
+
+const VoiceBroadcast = require('./VoiceBroadcast');
+const VoiceConnection = require('./VoiceConnection');
+const { Error } = require('../../errors');
+const Collection = require('../../util/Collection');
+
+/**
+ * Manages voice connections for the client
+ */
+class ClientVoiceManager {
+ constructor(client) {
+ /**
+ * The client that instantiated this voice manager
+ * @type {Client}
+ * @readonly
+ * @name ClientVoiceManager#client
+ */
+ Object.defineProperty(this, 'client', { value: client });
+
+ /**
+ * A collection mapping connection IDs to the Connection objects
+ * @type {Collection<Snowflake, VoiceConnection>}
+ */
+ this.connections = new Collection();
+
+ /**
+ * Active voice broadcasts that have been created
+ * @type {VoiceBroadcast[]}
+ */
+ this.broadcasts = [];
+ }
+
+ /**
+ * Creates a voice broadcast.
+ * @returns {VoiceBroadcast}
+ */
+ createBroadcast() {
+ const broadcast = new VoiceBroadcast(this.client);
+ this.broadcasts.push(broadcast);
+ return broadcast;
+ }
+
+ onVoiceServer({ guild_id, token, endpoint }) {
+ this.client.emit('debug', `[VOICE] voiceServer guild: ${guild_id} token: ${token} endpoint: ${endpoint}`);
+ const connection = this.connections.get(guild_id);
+ if (connection) connection.setTokenAndEndpoint(token, endpoint);
+ }
+
+ onVoiceStateUpdate({ guild_id, session_id, channel_id }) {
+ const connection = this.connections.get(guild_id);
+ this.client.emit('debug', `[VOICE] connection? ${!!connection}, ${guild_id} ${session_id} ${channel_id}`);
+ if (!connection) return;
+ if (!channel_id) {
+ connection._disconnect();
+ this.connections.delete(guild_id);
+ return;
+ }
+ connection.channel = this.client.channels.cache.get(channel_id);
+ connection.setSessionID(session_id);
+ }
+
+ /**
+ * Sets up a request to join a voice channel.
+ * @param {VoiceChannel} channel The voice channel to join
+ * @returns {Promise<VoiceConnection>}
+ * @private
+ */
+ joinChannel(channel) {
+ return new Promise((resolve, reject) => {
+ if (!channel.joinable) {
+ throw new Error('VOICE_JOIN_CHANNEL', channel.full);
+ }
+
+ let connection = this.connections.get(channel.guild.id);
+
+ if (connection) {
+ if (connection.channel.id !== channel.id) {
+ this.connections.get(channel.guild.id).updateChannel(channel);
+ }
+ resolve(connection);
+ return;
+ } else {
+ connection = new VoiceConnection(this, channel);
+ connection.on('debug', msg =>
+ this.client.emit('debug', `[VOICE (${channel.guild.id}:${connection.status})]: ${msg}`),
+ );
+ connection.authenticate();
+ this.connections.set(channel.guild.id, connection);
+ }
+
+ connection.once('failed', reason => {
+ this.connections.delete(channel.guild.id);
+ reject(reason);
+ });
+
+ connection.on('error', reject);
+
+ connection.once('authenticated', () => {
+ connection.once('ready', () => {
+ resolve(connection);
+ connection.removeListener('error', reject);
+ });
+ connection.once('disconnect', () => this.connections.delete(channel.guild.id));
+ });
+ });
+ }
+}
+
+module.exports = ClientVoiceManager;
diff --git a/node_modules/discord.js/src/client/voice/VoiceBroadcast.js b/node_modules/discord.js/src/client/voice/VoiceBroadcast.js
new file mode 100644
index 0000000..5755b52
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/VoiceBroadcast.js
@@ -0,0 +1,111 @@
+'use strict';
+
+const EventEmitter = require('events');
+const BroadcastAudioPlayer = require('./player/BroadcastAudioPlayer');
+const PlayInterface = require('./util/PlayInterface');
+const { Events } = require('../../util/Constants');
+
+/**
+ * A voice broadcast can be played across multiple voice connections for improved shared-stream efficiency.
+ *
+ * Example usage:
+ * ```js
+ * const broadcast = client.voice.createBroadcast();
+ * broadcast.play('./music.mp3');
+ * // Play "music.mp3" in all voice connections that the client is in
+ * for (const connection of client.voice.connections.values()) {
+ * connection.play(broadcast);
+ * }
+ * ```
+ * @implements {PlayInterface}
+ * @extends {EventEmitter}
+ */
+class VoiceBroadcast extends EventEmitter {
+ constructor(client) {
+ super();
+ /**
+ * The client that created the broadcast
+ * @type {Client}
+ */
+ this.client = client;
+ /**
+ * The subscribed StreamDispatchers of this broadcast
+ * @type {StreamDispatcher[]}
+ */
+ this.subscribers = [];
+ this.player = new BroadcastAudioPlayer(this);
+ }
+
+ /**
+ * The current master dispatcher, if any. This dispatcher controls all that is played by subscribed dispatchers.
+ * @type {?BroadcastDispatcher}
+ * @readonly
+ */
+ get dispatcher() {
+ return this.player.dispatcher;
+ }
+
+ /**
+ * Play an audio resource.
+ * @param {ReadableStream|string} resource The resource to play.
+ * @param {StreamOptions} [options] The options to play.
+ * @example
+ * // Play a local audio file
+ * broadcast.play('/home/hydrabolt/audio.mp3', { volume: 0.5 });
+ * @example
+ * // Play a ReadableStream
+ * broadcast.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { filter: 'audioonly' }));
+ * @example
+ * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html
+ * broadcast.play('http://www.sample-videos.com/audio/mp3/wave.mp3');
+ * @returns {BroadcastDispatcher}
+ */
+ play() {
+ return null;
+ }
+
+ /**
+ * Ends the broadcast, unsubscribing all subscribed channels and deleting the broadcast
+ */
+ end() {
+ for (const dispatcher of this.subscribers) this.delete(dispatcher);
+ const index = this.client.voice.broadcasts.indexOf(this);
+ if (index !== -1) this.client.voice.broadcasts.splice(index, 1);
+ }
+
+ add(dispatcher) {
+ const index = this.subscribers.indexOf(dispatcher);
+ if (index === -1) {
+ this.subscribers.push(dispatcher);
+ /**
+ * Emitted whenever a stream dispatcher subscribes to the broadcast.
+ * @event VoiceBroadcast#subscribe
+ * @param {StreamDispatcher} subscriber The subscribed dispatcher
+ */
+ this.emit(Events.VOICE_BROADCAST_SUBSCRIBE, dispatcher);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ delete(dispatcher) {
+ const index = this.subscribers.indexOf(dispatcher);
+ if (index !== -1) {
+ this.subscribers.splice(index, 1);
+ dispatcher.destroy();
+ /**
+ * Emitted whenever a stream dispatcher unsubscribes to the broadcast.
+ * @event VoiceBroadcast#unsubscribe
+ * @param {StreamDispatcher} dispatcher The unsubscribed dispatcher
+ */
+ this.emit(Events.VOICE_BROADCAST_UNSUBSCRIBE, dispatcher);
+ return true;
+ }
+ return false;
+ }
+}
+
+PlayInterface.applyToClass(VoiceBroadcast);
+
+module.exports = VoiceBroadcast;
diff --git a/node_modules/discord.js/src/client/voice/VoiceConnection.js b/node_modules/discord.js/src/client/voice/VoiceConnection.js
new file mode 100644
index 0000000..5f0e995
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/VoiceConnection.js
@@ -0,0 +1,523 @@
+'use strict';
+
+const EventEmitter = require('events');
+const VoiceUDP = require('./networking/VoiceUDPClient');
+const VoiceWebSocket = require('./networking/VoiceWebSocket');
+const AudioPlayer = require('./player/AudioPlayer');
+const VoiceReceiver = require('./receiver/Receiver');
+const PlayInterface = require('./util/PlayInterface');
+const Silence = require('./util/Silence');
+const { Error } = require('../../errors');
+const { OPCodes, VoiceOPCodes, VoiceStatus, Events } = require('../../util/Constants');
+const Speaking = require('../../util/Speaking');
+const Util = require('../../util/Util');
+
+// Workaround for Discord now requiring silence to be sent before being able to receive audio
+class SingleSilence extends Silence {
+ _read() {
+ super._read();
+ this.push(null);
+ }
+}
+
+const SUPPORTED_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'];
+
+/**
+ * Represents a connection to a guild's voice server.
+ * ```js
+ * // Obtained using:
+ * voiceChannel.join()
+ * .then(connection => {
+ *
+ * });
+ * ```
+ * @extends {EventEmitter}
+ * @implements {PlayInterface}
+ */
+class VoiceConnection extends EventEmitter {
+ constructor(voiceManager, channel) {
+ super();
+
+ /**
+ * The voice manager that instantiated this connection
+ * @type {ClientVoiceManager}
+ */
+ this.voiceManager = voiceManager;
+
+ /**
+ * The voice channel this connection is currently serving
+ * @type {VoiceChannel}
+ */
+ this.channel = channel;
+
+ /**
+ * The current status of the voice connection
+ * @type {VoiceStatus}
+ */
+ this.status = VoiceStatus.AUTHENTICATING;
+
+ /**
+ * Our current speaking state
+ * @type {Readonly<Speaking>}
+ */
+ this.speaking = new Speaking().freeze();
+
+ /**
+ * The authentication data needed to connect to the voice server
+ * @type {Object}
+ * @private
+ */
+ this.authentication = {};
+
+ /**
+ * The audio player for this voice connection
+ * @type {AudioPlayer}
+ */
+ this.player = new AudioPlayer(this);
+
+ this.player.on('debug', m => {
+ /**
+ * Debug info from the connection.
+ * @event VoiceConnection#debug
+ * @param {string} message The debug message
+ */
+ this.emit('debug', `audio player - ${m}`);
+ });
+
+ this.player.on('error', e => {
+ /**
+ * Warning info from the connection.
+ * @event VoiceConnection#warn
+ * @param {string|Error} warning The warning
+ */
+ this.emit('warn', e);
+ });
+
+ this.once('closing', () => this.player.destroy());
+
+ /**
+ * Map SSRC values to user IDs
+ * @type {Map<number, Snowflake>}
+ * @private
+ */
+ this.ssrcMap = new Map();
+
+ /**
+ * Tracks which users are talking
+ * @type {Map<Snowflake, Readonly<Speaking>>}
+ * @private
+ */
+ this._speaking = new Map();
+
+ /**
+ * Object that wraps contains the `ws` and `udp` sockets of this voice connection
+ * @type {Object}
+ * @private
+ */
+ this.sockets = {};
+
+ /**
+ * The voice receiver of this connection
+ * @type {VoiceReceiver}
+ */
+ this.receiver = new VoiceReceiver(this);
+ }
+
+ /**
+ * The client that instantiated this connection
+ * @type {Client}
+ * @readonly
+ */
+ get client() {
+ return this.voiceManager.client;
+ }
+
+ /**
+ * The current stream dispatcher (if any)
+ * @type {?StreamDispatcher}
+ * @readonly
+ */
+ get dispatcher() {
+ return this.player.dispatcher;
+ }
+
+ /**
+ * Sets whether the voice connection should display as "speaking", "soundshare" or "none".
+ * @param {BitFieldResolvable} value The new speaking state
+ * @private
+ */
+ setSpeaking(value) {
+ if (this.speaking.equals(value)) return;
+ if (this.status !== VoiceStatus.CONNECTED) return;
+ this.speaking = new Speaking(value).freeze();
+ this.sockets.ws
+ .sendPacket({
+ op: VoiceOPCodes.SPEAKING,
+ d: {
+ speaking: this.speaking.bitfield,
+ delay: 0,
+ ssrc: this.authentication.ssrc,
+ },
+ })
+ .catch(e => {
+ this.emit('debug', e);
+ });
+ }
+
+ /**
+ * The voice state of this connection
+ * @type {VoiceState}
+ */
+ get voice() {
+ return this.channel.guild.voice;
+ }
+
+ /**
+ * Sends a request to the main gateway to join a voice channel.
+ * @param {Object} [options] The options to provide
+ * @returns {Promise<Shard>}
+ * @private
+ */
+ sendVoiceStateUpdate(options = {}) {
+ options = Util.mergeDefault(
+ {
+ guild_id: this.channel.guild.id,
+ channel_id: this.channel.id,
+ self_mute: this.voice ? this.voice.selfMute : false,
+ self_deaf: this.voice ? this.voice.selfDeaf : false,
+ },
+ options,
+ );
+
+ this.emit('debug', `Sending voice state update: ${JSON.stringify(options)}`);
+
+ return this.channel.guild.shard.send(
+ {
+ op: OPCodes.VOICE_STATE_UPDATE,
+ d: options,
+ },
+ true,
+ );
+ }
+
+ /**
+ * Set the token and endpoint required to connect to the voice servers.
+ * @param {string} token The voice token
+ * @param {string} endpoint The voice endpoint
+ * @private
+ * @returns {void}
+ */
+ setTokenAndEndpoint(token, endpoint) {
+ this.emit('debug', `Token "${token}" and endpoint "${endpoint}"`);
+ if (!endpoint) {
+ // Signifies awaiting endpoint stage
+ return;
+ }
+
+ if (!token) {
+ this.authenticateFailed('VOICE_TOKEN_ABSENT');
+ return;
+ }
+
+ endpoint = endpoint.match(/([^:]*)/)[0];
+ this.emit('debug', `Endpoint resolved as ${endpoint}`);
+
+ if (!endpoint) {
+ this.authenticateFailed('VOICE_INVALID_ENDPOINT');
+ return;
+ }
+
+ if (this.status === VoiceStatus.AUTHENTICATING) {
+ this.authentication.token = token;
+ this.authentication.endpoint = endpoint;
+ this.checkAuthenticated();
+ } else if (token !== this.authentication.token || endpoint !== this.authentication.endpoint) {
+ this.reconnect(token, endpoint);
+ }
+ }
+
+ /**
+ * Sets the Session ID for the connection.
+ * @param {string} sessionID The voice session ID
+ * @private
+ */
+ setSessionID(sessionID) {
+ this.emit('debug', `Setting sessionID ${sessionID} (stored as "${this.authentication.sessionID}")`);
+ if (!sessionID) {
+ this.authenticateFailed('VOICE_SESSION_ABSENT');
+ return;
+ }
+
+ if (this.status === VoiceStatus.AUTHENTICATING) {
+ this.authentication.sessionID = sessionID;
+ this.checkAuthenticated();
+ } else if (sessionID !== this.authentication.sessionID) {
+ this.authentication.sessionID = sessionID;
+ /**
+ * Emitted when a new session ID is received.
+ * @event VoiceConnection#newSession
+ * @private
+ */
+ this.emit('newSession', sessionID);
+ }
+ }
+
+ /**
+ * Checks whether the voice connection is authenticated.
+ * @private
+ */
+ checkAuthenticated() {
+ const { token, endpoint, sessionID } = this.authentication;
+ this.emit('debug', `Authenticated with sessionID ${sessionID}`);
+ if (token && endpoint && sessionID) {
+ this.status = VoiceStatus.CONNECTING;
+ /**
+ * Emitted when we successfully initiate a voice connection.
+ * @event VoiceConnection#authenticated
+ */
+ this.emit('authenticated');
+ this.connect();
+ }
+ }
+
+ /**
+ * Invoked when we fail to initiate a voice connection.
+ * @param {string} reason The reason for failure
+ * @private
+ */
+ authenticateFailed(reason) {
+ this.client.clearTimeout(this.connectTimeout);
+ this.emit('debug', `Authenticate failed - ${reason}`);
+ if (this.status === VoiceStatus.AUTHENTICATING) {
+ /**
+ * Emitted when we fail to initiate a voice connection.
+ * @event VoiceConnection#failed
+ * @param {Error} error The encountered error
+ */
+ this.emit('failed', new Error(reason));
+ } else {
+ /**
+ * Emitted whenever the connection encounters an error.
+ * @event VoiceConnection#error
+ * @param {Error} error The encountered error
+ */
+ this.emit('error', new Error(reason));
+ }
+ this.status = VoiceStatus.DISCONNECTED;
+ }
+
+ /**
+ * Move to a different voice channel in the same guild.
+ * @param {VoiceChannel} channel The channel to move to
+ * @private
+ */
+ updateChannel(channel) {
+ this.channel = channel;
+ this.sendVoiceStateUpdate();
+ }
+
+ /**
+ * Attempts to authenticate to the voice server.
+ * @private
+ */
+ authenticate() {
+ this.sendVoiceStateUpdate();
+ this.connectTimeout = this.client.setTimeout(() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15000);
+ }
+
+ /**
+ * Attempts to reconnect to the voice server (typically after a region change).
+ * @param {string} token The voice token
+ * @param {string} endpoint The voice endpoint
+ * @private
+ */
+ reconnect(token, endpoint) {
+ this.authentication.token = token;
+ this.authentication.endpoint = endpoint;
+ this.speaking = new Speaking().freeze();
+ this.status = VoiceStatus.RECONNECTING;
+ this.emit('debug', `Reconnecting to ${endpoint}`);
+ /**
+ * Emitted when the voice connection is reconnecting (typically after a region change).
+ * @event VoiceConnection#reconnecting
+ */
+ this.emit('reconnecting');
+ this.connect();
+ }
+
+ /**
+ * Disconnects the voice connection, causing a disconnect and closing event to be emitted.
+ */
+ disconnect() {
+ this.emit('closing');
+ this.emit('debug', 'disconnect() triggered');
+ this.client.clearTimeout(this.connectTimeout);
+ const conn = this.voiceManager.connections.get(this.channel.guild.id);
+ if (conn === this) this.voiceManager.connections.delete(this.channel.guild.id);
+ this.sendVoiceStateUpdate({
+ channel_id: null,
+ });
+ this._disconnect();
+ }
+
+ /**
+ * Internally disconnects (doesn't send disconnect packet).
+ * @private
+ */
+ _disconnect() {
+ this.cleanup();
+ this.status = VoiceStatus.DISCONNECTED;
+ /**
+ * Emitted when the voice connection disconnects.
+ * @event VoiceConnection#disconnect
+ */
+ this.emit('disconnect');
+ }
+
+ /**
+ * Cleans up after disconnect.
+ * @private
+ */
+ cleanup() {
+ this.player.destroy();
+ this.speaking = new Speaking().freeze();
+ const { ws, udp } = this.sockets;
+
+ this.emit('debug', 'Connection clean up');
+
+ if (ws) {
+ ws.removeAllListeners('error');
+ ws.removeAllListeners('ready');
+ ws.removeAllListeners('sessionDescription');
+ ws.removeAllListeners('speaking');
+ ws.shutdown();
+ }
+
+ if (udp) udp.removeAllListeners('error');
+
+ this.sockets.ws = null;
+ this.sockets.udp = null;
+ }
+
+ /**
+ * Connect the voice connection.
+ * @private
+ */
+ connect() {
+ this.emit('debug', `Connect triggered`);
+ if (this.status !== VoiceStatus.RECONNECTING) {
+ if (this.sockets.ws) throw new Error('WS_CONNECTION_EXISTS');
+ if (this.sockets.udp) throw new Error('UDP_CONNECTION_EXISTS');
+ }
+
+ if (this.sockets.ws) this.sockets.ws.shutdown();
+ if (this.sockets.udp) this.sockets.udp.shutdown();
+
+ this.sockets.ws = new VoiceWebSocket(this);
+ this.sockets.udp = new VoiceUDP(this);
+
+ const { ws, udp } = this.sockets;
+
+ ws.on('debug', msg => this.emit('debug', msg));
+ udp.on('debug', msg => this.emit('debug', msg));
+ ws.on('error', err => this.emit('error', err));
+ udp.on('error', err => this.emit('error', err));
+ ws.on('ready', this.onReady.bind(this));
+ ws.on('sessionDescription', this.onSessionDescription.bind(this));
+ ws.on('startSpeaking', this.onStartSpeaking.bind(this));
+
+ this.sockets.ws.connect();
+ }
+
+ /**
+ * Invoked when the voice websocket is ready.
+ * @param {Object} data The received data
+ * @private
+ */
+ onReady(data) {
+ Object.assign(this.authentication, data);
+ for (let mode of data.modes) {
+ if (SUPPORTED_MODES.includes(mode)) {
+ this.authentication.mode = mode;
+ this.emit('debug', `Selecting the ${mode} mode`);
+ break;
+ }
+ }
+ this.sockets.udp.createUDPSocket(data.ip);
+ }
+
+ /**
+ * Invoked when a session description is received.
+ * @param {Object} data The received data
+ * @private
+ */
+ onSessionDescription(data) {
+ Object.assign(this.authentication, data);
+ this.status = VoiceStatus.CONNECTED;
+ const ready = () => {
+ this.client.clearTimeout(this.connectTimeout);
+ this.emit('debug', `Ready with authentication details: ${JSON.stringify(this.authentication)}`);
+ /**
+ * Emitted once the connection is ready, when a promise to join a voice channel resolves,
+ * the connection will already be ready.
+ * @event VoiceConnection#ready
+ */
+ this.emit('ready');
+ };
+ if (this.dispatcher) {
+ ready();
+ } else {
+ // This serves to provide support for voice receive, sending audio is required to receive it.
+ const dispatcher = this.play(new SingleSilence(), { type: 'opus', volume: false });
+ dispatcher.once('finish', ready);
+ }
+ }
+
+ onStartSpeaking({ user_id, ssrc, speaking }) {
+ this.ssrcMap.set(+ssrc, { userID: user_id, speaking: speaking });
+ }
+
+ /**
+ * Invoked when a speaking event is received.
+ * @param {Object} data The received data
+ * @private
+ */
+ onSpeaking({ user_id, speaking }) {
+ speaking = new Speaking(speaking).freeze();
+ const guild = this.channel.guild;
+ const user = this.client.users.cache.get(user_id);
+ const old = this._speaking.get(user_id);
+ this._speaking.set(user_id, speaking);
+ /**
+ * Emitted whenever a user changes speaking state.
+ * @event VoiceConnection#speaking
+ * @param {User} user The user that has changed speaking state
+ * @param {Readonly<Speaking>} speaking The speaking state of the user
+ */
+ if (this.status === VoiceStatus.CONNECTED) {
+ this.emit('speaking', user, speaking);
+ if (!speaking.has(Speaking.FLAGS.SPEAKING)) {
+ this.receiver.packets._stoppedSpeaking(user_id);
+ }
+ }
+
+ if (guild && user && !speaking.equals(old)) {
+ const member = guild.member(user);
+ if (member) {
+ /**
+ * Emitted once a guild member changes speaking state.
+ * @event Client#guildMemberSpeaking
+ * @param {GuildMember} member The member that started/stopped speaking
+ * @param {Readonly<Speaking>} speaking The speaking state of the member
+ */
+ this.client.emit(Events.GUILD_MEMBER_SPEAKING, member, speaking);
+ }
+ }
+ }
+
+ play() {} // eslint-disable-line no-empty-function
+}
+
+PlayInterface.applyToClass(VoiceConnection);
+
+module.exports = VoiceConnection;
diff --git a/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js
new file mode 100644
index 0000000..ae8d412
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/dispatcher/BroadcastDispatcher.js
@@ -0,0 +1,46 @@
+'use strict';
+
+const StreamDispatcher = require('./StreamDispatcher');
+
+/**
+ * The class that sends voice packet data to the voice connection.
+ * @implements {VolumeInterface}
+ * @extends {StreamDispatcher}
+ */
+class BroadcastDispatcher extends StreamDispatcher {
+ constructor(player, options, streams) {
+ super(player, options, streams);
+ this.broadcast = player.broadcast;
+ }
+
+ _write(chunk, enc, done) {
+ if (!this.startTime) this.startTime = Date.now();
+ for (const dispatcher of this.broadcast.subscribers) {
+ dispatcher._write(chunk, enc);
+ }
+ this._step(done);
+ }
+
+ _destroy(err, cb) {
+ if (this.player.dispatcher === this) this.player.dispatcher = null;
+ const { streams } = this;
+ if (streams.opus) streams.opus.unpipe(this);
+ if (streams.ffmpeg) streams.ffmpeg.destroy();
+ super._destroy(err, cb);
+ }
+
+ /**
+ * Set the bitrate of the current Opus encoder if using a compatible Opus stream.
+ * @param {number} value New bitrate, in kbps
+ * If set to 'auto', 48kbps will be used
+ * @returns {boolean} true if the bitrate has been successfully changed.
+ */
+ setBitrate(value) {
+ if (!value || !this.streams.opus || !this.streams.opus.setBitrate) return false;
+ const bitrate = value === 'auto' ? 48 : value;
+ this.streams.opus.setBitrate(bitrate * 1000);
+ return true;
+ }
+}
+
+module.exports = BroadcastDispatcher;
diff --git a/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js b/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js
new file mode 100644
index 0000000..62c46d3
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/dispatcher/StreamDispatcher.js
@@ -0,0 +1,354 @@
+'use strict';
+
+const { Writable } = require('stream');
+const secretbox = require('../util/Secretbox');
+const Silence = require('../util/Silence');
+const VolumeInterface = require('../util/VolumeInterface');
+
+const FRAME_LENGTH = 20;
+const CHANNELS = 2;
+const TIMESTAMP_INC = (48000 / 100) * CHANNELS;
+
+const MAX_NONCE_SIZE = 2 ** 32 - 1;
+const nonce = Buffer.alloc(24);
+
+/**
+ * @external WritableStream
+ * @see {@link https://nodejs.org/api/stream.html#stream_class_stream_writable}
+ */
+
+/**
+ * The class that sends voice packet data to the voice connection.
+ * ```js
+ * // Obtained using:
+ * voiceChannel.join().then(connection => {
+ * // You can play a file or a stream here:
+ * const dispatcher = connection.play('/home/hydrabolt/audio.mp3');
+ * });
+ * ```
+ * @implements {VolumeInterface}
+ * @extends {WritableStream}
+ */
+class StreamDispatcher extends Writable {
+ constructor(player, { seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {}, streams) {
+ const streamOptions = { seek, volume, fec, plp, bitrate, highWaterMark };
+ super(streamOptions);
+ /**
+ * The Audio Player that controls this dispatcher
+ * @type {AudioPlayer}
+ */
+ this.player = player;
+ this.streamOptions = streamOptions;
+ this.streams = streams;
+ this.streams.silence = new Silence();
+
+ this._nonce = 0;
+ this._nonceBuffer = Buffer.alloc(24);
+
+ /**
+ * The time that the stream was paused at (null if not paused)
+ * @type {?number}
+ */
+ this.pausedSince = null;
+ this._writeCallback = null;
+
+ /**
+ * The broadcast controlling this dispatcher, if any
+ * @type {?VoiceBroadcast}
+ */
+ this.broadcast = this.streams.broadcast;
+
+ this._pausedTime = 0;
+ this._silentPausedTime = 0;
+ this.count = 0;
+
+ this.on('finish', () => {
+ this._cleanup();
+ this._setSpeaking(0);
+ });
+
+ this.setVolume(volume);
+ this.setBitrate(bitrate);
+ if (typeof fec !== 'undefined') this.setFEC(fec);
+ if (typeof plp !== 'undefined') this.setPLP(plp);
+
+ const streamError = (type, err) => {
+ /**
+ * Emitted when the dispatcher encounters an error.
+ * @event StreamDispatcher#error
+ */
+ if (type && err) {
+ err.message = `${type} stream: ${err.message}`;
+ this.emit(this.player.dispatcher === this ? 'error' : 'debug', err);
+ }
+ this.destroy();
+ };
+
+ this.on('error', () => streamError());
+ if (this.streams.input) this.streams.input.on('error', err => streamError('input', err));
+ if (this.streams.ffmpeg) this.streams.ffmpeg.on('error', err => streamError('ffmpeg', err));
+ if (this.streams.opus) this.streams.opus.on('error', err => streamError('opus', err));
+ if (this.streams.volume) this.streams.volume.on('error', err => streamError('volume', err));
+ }
+
+ get _sdata() {
+ return this.player.streamingData;
+ }
+
+ _write(chunk, enc, done) {
+ if (!this.startTime) {
+ /**
+ * Emitted once the stream has started to play.
+ * @event StreamDispatcher#start
+ */
+ this.emit('start');
+ this.startTime = Date.now();
+ }
+ this._playChunk(chunk);
+ this._step(done);
+ }
+
+ _destroy(err, cb) {
+ this._cleanup();
+ super._destroy(err, cb);
+ }
+
+ _cleanup() {
+ if (this.player.dispatcher === this) this.player.dispatcher = null;
+ const { streams } = this;
+ if (streams.broadcast) streams.broadcast.delete(this);
+ if (streams.opus) streams.opus.destroy();
+ if (streams.ffmpeg) streams.ffmpeg.destroy();
+ }
+
+ /**
+ * Pauses playback
+ * @param {boolean} [silence=false] Whether to play silence while paused to prevent audio glitches
+ */
+ pause(silence = false) {
+ if (this.paused) return;
+ if (this.streams.opus) this.streams.opus.unpipe(this);
+ if (silence) {
+ this.streams.silence.pipe(this);
+ this._silence = true;
+ } else {
+ this._setSpeaking(0);
+ }
+ this.pausedSince = Date.now();
+ }
+
+ /**
+ * Whether or not playback is paused
+ * @type {boolean}
+ * @readonly
+ */
+ get paused() {
+ return Boolean(this.pausedSince);
+ }
+
+ /**
+ * Total time that this dispatcher has been paused in milliseconds
+ * @type {number}
+ * @readonly
+ */
+ get pausedTime() {
+ return this._silentPausedTime + this._pausedTime + (this.paused ? Date.now() - this.pausedSince : 0);
+ }
+
+ /**
+ * Resumes playback
+ */
+ resume() {
+ if (!this.pausedSince) return;
+ this.streams.silence.unpipe(this);
+ if (this.streams.opus) this.streams.opus.pipe(this);
+ if (this._silence) {
+ this._silentPausedTime += Date.now() - this.pausedSince;
+ this._silence = false;
+ } else {
+ this._pausedTime += Date.now() - this.pausedSince;
+ }
+ this.pausedSince = null;
+ if (typeof this._writeCallback === 'function') this._writeCallback();
+ }
+
+ /**
+ * The time (in milliseconds) that the dispatcher has actually been playing audio for
+ * @type {number}
+ * @readonly
+ */
+ get streamTime() {
+ return this.count * FRAME_LENGTH;
+ }
+
+ /**
+ * The time (in milliseconds) that the dispatcher has been playing audio for, taking into account skips and pauses
+ * @type {number}
+ * @readonly
+ */
+ get totalStreamTime() {
+ return Date.now() - this.startTime;
+ }
+
+ /**
+ * Set the bitrate of the current Opus encoder if using a compatible Opus stream.
+ * @param {number} value New bitrate, in kbps
+ * If set to 'auto', the voice channel's bitrate will be used
+ * @returns {boolean} true if the bitrate has been successfully changed.
+ */
+ setBitrate(value) {
+ if (!value || !this.bitrateEditable) return false;
+ const bitrate = value === 'auto' ? this.player.voiceConnection.channel.bitrate : value;
+ this.streams.opus.setBitrate(bitrate * 1000);
+ return true;
+ }
+
+ /**
+ * Sets the expected packet loss percentage if using a compatible Opus stream.
+ * @param {number} value between 0 and 1
+ * @returns {boolean} Returns true if it was successfully set.
+ */
+ setPLP(value) {
+ if (!this.bitrateEditable) return false;
+ this.streams.opus.setPLP(value);
+ return true;
+ }
+
+ /**
+ * Enables or disables forward error correction if using a compatible Opus stream.
+ * @param {boolean} enabled true to enable
+ * @returns {boolean} Returns true if it was successfully set.
+ */
+ setFEC(enabled) {
+ if (!this.bitrateEditable) return false;
+ this.streams.opus.setFEC(enabled);
+ return true;
+ }
+
+ _step(done) {
+ this._writeCallback = () => {
+ this._writeCallback = null;
+ done();
+ };
+ if (!this.streams.broadcast) {
+ const next = FRAME_LENGTH + this.count * FRAME_LENGTH - (Date.now() - this.startTime - this._pausedTime);
+ setTimeout(() => {
+ if ((!this.pausedSince || this._silence) && this._writeCallback) this._writeCallback();
+ }, next);
+ }
+ this._sdata.sequence++;
+ this._sdata.timestamp += TIMESTAMP_INC;
+ if (this._sdata.sequence >= 2 ** 16) this._sdata.sequence = 0;
+ if (this._sdata.timestamp >= 2 ** 32) this._sdata.timestamp = 0;
+ this.count++;
+ }
+
+ _final(callback) {
+ this._writeCallback = null;
+ callback();
+ }
+
+ _playChunk(chunk) {
+ if (this.player.dispatcher !== this || !this.player.voiceConnection.authentication.secret_key) return;
+ this._sendPacket(this._createPacket(this._sdata.sequence, this._sdata.timestamp, chunk));
+ }
+
+ _encrypt(buffer) {
+ const { secret_key, mode } = this.player.voiceConnection.authentication;
+ if (mode === 'xsalsa20_poly1305_lite') {
+ this._nonce++;
+ if (this._nonce > MAX_NONCE_SIZE) this._nonce = 0;
+ this._nonceBuffer.writeUInt32BE(this._nonce, 0);
+ return [secretbox.methods.close(buffer, this._nonceBuffer, secret_key), this._nonceBuffer.slice(0, 4)];
+ } else if (mode === 'xsalsa20_poly1305_suffix') {
+ const random = secretbox.methods.random(24);
+ return [secretbox.methods.close(buffer, random, secret_key), random];
+ } else {
+ return [secretbox.methods.close(buffer, nonce, secret_key)];
+ }
+ }
+
+ _createPacket(sequence, timestamp, buffer) {
+ const packetBuffer = Buffer.alloc(12);
+ packetBuffer[0] = 0x80;
+ packetBuffer[1] = 0x78;
+
+ packetBuffer.writeUIntBE(sequence, 2, 2);
+ packetBuffer.writeUIntBE(timestamp, 4, 4);
+ packetBuffer.writeUIntBE(this.player.voiceConnection.authentication.ssrc, 8, 4);
+
+ packetBuffer.copy(nonce, 0, 0, 12);
+ return Buffer.concat([packetBuffer, ...this._encrypt(buffer)]);
+ }
+
+ _sendPacket(packet) {
+ /**
+ * Emitted whenever the dispatcher has debug information.
+ * @event StreamDispatcher#debug
+ * @param {string} info The debug info
+ */
+ this._setSpeaking(1);
+ if (!this.player.voiceConnection.sockets.udp) {
+ this.emit('debug', 'Failed to send a packet - no UDP socket');
+ return;
+ }
+ this.player.voiceConnection.sockets.udp.send(packet).catch(e => {
+ this._setSpeaking(0);
+ this.emit('debug', `Failed to send a packet - ${e}`);
+ });
+ }
+
+ _setSpeaking(value) {
+ if (typeof this.player.voiceConnection !== 'undefined') {
+ this.player.voiceConnection.setSpeaking(value);
+ }
+ /**
+ * Emitted when the dispatcher starts/stops speaking.
+ * @event StreamDispatcher#speaking
+ * @param {boolean} value Whether or not the dispatcher is speaking
+ */
+ this.emit('speaking', value);
+ }
+
+ get volumeEditable() {
+ return Boolean(this.streams.volume);
+ }
+
+ /**
+ * Whether or not the Opus bitrate of this stream is editable
+ * @type {boolean}
+ * @readonly
+ */
+ get bitrateEditable() {
+ return this.streams.opus && this.streams.opus.setBitrate;
+ }
+
+ // Volume
+ get volume() {
+ return this.streams.volume ? this.streams.volume.volume : 1;
+ }
+
+ setVolume(value) {
+ if (!this.streams.volume) return false;
+ /**
+ * Emitted when the volume of this dispatcher changes.
+ * @event StreamDispatcher#volumeChange
+ * @param {number} oldVolume The old volume of this dispatcher
+ * @param {number} newVolume The new volume of this dispatcher
+ */
+ this.emit('volumeChange', this.volume, value);
+ this.streams.volume.setVolume(value);
+ return true;
+ }
+
+ // Volume stubs for docs
+ /* eslint-disable no-empty-function*/
+ get volumeDecibels() {}
+ get volumeLogarithmic() {}
+ setVolumeDecibels() {}
+ setVolumeLogarithmic() {}
+}
+
+VolumeInterface.applyToClass(StreamDispatcher);
+
+module.exports = StreamDispatcher;
diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js b/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js
new file mode 100644
index 0000000..b86428a
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/networking/VoiceUDPClient.js
@@ -0,0 +1,154 @@
+'use strict';
+
+const udp = require('dgram');
+const EventEmitter = require('events');
+const { Error } = require('../../../errors');
+const { VoiceOPCodes } = require('../../../util/Constants');
+
+/**
+ * Represents a UDP client for a Voice Connection.
+ * @extends {EventEmitter}
+ * @private
+ */
+class VoiceConnectionUDPClient extends EventEmitter {
+ constructor(voiceConnection) {
+ super();
+
+ /**
+ * The voice connection that this UDP client serves
+ * @type {VoiceConnection}
+ */
+ this.voiceConnection = voiceConnection;
+
+ /**
+ * The UDP socket
+ * @type {?Socket}
+ */
+ this.socket = null;
+
+ /**
+ * The address of the Discord voice server
+ * @type {?string}
+ */
+ this.discordAddress = null;
+
+ /**
+ * The local IP address
+ * @type {?string}
+ */
+ this.localAddress = null;
+
+ /**
+ * The local port
+ * @type {?string}
+ */
+ this.localPort = null;
+
+ this.voiceConnection.on('closing', this.shutdown.bind(this));
+ }
+
+ shutdown() {
+ this.emit('debug', `[UDP] shutdown requested`);
+ if (this.socket) {
+ this.socket.removeAllListeners('message');
+ try {
+ this.socket.close();
+ } finally {
+ this.socket = null;
+ }
+ }
+ }
+
+ /**
+ * The port of the Discord voice server
+ * @type {number}
+ * @readonly
+ */
+ get discordPort() {
+ return this.voiceConnection.authentication.port;
+ }
+
+ /**
+ * Send a packet to the UDP client.
+ * @param {Object} packet The packet to send
+ * @returns {Promise<Object>}
+ */
+ send(packet) {
+ return new Promise((resolve, reject) => {
+ if (!this.socket) throw new Error('UDP_SEND_FAIL');
+ if (!this.discordAddress || !this.discordPort) throw new Error('UDP_ADDRESS_MALFORMED');
+ this.socket.send(packet, 0, packet.length, this.discordPort, this.discordAddress, error => {
+ if (error) {
+ this.emit('debug', `[UDP] >> ERROR: ${error}`);
+ reject(error);
+ } else {
+ resolve(packet);
+ }
+ });
+ });
+ }
+
+ async createUDPSocket(address) {
+ this.discordAddress = address;
+ const socket = (this.socket = udp.createSocket('udp4'));
+ socket.on('error', e => {
+ this.emit('debug', `[UDP] Error: ${e}`);
+ this.emit('error', e);
+ });
+ socket.on('close', () => {
+ this.emit('debug', '[UDP] socket closed');
+ });
+ this.emit('debug', `[UDP] created socket`);
+ socket.once('message', message => {
+ this.emit('debug', `[UDP] message: [${[...message]}] (${message})`);
+ // Stop if the sockets have been deleted because the connection has been closed already
+ if (!this.voiceConnection.sockets.ws) return;
+
+ const packet = parseLocalPacket(message);
+ if (packet.error) {
+ this.emit('debug', `[UDP] ERROR: ${packet.error}`);
+ this.emit('error', packet.error);
+ return;
+ }
+
+ this.localAddress = packet.address;
+ this.localPort = packet.port;
+
+ this.voiceConnection.sockets.ws.sendPacket({
+ op: VoiceOPCodes.SELECT_PROTOCOL,
+ d: {
+ protocol: 'udp',
+ data: {
+ address: packet.address,
+ port: packet.port,
+ mode: this.voiceConnection.authentication.mode,
+ },
+ },
+ });
+
+ this.emit('debug', `[UDP] << ${JSON.stringify(packet)}`);
+
+ socket.on('message', buffer => this.voiceConnection.receiver.packets.push(buffer));
+ });
+
+ const blankMessage = Buffer.alloc(70);
+ blankMessage.writeUIntBE(this.voiceConnection.authentication.ssrc, 0, 4);
+ this.emit('debug', `Sending IP discovery packet: [${[...blankMessage]}]`);
+ await this.send(blankMessage);
+ this.emit('debug', `Successfully sent IP discovery packet`);
+ }
+}
+
+function parseLocalPacket(message) {
+ try {
+ const packet = Buffer.from(message);
+ let address = '';
+ for (let i = 4; i < packet.indexOf(0, i); i++) address += String.fromCharCode(packet[i]);
+ const port = parseInt(packet.readUIntLE(packet.length - 2, 2).toString(10), 10);
+ return { address, port };
+ } catch (error) {
+ return { error };
+ }
+}
+
+module.exports = VoiceConnectionUDPClient;
diff --git a/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js b/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js
new file mode 100644
index 0000000..efc97af
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/networking/VoiceWebSocket.js
@@ -0,0 +1,264 @@
+'use strict';
+
+const EventEmitter = require('events');
+const WebSocket = require('../../../WebSocket');
+const { Error } = require('../../../errors');
+const { OPCodes, VoiceOPCodes } = require('../../../util/Constants');
+
+/**
+ * Represents a Voice Connection's WebSocket.
+ * @extends {EventEmitter}
+ * @private
+ */
+class VoiceWebSocket extends EventEmitter {
+ constructor(connection) {
+ super();
+ /**
+ * The Voice Connection that this WebSocket serves
+ * @type {VoiceConnection}
+ */
+ this.connection = connection;
+
+ /**
+ * How many connection attempts have been made
+ * @type {number}
+ */
+ this.attempts = 0;
+
+ this.dead = false;
+ this.connection.on('closing', this.shutdown.bind(this));
+ }
+
+ /**
+ * The client of this voice WebSocket
+ * @type {Client}
+ * @readonly
+ */
+ get client() {
+ return this.connection.client;
+ }
+
+ shutdown() {
+ this.emit('debug', `[WS] shutdown requested`);
+ this.dead = true;
+ this.reset();
+ }
+
+ /**
+ * Resets the current WebSocket.
+ */
+ reset() {
+ this.emit('debug', `[WS] reset requested`);
+ if (this.ws) {
+ if (this.ws.readyState !== WebSocket.CLOSED) this.ws.close();
+ this.ws = null;
+ }
+ this.clearHeartbeat();
+ }
+
+ /**
+ * Starts connecting to the Voice WebSocket Server.
+ */
+ connect() {
+ this.emit('debug', `[WS] connect requested`);
+ if (this.dead) return;
+ if (this.ws) this.reset();
+ if (this.attempts >= 5) {
+ this.emit('debug', new Error('VOICE_CONNECTION_ATTEMPTS_EXCEEDED', this.attempts));
+ return;
+ }
+
+ this.attempts++;
+
+ /**
+ * The actual WebSocket used to connect to the Voice WebSocket Server.
+ * @type {WebSocket}
+ */
+ this.ws = WebSocket.create(`wss://${this.connection.authentication.endpoint}/`, { v: 4 });
+ this.emit('debug', `[WS] connecting, ${this.attempts} attempts, ${this.ws.url}`);
+ this.ws.onopen = this.onOpen.bind(this);
+ this.ws.onmessage = this.onMessage.bind(this);
+ this.ws.onclose = this.onClose.bind(this);
+ this.ws.onerror = this.onError.bind(this);
+ }
+
+ /**
+ * Sends data to the WebSocket if it is open.
+ * @param {string} data The data to send to the WebSocket
+ * @returns {Promise<string>}
+ */
+ send(data) {
+ this.emit('debug', `[WS] >> ${data}`);
+ return new Promise((resolve, reject) => {
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error('WS_NOT_OPEN', data);
+ this.ws.send(data, null, error => {
+ if (error) reject(error);
+ else resolve(data);
+ });
+ });
+ }
+
+ /**
+ * JSON.stringify's a packet and then sends it to the WebSocket Server.
+ * @param {Object} packet The packet to send
+ * @returns {Promise<string>}
+ */
+ sendPacket(packet) {
+ try {
+ packet = JSON.stringify(packet);
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ return this.send(packet);
+ }
+
+ /**
+ * Called whenever the WebSocket opens.
+ */
+ onOpen() {
+ this.emit('debug', `[WS] opened at gateway ${this.connection.authentication.endpoint}`);
+ this.sendPacket({
+ op: OPCodes.DISPATCH,
+ d: {
+ server_id: this.connection.channel.guild.id,
+ user_id: this.client.user.id,
+ token: this.connection.authentication.token,
+ session_id: this.connection.authentication.sessionID,
+ },
+ }).catch(() => {
+ this.emit('error', new Error('VOICE_JOIN_SOCKET_CLOSED'));
+ });
+ }
+
+ /**
+ * Called whenever a message is received from the WebSocket.
+ * @param {MessageEvent} event The message event that was received
+ * @returns {void}
+ */
+ onMessage(event) {
+ try {
+ return this.onPacket(WebSocket.unpack(event.data, 'json'));
+ } catch (error) {
+ return this.onError(error);
+ }
+ }
+
+ /**
+ * Called whenever the connection to the WebSocket server is lost.
+ */
+ onClose() {
+ this.emit('debug', `[WS] closed`);
+ if (!this.dead) this.client.setTimeout(this.connect.bind(this), this.attempts * 1000);
+ }
+
+ /**
+ * Called whenever an error occurs with the WebSocket.
+ * @param {Error} error The error that occurred
+ */
+ onError(error) {
+ this.emit('debug', `[WS] Error: ${error}`);
+ this.emit('error', error);
+ }
+
+ /**
+ * Called whenever a valid packet is received from the WebSocket.
+ * @param {Object} packet The received packet
+ */
+ onPacket(packet) {
+ this.emit('debug', `[WS] << ${JSON.stringify(packet)}`);
+ switch (packet.op) {
+ case VoiceOPCodes.HELLO:
+ this.setHeartbeat(packet.d.heartbeat_interval);
+ break;
+ case VoiceOPCodes.READY:
+ /**
+ * Emitted once the voice WebSocket receives the ready packet.
+ * @param {Object} packet The received packet
+ * @event VoiceWebSocket#ready
+ */
+ this.emit('ready', packet.d);
+ break;
+ /* eslint-disable no-case-declarations */
+ case VoiceOPCodes.SESSION_DESCRIPTION:
+ packet.d.secret_key = new Uint8Array(packet.d.secret_key);
+ /**
+ * Emitted once the Voice Websocket receives a description of this voice session.
+ * @param {Object} packet The received packet
+ * @event VoiceWebSocket#sessionDescription
+ */
+ this.emit('sessionDescription', packet.d);
+ break;
+ case VoiceOPCodes.CLIENT_CONNECT:
+ this.connection.ssrcMap.set(+packet.d.audio_ssrc, packet.d.user_id);
+ break;
+ case VoiceOPCodes.CLIENT_DISCONNECT:
+ const streamInfo = this.connection.receiver && this.connection.receiver.packets.streams.get(packet.d.user_id);
+ if (streamInfo) {
+ this.connection.receiver.packets.streams.delete(packet.d.user_id);
+ streamInfo.stream.push(null);
+ }
+ break;
+ case VoiceOPCodes.SPEAKING:
+ /**
+ * Emitted whenever a speaking packet is received.
+ * @param {Object} data
+ * @event VoiceWebSocket#startSpeaking
+ */
+ this.emit('startSpeaking', packet.d);
+ break;
+ default:
+ /**
+ * Emitted when an unhandled packet is received.
+ * @param {Object} packet
+ * @event VoiceWebSocket#unknownPacket
+ */
+ this.emit('unknownPacket', packet);
+ break;
+ }
+ }
+
+ /**
+ * Sets an interval at which to send a heartbeat packet to the WebSocket.
+ * @param {number} interval The interval at which to send a heartbeat packet
+ */
+ setHeartbeat(interval) {
+ if (!interval || isNaN(interval)) {
+ this.onError(new Error('VOICE_INVALID_HEARTBEAT'));
+ return;
+ }
+ if (this.heartbeatInterval) {
+ /**
+ * Emitted whenever the voice WebSocket encounters a non-fatal error.
+ * @param {string} warn The warning
+ * @event VoiceWebSocket#warn
+ */
+ this.emit('warn', 'A voice heartbeat interval is being overwritten');
+ this.client.clearInterval(this.heartbeatInterval);
+ }
+ this.heartbeatInterval = this.client.setInterval(this.sendHeartbeat.bind(this), interval);
+ }
+
+ /**
+ * Clears a heartbeat interval, if one exists.
+ */
+ clearHeartbeat() {
+ if (!this.heartbeatInterval) {
+ this.emit('warn', 'Tried to clear a heartbeat interval that does not exist');
+ return;
+ }
+ this.client.clearInterval(this.heartbeatInterval);
+ this.heartbeatInterval = null;
+ }
+
+ /**
+ * Sends a heartbeat packet.
+ */
+ sendHeartbeat() {
+ this.sendPacket({ op: VoiceOPCodes.HEARTBEAT, d: Math.floor(Math.random() * 10e10) }).catch(() => {
+ this.emit('warn', 'Tried to send heartbeat, but connection is not open');
+ this.clearHeartbeat();
+ });
+ }
+}
+
+module.exports = VoiceWebSocket;
diff --git a/node_modules/discord.js/src/client/voice/player/AudioPlayer.js b/node_modules/discord.js/src/client/voice/player/AudioPlayer.js
new file mode 100644
index 0000000..6f719a7
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/player/AudioPlayer.js
@@ -0,0 +1,27 @@
+'use strict';
+
+const BasePlayer = require('./BasePlayer');
+
+/**
+ * An Audio Player for a Voice Connection.
+ * @private
+ * @extends {BasePlayer}
+ */
+class AudioPlayer extends BasePlayer {
+ constructor(voiceConnection) {
+ super();
+ /**
+ * The voice connection that the player serves
+ * @type {VoiceConnection}
+ */
+ this.voiceConnection = voiceConnection;
+ }
+
+ playBroadcast(broadcast, options) {
+ const dispatcher = this.createDispatcher(options, { broadcast });
+ broadcast.add(dispatcher);
+ return dispatcher;
+ }
+}
+
+module.exports = AudioPlayer;
diff --git a/node_modules/discord.js/src/client/voice/player/BasePlayer.js b/node_modules/discord.js/src/client/voice/player/BasePlayer.js
new file mode 100644
index 0000000..b968f82
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/player/BasePlayer.js
@@ -0,0 +1,92 @@
+'use strict';
+
+const EventEmitter = require('events');
+const { Readable: ReadableStream } = require('stream');
+const prism = require('prism-media');
+const StreamDispatcher = require('../dispatcher/StreamDispatcher');
+
+const FFMPEG_ARGUMENTS = ['-analyzeduration', '0', '-loglevel', '0', '-f', 's16le', '-ar', '48000', '-ac', '2'];
+
+/**
+ * An Audio Player for a Voice Connection.
+ * @private
+ * @extends {EventEmitter}
+ */
+class BasePlayer extends EventEmitter {
+ constructor() {
+ super();
+
+ this.dispatcher = null;
+
+ this.streamingData = {
+ channels: 2,
+ sequence: 0,
+ timestamp: 0,
+ };
+ }
+
+ destroy() {
+ this.destroyDispatcher();
+ }
+
+ destroyDispatcher() {
+ if (this.dispatcher) {
+ this.dispatcher.destroy();
+ this.dispatcher = null;
+ }
+ }
+
+ playUnknown(input, options) {
+ this.destroyDispatcher();
+
+ const isStream = input instanceof ReadableStream;
+
+ const args = isStream ? FFMPEG_ARGUMENTS.slice() : ['-i', input, ...FFMPEG_ARGUMENTS];
+ if (options.seek) args.unshift('-ss', String(options.seek));
+
+ const ffmpeg = new prism.FFmpeg({ args });
+ const streams = { ffmpeg };
+ if (isStream) {
+ streams.input = input;
+ input.pipe(ffmpeg);
+ }
+ return this.playPCMStream(ffmpeg, options, streams);
+ }
+
+ playPCMStream(stream, options, streams = {}) {
+ this.destroyDispatcher();
+ const opus = (streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 }));
+ if (options && options.volume === false) {
+ stream.pipe(opus);
+ return this.playOpusStream(opus, options, streams);
+ }
+ streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 });
+ stream.pipe(streams.volume).pipe(opus);
+ return this.playOpusStream(opus, options, streams);
+ }
+
+ playOpusStream(stream, options, streams = {}) {
+ this.destroyDispatcher();
+ streams.opus = stream;
+ if (options.volume !== false && !streams.input) {
+ streams.input = stream;
+ const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 });
+ streams.volume = new prism.VolumeTransformer({ type: 's16le', volume: options ? options.volume : 1 });
+ streams.opus = stream
+ .pipe(decoder)
+ .pipe(streams.volume)
+ .pipe(new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 }));
+ }
+ const dispatcher = this.createDispatcher(options, streams);
+ streams.opus.pipe(dispatcher);
+ return dispatcher;
+ }
+
+ createDispatcher(options, streams, broadcast) {
+ this.destroyDispatcher();
+ const dispatcher = (this.dispatcher = new StreamDispatcher(this, options, streams, broadcast));
+ return dispatcher;
+ }
+}
+
+module.exports = BasePlayer;
diff --git a/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js b/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js
new file mode 100644
index 0000000..05197a4
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/player/BroadcastAudioPlayer.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const BasePlayer = require('./BasePlayer');
+const BroadcastDispatcher = require('../dispatcher/BroadcastDispatcher');
+
+/**
+ * An Audio Player for a Voice Connection.
+ * @private
+ * @extends {BasePlayer}
+ */
+class AudioPlayer extends BasePlayer {
+ constructor(broadcast) {
+ super();
+ /**
+ * The broadcast that the player serves
+ * @type {VoiceBroadcast}
+ */
+ this.broadcast = broadcast;
+ }
+
+ createDispatcher(options, streams) {
+ this.destroyDispatcher();
+ const dispatcher = (this.dispatcher = new BroadcastDispatcher(this, options, streams));
+ return dispatcher;
+ }
+}
+
+module.exports = AudioPlayer;
diff --git a/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js b/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js
new file mode 100644
index 0000000..c441c5e
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/receiver/PacketHandler.js
@@ -0,0 +1,116 @@
+'use strict';
+
+const EventEmitter = require('events');
+const secretbox = require('../util/Secretbox');
+
+// The delay between packets when a user is considered to have stopped speaking
+// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200
+const DISCORD_SPEAKING_DELAY = 250;
+
+class Readable extends require('stream').Readable {
+ _read() {} // eslint-disable-line no-empty-function
+}
+
+class PacketHandler extends EventEmitter {
+ constructor(receiver) {
+ super();
+ this.nonce = Buffer.alloc(24);
+ this.receiver = receiver;
+ this.streams = new Map();
+ this.speakingTimeouts = new Map();
+ }
+
+ get connection() {
+ return this.receiver.connection;
+ }
+
+ _stoppedSpeaking(userID) {
+ const streamInfo = this.streams.get(userID);
+ if (streamInfo && streamInfo.end === 'silence') {
+ this.streams.delete(userID);
+ streamInfo.stream.push(null);
+ }
+ }
+
+ makeStream(user, end) {
+ if (this.streams.has(user)) return this.streams.get(user).stream;
+ const stream = new Readable();
+ stream.on('end', () => this.streams.delete(user));
+ this.streams.set(user, { stream, end });
+ return stream;
+ }
+
+ parseBuffer(buffer) {
+ const { secret_key, mode } = this.receiver.connection.authentication;
+
+ // Choose correct nonce depending on encryption
+ let end;
+ if (mode === 'xsalsa20_poly1305_lite') {
+ buffer.copy(this.nonce, 0, buffer.length - 4);
+ end = buffer.length - 4;
+ } else if (mode === 'xsalsa20_poly1305_suffix') {
+ buffer.copy(this.nonce, 0, buffer.length - 24);
+ end = buffer.length - 24;
+ } else {
+ buffer.copy(this.nonce, 0, 0, 12);
+ }
+
+ // Open packet
+ let packet = secretbox.methods.open(buffer.slice(12, end), this.nonce, secret_key);
+ if (!packet) return new Error('Failed to decrypt voice packet');
+ packet = Buffer.from(packet);
+
+ // Strip RTP Header Extensions (one-byte only)
+ if (packet[0] === 0xbe && packet[1] === 0xde && packet.length > 4) {
+ const headerExtensionLength = packet.readUInt16BE(2);
+ let offset = 4;
+ for (let i = 0; i < headerExtensionLength; i++) {
+ const byte = packet[offset];
+ offset++;
+ if (byte === 0) continue;
+ offset += 1 + (0b1111 & (byte >> 4));
+ }
+ // Skip over undocumented Discord byte
+ offset++;
+
+ packet = packet.slice(offset);
+ }
+
+ return packet;
+ }
+
+ push(buffer) {
+ const ssrc = buffer.readUInt32BE(8);
+ const userStat = this.connection.ssrcMap.get(ssrc);
+ if (!userStat) return;
+
+ let speakingTimeout = this.speakingTimeouts.get(ssrc);
+ if (typeof speakingTimeout === 'undefined') {
+ this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: userStat.speaking });
+ speakingTimeout = this.receiver.connection.client.setTimeout(() => {
+ try {
+ this.connection.onSpeaking({ user_id: userStat.userID, ssrc: ssrc, speaking: 0 });
+ this.receiver.connection.client.clearTimeout(speakingTimeout);
+ this.speakingTimeouts.delete(ssrc);
+ } catch {
+ // Connection already closed, ignore
+ }
+ }, DISCORD_SPEAKING_DELAY);
+ this.speakingTimeouts.set(ssrc, speakingTimeout);
+ } else {
+ speakingTimeout.refresh();
+ }
+
+ let stream = this.streams.get(userStat.userID);
+ if (!stream) return;
+ stream = stream.stream;
+ const opusPacket = this.parseBuffer(buffer);
+ if (opusPacket instanceof Error) {
+ this.emit('error', opusPacket);
+ return;
+ }
+ stream.push(opusPacket);
+ }
+}
+
+module.exports = PacketHandler;
diff --git a/node_modules/discord.js/src/client/voice/receiver/Receiver.js b/node_modules/discord.js/src/client/voice/receiver/Receiver.js
new file mode 100644
index 0000000..605d992
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/receiver/Receiver.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const EventEmitter = require('events');
+const prism = require('prism-media');
+const PacketHandler = require('./PacketHandler');
+const { Error } = require('../../../errors');
+
+/**
+ * Receives audio packets from a voice connection.
+ * @example
+ * const receiver = connection.createReceiver();
+ * // opusStream is a ReadableStream - that means you could play it back to a voice channel if you wanted to!
+ * const opusStream = receiver.createStream(user);
+ */
+class VoiceReceiver extends EventEmitter {
+ constructor(connection) {
+ super();
+ this.connection = connection;
+ this.packets = new PacketHandler(this);
+ /**
+ * Emitted whenever there is a warning
+ * @event VoiceReceiver#debug
+ * @param {Error|string} error The error or message to debug
+ */
+ this.packets.on('error', err => this.emit('debug', err));
+ }
+
+ /**
+ * Options passed to `VoiceReceiver#createStream`.
+ * @typedef {Object} ReceiveStreamOptions
+ * @property {string} [mode='opus'] The mode for audio output. This defaults to opus, meaning discord.js won't decode
+ * the packets for you. You can set this to 'pcm' so that the stream's output will be 16-bit little-endian stereo
+ * audio
+ * @property {string} [end='silence'] When the stream should be destroyed. If `silence`, this will be when the user
+ * stops talking. Otherwise, if `manual`, this should be handled by you.
+ */
+
+ /**
+ * Creates a new audio receiving stream. If a stream already exists for a user, then that stream will be returned
+ * rather than generating a new one.
+ * @param {UserResolvable} user The user to start listening to.
+ * @param {ReceiveStreamOptions} options Options.
+ * @returns {ReadableStream}
+ */
+ createStream(user, { mode = 'opus', end = 'silence' } = {}) {
+ user = this.connection.client.users.resolve(user);
+ if (!user) throw new Error('VOICE_USER_MISSING');
+ const stream = this.packets.makeStream(user.id, end);
+ if (mode === 'pcm') {
+ const decoder = new prism.opus.Decoder({ channels: 2, rate: 48000, frameSize: 960 });
+ stream.pipe(decoder);
+ return decoder;
+ }
+ return stream;
+ }
+}
+
+module.exports = VoiceReceiver;
diff --git a/node_modules/discord.js/src/client/voice/util/PlayInterface.js b/node_modules/discord.js/src/client/voice/util/PlayInterface.js
new file mode 100644
index 0000000..9478ee8
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/util/PlayInterface.js
@@ -0,0 +1,94 @@
+'use strict';
+
+const { Readable } = require('stream');
+const prism = require('prism-media');
+const { Error } = require('../../../errors');
+
+/**
+ * Options that can be passed to stream-playing methods:
+ * @typedef {Object} StreamOptions
+ * @property {StreamType} [type='unknown'] The type of stream.
+ * @property {number} [seek=0] The time to seek to, will be ignored when playing `ogg/opus` or `webm/opus` streams
+ * @property {number|boolean} [volume=1] The volume to play at. Set this to false to disable volume transforms for
+ * this stream to improve performance.
+ * @property {number} [plp] Expected packet loss percentage
+ * @property {boolean} [fec] Enabled forward error correction
+ * @property {number|string} [bitrate=96] The bitrate (quality) of the audio in kbps.
+ * If set to 'auto', the voice channel's bitrate will be used
+ * @property {number} [highWaterMark=12] The maximum number of opus packets to make and store before they are
+ * actually needed. See https://nodejs.org/en/docs/guides/backpressuring-in-streams/. Setting this value to
+ * 1 means that changes in volume will be more instant.
+ */
+
+/**
+ * An option passed as part of `StreamOptions` specifying the type of the stream.
+ * * `unknown`: The default type, streams/input will be passed through to ffmpeg before encoding.
+ * Will play most streams.
+ * * `converted`: Play a stream of 16bit signed stereo PCM data, skipping ffmpeg.
+ * * `opus`: Play a stream of opus packets, skipping ffmpeg. You lose the ability to alter volume.
+ * * `ogg/opus`: Play an ogg file with the opus encoding, skipping ffmpeg. You lose the ability to alter volume.
+ * * `webm/opus`: Play a webm file with opus audio, skipping ffmpeg. You lose the ability to alter volume.
+ * @typedef {string} StreamType
+ */
+
+/**
+ * An interface class to allow you to play audio over VoiceConnections and VoiceBroadcasts.
+ */
+class PlayInterface {
+ constructor(player) {
+ this.player = player;
+ }
+
+ /**
+ * Play an audio resource.
+ * @param {VoiceBroadcast|ReadableStream|string} resource The resource to play.
+ * @param {StreamOptions} [options] The options to play.
+ * @example
+ * // Play a local audio file
+ * connection.play('/home/hydrabolt/audio.mp3', { volume: 0.5 });
+ * @example
+ * // Play a ReadableStream
+ * connection.play(ytdl('https://www.youtube.com/watch?v=ZlAU_w7-Xp8', { quality: 'highestaudio' }));
+ * @example
+ * // Play a voice broadcast
+ * const broadcast = client.voice.createBroadcast();
+ * broadcast.play('/home/hydrabolt/audio.mp3');
+ * connection.play(broadcast);
+ * @example
+ * // Using different protocols: https://ffmpeg.org/ffmpeg-protocols.html
+ * connection.play('http://www.sample-videos.com/audio/mp3/wave.mp3');
+ * @returns {StreamDispatcher}
+ */
+ play(resource, options = {}) {
+ const VoiceBroadcast = require('../VoiceBroadcast');
+ if (resource instanceof VoiceBroadcast) {
+ if (!this.player.playBroadcast) throw new Error('VOICE_PLAY_INTERFACE_NO_BROADCAST');
+ return this.player.playBroadcast(resource, options);
+ }
+ if (resource instanceof Readable || typeof resource === 'string') {
+ const type = options.type || 'unknown';
+ if (type === 'unknown') {
+ return this.player.playUnknown(resource, options);
+ } else if (type === 'converted') {
+ return this.player.playPCMStream(resource, options);
+ } else if (type === 'opus') {
+ return this.player.playOpusStream(resource, options);
+ } else if (type === 'ogg/opus') {
+ if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM');
+ return this.player.playOpusStream(resource.pipe(new prism.opus.OggDemuxer()), options);
+ } else if (type === 'webm/opus') {
+ if (!(resource instanceof Readable)) throw new Error('VOICE_PRISM_DEMUXERS_NEED_STREAM');
+ return this.player.playOpusStream(resource.pipe(new prism.opus.WebmDemuxer()), options);
+ }
+ }
+ throw new Error('VOICE_PLAY_INTERFACE_BAD_TYPE');
+ }
+
+ static applyToClass(structure) {
+ for (const prop of ['play']) {
+ Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(PlayInterface.prototype, prop));
+ }
+ }
+}
+
+module.exports = PlayInterface;
diff --git a/node_modules/discord.js/src/client/voice/util/Secretbox.js b/node_modules/discord.js/src/client/voice/util/Secretbox.js
new file mode 100644
index 0000000..c16a435
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/util/Secretbox.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const libs = {
+ sodium: sodium => ({
+ open: sodium.api.crypto_secretbox_open_easy,
+ close: sodium.api.crypto_secretbox_easy,
+ random: n => sodium.randombytes_buf(n),
+ }),
+ 'libsodium-wrappers': sodium => ({
+ open: sodium.crypto_secretbox_open_easy,
+ close: sodium.crypto_secretbox_easy,
+ random: n => sodium.randombytes_buf(n),
+ }),
+ tweetnacl: tweetnacl => ({
+ open: tweetnacl.secretbox.open,
+ close: tweetnacl.secretbox,
+ random: n => tweetnacl.randomBytes(n),
+ }),
+};
+
+exports.methods = {};
+
+(async () => {
+ for (const libName of Object.keys(libs)) {
+ try {
+ const lib = require(libName);
+ if (libName === 'libsodium-wrappers' && lib.ready) await lib.ready; // eslint-disable-line no-await-in-loop
+ exports.methods = libs[libName](lib);
+ break;
+ } catch {} // eslint-disable-line no-empty
+ }
+})();
diff --git a/node_modules/discord.js/src/client/voice/util/Silence.js b/node_modules/discord.js/src/client/voice/util/Silence.js
new file mode 100644
index 0000000..9bea3d0
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/util/Silence.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const { Readable } = require('stream');
+
+const SILENCE_FRAME = Buffer.from([0xf8, 0xff, 0xfe]);
+
+class Silence extends Readable {
+ _read() {
+ this.push(SILENCE_FRAME);
+ }
+}
+
+module.exports = Silence;
diff --git a/node_modules/discord.js/src/client/voice/util/VolumeInterface.js b/node_modules/discord.js/src/client/voice/util/VolumeInterface.js
new file mode 100644
index 0000000..0dca04f
--- /dev/null
+++ b/node_modules/discord.js/src/client/voice/util/VolumeInterface.js
@@ -0,0 +1,103 @@
+'use strict';
+
+const EventEmitter = require('events');
+
+/**
+ * An interface class for volume transformation.
+ * @extends {EventEmitter}
+ */
+class VolumeInterface extends EventEmitter {
+ constructor({ volume = 1 } = {}) {
+ super();
+ this.setVolume(volume);
+ }
+
+ /**
+ * Whether or not the volume of this stream is editable
+ * @type {boolean}
+ * @readonly
+ */
+ get volumeEditable() {
+ return true;
+ }
+
+ /**
+ * The current volume of the stream
+ * @type {number}
+ * @readonly
+ */
+ get volume() {
+ return this._volume;
+ }
+
+ /**
+ * The current volume of the stream in decibels
+ * @type {number}
+ * @readonly
+ */
+ get volumeDecibels() {
+ return Math.log10(this.volume) * 20;
+ }
+
+ /**
+ * The current volume of the stream from a logarithmic scale
+ * @type {number}
+ * @readonly
+ */
+ get volumeLogarithmic() {
+ return Math.pow(this.volume, 1 / 1.660964);
+ }
+
+ applyVolume(buffer, volume) {
+ volume = volume || this._volume;
+ if (volume === 1) return buffer;
+
+ const out = Buffer.alloc(buffer.length);
+ for (let i = 0; i < buffer.length; i += 2) {
+ if (i >= buffer.length - 1) break;
+ const uint = Math.min(32767, Math.max(-32767, Math.floor(volume * buffer.readInt16LE(i))));
+ out.writeInt16LE(uint, i);
+ }
+
+ return out;
+ }
+
+ /**
+ * Sets the volume relative to the input stream - i.e. 1 is normal, 0.5 is half, 2 is double.
+ * @param {number} volume The volume that you want to set
+ */
+ setVolume(volume) {
+ /**
+ * Emitted when the volume of this interface changes.
+ * @event VolumeInterface#volumeChange
+ * @param {number} oldVolume The old volume of this interface
+ * @param {number} newVolume The new volume of this interface
+ */
+ this.emit('volumeChange', this._volume, volume);
+ this._volume = volume;
+ }
+
+ /**
+ * Sets the volume in decibels.
+ * @param {number} db The decibels
+ */
+ setVolumeDecibels(db) {
+ this.setVolume(Math.pow(10, db / 20));
+ }
+
+ /**
+ * Sets the volume so that a perceived value of 0.5 is half the perceived volume etc.
+ * @param {number} value The value for the volume
+ */
+ setVolumeLogarithmic(value) {
+ this.setVolume(Math.pow(value, 1.660964));
+ }
+}
+
+const props = ['volumeDecibels', 'volumeLogarithmic', 'setVolumeDecibels', 'setVolumeLogarithmic'];
+
+exports.applyToClass = function applyToClass(structure) {
+ for (const prop of props) {
+ Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(VolumeInterface.prototype, prop));
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/WebSocketManager.js b/node_modules/discord.js/src/client/websocket/WebSocketManager.js
new file mode 100644
index 0000000..1801106
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/WebSocketManager.js
@@ -0,0 +1,439 @@
+'use strict';
+
+const EventEmitter = require('events');
+const WebSocketShard = require('./WebSocketShard');
+const PacketHandlers = require('./handlers');
+const { Error: DJSError } = require('../../errors');
+const Collection = require('../../util/Collection');
+const { Events, ShardEvents, Status, WSCodes, WSEvents } = require('../../util/Constants');
+const Util = require('../../util/Util');
+
+const BeforeReadyWhitelist = [
+ WSEvents.READY,
+ WSEvents.RESUMED,
+ WSEvents.GUILD_CREATE,
+ WSEvents.GUILD_DELETE,
+ WSEvents.GUILD_MEMBERS_CHUNK,
+ WSEvents.GUILD_MEMBER_ADD,
+ WSEvents.GUILD_MEMBER_REMOVE,
+];
+
+const UNRECOVERABLE_CLOSE_CODES = Object.keys(WSCodes)
+ .slice(1)
+ .map(Number);
+const UNRESUMABLE_CLOSE_CODES = [1000, 4006, 4007];
+
+/**
+ * The WebSocket manager for this client.
+ * <info>This class forwards raw dispatch events,
+ * read more about it here {@link https://discordapp.com/developers/docs/topics/gateway}</info>
+ * @extends EventEmitter
+ */
+class WebSocketManager extends EventEmitter {
+ constructor(client) {
+ super();
+
+ /**
+ * The client that instantiated this WebSocketManager
+ * @type {Client}
+ * @readonly
+ * @name WebSocketManager#client
+ */
+ Object.defineProperty(this, 'client', { value: client });
+
+ /**
+ * The gateway this manager uses
+ * @type {?string}
+ */
+ this.gateway = undefined;
+
+ /**
+ * The amount of shards this manager handles
+ * @private
+ * @type {number}
+ */
+ this.totalShards = this.client.options.shards.length;
+
+ /**
+ * A collection of all shards this manager handles
+ * @type {Collection<number, WebSocketShard>}
+ */
+ this.shards = new Collection();
+
+ /**
+ * An array of shards to be connected or that need to reconnect
+ * @type {Set<WebSocketShard>}
+ * @private
+ * @name WebSocketManager#shardQueue
+ */
+ Object.defineProperty(this, 'shardQueue', { value: new Set(), writable: true });
+
+ /**
+ * An array of queued events before this WebSocketManager became ready
+ * @type {object[]}
+ * @private
+ * @name WebSocketManager#packetQueue
+ */
+ Object.defineProperty(this, 'packetQueue', { value: [] });
+
+ /**
+ * The current status of this WebSocketManager
+ * @type {number}
+ */
+ this.status = Status.IDLE;
+
+ /**
+ * If this manager was destroyed. It will prevent shards from reconnecting
+ * @type {boolean}
+ * @private
+ */
+ this.destroyed = false;
+
+ /**
+ * If this manager is currently reconnecting one or multiple shards
+ * @type {boolean}
+ * @private
+ */
+ this.reconnecting = false;
+
+ /**
+ * The current session limit of the client
+ * @private
+ * @type {?Object}
+ * @prop {number} total Total number of identifies available
+ * @prop {number} remaining Number of identifies remaining
+ * @prop {number} reset_after Number of milliseconds after which the limit resets
+ */
+ this.sessionStartLimit = undefined;
+ }
+
+ /**
+ * The average ping of all WebSocketShards
+ * @type {number}
+ * @readonly
+ */
+ get ping() {
+ const sum = this.shards.reduce((a, b) => a + b.ping, 0);
+ return sum / this.shards.size;
+ }
+
+ /**
+ * Emits a debug message.
+ * @param {string} message The debug message
+ * @param {?WebSocketShard} [shard] The shard that emitted this message, if any
+ * @private
+ */
+ debug(message, shard) {
+ this.client.emit(Events.DEBUG, `[WS => ${shard ? `Shard ${shard.id}` : 'Manager'}] ${message}`);
+ }
+
+ /**
+ * Connects this manager to the gateway.
+ * @private
+ */
+ async connect() {
+ const invalidToken = new DJSError(WSCodes[4004]);
+ const {
+ url: gatewayURL,
+ shards: recommendedShards,
+ session_start_limit: sessionStartLimit,
+ } = await this.client.api.gateway.bot.get().catch(error => {
+ throw error.httpStatus === 401 ? invalidToken : error;
+ });
+
+ this.sessionStartLimit = sessionStartLimit;
+
+ const { total, remaining, reset_after } = sessionStartLimit;
+
+ this.debug(`Fetched Gateway Information
+ URL: ${gatewayURL}
+ Recommended Shards: ${recommendedShards}`);
+
+ this.debug(`Session Limit Information
+ Total: ${total}
+ Remaining: ${remaining}`);
+
+ this.gateway = `${gatewayURL}/`;
+
+ let { shards } = this.client.options;
+
+ if (shards === 'auto') {
+ this.debug(`Using the recommended shard count provided by Discord: ${recommendedShards}`);
+ this.totalShards = this.client.options.shardCount = recommendedShards;
+ shards = this.client.options.shards = Array.from({ length: recommendedShards }, (_, i) => i);
+ }
+
+ this.totalShards = shards.length;
+ this.debug(`Spawning shards: ${shards.join(', ')}`);
+ this.shardQueue = new Set(shards.map(id => new WebSocketShard(this, id)));
+
+ await this._handleSessionLimit(remaining, reset_after);
+
+ return this.createShards();
+ }
+
+ /**
+ * Handles the creation of a shard.
+ * @returns {Promise<boolean>}
+ * @private
+ */
+ async createShards() {
+ // If we don't have any shards to handle, return
+ if (!this.shardQueue.size) return false;
+
+ const [shard] = this.shardQueue;
+
+ this.shardQueue.delete(shard);
+
+ if (!shard.eventsAttached) {
+ shard.on(ShardEvents.ALL_READY, unavailableGuilds => {
+ /**
+ * Emitted when a shard turns ready.
+ * @event Client#shardReady
+ * @param {number} id The shard ID that turned ready
+ * @param {?Set<string>} unavailableGuilds Set of unavailable guild IDs, if any
+ */
+ this.client.emit(Events.SHARD_READY, shard.id, unavailableGuilds);
+
+ if (!this.shardQueue.size) this.reconnecting = false;
+ this.checkShardsReady();
+ });
+
+ shard.on(ShardEvents.CLOSE, event => {
+ if (event.code === 1000 ? this.destroyed : UNRECOVERABLE_CLOSE_CODES.includes(event.code)) {
+ /**
+ * Emitted when a shard's WebSocket disconnects and will no longer reconnect.
+ * @event Client#shardDisconnect
+ * @param {CloseEvent} event The WebSocket close event
+ * @param {number} id The shard ID that disconnected
+ */
+ this.client.emit(Events.SHARD_DISCONNECT, event, shard.id);
+ this.debug(WSCodes[event.code], shard);
+ return;
+ }
+
+ if (UNRESUMABLE_CLOSE_CODES.includes(event.code)) {
+ // These event codes cannot be resumed
+ shard.sessionID = undefined;
+ }
+
+ /**
+ * Emitted when a shard is attempting to reconnect or re-identify.
+ * @event Client#shardReconnecting
+ * @param {number} id The shard ID that is attempting to reconnect
+ */
+ this.client.emit(Events.SHARD_RECONNECTING, shard.id);
+
+ this.shardQueue.add(shard);
+
+ if (shard.sessionID) {
+ this.debug(`Session ID is present, attempting an immediate reconnect...`, shard);
+ this.reconnect(true);
+ } else {
+ shard.destroy({ reset: true, emit: false, log: false });
+ this.reconnect();
+ }
+ });
+
+ shard.on(ShardEvents.INVALID_SESSION, () => {
+ this.client.emit(Events.SHARD_RECONNECTING, shard.id);
+ });
+
+ shard.on(ShardEvents.DESTROYED, () => {
+ this.debug('Shard was destroyed but no WebSocket connection was present! Reconnecting...', shard);
+
+ this.client.emit(Events.SHARD_RECONNECTING, shard.id);
+
+ this.shardQueue.add(shard);
+ this.reconnect();
+ });
+
+ shard.eventsAttached = true;
+ }
+
+ this.shards.set(shard.id, shard);
+
+ try {
+ await shard.connect();
+ } catch (error) {
+ if (error && error.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) {
+ throw new DJSError(WSCodes[error.code]);
+ // Undefined if session is invalid, error event for regular closes
+ } else if (!error || error.code) {
+ this.debug('Failed to connect to the gateway, requeueing...', shard);
+ this.shardQueue.add(shard);
+ } else {
+ throw error;
+ }
+ }
+ // If we have more shards, add a 5s delay
+ if (this.shardQueue.size) {
+ this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`);
+ await Util.delayFor(5000);
+ await this._handleSessionLimit();
+ return this.createShards();
+ }
+
+ return true;
+ }
+
+ /**
+ * Handles reconnects for this manager.
+ * @param {boolean} [skipLimit=false] IF this reconnect should skip checking the session limit
+ * @private
+ * @returns {Promise<boolean>}
+ */
+ async reconnect(skipLimit = false) {
+ if (this.reconnecting || this.status !== Status.READY) return false;
+ this.reconnecting = true;
+ try {
+ if (!skipLimit) await this._handleSessionLimit();
+ await this.createShards();
+ } catch (error) {
+ this.debug(`Couldn't reconnect or fetch information about the gateway. ${error}`);
+ if (error.httpStatus !== 401) {
+ this.debug(`Possible network error occurred. Retrying in 5s...`);
+ await Util.delayFor(5000);
+ this.reconnecting = false;
+ return this.reconnect();
+ }
+ // If we get an error at this point, it means we cannot reconnect anymore
+ if (this.client.listenerCount(Events.INVALIDATED)) {
+ /**
+ * Emitted when the client's session becomes invalidated.
+ * You are expected to handle closing the process gracefully and preventing a boot loop
+ * if you are listening to this event.
+ * @event Client#invalidated
+ */
+ this.client.emit(Events.INVALIDATED);
+ // Destroy just the shards. This means you have to handle the cleanup yourself
+ this.destroy();
+ } else {
+ this.client.destroy();
+ }
+ } finally {
+ this.reconnecting = false;
+ }
+ return true;
+ }
+
+ /**
+ * Broadcasts a packet to every shard this manager handles.
+ * @param {Object} packet The packet to send
+ * @private
+ */
+ broadcast(packet) {
+ for (const shard of this.shards.values()) shard.send(packet);
+ }
+
+ /**
+ * Destroys this manager and all its shards.
+ * @private
+ */
+ destroy() {
+ if (this.destroyed) return;
+ this.debug(`Manager was destroyed. Called by:\n${new Error('MANAGER_DESTROYED').stack}`);
+ this.destroyed = true;
+ this.shardQueue.clear();
+ for (const shard of this.shards.values()) shard.destroy({ closeCode: 1000, reset: true, emit: false, log: false });
+ }
+
+ /**
+ * Handles the timeout required if we cannot identify anymore.
+ * @param {number} [remaining] The amount of remaining identify sessions that can be done today
+ * @param {number} [resetAfter] The amount of time in which the identify counter resets
+ * @private
+ */
+ async _handleSessionLimit(remaining, resetAfter) {
+ if (typeof remaining === 'undefined' && typeof resetAfter === 'undefined') {
+ const { session_start_limit } = await this.client.api.gateway.bot.get();
+ this.sessionStartLimit = session_start_limit;
+ remaining = session_start_limit.remaining;
+ resetAfter = session_start_limit.reset_after;
+ this.debug(`Session Limit Information
+ Total: ${session_start_limit.total}
+ Remaining: ${remaining}`);
+ }
+ if (!remaining) {
+ this.debug(`Exceeded identify threshold. Will attempt a connection in ${resetAfter}ms`);
+ await Util.delayFor(resetAfter);
+ }
+ }
+
+ /**
+ * Processes a packet and queues it if this WebSocketManager is not ready.
+ * @param {Object} [packet] The packet to be handled
+ * @param {WebSocketShard} [shard] The shard that will handle this packet
+ * @returns {boolean}
+ * @private
+ */
+ handlePacket(packet, shard) {
+ if (packet && this.status !== Status.READY) {
+ if (!BeforeReadyWhitelist.includes(packet.t)) {
+ this.packetQueue.push({ packet, shard });
+ return false;
+ }
+ }
+
+ if (this.packetQueue.length) {
+ const item = this.packetQueue.shift();
+ this.client.setImmediate(() => {
+ this.handlePacket(item.packet, item.shard);
+ });
+ }
+
+ if (packet && PacketHandlers[packet.t]) {
+ PacketHandlers[packet.t](this.client, packet, shard);
+ }
+
+ return true;
+ }
+
+ /**
+ * Checks whether the client is ready to be marked as ready.
+ * @private
+ */
+ async checkShardsReady() {
+ if (this.status === Status.READY) return;
+ if (this.shards.size !== this.totalShards || this.shards.some(s => s.status !== Status.READY)) {
+ return;
+ }
+
+ this.status = Status.NEARLY;
+
+ if (this.client.options.fetchAllMembers) {
+ try {
+ const promises = this.client.guilds.cache.map(guild => {
+ if (guild.available) return guild.members.fetch();
+ // Return empty promise if guild is unavailable
+ return Promise.resolve();
+ });
+ await Promise.all(promises);
+ } catch (err) {
+ this.debug(`Failed to fetch all members before ready! ${err}\n${err.stack}`);
+ }
+ }
+
+ this.triggerClientReady();
+ }
+
+ /**
+ * Causes the client to be marked as ready and emits the ready event.
+ * @private
+ */
+ triggerClientReady() {
+ this.status = Status.READY;
+
+ this.client.readyAt = new Date();
+
+ /**
+ * Emitted when the client becomes ready to start working.
+ * @event Client#ready
+ */
+ this.client.emit(Events.CLIENT_READY);
+
+ this.handlePacket();
+ }
+}
+
+module.exports = WebSocketManager;
diff --git a/node_modules/discord.js/src/client/websocket/WebSocketShard.js b/node_modules/discord.js/src/client/websocket/WebSocketShard.js
new file mode 100644
index 0000000..9f80f45
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/WebSocketShard.js
@@ -0,0 +1,763 @@
+'use strict';
+
+const EventEmitter = require('events');
+const WebSocket = require('../../WebSocket');
+const { browser, Status, Events, ShardEvents, OPCodes, WSEvents } = require('../../util/Constants');
+
+const STATUS_KEYS = Object.keys(Status);
+const CONNECTION_STATE = Object.keys(WebSocket.WebSocket);
+
+let zlib;
+
+if (!browser) {
+ try {
+ zlib = require('zlib-sync');
+ } catch {} // eslint-disable-line no-empty
+}
+
+/**
+ * Represents a Shard's WebSocket connection
+ */
+class WebSocketShard extends EventEmitter {
+ constructor(manager, id) {
+ super();
+
+ /**
+ * The WebSocketManager of the shard
+ * @type {WebSocketManager}
+ */
+ this.manager = manager;
+
+ /**
+ * The ID of the shard
+ * @type {number}
+ */
+ this.id = id;
+
+ /**
+ * The current status of the shard
+ * @type {Status}
+ */
+ this.status = Status.IDLE;
+
+ /**
+ * The current sequence of the shard
+ * @type {number}
+ * @private
+ */
+ this.sequence = -1;
+
+ /**
+ * The sequence of the shard after close
+ * @type {number}
+ * @private
+ */
+ this.closeSequence = 0;
+
+ /**
+ * The current session ID of the shard
+ * @type {string}
+ * @private
+ */
+ this.sessionID = undefined;
+
+ /**
+ * The previous heartbeat ping of the shard
+ * @type {number}
+ */
+ this.ping = -1;
+
+ /**
+ * The last time a ping was sent (a timestamp)
+ * @type {number}
+ * @private
+ */
+ this.lastPingTimestamp = -1;
+
+ /**
+ * If we received a heartbeat ack back. Used to identify zombie connections
+ * @type {boolean}
+ * @private
+ */
+ this.lastHeartbeatAcked = true;
+
+ /**
+ * Contains the rate limit queue and metadata
+ * @type {Object}
+ * @private
+ */
+ Object.defineProperty(this, 'ratelimit', {
+ value: {
+ queue: [],
+ total: 120,
+ remaining: 120,
+ time: 60e3,
+ timer: null,
+ },
+ });
+
+ /**
+ * The WebSocket connection for the current shard
+ * @type {?WebSocket}
+ * @private
+ */
+ Object.defineProperty(this, 'connection', { value: null, writable: true });
+
+ /**
+ * @external Inflate
+ * @see {@link https://www.npmjs.com/package/zlib-sync}
+ */
+
+ /**
+ * The compression to use
+ * @type {?Inflate}
+ * @private
+ */
+ Object.defineProperty(this, 'inflate', { value: null, writable: true });
+
+ /**
+ * The HELLO timeout
+ * @type {?NodeJS.Timer}
+ * @private
+ */
+ Object.defineProperty(this, 'helloTimeout', { value: undefined, writable: true });
+
+ /**
+ * If the manager attached its event handlers on the shard
+ * @type {boolean}
+ * @private
+ */
+ Object.defineProperty(this, 'eventsAttached', { value: false, writable: true });
+
+ /**
+ * A set of guild IDs this shard expects to receive
+ * @type {?Set<string>}
+ * @private
+ */
+ Object.defineProperty(this, 'expectedGuilds', { value: undefined, writable: true });
+
+ /**
+ * The ready timeout
+ * @type {?NodeJS.Timer}
+ * @private
+ */
+ Object.defineProperty(this, 'readyTimeout', { value: undefined, writable: true });
+
+ /**
+ * Time when the WebSocket connection was opened
+ * @type {number}
+ * @private
+ */
+ Object.defineProperty(this, 'connectedAt', { value: 0, writable: true });
+ }
+
+ /**
+ * Emits a debug event.
+ * @param {string} message The debug message
+ * @private
+ */
+ debug(message) {
+ this.manager.debug(message, this);
+ }
+
+ /**
+ * Connects the shard to the gateway.
+ * @private
+ * @returns {Promise<void>} A promise that will resolve if the shard turns ready successfully,
+ * or reject if we couldn't connect
+ */
+ connect() {
+ const { gateway, client } = this.manager;
+
+ if (this.connection && this.connection.readyState === WebSocket.OPEN && this.status === Status.READY) {
+ return Promise.resolve();
+ }
+
+ return new Promise((resolve, reject) => {
+ const cleanup = () => {
+ this.removeListener(ShardEvents.CLOSE, onClose);
+ this.removeListener(ShardEvents.READY, onReady);
+ this.removeListener(ShardEvents.RESUMED, onResumed);
+ this.removeListener(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed);
+ this.removeListener(ShardEvents.DESTROYED, onInvalidOrDestroyed);
+ };
+
+ const onReady = () => {
+ cleanup();
+ resolve();
+ };
+
+ const onResumed = () => {
+ cleanup();
+ resolve();
+ };
+
+ const onClose = event => {
+ cleanup();
+ reject(event);
+ };
+
+ const onInvalidOrDestroyed = () => {
+ cleanup();
+ // eslint-disable-next-line prefer-promise-reject-errors
+ reject();
+ };
+
+ this.once(ShardEvents.READY, onReady);
+ this.once(ShardEvents.RESUMED, onResumed);
+ this.once(ShardEvents.CLOSE, onClose);
+ this.once(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed);
+ this.once(ShardEvents.DESTROYED, onInvalidOrDestroyed);
+
+ if (this.connection && this.connection.readyState === WebSocket.OPEN) {
+ this.debug('An open connection was found, attempting an immediate identify.');
+ this.identify();
+ return;
+ }
+
+ if (this.connection) {
+ this.debug(`A connection object was found. Cleaning up before continuing.
+ State: ${CONNECTION_STATE[this.connection.readyState]}`);
+ this.destroy({ emit: false });
+ }
+
+ const wsQuery = { v: client.options.ws.version };
+
+ if (zlib) {
+ this.inflate = new zlib.Inflate({
+ chunkSize: 65535,
+ flush: zlib.Z_SYNC_FLUSH,
+ to: WebSocket.encoding === 'json' ? 'string' : '',
+ });
+ wsQuery.compress = 'zlib-stream';
+ }
+
+ this.debug(
+ `[CONNECT]
+ Gateway : ${gateway}
+ Version : ${client.options.ws.version}
+ Encoding : ${WebSocket.encoding}
+ Compression: ${zlib ? 'zlib-stream' : 'none'}`,
+ );
+
+ this.status = this.status === Status.DISCONNECTED ? Status.RECONNECTING : Status.CONNECTING;
+ this.setHelloTimeout();
+
+ this.connectedAt = Date.now();
+
+ const ws = (this.connection = WebSocket.create(gateway, wsQuery));
+ ws.onopen = this.onOpen.bind(this);
+ ws.onmessage = this.onMessage.bind(this);
+ ws.onerror = this.onError.bind(this);
+ ws.onclose = this.onClose.bind(this);
+ });
+ }
+
+ /**
+ * Called whenever a connection is opened to the gateway.
+ * @private
+ */
+ onOpen() {
+ this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now() - this.connectedAt}ms`);
+ this.status = Status.NEARLY;
+ }
+
+ /**
+ * Called whenever a message is received.
+ * @param {MessageEvent} event Event received
+ * @private
+ */
+ onMessage({ data }) {
+ let raw;
+ if (data instanceof ArrayBuffer) data = new Uint8Array(data);
+ if (zlib) {
+ const l = data.length;
+ const flush =
+ l >= 4 && data[l - 4] === 0x00 && data[l - 3] === 0x00 && data[l - 2] === 0xff && data[l - 1] === 0xff;
+
+ this.inflate.push(data, flush && zlib.Z_SYNC_FLUSH);
+ if (!flush) return;
+ raw = this.inflate.result;
+ } else {
+ raw = data;
+ }
+ let packet;
+ try {
+ packet = WebSocket.unpack(raw);
+ this.manager.client.emit(Events.RAW, packet, this.id);
+ if (packet.op === OPCodes.DISPATCH) this.manager.emit(packet.t, packet.d, this.id);
+ } catch (err) {
+ this.manager.client.emit(Events.SHARD_ERROR, err, this.id);
+ return;
+ }
+ this.onPacket(packet);
+ }
+
+ /**
+ * Called whenever an error occurs with the WebSocket.
+ * @param {ErrorEvent} event The error that occurred
+ * @private
+ */
+ onError(event) {
+ const error = event && event.error ? event.error : event;
+ if (!error) return;
+
+ /**
+ * Emitted whenever a shard's WebSocket encounters a connection error.
+ * @event Client#shardError
+ * @param {Error} error The encountered error
+ * @param {number} shardID The shard that encountered this error
+ */
+ this.manager.client.emit(Events.SHARD_ERROR, error, this.id);
+ }
+
+ /**
+ * @external CloseEvent
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent}
+ */
+
+ /**
+ * @external ErrorEvent
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent}
+ */
+
+ /**
+ * @external MessageEvent
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent}
+ */
+
+ /**
+ * Called whenever a connection to the gateway is closed.
+ * @param {CloseEvent} event Close event that was received
+ * @private
+ */
+ onClose(event) {
+ if (this.sequence !== -1) this.closeSequence = this.sequence;
+ this.sequence = -1;
+
+ this.debug(`[CLOSE]
+ Event Code: ${event.code}
+ Clean : ${event.wasClean}
+ Reason : ${event.reason || 'No reason received'}`);
+
+ this.setHeartbeatTimer(-1);
+ this.setHelloTimeout(-1);
+ // If we still have a connection object, clean up its listeners
+ if (this.connection) this._cleanupConnection();
+
+ this.status = Status.DISCONNECTED;
+
+ /**
+ * Emitted when a shard's WebSocket closes.
+ * @private
+ * @event WebSocketShard#close
+ * @param {CloseEvent} event The received event
+ */
+ this.emit(ShardEvents.CLOSE, event);
+ }
+
+ /**
+ * Called whenever a packet is received.
+ * @param {Object} packet The received packet
+ * @private
+ */
+ onPacket(packet) {
+ if (!packet) {
+ this.debug(`Received broken packet: '${packet}'.`);
+ return;
+ }
+
+ switch (packet.t) {
+ case WSEvents.READY:
+ /**
+ * Emitted when the shard receives the READY payload and is now waiting for guilds
+ * @event WebSocketShard#ready
+ */
+ this.emit(ShardEvents.READY);
+
+ this.sessionID = packet.d.session_id;
+ this.expectedGuilds = new Set(packet.d.guilds.map(d => d.id));
+ this.status = Status.WAITING_FOR_GUILDS;
+ this.debug(`[READY] Session ${this.sessionID}.`);
+ this.lastHeartbeatAcked = true;
+ this.sendHeartbeat('ReadyHeartbeat');
+ break;
+ case WSEvents.RESUMED: {
+ /**
+ * Emitted when the shard resumes successfully
+ * @event WebSocketShard#resumed
+ */
+ this.emit(ShardEvents.RESUMED);
+
+ this.status = Status.READY;
+ const replayed = packet.s - this.closeSequence;
+ this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${replayed} events.`);
+ this.lastHeartbeatAcked = true;
+ this.sendHeartbeat('ResumeHeartbeat');
+ break;
+ }
+ }
+
+ if (packet.s > this.sequence) this.sequence = packet.s;
+
+ switch (packet.op) {
+ case OPCodes.HELLO:
+ this.setHelloTimeout(-1);
+ this.setHeartbeatTimer(packet.d.heartbeat_interval);
+ this.identify();
+ break;
+ case OPCodes.RECONNECT:
+ this.debug('[RECONNECT] Discord asked us to reconnect');
+ this.destroy({ closeCode: 4000 });
+ break;
+ case OPCodes.INVALID_SESSION:
+ this.debug(`[INVALID SESSION] Resumable: ${packet.d}.`);
+ // If we can resume the session, do so immediately
+ if (packet.d) {
+ this.identifyResume();
+ return;
+ }
+ // Reset the sequence
+ this.sequence = -1;
+ // Reset the session ID as it's invalid
+ this.sessionID = undefined;
+ // Set the status to reconnecting
+ this.status = Status.RECONNECTING;
+ // Finally, emit the INVALID_SESSION event
+ this.emit(ShardEvents.INVALID_SESSION);
+ break;
+ case OPCodes.HEARTBEAT_ACK:
+ this.ackHeartbeat();
+ break;
+ case OPCodes.HEARTBEAT:
+ this.sendHeartbeat('HeartbeatRequest', true);
+ break;
+ default:
+ this.manager.handlePacket(packet, this);
+ if (this.status === Status.WAITING_FOR_GUILDS && packet.t === WSEvents.GUILD_CREATE) {
+ this.expectedGuilds.delete(packet.d.id);
+ this.checkReady();
+ }
+ }
+ }
+
+ /**
+ * Checks if the shard can be marked as ready
+ * @private
+ */
+ checkReady() {
+ // Step 0. Clear the ready timeout, if it exists
+ if (this.readyTimeout) {
+ this.manager.client.clearTimeout(this.readyTimeout);
+ this.readyTimeout = undefined;
+ }
+ // Step 1. If we don't have any other guilds pending, we are ready
+ if (!this.expectedGuilds.size) {
+ this.debug('Shard received all its guilds. Marking as fully ready.');
+ this.status = Status.READY;
+
+ /**
+ * Emitted when the shard is fully ready.
+ * This event is emitted if:
+ * * all guilds were received by this shard
+ * * the ready timeout expired, and some guilds are unavailable
+ * @event WebSocketShard#allReady
+ * @param {?Set<string>} unavailableGuilds Set of unavailable guilds, if any
+ */
+ this.emit(ShardEvents.ALL_READY);
+ return;
+ }
+ // Step 2. Create a 15s timeout that will mark the shard as ready if there are still unavailable guilds
+ this.readyTimeout = this.manager.client.setTimeout(() => {
+ this.debug(`Shard did not receive any more guild packets in 15 seconds.
+ Unavailable guild count: ${this.expectedGuilds.size}`);
+
+ this.readyTimeout = undefined;
+
+ this.status = Status.READY;
+
+ this.emit(ShardEvents.ALL_READY, this.expectedGuilds);
+ }, 15000);
+ }
+
+ /**
+ * Sets the HELLO packet timeout.
+ * @param {number} [time] If set to -1, it will clear the hello timeout timeout
+ * @private
+ */
+ setHelloTimeout(time) {
+ if (time === -1) {
+ if (this.helloTimeout) {
+ this.debug('Clearing the HELLO timeout.');
+ this.manager.client.clearTimeout(this.helloTimeout);
+ this.helloTimeout = undefined;
+ }
+ return;
+ }
+ this.debug('Setting a HELLO timeout for 20s.');
+ this.helloTimeout = this.manager.client.setTimeout(() => {
+ this.debug('Did not receive HELLO in time. Destroying and connecting again.');
+ this.destroy({ reset: true, closeCode: 4009 });
+ }, 20000);
+ }
+
+ /**
+ * Sets the heartbeat timer for this shard.
+ * @param {number} time If -1, clears the interval, any other number sets an interval
+ * @private
+ */
+ setHeartbeatTimer(time) {
+ if (time === -1) {
+ if (this.heartbeatInterval) {
+ this.debug('Clearing the heartbeat interval.');
+ this.manager.client.clearInterval(this.heartbeatInterval);
+ this.heartbeatInterval = undefined;
+ }
+ return;
+ }
+ this.debug(`Setting a heartbeat interval for ${time}ms.`);
+ // Sanity checks
+ if (this.heartbeatInterval) this.manager.client.clearInterval(this.heartbeatInterval);
+ this.heartbeatInterval = this.manager.client.setInterval(() => this.sendHeartbeat(), time);
+ }
+
+ /**
+ * Sends a heartbeat to the WebSocket.
+ * If this shard didn't receive a heartbeat last time, it will destroy it and reconnect
+ * @param {string} [tag='HeartbeatTimer'] What caused this heartbeat to be sent
+ * @param {boolean} [ignoreHeartbeatAck] If we should send the heartbeat forcefully.
+ * @private
+ */
+ sendHeartbeat(
+ tag = 'HeartbeatTimer',
+ ignoreHeartbeatAck = [Status.WAITING_FOR_GUILDS, Status.IDENTIFYING, Status.RESUMING].includes(this.status),
+ ) {
+ if (ignoreHeartbeatAck && !this.lastHeartbeatAcked) {
+ this.debug(`[${tag}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);
+ } else if (!this.lastHeartbeatAcked) {
+ this.debug(
+ `[${tag}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.
+ Status : ${STATUS_KEYS[this.status]}
+ Sequence : ${this.sequence}
+ Connection State: ${this.connection ? CONNECTION_STATE[this.connection.readyState] : 'No Connection??'}`,
+ );
+
+ this.destroy({ closeCode: 4009, reset: true });
+ return;
+ }
+
+ this.debug(`[${tag}] Sending a heartbeat.`);
+ this.lastHeartbeatAcked = false;
+ this.lastPingTimestamp = Date.now();
+ this.send({ op: OPCodes.HEARTBEAT, d: this.sequence }, true);
+ }
+
+ /**
+ * Acknowledges a heartbeat.
+ * @private
+ */
+ ackHeartbeat() {
+ this.lastHeartbeatAcked = true;
+ const latency = Date.now() - this.lastPingTimestamp;
+ this.debug(`Heartbeat acknowledged, latency of ${latency}ms.`);
+ this.ping = latency;
+ }
+
+ /**
+ * Identifies the client on the connection.
+ * @private
+ * @returns {void}
+ */
+ identify() {
+ return this.sessionID ? this.identifyResume() : this.identifyNew();
+ }
+
+ /**
+ * Identifies as a new connection on the gateway.
+ * @private
+ */
+ identifyNew() {
+ const { client } = this.manager;
+ if (!client.token) {
+ this.debug('[IDENTIFY] No token available to identify a new session.');
+ return;
+ }
+
+ this.status = Status.IDENTIFYING;
+
+ // Clone the identify payload and assign the token and shard info
+ const d = {
+ ...client.options.ws,
+ token: client.token,
+ shard: [this.id, Number(client.options.shardCount)],
+ };
+
+ this.debug(`[IDENTIFY] Shard ${this.id}/${client.options.shardCount}`);
+ this.send({ op: OPCodes.IDENTIFY, d }, true);
+ }
+
+ /**
+ * Resumes a session on the gateway.
+ * @private
+ */
+ identifyResume() {
+ if (!this.sessionID) {
+ this.debug('[RESUME] No session ID was present; identifying as a new session.');
+ this.identifyNew();
+ return;
+ }
+
+ this.status = Status.RESUMING;
+
+ this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`);
+
+ const d = {
+ token: this.manager.client.token,
+ session_id: this.sessionID,
+ seq: this.closeSequence,
+ };
+
+ this.send({ op: OPCodes.RESUME, d }, true);
+ }
+
+ /**
+ * Adds a packet to the queue to be sent to the gateway.
+ * <warn>If you use this method, make sure you understand that you need to provide
+ * a full [Payload](https://discordapp.com/developers/docs/topics/gateway#commands-and-events-gateway-commands).
+ * Do not use this method if you don't know what you're doing.</warn>
+ * @param {Object} data The full packet to send
+ * @param {boolean} [important=false] If this packet should be added first in queue
+ */
+ send(data, important = false) {
+ this.ratelimit.queue[important ? 'unshift' : 'push'](data);
+ this.processQueue();
+ }
+
+ /**
+ * Sends data, bypassing the queue.
+ * @param {Object} data Packet to send
+ * @returns {void}
+ * @private
+ */
+ _send(data) {
+ if (!this.connection || this.connection.readyState !== WebSocket.OPEN) {
+ this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`);
+ this.destroy({ close: 4000 });
+ return;
+ }
+
+ this.connection.send(WebSocket.pack(data), err => {
+ if (err) this.manager.client.emit(Events.SHARD_ERROR, err, this.id);
+ });
+ }
+
+ /**
+ * Processes the current WebSocket queue.
+ * @returns {void}
+ * @private
+ */
+ processQueue() {
+ if (this.ratelimit.remaining === 0) return;
+ if (this.ratelimit.queue.length === 0) return;
+ if (this.ratelimit.remaining === this.ratelimit.total) {
+ this.ratelimit.timer = this.manager.client.setTimeout(() => {
+ this.ratelimit.remaining = this.ratelimit.total;
+ this.processQueue();
+ }, this.ratelimit.time);
+ }
+ while (this.ratelimit.remaining > 0) {
+ const item = this.ratelimit.queue.shift();
+ if (!item) return;
+ this._send(item);
+ this.ratelimit.remaining--;
+ }
+ }
+
+ /**
+ * Destroys this shard and closes its WebSocket connection.
+ * @param {Object} [options={ closeCode: 1000, reset: false, emit: true, log: true }] Options for destroying the shard
+ * @private
+ */
+ destroy({ closeCode = 1000, reset = false, emit = true, log = true } = {}) {
+ if (log) {
+ this.debug(`[DESTROY]
+ Close Code : ${closeCode}
+ Reset : ${reset}
+ Emit DESTROYED: ${emit}`);
+ }
+
+ // Step 0: Remove all timers
+ this.setHeartbeatTimer(-1);
+ this.setHelloTimeout(-1);
+
+ // Step 1: Close the WebSocket connection, if any, otherwise, emit DESTROYED
+ if (this.connection) {
+ // If the connection is currently opened, we will (hopefully) receive close
+ if (this.connection.readyState === WebSocket.OPEN) {
+ this.connection.close(closeCode);
+ } else {
+ // Connection is not OPEN
+ this.debug(`WS State: ${CONNECTION_STATE[this.connection.readyState]}`);
+ // Remove listeners from the connection
+ this._cleanupConnection();
+ // Attempt to close the connection just in case
+ try {
+ this.connection.close(closeCode);
+ } catch {
+ // No-op
+ }
+ // Emit the destroyed event if needed
+ if (emit) this._emitDestroyed();
+ }
+ } else if (emit) {
+ // We requested a destroy, but we had no connection. Emit destroyed
+ this._emitDestroyed();
+ }
+
+ // Step 2: Null the connection object
+ this.connection = null;
+
+ // Step 3: Set the shard status to DISCONNECTED
+ this.status = Status.DISCONNECTED;
+
+ // Step 4: Cache the old sequence (use to attempt a resume)
+ if (this.sequence !== -1) this.closeSequence = this.sequence;
+
+ // Step 5: Reset the sequence and session ID if requested
+ if (reset) {
+ this.sequence = -1;
+ this.sessionID = undefined;
+ }
+
+ // Step 6: reset the ratelimit data
+ this.ratelimit.remaining = this.ratelimit.total;
+ this.ratelimit.queue.length = 0;
+ if (this.ratelimit.timer) {
+ this.manager.client.clearTimeout(this.ratelimit.timer);
+ this.ratelimit.timer = null;
+ }
+ }
+
+ /**
+ * Cleans up the WebSocket connection listeners.
+ * @private
+ */
+ _cleanupConnection() {
+ this.connection.onopen = this.connection.onclose = this.connection.onerror = this.connection.onmessage = null;
+ }
+
+ /**
+ * Emits the DESTROYED event on the shard
+ * @private
+ */
+ _emitDestroyed() {
+ /**
+ * Emitted when a shard is destroyed, but no WebSocket connection was present.
+ * @private
+ * @event WebSocketShard#destroyed
+ */
+ this.emit(ShardEvents.DESTROYED);
+ }
+}
+
+module.exports = WebSocketShard;
diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js
new file mode 100644
index 0000000..d6d560d
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_CREATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.ChannelCreate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js
new file mode 100644
index 0000000..cb9f3d8
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_DELETE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.ChannelDelete.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js
new file mode 100644
index 0000000..13e6f0f
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }) => {
+ const channel = client.channels.cache.get(data.channel_id);
+ const time = new Date(data.last_pin_timestamp);
+
+ if (channel && !Number.isNaN(time.getTime())) {
+ // Discord sends null for last_pin_timestamp if the last pinned message was removed
+ channel.lastPinTimestamp = time.getTime() || null;
+
+ /**
+ * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event,
+ * not much information can be provided easily here - you need to manually check the pins yourself.
+ * @event Client#channelPinsUpdate
+ * @param {DMChannel|TextChannel} channel The channel that the pins update occurred in
+ * @param {Date} time The time of the pins update
+ */
+ client.emit(Events.CHANNEL_PINS_UPDATE, channel, time);
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js
new file mode 100644
index 0000000..d441478
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/CHANNEL_UPDATE.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, packet) => {
+ const { old, updated } = client.actions.ChannelUpdate.handle(packet.d);
+ if (old && updated) {
+ /**
+ * Emitted whenever a channel is updated - e.g. name change, topic change, channel type change.
+ * @event Client#channelUpdate
+ * @param {DMChannel|GuildChannel} oldChannel The channel before the update
+ * @param {DMChannel|GuildChannel} newChannel The channel after the update
+ */
+ client.emit(Events.CHANNEL_UPDATE, old, updated);
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js
new file mode 100644
index 0000000..5d4a096
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_ADD.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }) => {
+ const guild = client.guilds.cache.get(data.guild_id);
+ const user = client.users.add(data.user);
+
+ /**
+ * Emitted whenever a member is banned from a guild.
+ * @event Client#guildBanAdd
+ * @param {Guild} guild The guild that the ban occurred in
+ * @param {User} user The user that was banned
+ */
+ if (guild && user) client.emit(Events.GUILD_BAN_ADD, guild, user);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js
new file mode 100644
index 0000000..8389e46
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_BAN_REMOVE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildBanRemove.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js
new file mode 100644
index 0000000..6743204
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_CREATE.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const { Events, Status } = require('../../../util/Constants');
+
+module.exports = async (client, { d: data }, shard) => {
+ let guild = client.guilds.cache.get(data.id);
+ if (guild) {
+ if (!guild.available && !data.unavailable) {
+ // A newly available guild
+ guild._patch(data);
+ // If the client was ready before and we had unavailable guilds, fetch them
+ if (client.ws.status === Status.READY && client.options.fetchAllMembers) {
+ await guild.members
+ .fetch()
+ .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`));
+ }
+ }
+ } else {
+ // A new guild
+ data.shardID = shard.id;
+ guild = client.guilds.add(data);
+ if (client.ws.status === Status.READY) {
+ /**
+ * Emitted whenever the client joins a guild.
+ * @event Client#guildCreate
+ * @param {Guild} guild The created guild
+ */
+ if (client.options.fetchAllMembers) {
+ await guild.members
+ .fetch()
+ .catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`));
+ }
+ client.emit(Events.GUILD_CREATE, guild);
+ }
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js
new file mode 100644
index 0000000..27a3256
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_DELETE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildDelete.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js
new file mode 100644
index 0000000..e23b671
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildEmojisUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js
new file mode 100644
index 0000000..e90a72c
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildIntegrationsUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js
new file mode 100644
index 0000000..3ceb622
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const Collection = require('../../../util/Collection');
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }) => {
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (!guild) return;
+ const members = new Collection();
+
+ for (const member of data.members) members.set(member.user.id, guild.members.add(member));
+ if (data.presences) {
+ for (const presence of data.presences) guild.presences.cache.add(Object.assign(presence, { guild }));
+ }
+ /**
+ * Emitted whenever a chunk of guild members is received (all members come from the same guild).
+ * @event Client#guildMembersChunk
+ * @param {Collection<Snowflake, GuildMember>} members The members in the chunk
+ * @param {Guild} guild The guild related to the member chunk
+ */
+ client.emit(Events.GUILD_MEMBERS_CHUNK, members, guild);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js
new file mode 100644
index 0000000..5128756
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_ADD.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const { Events, Status } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }, shard) => {
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ guild.memberCount++;
+ const member = guild.members.add(data);
+ if (shard.status === Status.READY) {
+ /**
+ * Emitted whenever a user joins a guild.
+ * @event Client#guildMemberAdd
+ * @param {GuildMember} member The member that has joined a guild
+ */
+ client.emit(Events.GUILD_MEMBER_ADD, member);
+ }
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js
new file mode 100644
index 0000000..72432af
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet, shard) => {
+ client.actions.GuildMemberRemove.handle(packet.d, shard);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js
new file mode 100644
index 0000000..92c9da6
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const { Status, Events } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }, shard) => {
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ const member = guild.members.cache.get(data.user.id);
+ if (member) {
+ const old = member._update(data);
+ if (shard.status === Status.READY) {
+ /**
+ * Emitted whenever a guild member changes - i.e. new role, removed role, nickname.
+ * @event Client#guildMemberUpdate
+ * @param {GuildMember} oldMember The member before the update
+ * @param {GuildMember} newMember The member after the update
+ */
+ client.emit(Events.GUILD_MEMBER_UPDATE, old, member);
+ }
+ }
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js
new file mode 100644
index 0000000..da9e7bc
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_CREATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildRoleCreate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js
new file mode 100644
index 0000000..cdc6353
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_DELETE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildRoleDelete.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js
new file mode 100644
index 0000000..3a9b62e
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildRoleUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js
new file mode 100644
index 0000000..fd0012a
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/GUILD_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.GuildUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js
new file mode 100644
index 0000000..50a2e72
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/INVITE_CREATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.InviteCreate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js
new file mode 100644
index 0000000..5971852
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/INVITE_DELETE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.InviteDelete.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js
new file mode 100644
index 0000000..c9b79a8
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_CREATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageCreate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js
new file mode 100644
index 0000000..85ae2bc
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageDelete.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js
new file mode 100644
index 0000000..fbcf80f
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageDeleteBulk.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js
new file mode 100644
index 0000000..e219b4a
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageReactionAdd.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js
new file mode 100644
index 0000000..2980e69
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageReactionRemove.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js
new file mode 100644
index 0000000..ead80f7
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageReactionRemoveAll.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js
new file mode 100644
index 0000000..579444c
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.MessageReactionRemoveEmoji.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js
new file mode 100644
index 0000000..7428e90
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/MESSAGE_UPDATE.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, packet) => {
+ const { old, updated } = client.actions.MessageUpdate.handle(packet.d);
+ if (old && updated) {
+ /**
+ * Emitted whenever a message is updated - e.g. embed or content change.
+ * @event Client#messageUpdate
+ * @param {Message} oldMessage The message before the update
+ * @param {Message} newMessage The message after the update
+ */
+ client.emit(Events.MESSAGE_UPDATE, old, updated);
+ }
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js
new file mode 100644
index 0000000..bde3629
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/PRESENCE_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.PresenceUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/READY.js b/node_modules/discord.js/src/client/websocket/handlers/READY.js
new file mode 100644
index 0000000..c38b681
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/READY.js
@@ -0,0 +1,21 @@
+'use strict';
+
+let ClientUser;
+
+module.exports = (client, { d: data }, shard) => {
+ if (client.user) {
+ client.user._patch(data.user);
+ } else {
+ if (!ClientUser) ClientUser = require('../../../structures/ClientUser');
+ const clientUser = new ClientUser(client, data.user);
+ client.user = clientUser;
+ client.users.cache.set(clientUser.id, clientUser);
+ }
+
+ for (const guild of data.guilds) {
+ guild.shardID = shard.id;
+ client.guilds.add(guild);
+ }
+
+ shard.checkReady();
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js
new file mode 100644
index 0000000..5e5f403
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/RESUMED.js
@@ -0,0 +1,14 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, packet, shard) => {
+ const replayed = shard.sequence - shard.closeSequence;
+ /**
+ * Emitted when a shard resumes successfully.
+ * @event Client#shardResume
+ * @param {number} id The shard ID that resumed
+ * @param {number} replayedEvents The amount of replayed events
+ */
+ client.emit(Events.SHARD_RESUME, shard.id, replayed);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js b/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js
new file mode 100644
index 0000000..86fb26b
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/TYPING_START.js
@@ -0,0 +1,49 @@
+'use strict';
+
+const { Events } = require('../../../util/Constants');
+
+module.exports = (client, { d: data }) => {
+ const channel = client.channels.cache.get(data.channel_id);
+ const user = client.users.cache.get(data.user_id);
+ const timestamp = new Date(data.timestamp * 1000);
+
+ if (channel && user) {
+ if (channel.type === 'voice') {
+ client.emit(Events.WARN, `Discord sent a typing packet to a voice channel ${channel.id}`);
+ return;
+ }
+
+ if (channel._typing.has(user.id)) {
+ const typing = channel._typing.get(user.id);
+
+ typing.lastTimestamp = timestamp;
+ typing.elapsedTime = Date.now() - typing.since;
+ client.clearTimeout(typing.timeout);
+ typing.timeout = tooLate(channel, user);
+ } else {
+ const since = new Date();
+ const lastTimestamp = new Date();
+ channel._typing.set(user.id, {
+ user,
+ since,
+ lastTimestamp,
+ elapsedTime: Date.now() - since,
+ timeout: tooLate(channel, user),
+ });
+
+ /**
+ * Emitted whenever a user starts typing in a channel.
+ * @event Client#typingStart
+ * @param {Channel} channel The channel the user started typing in
+ * @param {User} user The user that started typing
+ */
+ client.emit(Events.TYPING_START, channel, user);
+ }
+ }
+};
+
+function tooLate(channel, user) {
+ return channel.client.setTimeout(() => {
+ channel._typing.delete(user.id);
+ }, 10000);
+}
diff --git a/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js
new file mode 100644
index 0000000..a02bf58
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/USER_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.UserUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js
new file mode 100644
index 0000000..f9cf534
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js
@@ -0,0 +1,6 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.emit('debug', `[VOICE] received voice server: ${JSON.stringify(packet)}`);
+ client.voice.onVoiceServer(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js
new file mode 100644
index 0000000..dbff6ea
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/VOICE_STATE_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.VoiceStateUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js b/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js
new file mode 100644
index 0000000..46cacee
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/WEBHOOKS_UPDATE.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = (client, packet) => {
+ client.actions.WebhooksUpdate.handle(packet.d);
+};
diff --git a/node_modules/discord.js/src/client/websocket/handlers/index.js b/node_modules/discord.js/src/client/websocket/handlers/index.js
new file mode 100644
index 0000000..d69c105
--- /dev/null
+++ b/node_modules/discord.js/src/client/websocket/handlers/index.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const { WSEvents } = require('../../../util/Constants');
+
+const handlers = {};
+
+for (const name of Object.keys(WSEvents)) {
+ try {
+ handlers[name] = require(`./${name}.js`);
+ } catch {} // eslint-disable-line no-empty
+}
+
+module.exports = handlers;
diff --git a/node_modules/discord.js/src/errors/DJSError.js b/node_modules/discord.js/src/errors/DJSError.js
new file mode 100644
index 0000000..157ca66
--- /dev/null
+++ b/node_modules/discord.js/src/errors/DJSError.js
@@ -0,0 +1,61 @@
+'use strict';
+
+// Heavily inspired by node's `internal/errors` module
+
+const kCode = Symbol('code');
+const messages = new Map();
+
+/**
+ * Extend an error of some sort into a DiscordjsError.
+ * @param {Error} Base Base error to extend
+ * @returns {DiscordjsError}
+ */
+function makeDiscordjsError(Base) {
+ return class DiscordjsError extends Base {
+ constructor(key, ...args) {
+ super(message(key, args));
+ this[kCode] = key;
+ if (Error.captureStackTrace) Error.captureStackTrace(this, DiscordjsError);
+ }
+
+ get name() {
+ return `${super.name} [${this[kCode]}]`;
+ }
+
+ get code() {
+ return this[kCode];
+ }
+ };
+}
+
+/**
+ * Format the message for an error.
+ * @param {string} key Error key
+ * @param {Array<*>} args Arguments to pass for util format or as function args
+ * @returns {string} Formatted string
+ */
+function message(key, args) {
+ if (typeof key !== 'string') throw new Error('Error message key must be a string');
+ const msg = messages.get(key);
+ if (!msg) throw new Error(`An invalid error message key was used: ${key}.`);
+ if (typeof msg === 'function') return msg(...args);
+ if (args === undefined || args.length === 0) return msg;
+ args.unshift(msg);
+ return String(...args);
+}
+
+/**
+ * Register an error code and message.
+ * @param {string} sym Unique name for the error
+ * @param {*} val Value of the error
+ */
+function register(sym, val) {
+ messages.set(sym, typeof val === 'function' ? val : String(val));
+}
+
+module.exports = {
+ register,
+ Error: makeDiscordjsError(Error),
+ TypeError: makeDiscordjsError(TypeError),
+ RangeError: makeDiscordjsError(RangeError),
+};
diff --git a/node_modules/discord.js/src/errors/Messages.js b/node_modules/discord.js/src/errors/Messages.js
new file mode 100644
index 0000000..5b4299d
--- /dev/null
+++ b/node_modules/discord.js/src/errors/Messages.js
@@ -0,0 +1,104 @@
+'use strict';
+
+const { register } = require('./DJSError');
+
+const Messages = {
+ CLIENT_INVALID_OPTION: (prop, must) => `The ${prop} option must be ${must}`,
+ CLIENT_INVALID_PROVIDED_SHARDS: 'None of the provided shards were valid.',
+
+ TOKEN_INVALID: 'An invalid token was provided.',
+ TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.',
+
+ WS_CLOSE_REQUESTED: 'WebSocket closed due to user request.',
+ WS_CONNECTION_EXISTS: 'There is already an existing WebSocket connection.',
+ WS_NOT_OPEN: (data = 'data') => `Websocket not open to send ${data}`,
+
+ BITFIELD_INVALID: 'Invalid bitfield flag or number.',
+
+ SHARDING_INVALID: 'Invalid shard settings were provided.',
+ SHARDING_REQUIRED: 'This session would have handled too many guilds - Sharding is required.',
+ INVALID_INTENTS: 'Invalid intent provided for WebSocket intents.',
+ DISALLOWED_INTENTS: 'Privileged intent provided is not enabled or whitelisted.',
+ SHARDING_NO_SHARDS: 'No shards have been spawned.',
+ SHARDING_IN_PROCESS: 'Shards are still being spawned.',
+ SHARDING_ALREADY_SPAWNED: count => `Already spawned ${count} shards.`,
+ SHARDING_PROCESS_EXISTS: id => `Shard ${id} already has an active process.`,
+ SHARDING_READY_TIMEOUT: id => `Shard ${id}'s Client took too long to become ready.`,
+ SHARDING_READY_DISCONNECTED: id => `Shard ${id}'s Client disconnected before becoming ready.`,
+ SHARDING_READY_DIED: id => `Shard ${id}'s process exited before its Client became ready.`,
+
+ COLOR_RANGE: 'Color must be within the range 0 - 16777215 (0xFFFFFF).',
+ COLOR_CONVERT: 'Unable to convert color to a number.',
+
+ EMBED_FIELD_NAME: 'MessageEmbed field names may not be empty.',
+ EMBED_FIELD_VALUE: 'MessageEmbed field values may not be empty.',
+
+ FILE_NOT_FOUND: file => `File could not be found: ${file}`,
+
+ USER_NO_DMCHANNEL: 'No DM Channel exists!',
+
+ VOICE_INVALID_HEARTBEAT: 'Tried to set voice heartbeat but no valid interval was specified.',
+ VOICE_USER_MISSING: "Couldn't resolve the user to create stream.",
+ VOICE_JOIN_CHANNEL: (full = false) =>
+ `You do not have permission to join this voice channel${full ? '; it is full.' : '.'}`,
+ VOICE_CONNECTION_TIMEOUT: 'Connection not established within 15 seconds.',
+ VOICE_TOKEN_ABSENT: 'Token not provided from voice server packet.',
+ VOICE_SESSION_ABSENT: 'Session ID not supplied.',
+ VOICE_INVALID_ENDPOINT: 'Invalid endpoint received.',
+ VOICE_NO_BROWSER: 'Voice connections are not available in browsers.',
+ VOICE_CONNECTION_ATTEMPTS_EXCEEDED: attempts => `Too many connection attempts (${attempts}).`,
+ VOICE_JOIN_SOCKET_CLOSED: 'Tried to send join packet, but the WebSocket is not open.',
+ VOICE_PLAY_INTERFACE_NO_BROADCAST: 'A broadcast cannot be played in this context.',
+ VOICE_PLAY_INTERFACE_BAD_TYPE: 'Unknown stream type',
+ VOICE_PRISM_DEMUXERS_NEED_STREAM: 'To play a webm/ogg stream, you need to pass a ReadableStream.',
+
+ VOICE_STATE_UNCACHED_MEMBER: 'The member of this voice state is uncached.',
+ VOICE_STATE_NOT_OWN: 'You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.',
+ VOICE_STATE_INVALID_TYPE: name => `${name} must be a boolean.`,
+
+ UDP_SEND_FAIL: 'Tried to send a UDP packet, but there is no socket available.',
+ UDP_ADDRESS_MALFORMED: 'Malformed UDP address or port.',
+ UDP_CONNECTION_EXISTS: 'There is already an existing UDP connection.',
+
+ REQ_RESOURCE_TYPE: 'The resource must be a string, Buffer or a valid file stream.',
+
+ IMAGE_FORMAT: format => `Invalid image format: ${format}`,
+ IMAGE_SIZE: size => `Invalid image size: ${size}`,
+
+ MESSAGE_BULK_DELETE_TYPE: 'The messages must be an Array, Collection, or number.',
+ MESSAGE_NONCE_TYPE: 'Message nonce must fit in an unsigned 64-bit integer.',
+
+ TYPING_COUNT: 'Count must be at least 1',
+
+ SPLIT_MAX_LEN: 'Chunk exceeds the max length and contains no split characters.',
+
+ BAN_RESOLVE_ID: (ban = false) => `Couldn't resolve the user ID to ${ban ? 'ban' : 'unban'}.`,
+ FETCH_BAN_RESOLVE_ID: "Couldn't resolve the user ID to fetch the ban.",
+
+ PRUNE_DAYS_TYPE: 'Days must be a number',
+
+ GUILD_CHANNEL_RESOLVE: 'Could not resolve channel to a guild channel.',
+ GUILD_VOICE_CHANNEL_RESOLVE: 'Could not resolve channel to a guild voice channel.',
+ GUILD_CHANNEL_ORPHAN: 'Could not find a parent to this guild channel.',
+ GUILD_OWNED: 'Guild is owned by the client.',
+ GUILD_MEMBERS_TIMEOUT: "Members didn't arrive in time.",
+ GUILD_UNCACHED_ME: 'The client user as a member of this guild is uncached.',
+
+ INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`,
+
+ WEBHOOK_MESSAGE: 'The message was not sent by a webhook.',
+
+ EMOJI_TYPE: 'Emoji must be a string or GuildEmoji/ReactionEmoji',
+ EMOJI_MANAGED: 'Emoji is managed and has no Author.',
+ MISSING_MANAGE_EMOJIS_PERMISSION: guild =>
+ `Client must have Manage Emoji permission in guild ${guild} to see emoji authors.`,
+
+ REACTION_RESOLVE_USER: "Couldn't resolve the user ID to remove from the reaction.",
+
+ VANITY_URL: 'This guild does not have the VANITY_URL feature enabled.',
+
+ DELETE_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot delete them",
+ FETCH_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot fetch them",
+};
+
+for (const [name, message] of Object.entries(Messages)) register(name, message);
diff --git a/node_modules/discord.js/src/errors/index.js b/node_modules/discord.js/src/errors/index.js
new file mode 100644
index 0000000..c94ddc7
--- /dev/null
+++ b/node_modules/discord.js/src/errors/index.js
@@ -0,0 +1,4 @@
+'use strict';
+
+module.exports = require('./DJSError');
+module.exports.Messages = require('./Messages');
diff --git a/node_modules/discord.js/src/index.js b/node_modules/discord.js/src/index.js
new file mode 100644
index 0000000..edce6e8
--- /dev/null
+++ b/node_modules/discord.js/src/index.js
@@ -0,0 +1,105 @@
+'use strict';
+
+const Util = require('./util/Util');
+
+module.exports = {
+ // "Root" classes (starting points)
+ BaseClient: require('./client/BaseClient'),
+ Client: require('./client/Client'),
+ Shard: require('./sharding/Shard'),
+ ShardClientUtil: require('./sharding/ShardClientUtil'),
+ ShardingManager: require('./sharding/ShardingManager'),
+ WebhookClient: require('./client/WebhookClient'),
+
+ // Utilities
+ ActivityFlags: require('./util/ActivityFlags'),
+ BitField: require('./util/BitField'),
+ Collection: require('./util/Collection'),
+ Constants: require('./util/Constants'),
+ DataResolver: require('./util/DataResolver'),
+ BaseManager: require('./managers/BaseManager'),
+ DiscordAPIError: require('./rest/DiscordAPIError'),
+ HTTPError: require('./rest/HTTPError'),
+ MessageFlags: require('./util/MessageFlags'),
+ Intents: require('./util/Intents'),
+ Permissions: require('./util/Permissions'),
+ Speaking: require('./util/Speaking'),
+ Snowflake: require('./util/Snowflake'),
+ SnowflakeUtil: require('./util/Snowflake'),
+ Structures: require('./util/Structures'),
+ SystemChannelFlags: require('./util/SystemChannelFlags'),
+ UserFlags: require('./util/UserFlags'),
+ Util: Util,
+ version: require('../package.json').version,
+
+ // Managers
+ ChannelManager: require('./managers/ChannelManager'),
+ GuildChannelManager: require('./managers/GuildChannelManager'),
+ GuildEmojiManager: require('./managers/GuildEmojiManager'),
+ GuildEmojiRoleManager: require('./managers/GuildEmojiRoleManager'),
+ GuildMemberManager: require('./managers/GuildMemberManager'),
+ GuildMemberRoleManager: require('./managers/GuildMemberRoleManager'),
+ GuildManager: require('./managers/GuildManager'),
+ ReactionUserManager: require('./managers/ReactionUserManager'),
+ MessageManager: require('./managers/MessageManager'),
+ PresenceManager: require('./managers/PresenceManager'),
+ RoleManager: require('./managers/RoleManager'),
+ UserManager: require('./managers/UserManager'),
+
+ // Shortcuts to Util methods
+ discordSort: Util.discordSort,
+ escapeMarkdown: Util.escapeMarkdown,
+ fetchRecommendedShards: Util.fetchRecommendedShards,
+ resolveColor: Util.resolveColor,
+ resolveString: Util.resolveString,
+ splitMessage: Util.splitMessage,
+
+ // Structures
+ Base: require('./structures/Base'),
+ Activity: require('./structures/Presence').Activity,
+ APIMessage: require('./structures/APIMessage'),
+ BaseGuildEmoji: require('./structures/BaseGuildEmoji'),
+ CategoryChannel: require('./structures/CategoryChannel'),
+ Channel: require('./structures/Channel'),
+ ClientApplication: require('./structures/ClientApplication'),
+ get ClientUser() {
+ // This is a getter so that it properly extends any custom User class
+ return require('./structures/ClientUser');
+ },
+ Collector: require('./structures/interfaces/Collector'),
+ DMChannel: require('./structures/DMChannel'),
+ Emoji: require('./structures/Emoji'),
+ Guild: require('./structures/Guild'),
+ GuildAuditLogs: require('./structures/GuildAuditLogs'),
+ GuildChannel: require('./structures/GuildChannel'),
+ GuildEmoji: require('./structures/GuildEmoji'),
+ GuildMember: require('./structures/GuildMember'),
+ GuildPreview: require('./structures/GuildPreview'),
+ Integration: require('./structures/Integration'),
+ Invite: require('./structures/Invite'),
+ Message: require('./structures/Message'),
+ MessageAttachment: require('./structures/MessageAttachment'),
+ MessageCollector: require('./structures/MessageCollector'),
+ MessageEmbed: require('./structures/MessageEmbed'),
+ MessageMentions: require('./structures/MessageMentions'),
+ MessageReaction: require('./structures/MessageReaction'),
+ NewsChannel: require('./structures/NewsChannel'),
+ PermissionOverwrites: require('./structures/PermissionOverwrites'),
+ Presence: require('./structures/Presence').Presence,
+ ClientPresence: require('./structures/ClientPresence'),
+ ReactionCollector: require('./structures/ReactionCollector'),
+ ReactionEmoji: require('./structures/ReactionEmoji'),
+ RichPresenceAssets: require('./structures/Presence').RichPresenceAssets,
+ Role: require('./structures/Role'),
+ StoreChannel: require('./structures/StoreChannel'),
+ Team: require('./structures/Team'),
+ TeamMember: require('./structures/TeamMember'),
+ TextChannel: require('./structures/TextChannel'),
+ User: require('./structures/User'),
+ VoiceChannel: require('./structures/VoiceChannel'),
+ VoiceRegion: require('./structures/VoiceRegion'),
+ VoiceState: require('./structures/VoiceState'),
+ Webhook: require('./structures/Webhook'),
+
+ WebSocket: require('./WebSocket'),
+};
diff --git a/node_modules/discord.js/src/managers/BaseManager.js b/node_modules/discord.js/src/managers/BaseManager.js
new file mode 100644
index 0000000..c11d191
--- /dev/null
+++ b/node_modules/discord.js/src/managers/BaseManager.js
@@ -0,0 +1,81 @@
+'use strict';
+
+const Collection = require('../util/Collection');
+let Structures;
+
+/**
+ * Manages the API methods of a data model and holds its cache.
+ * @abstract
+ */
+class BaseManager {
+ constructor(client, iterable, holds, cacheType = Collection, ...cacheOptions) {
+ if (!Structures) Structures = require('../util/Structures');
+ /**
+ * The data structure belonging to this manager
+ * @name BaseManager#holds
+ * @type {Function}
+ * @private
+ * @readonly
+ */
+ Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) || holds });
+
+ /**
+ * The client that instantiated this Manager
+ * @name BaseManager#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+
+ /**
+ * The type of Collection of the Manager
+ * @type {Collection}
+ */
+ this.cacheType = cacheType;
+
+ /**
+ * Holds the cache for the data model
+ * @type {Collection}
+ */
+ this.cache = new cacheType(...cacheOptions);
+ if (iterable) for (const i of iterable) this.add(i);
+ }
+
+ add(data, cache = true, { id, extras = [] } = {}) {
+ const existing = this.cache.get(id || data.id);
+ if (existing && existing._patch && cache) existing._patch(data);
+ if (existing) return existing;
+
+ const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
+ if (cache) this.cache.set(id || entry.id, entry);
+ return entry;
+ }
+
+ /**
+ * Resolves a data entry to a data Object.
+ * @param {string|Object} idOrInstance The id or instance of something in this Manager
+ * @returns {?Object} An instance from this Manager
+ */
+ resolve(idOrInstance) {
+ if (idOrInstance instanceof this.holds) return idOrInstance;
+ if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) || null;
+ return null;
+ }
+
+ /**
+ * Resolves a data entry to a instance ID.
+ * @param {string|Object} idOrInstance The id or instance of something in this Manager
+ * @returns {?Snowflake}
+ */
+ resolveID(idOrInstance) {
+ if (idOrInstance instanceof this.holds) return idOrInstance.id;
+ if (typeof idOrInstance === 'string') return idOrInstance;
+ return null;
+ }
+
+ valueOf() {
+ return this.cache;
+ }
+}
+
+module.exports = BaseManager;
diff --git a/node_modules/discord.js/src/managers/ChannelManager.js b/node_modules/discord.js/src/managers/ChannelManager.js
new file mode 100644
index 0000000..99fde10
--- /dev/null
+++ b/node_modules/discord.js/src/managers/ChannelManager.js
@@ -0,0 +1,93 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const Channel = require('../structures/Channel');
+const { Events } = require('../util/Constants');
+
+/**
+ * A manager of channels belonging to a client
+ * @extends {BaseManager}
+ */
+class ChannelManager extends BaseManager {
+ constructor(client, iterable) {
+ super(client, iterable, Channel);
+ }
+
+ /**
+ * The cache of Channels
+ * @type {Collection<Snowflake, Channel>}
+ * @name ChannelManager#cache
+ */
+
+ add(data, guild, cache = true) {
+ const existing = this.cache.get(data.id);
+ if (existing) {
+ if (existing._patch && cache) existing._patch(data);
+ if (guild) guild.channels.add(existing);
+ return existing;
+ }
+
+ const channel = Channel.create(this.client, data, guild);
+
+ if (!channel) {
+ this.client.emit(Events.DEBUG, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`);
+ return null;
+ }
+
+ if (cache) this.cache.set(channel.id, channel);
+
+ return channel;
+ }
+
+ remove(id) {
+ const channel = this.cache.get(id);
+ if (channel.guild) channel.guild.channels.cache.delete(id);
+ this.cache.delete(id);
+ }
+
+ /**
+ * Data that can be resolved to give a Channel object. This can be:
+ * * A Channel object
+ * * A Snowflake
+ * @typedef {Channel|Snowflake} ChannelResolvable
+ */
+
+ /**
+ * Resolves a ChannelResolvable to a Channel object.
+ * @method resolve
+ * @memberof ChannelManager
+ * @instance
+ * @param {ChannelResolvable} channel The channel resolvable to resolve
+ * @returns {?Channel}
+ */
+
+ /**
+ * Resolves a ChannelResolvable to a channel ID string.
+ * @method resolveID
+ * @memberof ChannelManager
+ * @instance
+ * @param {ChannelResolvable} channel The channel resolvable to resolve
+ * @returns {?Snowflake}
+ */
+
+ /**
+ * Obtains a channel from Discord, or the channel cache if it's already available.
+ * @param {Snowflake} id ID of the channel
+ * @param {boolean} [cache=true] Whether to cache the new channel object if it isn't already
+ * @returns {Promise<Channel>}
+ * @example
+ * // Fetch a channel by its id
+ * client.channels.fetch('222109930545610754')
+ * .then(channel => console.log(channel.name))
+ * .catch(console.error);
+ */
+ async fetch(id, cache = true) {
+ const existing = this.cache.get(id);
+ if (existing && !existing.partial) return existing;
+
+ const data = await this.client.api.channels(id).get();
+ return this.add(data, null, cache);
+ }
+}
+
+module.exports = ChannelManager;
diff --git a/node_modules/discord.js/src/managers/GuildChannelManager.js b/node_modules/discord.js/src/managers/GuildChannelManager.js
new file mode 100644
index 0000000..bc72e9a
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildChannelManager.js
@@ -0,0 +1,131 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const GuildChannel = require('../structures/GuildChannel');
+const PermissionOverwrites = require('../structures/PermissionOverwrites');
+const { ChannelTypes } = require('../util/Constants');
+
+/**
+ * Manages API methods for GuildChannels and stores their cache.
+ * @extends {BaseManager}
+ */
+class GuildChannelManager extends BaseManager {
+ constructor(guild, iterable) {
+ super(guild.client, iterable, GuildChannel);
+
+ /**
+ * The guild this Manager belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ /**
+ * The cache of this Manager
+ * @type {Collection<Snowflake, GuildChannel>}
+ * @name GuildChannelManager#cache
+ */
+
+ add(channel) {
+ const existing = this.cache.get(channel.id);
+ if (existing) return existing;
+ this.cache.set(channel.id, channel);
+ return channel;
+ }
+
+ /**
+ * Data that can be resolved to give a Guild Channel object. This can be:
+ * * A GuildChannel object
+ * * A Snowflake
+ * @typedef {GuildChannel|Snowflake} GuildChannelResolvable
+ */
+
+ /**
+ * Resolves a GuildChannelResolvable to a Channel object.
+ * @method resolve
+ * @memberof GuildChannelManager
+ * @instance
+ * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
+ * @returns {?Channel}
+ */
+
+ /**
+ * Resolves a GuildChannelResolvable to a channel ID string.
+ * @method resolveID
+ * @memberof GuildChannelManager
+ * @instance
+ * @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
+ * @returns {?Snowflake}
+ */
+
+ /**
+ * Creates a new channel in the guild.
+ * @param {string} name The name of the new channel
+ * @param {Object} [options] Options
+ * @param {string} [options.type='text'] The type of the new channel, either `text`, `voice`, or `category`
+ * @param {string} [options.topic] The topic for the new channel
+ * @param {boolean} [options.nsfw] Whether the new channel is nsfw
+ * @param {number} [options.bitrate] Bitrate of the new channel in bits (only voice)
+ * @param {number} [options.userLimit] Maximum amount of users allowed in the new channel (only voice)
+ * @param {ChannelResolvable} [options.parent] Parent of the new channel
+ * @param {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [options.permissionOverwrites]
+ * Permission overwrites of the new channel
+ * @param {number} [options.position] Position of the new channel
+ * @param {number} [options.rateLimitPerUser] The ratelimit per user for the channel
+ * @param {string} [options.reason] Reason for creating the channel
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Create a new text channel
+ * guild.channels.create('new-general', { reason: 'Needed a cool new channel' })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Create a new channel with permission overwrites
+ * guild.channels.create('new-voice', {
+ * type: 'voice',
+ * permissionOverwrites: [
+ * {
+ * id: message.author.id,
+ * deny: ['VIEW_CHANNEL'],
+ * },
+ * ],
+ * })
+ */
+ async create(name, options = {}) {
+ let {
+ type,
+ topic,
+ nsfw,
+ bitrate,
+ userLimit,
+ parent,
+ permissionOverwrites,
+ position,
+ rateLimitPerUser,
+ reason,
+ } = options;
+ if (parent) parent = this.client.channels.resolveID(parent);
+ if (permissionOverwrites) {
+ permissionOverwrites = permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
+ }
+
+ const data = await this.client.api.guilds(this.guild.id).channels.post({
+ data: {
+ name,
+ topic,
+ type: type ? ChannelTypes[type.toUpperCase()] : ChannelTypes.TEXT,
+ nsfw,
+ bitrate,
+ user_limit: userLimit,
+ parent_id: parent,
+ position,
+ permission_overwrites: permissionOverwrites,
+ rate_limit_per_user: rateLimitPerUser,
+ },
+ reason,
+ });
+ return this.client.actions.ChannelCreate.handle(data).channel;
+ }
+}
+
+module.exports = GuildChannelManager;
diff --git a/node_modules/discord.js/src/managers/GuildEmojiManager.js b/node_modules/discord.js/src/managers/GuildEmojiManager.js
new file mode 100644
index 0000000..c13ad13
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildEmojiManager.js
@@ -0,0 +1,129 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const { TypeError } = require('../errors');
+const GuildEmoji = require('../structures/GuildEmoji');
+const ReactionEmoji = require('../structures/ReactionEmoji');
+const Collection = require('../util/Collection');
+const DataResolver = require('../util/DataResolver');
+
+/**
+ * Manages API methods for GuildEmojis and stores their cache.
+ * @extends {BaseManager}
+ */
+class GuildEmojiManager extends BaseManager {
+ constructor(guild, iterable) {
+ super(guild.client, iterable, GuildEmoji);
+ /**
+ * The guild this manager belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ /**
+ * The cache of GuildEmojis
+ * @type {Collection<Snowflake, GuildEmoji>}
+ * @name GuildEmojiManager#cache
+ */
+
+ add(data, cache) {
+ return super.add(data, cache, { extras: [this.guild] });
+ }
+
+ /**
+ * Creates a new custom emoji in the guild.
+ * @param {BufferResolvable|Base64Resolvable} attachment The image for the emoji
+ * @param {string} name The name for the emoji
+ * @param {Object} [options] Options
+ * @param {Collection<Snowflake, Role>|RoleResolvable[]} [options.roles] Roles to limit the emoji to
+ * @param {string} [options.reason] Reason for creating the emoji
+ * @returns {Promise<Emoji>} The created emoji
+ * @example
+ * // Create a new emoji from a url
+ * guild.emojis.create('https://i.imgur.com/w3duR07.png', 'rip')
+ * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
+ * .catch(console.error);
+ * @example
+ * // Create a new emoji from a file on your computer
+ * guild.emojis.create('./memes/banana.png', 'banana')
+ * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
+ * .catch(console.error);
+ */
+ async create(attachment, name, { roles, reason } = {}) {
+ attachment = await DataResolver.resolveImage(attachment);
+ if (!attachment) throw new TypeError('REQ_RESOURCE_TYPE');
+
+ const data = { image: attachment, name };
+ if (roles) {
+ data.roles = [];
+ for (let role of roles instanceof Collection ? roles.values() : roles) {
+ role = this.guild.roles.resolve(role);
+ if (!role) {
+ return Promise.reject(
+ new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true),
+ );
+ }
+ data.roles.push(role.id);
+ }
+ }
+
+ return this.client.api
+ .guilds(this.guild.id)
+ .emojis.post({ data, reason })
+ .then(emoji => this.client.actions.GuildEmojiCreate.handle(this.guild, emoji).emoji);
+ }
+
+ /**
+ * Data that can be resolved into an GuildEmoji object. This can be:
+ * * A custom emoji ID
+ * * A GuildEmoji object
+ * * A ReactionEmoji object
+ * @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable
+ */
+
+ /**
+ * Resolves an EmojiResolvable to an Emoji object.
+ * @param {EmojiResolvable} emoji The Emoji resolvable to identify
+ * @returns {?GuildEmoji}
+ */
+ resolve(emoji) {
+ if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id);
+ return super.resolve(emoji);
+ }
+
+ /**
+ * Resolves an EmojiResolvable to an Emoji ID string.
+ * @param {EmojiResolvable} emoji The Emoji resolvable to identify
+ * @returns {?Snowflake}
+ */
+ resolveID(emoji) {
+ if (emoji instanceof ReactionEmoji) return emoji.id;
+ return super.resolveID(emoji);
+ }
+
+ /**
+ * Data that can be resolved to give an emoji identifier. This can be:
+ * * The unicode representation of an emoji
+ * * An EmojiResolvable
+ * @typedef {string|EmojiResolvable} EmojiIdentifierResolvable
+ */
+
+ /**
+ * Resolves an EmojiResolvable to an emoji identifier.
+ * @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve
+ * @returns {?string}
+ */
+ resolveIdentifier(emoji) {
+ const emojiResolvable = this.resolve(emoji);
+ if (emojiResolvable) return emojiResolvable.identifier;
+ if (emoji instanceof ReactionEmoji) return emoji.identifier;
+ if (typeof emoji === 'string') {
+ if (!emoji.includes('%')) return encodeURIComponent(emoji);
+ else return emoji;
+ }
+ return null;
+ }
+}
+
+module.exports = GuildEmojiManager;
diff --git a/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js
new file mode 100644
index 0000000..038571f
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildEmojiRoleManager.js
@@ -0,0 +1,119 @@
+'use strict';
+
+const { TypeError } = require('../errors');
+const Collection = require('../util/Collection');
+
+/**
+ * Manages API methods for roles belonging to emojis and stores their cache.
+ */
+class GuildEmojiRoleManager {
+ constructor(emoji) {
+ /**
+ * The emoji belonging to this manager
+ * @type {GuildEmoji}
+ */
+ this.emoji = emoji;
+ /**
+ * The guild belonging to this manager
+ * @type {Guild}
+ */
+ this.guild = emoji.guild;
+ /**
+ * The client belonging to this manager
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: emoji.client });
+ }
+
+ /**
+ * The filtered collection of roles of the guild emoji
+ * @type {Collection<Snowflake, Role>}
+ * @private
+ * @readonly
+ */
+ get _roles() {
+ return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id));
+ }
+
+ /**
+ * The cache of roles belonging to this emoji
+ * @type {Collection<Snowflake, Role>}
+ * @readonly
+ */
+ get cache() {
+ return this._roles;
+ }
+
+ /**
+ * Adds a role (or multiple roles) to the list of roles that can use this emoji.
+ * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
+ * @returns {Promise<GuildEmoji>}
+ */
+ add(roleOrRoles) {
+ if (roleOrRoles instanceof Collection) return this.add(roleOrRoles.keyArray());
+ if (!Array.isArray(roleOrRoles)) return this.add([roleOrRoles]);
+ roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
+
+ if (roleOrRoles.includes(null)) {
+ return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true));
+ }
+
+ const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))];
+ return this.set(newRoles);
+ }
+
+ /**
+ * Removes a role (or multiple roles) from the list of roles that can use this emoji.
+ * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
+ * @returns {Promise<GuildEmoji>}
+ */
+ remove(roleOrRoles) {
+ if (roleOrRoles instanceof Collection) return this.remove(roleOrRoles.keyArray());
+ if (!Array.isArray(roleOrRoles)) return this.remove([roleOrRoles]);
+ roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolveID(r));
+
+ if (roleOrRoles.includes(null)) {
+ return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true));
+ }
+
+ const newRoles = this._roles.keyArray().filter(role => !roleOrRoles.includes(role));
+ return this.set(newRoles);
+ }
+
+ /**
+ * Sets the role(s) that can use this emoji.
+ * @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to apply
+ * @returns {Promise<GuildEmoji>}
+ * @example
+ * // Set the emoji's roles to a single role
+ * guildEmoji.roles.set(['391156570408615936'])
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Remove all roles from an emoji
+ * guildEmoji.roles.set([])
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ set(roles) {
+ return this.emoji.edit({ roles });
+ }
+
+ clone() {
+ const clone = new this.constructor(this.emoji);
+ clone._patch(this._roles.keyArray().slice());
+ return clone;
+ }
+
+ /**
+ * Patches the roles for this manager's cache
+ * @param {Snowflake[]} roles The new roles
+ * @private
+ */
+ _patch(roles) {
+ this.emoji._roles = roles;
+ }
+}
+
+module.exports = GuildEmojiRoleManager;
diff --git a/node_modules/discord.js/src/managers/GuildManager.js b/node_modules/discord.js/src/managers/GuildManager.js
new file mode 100644
index 0000000..42cbcd4
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildManager.js
@@ -0,0 +1,216 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const Guild = require('../structures/Guild');
+const GuildChannel = require('../structures/GuildChannel');
+const GuildEmoji = require('../structures/GuildEmoji');
+const GuildMember = require('../structures/GuildMember');
+const Invite = require('../structures/Invite');
+const Role = require('../structures/Role');
+const {
+ Events,
+ VerificationLevels,
+ DefaultMessageNotifications,
+ ExplicitContentFilterLevels,
+} = require('../util/Constants');
+const DataResolver = require('../util/DataResolver');
+const Permissions = require('../util/Permissions');
+const { resolveColor } = require('../util/Util');
+
+/**
+ * Manages API methods for Guilds and stores their cache.
+ * @extends {BaseManager}
+ */
+class GuildManager extends BaseManager {
+ constructor(client, iterable) {
+ super(client, iterable, Guild);
+ }
+
+ /**
+ * The cache of this Manager
+ * @type {Collection<Snowflake, Guild>}
+ * @name GuildManager#cache
+ */
+
+ /**
+ * Data that resolves to give a Guild object. This can be:
+ * * A Guild object
+ * * A GuildChannel object
+ * * A GuildEmoji object
+ * * A Role object
+ * * A Snowflake
+ * * An Invite object
+ * @typedef {Guild|GuildChannel|GuildMember|GuildEmoji|Role|Snowflake|Invite} GuildResolvable
+ */
+
+ /**
+ * Partial data for a Role.
+ * @typedef {Object} PartialRoleData
+ * @property {number} [id] The ID for this role, used to set channel overrides,
+ * this is a placeholder and will be replaced by the API after consumption
+ * @property {string} [name] The name of the role
+ * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
+ * @property {boolean} [hoist] Whether or not the role should be hoisted
+ * @property {number} [position] The position of the role
+ * @property {PermissionResolvable|number} [permissions] The permissions of the role
+ * @property {boolean} [mentionable] Whether or not the role should be mentionable
+ */
+
+ /**
+ * Partial overwrite data.
+ * @typedef {Object} PartialOverwriteData
+ * @property {number|Snowflake} id The Role or User ID for this overwrite
+ * @property {string} [type] The type of this overwrite
+ * @property {PermissionResolvable} [allow] The permissions to allow
+ * @property {PermissionResolvable} [deny] The permissions to deny
+ */
+
+ /**
+ * Partial data for a Channel.
+ * @typedef {Object} PartialChannelData
+ * @property {number} [id] The ID for this channel, used to set its parent,
+ * this is a placeholder and will be replaced by the API after consumption
+ * @property {number} [parentID] The parent ID for this channel
+ * @property {string} [type] The type of the channel
+ * @property {string} name The name of the channel
+ * @property {string} [topic] The topic of the text channel
+ * @property {boolean} [nsfw] Whether the channel is NSFW
+ * @property {number} [bitrate] The bitrate of the voice channel
+ * @property {number} [userLimit] The user limit of the channel
+ * @property {PartialOverwriteData} [permissionOverwrites]
+ * Overwrites of the channel
+ * @property {number} [rateLimitPerUser] The rate limit per user of the channel in seconds
+ */
+
+ /**
+ * Resolves a GuildResolvable to a Guild object.
+ * @method resolve
+ * @memberof GuildManager
+ * @instance
+ * @param {GuildResolvable} guild The guild resolvable to identify
+ * @returns {?Guild}
+ */
+ resolve(guild) {
+ if (
+ guild instanceof GuildChannel ||
+ guild instanceof GuildMember ||
+ guild instanceof GuildEmoji ||
+ guild instanceof Role ||
+ (guild instanceof Invite && guild.guild)
+ ) {
+ return super.resolve(guild.guild);
+ }
+ return super.resolve(guild);
+ }
+
+ /**
+ * Resolves a GuildResolvable to a Guild ID string.
+ * @method resolveID
+ * @memberof GuildManager
+ * @instance
+ * @param {GuildResolvable} guild The guild resolvable to identify
+ * @returns {?Snowflake}
+ */
+ resolveID(guild) {
+ if (
+ guild instanceof GuildChannel ||
+ guild instanceof GuildMember ||
+ guild instanceof GuildEmoji ||
+ guild instanceof Role ||
+ (guild instanceof Invite && guild.guild)
+ ) {
+ return super.resolveID(guild.guild.id);
+ }
+ return super.resolveID(guild);
+ }
+
+ /**
+ * Creates a guild.
+ * <warn>This is only available to bots in fewer than 10 guilds.</warn>
+ * @param {string} name The name of the guild
+ * @param {Object} [options] Options for the creating
+ * @param {PartialChannelData[]} [options.channels] The channels for this guild
+ * @param {DefaultMessageNotifications} [options.defaultMessageNotifications] The default message notifications
+ * for the guild
+ * @param {ExplicitContentFilterLevel} [options.explicitContentFilter] The explicit content filter level for the guild
+ * @param {BufferResolvable|Base64Resolvable} [options.icon=null] The icon for the guild
+ * @param {string} [options.region] The region for the server, defaults to the closest one available
+ * @param {PartialRoleData[]} [options.roles] The roles for this guild,
+ * the first element of this array is used to change properties of the guild's everyone role.
+ * @param {VerificationLevel} [options.verificationLevel] The verification level for the guild
+ * @returns {Promise<Guild>} The guild that was created
+ */
+ async create(
+ name,
+ {
+ channels = [],
+ defaultMessageNotifications,
+ explicitContentFilter,
+ icon = null,
+ region,
+ roles = [],
+ verificationLevel,
+ } = {},
+ ) {
+ icon = await DataResolver.resolveImage(icon);
+ if (typeof verificationLevel !== 'undefined' && typeof verificationLevel !== 'number') {
+ verificationLevel = VerificationLevels.indexOf(verificationLevel);
+ }
+ if (typeof defaultMessageNotifications !== 'undefined' && typeof defaultMessageNotifications !== 'number') {
+ defaultMessageNotifications = DefaultMessageNotifications.indexOf(defaultMessageNotifications);
+ }
+ if (typeof explicitContentFilter !== 'undefined' && typeof explicitContentFilter !== 'number') {
+ explicitContentFilter = ExplicitContentFilterLevels.indexOf(explicitContentFilter);
+ }
+ for (const channel of channels) {
+ channel.parent_id = channel.parentID;
+ delete channel.parentID;
+ if (!channel.permissionOverwrites) continue;
+ for (const overwrite of channel.permissionOverwrites) {
+ if (overwrite.allow) overwrite.allow = Permissions.resolve(overwrite.allow);
+ if (overwrite.deny) overwrite.deny = Permissions.resolve(overwrite.deny);
+ }
+ channel.permission_overwrites = channel.permissionOverwrites;
+ delete channel.permissionOverwrites;
+ }
+ for (const role of roles) {
+ if (role.color) role.color = resolveColor(role.color);
+ if (role.permissions) role.permissions = Permissions.resolve(role.permissions);
+ }
+ return new Promise((resolve, reject) =>
+ this.client.api.guilds
+ .post({
+ data: {
+ name,
+ region,
+ icon,
+ verification_level: verificationLevel,
+ default_message_notifications: defaultMessageNotifications,
+ explicit_content_filter: explicitContentFilter,
+ channels,
+ roles,
+ },
+ })
+ .then(data => {
+ if (this.client.guilds.cache.has(data.id)) return resolve(this.client.guilds.cache.get(data.id));
+
+ const handleGuild = guild => {
+ if (guild.id === data.id) {
+ this.client.removeListener(Events.GUILD_CREATE, handleGuild);
+ this.client.clearTimeout(timeout);
+ resolve(guild);
+ }
+ };
+ this.client.on(Events.GUILD_CREATE, handleGuild);
+
+ const timeout = this.client.setTimeout(() => {
+ this.client.removeListener(Events.GUILD_CREATE, handleGuild);
+ resolve(this.client.guilds.add(data));
+ }, 10000);
+ return undefined;
+ }, reject),
+ );
+ }
+}
+
+module.exports = GuildManager;
diff --git a/node_modules/discord.js/src/managers/GuildMemberManager.js b/node_modules/discord.js/src/managers/GuildMemberManager.js
new file mode 100644
index 0000000..e1387e8
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildMemberManager.js
@@ -0,0 +1,272 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const { Error, TypeError } = require('../errors');
+const GuildMember = require('../structures/GuildMember');
+const Collection = require('../util/Collection');
+const { Events, OPCodes } = require('../util/Constants');
+
+/**
+ * Manages API methods for GuildMembers and stores their cache.
+ * @extends {BaseManager}
+ */
+class GuildMemberManager extends BaseManager {
+ constructor(guild, iterable) {
+ super(guild.client, iterable, GuildMember);
+ /**
+ * The guild this manager belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ /**
+ * The cache of this Manager
+ * @type {Collection<Snowflake, GuildMember>}
+ * @name GuildMemberManager#cache
+ */
+
+ add(data, cache = true) {
+ return super.add(data, cache, { id: data.user.id, extras: [this.guild] });
+ }
+
+ /**
+ * Data that resolves to give a GuildMember object. This can be:
+ * * A GuildMember object
+ * * A User resolvable
+ * @typedef {GuildMember|UserResolvable} GuildMemberResolvable
+ */
+
+ /**
+ * Resolves a GuildMemberResolvable to a GuildMember object.
+ * @param {GuildMemberResolvable} member The user that is part of the guild
+ * @returns {?GuildMember}
+ */
+ resolve(member) {
+ const memberResolvable = super.resolve(member);
+ if (memberResolvable) return memberResolvable;
+ const userResolvable = this.client.users.resolveID(member);
+ if (userResolvable) return super.resolve(userResolvable);
+ return null;
+ }
+
+ /**
+ * Resolves a GuildMemberResolvable to a member ID string.
+ * @param {GuildMemberResolvable} member The user that is part of the guild
+ * @returns {?Snowflake}
+ */
+ resolveID(member) {
+ const memberResolvable = super.resolveID(member);
+ if (memberResolvable) return memberResolvable;
+ const userResolvable = this.client.users.resolveID(member);
+ return this.cache.has(userResolvable) ? userResolvable : null;
+ }
+
+ /**
+ * Options used to fetch a single member from a guild.
+ * @typedef {Object} FetchMemberOptions
+ * @property {UserResolvable} user The user to fetch
+ * @property {boolean} [cache=true] Whether or not to cache the fetched member
+ */
+
+ /**
+ * Options used to fetch multiple members from a guild.
+ * @typedef {Object} FetchMembersOptions
+ * @property {UserResolvable|UserResolvable[]} user The user(s) to fetch
+ * @property {?string} query Limit fetch to members with similar usernames
+ * @property {number} [limit=0] Maximum number of members to request
+ * @property {boolean} [withPresences=false] Whether or not to include the presences
+ * @property {number} [time=120e3] Timeout for receipt of members
+ */
+
+ /**
+ * Fetches member(s) from Discord, even if they're offline.
+ * @param {UserResolvable|FetchMemberOptions|FetchMembersOptions} [options] If a UserResolvable, the user to fetch.
+ * If undefined, fetches all members.
+ * If a query, it limits the results to users with similar usernames.
+ * @returns {Promise<GuildMember>|Promise<Collection<Snowflake, GuildMember>>}
+ * @example
+ * // Fetch all members from a guild
+ * guild.members.fetch()
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Fetch a single member
+ * guild.members.fetch('66564597481480192')
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Fetch a single member without caching
+ * guild.members.fetch({ user, cache: false })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Fetch by an array of users including their presences
+ * guild.members.fetch({ user: ['66564597481480192', '191615925336670208'], withPresences: true })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Fetch by query
+ * guild.members.fetch({ query: 'hydra', limit: 1 })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ fetch(options) {
+ if (!options) return this._fetchMany();
+ const user = this.client.users.resolveID(options);
+ if (user) return this._fetchSingle({ user, cache: true });
+ if (options.user) {
+ if (Array.isArray(options.user)) {
+ options.user = options.user.map(u => this.client.users.resolveID(u));
+ return this._fetchMany(options);
+ } else {
+ options.user = this.client.users.resolveID(options.user);
+ }
+ if (!options.limit && !options.withPresences) return this._fetchSingle(options);
+ }
+ return this._fetchMany(options);
+ }
+
+ /**
+ * Prunes members from the guild based on how long they have been inactive.
+ * <info>It's recommended to set options.count to `false` for large guilds.</info>
+ * @param {Object} [options] Prune options
+ * @param {number} [options.days=7] Number of days of inactivity required to kick
+ * @param {boolean} [options.dry=false] Get number of users that will be kicked, without actually kicking them
+ * @param {boolean} [options.count=true] Whether or not to return the number of users that have been kicked.
+ * @param {string} [options.reason] Reason for this prune
+ * @returns {Promise<number|null>} The number of members that were/will be kicked
+ * @example
+ * // See how many members will be pruned
+ * guild.members.prune({ dry: true })
+ * .then(pruned => console.log(`This will prune ${pruned} people!`))
+ * .catch(console.error);
+ * @example
+ * // Actually prune the members
+ * guild.members.prune({ days: 1, reason: 'too many people!' })
+ * .then(pruned => console.log(`I just pruned ${pruned} people!`))
+ * .catch(console.error);
+ */
+ prune({ days = 7, dry = false, count = true, reason } = {}) {
+ if (typeof days !== 'number') throw new TypeError('PRUNE_DAYS_TYPE');
+ return this.client.api
+ .guilds(this.guild.id)
+ .prune[dry ? 'get' : 'post']({
+ query: {
+ days,
+ compute_prune_count: count,
+ },
+ reason,
+ })
+ .then(data => data.pruned);
+ }
+
+ /**
+ * Bans a user from the guild.
+ * @param {UserResolvable} user The user to ban
+ * @param {Object} [options] Options for the ban
+ * @param {number} [options.days=0] Number of days of messages to delete
+ * @param {string} [options.reason] Reason for banning
+ * @returns {Promise<GuildMember|User|Snowflake>} Result object will be resolved as specifically as possible.
+ * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot
+ * be resolved, the user ID will be the result.
+ * @example
+ * // Ban a user by ID (or with a user/guild member object)
+ * guild.members.ban('84484653687267328')
+ * .then(user => console.log(`Banned ${user.username || user.id || user} from ${guild.name}`))
+ * .catch(console.error);
+ */
+ ban(user, options = { days: 0 }) {
+ if (options.days) options['delete-message-days'] = options.days;
+ const id = this.client.users.resolveID(user);
+ if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true));
+ return this.client.api
+ .guilds(this.guild.id)
+ .bans[id].put({ query: options })
+ .then(() => {
+ if (user instanceof GuildMember) return user;
+ const _user = this.client.users.resolve(id);
+ if (_user) {
+ const member = this.resolve(_user);
+ return member || _user;
+ }
+ return id;
+ });
+ }
+
+ /**
+ * Unbans a user from the guild.
+ * @param {UserResolvable} user The user to unban
+ * @param {string} [reason] Reason for unbanning user
+ * @returns {Promise<User>}
+ * @example
+ * // Unban a user by ID (or with a user/guild member object)
+ * guild.members.unban('84484653687267328')
+ * .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`))
+ * .catch(console.error);
+ */
+ unban(user, reason) {
+ const id = this.client.users.resolveID(user);
+ if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID'));
+ return this.client.api
+ .guilds(this.guild.id)
+ .bans[id].delete({ reason })
+ .then(() => this.client.users.resolve(user));
+ }
+
+ _fetchSingle({ user, cache }) {
+ const existing = this.cache.get(user);
+ if (existing && !existing.partial) return Promise.resolve(existing);
+ return this.client.api
+ .guilds(this.guild.id)
+ .members(user)
+ .get()
+ .then(data => this.add(data, cache));
+ }
+
+ _fetchMany({ limit = 0, withPresences: presences = false, user: user_ids, query, time = 120e3 } = {}) {
+ return new Promise((resolve, reject) => {
+ if (this.guild.memberCount === this.cache.size && !query && !limit && !presences && !user_ids) {
+ resolve(this.cache);
+ return;
+ }
+ if (!query && !user_ids) query = '';
+ this.guild.shard.send({
+ op: OPCodes.REQUEST_GUILD_MEMBERS,
+ d: {
+ guild_id: this.guild.id,
+ presences,
+ user_ids,
+ query,
+ limit,
+ },
+ });
+ const fetchedMembers = new Collection();
+ const option = query || limit || presences || user_ids;
+ const handler = (members, guild) => {
+ if (guild.id !== this.guild.id) return;
+ timeout.refresh();
+ for (const member of members.values()) {
+ if (option) fetchedMembers.set(member.id, member);
+ }
+ if (
+ this.guild.memberCount <= this.cache.size ||
+ (option && members.size < 1000) ||
+ (limit && fetchedMembers.size >= limit)
+ ) {
+ this.guild.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler);
+ let fetched = option ? fetchedMembers : this.cache;
+ if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first();
+ resolve(fetched);
+ }
+ };
+ const timeout = this.guild.client.setTimeout(() => {
+ this.guild.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler);
+ reject(new Error('GUILD_MEMBERS_TIMEOUT'));
+ }, time);
+ this.guild.client.on(Events.GUILD_MEMBERS_CHUNK, handler);
+ });
+ }
+}
+
+module.exports = GuildMemberManager;
diff --git a/node_modules/discord.js/src/managers/GuildMemberRoleManager.js b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js
new file mode 100644
index 0000000..f4f530d
--- /dev/null
+++ b/node_modules/discord.js/src/managers/GuildMemberRoleManager.js
@@ -0,0 +1,166 @@
+'use strict';
+
+const { TypeError } = require('../errors');
+const Collection = require('../util/Collection');
+
+/**
+ * Manages API methods for roles of a GuildMember and stores their cache.
+ */
+class GuildMemberRoleManager {
+ constructor(member) {
+ /**
+ * The GuildMember this manager belongs to
+ * @type {GuildMember}
+ */
+ this.member = member;
+ /**
+ * The Guild this manager belongs to
+ * @type {Guild}
+ */
+ this.guild = member.guild;
+ Object.defineProperty(this, 'client', { value: member.client });
+ }
+
+ /**
+ * The filtered collection of roles of the member
+ * @type {Collection<Snowflake, Role>}
+ * @private
+ * @readonly
+ */
+ get _roles() {
+ const everyone = this.guild.roles.everyone;
+ return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone);
+ }
+
+ /**
+ * The roles of this member
+ * @type {Collection<Snowflake, Role>}
+ * @readonly
+ */
+ get cache() {
+ return this._roles;
+ }
+
+ /**
+ * The role of the member used to hoist them in a separate category in the users list
+ * @type {?Role}
+ * @readonly
+ */
+ get hoist() {
+ const hoistedRoles = this._roles.filter(role => role.hoist);
+ if (!hoistedRoles.size) return null;
+ return hoistedRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev));
+ }
+
+ /**
+ * The role of the member used to set their color
+ * @type {?Role}
+ * @readonly
+ */
+ get color() {
+ const coloredRoles = this._roles.filter(role => role.color);
+ if (!coloredRoles.size) return null;
+ return coloredRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev));
+ }
+
+ /**
+ * The role of the member with the highest position
+ * @type {Role}
+ * @readonly
+ */
+ get highest() {
+ return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first());
+ }
+
+ /**
+ * Adds a role (or multiple roles) to the member.
+ * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
+ * @param {string} [reason] Reason for adding the role(s)
+ * @returns {Promise<GuildMember>}
+ */
+ async add(roleOrRoles, reason) {
+ if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
+ roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
+ if (roleOrRoles.includes(null)) {
+ throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
+ }
+
+ const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))];
+ return this.set(newRoles, reason);
+ } else {
+ roleOrRoles = this.guild.roles.resolve(roleOrRoles);
+ if (roleOrRoles === null) {
+ throw new TypeError(
+ 'INVALID_TYPE',
+ 'roles',
+ 'Role, Snowflake or Array or Collection of Roles or Snowflakes',
+ true,
+ );
+ }
+
+ await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].put({ reason });
+
+ const clone = this.member._clone();
+ clone._roles = [...this._roles.keys(), roleOrRoles.id];
+ return clone;
+ }
+ }
+
+ /**
+ * Removes a role (or multiple roles) from the member.
+ * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
+ * @param {string} [reason] Reason for removing the role(s)
+ * @returns {Promise<GuildMember>}
+ */
+ async remove(roleOrRoles, reason) {
+ if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
+ roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
+ if (roleOrRoles.includes(null)) {
+ throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
+ }
+
+ const newRoles = this._roles.filter(role => !roleOrRoles.includes(role));
+ return this.set(newRoles, reason);
+ } else {
+ roleOrRoles = this.guild.roles.resolve(roleOrRoles);
+ if (roleOrRoles === null) {
+ throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
+ }
+
+ await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].delete({ reason });
+
+ const clone = this.member._clone();
+ const newRoles = this._roles.filter(role => role.id !== roleOrRoles.id);
+ clone._roles = [...newRoles.keys()];
+ return clone;
+ }
+ }
+
+ /**
+ * Sets the roles applied to the member.
+ * @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to apply
+ * @param {string} [reason] Reason for applying the roles
+ * @returns {Promise<GuildMember>}
+ * @example
+ * // Set the member's roles to a single role
+ * guildMember.roles.set(['391156570408615936'])
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Remove all the roles from a member
+ * guildMember.roles.set([])
+ * .then(member => console.log(`Member roles is now of ${member.roles.cache.size} size`))
+ * .catch(console.error);
+ */
+ set(roles, reason) {
+ return this.member.edit({ roles }, reason);
+ }
+
+ clone() {
+ const clone = new this.constructor(this.member);
+ clone.member._roles = [...this._roles.keyArray()];
+ return clone;
+ }
+}
+
+module.exports = GuildMemberRoleManager;
diff --git a/node_modules/discord.js/src/managers/MessageManager.js b/node_modules/discord.js/src/managers/MessageManager.js
new file mode 100644
index 0000000..6d51bcf
--- /dev/null
+++ b/node_modules/discord.js/src/managers/MessageManager.js
@@ -0,0 +1,145 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const Message = require('../structures/Message');
+const Collection = require('../util/Collection');
+const LimitedCollection = require('../util/LimitedCollection');
+
+/**
+ * Manages API methods for Messages and holds their cache.
+ * @extends {BaseManager}
+ */
+class MessageManager extends BaseManager {
+ constructor(channel, iterable) {
+ super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize);
+ /**
+ * The channel that the messages belong to
+ * @type {TextBasedChannel}
+ */
+ this.channel = channel;
+ }
+
+ /**
+ * The cache of Messages
+ * @type {Collection<Snowflake, Message>}
+ * @name MessageManager#cache
+ */
+
+ add(data, cache) {
+ return super.add(data, cache, { extras: [this.channel] });
+ }
+
+ /**
+ * The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
+ * `after` are mutually exclusive. All the parameters are optional.
+ * @typedef {Object} ChannelLogsQueryOptions
+ * @property {number} [limit=50] Number of messages to acquire
+ * @property {Snowflake} [before] ID of a message to get the messages that were posted before it
+ * @property {Snowflake} [after] ID of a message to get the messages that were posted after it
+ * @property {Snowflake} [around] ID of a message to get the messages that were posted around it
+ */
+
+ /**
+ * Gets a message, or messages, from this channel.
+ * <info>The returned Collection does not contain reaction users of the messages if they were not cached.
+ * Those need to be fetched separately in such a case.</info>
+ * @param {Snowflake|ChannelLogsQueryOptions} [message] The ID of the message to fetch, or query parameters.
+ * @param {boolean} [cache=true] Whether to cache the message(s)
+ * @returns {Promise<Message>|Promise<Collection<Snowflake, Message>>}
+ * @example
+ * // Get message
+ * channel.messages.fetch('99539446449315840')
+ * .then(message => console.log(message.content))
+ * .catch(console.error);
+ * @example
+ * // Get messages
+ * channel.messages.fetch({ limit: 10 })
+ * .then(messages => console.log(`Received ${messages.size} messages`))
+ * .catch(console.error);
+ * @example
+ * // Get messages and filter by user ID
+ * channel.messages.fetch()
+ * .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`))
+ * .catch(console.error);
+ */
+ fetch(message, cache = true) {
+ return typeof message === 'string' ? this._fetchId(message, cache) : this._fetchMany(message, cache);
+ }
+
+ /**
+ * Fetches the pinned messages of this channel and returns a collection of them.
+ * <info>The returned Collection does not contain any reaction data of the messages.
+ * Those need to be fetched separately.</info>
+ * @param {boolean} [cache=true] Whether to cache the message(s)
+ * @returns {Promise<Collection<Snowflake, Message>>}
+ * @example
+ * // Get pinned messages
+ * channel.fetchPinned()
+ * .then(messages => console.log(`Received ${messages.size} messages`))
+ * .catch(console.error);
+ */
+ fetchPinned(cache = true) {
+ return this.client.api.channels[this.channel.id].pins.get().then(data => {
+ const messages = new Collection();
+ for (const message of data) messages.set(message.id, this.add(message, cache));
+ return messages;
+ });
+ }
+
+ /**
+ * Data that can be resolved to a Message object. This can be:
+ * * A Message
+ * * A Snowflake
+ * @typedef {Message|Snowflake} MessageResolvable
+ */
+
+ /**
+ * Resolves a MessageResolvable to a Message object.
+ * @method resolve
+ * @memberof MessageManager
+ * @instance
+ * @param {MessageResolvable} message The message resolvable to resolve
+ * @returns {?Message}
+ */
+
+ /**
+ * Resolves a MessageResolvable to a Message ID string.
+ * @method resolveID
+ * @memberof MessageManager
+ * @instance
+ * @param {MessageResolvable} message The message resolvable to resolve
+ * @returns {?Snowflake}
+ */
+
+ /**
+ * Deletes a message, even if it's not cached.
+ * @param {MessageResolvable} message The message to delete
+ * @param {string} [reason] Reason for deleting this message, if it does not belong to the client user
+ * @returns {Promise<void>}
+ */
+ async delete(message, reason) {
+ message = this.resolveID(message);
+ if (message) {
+ await this.client.api
+ .channels(this.channel.id)
+ .messages(message)
+ .delete({ reason });
+ }
+ }
+
+ async _fetchId(messageID, cache) {
+ const existing = this.cache.get(messageID);
+ if (existing && !existing.partial) return existing;
+ const data = await this.client.api.channels[this.channel.id].messages[messageID].get();
+ return this.add(data, cache);
+ }
+
+ async _fetchMany(options = {}, cache) {
+ const data = await this.client.api.channels[this.channel.id].messages.get({ query: options });
+ const messages = new Collection();
+ for (const message of data) messages.set(message.id, this.add(message, cache));
+ return messages;
+ }
+}
+
+module.exports = MessageManager;
diff --git a/node_modules/discord.js/src/managers/PresenceManager.js b/node_modules/discord.js/src/managers/PresenceManager.js
new file mode 100644
index 0000000..c02fe04
--- /dev/null
+++ b/node_modules/discord.js/src/managers/PresenceManager.js
@@ -0,0 +1,59 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const { Presence } = require('../structures/Presence');
+
+/**
+ * Manages API methods for Presences and holds their cache.
+ * @extends {BaseManager}
+ */
+class PresenceManager extends BaseManager {
+ constructor(client, iterable) {
+ super(client, iterable, Presence);
+ }
+
+ /**
+ * The cache of Presences
+ * @type {Collection<Snowflake, Presence>}
+ * @name PresenceManager#cache
+ */
+
+ add(data, cache) {
+ const existing = this.cache.get(data.user.id);
+ return existing ? existing.patch(data) : super.add(data, cache, { id: data.user.id });
+ }
+
+ /**
+ * Data that can be resolved to a Presence object. This can be:
+ * * A Presence
+ * * A UserResolvable
+ * * A Snowflake
+ * @typedef {Presence|UserResolvable|Snowflake} PresenceResolvable
+ */
+
+ /**
+ * Resolves a PresenceResolvable to a Presence object.
+ * @param {PresenceResolvable} presence The presence resolvable to resolve
+ * @returns {?Presence}
+ */
+ resolve(presence) {
+ const presenceResolvable = super.resolve(presence);
+ if (presenceResolvable) return presenceResolvable;
+ const UserResolvable = this.client.users.resolveID(presence);
+ return super.resolve(UserResolvable) || null;
+ }
+
+ /**
+ * Resolves a PresenceResolvable to a Presence ID string.
+ * @param {PresenceResolvable} presence The presence resolvable to resolve
+ * @returns {?Snowflake}
+ */
+ resolveID(presence) {
+ const presenceResolvable = super.resolveID(presence);
+ if (presenceResolvable) return presenceResolvable;
+ const userResolvable = this.client.users.resolveID(presence);
+ return this.cache.has(userResolvable) ? userResolvable : null;
+ }
+}
+
+module.exports = PresenceManager;
diff --git a/node_modules/discord.js/src/managers/ReactionManager.js b/node_modules/discord.js/src/managers/ReactionManager.js
new file mode 100644
index 0000000..b46d187
--- /dev/null
+++ b/node_modules/discord.js/src/managers/ReactionManager.js
@@ -0,0 +1,69 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const MessageReaction = require('../structures/MessageReaction');
+
+/**
+ * Manages API methods for reactions and holds their cache.
+ * @extends {BaseManager}
+ */
+class ReactionManager extends BaseManager {
+ constructor(message, iterable) {
+ super(message.client, iterable, MessageReaction);
+
+ /**
+ * The message that this manager belongs to
+ * @type {Message}
+ */
+ this.message = message;
+ }
+
+ add(data, cache) {
+ return super.add(data, cache, { id: data.emoji.id || data.emoji.name, extras: [this.message] });
+ }
+
+ /**
+ * The reaction cache of this manager
+ * @type {Collection<Snowflake, MessageReaction>}
+ * @name ReactionManager#cache
+ */
+
+ /**
+ * Data that can be resolved to a MessageReaction object. This can be:
+ * * A MessageReaction
+ * * A Snowflake
+ * @typedef {MessageReaction|Snowflake} MessageReactionResolvable
+ */
+
+ /**
+ * Resolves a MessageReactionResolvable to a MessageReaction object.
+ * @method resolve
+ * @memberof ReactionManager
+ * @instance
+ * @param {MessageReactionResolvable} reaction The MessageReaction to resolve
+ * @returns {?MessageReaction}
+ */
+
+ /**
+ * Resolves a MessageReactionResolvable to a MessageReaction ID string.
+ * @method resolveID
+ * @memberof ReactionManager
+ * @instance
+ * @param {MessageReactionResolvable} reaction The MessageReaction to resolve
+ * @returns {?Snowflake}
+ */
+
+ /**
+ * Removes all reactions from a message.
+ * @returns {Promise<Message>}
+ */
+ removeAll() {
+ return this.client.api
+ .channels(this.message.channel.id)
+ .messages(this.message.id)
+ .reactions.delete()
+ .then(() => this.message);
+ }
+}
+
+module.exports = ReactionManager;
diff --git a/node_modules/discord.js/src/managers/ReactionUserManager.js b/node_modules/discord.js/src/managers/ReactionUserManager.js
new file mode 100644
index 0000000..1a6ce14
--- /dev/null
+++ b/node_modules/discord.js/src/managers/ReactionUserManager.js
@@ -0,0 +1,66 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const { Error } = require('../errors');
+const Collection = require('../util/Collection');
+
+/**
+ * Manages API methods for users who reacted to a reaction and stores their cache.
+ * @extends {BaseManager}
+ */
+class ReactionUserManager extends BaseManager {
+ constructor(client, iterable, reaction) {
+ super(client, iterable, { name: 'User' });
+ /**
+ * The reaction that this manager belongs to
+ * @type {MessageReaction}
+ */
+ this.reaction = reaction;
+ }
+
+ /**
+ * The cache of this manager
+ * @type {Collection<Snowflake, User>}
+ * @name ReactionUserManager#cache
+ */
+
+ /**
+ * Fetches all the users that gave this reaction. Resolves with a collection of users, mapped by their IDs.
+ * @param {Object} [options] Options for fetching the users
+ * @param {number} [options.limit=100] The maximum amount of users to fetch, defaults to 100
+ * @param {Snowflake} [options.before] Limit fetching users to those with an id lower than the supplied id
+ * @param {Snowflake} [options.after] Limit fetching users to those with an id greater than the supplied id
+ * @returns {Promise<Collection<Snowflake, User>>}
+ */
+ async fetch({ limit = 100, after, before } = {}) {
+ const message = this.reaction.message;
+ const data = await this.client.api.channels[message.channel.id].messages[message.id].reactions[
+ this.reaction.emoji.identifier
+ ].get({ query: { limit, before, after } });
+ const users = new Collection();
+ for (const rawUser of data) {
+ const user = this.client.users.add(rawUser);
+ this.cache.set(user.id, user);
+ users.set(user.id, user);
+ }
+ return users;
+ }
+
+ /**
+ * Removes a user from this reaction.
+ * @param {UserResolvable} [user=this.reaction.message.client.user] The user to remove the reaction of
+ * @returns {Promise<MessageReaction>}
+ */
+ remove(user = this.reaction.message.client.user) {
+ const message = this.reaction.message;
+ const userID = message.client.users.resolveID(user);
+ if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER'));
+ return message.client.api.channels[message.channel.id].messages[message.id].reactions[
+ this.reaction.emoji.identifier
+ ][userID === message.client.user.id ? '@me' : userID]
+ .delete()
+ .then(() => this.reaction);
+ }
+}
+
+module.exports = ReactionUserManager;
diff --git a/node_modules/discord.js/src/managers/RoleManager.js b/node_modules/discord.js/src/managers/RoleManager.js
new file mode 100644
index 0000000..7c5bf51
--- /dev/null
+++ b/node_modules/discord.js/src/managers/RoleManager.js
@@ -0,0 +1,145 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const Role = require('../structures/Role');
+const Permissions = require('../util/Permissions');
+const { resolveColor } = require('../util/Util');
+
+/**
+ * Manages API methods for roles and stores their cache.
+ * @extends {BaseManager}
+ */
+class RoleManager extends BaseManager {
+ constructor(guild, iterable) {
+ super(guild.client, iterable, Role);
+ /**
+ * The guild belonging to this manager
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ /**
+ * The role cache of this manager
+ * @type {Collection<Snowflake, Role>}
+ * @name RoleManager#cache
+ */
+
+ add(data, cache) {
+ return super.add(data, cache, { extras: [this.guild] });
+ }
+
+ /**
+ * Obtains one or more roles from Discord, or the role cache if they're already available.
+ * @param {Snowflake} [id] ID or IDs of the role(s)
+ * @param {boolean} [cache=true] Whether to cache the new roles objects if it weren't already
+ * @returns {Promise<Role|RoleManager>}
+ * @example
+ * // Fetch all roles from the guild
+ * message.guild.roles.fetch()
+ * .then(roles => console.log(`There are ${roles.cache.size} roles.`))
+ * .catch(console.error);
+ * @example
+ * // Fetch a single role
+ * message.guild.roles.fetch('222078108977594368')
+ * .then(role => console.log(`The role color is: ${role.color}`))
+ * .catch(console.error);
+ */
+ async fetch(id, cache = true) {
+ if (id) {
+ const existing = this.cache.get(id);
+ if (existing) return existing;
+ }
+
+ // We cannot fetch a single role, as of this commit's date, Discord API throws with 405
+ const roles = await this.client.api.guilds(this.guild.id).roles.get();
+ for (const role of roles) this.add(role, cache);
+ return id ? this.cache.get(id) || null : this;
+ }
+
+ /**
+ * Data that can be resolved to a Role object. This can be:
+ * * A Role
+ * * A Snowflake
+ * @typedef {Role|Snowflake} RoleResolvable
+ */
+
+ /**
+ * Resolves a RoleResolvable to a Role object.
+ * @method resolve
+ * @memberof RoleManager
+ * @instance
+ * @param {RoleResolvable} role The role resolvable to resolve
+ * @returns {?Role}
+ */
+
+ /**
+ * Resolves a RoleResolvable to a role ID string.
+ * @method resolveID
+ * @memberof RoleManager
+ * @instance
+ * @param {RoleResolvable} role The role resolvable to resolve
+ * @returns {?Snowflake}
+ */
+
+ /**
+ * Creates a new role in the guild with given information.
+ * <warn>The position will silently reset to 1 if an invalid one is provided, or none.</warn>
+ * @param {Object} [options] Options
+ * @param {RoleData} [options.data] The data to create the role with
+ * @param {string} [options.reason] Reason for creating this role
+ * @returns {Promise<Role>}
+ * @example
+ * // Create a new role
+ * guild.roles.create()
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Create a new role with data and a reason
+ * guild.roles.create({
+ * data: {
+ * name: 'Super Cool People',
+ * color: 'BLUE',
+ * },
+ * reason: 'we needed a role for Super Cool People',
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ create({ data = {}, reason } = {}) {
+ if (data.color) data.color = resolveColor(data.color);
+ if (data.permissions) data.permissions = Permissions.resolve(data.permissions);
+
+ return this.guild.client.api
+ .guilds(this.guild.id)
+ .roles.post({ data, reason })
+ .then(r => {
+ const { role } = this.client.actions.GuildRoleCreate.handle({
+ guild_id: this.guild.id,
+ role: r,
+ });
+ if (data.position) return role.setPosition(data.position, reason);
+ return role;
+ });
+ }
+
+ /**
+ * The `@everyone` role of the guild
+ * @type {Role}
+ * @readonly
+ */
+ get everyone() {
+ return this.cache.get(this.guild.id);
+ }
+
+ /**
+ * The role with the highest position in the cache
+ * @type {Role}
+ * @readonly
+ */
+ get highest() {
+ return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
+ }
+}
+
+module.exports = RoleManager;
diff --git a/node_modules/discord.js/src/managers/UserManager.js b/node_modules/discord.js/src/managers/UserManager.js
new file mode 100644
index 0000000..ebd7fdf
--- /dev/null
+++ b/node_modules/discord.js/src/managers/UserManager.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const GuildMember = require('../structures/GuildMember');
+const Message = require('../structures/Message');
+const User = require('../structures/User');
+
+/**
+ * Manages API methods for users and stores their cache.
+ * @extends {BaseManager}
+ */
+class UserManager extends BaseManager {
+ constructor(client, iterable) {
+ super(client, iterable, User);
+ }
+
+ /**
+ * The cache of this manager
+ * @type {Collection<Snowflake, User>}
+ * @name UserManager#cache
+ */
+
+ /**
+ * Data that resolves to give a User object. This can be:
+ * * A User object
+ * * A Snowflake
+ * * A Message object (resolves to the message author)
+ * * A GuildMember object
+ * @typedef {User|Snowflake|Message|GuildMember} UserResolvable
+ */
+
+ /**
+ * Resolves a UserResolvable to a User object.
+ * @param {UserResolvable} user The UserResolvable to identify
+ * @returns {?User}
+ */
+ resolve(user) {
+ if (user instanceof GuildMember) return user.user;
+ if (user instanceof Message) return user.author;
+ return super.resolve(user);
+ }
+
+ /**
+ * Resolves a UserResolvable to a user ID string.
+ * @param {UserResolvable} user The UserResolvable to identify
+ * @returns {?Snowflake}
+ */
+ resolveID(user) {
+ if (user instanceof GuildMember) return user.user.id;
+ if (user instanceof Message) return user.author.id;
+ return super.resolveID(user);
+ }
+
+ /**
+ * Obtains a user from Discord, or the user cache if it's already available.
+ * @param {Snowflake} id ID of the user
+ * @param {boolean} [cache=true] Whether to cache the new user object if it isn't already
+ * @returns {Promise<User>}
+ */
+ async fetch(id, cache = true) {
+ const existing = this.cache.get(id);
+ if (existing && !existing.partial) return existing;
+ const data = await this.client.api.users(id).get();
+ return this.add(data, cache);
+ }
+}
+
+module.exports = UserManager;
diff --git a/node_modules/discord.js/src/managers/VoiceStateManager.js b/node_modules/discord.js/src/managers/VoiceStateManager.js
new file mode 100644
index 0000000..4a26b30
--- /dev/null
+++ b/node_modules/discord.js/src/managers/VoiceStateManager.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const BaseManager = require('./BaseManager');
+const VoiceState = require('../structures/VoiceState');
+
+/**
+ * Manages API methods for VoiceStates and stores their cache.
+ * @extends {BaseManager}
+ */
+class VoiceStateManager extends BaseManager {
+ constructor(guild, iterable) {
+ super(guild.client, iterable, VoiceState);
+ /**
+ * The guild this manager belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ /**
+ * The cache of this manager
+ * @type {Collection<Snowflake, VoiceState>}
+ * @name VoiceStateManager#cache
+ */
+
+ add(data, cache = true) {
+ const existing = this.cache.get(data.user_id);
+ if (existing) return existing._patch(data);
+
+ const entry = new VoiceState(this.guild, data);
+ if (cache) this.cache.set(data.user_id, entry);
+ return entry;
+ }
+}
+
+module.exports = VoiceStateManager;
diff --git a/node_modules/discord.js/src/rest/APIRequest.js b/node_modules/discord.js/src/rest/APIRequest.js
new file mode 100644
index 0000000..36ad0d7
--- /dev/null
+++ b/node_modules/discord.js/src/rest/APIRequest.js
@@ -0,0 +1,65 @@
+'use strict';
+
+const https = require('https');
+const FormData = require('@discordjs/form-data');
+const AbortController = require('abort-controller');
+const fetch = require('node-fetch');
+const { browser, UserAgent } = require('../util/Constants');
+
+if (https.Agent) var agent = new https.Agent({ keepAlive: true });
+
+class APIRequest {
+ constructor(rest, method, path, options) {
+ this.rest = rest;
+ this.client = rest.client;
+ this.method = method;
+ this.route = options.route;
+ this.options = options;
+
+ let queryString = '';
+ if (options.query) {
+ // Filter out undefined query options
+ const query = Object.entries(options.query).filter(([, value]) => value !== null && typeof value !== 'undefined');
+ queryString = new URLSearchParams(query).toString();
+ }
+ this.path = `${path}${queryString && `?${queryString}`}`;
+ }
+
+ make() {
+ const API =
+ this.options.versioned === false
+ ? this.client.options.http.api
+ : `${this.client.options.http.api}/v${this.client.options.http.version}`;
+ const url = API + this.path;
+ let headers = {};
+
+ if (this.options.auth !== false) headers.Authorization = this.rest.getAuth();
+ if (this.options.reason) headers['X-Audit-Log-Reason'] = encodeURIComponent(this.options.reason);
+ if (!browser) headers['User-Agent'] = UserAgent;
+ if (this.options.headers) headers = Object.assign(headers, this.options.headers);
+
+ let body;
+ if (this.options.files && this.options.files.length) {
+ body = new FormData();
+ for (const file of this.options.files) if (file && file.file) body.append(file.name, file.file, file.name);
+ if (typeof this.options.data !== 'undefined') body.append('payload_json', JSON.stringify(this.options.data));
+ if (!browser) headers = Object.assign(headers, body.getHeaders());
+ // eslint-disable-next-line eqeqeq
+ } else if (this.options.data != null) {
+ body = JSON.stringify(this.options.data);
+ headers['Content-Type'] = 'application/json';
+ }
+
+ const controller = new AbortController();
+ const timeout = this.client.setTimeout(() => controller.abort(), this.client.options.restRequestTimeout);
+ return fetch(url, {
+ method: this.method,
+ headers,
+ agent,
+ body,
+ signal: controller.signal,
+ }).finally(() => this.client.clearTimeout(timeout));
+ }
+}
+
+module.exports = APIRequest;
diff --git a/node_modules/discord.js/src/rest/APIRouter.js b/node_modules/discord.js/src/rest/APIRouter.js
new file mode 100644
index 0000000..e85c739
--- /dev/null
+++ b/node_modules/discord.js/src/rest/APIRouter.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const noop = () => {}; // eslint-disable-line no-empty-function
+const methods = ['get', 'post', 'delete', 'patch', 'put'];
+const reflectors = [
+ 'toString',
+ 'valueOf',
+ 'inspect',
+ 'constructor',
+ Symbol.toPrimitive,
+ Symbol.for('nodejs.util.inspect.custom'),
+];
+
+function buildRoute(manager) {
+ const route = [''];
+ const handler = {
+ get(target, name) {
+ if (reflectors.includes(name)) return () => route.join('/');
+ if (methods.includes(name)) {
+ const routeBucket = [];
+ for (let i = 0; i < route.length; i++) {
+ // Reactions routes and sub-routes all share the same bucket
+ if (route[i - 1] === 'reactions') break;
+ // Literal IDs should only be taken account if they are the Major ID (the Channel/Guild ID)
+ if (/\d{16,19}/g.test(route[i]) && !/channels|guilds/.test(route[i - 1])) routeBucket.push(':id');
+ // All other parts of the route should be considered as part of the bucket identifier
+ else routeBucket.push(route[i]);
+ }
+ return options =>
+ manager.request(
+ name,
+ route.join('/'),
+ Object.assign(
+ {
+ versioned: manager.versioned,
+ route: routeBucket.join('/'),
+ },
+ options,
+ ),
+ );
+ }
+ route.push(name);
+ return new Proxy(noop, handler);
+ },
+ apply(target, _, args) {
+ route.push(...args.filter(x => x != null)); // eslint-disable-line eqeqeq
+ return new Proxy(noop, handler);
+ },
+ };
+ return new Proxy(noop, handler);
+}
+
+module.exports = buildRoute;
diff --git a/node_modules/discord.js/src/rest/DiscordAPIError.js b/node_modules/discord.js/src/rest/DiscordAPIError.js
new file mode 100644
index 0000000..aebe513
--- /dev/null
+++ b/node_modules/discord.js/src/rest/DiscordAPIError.js
@@ -0,0 +1,68 @@
+'use strict';
+
+/**
+ * Represents an error from the Discord API.
+ * @extends Error
+ */
+class DiscordAPIError extends Error {
+ constructor(path, error, method, status) {
+ super();
+ const flattened = this.constructor.flattenErrors(error.errors || error).join('\n');
+ this.name = 'DiscordAPIError';
+ this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message || flattened;
+
+ /**
+ * The HTTP method used for the request
+ * @type {string}
+ */
+ this.method = method;
+
+ /**
+ * The path of the request relative to the HTTP endpoint
+ * @type {string}
+ */
+ this.path = path;
+
+ /**
+ * HTTP error code returned by Discord
+ * @type {number}
+ */
+ this.code = error.code;
+
+ /**
+ * The HTTP status code
+ * @type {number}
+ */
+ this.httpStatus = status;
+ }
+
+ /**
+ * Flattens an errors object returned from the API into an array.
+ * @param {Object} obj Discord errors object
+ * @param {string} [key] Used internally to determine key names of nested fields
+ * @returns {string[]}
+ * @private
+ */
+ static flattenErrors(obj, key = '') {
+ let messages = [];
+
+ for (const [k, v] of Object.entries(obj)) {
+ if (k === 'message') continue;
+ const newKey = key ? (isNaN(k) ? `${key}.${k}` : `${key}[${k}]`) : k;
+
+ if (v._errors) {
+ messages.push(`${newKey}: ${v._errors.map(e => e.message).join(' ')}`);
+ } else if (v.code || v.message) {
+ messages.push(`${v.code ? `${v.code}: ` : ''}${v.message}`.trim());
+ } else if (typeof v === 'string') {
+ messages.push(v);
+ } else {
+ messages = messages.concat(this.flattenErrors(v, newKey));
+ }
+ }
+
+ return messages;
+ }
+}
+
+module.exports = DiscordAPIError;
diff --git a/node_modules/discord.js/src/rest/HTTPError.js b/node_modules/discord.js/src/rest/HTTPError.js
new file mode 100644
index 0000000..2911467
--- /dev/null
+++ b/node_modules/discord.js/src/rest/HTTPError.js
@@ -0,0 +1,37 @@
+'use strict';
+
+/**
+ * Represents a HTTP error from a request.
+ * @extends Error
+ */
+class HTTPError extends Error {
+ constructor(message, name, code, method, path) {
+ super(message);
+
+ /**
+ * The name of the error
+ * @type {string}
+ */
+ this.name = name;
+
+ /**
+ * HTTP error code returned from the request
+ * @type {number}
+ */
+ this.code = code || 500;
+
+ /**
+ * The HTTP method used for the request
+ * @type {string}
+ */
+ this.method = method;
+
+ /**
+ * The path of the request relative to the HTTP endpoint
+ * @type {string}
+ */
+ this.path = path;
+ }
+}
+
+module.exports = HTTPError;
diff --git a/node_modules/discord.js/src/rest/RESTManager.js b/node_modules/discord.js/src/rest/RESTManager.js
new file mode 100644
index 0000000..b02ae81
--- /dev/null
+++ b/node_modules/discord.js/src/rest/RESTManager.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const APIRequest = require('./APIRequest');
+const routeBuilder = require('./APIRouter');
+const RequestHandler = require('./RequestHandler');
+const { Error } = require('../errors');
+const Collection = require('../util/Collection');
+const { Endpoints } = require('../util/Constants');
+
+class RESTManager {
+ constructor(client, tokenPrefix = 'Bot') {
+ this.client = client;
+ this.handlers = new Collection();
+ this.tokenPrefix = tokenPrefix;
+ this.versioned = true;
+ this.globalTimeout = null;
+ if (client.options.restSweepInterval > 0) {
+ client.setInterval(() => {
+ this.handlers.sweep(handler => handler._inactive);
+ }, client.options.restSweepInterval * 1000);
+ }
+ }
+
+ get api() {
+ return routeBuilder(this);
+ }
+
+ getAuth() {
+ const token = this.client.token || this.client.accessToken;
+ if (token) return `${this.tokenPrefix} ${token}`;
+ throw new Error('TOKEN_MISSING');
+ }
+
+ get cdn() {
+ return Endpoints.CDN(this.client.options.http.cdn);
+ }
+
+ push(handler, apiRequest) {
+ return new Promise((resolve, reject) => {
+ handler
+ .push({
+ request: apiRequest,
+ resolve,
+ reject,
+ retries: 0,
+ })
+ .catch(reject);
+ });
+ }
+
+ request(method, url, options = {}) {
+ const apiRequest = new APIRequest(this, method, url, options);
+ let handler = this.handlers.get(apiRequest.route);
+
+ if (!handler) {
+ handler = new RequestHandler(this);
+ this.handlers.set(apiRequest.route, handler);
+ }
+
+ return this.push(handler, apiRequest);
+ }
+
+ set endpoint(endpoint) {
+ this.client.options.http.api = endpoint;
+ }
+}
+
+module.exports = RESTManager;
diff --git a/node_modules/discord.js/src/rest/RequestHandler.js b/node_modules/discord.js/src/rest/RequestHandler.js
new file mode 100644
index 0000000..27879f0
--- /dev/null
+++ b/node_modules/discord.js/src/rest/RequestHandler.js
@@ -0,0 +1,180 @@
+'use strict';
+
+const DiscordAPIError = require('./DiscordAPIError');
+const HTTPError = require('./HTTPError');
+const {
+ Events: { RATE_LIMIT },
+ browser,
+} = require('../util/Constants');
+const Util = require('../util/Util');
+
+function parseResponse(res) {
+ if (res.headers.get('content-type').startsWith('application/json')) return res.json();
+ if (browser) return res.blob();
+ return res.buffer();
+}
+
+function getAPIOffset(serverDate) {
+ return new Date(serverDate).getTime() - Date.now();
+}
+
+function calculateReset(reset, serverDate) {
+ return new Date(Number(reset) * 1000).getTime() - getAPIOffset(serverDate);
+}
+
+class RequestHandler {
+ constructor(manager) {
+ this.manager = manager;
+ this.busy = false;
+ this.queue = [];
+ this.reset = -1;
+ this.remaining = -1;
+ this.limit = -1;
+ this.retryAfter = -1;
+ }
+
+ push(request) {
+ if (this.busy) {
+ this.queue.push(request);
+ return this.run();
+ } else {
+ return this.execute(request);
+ }
+ }
+
+ run() {
+ if (this.queue.length === 0) return Promise.resolve();
+ return this.execute(this.queue.shift());
+ }
+
+ get limited() {
+ return Boolean(this.manager.globalTimeout) || (this.remaining <= 0 && Date.now() < this.reset);
+ }
+
+ get _inactive() {
+ return this.queue.length === 0 && !this.limited && this.busy !== true;
+ }
+
+ async execute(item) {
+ // Insert item back to the beginning if currently busy
+ if (this.busy) {
+ this.queue.unshift(item);
+ return null;
+ }
+
+ this.busy = true;
+ const { reject, request, resolve } = item;
+
+ // After calculations and requests have been done, pre-emptively stop further requests
+ if (this.limited) {
+ const timeout = this.reset + this.manager.client.options.restTimeOffset - Date.now();
+
+ if (this.manager.client.listenerCount(RATE_LIMIT)) {
+ /**
+ * Emitted when the client hits a rate limit while making a request
+ * @event Client#rateLimit
+ * @param {Object} rateLimitInfo Object containing the rate limit info
+ * @param {number} rateLimitInfo.timeout Timeout in ms
+ * @param {number} rateLimitInfo.limit Number of requests that can be made to this endpoint
+ * @param {string} rateLimitInfo.method HTTP method used for request that triggered this event
+ * @param {string} rateLimitInfo.path Path used for request that triggered this event
+ * @param {string} rateLimitInfo.route Route used for request that triggered this event
+ */
+ this.manager.client.emit(RATE_LIMIT, {
+ timeout,
+ limit: this.limit,
+ method: request.method,
+ path: request.path,
+ route: request.route,
+ });
+ }
+
+ if (this.manager.globalTimeout) {
+ await this.manager.globalTimeout;
+ } else {
+ // Wait for the timeout to expire in order to avoid an actual 429
+ await Util.delayFor(timeout);
+ }
+ }
+
+ // Perform the request
+ let res;
+ try {
+ res = await request.make();
+ } catch (error) {
+ // NodeFetch error expected for all "operational" errors, such as 500 status code
+ this.busy = false;
+ return reject(new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path));
+ }
+
+ if (res && res.headers) {
+ const serverDate = res.headers.get('date');
+ const limit = res.headers.get('x-ratelimit-limit');
+ const remaining = res.headers.get('x-ratelimit-remaining');
+ const reset = res.headers.get('x-ratelimit-reset');
+ const retryAfter = res.headers.get('retry-after');
+
+ this.limit = limit ? Number(limit) : Infinity;
+ this.remaining = remaining ? Number(remaining) : 1;
+ this.reset = reset ? calculateReset(reset, serverDate) : Date.now();
+ this.retryAfter = retryAfter ? Number(retryAfter) : -1;
+
+ // https://github.com/discordapp/discord-api-docs/issues/182
+ if (item.request.route.includes('reactions')) {
+ this.reset = new Date(serverDate).getTime() - getAPIOffset(serverDate) + 250;
+ }
+
+ // Handle global ratelimit
+ if (res.headers.get('x-ratelimit-global')) {
+ // Set the manager's global timeout as the promise for other requests to "wait"
+ this.manager.globalTimeout = Util.delayFor(this.retryAfter);
+
+ // Wait for the global timeout to resolve before continuing
+ await this.manager.globalTimeout;
+
+ // Clean up global timeout
+ this.manager.globalTimeout = null;
+ }
+ }
+
+ // Finished handling headers, safe to unlock manager
+ this.busy = false;
+
+ if (res.ok) {
+ const success = await parseResponse(res);
+ // Nothing wrong with the request, proceed with the next one
+ resolve(success);
+ return this.run();
+ } else if (res.status === 429) {
+ // A ratelimit was hit - this should never happen
+ this.queue.unshift(item);
+ this.manager.client.emit('debug', `429 hit on route ${item.request.route}`);
+ await Util.delayFor(this.retryAfter);
+ return this.run();
+ } else if (res.status >= 500 && res.status < 600) {
+ // Retry the specified number of times for possible serverside issues
+ if (item.retries === this.manager.client.options.retryLimit) {
+ return reject(
+ new HTTPError(res.statusText, res.constructor.name, res.status, item.request.method, request.path),
+ );
+ } else {
+ item.retries++;
+ this.queue.unshift(item);
+ return this.run();
+ }
+ } else {
+ // Handle possible malformed requests
+ try {
+ const data = await parseResponse(res);
+ if (res.status >= 400 && res.status < 500) {
+ return reject(new DiscordAPIError(request.path, data, request.method, res.status));
+ }
+ return null;
+ } catch (err) {
+ return reject(new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path));
+ }
+ }
+ }
+}
+
+module.exports = RequestHandler;
diff --git a/node_modules/discord.js/src/sharding/Shard.js b/node_modules/discord.js/src/sharding/Shard.js
new file mode 100644
index 0000000..3ef8b9b
--- /dev/null
+++ b/node_modules/discord.js/src/sharding/Shard.js
@@ -0,0 +1,383 @@
+'use strict';
+
+const EventEmitter = require('events');
+const path = require('path');
+const { Error } = require('../errors');
+const Util = require('../util/Util');
+let childProcess = null;
+let Worker = null;
+
+/**
+ * A self-contained shard created by the {@link ShardingManager}. Each one has a {@link ChildProcess} that contains
+ * an instance of the bot and its {@link Client}. When its child process/worker exits for any reason, the shard will
+ * spawn a new one to replace it as necessary.
+ * @extends EventEmitter
+ */
+class Shard extends EventEmitter {
+ /**
+ * @param {ShardingManager} manager Manager that is creating this shard
+ * @param {number} id ID of this shard
+ */
+ constructor(manager, id) {
+ super();
+
+ if (manager.mode === 'process') childProcess = require('child_process');
+ else if (manager.mode === 'worker') Worker = require('worker_threads').Worker;
+
+ /**
+ * Manager that created the shard
+ * @type {ShardingManager}
+ */
+ this.manager = manager;
+
+ /**
+ * ID of the shard in the manager
+ * @type {number}
+ */
+ this.id = id;
+
+ /**
+ * Arguments for the shard's process (only when {@link ShardingManager#mode} is `process`)
+ * @type {string[]}
+ */
+ this.args = manager.shardArgs || [];
+
+ /**
+ * Arguments for the shard's process executable (only when {@link ShardingManager#mode} is `process`)
+ * @type {?string[]}
+ */
+ this.execArgv = manager.execArgv;
+
+ /**
+ * Environment variables for the shard's process, or workerData for the shard's worker
+ * @type {Object}
+ */
+ this.env = Object.assign({}, process.env, {
+ SHARDING_MANAGER: true,
+ SHARDS: this.id,
+ SHARD_COUNT: this.manager.totalShards,
+ DISCORD_TOKEN: this.manager.token,
+ });
+
+ /**
+ * Whether the shard's {@link Client} is ready
+ * @type {boolean}
+ */
+ this.ready = false;
+
+ /**
+ * Process of the shard (if {@link ShardingManager#mode} is `process`)
+ * @type {?ChildProcess}
+ */
+ this.process = null;
+
+ /**
+ * Worker of the shard (if {@link ShardingManager#mode} is `worker`)
+ * @type {?Worker}
+ */
+ this.worker = null;
+
+ /**
+ * Ongoing promises for calls to {@link Shard#eval}, mapped by the `script` they were called with
+ * @type {Map<string, Promise>}
+ * @private
+ */
+ this._evals = new Map();
+
+ /**
+ * Ongoing promises for calls to {@link Shard#fetchClientValue}, mapped by the `prop` they were called with
+ * @type {Map<string, Promise>}
+ * @private
+ */
+ this._fetches = new Map();
+
+ /**
+ * Listener function for the {@link ChildProcess}' `exit` event
+ * @type {Function}
+ * @private
+ */
+ this._exitListener = this._handleExit.bind(this, undefined);
+ }
+
+ /**
+ * Forks a child process or creates a worker thread for the shard.
+ * <warn>You should not need to call this manually.</warn>
+ * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
+ * before resolving. (-1 or Infinity for no wait)
+ * @returns {Promise<ChildProcess>}
+ */
+ async spawn(spawnTimeout = 30000) {
+ if (this.process) throw new Error('SHARDING_PROCESS_EXISTS', this.id);
+ if (this.worker) throw new Error('SHARDING_WORKER_EXISTS', this.id);
+
+ if (this.manager.mode === 'process') {
+ this.process = childProcess
+ .fork(path.resolve(this.manager.file), this.args, {
+ env: this.env,
+ execArgv: this.execArgv,
+ })
+ .on('message', this._handleMessage.bind(this))
+ .on('exit', this._exitListener);
+ } else if (this.manager.mode === 'worker') {
+ this.worker = new Worker(path.resolve(this.manager.file), { workerData: this.env })
+ .on('message', this._handleMessage.bind(this))
+ .on('exit', this._exitListener);
+ }
+
+ /**
+ * Emitted upon the creation of the shard's child process/worker.
+ * @event Shard#spawn
+ * @param {ChildProcess|Worker} process Child process/worker that was created
+ */
+ this.emit('spawn', this.process || this.worker);
+
+ if (spawnTimeout === -1 || spawnTimeout === Infinity) return this.process || this.worker;
+ await new Promise((resolve, reject) => {
+ const cleanup = () => {
+ clearTimeout(spawnTimeoutTimer);
+ this.off('ready', onReady);
+ this.off('disconnect', onDisconnect);
+ this.off('death', onDeath);
+ };
+
+ const onReady = () => {
+ cleanup();
+ resolve();
+ };
+
+ const onDisconnect = () => {
+ cleanup();
+ reject(new Error('SHARDING_READY_DISCONNECTED', this.id));
+ };
+
+ const onDeath = () => {
+ cleanup();
+ reject(new Error('SHARDING_READY_DIED', this.id));
+ };
+
+ const onTimeout = () => {
+ cleanup();
+ reject(new Error('SHARDING_READY_TIMEOUT', this.id));
+ };
+
+ const spawnTimeoutTimer = setTimeout(onTimeout, spawnTimeout);
+ this.once('ready', onReady);
+ this.once('disconnect', onDisconnect);
+ this.once('death', onDeath);
+ });
+ return this.process || this.worker;
+ }
+
+ /**
+ * Immediately kills the shard's process/worker and does not restart it.
+ */
+ kill() {
+ if (this.process) {
+ this.process.removeListener('exit', this._exitListener);
+ this.process.kill();
+ } else {
+ this.worker.removeListener('exit', this._exitListener);
+ this.worker.terminate();
+ }
+
+ this._handleExit(false);
+ }
+
+ /**
+ * Kills and restarts the shard's process/worker.
+ * @param {number} [delay=500] How long to wait between killing the process/worker and restarting it (in milliseconds)
+ * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
+ * before resolving. (-1 or Infinity for no wait)
+ * @returns {Promise<ChildProcess>}
+ */
+ async respawn(delay = 500, spawnTimeout) {
+ this.kill();
+ if (delay > 0) await Util.delayFor(delay);
+ return this.spawn(spawnTimeout);
+ }
+
+ /**
+ * Sends a message to the shard's process/worker.
+ * @param {*} message Message to send to the shard
+ * @returns {Promise<Shard>}
+ */
+ send(message) {
+ return new Promise((resolve, reject) => {
+ if (this.process) {
+ this.process.send(message, err => {
+ if (err) reject(err);
+ else resolve(this);
+ });
+ } else {
+ this.worker.postMessage(message);
+ resolve(this);
+ }
+ });
+ }
+
+ /**
+ * Fetches a client property value of the shard.
+ * @param {string} prop Name of the client property to get, using periods for nesting
+ * @returns {Promise<*>}
+ * @example
+ * shard.fetchClientValue('guilds.cache.size')
+ * .then(count => console.log(`${count} guilds in shard ${shard.id}`))
+ * .catch(console.error);
+ */
+ fetchClientValue(prop) {
+ if (this._fetches.has(prop)) return this._fetches.get(prop);
+
+ const promise = new Promise((resolve, reject) => {
+ const child = this.process || this.worker;
+
+ const listener = message => {
+ if (!message || message._fetchProp !== prop) return;
+ child.removeListener('message', listener);
+ this._fetches.delete(prop);
+ resolve(message._result);
+ };
+ child.on('message', listener);
+
+ this.send({ _fetchProp: prop }).catch(err => {
+ child.removeListener('message', listener);
+ this._fetches.delete(prop);
+ reject(err);
+ });
+ });
+
+ this._fetches.set(prop, promise);
+ return promise;
+ }
+
+ /**
+ * Evaluates a script or function on the shard, in the context of the {@link Client}.
+ * @param {string|Function} script JavaScript to run on the shard
+ * @returns {Promise<*>} Result of the script execution
+ */
+ eval(script) {
+ if (this._evals.has(script)) return this._evals.get(script);
+
+ const promise = new Promise((resolve, reject) => {
+ const child = this.process || this.worker;
+
+ const listener = message => {
+ if (!message || message._eval !== script) return;
+ child.removeListener('message', listener);
+ this._evals.delete(script);
+ if (!message._error) resolve(message._result);
+ else reject(Util.makeError(message._error));
+ };
+ child.on('message', listener);
+
+ const _eval = typeof script === 'function' ? `(${script})(this)` : script;
+ this.send({ _eval }).catch(err => {
+ child.removeListener('message', listener);
+ this._evals.delete(script);
+ reject(err);
+ });
+ });
+
+ this._evals.set(script, promise);
+ return promise;
+ }
+
+ /**
+ * Handles a message received from the child process/worker.
+ * @param {*} message Message received
+ * @private
+ */
+ _handleMessage(message) {
+ if (message) {
+ // Shard is ready
+ if (message._ready) {
+ this.ready = true;
+ /**
+ * Emitted upon the shard's {@link Client#ready} event.
+ * @event Shard#ready
+ */
+ this.emit('ready');
+ return;
+ }
+
+ // Shard has disconnected
+ if (message._disconnect) {
+ this.ready = false;
+ /**
+ * Emitted upon the shard's {@link Client#disconnect} event.
+ * @event Shard#disconnect
+ */
+ this.emit('disconnect');
+ return;
+ }
+
+ // Shard is attempting to reconnect
+ if (message._reconnecting) {
+ this.ready = false;
+ /**
+ * Emitted upon the shard's {@link Client#reconnecting} event.
+ * @event Shard#reconnecting
+ */
+ this.emit('reconnecting');
+ return;
+ }
+
+ // Shard is requesting a property fetch
+ if (message._sFetchProp) {
+ this.manager.fetchClientValues(message._sFetchProp).then(
+ results => this.send({ _sFetchProp: message._sFetchProp, _result: results }),
+ err => this.send({ _sFetchProp: message._sFetchProp, _error: Util.makePlainError(err) }),
+ );
+ return;
+ }
+
+ // Shard is requesting an eval broadcast
+ if (message._sEval) {
+ this.manager.broadcastEval(message._sEval).then(
+ results => this.send({ _sEval: message._sEval, _result: results }),
+ err => this.send({ _sEval: message._sEval, _error: Util.makePlainError(err) }),
+ );
+ return;
+ }
+
+ // Shard is requesting a respawn of all shards
+ if (message._sRespawnAll) {
+ const { shardDelay, respawnDelay, spawnTimeout } = message._sRespawnAll;
+ this.manager.respawnAll(shardDelay, respawnDelay, spawnTimeout).catch(() => {
+ // Do nothing
+ });
+ return;
+ }
+ }
+
+ /**
+ * Emitted upon receiving a message from the child process/worker.
+ * @event Shard#message
+ * @param {*} message Message that was received
+ */
+ this.emit('message', message);
+ }
+
+ /**
+ * Handles the shard's process/worker exiting.
+ * @param {boolean} [respawn=this.manager.respawn] Whether to spawn the shard again
+ * @private
+ */
+ _handleExit(respawn = this.manager.respawn) {
+ /**
+ * Emitted upon the shard's child process/worker exiting.
+ * @event Shard#death
+ * @param {ChildProcess|Worker} process Child process/worker that exited
+ */
+ this.emit('death', this.process || this.worker);
+
+ this.ready = false;
+ this.process = null;
+ this.worker = null;
+ this._evals.clear();
+ this._fetches.clear();
+
+ if (respawn) this.spawn().catch(err => this.emit('error', err));
+ }
+}
+
+module.exports = Shard;
diff --git a/node_modules/discord.js/src/sharding/ShardClientUtil.js b/node_modules/discord.js/src/sharding/ShardClientUtil.js
new file mode 100644
index 0000000..79345d8
--- /dev/null
+++ b/node_modules/discord.js/src/sharding/ShardClientUtil.js
@@ -0,0 +1,229 @@
+'use strict';
+
+const { Events } = require('../util/Constants');
+const Util = require('../util/Util');
+
+/**
+ * Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}.
+ * Utilises IPC to send and receive data to/from the master process and other shards.
+ */
+class ShardClientUtil {
+ /**
+ * @param {Client} client Client of the current shard
+ * @param {ShardingManagerMode} mode Mode the shard was spawned with
+ */
+ constructor(client, mode) {
+ /**
+ * Client for the shard
+ * @type {Client}
+ */
+ this.client = client;
+
+ /**
+ * Mode the shard was spawned with
+ * @type {ShardingManagerMode}
+ */
+ this.mode = mode;
+
+ /**
+ * Message port for the master process (only when {@link ShardClientUtil#mode} is `worker`)
+ * @type {?MessagePort}
+ */
+ this.parentPort = null;
+
+ if (mode === 'process') {
+ process.on('message', this._handleMessage.bind(this));
+ client.on('ready', () => {
+ process.send({ _ready: true });
+ });
+ client.on('disconnect', () => {
+ process.send({ _disconnect: true });
+ });
+ client.on('reconnecting', () => {
+ process.send({ _reconnecting: true });
+ });
+ } else if (mode === 'worker') {
+ this.parentPort = require('worker_threads').parentPort;
+ this.parentPort.on('message', this._handleMessage.bind(this));
+ client.on('ready', () => {
+ this.parentPort.postMessage({ _ready: true });
+ });
+ client.on('disconnect', () => {
+ this.parentPort.postMessage({ _disconnect: true });
+ });
+ client.on('reconnecting', () => {
+ this.parentPort.postMessage({ _reconnecting: true });
+ });
+ }
+ }
+
+ /**
+ * Array of shard IDs of this client
+ * @type {number[]}
+ * @readonly
+ */
+ get ids() {
+ return this.client.options.shards;
+ }
+
+ /**
+ * Total number of shards
+ * @type {number}
+ * @readonly
+ */
+ get count() {
+ return this.client.options.shardCount;
+ }
+
+ /**
+ * Sends a message to the master process.
+ * @param {*} message Message to send
+ * @returns {Promise<void>}
+ * @emits Shard#message
+ */
+ send(message) {
+ return new Promise((resolve, reject) => {
+ if (this.mode === 'process') {
+ process.send(message, err => {
+ if (err) reject(err);
+ else resolve();
+ });
+ } else if (this.mode === 'worker') {
+ this.parentPort.postMessage(message);
+ resolve();
+ }
+ });
+ }
+
+ /**
+ * Fetches a client property value of each shard.
+ * @param {string} prop Name of the client property to get, using periods for nesting
+ * @returns {Promise<Array<*>>}
+ * @example
+ * client.shard.fetchClientValues('guilds.cache.size')
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
+ * .catch(console.error);
+ * @see {@link ShardingManager#fetchClientValues}
+ */
+ fetchClientValues(prop) {
+ return new Promise((resolve, reject) => {
+ const parent = this.parentPort || process;
+
+ const listener = message => {
+ if (!message || message._sFetchProp !== prop) return;
+ parent.removeListener('message', listener);
+ if (!message._error) resolve(message._result);
+ else reject(Util.makeError(message._error));
+ };
+ parent.on('message', listener);
+
+ this.send({ _sFetchProp: prop }).catch(err => {
+ parent.removeListener('message', listener);
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * Evaluates a script or function on all shards, in the context of the {@link Clients}.
+ * @param {string|Function} script JavaScript to run on each shard
+ * @returns {Promise<Array<*>>} Results of the script execution
+ * @example
+ * client.shard.broadcastEval('this.guilds.cache.size')
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
+ * .catch(console.error);
+ * @see {@link ShardingManager#broadcastEval}
+ */
+ broadcastEval(script) {
+ return new Promise((resolve, reject) => {
+ const parent = this.parentPort || process;
+ script = typeof script === 'function' ? `(${script})(this)` : script;
+
+ const listener = message => {
+ if (!message || message._sEval !== script) return;
+ parent.removeListener('message', listener);
+ if (!message._error) resolve(message._result);
+ else reject(Util.makeError(message._error));
+ };
+ parent.on('message', listener);
+
+ this.send({ _sEval: script }).catch(err => {
+ parent.removeListener('message', listener);
+ reject(err);
+ });
+ });
+ }
+
+ /**
+ * Requests a respawn of all shards.
+ * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
+ * @param {number} [respawnDelay=500] How long to wait between killing a shard's process/worker and restarting it
+ * (in milliseconds)
+ * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before
+ * continuing to another. (-1 or Infinity for no wait)
+ * @returns {Promise<void>} Resolves upon the message being sent
+ * @see {@link ShardingManager#respawnAll}
+ */
+ respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout = 30000) {
+ return this.send({ _sRespawnAll: { shardDelay, respawnDelay, spawnTimeout } });
+ }
+
+ /**
+ * Handles an IPC message.
+ * @param {*} message Message received
+ * @private
+ */
+ async _handleMessage(message) {
+ if (!message) return;
+ if (message._fetchProp) {
+ const props = message._fetchProp.split('.');
+ let value = this.client;
+ for (const prop of props) value = value[prop];
+ this._respond('fetchProp', { _fetchProp: message._fetchProp, _result: value });
+ } else if (message._eval) {
+ try {
+ this._respond('eval', { _eval: message._eval, _result: await this.client._eval(message._eval) });
+ } catch (err) {
+ this._respond('eval', { _eval: message._eval, _error: Util.makePlainError(err) });
+ }
+ }
+ }
+
+ /**
+ * Sends a message to the master process, emitting an error from the client upon failure.
+ * @param {string} type Type of response to send
+ * @param {*} message Message to send
+ * @private
+ */
+ _respond(type, message) {
+ this.send(message).catch(err => {
+ err.message = `Error when sending ${type} response to master process: ${err.message}`;
+ /**
+ * Emitted when the client encounters an error.
+ * @event Client#error
+ * @param {Error} error The error encountered
+ */
+ this.client.emit(Events.ERROR, err);
+ });
+ }
+
+ /**
+ * Creates/gets the singleton of this class.
+ * @param {Client} client The client to use
+ * @param {ShardingManagerMode} mode Mode the shard was spawned with
+ * @returns {ShardClientUtil}
+ */
+ static singleton(client, mode) {
+ if (!this._singleton) {
+ this._singleton = new this(client, mode);
+ } else {
+ client.emit(
+ Events.WARN,
+ 'Multiple clients created in child process/worker; only the first will handle sharding helpers.',
+ );
+ }
+ return this._singleton;
+ }
+}
+
+module.exports = ShardClientUtil;
diff --git a/node_modules/discord.js/src/sharding/ShardingManager.js b/node_modules/discord.js/src/sharding/ShardingManager.js
new file mode 100644
index 0000000..0b9fdd9
--- /dev/null
+++ b/node_modules/discord.js/src/sharding/ShardingManager.js
@@ -0,0 +1,274 @@
+'use strict';
+
+const EventEmitter = require('events');
+const fs = require('fs');
+const path = require('path');
+const Shard = require('./Shard');
+const { Error, TypeError, RangeError } = require('../errors');
+const Collection = require('../util/Collection');
+const Util = require('../util/Util');
+
+/**
+ * This is a utility class that makes multi-process sharding of a bot an easy and painless experience.
+ * It works by spawning a self-contained {@link ChildProcess} or {@link Worker} for each individual shard, each
+ * containing its own instance of your bot's {@link Client}. They all have a line of communication with the master
+ * process, and there are several useful methods that utilise it in order to simplify tasks that are normally difficult
+ * with sharding. It can spawn a specific number of shards or the amount that Discord suggests for the bot, and takes a
+ * path to your main bot script to launch for each one.
+ * @extends {EventEmitter}
+ */
+class ShardingManager extends EventEmitter {
+ /**
+ * The mode to spawn shards with for a {@link ShardingManager}: either "process" to use child processes, or
+ * "worker" to use workers. The "worker" mode relies on the experimental
+ * [Worker threads](https://nodejs.org/api/worker_threads.html) functionality that is present in Node v10.5.0 or
+ * newer. Node must be started with the `--experimental-worker` flag to expose it.
+ * @typedef {Object} ShardingManagerMode
+ */
+
+ /**
+ * @param {string} file Path to your shard script file
+ * @param {Object} [options] Options for the sharding manager
+ * @param {string|number} [options.totalShards='auto'] Number of total shards of all shard managers or "auto"
+ * @param {string|number[]} [options.shardList='auto'] List of shards to spawn or "auto"
+ * @param {ShardingManagerMode} [options.mode='process'] Which mode to use for shards
+ * @param {boolean} [options.respawn=true] Whether shards should automatically respawn upon exiting
+ * @param {string[]} [options.shardArgs=[]] Arguments to pass to the shard script when spawning
+ * (only available when using the `process` mode)
+ * @param {string[]} [options.execArgv=[]] Arguments to pass to the shard script executable when spawning
+ * (only available when using the `process` mode)
+ * @param {string} [options.token] Token to use for automatic shard count and passing to shards
+ */
+ constructor(file, options = {}) {
+ super();
+ options = Util.mergeDefault(
+ {
+ totalShards: 'auto',
+ mode: 'process',
+ respawn: true,
+ shardArgs: [],
+ execArgv: [],
+ token: process.env.DISCORD_TOKEN,
+ },
+ options,
+ );
+
+ /**
+ * Path to the shard script file
+ * @type {string}
+ */
+ this.file = file;
+ if (!file) throw new Error('CLIENT_INVALID_OPTION', 'File', 'specified.');
+ if (!path.isAbsolute(file)) this.file = path.resolve(process.cwd(), file);
+ const stats = fs.statSync(this.file);
+ if (!stats.isFile()) throw new Error('CLIENT_INVALID_OPTION', 'File', 'a file');
+
+ /**
+ * List of shards this sharding manager spawns
+ * @type {string|number[]}
+ */
+ this.shardList = options.shardList || 'auto';
+ if (this.shardList !== 'auto') {
+ if (!Array.isArray(this.shardList)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.');
+ }
+ this.shardList = [...new Set(this.shardList)];
+ if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 ID.');
+ if (
+ this.shardList.some(
+ shardID => typeof shardID !== 'number' || isNaN(shardID) || !Number.isInteger(shardID) || shardID < 0,
+ )
+ ) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of positive integers.');
+ }
+ }
+
+ /**
+ * Amount of shards that all sharding managers spawn in total
+ * @type {number}
+ */
+ this.totalShards = options.totalShards || 'auto';
+ if (this.totalShards !== 'auto') {
+ if (typeof this.totalShards !== 'number' || isNaN(this.totalShards)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
+ }
+ if (this.totalShards < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
+ if (!Number.isInteger(this.totalShards)) {
+ throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
+ }
+ }
+
+ /**
+ * Mode for shards to spawn with
+ * @type {ShardingManagerMode}
+ */
+ this.mode = options.mode;
+ if (this.mode !== 'process' && this.mode !== 'worker') {
+ throw new RangeError('CLIENT_INVALID_OPTION', 'Sharding mode', '"process" or "worker"');
+ }
+
+ /**
+ * Whether shards should automatically respawn upon exiting
+ * @type {boolean}
+ */
+ this.respawn = options.respawn;
+
+ /**
+ * An array of arguments to pass to shards (only when {@link ShardingManager#mode} is `process`)
+ * @type {string[]}
+ */
+ this.shardArgs = options.shardArgs;
+
+ /**
+ * An array of arguments to pass to the executable (only when {@link ShardingManager#mode} is `process`)
+ * @type {string[]}
+ */
+ this.execArgv = options.execArgv;
+
+ /**
+ * Token to use for obtaining the automatic shard count, and passing to shards
+ * @type {?string}
+ */
+ this.token = options.token ? options.token.replace(/^Bot\s*/i, '') : null;
+
+ /**
+ * A collection of shards that this manager has spawned
+ * @type {Collection<number, Shard>}
+ */
+ this.shards = new Collection();
+
+ process.env.SHARDING_MANAGER = true;
+ process.env.SHARDING_MANAGER_MODE = this.mode;
+ process.env.DISCORD_TOKEN = this.token;
+ }
+
+ /**
+ * Creates a single shard.
+ * <warn>Using this method is usually not necessary if you use the spawn method.</warn>
+ * @param {number} [id=this.shards.size] ID of the shard to create
+ * <info>This is usually not necessary to manually specify.</info>
+ * @returns {Shard} Note that the created shard needs to be explicitly spawned using its spawn method.
+ */
+ createShard(id = this.shards.size) {
+ const shard = new Shard(this, id);
+ this.shards.set(id, shard);
+ /**
+ * Emitted upon creating a shard.
+ * @event ShardingManager#shardCreate
+ * @param {Shard} shard Shard that was created
+ */
+ this.emit('shardCreate', shard);
+ return shard;
+ }
+
+ /**
+ * Spawns multiple shards.
+ * @param {number|string} [amount=this.totalShards] Number of shards to spawn
+ * @param {number} [delay=5500] How long to wait in between spawning each shard (in milliseconds)
+ * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait until the {@link Client} has become ready
+ * before resolving. (-1 or Infinity for no wait)
+ * @returns {Promise<Collection<number, Shard>>}
+ */
+ async spawn(amount = this.totalShards, delay = 5500, spawnTimeout) {
+ // Obtain/verify the number of shards to spawn
+ if (amount === 'auto') {
+ amount = await Util.fetchRecommendedShards(this.token);
+ } else {
+ if (typeof amount !== 'number' || isNaN(amount)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'a number.');
+ }
+ if (amount < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'at least 1.');
+ if (!Number.isInteger(amount)) {
+ throw new TypeError('CLIENT_INVALID_OPTION', 'Amount of shards', 'an integer.');
+ }
+ }
+
+ // Make sure this many shards haven't already been spawned
+ if (this.shards.size >= amount) throw new Error('SHARDING_ALREADY_SPAWNED', this.shards.size);
+ if (this.shardList === 'auto' || this.totalShards === 'auto' || this.totalShards !== amount) {
+ this.shardList = [...Array(amount).keys()];
+ }
+ if (this.totalShards === 'auto' || this.totalShards !== amount) {
+ this.totalShards = amount;
+ }
+
+ if (this.shardList.some(shardID => shardID >= amount)) {
+ throw new RangeError(
+ 'CLIENT_INVALID_OPTION',
+ 'Amount of shards',
+ 'bigger than the highest shardID in the shardList option.',
+ );
+ }
+
+ // Spawn the shards
+ for (const shardID of this.shardList) {
+ const promises = [];
+ const shard = this.createShard(shardID);
+ promises.push(shard.spawn(spawnTimeout));
+ if (delay > 0 && this.shards.size !== this.shardList.length) promises.push(Util.delayFor(delay));
+ await Promise.all(promises); // eslint-disable-line no-await-in-loop
+ }
+
+ return this.shards;
+ }
+
+ /**
+ * Sends a message to all shards.
+ * @param {*} message Message to be sent to the shards
+ * @returns {Promise<Shard[]>}
+ */
+ broadcast(message) {
+ const promises = [];
+ for (const shard of this.shards.values()) promises.push(shard.send(message));
+ return Promise.all(promises);
+ }
+
+ /**
+ * Evaluates a script on all shards, in the context of the {@link Client}s.
+ * @param {string} script JavaScript to run on each shard
+ * @returns {Promise<Array<*>>} Results of the script execution
+ */
+ broadcastEval(script) {
+ const promises = [];
+ for (const shard of this.shards.values()) promises.push(shard.eval(script));
+ return Promise.all(promises);
+ }
+
+ /**
+ * Fetches a client property value of each shard.
+ * @param {string} prop Name of the client property to get, using periods for nesting
+ * @returns {Promise<Array<*>>}
+ * @example
+ * manager.fetchClientValues('guilds.cache.size')
+ * .then(results => console.log(`${results.reduce((prev, val) => prev + val, 0)} total guilds`))
+ * .catch(console.error);
+ */
+ fetchClientValues(prop) {
+ if (this.shards.size === 0) return Promise.reject(new Error('SHARDING_NO_SHARDS'));
+ if (this.shards.size !== this.shardList.length) return Promise.reject(new Error('SHARDING_IN_PROCESS'));
+ const promises = [];
+ for (const shard of this.shards.values()) promises.push(shard.fetchClientValue(prop));
+ return Promise.all(promises);
+ }
+
+ /**
+ * Kills all running shards and respawns them.
+ * @param {number} [shardDelay=5000] How long to wait between shards (in milliseconds)
+ * @param {number} [respawnDelay=500] How long to wait between killing a shard's process and restarting it
+ * (in milliseconds)
+ * @param {number} [spawnTimeout=30000] The amount in milliseconds to wait for a shard to become ready before
+ * continuing to another. (-1 or Infinity for no wait)
+ * @returns {Promise<Collection<string, Shard>>}
+ */
+ async respawnAll(shardDelay = 5000, respawnDelay = 500, spawnTimeout) {
+ let s = 0;
+ for (const shard of this.shards.values()) {
+ const promises = [shard.respawn(respawnDelay, spawnTimeout)];
+ if (++s < this.shards.size && shardDelay > 0) promises.push(Util.delayFor(shardDelay));
+ await Promise.all(promises); // eslint-disable-line no-await-in-loop
+ }
+ return this.shards;
+ }
+}
+
+module.exports = ShardingManager;
diff --git a/node_modules/discord.js/src/structures/APIMessage.js b/node_modules/discord.js/src/structures/APIMessage.js
new file mode 100644
index 0000000..86dab74
--- /dev/null
+++ b/node_modules/discord.js/src/structures/APIMessage.js
@@ -0,0 +1,379 @@
+'use strict';
+
+const MessageAttachment = require('./MessageAttachment');
+const MessageEmbed = require('./MessageEmbed');
+const { RangeError } = require('../errors');
+const { browser } = require('../util/Constants');
+const DataResolver = require('../util/DataResolver');
+const MessageFlags = require('../util/MessageFlags');
+const Util = require('../util/Util');
+
+/**
+ * Represents a message to be sent to the API.
+ */
+class APIMessage {
+ /**
+ * @param {MessageTarget} target - The target for this message to be sent to
+ * @param {MessageOptions|WebhookMessageOptions} options - Options passed in from send
+ */
+ constructor(target, options) {
+ /**
+ * The target for this message to be sent to
+ * @type {MessageTarget}
+ */
+ this.target = target;
+
+ /**
+ * Options passed in from send
+ * @type {MessageOptions|WebhookMessageOptions}
+ */
+ this.options = options;
+
+ /**
+ * Data sendable to the API
+ * @type {?Object}
+ */
+ this.data = null;
+
+ /**
+ * Files sendable to the API
+ * @type {?Object[]}
+ */
+ this.files = null;
+ }
+
+ /**
+ * Whether or not the target is a webhook
+ * @type {boolean}
+ * @readonly
+ */
+ get isWebhook() {
+ const Webhook = require('./Webhook');
+ const WebhookClient = require('../client/WebhookClient');
+ return this.target instanceof Webhook || this.target instanceof WebhookClient;
+ }
+
+ /**
+ * Whether or not the target is a user
+ * @type {boolean}
+ * @readonly
+ */
+ get isUser() {
+ const User = require('./User');
+ const GuildMember = require('./GuildMember');
+ return this.target instanceof User || this.target instanceof GuildMember;
+ }
+
+ /**
+ * Whether or not the target is a message
+ * @type {boolean}
+ * @readonly
+ */
+ get isMessage() {
+ const Message = require('./Message');
+ return this.target instanceof Message;
+ }
+
+ /**
+ * Makes the content of this message.
+ * @returns {?(string|string[])}
+ */
+ makeContent() {
+ const GuildMember = require('./GuildMember');
+
+ let content;
+ if (this.options.content === null) {
+ content = '';
+ } else if (typeof this.options.content !== 'undefined') {
+ content = Util.resolveString(this.options.content);
+ }
+
+ const disableMentions =
+ typeof this.options.disableMentions === 'undefined'
+ ? this.target.client.options.disableMentions
+ : this.options.disableMentions;
+ if (disableMentions === 'all') {
+ content = Util.removeMentions(content || '');
+ } else if (disableMentions === 'everyone') {
+ content = (content || '').replace(/@([^<>@ ]*)/gmsu, (match, target) => {
+ if (target.match(/^[&!]?\d+$/)) {
+ return `@${target}`;
+ } else {
+ return `@\u200b${target}`;
+ }
+ });
+ }
+
+ const isSplit = typeof this.options.split !== 'undefined' && this.options.split !== false;
+ const isCode = typeof this.options.code !== 'undefined' && this.options.code !== false;
+ const splitOptions = isSplit ? { ...this.options.split } : undefined;
+
+ let mentionPart = '';
+ if (this.options.reply && !this.isUser && this.target.type !== 'dm') {
+ const id = this.target.client.users.resolveID(this.options.reply);
+ mentionPart = `<@${this.options.reply instanceof GuildMember && this.options.reply.nickname ? '!' : ''}${id}>, `;
+ if (isSplit) {
+ splitOptions.prepend = `${mentionPart}${splitOptions.prepend || ''}`;
+ }
+ }
+
+ if (content || mentionPart) {
+ if (isCode) {
+ const codeName = typeof this.options.code === 'string' ? this.options.code : '';
+ content = `${mentionPart}\`\`\`${codeName}\n${Util.cleanCodeBlockContent(content || '')}\n\`\`\``;
+ if (isSplit) {
+ splitOptions.prepend = `${splitOptions.prepend || ''}\`\`\`${codeName}\n`;
+ splitOptions.append = `\n\`\`\`${splitOptions.append || ''}`;
+ }
+ } else if (mentionPart) {
+ content = `${mentionPart}${content || ''}`;
+ }
+
+ if (isSplit) {
+ content = Util.splitMessage(content || '', splitOptions);
+ }
+ }
+
+ return content;
+ }
+
+ /**
+ * Resolves data.
+ * @returns {APIMessage}
+ */
+ resolveData() {
+ if (this.data) return this;
+
+ const content = this.makeContent();
+ const tts = Boolean(this.options.tts);
+
+ let nonce;
+ if (typeof this.options.nonce !== 'undefined') {
+ nonce = parseInt(this.options.nonce);
+ if (isNaN(nonce) || nonce < 0) throw new RangeError('MESSAGE_NONCE_TYPE');
+ }
+
+ const embedLikes = [];
+ if (this.isWebhook) {
+ if (this.options.embeds) {
+ embedLikes.push(...this.options.embeds);
+ }
+ } else if (this.options.embed) {
+ embedLikes.push(this.options.embed);
+ }
+ const embeds = embedLikes.map(e => new MessageEmbed(e).toJSON());
+
+ let username;
+ let avatarURL;
+ if (this.isWebhook) {
+ username = this.options.username || this.target.name;
+ if (this.options.avatarURL) avatarURL = this.options.avatarURL;
+ }
+
+ let flags;
+ if (this.isMessage) {
+ // eslint-disable-next-line eqeqeq
+ flags = this.options.flags != null ? new MessageFlags(this.options.flags).bitfield : this.target.flags.bitfield;
+ }
+
+ const allowedMentions =
+ typeof this.options.allowedMentions === 'undefined'
+ ? this.target.client.options.allowedMentions
+ : this.options.allowedMentions;
+
+ this.data = {
+ content,
+ tts,
+ nonce,
+ embed: this.options.embed === null ? null : embeds[0],
+ embeds,
+ username,
+ avatar_url: avatarURL,
+ allowed_mentions: allowedMentions,
+ flags,
+ };
+ return this;
+ }
+
+ /**
+ * Resolves files.
+ * @returns {Promise<APIMessage>}
+ */
+ async resolveFiles() {
+ if (this.files) return this;
+
+ const embedLikes = [];
+ if (this.isWebhook) {
+ if (this.options.embeds) {
+ embedLikes.push(...this.options.embeds);
+ }
+ } else if (this.options.embed) {
+ embedLikes.push(this.options.embed);
+ }
+
+ const fileLikes = [];
+ if (this.options.files) {
+ fileLikes.push(...this.options.files);
+ }
+ for (const embed of embedLikes) {
+ if (embed.files) {
+ fileLikes.push(...embed.files);
+ }
+ }
+
+ this.files = await Promise.all(fileLikes.map(f => this.constructor.resolveFile(f)));
+ return this;
+ }
+
+ /**
+ * Converts this APIMessage into an array of APIMessages for each split content
+ * @returns {APIMessage[]}
+ */
+ split() {
+ if (!this.data) this.resolveData();
+
+ if (!Array.isArray(this.data.content)) return [this];
+
+ const apiMessages = [];
+
+ for (let i = 0; i < this.data.content.length; i++) {
+ let data;
+ let opt;
+
+ if (i === this.data.content.length - 1) {
+ data = { ...this.data, content: this.data.content[i] };
+ opt = { ...this.options, content: this.data.content[i] };
+ } else {
+ data = { content: this.data.content[i], tts: this.data.tts };
+ opt = { content: this.data.content[i], tts: this.data.tts };
+ }
+
+ const apiMessage = new APIMessage(this.target, opt);
+ apiMessage.data = data;
+ apiMessages.push(apiMessage);
+ }
+
+ return apiMessages;
+ }
+
+ /**
+ * Resolves a single file into an object sendable to the API.
+ * @param {BufferResolvable|Stream|FileOptions|MessageAttachment} fileLike Something that could be resolved to a file
+ * @returns {Object}
+ */
+ static async resolveFile(fileLike) {
+ let attachment;
+ let name;
+
+ const findName = thing => {
+ if (typeof thing === 'string') {
+ return Util.basename(thing);
+ }
+
+ if (thing.path) {
+ return Util.basename(thing.path);
+ }
+
+ return 'file.jpg';
+ };
+
+ const ownAttachment =
+ typeof fileLike === 'string' ||
+ fileLike instanceof (browser ? ArrayBuffer : Buffer) ||
+ typeof fileLike.pipe === 'function';
+ if (ownAttachment) {
+ attachment = fileLike;
+ name = findName(attachment);
+ } else {
+ attachment = fileLike.attachment;
+ name = fileLike.name || findName(attachment);
+ }
+
+ const resource = await DataResolver.resolveFile(attachment);
+ return { attachment, name, file: resource };
+ }
+
+ /**
+ * Partitions embeds and attachments.
+ * @param {Array<MessageEmbed|MessageAttachment>} items Items to partition
+ * @returns {Array<MessageEmbed[], MessageAttachment[]>}
+ */
+ static partitionMessageAdditions(items) {
+ const embeds = [];
+ const files = [];
+ for (const item of items) {
+ if (item instanceof MessageEmbed) {
+ embeds.push(item);
+ } else if (item instanceof MessageAttachment) {
+ files.push(item);
+ }
+ }
+
+ return [embeds, files];
+ }
+
+ /**
+ * Transforms the user-level arguments into a final options object. Passing a transformed options object alone into
+ * this method will keep it the same, allowing for the reuse of the final options object.
+ * @param {StringResolvable} [content] Content to send
+ * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use
+ * @param {MessageOptions|WebhookMessageOptions} [extra={}] Extra options to add onto transformed options
+ * @param {boolean} [isWebhook=false] Whether or not to use WebhookMessageOptions as the result
+ * @returns {MessageOptions|WebhookMessageOptions}
+ */
+ static transformOptions(content, options, extra = {}, isWebhook = false) {
+ if (!options && typeof content === 'object' && !Array.isArray(content)) {
+ options = content;
+ content = undefined;
+ }
+
+ if (!options) {
+ options = {};
+ } else if (options instanceof MessageEmbed) {
+ return isWebhook ? { content, embeds: [options], ...extra } : { content, embed: options, ...extra };
+ } else if (options instanceof MessageAttachment) {
+ return { content, files: [options], ...extra };
+ }
+
+ if (Array.isArray(options)) {
+ const [embeds, files] = this.partitionMessageAdditions(options);
+ return isWebhook ? { content, embeds, files, ...extra } : { content, embed: embeds[0], files, ...extra };
+ } else if (Array.isArray(content)) {
+ const [embeds, files] = this.partitionMessageAdditions(content);
+ if (embeds.length || files.length) {
+ return isWebhook ? { embeds, files, ...extra } : { embed: embeds[0], files, ...extra };
+ }
+ }
+
+ return { content, ...options, ...extra };
+ }
+
+ /**
+ * Creates an `APIMessage` from user-level arguments.
+ * @param {MessageTarget} target Target to send to
+ * @param {StringResolvable} [content] Content to send
+ * @param {MessageOptions|WebhookMessageOptions|MessageAdditions} [options={}] Options to use
+ * @param {MessageOptions|WebhookMessageOptions} [extra={}] - Extra options to add onto transformed options
+ * @returns {MessageOptions|WebhookMessageOptions}
+ */
+ static create(target, content, options, extra = {}) {
+ const Webhook = require('./Webhook');
+ const WebhookClient = require('../client/WebhookClient');
+
+ const isWebhook = target instanceof Webhook || target instanceof WebhookClient;
+ const transformed = this.transformOptions(content, options, extra, isWebhook);
+ return new this(target, transformed);
+ }
+}
+
+module.exports = APIMessage;
+
+/**
+ * A target for a message.
+ * @typedef {TextChannel|DMChannel|User|GuildMember|Webhook|WebhookClient} MessageTarget
+ */
+
+/**
+ * Additional items that can be sent with a message.
+ * @typedef {MessageEmbed|MessageAttachment|Array<MessageEmbed|MessageAttachment>} MessageAdditions
+ */
diff --git a/node_modules/discord.js/src/structures/Base.js b/node_modules/discord.js/src/structures/Base.js
new file mode 100644
index 0000000..65c1fa5
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Base.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const Util = require('../util/Util');
+
+/**
+ * Represents a data model that is identifiable by a Snowflake (i.e. Discord API data models).
+ */
+class Base {
+ constructor(client) {
+ /**
+ * The client that instantiated this
+ * @name Base#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+ }
+
+ _clone() {
+ return Object.assign(Object.create(this), this);
+ }
+
+ _patch(data) {
+ return data;
+ }
+
+ _update(data) {
+ const clone = this._clone();
+ this._patch(data);
+ return clone;
+ }
+
+ toJSON(...props) {
+ return Util.flatten(this, ...props);
+ }
+
+ valueOf() {
+ return this.id;
+ }
+}
+
+module.exports = Base;
diff --git a/node_modules/discord.js/src/structures/BaseGuildEmoji.js b/node_modules/discord.js/src/structures/BaseGuildEmoji.js
new file mode 100644
index 0000000..d366527
--- /dev/null
+++ b/node_modules/discord.js/src/structures/BaseGuildEmoji.js
@@ -0,0 +1,58 @@
+'use strict';
+
+const Emoji = require('./Emoji');
+
+/**
+ * Parent class for {@link GuildEmoji} and {@link GuildPreviewEmoji}.
+ * @extends {Emoji}
+ */
+class BaseGuildEmoji extends Emoji {
+ constructor(client, data, guild) {
+ super(client, data);
+
+ /**
+ * The guild this emoji is a part of
+ * @type {Guild|GuildPreview}
+ */
+ this.guild = guild;
+
+ /**
+ * Array of role ids this emoji is active for
+ * @name BaseGuildEmoji#_roles
+ * @type {Snowflake[]}
+ * @private
+ */
+ Object.defineProperty(this, '_roles', { value: [], writable: true });
+
+ this._patch(data);
+ }
+
+ _patch(data) {
+ if (data.name) this.name = data.name;
+
+ /**
+ * Whether or not this emoji requires colons surrounding it
+ * @type {boolean}
+ * @name GuildEmoji#requiresColons
+ */
+ if (typeof data.require_colons !== 'undefined') this.requiresColons = data.require_colons;
+
+ /**
+ * Whether this emoji is managed by an external service
+ * @type {boolean}
+ * @name GuildEmoji#managed
+ */
+ if (typeof data.managed !== 'undefined') this.managed = data.managed;
+
+ /**
+ * Whether this emoji is available
+ * @type {boolean}
+ * @name GuildEmoji#available
+ */
+ if (typeof data.available !== 'undefined') this.available = data.available;
+
+ if (data.roles) this._roles = data.roles;
+ }
+}
+
+module.exports = BaseGuildEmoji;
diff --git a/node_modules/discord.js/src/structures/CategoryChannel.js b/node_modules/discord.js/src/structures/CategoryChannel.js
new file mode 100644
index 0000000..4ac9fbb
--- /dev/null
+++ b/node_modules/discord.js/src/structures/CategoryChannel.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const GuildChannel = require('./GuildChannel');
+
+/**
+ * Represents a guild category channel on Discord.
+ * @extends {GuildChannel}
+ */
+class CategoryChannel extends GuildChannel {
+ /**
+ * Channels that are a part of this category
+ * @type {?Collection<Snowflake, GuildChannel>}
+ * @readonly
+ */
+ get children() {
+ return this.guild.channels.cache.filter(c => c.parentID === this.id);
+ }
+
+ /**
+ * Sets the category parent of this channel.
+ * <warn>It is not currently possible to set the parent of a CategoryChannel.</warn>
+ * @method setParent
+ * @memberof CategoryChannel
+ * @instance
+ * @param {?GuildChannel|Snowflake} channel Parent channel
+ * @param {Object} [options={}] Options to pass
+ * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are
+ * @param {string} [options.reason] Reason for modifying the parent of this channel
+ * @returns {Promise<GuildChannel>}
+ */
+}
+
+module.exports = CategoryChannel;
diff --git a/node_modules/discord.js/src/structures/Channel.js b/node_modules/discord.js/src/structures/Channel.js
new file mode 100644
index 0000000..1dc7ee0
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Channel.js
@@ -0,0 +1,151 @@
+'use strict';
+
+const Base = require('./Base');
+const { ChannelTypes } = require('../util/Constants');
+const Snowflake = require('../util/Snowflake');
+
+/**
+ * Represents any channel on Discord.
+ * @extends {Base}
+ */
+class Channel extends Base {
+ constructor(client, data) {
+ super(client);
+
+ const type = Object.keys(ChannelTypes)[data.type];
+ /**
+ * The type of the channel, either:
+ * * `dm` - a DM channel
+ * * `text` - a guild text channel
+ * * `voice` - a guild voice channel
+ * * `category` - a guild category channel
+ * * `news` - a guild news channel
+ * * `store` - a guild store channel
+ * * `unknown` - a generic channel of unknown type, could be Channel or GuildChannel
+ * @type {string}
+ */
+ this.type = type ? type.toLowerCase() : 'unknown';
+
+ /**
+ * Whether the channel has been deleted
+ * @type {boolean}
+ */
+ this.deleted = false;
+
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The unique ID of the channel
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+ }
+
+ /**
+ * The timestamp the channel was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the channel was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from <#123456789012345678>!
+ * console.log(`Hello from ${channel}!`);
+ */
+ toString() {
+ return `<#${this.id}>`;
+ }
+
+ /**
+ * Deletes this channel.
+ * @returns {Promise<Channel>}
+ * @example
+ * // Delete the channel
+ * channel.delete()
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ delete() {
+ return this.client.api
+ .channels(this.id)
+ .delete()
+ .then(() => this);
+ }
+
+ /**
+ * Fetches this channel.
+ * @returns {Promise<Channel>}
+ */
+ fetch() {
+ return this.client.channels.fetch(this.id, true);
+ }
+
+ static create(client, data, guild) {
+ const Structures = require('../util/Structures');
+ let channel;
+ if (!data.guild_id && !guild) {
+ if ((data.recipients && data.type !== ChannelTypes.GROUP) || data.type === ChannelTypes.DM) {
+ const DMChannel = Structures.get('DMChannel');
+ channel = new DMChannel(client, data);
+ } else if (data.type === ChannelTypes.GROUP) {
+ const PartialGroupDMChannel = require('./PartialGroupDMChannel');
+ channel = new PartialGroupDMChannel(client, data);
+ }
+ } else {
+ guild = guild || client.guilds.cache.get(data.guild_id);
+ if (guild) {
+ switch (data.type) {
+ case ChannelTypes.TEXT: {
+ const TextChannel = Structures.get('TextChannel');
+ channel = new TextChannel(guild, data);
+ break;
+ }
+ case ChannelTypes.VOICE: {
+ const VoiceChannel = Structures.get('VoiceChannel');
+ channel = new VoiceChannel(guild, data);
+ break;
+ }
+ case ChannelTypes.CATEGORY: {
+ const CategoryChannel = Structures.get('CategoryChannel');
+ channel = new CategoryChannel(guild, data);
+ break;
+ }
+ case ChannelTypes.NEWS: {
+ const NewsChannel = Structures.get('NewsChannel');
+ channel = new NewsChannel(guild, data);
+ break;
+ }
+ case ChannelTypes.STORE: {
+ const StoreChannel = Structures.get('StoreChannel');
+ channel = new StoreChannel(guild, data);
+ break;
+ }
+ }
+ if (channel) guild.channels.cache.set(channel.id, channel);
+ }
+ }
+ return channel;
+ }
+
+ toJSON(...props) {
+ return super.toJSON({ createdTimestamp: true }, ...props);
+ }
+}
+
+module.exports = Channel;
diff --git a/node_modules/discord.js/src/structures/ClientApplication.js b/node_modules/discord.js/src/structures/ClientApplication.js
new file mode 100644
index 0000000..753d90d
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ClientApplication.js
@@ -0,0 +1,156 @@
+'use strict';
+
+const Base = require('./Base');
+const Team = require('./Team');
+const { ClientApplicationAssetTypes, Endpoints } = require('../util/Constants');
+const Snowflake = require('../util/Snowflake');
+
+const AssetTypes = Object.keys(ClientApplicationAssetTypes);
+
+/**
+ * Represents a Client OAuth2 Application.
+ * @extends {Base}
+ */
+class ClientApplication extends Base {
+ constructor(client, data) {
+ super(client);
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The ID of the app
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The name of the app
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The app's description
+ * @type {string}
+ */
+ this.description = data.description;
+
+ /**
+ * The app's icon hash
+ * @type {string}
+ */
+ this.icon = data.icon;
+
+ /**
+ * The app's cover image
+ * @type {?string}
+ */
+ this.cover = data.cover_image || null;
+
+ /**
+ * The app's RPC origins, if enabled
+ * @type {string[]}
+ */
+ this.rpcOrigins = data.rpc_origins || [];
+
+ /**
+ * If this app's bot requires a code grant when using the OAuth2 flow
+ * @type {?boolean}
+ */
+ this.botRequireCodeGrant = typeof data.bot_require_code_grant !== 'undefined' ? data.bot_require_code_grant : null;
+
+ /**
+ * If this app's bot is public
+ * @type {?boolean}
+ */
+ this.botPublic = typeof data.bot_public !== 'undefined' ? data.bot_public : null;
+
+ /**
+ * The owner of this OAuth application
+ * @type {?User|Team}
+ */
+ this.owner = data.team ? new Team(this.client, data.team) : data.owner ? this.client.users.add(data.owner) : null;
+ }
+
+ /**
+ * The timestamp the app was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the app was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * A link to the application's icon.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string} URL to the icon
+ */
+ iconURL({ format, size } = {}) {
+ if (!this.icon) return null;
+ return this.client.rest.cdn.AppIcon(this.id, this.icon, { format, size });
+ }
+
+ /**
+ * A link to this application's cover image.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string} URL to the cover image
+ */
+ coverImage({ format, size } = {}) {
+ if (!this.cover) return null;
+ return Endpoints.CDN(this.client.options.http.cdn).AppIcon(this.id, this.cover, { format, size });
+ }
+
+ /**
+ * Asset data.
+ * @typedef {Object} ClientAsset
+ * @property {Snowflake} id The asset ID
+ * @property {string} name The asset name
+ * @property {string} type The asset type
+ */
+
+ /**
+ * Gets the clients rich presence assets.
+ * @returns {Promise<Array<ClientAsset>>}
+ */
+ fetchAssets() {
+ return this.client.api.oauth2
+ .applications(this.id)
+ .assets.get()
+ .then(assets =>
+ assets.map(a => ({
+ id: a.id,
+ name: a.name,
+ type: AssetTypes[a.type - 1],
+ })),
+ );
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the application's name instead of the
+ * ClientApplication object.
+ * @returns {string}
+ * @example
+ * // Logs: Application name: My App
+ * console.log(`Application name: ${application}`);
+ */
+ toString() {
+ return this.name;
+ }
+
+ toJSON() {
+ return super.toJSON({ createdTimestamp: true });
+ }
+}
+
+module.exports = ClientApplication;
diff --git a/node_modules/discord.js/src/structures/ClientPresence.js b/node_modules/discord.js/src/structures/ClientPresence.js
new file mode 100644
index 0000000..a39ba00
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ClientPresence.js
@@ -0,0 +1,87 @@
+'use strict';
+
+const { Presence } = require('./Presence');
+const { TypeError } = require('../errors');
+const Collection = require('../util/Collection');
+const { ActivityTypes, OPCodes } = require('../util/Constants');
+
+class ClientPresence extends Presence {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} [data={}] The data for the client presence
+ */
+ constructor(client, data = {}) {
+ super(client, Object.assign(data, { status: 'online', user: { id: null } }));
+ }
+
+ async set(presence) {
+ const packet = await this._parse(presence);
+ this.patch(packet);
+ if (typeof presence.shardID === 'undefined') {
+ this.client.ws.broadcast({ op: OPCodes.STATUS_UPDATE, d: packet });
+ } else if (Array.isArray(presence.shardID)) {
+ for (const shardID of presence.shardID) {
+ this.client.ws.shards.get(shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet });
+ }
+ } else {
+ this.client.ws.shards.get(presence.shardID).send({ op: OPCodes.STATUS_UPDATE, d: packet });
+ }
+ return this;
+ }
+
+ async _parse({ status, since, afk, activity }) {
+ const applicationID = activity && (activity.application ? activity.application.id || activity.application : null);
+ let assets = new Collection();
+ if (activity) {
+ if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', 'name', 'string');
+ if (!activity.type) activity.type = 0;
+ if (activity.assets && applicationID) {
+ try {
+ const a = await this.client.api.oauth2.applications(applicationID).assets.get();
+ for (const asset of a) assets.set(asset.name, asset.id);
+ } catch {} // eslint-disable-line no-empty
+ }
+ }
+
+ const packet = {
+ afk: afk != null ? afk : false, // eslint-disable-line eqeqeq
+ since: since != null ? since : null, // eslint-disable-line eqeqeq
+ status: status || this.status,
+ game: activity
+ ? {
+ type: activity.type,
+ name: activity.name,
+ url: activity.url,
+ details: activity.details || undefined,
+ state: activity.state || undefined,
+ assets: activity.assets
+ ? {
+ large_text: activity.assets.largeText || undefined,
+ small_text: activity.assets.smallText || undefined,
+ large_image: assets.get(activity.assets.largeImage) || activity.assets.largeImage,
+ small_image: assets.get(activity.assets.smallImage) || activity.assets.smallImage,
+ }
+ : undefined,
+ timestamps: activity.timestamps || undefined,
+ party: activity.party || undefined,
+ application_id: applicationID || undefined,
+ secrets: activity.secrets || undefined,
+ instance: activity.instance || undefined,
+ }
+ : null,
+ };
+
+ if ((status || afk || since) && !activity) {
+ packet.game = this.activities[0] || null;
+ }
+
+ if (packet.game) {
+ packet.game.type =
+ typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type);
+ }
+
+ return packet;
+ }
+}
+
+module.exports = ClientPresence;
diff --git a/node_modules/discord.js/src/structures/ClientUser.js b/node_modules/discord.js/src/structures/ClientUser.js
new file mode 100644
index 0000000..84ada54
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ClientUser.js
@@ -0,0 +1,180 @@
+'use strict';
+
+const DataResolver = require('../util/DataResolver');
+const Structures = require('../util/Structures');
+
+/**
+ * Represents the logged in client's Discord user.
+ * @extends {User}
+ */
+class ClientUser extends Structures.get('User') {
+ constructor(client, data) {
+ super(client, data);
+ this._typing = new Map();
+ }
+
+ _patch(data) {
+ super._patch(data);
+
+ if ('verified' in data) {
+ /**
+ * Whether or not this account has been verified
+ * @type {boolean}
+ */
+ this.verified = data.verified;
+ }
+
+ if ('mfa_enabled' in data) {
+ /**
+ * If the bot's {@link ClientApplication#owner Owner} has MFA enabled on their account
+ * @type {?boolean}
+ */
+ this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null;
+ } else if (typeof this.mfaEnabled === 'undefined') {
+ this.mfaEnabled = null;
+ }
+
+ if (data.token) this.client.token = data.token;
+ }
+
+ /**
+ * ClientUser's presence
+ * @type {Presence}
+ * @readonly
+ */
+ get presence() {
+ return this.client.presence;
+ }
+
+ edit(data) {
+ return this.client.api
+ .users('@me')
+ .patch({ data })
+ .then(newData => {
+ this.client.token = newData.token;
+ const { updated } = this.client.actions.UserUpdate.handle(newData);
+ if (updated) return updated;
+ return this;
+ });
+ }
+
+ /**
+ * Sets the username of the logged in client.
+ * <info>Changing usernames in Discord is heavily rate limited, with only 2 requests
+ * every hour. Use this sparingly!</info>
+ * @param {string} username The new username
+ * @returns {Promise<ClientUser>}
+ * @example
+ * // Set username
+ * client.user.setUsername('discordjs')
+ * .then(user => console.log(`My new username is ${user.username}`))
+ * .catch(console.error);
+ */
+ setUsername(username) {
+ return this.edit({ username });
+ }
+
+ /**
+ * Sets the avatar of the logged in client.
+ * @param {BufferResolvable|Base64Resolvable} avatar The new avatar
+ * @returns {Promise<ClientUser>}
+ * @example
+ * // Set avatar
+ * client.user.setAvatar('./avatar.png')
+ * .then(user => console.log(`New avatar set!`))
+ * .catch(console.error);
+ */
+ async setAvatar(avatar) {
+ return this.edit({ avatar: await DataResolver.resolveImage(avatar) });
+ }
+
+ /**
+ * Data resembling a raw Discord presence.
+ * @typedef {Object} PresenceData
+ * @property {PresenceStatusData} [status] Status of the user
+ * @property {boolean} [afk] Whether the user is AFK
+ * @property {Object} [activity] Activity the user is playing
+ * @property {Object|string} [activity.application] An application object or application id
+ * @property {string} [activity.application.id] The id of the application
+ * @property {string} [activity.name] Name of the activity
+ * @property {ActivityType|number} [activity.type] Type of the activity
+ * @property {string} [activity.url] Stream url
+ * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on
+ */
+
+ /**
+ * Sets the full presence of the client user.
+ * @param {PresenceData} data Data for the presence
+ * @returns {Promise<Presence>}
+ * @example
+ * // Set the client user's presence
+ * client.user.setPresence({ activity: { name: 'with discord.js' }, status: 'idle' })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ setPresence(data) {
+ return this.client.presence.set(data);
+ }
+
+ /**
+ * A user's status. Must be one of:
+ * * `online`
+ * * `idle`
+ * * `invisible`
+ * * `dnd` (do not disturb)
+ * @typedef {string} PresenceStatusData
+ */
+
+ /**
+ * Sets the status of the client user.
+ * @param {PresenceStatusData} status Status to change to
+ * @param {?number|number[]} [shardID] Shard ID(s) to have the activity set on
+ * @returns {Promise<Presence>}
+ * @example
+ * // Set the client user's status
+ * client.user.setStatus('idle')
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ setStatus(status, shardID) {
+ return this.setPresence({ status, shardID });
+ }
+
+ /**
+ * Options for setting an activity
+ * @typedef ActivityOptions
+ * @type {Object}
+ * @property {string} [url] Twitch stream URL
+ * @property {ActivityType|number} [type] Type of the activity
+ * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on
+ */
+
+ /**
+ * Sets the activity the client user is playing.
+ * @param {string|ActivityOptions} [name] Activity being played, or options for setting the activity
+ * @param {ActivityOptions} [options] Options for setting the activity
+ * @returns {Promise<Presence>}
+ * @example
+ * // Set the client user's activity
+ * client.user.setActivity('discord.js', { type: 'WATCHING' })
+ * .then(presence => console.log(`Activity set to ${presence.activities[0].name}`))
+ * .catch(console.error);
+ */
+ setActivity(name, options = {}) {
+ if (!name) return this.setPresence({ activity: null, shardID: options.shardID });
+
+ const activity = Object.assign({}, options, typeof name === 'object' ? name : { name });
+ return this.setPresence({ activity, shardID: activity.shardID });
+ }
+
+ /**
+ * Sets/removes the AFK flag for the client user.
+ * @param {boolean} afk Whether or not the user is AFK
+ * @returns {Promise<Presence>}
+ */
+ setAFK(afk) {
+ return this.setPresence({ afk });
+ }
+}
+
+module.exports = ClientUser;
diff --git a/node_modules/discord.js/src/structures/DMChannel.js b/node_modules/discord.js/src/structures/DMChannel.js
new file mode 100644
index 0000000..e661bc4
--- /dev/null
+++ b/node_modules/discord.js/src/structures/DMChannel.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const Channel = require('./Channel');
+const TextBasedChannel = require('./interfaces/TextBasedChannel');
+const MessageManager = require('../managers/MessageManager');
+
+/**
+ * Represents a direct message channel between two users.
+ * @extends {Channel}
+ * @implements {TextBasedChannel}
+ */
+class DMChannel extends Channel {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the DM channel
+ */
+ constructor(client, data) {
+ super(client, data);
+ // Override the channel type so partials have a known type
+ this.type = 'dm';
+ /**
+ * A manager of the messages belonging to this channel
+ * @type {MessageManager}
+ */
+ this.messages = new MessageManager(this);
+ this._typing = new Map();
+ }
+
+ _patch(data) {
+ super._patch(data);
+
+ if (data.recipients) {
+ /**
+ * The recipient on the other end of the DM
+ * @type {User}
+ */
+ this.recipient = this.client.users.add(data.recipients[0]);
+ }
+
+ /**
+ * The ID of the last message in the channel, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageID = data.last_message_id;
+
+ /**
+ * The timestamp when the last pinned message was pinned, if there was one
+ * @type {?number}
+ */
+ this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null;
+ }
+
+ /**
+ * Whether this DMChannel is a partial
+ * @type {boolean}
+ * @readonly
+ */
+ get partial() {
+ return typeof this.lastMessageID === 'undefined';
+ }
+
+ /**
+ * Fetch this DMChannel.
+ * @returns {Promise<DMChannel>}
+ */
+ fetch() {
+ return this.recipient.createDM();
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the recipient's mention instead of the
+ * DMChannel object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from <@123456789012345678>!
+ * console.log(`Hello from ${channel}!`);
+ */
+ toString() {
+ return this.recipient.toString();
+ }
+
+ // These are here only for documentation purposes - they are implemented by TextBasedChannel
+ /* eslint-disable no-empty-function */
+ get lastMessage() {}
+ get lastPinAt() {}
+ send() {}
+ startTyping() {}
+ stopTyping() {}
+ get typing() {}
+ get typingCount() {}
+ createMessageCollector() {}
+ awaitMessages() {}
+ // Doesn't work on DM channels; bulkDelete() {}
+}
+
+TextBasedChannel.applyToClass(DMChannel, true, ['bulkDelete']);
+
+module.exports = DMChannel;
diff --git a/node_modules/discord.js/src/structures/Emoji.js b/node_modules/discord.js/src/structures/Emoji.js
new file mode 100644
index 0000000..0214ea8
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Emoji.js
@@ -0,0 +1,104 @@
+'use strict';
+
+const Base = require('./Base');
+const Snowflake = require('../util/Snowflake');
+
+/**
+ * Represents an emoji, see {@link GuildEmoji} and {@link ReactionEmoji}.
+ * @extends {Base}
+ */
+class Emoji extends Base {
+ constructor(client, emoji) {
+ super(client);
+ /**
+ * Whether this emoji is animated
+ * @type {boolean}
+ */
+ this.animated = emoji.animated;
+
+ /**
+ * The name of this emoji
+ * @type {string}
+ */
+ this.name = emoji.name;
+
+ /**
+ * The ID of this emoji
+ * @type {?Snowflake}
+ */
+ this.id = emoji.id;
+
+ /**
+ * Whether this emoji has been deleted
+ * @type {boolean}
+ */
+ this.deleted = false;
+ }
+
+ /**
+ * The identifier of this emoji, used for message reactions
+ * @type {string}
+ * @readonly
+ */
+ get identifier() {
+ if (this.id) return `${this.animated ? 'a:' : ''}${this.name}:${this.id}`;
+ return encodeURIComponent(this.name);
+ }
+
+ /**
+ * The URL to the emoji file if its a custom emoji
+ * @type {?string}
+ * @readonly
+ */
+ get url() {
+ if (!this.id) return null;
+ return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png');
+ }
+
+ /**
+ * The timestamp the emoji was created at, or null if unicode
+ * @type {?number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ if (!this.id) return null;
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the emoji was created at, or null if unicode
+ * @type {?Date}
+ * @readonly
+ */
+ get createdAt() {
+ if (!this.id) return null;
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the text required to form a graphical emoji on Discord
+ * instead of the Emoji object.
+ * @returns {string}
+ * @example
+ * // Send a custom emoji from a guild:
+ * const emoji = guild.emojis.cache.first();
+ * msg.reply(`Hello! ${emoji}`);
+ * @example
+ * // Send the emoji used in a reaction to the channel the reaction is part of
+ * reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`);
+ */
+ toString() {
+ return this.id ? `<${this.animated ? 'a' : ''}:${this.name}:${this.id}>` : this.name;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ guild: 'guildID',
+ createdTimestamp: true,
+ url: true,
+ identifier: true,
+ });
+ }
+}
+
+module.exports = Emoji;
diff --git a/node_modules/discord.js/src/structures/Guild.js b/node_modules/discord.js/src/structures/Guild.js
new file mode 100644
index 0000000..e2bc8c4
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Guild.js
@@ -0,0 +1,1349 @@
+'use strict';
+
+const Base = require('./Base');
+const GuildAuditLogs = require('./GuildAuditLogs');
+const GuildPreview = require('./GuildPreview');
+const Integration = require('./Integration');
+const Invite = require('./Invite');
+const VoiceRegion = require('./VoiceRegion');
+const Webhook = require('./Webhook');
+const GuildChannelManager = require('../managers/GuildChannelManager');
+const GuildEmojiManager = require('../managers/GuildEmojiManager');
+const GuildMemberManager = require('../managers/GuildMemberManager');
+const PresenceManager = require('../managers/PresenceManager');
+const RoleManager = require('../managers/RoleManager');
+const VoiceStateManager = require('../managers/VoiceStateManager');
+const Collection = require('../util/Collection');
+const {
+ ChannelTypes,
+ DefaultMessageNotifications,
+ PartialTypes,
+ VerificationLevels,
+ ExplicitContentFilterLevels,
+} = require('../util/Constants');
+const DataResolver = require('../util/DataResolver');
+const Snowflake = require('../util/Snowflake');
+const SystemChannelFlags = require('../util/SystemChannelFlags');
+const Util = require('../util/Util');
+
+/**
+ * Represents a guild (or a server) on Discord.
+ * <info>It's recommended to see if a guild is available before performing operations or reading data from it. You can
+ * check this with `guild.available`.</info>
+ * @extends {Base}
+ */
+class Guild extends Base {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the guild
+ */
+ constructor(client, data) {
+ super(client);
+
+ /**
+ * A manager of the members belonging to this guild
+ * @type {GuildMemberManager}
+ */
+ this.members = new GuildMemberManager(this);
+
+ /**
+ * A manager of the channels belonging to this guild
+ * @type {GuildChannelManager}
+ */
+ this.channels = new GuildChannelManager(this);
+
+ /**
+ * A manager of the roles belonging to this guild
+ * @type {RoleManager}
+ */
+ this.roles = new RoleManager(this);
+
+ /**
+ * A manager of the presences belonging to this guild
+ * @type {PresenceManager}
+ */
+ this.presences = new PresenceManager(this.client);
+
+ /**
+ * A manager of the voice states of this guild
+ * @type {VoiceStateManager}
+ */
+ this.voiceStates = new VoiceStateManager(this);
+
+ /**
+ * Whether the bot has been removed from the guild
+ * @type {boolean}
+ */
+ this.deleted = false;
+
+ if (!data) return;
+ if (data.unavailable) {
+ /**
+ * Whether the guild is available to access. If it is not available, it indicates a server outage
+ * @type {boolean}
+ */
+ this.available = false;
+
+ /**
+ * The Unique ID of the guild, useful for comparisons
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+ } else {
+ this._patch(data);
+ if (!data.channels) this.available = false;
+ }
+
+ /**
+ * The id of the shard this Guild belongs to.
+ * @type {number}
+ */
+ this.shardID = data.shardID;
+ }
+
+ /**
+ * The Shard this Guild belongs to.
+ * @type {WebSocketShard}
+ * @readonly
+ */
+ get shard() {
+ return this.client.ws.shards.get(this.shardID);
+ }
+
+ /**
+ * Sets up the guild.
+ * @param {*} data The raw data of the guild
+ * @private
+ */
+ _patch(data) {
+ /**
+ * The name of the guild
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The hash of the guild icon
+ * @type {?string}
+ */
+ this.icon = data.icon;
+
+ /**
+ * The hash of the guild splash image (VIP only)
+ * @type {?string}
+ */
+ this.splash = data.splash;
+
+ /**
+ * The region the guild is located in
+ * @type {string}
+ */
+ this.region = data.region;
+
+ /**
+ * The full amount of members in this guild
+ * @type {number}
+ */
+ this.memberCount = data.member_count || this.memberCount;
+
+ /**
+ * Whether the guild is "large" (has more than 250 members)
+ * @type {boolean}
+ */
+ this.large = Boolean('large' in data ? data.large : this.large);
+
+ /**
+ * An array of enabled guild features, here are the possible values:
+ * * ANIMATED_ICON
+ * * BANNER
+ * * COMMERCE
+ * * DISCOVERABLE
+ * * FEATURABLE
+ * * INVITE_SPLASH
+ * * NEWS
+ * * PARTNERED
+ * * PUBLIC
+ * * PUBLIC_DISABLED
+ * * VANITY_URL
+ * * VERIFIED
+ * * VIP_REGIONS
+ * * WELCOME_SCREEN_ENABLED
+ * @typedef {string} Features
+ */
+
+ /**
+ * An array of guild features partnered guilds have enabled
+ * @type {Features[]}
+ */
+ this.features = data.features;
+
+ /**
+ * The ID of the application that created this guild (if applicable)
+ * @type {?Snowflake}
+ */
+ this.applicationID = data.application_id;
+
+ /**
+ * The time in seconds before a user is counted as "away from keyboard"
+ * @type {?number}
+ */
+ this.afkTimeout = data.afk_timeout;
+
+ /**
+ * The ID of the voice channel where AFK members are moved
+ * @type {?Snowflake}
+ */
+ this.afkChannelID = data.afk_channel_id;
+
+ /**
+ * The ID of the system channel
+ * @type {?Snowflake}
+ */
+ this.systemChannelID = data.system_channel_id;
+
+ /**
+ * Whether embedded images are enabled on this guild
+ * @type {boolean}
+ */
+ this.embedEnabled = data.embed_enabled;
+
+ /**
+ * The type of premium tier:
+ * * 0: NONE
+ * * 1: TIER_1
+ * * 2: TIER_2
+ * * 3: TIER_3
+ * @typedef {number} PremiumTier
+ */
+
+ /**
+ * The premium tier on this guild
+ * @type {PremiumTier}
+ */
+ this.premiumTier = data.premium_tier;
+
+ /**
+ * The total number of users currently boosting this server
+ * @type {?number}
+ * @name Guild#premiumSubscriptionCount
+ */
+ if (typeof data.premium_subscription_count !== 'undefined') {
+ this.premiumSubscriptionCount = data.premium_subscription_count;
+ }
+
+ /**
+ * Whether widget images are enabled on this guild
+ * @type {?boolean}
+ * @name Guild#widgetEnabled
+ */
+ if (typeof data.widget_enabled !== 'undefined') this.widgetEnabled = data.widget_enabled;
+
+ /**
+ * The widget channel ID, if enabled
+ * @type {?string}
+ * @name Guild#widgetChannelID
+ */
+ if (typeof data.widget_channel_id !== 'undefined') this.widgetChannelID = data.widget_channel_id;
+
+ /**
+ * The embed channel ID, if enabled
+ * @type {?string}
+ * @name Guild#embedChannelID
+ */
+ if (typeof data.embed_channel_id !== 'undefined') this.embedChannelID = data.embed_channel_id;
+
+ /**
+ * The verification level of the guild
+ * @type {VerificationLevel}
+ */
+ this.verificationLevel = VerificationLevels[data.verification_level];
+
+ /**
+ * The explicit content filter level of the guild
+ * @type {ExplicitContentFilterLevel}
+ */
+ this.explicitContentFilter = ExplicitContentFilterLevels[data.explicit_content_filter];
+
+ /**
+ * The required MFA level for the guild
+ * @type {number}
+ */
+ this.mfaLevel = data.mfa_level;
+
+ /**
+ * The timestamp the client user joined the guild at
+ * @type {number}
+ */
+ this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp;
+
+ /**
+ * The value set for the guild's default message notifications
+ * @type {DefaultMessageNotifications|number}
+ */
+ this.defaultMessageNotifications =
+ DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications;
+
+ /**
+ * The value set for the guild's system channel flags
+ * @type {Readonly<SystemChannelFlags>}
+ */
+ this.systemChannelFlags = new SystemChannelFlags(data.system_channel_flags).freeze();
+
+ /**
+ * The maximum amount of members the guild can have
+ * <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
+ * @type {?number}
+ * @name Guild#maximumMembers
+ */
+ if (typeof data.max_members !== 'undefined') this.maximumMembers = data.max_members || 250000;
+
+ /**
+ * The maximum amount of presences the guild can have
+ * <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
+ * @type {?number}
+ * @name Guild#maximumPresences
+ */
+ if (typeof data.max_presences !== 'undefined') this.maximumPresences = data.max_presences || 25000;
+
+ /**
+ * The vanity URL code of the guild, if any
+ * @type {?string}
+ */
+ this.vanityURLCode = data.vanity_url_code;
+
+ /**
+ * The description of the guild, if any
+ * @type {?string}
+ */
+ this.description = data.description;
+
+ /**
+ * The hash of the guild banner
+ * @type {?string}
+ */
+ this.banner = data.banner;
+
+ this.id = data.id;
+ this.available = !data.unavailable;
+ this.features = data.features || this.features || [];
+
+ /**
+ * The ID of the rules channel for the guild
+ * <info>This is only available on guilds with the `PUBLIC` feature</info>
+ * @type {?Snowflake}
+ */
+ this.rulesChannelID = data.rules_channel_id;
+
+ /**
+ * The ID of the public updates channel for the guild
+ * <info>This is only available on guilds with the `PUBLIC` feature</info>
+ * @type {?Snowflake}
+ */
+ this.publicUpdatesChannelID = data.public_updates_channel_id;
+
+ if (data.channels) {
+ this.channels.cache.clear();
+ for (const rawChannel of data.channels) {
+ this.client.channels.add(rawChannel, this);
+ }
+ }
+
+ if (data.roles) {
+ this.roles.cache.clear();
+ for (const role of data.roles) this.roles.add(role);
+ }
+
+ if (data.members) {
+ this.members.cache.clear();
+ for (const guildUser of data.members) this.members.add(guildUser);
+ }
+
+ if (data.owner_id) {
+ /**
+ * The user ID of this guild's owner
+ * @type {Snowflake}
+ */
+ this.ownerID = data.owner_id;
+ }
+
+ if (data.presences) {
+ for (const presence of data.presences) {
+ this.presences.add(Object.assign(presence, { guild: this }));
+ }
+ }
+
+ if (data.voice_states) {
+ this.voiceStates.cache.clear();
+ for (const voiceState of data.voice_states) {
+ this.voiceStates.add(voiceState);
+ }
+ }
+
+ if (!this.emojis) {
+ /**
+ * A manager of the emojis belonging to this guild
+ * @type {GuildEmojiManager}
+ */
+ this.emojis = new GuildEmojiManager(this);
+ if (data.emojis) for (const emoji of data.emojis) this.emojis.add(emoji);
+ } else if (data.emojis) {
+ this.client.actions.GuildEmojisUpdate.handle({
+ guild_id: this.id,
+ emojis: data.emojis,
+ });
+ }
+ }
+
+ /**
+ * The URL to this guild's banner.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ bannerURL({ format, size } = {}) {
+ if (!this.banner) return null;
+ return this.client.rest.cdn.Banner(this.id, this.banner, format, size);
+ }
+
+ /**
+ * The timestamp the guild was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the guild was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * The time the client user joined the guild
+ * @type {Date}
+ * @readonly
+ */
+ get joinedAt() {
+ return new Date(this.joinedTimestamp);
+ }
+
+ /**
+ * If this guild is partnered
+ * @type {boolean}
+ * @readonly
+ */
+ get partnered() {
+ return this.features.includes('PARTNERED');
+ }
+
+ /**
+ * If this guild is verified
+ * @type {boolean}
+ * @readonly
+ */
+ get verified() {
+ return this.features.includes('VERIFIED');
+ }
+
+ /**
+ * The URL to this guild's icon.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ iconURL({ format, size, dynamic } = {}) {
+ if (!this.icon) return null;
+ return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic);
+ }
+
+ /**
+ * The acronym that shows up in place of a guild icon.
+ * @type {string}
+ * @readonly
+ */
+ get nameAcronym() {
+ return this.name.replace(/\w+/g, name => name[0]).replace(/\s/g, '');
+ }
+
+ /**
+ * The URL to this guild's splash.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ splashURL({ format, size } = {}) {
+ if (!this.splash) return null;
+ return this.client.rest.cdn.Splash(this.id, this.splash, format, size);
+ }
+
+ /**
+ * The owner of the guild
+ * @type {?GuildMember}
+ * @readonly
+ */
+ get owner() {
+ return (
+ this.members.cache.get(this.ownerID) ||
+ (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
+ ? this.members.add({ user: { id: this.ownerID } }, true)
+ : null)
+ );
+ }
+
+ /**
+ * AFK voice channel for this guild
+ * @type {?VoiceChannel}
+ * @readonly
+ */
+ get afkChannel() {
+ return this.client.channels.cache.get(this.afkChannelID) || null;
+ }
+
+ /**
+ * System channel for this guild
+ * @type {?TextChannel}
+ * @readonly
+ */
+ get systemChannel() {
+ return this.client.channels.cache.get(this.systemChannelID) || null;
+ }
+
+ /**
+ * Widget channel for this guild
+ * @type {?TextChannel}
+ * @readonly
+ */
+ get widgetChannel() {
+ return this.client.channels.cache.get(this.widgetChannelID) || null;
+ }
+
+ /**
+ * Embed channel for this guild
+ * @type {?TextChannel}
+ * @readonly
+ */
+ get embedChannel() {
+ return this.client.channels.cache.get(this.embedChannelID) || null;
+ }
+
+ /**
+ * Rules channel for this guild
+ * <info>This is only available on guilds with the `PUBLIC` feature</info>
+ * @type {?TextChannel}
+ * @readonly
+ */
+ get rulesChannel() {
+ return this.client.channels.cache.get(this.rulesChannelID) || null;
+ }
+
+ /**
+ * Public updates channel for this guild
+ * <info>This is only available on guilds with the `PUBLIC` feature</info>
+ * @type {?TextChannel}
+ * @readonly
+ */
+ get publicUpdatesChannel() {
+ return this.client.channels.cache.get(this.publicUpdatesChannelID) || null;
+ }
+
+ /**
+ * The client user as a GuildMember of this guild
+ * @type {?GuildMember}
+ * @readonly
+ */
+ get me() {
+ return (
+ this.members.cache.get(this.client.user.id) ||
+ (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
+ ? this.members.add({ user: { id: this.client.user.id } }, true)
+ : null)
+ );
+ }
+
+ /**
+ * The voice state for the client user of this guild, if any
+ * @type {?VoiceState}
+ * @readonly
+ */
+ get voice() {
+ return this.voiceStates.cache.get(this.client.user.id);
+ }
+
+ /**
+ * Returns the GuildMember form of a User object, if the user is present in the guild.
+ * @param {UserResolvable} user The user that you want to obtain the GuildMember of
+ * @returns {?GuildMember}
+ * @example
+ * // Get the guild member of a user
+ * const member = guild.member(message.author);
+ */
+ member(user) {
+ return this.members.resolve(user);
+ }
+
+ /**
+ * Fetches this guild.
+ * @returns {Promise<Guild>}
+ */
+ fetch() {
+ return this.client.api
+ .guilds(this.id)
+ .get()
+ .then(data => {
+ this._patch(data);
+ return this;
+ });
+ }
+
+ /**
+ * An object containing information about a guild member's ban.
+ * @typedef {Object} BanInfo
+ * @property {User} user User that was banned
+ * @property {?string} reason Reason the user was banned
+ */
+
+ /**
+ * Fetches information on a banned user from this guild.
+ * @param {UserResolvable} user The User to fetch the ban info of
+ * @returns {Promise<BanInfo>}
+ */
+ fetchBan(user) {
+ const id = this.client.users.resolveID(user);
+ if (!id) throw new Error('FETCH_BAN_RESOLVE_ID');
+ return this.client.api
+ .guilds(this.id)
+ .bans(id)
+ .get()
+ .then(ban => ({
+ reason: ban.reason,
+ user: this.client.users.add(ban.user),
+ }));
+ }
+
+ /**
+ * Fetches a collection of banned users in this guild.
+ * @returns {Promise<Collection<Snowflake, BanInfo>>}
+ */
+ fetchBans() {
+ return this.client.api
+ .guilds(this.id)
+ .bans.get()
+ .then(bans =>
+ bans.reduce((collection, ban) => {
+ collection.set(ban.user.id, {
+ reason: ban.reason,
+ user: this.client.users.add(ban.user),
+ });
+ return collection;
+ }, new Collection()),
+ );
+ }
+
+ /**
+ * Fetches a collection of integrations to this guild.
+ * Resolves with a collection mapping integrations by their ids.
+ * @returns {Promise<Collection<string, Integration>>}
+ * @example
+ * // Fetch integrations
+ * guild.fetchIntegrations()
+ * .then(integrations => console.log(`Fetched ${integrations.size} integrations`))
+ * .catch(console.error);
+ */
+ fetchIntegrations() {
+ return this.client.api
+ .guilds(this.id)
+ .integrations.get()
+ .then(data =>
+ data.reduce(
+ (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)),
+ new Collection(),
+ ),
+ );
+ }
+
+ /**
+ * The data for creating an integration.
+ * @typedef {Object} IntegrationData
+ * @property {string} id The integration id
+ * @property {string} type The integration type
+ */
+
+ /**
+ * Creates an integration by attaching an integration object
+ * @param {IntegrationData} data The data for the integration
+ * @param {string} reason Reason for creating the integration
+ * @returns {Promise<Guild>}
+ */
+ createIntegration(data, reason) {
+ return this.client.api
+ .guilds(this.id)
+ .integrations.post({ data, reason })
+ .then(() => this);
+ }
+
+ /**
+ * Fetches a collection of invites to this guild.
+ * Resolves with a collection mapping invites by their codes.
+ * @returns {Promise<Collection<string, Invite>>}
+ * @example
+ * // Fetch invites
+ * guild.fetchInvites()
+ * .then(invites => console.log(`Fetched ${invites.size} invites`))
+ * .catch(console.error);
+ * @example
+ * // Fetch invite creator by their id
+ * guild.fetchInvites()
+ * .then(invites => console.log(invites.find(invite => invite.inviter.id === '84484653687267328')))
+ * .catch(console.error);
+ */
+ fetchInvites() {
+ return this.client.api
+ .guilds(this.id)
+ .invites.get()
+ .then(inviteItems => {
+ const invites = new Collection();
+ for (const inviteItem of inviteItems) {
+ const invite = new Invite(this.client, inviteItem);
+ invites.set(invite.code, invite);
+ }
+ return invites;
+ });
+ }
+
+ /**
+ * Obtains a guild preview for this guild from Discord, only available for public guilds.
+ * @returns {Promise<GuildPreview>}
+ */
+ fetchPreview() {
+ return this.client.api
+ .guilds(this.id)
+ .preview.get()
+ .then(data => new GuildPreview(this.client, data));
+ }
+
+ /**
+ * Fetches the vanity url invite code to this guild.
+ * Resolves with a string matching the vanity url invite code, not the full url.
+ * @returns {Promise<string>}
+ * @example
+ * // Fetch invites
+ * guild.fetchVanityCode()
+ * .then(code => {
+ * console.log(`Vanity URL: https://discord.gg/${code}`);
+ * })
+ * .catch(console.error);
+ */
+ fetchVanityCode() {
+ if (!this.features.includes('VANITY_URL')) {
+ return Promise.reject(new Error('VANITY_URL'));
+ }
+ return this.client.api
+ .guilds(this.id, 'vanity-url')
+ .get()
+ .then(res => res.code);
+ }
+
+ /**
+ * Fetches all webhooks for the guild.
+ * @returns {Promise<Collection<Snowflake, Webhook>>}
+ * @example
+ * // Fetch webhooks
+ * guild.fetchWebhooks()
+ * .then(webhooks => console.log(`Fetched ${webhooks.size} webhooks`))
+ * .catch(console.error);
+ */
+ fetchWebhooks() {
+ return this.client.api
+ .guilds(this.id)
+ .webhooks.get()
+ .then(data => {
+ const hooks = new Collection();
+ for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook));
+ return hooks;
+ });
+ }
+
+ /**
+ * Fetches available voice regions.
+ * @returns {Promise<Collection<string, VoiceRegion>>}
+ */
+ fetchVoiceRegions() {
+ return this.client.api
+ .guilds(this.id)
+ .regions.get()
+ .then(res => {
+ const regions = new Collection();
+ for (const region of res) regions.set(region.id, new VoiceRegion(region));
+ return regions;
+ });
+ }
+
+ /**
+ * The Guild Embed object
+ * @typedef {Object} GuildEmbedData
+ * @property {boolean} enabled Whether the embed is enabled
+ * @property {?GuildChannel} channel The embed channel
+ */
+
+ /**
+ * Fetches the guild embed.
+ * @returns {Promise<GuildEmbedData>}
+ * @example
+ * // Fetches the guild embed
+ * guild.fetchEmbed()
+ * .then(embed => console.log(`The embed is ${embed.enabled ? 'enabled' : 'disabled'}`))
+ * .catch(console.error);
+ */
+ fetchEmbed() {
+ return this.client.api
+ .guilds(this.id)
+ .embed.get()
+ .then(data => ({
+ enabled: data.enabled,
+ channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null,
+ }));
+ }
+
+ /**
+ * Fetches audit logs for this guild.
+ * @param {Object} [options={}] Options for fetching audit logs
+ * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry
+ * @param {number} [options.limit] Limit number of entries
+ * @param {UserResolvable} [options.user] Only show entries involving this user
+ * @param {AuditLogAction|number} [options.type] Only show entries involving this action type
+ * @returns {Promise<GuildAuditLogs>}
+ * @example
+ * // Output audit log entries
+ * guild.fetchAuditLogs()
+ * .then(audit => console.log(audit.entries.first()))
+ * .catch(console.error);
+ */
+ fetchAuditLogs(options = {}) {
+ if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id;
+ if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type];
+
+ return this.client.api
+ .guilds(this.id)
+ ['audit-logs'].get({
+ query: {
+ before: options.before,
+ limit: options.limit,
+ user_id: this.client.users.resolveID(options.user),
+ action_type: options.type,
+ },
+ })
+ .then(data => GuildAuditLogs.build(this, data));
+ }
+
+ /**
+ * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission.
+ * @param {UserResolvable} user User to add to the guild
+ * @param {Object} options Options for the addition
+ * @param {string} options.accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the
+ * bot's application
+ * @param {string} [options.nick] Nickname to give the member (requires `MANAGE_NICKNAMES`)
+ * @param {Collection<Snowflake, Role>|RoleResolvable[]} [options.roles] Roles to add to the member
+ * (requires `MANAGE_ROLES`)
+ * @param {boolean} [options.mute] Whether the member should be muted (requires `MUTE_MEMBERS`)
+ * @param {boolean} [options.deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`)
+ * @returns {Promise<GuildMember>}
+ */
+ addMember(user, options) {
+ user = this.client.users.resolveID(user);
+ if (!user) return Promise.reject(new TypeError('INVALID_TYPE', 'user', 'UserResolvable'));
+ if (this.members.cache.has(user)) return Promise.resolve(this.members.cache.get(user));
+ options.access_token = options.accessToken;
+ if (options.roles) {
+ const roles = [];
+ for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) {
+ role = this.roles.resolve(role);
+ if (!role) {
+ return Promise.reject(
+ new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true),
+ );
+ }
+ roles.push(role.id);
+ }
+ options.roles = roles;
+ }
+ return this.client.api
+ .guilds(this.id)
+ .members(user)
+ .put({ data: options })
+ .then(data => this.members.add(data));
+ }
+
+ /**
+ * The data for editing a guild.
+ * @typedef {Object} GuildEditData
+ * @property {string} [name] The name of the guild
+ * @property {string} [region] The region of the guild
+ * @property {VerificationLevel|number} [verificationLevel] The verification level of the guild
+ * @property {ExplicitContentFilterLevel|number} [explicitContentFilter] The level of the explicit content filter
+ * @property {ChannelResolvable} [afkChannel] The AFK channel of the guild
+ * @property {ChannelResolvable} [systemChannel] The system channel of the guild
+ * @property {number} [afkTimeout] The AFK timeout of the guild
+ * @property {Base64Resolvable} [icon] The icon of the guild
+ * @property {GuildMemberResolvable} [owner] The owner of the guild
+ * @property {Base64Resolvable} [splash] The splash screen of the guild
+ * @property {Base64Resolvable} [banner] The banner of the guild
+ * @property {DefaultMessageNotifications|number} [defaultMessageNotifications] The default message notifications
+ * @property {SystemChannelFlagsResolvable} [systemChannelFlags] The system channel flags of the guild
+ */
+
+ /**
+ * Updates the guild with new information - e.g. a new name.
+ * @param {GuildEditData} data The data to update the guild with
+ * @param {string} [reason] Reason for editing this guild
+ * @returns {Promise<Guild>}
+ * @example
+ * // Set the guild name and region
+ * guild.edit({
+ * name: 'Discord Guild',
+ * region: 'london',
+ * })
+ * .then(updated => console.log(`New guild name ${updated} in region ${updated.region}`))
+ * .catch(console.error);
+ */
+ edit(data, reason) {
+ const _data = {};
+ if (data.name) _data.name = data.name;
+ if (data.region) _data.region = data.region;
+ if (typeof data.verificationLevel !== 'undefined') {
+ _data.verification_level =
+ typeof data.verificationLevel === 'number'
+ ? Number(data.verificationLevel)
+ : VerificationLevels.indexOf(data.verificationLevel);
+ }
+ if (typeof data.afkChannel !== 'undefined') {
+ _data.afk_channel_id = this.client.channels.resolveID(data.afkChannel);
+ }
+ if (typeof data.systemChannel !== 'undefined') {
+ _data.system_channel_id = this.client.channels.resolveID(data.systemChannel);
+ }
+ if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout);
+ if (typeof data.icon !== 'undefined') _data.icon = data.icon;
+ if (data.owner) _data.owner_id = this.client.users.resolveID(data.owner);
+ if (data.splash) _data.splash = data.splash;
+ if (data.banner) _data.banner = data.banner;
+ if (typeof data.explicitContentFilter !== 'undefined') {
+ _data.explicit_content_filter =
+ typeof data.explicitContentFilter === 'number'
+ ? data.explicitContentFilter
+ : ExplicitContentFilterLevels.indexOf(data.explicitContentFilter);
+ }
+ if (typeof data.defaultMessageNotifications !== 'undefined') {
+ _data.default_message_notifications =
+ typeof data.defaultMessageNotifications === 'string'
+ ? DefaultMessageNotifications.indexOf(data.defaultMessageNotifications)
+ : data.defaultMessageNotifications;
+ }
+ if (typeof data.systemChannelFlags !== 'undefined') {
+ _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags);
+ }
+ return this.client.api
+ .guilds(this.id)
+ .patch({ data: _data, reason })
+ .then(newData => this.client.actions.GuildUpdate.handle(newData).updated);
+ }
+
+ /**
+ * Edits the level of the explicit content filter.
+ * @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter
+ * @param {string} [reason] Reason for changing the level of the guild's explicit content filter
+ * @returns {Promise<Guild>}
+ */
+ setExplicitContentFilter(explicitContentFilter, reason) {
+ return this.edit({ explicitContentFilter }, reason);
+ }
+
+ /* eslint-disable max-len */
+ /**
+ * Edits the setting of the default message notifications of the guild.
+ * @param {DefaultMessageNotifications|number} defaultMessageNotifications The new setting for the default message notifications
+ * @param {string} [reason] Reason for changing the setting of the default message notifications
+ * @returns {Promise<Guild>}
+ */
+ setDefaultMessageNotifications(defaultMessageNotifications, reason) {
+ return this.edit({ defaultMessageNotifications }, reason);
+ }
+ /* eslint-enable max-len */
+
+ /**
+ * Edits the flags of the default message notifications of the guild.
+ * @param {SystemChannelFlagsResolvable} systemChannelFlags The new flags for the default message notifications
+ * @param {string} [reason] Reason for changing the flags of the default message notifications
+ * @returns {Promise<Guild>}
+ */
+ setSystemChannelFlags(systemChannelFlags, reason) {
+ return this.edit({ systemChannelFlags }, reason);
+ }
+
+ /**
+ * Edits the name of the guild.
+ * @param {string} name The new name of the guild
+ * @param {string} [reason] Reason for changing the guild's name
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild name
+ * guild.setName('Discord Guild')
+ * .then(updated => console.log(`Updated guild name to ${guild}`))
+ * .catch(console.error);
+ */
+ setName(name, reason) {
+ return this.edit({ name }, reason);
+ }
+
+ /**
+ * Edits the region of the guild.
+ * @param {string} region The new region of the guild
+ * @param {string} [reason] Reason for changing the guild's region
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild region
+ * guild.setRegion('london')
+ * .then(updated => console.log(`Updated guild region to ${updated.region}`))
+ * .catch(console.error);
+ */
+ setRegion(region, reason) {
+ return this.edit({ region }, reason);
+ }
+
+ /**
+ * Edits the verification level of the guild.
+ * @param {VerificationLevel|number} verificationLevel The new verification level of the guild
+ * @param {string} [reason] Reason for changing the guild's verification level
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild verification level
+ * guild.setVerificationLevel(1)
+ * .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))
+ * .catch(console.error);
+ */
+ setVerificationLevel(verificationLevel, reason) {
+ return this.edit({ verificationLevel }, reason);
+ }
+
+ /**
+ * Edits the AFK channel of the guild.
+ * @param {ChannelResolvable} afkChannel The new AFK channel
+ * @param {string} [reason] Reason for changing the guild's AFK channel
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild AFK channel
+ * guild.setAFKChannel(channel)
+ * .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel.name}`))
+ * .catch(console.error);
+ */
+ setAFKChannel(afkChannel, reason) {
+ return this.edit({ afkChannel }, reason);
+ }
+
+ /**
+ * Edits the system channel of the guild.
+ * @param {ChannelResolvable} systemChannel The new system channel
+ * @param {string} [reason] Reason for changing the guild's system channel
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild system channel
+ * guild.setSystemChannel(channel)
+ * .then(updated => console.log(`Updated guild system channel to ${guild.systemChannel.name}`))
+ * .catch(console.error);
+ */
+ setSystemChannel(systemChannel, reason) {
+ return this.edit({ systemChannel }, reason);
+ }
+
+ /**
+ * Edits the AFK timeout of the guild.
+ * @param {number} afkTimeout The time in seconds that a user must be idle to be considered AFK
+ * @param {string} [reason] Reason for changing the guild's AFK timeout
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild AFK channel
+ * guild.setAFKTimeout(60)
+ * .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))
+ * .catch(console.error);
+ */
+ setAFKTimeout(afkTimeout, reason) {
+ return this.edit({ afkTimeout }, reason);
+ }
+
+ /**
+ * Sets a new guild icon.
+ * @param {Base64Resolvable|BufferResolvable} icon The new icon of the guild
+ * @param {string} [reason] Reason for changing the guild's icon
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild icon
+ * guild.setIcon('./icon.png')
+ * .then(updated => console.log('Updated the guild icon'))
+ * .catch(console.error);
+ */
+ async setIcon(icon, reason) {
+ return this.edit({ icon: await DataResolver.resolveImage(icon), reason });
+ }
+
+ /**
+ * Sets a new owner of the guild.
+ * @param {GuildMemberResolvable} owner The new owner of the guild
+ * @param {string} [reason] Reason for setting the new owner
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild owner
+ * guild.setOwner(guild.members.cache.first())
+ * .then(updated => console.log(`Updated the guild owner to ${updated.owner.displayName}`))
+ * .catch(console.error);
+ */
+ setOwner(owner, reason) {
+ return this.edit({ owner }, reason);
+ }
+
+ /**
+ * Sets a new guild splash screen.
+ * @param {Base64Resolvable|BufferResolvable} splash The new splash screen of the guild
+ * @param {string} [reason] Reason for changing the guild's splash screen
+ * @returns {Promise<Guild>}
+ * @example
+ * // Edit the guild splash
+ * guild.setSplash('./splash.png')
+ * .then(updated => console.log('Updated the guild splash'))
+ * .catch(console.error);
+ */
+ async setSplash(splash, reason) {
+ return this.edit({ splash: await DataResolver.resolveImage(splash), reason });
+ }
+
+ /**
+ * Sets a new guild banner.
+ * @param {Base64Resolvable|BufferResolvable} banner The new banner of the guild
+ * @param {string} [reason] Reason for changing the guild's banner
+ * @returns {Promise<Guild>}
+ * @example
+ * guild.setBanner('./banner.png')
+ * .then(updated => console.log('Updated the guild banner'))
+ * .catch(console.error);
+ */
+ async setBanner(banner, reason) {
+ return this.edit({ banner: await DataResolver.resolveImage(banner), reason });
+ }
+
+ /**
+ * The data needed for updating a channel's position.
+ * @typedef {Object} ChannelPosition
+ * @property {ChannelResolvable} channel Channel to update
+ * @property {number} position New position for the channel
+ */
+
+ /**
+ * Batch-updates the guild's channels' positions.
+ * @param {ChannelPosition[]} channelPositions Channel positions to update
+ * @returns {Promise<Guild>}
+ * @example
+ * guild.setChannelPositions([{ channel: channelID, position: newChannelIndex }])
+ * .then(guild => console.log(`Updated channel positions for ${guild}`))
+ * .catch(console.error);
+ */
+ setChannelPositions(channelPositions) {
+ const updatedChannels = channelPositions.map(r => ({
+ id: this.client.channels.resolveID(r.channel),
+ position: r.position,
+ }));
+
+ return this.client.api
+ .guilds(this.id)
+ .channels.patch({ data: updatedChannels })
+ .then(
+ () =>
+ this.client.actions.GuildChannelsPositionUpdate.handle({
+ guild_id: this.id,
+ channels: updatedChannels,
+ }).guild,
+ );
+ }
+
+ /**
+ * The data needed for updating a guild role's position
+ * @typedef {Object} GuildRolePosition
+ * @property {RoleResolveable} role The ID of the role
+ * @property {number} position The position to update
+ */
+
+ /**
+ * Batch-updates the guild's role positions
+ * @param {GuildRolePosition[]} rolePositions Role positions to update
+ * @returns {Promise<Guild>}
+ * @example
+ * guild.setRolePositions([{ role: roleID, position: updatedRoleIndex }])
+ * .then(guild => console.log(`Role permissions updated for ${guild}`))
+ * .catch(console.error);
+ */
+ setRolePositions(rolePositions) {
+ // Make sure rolePositions are prepared for API
+ rolePositions = rolePositions.map(o => ({
+ id: this.roles.resolveID(o.role),
+ position: o.position,
+ }));
+
+ // Call the API to update role positions
+ return this.client.api
+ .guilds(this.id)
+ .roles.patch({
+ data: rolePositions,
+ })
+ .then(
+ () =>
+ this.client.actions.GuildRolesPositionUpdate.handle({
+ guild_id: this.id,
+ roles: rolePositions,
+ }).guild,
+ );
+ }
+
+ /**
+ * Edits the guild's embed.
+ * @param {GuildEmbedData} embed The embed for the guild
+ * @param {string} [reason] Reason for changing the guild's embed
+ * @returns {Promise<Guild>}
+ */
+ setEmbed(embed, reason) {
+ return this.client.api
+ .guilds(this.id)
+ .embed.patch({
+ data: {
+ enabled: embed.enabled,
+ channel_id: this.channels.resolveID(embed.channel),
+ },
+ reason,
+ })
+ .then(() => this);
+ }
+
+ /**
+ * Leaves the guild.
+ * @returns {Promise<Guild>}
+ * @example
+ * // Leave a guild
+ * guild.leave()
+ * .then(g => console.log(`Left the guild ${g}`))
+ * .catch(console.error);
+ */
+ leave() {
+ if (this.ownerID === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED'));
+ return this.client.api
+ .users('@me')
+ .guilds(this.id)
+ .delete()
+ .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
+ }
+
+ /**
+ * Deletes the guild.
+ * @returns {Promise<Guild>}
+ * @example
+ * // Delete a guild
+ * guild.delete()
+ * .then(g => console.log(`Deleted the guild ${g}`))
+ * .catch(console.error);
+ */
+ delete() {
+ return this.client.api
+ .guilds(this.id)
+ .delete()
+ .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
+ }
+
+ /**
+ * Whether this guild equals another guild. It compares all properties, so for most operations
+ * it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
+ * what most users need.
+ * @param {Guild} guild The guild to compare with
+ * @returns {boolean}
+ */
+ equals(guild) {
+ let equal =
+ guild &&
+ guild instanceof this.constructor &&
+ this.id === guild.id &&
+ this.available === guild.available &&
+ this.splash === guild.splash &&
+ this.region === guild.region &&
+ this.name === guild.name &&
+ this.memberCount === guild.memberCount &&
+ this.large === guild.large &&
+ this.icon === guild.icon &&
+ this.ownerID === guild.ownerID &&
+ this.verificationLevel === guild.verificationLevel &&
+ this.embedEnabled === guild.embedEnabled &&
+ (this.features === guild.features ||
+ (this.features.length === guild.features.length &&
+ this.features.every((feat, i) => feat === guild.features[i])));
+
+ if (equal) {
+ if (this.embedChannel) {
+ if (!guild.embedChannel || this.embedChannel.id !== guild.embedChannel.id) equal = false;
+ } else if (guild.embedChannel) {
+ equal = false;
+ }
+ }
+
+ return equal;
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the guild's name instead of the Guild object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from My Guild!
+ * console.log(`Hello from ${guild}!`);
+ */
+ toString() {
+ return this.name;
+ }
+
+ toJSON() {
+ const json = super.toJSON({
+ available: false,
+ createdTimestamp: true,
+ nameAcronym: true,
+ presences: false,
+ voiceStates: false,
+ });
+ json.iconURL = this.iconURL();
+ json.splashURL = this.splashURL();
+ json.bannerURL = this.bannerURL();
+ return json;
+ }
+
+ /**
+ * Creates a collection of this guild's roles, sorted by their position and IDs.
+ * @returns {Collection<Role>}
+ * @private
+ */
+ _sortedRoles() {
+ return Util.discordSort(this.roles.cache);
+ }
+
+ /**
+ * Creates a collection of this guild's or a specific category's channels, sorted by their position and IDs.
+ * @param {GuildChannel} [channel] Category to get the channels of
+ * @returns {Collection<GuildChannel>}
+ * @private
+ */
+ _sortedChannels(channel) {
+ const category = channel.type === ChannelTypes.CATEGORY;
+ return Util.discordSort(
+ this.channels.cache.filter(
+ c =>
+ (['text', 'news', 'store'].includes(channel.type)
+ ? ['text', 'news', 'store'].includes(c.type)
+ : c.type === channel.type) &&
+ (category || c.parent === channel.parent),
+ ),
+ );
+ }
+}
+
+module.exports = Guild;
diff --git a/node_modules/discord.js/src/structures/GuildAuditLogs.js b/node_modules/discord.js/src/structures/GuildAuditLogs.js
new file mode 100644
index 0000000..b3522b0
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildAuditLogs.js
@@ -0,0 +1,509 @@
+'use strict';
+
+const Integration = require('./Integration');
+const Webhook = require('./Webhook');
+const Collection = require('../util/Collection');
+const { PartialTypes } = require('../util/Constants');
+const Snowflake = require('../util/Snowflake');
+const Util = require('../util/Util');
+
+/**
+ * The target type of an entry, e.g. `GUILD`. Here are the available types:
+ * * GUILD
+ * * CHANNEL
+ * * USER
+ * * ROLE
+ * * INVITE
+ * * WEBHOOK
+ * * EMOJI
+ * * MESSAGE
+ * * INTEGRATION
+ * @typedef {string} AuditLogTargetType
+ */
+
+/**
+ * Key mirror of all available audit log targets.
+ * @name GuildAuditLogs.Targets
+ * @type {AuditLogTargetType}
+ */
+const Targets = {
+ ALL: 'ALL',
+ GUILD: 'GUILD',
+ CHANNEL: 'CHANNEL',
+ USER: 'USER',
+ ROLE: 'ROLE',
+ INVITE: 'INVITE',
+ WEBHOOK: 'WEBHOOK',
+ EMOJI: 'EMOJI',
+ MESSAGE: 'MESSAGE',
+ INTEGRATION: 'INTEGRATION',
+ UNKNOWN: 'UNKNOWN',
+};
+
+/**
+ * The action of an entry. Here are the available actions:
+ * * ALL: null
+ * * GUILD_UPDATE: 1
+ * * CHANNEL_CREATE: 10
+ * * CHANNEL_UPDATE: 11
+ * * CHANNEL_DELETE: 12
+ * * CHANNEL_OVERWRITE_CREATE: 13
+ * * CHANNEL_OVERWRITE_UPDATE: 14
+ * * CHANNEL_OVERWRITE_DELETE: 15
+ * * MEMBER_KICK: 20
+ * * MEMBER_PRUNE: 21
+ * * MEMBER_BAN_ADD: 22
+ * * MEMBER_BAN_REMOVE: 23
+ * * MEMBER_UPDATE: 24
+ * * MEMBER_ROLE_UPDATE: 25
+ * * MEMBER_MOVE: 26
+ * * MEMBER_DISCONNECT: 27
+ * * BOT_ADD: 28,
+ * * ROLE_CREATE: 30
+ * * ROLE_UPDATE: 31
+ * * ROLE_DELETE: 32
+ * * INVITE_CREATE: 40
+ * * INVITE_UPDATE: 41
+ * * INVITE_DELETE: 42
+ * * WEBHOOK_CREATE: 50
+ * * WEBHOOK_UPDATE: 51
+ * * WEBHOOK_DELETE: 52
+ * * EMOJI_CREATE: 60
+ * * EMOJI_UPDATE: 61
+ * * EMOJI_DELETE: 62
+ * * MESSAGE_DELETE: 72
+ * * MESSAGE_BULK_DELETE: 73
+ * * MESSAGE_PIN: 74
+ * * MESSAGE_UNPIN: 75
+ * * INTEGRATION_CREATE: 80
+ * * INTEGRATION_UPDATE: 81
+ * * INTEGRATION_DELETE: 82
+ * @typedef {?number|string} AuditLogAction
+ */
+
+/**
+ * All available actions keyed under their names to their numeric values.
+ * @name GuildAuditLogs.Actions
+ * @type {AuditLogAction}
+ */
+const Actions = {
+ ALL: null,
+ GUILD_UPDATE: 1,
+ CHANNEL_CREATE: 10,
+ CHANNEL_UPDATE: 11,
+ CHANNEL_DELETE: 12,
+ CHANNEL_OVERWRITE_CREATE: 13,
+ CHANNEL_OVERWRITE_UPDATE: 14,
+ CHANNEL_OVERWRITE_DELETE: 15,
+ MEMBER_KICK: 20,
+ MEMBER_PRUNE: 21,
+ MEMBER_BAN_ADD: 22,
+ MEMBER_BAN_REMOVE: 23,
+ MEMBER_UPDATE: 24,
+ MEMBER_ROLE_UPDATE: 25,
+ MEMBER_MOVE: 26,
+ MEMBER_DISCONNECT: 27,
+ BOT_ADD: 28,
+ ROLE_CREATE: 30,
+ ROLE_UPDATE: 31,
+ ROLE_DELETE: 32,
+ INVITE_CREATE: 40,
+ INVITE_UPDATE: 41,
+ INVITE_DELETE: 42,
+ WEBHOOK_CREATE: 50,
+ WEBHOOK_UPDATE: 51,
+ WEBHOOK_DELETE: 52,
+ EMOJI_CREATE: 60,
+ EMOJI_UPDATE: 61,
+ EMOJI_DELETE: 62,
+ MESSAGE_DELETE: 72,
+ MESSAGE_BULK_DELETE: 73,
+ MESSAGE_PIN: 74,
+ MESSAGE_UNPIN: 75,
+ INTEGRATION_CREATE: 80,
+ INTEGRATION_UPDATE: 81,
+ INTEGRATION_DELETE: 82,
+};
+
+/**
+ * Audit logs entries are held in this class.
+ */
+class GuildAuditLogs {
+ constructor(guild, data) {
+ if (data.users) for (const user of data.users) guild.client.users.add(user);
+ /**
+ * Cached webhooks
+ * @type {Collection<Snowflake, Webhook>}
+ * @private
+ */
+ this.webhooks = new Collection();
+ if (data.webhooks) {
+ for (const hook of data.webhooks) {
+ this.webhooks.set(hook.id, new Webhook(guild.client, hook));
+ }
+ }
+
+ /**
+ * Cached integrations
+ * @type {Collection<Snowflake, Integration>}
+ * @private
+ */
+ this.integrations = new Collection();
+ if (data.integrations) {
+ for (const integration of data.integrations) {
+ this.integrations.set(integration.id, new Integration(guild.client, integration, guild));
+ }
+ }
+
+ /**
+ * The entries for this guild's audit logs
+ * @type {Collection<Snowflake, GuildAuditLogsEntry>}
+ */
+ this.entries = new Collection();
+ for (const item of data.audit_log_entries) {
+ const entry = new GuildAuditLogsEntry(this, guild, item);
+ this.entries.set(entry.id, entry);
+ }
+ }
+
+ /**
+ * Handles possible promises for entry targets.
+ * @returns {Promise<GuildAuditLogs>}
+ */
+ static build(...args) {
+ const logs = new GuildAuditLogs(...args);
+ return Promise.all(logs.entries.map(e => e.target)).then(() => logs);
+ }
+
+ /**
+ * The target of an entry. It can be one of:
+ * * A guild
+ * * A user
+ * * A role
+ * * An emoji
+ * * An invite
+ * * A webhook
+ * * An integration
+ * * An object with an id key if target was deleted
+ * * An object where the keys represent either the new value or the old value
+ * @typedef {?Object|Guild|User|Role|GuildEmoji|Invite|Webhook|Integration} AuditLogEntryTarget
+ */
+
+ /**
+ * Finds the target type from the entry action.
+ * @param {AuditLogAction} target The action target
+ * @returns {AuditLogTargetType}
+ */
+ static targetType(target) {
+ if (target < 10) return Targets.GUILD;
+ if (target < 20) return Targets.CHANNEL;
+ if (target < 30) return Targets.USER;
+ if (target < 40) return Targets.ROLE;
+ if (target < 50) return Targets.INVITE;
+ if (target < 60) return Targets.WEBHOOK;
+ if (target < 70) return Targets.EMOJI;
+ if (target < 80) return Targets.MESSAGE;
+ if (target < 90) return Targets.INTEGRATION;
+ return Targets.UNKNOWN;
+ }
+
+ /**
+ * The action type of an entry, e.g. `CREATE`. Here are the available types:
+ * * CREATE
+ * * DELETE
+ * * UPDATE
+ * * ALL
+ * @typedef {string} AuditLogActionType
+ */
+
+ /**
+ * Finds the action type from the entry action.
+ * @param {AuditLogAction} action The action target
+ * @returns {AuditLogActionType}
+ */
+ static actionType(action) {
+ if (
+ [
+ Actions.CHANNEL_CREATE,
+ Actions.CHANNEL_OVERWRITE_CREATE,
+ Actions.MEMBER_BAN_REMOVE,
+ Actions.BOT_ADD,
+ Actions.ROLE_CREATE,
+ Actions.INVITE_CREATE,
+ Actions.WEBHOOK_CREATE,
+ Actions.EMOJI_CREATE,
+ Actions.MESSAGE_PIN,
+ Actions.INTEGRATION_CREATE,
+ ].includes(action)
+ ) {
+ return 'CREATE';
+ }
+
+ if (
+ [
+ Actions.CHANNEL_DELETE,
+ Actions.CHANNEL_OVERWRITE_DELETE,
+ Actions.MEMBER_KICK,
+ Actions.MEMBER_PRUNE,
+ Actions.MEMBER_BAN_ADD,
+ Actions.MEMBER_DISCONNECT,
+ Actions.ROLE_DELETE,
+ Actions.INVITE_DELETE,
+ Actions.WEBHOOK_DELETE,
+ Actions.EMOJI_DELETE,
+ Actions.MESSAGE_DELETE,
+ Actions.MESSAGE_BULK_DELETE,
+ Actions.MESSAGE_UNPIN,
+ Actions.INTEGRATION_DELETE,
+ ].includes(action)
+ ) {
+ return 'DELETE';
+ }
+
+ if (
+ [
+ Actions.GUILD_UPDATE,
+ Actions.CHANNEL_UPDATE,
+ Actions.CHANNEL_OVERWRITE_UPDATE,
+ Actions.MEMBER_UPDATE,
+ Actions.MEMBER_ROLE_UPDATE,
+ Actions.MEMBER_MOVE,
+ Actions.ROLE_UPDATE,
+ Actions.INVITE_UPDATE,
+ Actions.WEBHOOK_UPDATE,
+ Actions.EMOJI_UPDATE,
+ Actions.INTEGRATION_UPDATE,
+ ].includes(action)
+ ) {
+ return 'UPDATE';
+ }
+
+ return 'ALL';
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+}
+
+/**
+ * Audit logs entry.
+ */
+class GuildAuditLogsEntry {
+ constructor(logs, guild, data) {
+ const targetType = GuildAuditLogs.targetType(data.action_type);
+ /**
+ * The target type of this entry
+ * @type {AuditLogTargetType}
+ */
+ this.targetType = targetType;
+
+ /**
+ * The action type of this entry
+ * @type {AuditLogActionType}
+ */
+ this.actionType = GuildAuditLogs.actionType(data.action_type);
+
+ /**
+ * Specific action type of this entry in its string presentation
+ * @type {AuditLogAction}
+ */
+ this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type);
+
+ /**
+ * The reason of this entry
+ * @type {?string}
+ */
+ this.reason = data.reason || null;
+
+ /**
+ * The user that executed this entry
+ * @type {User}
+ */
+ this.executor = guild.client.options.partials.includes(PartialTypes.USER)
+ ? guild.client.users.add({ id: data.user_id })
+ : guild.client.users.cache.get(data.user_id);
+
+ /**
+ * An entry in the audit log representing a specific change.
+ * @typedef {object} AuditLogChange
+ * @property {string} key The property that was changed, e.g. `nick` for nickname changes
+ * @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname
+ * @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname
+ */
+
+ /**
+ * Specific property changes
+ * @type {AuditLogChange[]}
+ */
+ this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null;
+
+ /**
+ * The ID of this entry
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * Any extra data from the entry
+ * @type {?Object|Role|GuildMember}
+ */
+ this.extra = null;
+ switch (data.action_type) {
+ case Actions.MEMBER_PRUNE:
+ this.extra = {
+ removed: Number(data.options.members_removed),
+ days: Number(data.options.delete_member_days),
+ };
+ break;
+
+ case Actions.MEMBER_MOVE:
+ case Actions.MESSAGE_DELETE:
+ case Actions.MESSAGE_BULK_DELETE:
+ this.extra = {
+ channel: guild.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id },
+ count: Number(data.options.count),
+ };
+ break;
+
+ case Actions.MESSAGE_PIN:
+ case Actions.MESSAGE_UNPIN:
+ this.extra = {
+ channel: guild.client.channels.cache.get(data.options.channel_id) || { id: data.options.channel_id },
+ messageID: data.options.message_id,
+ };
+ break;
+
+ case Actions.MEMBER_DISCONNECT:
+ this.extra = {
+ count: Number(data.options.count),
+ };
+ break;
+
+ case Actions.CHANNEL_OVERWRITE_CREATE:
+ case Actions.CHANNEL_OVERWRITE_UPDATE:
+ case Actions.CHANNEL_OVERWRITE_DELETE:
+ switch (data.options.type) {
+ case 'member':
+ this.extra = guild.members.cache.get(data.options.id) || { id: data.options.id, type: 'member' };
+ break;
+
+ case 'role':
+ this.extra = guild.roles.cache.get(data.options.id) || {
+ id: data.options.id,
+ name: data.options.role_name,
+ type: 'role',
+ };
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /**
+ * The target of this entry
+ * @type {?AuditLogEntryTarget}
+ */
+ this.target = null;
+ if (targetType === Targets.UNKNOWN) {
+ this.target = this.changes.reduce((o, c) => {
+ o[c.key] = c.new || c.old;
+ return o;
+ }, {});
+ this.target.id = data.target_id;
+ // MEMBER_DISCONNECT and similar types do not provide a target_id.
+ } else if (targetType === Targets.USER && data.target_id) {
+ this.target = guild.client.options.partials.includes(PartialTypes.USER)
+ ? guild.client.users.add({ id: data.target_id })
+ : guild.client.users.cache.get(data.target_id);
+ } else if (targetType === Targets.GUILD) {
+ this.target = guild.client.guilds.cache.get(data.target_id);
+ } else if (targetType === Targets.WEBHOOK) {
+ this.target =
+ logs.webhooks.get(data.target_id) ||
+ new Webhook(
+ guild.client,
+ this.changes.reduce(
+ (o, c) => {
+ o[c.key] = c.new || c.old;
+ return o;
+ },
+ {
+ id: data.target_id,
+ guild_id: guild.id,
+ },
+ ),
+ );
+ } else if (targetType === Targets.INVITE) {
+ this.target = guild.members.fetch(guild.client.user.id).then(me => {
+ if (me.permissions.has('MANAGE_GUILD')) {
+ const change = this.changes.find(c => c.key === 'code');
+ return guild.fetchInvites().then(invites => {
+ this.target = invites.find(i => i.code === (change.new || change.old));
+ });
+ } else {
+ this.target = this.changes.reduce((o, c) => {
+ o[c.key] = c.new || c.old;
+ return o;
+ }, {});
+ return this.target;
+ }
+ });
+ } else if (targetType === Targets.MESSAGE) {
+ // Discord sends a channel id for the MESSAGE_BULK_DELETE action type.
+ this.target =
+ data.action_type === Actions.MESSAGE_BULK_DELETE
+ ? guild.channels.cache.get(data.target_id) || { id: data.target_id }
+ : guild.client.users.cache.get(data.target_id);
+ } else if (targetType === Targets.INTEGRATION) {
+ this.target =
+ logs.integrations.get(data.target_id) ||
+ new Integration(
+ guild.client,
+ this.changes.reduce(
+ (o, c) => {
+ o[c.key] = c.new || c.old;
+ return o;
+ },
+ { id: data.target_id },
+ ),
+ guild,
+ );
+ } else if (data.target_id) {
+ this.target = guild[`${targetType.toLowerCase()}s`].cache.get(data.target_id) || { id: data.target_id };
+ }
+ }
+
+ /**
+ * The timestamp this entry was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time this entry was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ toJSON() {
+ return Util.flatten(this, { createdTimestamp: true });
+ }
+}
+
+GuildAuditLogs.Actions = Actions;
+GuildAuditLogs.Targets = Targets;
+GuildAuditLogs.Entry = GuildAuditLogsEntry;
+
+module.exports = GuildAuditLogs;
diff --git a/node_modules/discord.js/src/structures/GuildChannel.js b/node_modules/discord.js/src/structures/GuildChannel.js
new file mode 100644
index 0000000..2e80eca
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildChannel.js
@@ -0,0 +1,609 @@
+'use strict';
+
+const Channel = require('./Channel');
+const Invite = require('./Invite');
+const PermissionOverwrites = require('./PermissionOverwrites');
+const Role = require('./Role');
+const { Error, TypeError } = require('../errors');
+const Collection = require('../util/Collection');
+const Permissions = require('../util/Permissions');
+const Util = require('../util/Util');
+
+/**
+ * Represents a guild channel from any of the following:
+ * - {@link TextChannel}
+ * - {@link VoiceChannel}
+ * - {@link CategoryChannel}
+ * - {@link NewsChannel}
+ * - {@link StoreChannel}
+ * @extends {Channel}
+ */
+class GuildChannel extends Channel {
+ /**
+ * @param {Guild} guild The guild the guild channel is part of
+ * @param {Object} data The data for the guild channel
+ */
+ constructor(guild, data) {
+ super(guild.client, data);
+
+ /**
+ * The guild the channel is in
+ * @type {Guild}
+ */
+ this.guild = guild;
+ }
+
+ _patch(data) {
+ super._patch(data);
+
+ /**
+ * The name of the guild channel
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The raw position of the channel from discord
+ * @type {number}
+ */
+ this.rawPosition = data.position;
+
+ /**
+ * The ID of the category parent of this channel
+ * @type {?Snowflake}
+ */
+ this.parentID = data.parent_id;
+
+ /**
+ * A map of permission overwrites in this channel for roles and users
+ * @type {Collection<Snowflake, PermissionOverwrites>}
+ */
+ this.permissionOverwrites = new Collection();
+ if (data.permission_overwrites) {
+ for (const overwrite of data.permission_overwrites) {
+ this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite));
+ }
+ }
+ }
+
+ /**
+ * The category parent of this channel
+ * @type {?CategoryChannel}
+ * @readonly
+ */
+ get parent() {
+ return this.guild.channels.cache.get(this.parentID) || null;
+ }
+
+ /**
+ * If the permissionOverwrites match the parent channel, null if no parent
+ * @type {?boolean}
+ * @readonly
+ */
+ get permissionsLocked() {
+ if (!this.parent) return null;
+ if (this.permissionOverwrites.size !== this.parent.permissionOverwrites.size) return false;
+ return this.permissionOverwrites.every((value, key) => {
+ const testVal = this.parent.permissionOverwrites.get(key);
+ return (
+ testVal !== undefined &&
+ testVal.deny.bitfield === value.deny.bitfield &&
+ testVal.allow.bitfield === value.allow.bitfield
+ );
+ });
+ }
+
+ /**
+ * The position of the channel
+ * @type {number}
+ * @readonly
+ */
+ get position() {
+ const sorted = this.guild._sortedChannels(this);
+ return sorted.array().indexOf(sorted.get(this.id));
+ }
+
+ /**
+ * Gets the overall set of permissions for a member or role in this channel, taking into account channel overwrites.
+ * @param {GuildMemberResolvable|RoleResolvable} memberOrRole The member or role to obtain the overall permissions for
+ * @returns {?Readonly<Permissions>}
+ */
+ permissionsFor(memberOrRole) {
+ const member = this.guild.members.resolve(memberOrRole);
+ if (member) return this.memberPermissions(member);
+ const role = this.guild.roles.resolve(memberOrRole);
+ if (role) return this.rolePermissions(role);
+ return null;
+ }
+
+ overwritesFor(member, verified = false, roles = null) {
+ if (!verified) member = this.guild.members.resolve(member);
+ if (!member) return [];
+
+ roles = roles || member.roles.cache;
+ const roleOverwrites = [];
+ let memberOverwrites;
+ let everyoneOverwrites;
+
+ for (const overwrite of this.permissionOverwrites.values()) {
+ if (overwrite.id === this.guild.id) {
+ everyoneOverwrites = overwrite;
+ } else if (roles.has(overwrite.id)) {
+ roleOverwrites.push(overwrite);
+ } else if (overwrite.id === member.id) {
+ memberOverwrites = overwrite;
+ }
+ }
+
+ return {
+ everyone: everyoneOverwrites,
+ roles: roleOverwrites,
+ member: memberOverwrites,
+ };
+ }
+
+ /**
+ * Gets the overall set of permissions for a member in this channel, taking into account channel overwrites.
+ * @param {GuildMember} member The member to obtain the overall permissions for
+ * @returns {Readonly<Permissions>}
+ * @private
+ */
+ memberPermissions(member) {
+ if (member.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze();
+
+ const roles = member.roles.cache;
+ const permissions = new Permissions(roles.map(role => role.permissions));
+
+ if (permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
+
+ const overwrites = this.overwritesFor(member, true, roles);
+
+ return permissions
+ .remove(overwrites.everyone ? overwrites.everyone.deny : 0)
+ .add(overwrites.everyone ? overwrites.everyone.allow : 0)
+ .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : 0)
+ .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : 0)
+ .remove(overwrites.member ? overwrites.member.deny : 0)
+ .add(overwrites.member ? overwrites.member.allow : 0)
+ .freeze();
+ }
+
+ /**
+ * Gets the overall set of permissions for a role in this channel, taking into account channel overwrites.
+ * @param {Role} role The role to obtain the overall permissions for
+ * @returns {Readonly<Permissions>}
+ * @private
+ */
+ rolePermissions(role) {
+ if (role.permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
+
+ const everyoneOverwrites = this.permissionOverwrites.get(this.guild.id);
+ const roleOverwrites = this.permissionOverwrites.get(role.id);
+
+ return role.permissions
+ .remove(everyoneOverwrites ? everyoneOverwrites.deny : 0)
+ .add(everyoneOverwrites ? everyoneOverwrites.allow : 0)
+ .remove(roleOverwrites ? roleOverwrites.deny : 0)
+ .add(roleOverwrites ? roleOverwrites.allow : 0)
+ .freeze();
+ }
+
+ /**
+ * Replaces the permission overwrites in this channel.
+ * @param {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} overwrites
+ * Permission overwrites the channel gets updated with
+ * @param {string} [reason] Reason for updating the channel overwrites
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * channel.overwritePermissions([
+ * {
+ * id: message.author.id,
+ * deny: ['VIEW_CHANNEL'],
+ * },
+ * ], 'Needed to change permissions');
+ */
+ overwritePermissions(overwrites, reason) {
+ if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
+ return Promise.reject(
+ new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true),
+ );
+ }
+ return this.edit({ permissionOverwrites: overwrites, reason }).then(() => this);
+ }
+
+ /**
+ * Updates Overwrites for a user or role in this channel. (creates if non-existent)
+ * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
+ * @param {PermissionOverwriteOptions} options The options for the update
+ * @param {string} [reason] Reason for creating/editing this overwrite
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Update or Create permission overwrites for a message author
+ * message.channel.updateOverwrite(message.author, {
+ * SEND_MESSAGES: false
+ * })
+ * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id)))
+ * .catch(console.error);
+ */
+ updateOverwrite(userOrRole, options, reason) {
+ userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole);
+ if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role', true));
+
+ const existing = this.permissionOverwrites.get(userOrRole.id);
+ if (existing) return existing.update(options, reason).then(() => this);
+ return this.createOverwrite(userOrRole, options, reason);
+ }
+
+ /**
+ * Overwrites the permissions for a user or role in this channel. (replaces if existent)
+ * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
+ * @param {PermissionOverwriteOptions} options The options for the update
+ * @param {string} [reason] Reason for creating/editing this overwrite
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Create or Replace permissions overwrites for a message author
+ * message.channel.createOverwrite(message.author, {
+ * SEND_MESSAGES: false
+ * })
+ * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id)))
+ * .catch(console.error);
+ */
+ createOverwrite(userOrRole, options, reason) {
+ userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole);
+ if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role', true));
+
+ const type = userOrRole instanceof Role ? 'role' : 'member';
+ const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options);
+
+ return this.client.api
+ .channels(this.id)
+ .permissions[userOrRole.id].put({
+ data: { id: userOrRole.id, type, allow: allow.bitfield, deny: deny.bitfield },
+ reason,
+ })
+ .then(() => this);
+ }
+
+ /**
+ * Locks in the permission overwrites from the parent channel.
+ * @returns {Promise<GuildChannel>}
+ */
+ lockPermissions() {
+ if (!this.parent) return Promise.reject(new Error('GUILD_CHANNEL_ORPHAN'));
+ const permissionOverwrites = this.parent.permissionOverwrites.map(overwrite => overwrite.toJSON());
+ return this.edit({ permissionOverwrites });
+ }
+
+ /**
+ * A collection of members that can see this channel, mapped by their ID
+ * @type {Collection<Snowflake, GuildMember>}
+ * @readonly
+ */
+ get members() {
+ const members = new Collection();
+ for (const member of this.guild.members.cache.values()) {
+ if (this.permissionsFor(member).has('VIEW_CHANNEL', false)) {
+ members.set(member.id, member);
+ }
+ }
+ return members;
+ }
+
+ /**
+ * The data for a guild channel.
+ * @typedef {Object} ChannelData
+ * @property {string} [name] The name of the channel
+ * @property {number} [position] The position of the channel
+ * @property {string} [topic] The topic of the text channel
+ * @property {boolean} [nsfw] Whether the channel is NSFW
+ * @property {number} [bitrate] The bitrate of the voice channel
+ * @property {number} [userLimit] The user limit of the voice channel
+ * @property {Snowflake} [parentID] The parent ID of the channel
+ * @property {boolean} [lockPermissions]
+ * Lock the permissions of the channel to what the parent's permissions are
+ * @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
+ * Permission overwrites for the channel
+ * @property {number} [rateLimitPerUser] The ratelimit per user for the channel in seconds
+ */
+
+ /**
+ * Edits the channel.
+ * @param {ChannelData} data The new data for the channel
+ * @param {string} [reason] Reason for editing this channel
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Edit a channel
+ * channel.edit({ name: 'new-channel' })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ async edit(data, reason) {
+ if (typeof data.position !== 'undefined') {
+ await Util.setPosition(
+ this,
+ data.position,
+ false,
+ this.guild._sortedChannels(this),
+ this.client.api.guilds(this.guild.id).channels,
+ reason,
+ ).then(updatedChannels => {
+ this.client.actions.GuildChannelsPositionUpdate.handle({
+ guild_id: this.guild.id,
+ channels: updatedChannels,
+ });
+ });
+ }
+
+ const permission_overwrites =
+ data.permissionOverwrites && data.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
+
+ const newData = await this.client.api.channels(this.id).patch({
+ data: {
+ name: (data.name || this.name).trim(),
+ topic: data.topic,
+ nsfw: data.nsfw,
+ bitrate: data.bitrate || this.bitrate,
+ user_limit: typeof data.userLimit !== 'undefined' ? data.userLimit : this.userLimit,
+ parent_id: data.parentID,
+ lock_permissions: data.lockPermissions,
+ rate_limit_per_user: data.rateLimitPerUser,
+ permission_overwrites,
+ },
+ reason,
+ });
+
+ const clone = this._clone();
+ clone._patch(newData);
+ return clone;
+ }
+
+ /**
+ * Sets a new name for the guild channel.
+ * @param {string} name The new name for the guild channel
+ * @param {string} [reason] Reason for changing the guild channel's name
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Set a new channel name
+ * channel.setName('not_general')
+ * .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`))
+ * .catch(console.error);
+ */
+ setName(name, reason) {
+ return this.edit({ name }, reason);
+ }
+
+ /**
+ * Sets the category parent of this channel.
+ * @param {?CategoryChannel|Snowflake} channel Parent channel
+ * @param {Object} [options={}] Options to pass
+ * @param {boolean} [options.lockPermissions=true] Lock the permissions to what the parent's permissions are
+ * @param {string} [options.reason] Reason for modifying the parent of this channel
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Add a parent to a channel
+ * message.channel.setParent('355908108431917066', { lockPermissions: false })
+ * .then(channel => console.log(`New parent of ${message.channel.name}: ${channel.name}`))
+ * .catch(console.error);
+ */
+ setParent(channel, { lockPermissions = true, reason } = {}) {
+ return this.edit(
+ {
+ // eslint-disable-next-line no-prototype-builtins
+ parentID: channel !== null ? (channel.hasOwnProperty('id') ? channel.id : channel) : null,
+ lockPermissions,
+ },
+ reason,
+ );
+ }
+
+ /**
+ * Sets a new topic for the guild channel.
+ * @param {string} topic The new topic for the guild channel
+ * @param {string} [reason] Reason for changing the guild channel's topic
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Set a new channel topic
+ * channel.setTopic('needs more rate limiting')
+ * .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`))
+ * .catch(console.error);
+ */
+ setTopic(topic, reason) {
+ return this.edit({ topic }, reason);
+ }
+
+ /**
+ * Sets a new position for the guild channel.
+ * @param {number} position The new position for the guild channel
+ * @param {Object} [options] Options for setting position
+ * @param {boolean} [options.relative=false] Change the position relative to its current value
+ * @param {string} [options.reason] Reason for changing the position
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Set a new channel position
+ * channel.setPosition(2)
+ * .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
+ * .catch(console.error);
+ */
+ setPosition(position, { relative, reason } = {}) {
+ return Util.setPosition(
+ this,
+ position,
+ relative,
+ this.guild._sortedChannels(this),
+ this.client.api.guilds(this.guild.id).channels,
+ reason,
+ ).then(updatedChannels => {
+ this.client.actions.GuildChannelsPositionUpdate.handle({
+ guild_id: this.guild.id,
+ channels: updatedChannels,
+ });
+ return this;
+ });
+ }
+
+ /**
+ * Creates an invite to this guild channel.
+ * @param {Object} [options={}] Options for the invite
+ * @param {boolean} [options.temporary=false] Whether members that joined via the invite should be automatically
+ * kicked after 24 hours if they have not yet received a role
+ * @param {number} [options.maxAge=86400] How long the invite should last (in seconds, 0 for forever)
+ * @param {number} [options.maxUses=0] Maximum number of uses
+ * @param {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings
+ * @param {string} [options.reason] Reason for creating this
+ * @returns {Promise<Invite>}
+ * @example
+ * // Create an invite to a channel
+ * channel.createInvite()
+ * .then(invite => console.log(`Created an invite with a code of ${invite.code}`))
+ * .catch(console.error);
+ */
+ createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) {
+ return this.client.api
+ .channels(this.id)
+ .invites.post({
+ data: {
+ temporary,
+ max_age: maxAge,
+ max_uses: maxUses,
+ unique,
+ },
+ reason,
+ })
+ .then(invite => new Invite(this.client, invite));
+ }
+
+ /**
+ * Fetches a collection of invites to this guild channel.
+ * Resolves with a collection mapping invites by their codes.
+ * @returns {Promise<Collection<string, Invite>>}
+ */
+ async fetchInvites() {
+ const inviteItems = await this.client.api.channels(this.id).invites.get();
+ const invites = new Collection();
+ for (const inviteItem of inviteItems) {
+ const invite = new Invite(this.client, inviteItem);
+ invites.set(invite.code, invite);
+ }
+ return invites;
+ }
+
+ /* eslint-disable max-len */
+ /**
+ * Clones this channel.
+ * @param {Object} [options] The options
+ * @param {string} [options.name=this.name] Name of the new channel
+ * @param {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [options.permissionOverwrites=this.permissionOverwrites]
+ * Permission overwrites of the new channel
+ * @param {string} [options.type=this.type] Type of the new channel
+ * @param {string} [options.topic=this.topic] Topic of the new channel (only text)
+ * @param {boolean} [options.nsfw=this.nsfw] Whether the new channel is nsfw (only text)
+ * @param {number} [options.bitrate=this.bitrate] Bitrate of the new channel in bits (only voice)
+ * @param {number} [options.userLimit=this.userLimit] Maximum amount of users allowed in the new channel (only voice)
+ * @param {number} [options.rateLimitPerUser=ThisType.rateLimitPerUser] Ratelimit per user for the new channel (only text)
+ * @param {ChannelResolvable} [options.parent=this.parent] Parent of the new channel
+ * @param {string} [options.reason] Reason for cloning this channel
+ * @returns {Promise<GuildChannel>}
+ */
+ clone(options = {}) {
+ Util.mergeDefault(
+ {
+ name: this.name,
+ permissionOverwrites: this.permissionOverwrites,
+ topic: this.topic,
+ type: this.type,
+ nsfw: this.nsfw,
+ parent: this.parent,
+ bitrate: this.bitrate,
+ userLimit: this.userLimit,
+ rateLimitPerUser: this.rateLimitPerUser,
+ reason: null,
+ },
+ options,
+ );
+ return this.guild.channels.create(options.name, options);
+ }
+ /* eslint-enable max-len */
+
+ /**
+ * Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel.
+ * In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
+ * @param {GuildChannel} channel Channel to compare with
+ * @returns {boolean}
+ */
+ equals(channel) {
+ let equal =
+ channel &&
+ this.id === channel.id &&
+ this.type === channel.type &&
+ this.topic === channel.topic &&
+ this.position === channel.position &&
+ this.name === channel.name;
+
+ if (equal) {
+ if (this.permissionOverwrites && channel.permissionOverwrites) {
+ equal = this.permissionOverwrites.equals(channel.permissionOverwrites);
+ } else {
+ equal = !this.permissionOverwrites && !channel.permissionOverwrites;
+ }
+ }
+
+ return equal;
+ }
+
+ /**
+ * Whether the channel is deletable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get deletable() {
+ return this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false);
+ }
+
+ /**
+ * Whether the channel is manageable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get manageable() {
+ if (this.client.user.id === this.guild.ownerID) return true;
+ if (this.type === 'voice') {
+ if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) {
+ return false;
+ }
+ } else if (!this.viewable) {
+ return false;
+ }
+ return this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false);
+ }
+
+ /**
+ * Whether the channel is viewable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get viewable() {
+ if (this.client.user.id === this.guild.ownerID) return true;
+ const permissions = this.permissionsFor(this.client.user);
+ if (!permissions) return false;
+ return permissions.has(Permissions.FLAGS.VIEW_CHANNEL, false);
+ }
+
+ /**
+ * Deletes this channel.
+ * @param {string} [reason] Reason for deleting this channel
+ * @returns {Promise<GuildChannel>}
+ * @example
+ * // Delete the channel
+ * channel.delete('making room for new channels')
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ delete(reason) {
+ return this.client.api
+ .channels(this.id)
+ .delete({ reason })
+ .then(() => this);
+ }
+}
+
+module.exports = GuildChannel;
diff --git a/node_modules/discord.js/src/structures/GuildEmoji.js b/node_modules/discord.js/src/structures/GuildEmoji.js
new file mode 100644
index 0000000..d4189e9
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildEmoji.js
@@ -0,0 +1,159 @@
+'use strict';
+
+const BaseGuildEmoji = require('./BaseGuildEmoji');
+const { Error } = require('../errors');
+const GuildEmojiRoleManager = require('../managers/GuildEmojiRoleManager');
+const Permissions = require('../util/Permissions');
+
+/**
+ * Represents a custom emoji.
+ * @extends {BaseGuildEmoji}
+ */
+class GuildEmoji extends BaseGuildEmoji {
+ /**
+ * @name GuildEmoji
+ * @kind constructor
+ * @memberof GuildEmoji
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the guild emoji
+ * @param {Guild} guild The guild the guild emoji is part of
+ */
+
+ /**
+ * The guild this emoji is part of
+ * @type {Guild}
+ * @name GuildEmoji#guild
+ */
+
+ _clone() {
+ const clone = super._clone();
+ clone._roles = this._roles.slice();
+ return clone;
+ }
+
+ /**
+ * Whether the emoji is deletable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get deletable() {
+ if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME');
+ return !this.managed && this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS);
+ }
+
+ /**
+ * A manager for roles this emoji is active for.
+ * @type {GuildEmojiRoleManager}
+ * @readonly
+ */
+ get roles() {
+ return new GuildEmojiRoleManager(this);
+ }
+
+ /**
+ * Fetches the author for this emoji
+ * @returns {Promise<User>}
+ */
+ fetchAuthor() {
+ if (this.managed) {
+ return Promise.reject(new Error('EMOJI_MANAGED'));
+ } else {
+ if (!this.guild.me) return Promise.reject(new Error('GUILD_UNCACHED_ME'));
+ if (!this.guild.me.permissions.has(Permissions.FLAGS.MANAGE_EMOJIS)) {
+ return Promise.reject(new Error('MISSING_MANAGE_EMOJIS_PERMISSION', this.guild));
+ }
+ }
+ return this.client.api
+ .guilds(this.guild.id)
+ .emojis(this.id)
+ .get()
+ .then(emoji => this.client.users.add(emoji.user));
+ }
+
+ /**
+ * Data for editing an emoji.
+ * @typedef {Object} GuildEmojiEditData
+ * @property {string} [name] The name of the emoji
+ * @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] Roles to restrict emoji to
+ */
+
+ /**
+ * Edits the emoji.
+ * @param {GuildEmojiEditData} data The new data for the emoji
+ * @param {string} [reason] Reason for editing this emoji
+ * @returns {Promise<GuildEmoji>}
+ * @example
+ * // Edit an emoji
+ * emoji.edit({ name: 'newemoji' })
+ * .then(e => console.log(`Edited emoji ${e}`))
+ * .catch(console.error);
+ */
+ edit(data, reason) {
+ const roles = data.roles ? data.roles.map(r => r.id || r) : undefined;
+ return this.client.api
+ .guilds(this.guild.id)
+ .emojis(this.id)
+ .patch({
+ data: {
+ name: data.name,
+ roles,
+ },
+ reason,
+ })
+ .then(newData => {
+ const clone = this._clone();
+ clone._patch(newData);
+ return clone;
+ });
+ }
+
+ /**
+ * Sets the name of the emoji.
+ * @param {string} name The new name for the emoji
+ * @param {string} [reason] Reason for changing the emoji's name
+ * @returns {Promise<GuildEmoji>}
+ */
+ setName(name, reason) {
+ return this.edit({ name }, reason);
+ }
+
+ /**
+ * Deletes the emoji.
+ * @param {string} [reason] Reason for deleting the emoji
+ * @returns {Promise<GuildEmoji>}
+ */
+ delete(reason) {
+ return this.client.api
+ .guilds(this.guild.id)
+ .emojis(this.id)
+ .delete({ reason })
+ .then(() => this);
+ }
+
+ /**
+ * Whether this emoji is the same as another one.
+ * @param {GuildEmoji|Object} other The emoji to compare it to
+ * @returns {boolean} Whether the emoji is equal to the given emoji or not
+ */
+ equals(other) {
+ if (other instanceof GuildEmoji) {
+ return (
+ other.id === this.id &&
+ other.name === this.name &&
+ other.managed === this.managed &&
+ other.requiresColons === this.requiresColons &&
+ other.roles.cache.size === this.roles.cache.size &&
+ other.roles.cache.every(role => this.roles.cache.has(role.id))
+ );
+ } else {
+ return (
+ other.id === this.id &&
+ other.name === this.name &&
+ other.roles.length === this.roles.cache.size &&
+ other.roles.every(role => this.roles.cache.has(role))
+ );
+ }
+ }
+}
+
+module.exports = GuildEmoji;
diff --git a/node_modules/discord.js/src/structures/GuildMember.js b/node_modules/discord.js/src/structures/GuildMember.js
new file mode 100644
index 0000000..f949517
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildMember.js
@@ -0,0 +1,410 @@
+'use strict';
+
+const Base = require('./Base');
+const { Presence } = require('./Presence');
+const Role = require('./Role');
+const VoiceState = require('./VoiceState');
+const TextBasedChannel = require('./interfaces/TextBasedChannel');
+const { Error } = require('../errors');
+const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
+const Permissions = require('../util/Permissions');
+
+/**
+ * Represents a member of a guild on Discord.
+ * @implements {TextBasedChannel}
+ * @extends {Base}
+ */
+class GuildMember extends Base {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the guild member
+ * @param {Guild} guild The guild the member is part of
+ */
+ constructor(client, data, guild) {
+ super(client);
+
+ /**
+ * The guild that this member is part of
+ * @type {Guild}
+ */
+ this.guild = guild;
+
+ /**
+ * The user that this guild member instance represents
+ * @type {User}
+ * @name GuildMember#user
+ */
+ if (data.user) this.user = client.users.add(data.user, true);
+
+ /**
+ * The timestamp the member joined the guild at
+ * @type {?number}
+ */
+ this.joinedTimestamp = null;
+
+ /**
+ * The ID of the last message sent by the member in their guild, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageID = null;
+
+ /**
+ * The ID of the channel for the last message sent by the member in their guild, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageChannelID = null;
+
+ /**
+ * The timestamp of when the member used their Nitro boost on the guild, if it was used
+ * @type {?number}
+ */
+ this.premiumSinceTimestamp = null;
+
+ /**
+ * Whether the member has been removed from the guild
+ * @type {boolean}
+ */
+ this.deleted = false;
+
+ this._roles = [];
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The nickname of this member, if they have one
+ * @type {?string}
+ * @name GuildMember#nickname
+ */
+ if (typeof data.nick !== 'undefined') this.nickname = data.nick;
+
+ if (data.joined_at) this.joinedTimestamp = new Date(data.joined_at).getTime();
+ if (data.premium_since) this.premiumSinceTimestamp = new Date(data.premium_since).getTime();
+
+ if (data.user) this.user = this.guild.client.users.add(data.user);
+ if (data.roles) this._roles = data.roles;
+ }
+
+ _clone() {
+ const clone = super._clone();
+ clone._roles = this._roles.slice();
+ return clone;
+ }
+
+ /**
+ * Whether this GuildMember is a partial
+ * @type {boolean}
+ * @readonly
+ */
+ get partial() {
+ return !this.joinedTimestamp;
+ }
+
+ /**
+ * A manager for the roles belonging to this member
+ * @type {GuildMemberRoleManager}
+ * @readonly
+ */
+ get roles() {
+ return new GuildMemberRoleManager(this);
+ }
+
+ /**
+ * The Message object of the last message sent by the member in their guild, if one was sent
+ * @type {?Message}
+ * @readonly
+ */
+ get lastMessage() {
+ const channel = this.guild.channels.cache.get(this.lastMessageChannelID);
+ return (channel && channel.messages.cache.get(this.lastMessageID)) || null;
+ }
+
+ /**
+ * The voice state of this member
+ * @type {VoiceState}
+ * @readonly
+ */
+ get voice() {
+ return this.guild.voiceStates.cache.get(this.id) || new VoiceState(this.guild, { user_id: this.id });
+ }
+
+ /**
+ * The time this member joined the guild
+ * @type {?Date}
+ * @readonly
+ */
+ get joinedAt() {
+ return this.joinedTimestamp ? new Date(this.joinedTimestamp) : null;
+ }
+
+ /**
+ * The time of when the member used their Nitro boost on the guild, if it was used
+ * @type {?Date}
+ * @readonly
+ */
+ get premiumSince() {
+ return this.premiumSinceTimestamp ? new Date(this.premiumSinceTimestamp) : null;
+ }
+
+ /**
+ * The presence of this guild member
+ * @type {Presence}
+ * @readonly
+ */
+ get presence() {
+ return (
+ this.guild.presences.cache.get(this.id) ||
+ new Presence(this.client, {
+ user: {
+ id: this.id,
+ },
+ guild: this.guild,
+ })
+ );
+ }
+
+ /**
+ * The displayed color of this member in base 10
+ * @type {number}
+ * @readonly
+ */
+ get displayColor() {
+ const role = this.roles.color;
+ return (role && role.color) || 0;
+ }
+
+ /**
+ * The displayed color of this member in hexadecimal
+ * @type {string}
+ * @readonly
+ */
+ get displayHexColor() {
+ const role = this.roles.color;
+ return (role && role.hexColor) || '#000000';
+ }
+
+ /**
+ * The ID of this member
+ * @type {Snowflake}
+ * @readonly
+ */
+ get id() {
+ return this.user.id;
+ }
+
+ /**
+ * The nickname of this member, or their username if they don't have one
+ * @type {string}
+ * @readonly
+ */
+ get displayName() {
+ return this.nickname || this.user.username;
+ }
+
+ /**
+ * The overall set of permissions for this member, taking only roles into account
+ * @type {Readonly<Permissions>}
+ * @readonly
+ */
+ get permissions() {
+ if (this.user.id === this.guild.ownerID) return new Permissions(Permissions.ALL).freeze();
+ return new Permissions(this.roles.cache.map(role => role.permissions)).freeze();
+ }
+
+ /**
+ * Whether the client user is above this user in the hierarchy, according to role position and guild ownership.
+ * This is a prerequisite for many moderative actions.
+ * @type {boolean}
+ * @readonly
+ */
+ get manageable() {
+ if (this.user.id === this.guild.ownerID) return false;
+ if (this.user.id === this.client.user.id) return false;
+ if (this.client.user.id === this.guild.ownerID) return true;
+ if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME');
+ return this.guild.me.roles.highest.comparePositionTo(this.roles.highest) > 0;
+ }
+
+ /**
+ * Whether this member is kickable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get kickable() {
+ return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.KICK_MEMBERS);
+ }
+
+ /**
+ * Whether this member is bannable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get bannable() {
+ return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.BAN_MEMBERS);
+ }
+
+ /**
+ * Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel,
+ * taking into account roles and permission overwrites.
+ * @param {ChannelResolvable} channel The guild channel to use as context
+ * @returns {Readonly<Permissions>}
+ */
+ permissionsIn(channel) {
+ channel = this.guild.channels.resolve(channel);
+ if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE');
+ return channel.memberPermissions(this);
+ }
+
+ /**
+ * Checks if any of this member's roles have a permission.
+ * @param {PermissionResolvable} permission Permission(s) to check for
+ * @param {Object} [options] Options
+ * @param {boolean} [options.checkAdmin=true] Whether to allow the administrator permission to override
+ * @param {boolean} [options.checkOwner=true] Whether to allow being the guild's owner to override
+ * @returns {boolean}
+ */
+ hasPermission(permission, { checkAdmin = true, checkOwner = true } = {}) {
+ if (checkOwner && this.user.id === this.guild.ownerID) return true;
+ return this.roles.cache.some(r => r.permissions.has(permission, checkAdmin));
+ }
+
+ /**
+ * The data for editing a guild member.
+ * @typedef {Object} GuildMemberEditData
+ * @property {string} [nick] The nickname to set for the member
+ * @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] The roles or role IDs to apply
+ * @property {boolean} [mute] Whether or not the member should be muted
+ * @property {boolean} [deaf] Whether or not the member should be deafened
+ * @property {ChannelResolvable|null} [channel] Channel to move member to (if they are connected to voice), or `null`
+ * if you want to kick them from voice
+ */
+
+ /**
+ * Edits this member.
+ * @param {GuildMemberEditData} data The data to edit the member with
+ * @param {string} [reason] Reason for editing this user
+ * @returns {Promise<GuildMember>}
+ */
+ async edit(data, reason) {
+ if (data.channel) {
+ data.channel = this.guild.channels.resolve(data.channel);
+ if (!data.channel || data.channel.type !== 'voice') {
+ throw new Error('GUILD_VOICE_CHANNEL_RESOLVE');
+ }
+ data.channel_id = data.channel.id;
+ data.channel = undefined;
+ } else if (data.channel === null) {
+ data.channel_id = null;
+ data.channel = undefined;
+ }
+ if (data.roles) data.roles = data.roles.map(role => (role instanceof Role ? role.id : role));
+ let endpoint = this.client.api.guilds(this.guild.id);
+ if (this.user.id === this.client.user.id) {
+ const keys = Object.keys(data);
+ if (keys.length === 1 && keys[0] === 'nick') endpoint = endpoint.members('@me').nick;
+ else endpoint = endpoint.members(this.id);
+ } else {
+ endpoint = endpoint.members(this.id);
+ }
+ await endpoint.patch({ data, reason });
+
+ const clone = this._clone();
+ data.user = this.user;
+ clone._patch(data);
+ return clone;
+ }
+
+ /**
+ * Sets the nickname for this member.
+ * @param {string} nick The nickname for the guild member
+ * @param {string} [reason] Reason for setting the nickname
+ * @returns {Promise<GuildMember>}
+ */
+ setNickname(nick, reason) {
+ return this.edit({ nick }, reason);
+ }
+
+ /**
+ * Creates a DM channel between the client and this member.
+ * @returns {Promise<DMChannel>}
+ */
+ createDM() {
+ return this.user.createDM();
+ }
+
+ /**
+ * Deletes any DMs with this member.
+ * @returns {Promise<DMChannel>}
+ */
+ deleteDM() {
+ return this.user.deleteDM();
+ }
+
+ /**
+ * Kicks this member from the guild.
+ * @param {string} [reason] Reason for kicking user
+ * @returns {Promise<GuildMember>}
+ */
+ kick(reason) {
+ return this.client.api
+ .guilds(this.guild.id)
+ .members(this.user.id)
+ .delete({ reason })
+ .then(() => this);
+ }
+
+ /**
+ * Bans this guild member.
+ * @param {Object} [options] Options for the ban
+ * @param {number} [options.days=0] Number of days of messages to delete
+ * @param {string} [options.reason] Reason for banning
+ * @returns {Promise<GuildMember>}
+ * @example
+ * // ban a guild member
+ * guildMember.ban({ days: 7, reason: 'They deserved it' })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ ban(options) {
+ return this.guild.members.ban(this, options);
+ }
+
+ /**
+ * Fetches this GuildMember.
+ * @returns {Promise<GuildMember>}
+ */
+ fetch() {
+ return this.guild.members.fetch(this.id, true);
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from <@123456789012345678>!
+ * console.log(`Hello from ${member}!`);
+ */
+ toString() {
+ return `<@${this.nickname ? '!' : ''}${this.user.id}>`;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ guild: 'guildID',
+ user: 'userID',
+ displayName: true,
+ speaking: false,
+ lastMessage: false,
+ lastMessageID: false,
+ roles: true,
+ });
+ }
+
+ // These are here only for documentation purposes - they are implemented by TextBasedChannel
+ /* eslint-disable no-empty-function */
+ send() {}
+}
+
+TextBasedChannel.applyToClass(GuildMember);
+
+module.exports = GuildMember;
diff --git a/node_modules/discord.js/src/structures/GuildPreview.js b/node_modules/discord.js/src/structures/GuildPreview.js
new file mode 100644
index 0000000..681ff60
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildPreview.js
@@ -0,0 +1,157 @@
+'use strict';
+
+const Base = require('./Base');
+const GuildPreviewEmoji = require('./GuildPreviewEmoji');
+const Collection = require('../util/Collection');
+
+/**
+ * Represents the data about the guild any bot can preview, connected to the specified public guild.
+ * @extends {Base}
+ */
+class GuildPreview extends Base {
+ constructor(client, data) {
+ super(client);
+
+ if (!data) return;
+
+ this._patch(data);
+ }
+
+ /**
+ * Builds the public guild with the provided data.
+ * @param {*} data The raw data of the public guild
+ * @private
+ */
+ _patch(data) {
+ /**
+ * The id of this public guild
+ * @type {string}
+ */
+ this.id = data.id;
+
+ /**
+ * The name of this public guild
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The icon of this public guild
+ * @type {?string}
+ */
+ this.icon = data.icon;
+
+ /**
+ * The splash icon of this public guild
+ * @type {?string}
+ */
+ this.splash = data.splash;
+
+ /**
+ * The discovery splash icon of this public guild
+ * @type {?string}
+ */
+ this.discoverySplash = data.discovery_splash;
+
+ /**
+ * An array of enabled guild features
+ * @type {Features[]}
+ */
+ this.features = data.features;
+
+ /**
+ * The approximate count of members in this public guild
+ * @type {number}
+ */
+ this.approximateMemberCount = data.approximate_member_count;
+
+ /**
+ * The approximate count of online members in this public guild
+ * @type {number}
+ */
+ this.approximatePresenceCount = data.approximate_presence_count;
+
+ /**
+ * The description for this public guild
+ * @type {?string}
+ */
+ this.description = data.description;
+
+ if (!this.emojis) {
+ /**
+ * Collection of emojis belonging to this public guild
+ * @type {Collection<Snowflake, GuildPreviewEmoji>}
+ */
+ this.emojis = new Collection();
+ } else {
+ this.emojis.clear();
+ }
+ for (const emoji of data.emojis) {
+ this.emojis.set(emoji.id, new GuildPreviewEmoji(this.client, emoji, this));
+ }
+ }
+
+ /**
+ * The URL to this public guild's splash.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ splashURL({ format, size } = {}) {
+ if (!this.splash) return null;
+ return this.client.rest.cdn.Splash(this.id, this.splash, format, size);
+ }
+
+ /**
+ * The URL to this public guild's discovery splash.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ discoverySplashURL({ format, size } = {}) {
+ if (!this.discoverySplash) return null;
+ return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size);
+ }
+
+ /**
+ * The URL to this public guild's icon.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ iconURL({ format, size, dynamic } = {}) {
+ if (!this.icon) return null;
+ return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic);
+ }
+
+ /**
+ * Fetches this public guild.
+ * @returns {Promise<GuildPreview>}
+ */
+ fetch() {
+ return this.client.api
+ .guilds(this.id)
+ .preview.get()
+ .then(data => {
+ this._patch(data);
+ return this;
+ });
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the guild's name instead of the Guild object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from My Guild!
+ * console.log(`Hello from ${previewGuild}!`);
+ */
+ toString() {
+ return this.name;
+ }
+
+ toJSON() {
+ const json = super.toJSON();
+ json.iconURL = this.iconURL();
+ json.splashURL = this.splashURL();
+ return json;
+ }
+}
+
+module.exports = GuildPreview;
diff --git a/node_modules/discord.js/src/structures/GuildPreviewEmoji.js b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js
new file mode 100644
index 0000000..4c70903
--- /dev/null
+++ b/node_modules/discord.js/src/structures/GuildPreviewEmoji.js
@@ -0,0 +1,26 @@
+'use strict';
+
+const BaseGuildEmoji = require('./BaseGuildEmoji');
+
+/**
+ * Represents an instance of an emoji belonging to a public guild obtained through Discord's preview endpoint.
+ * @extends {BaseGuildEmoji}
+ */
+class GuildPreviewEmoji extends BaseGuildEmoji {
+ /**
+ * The public guild this emoji is part of
+ * @type {GuildPreview}
+ * @name GuildPreviewEmoji#guild
+ */
+
+ /**
+ * Set of roles this emoji is active for
+ * @type {Set<Snowflake>}
+ * @readonly
+ */
+ get roles() {
+ return new Set(this._roles);
+ }
+}
+
+module.exports = GuildPreviewEmoji;
diff --git a/node_modules/discord.js/src/structures/Integration.js b/node_modules/discord.js/src/structures/Integration.js
new file mode 100644
index 0000000..49a0227
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Integration.js
@@ -0,0 +1,167 @@
+'use strict';
+
+const Base = require('./Base');
+
+/**
+ * The information account for an integration
+ * @typedef {Object} IntegrationAccount
+ * @property {string} id The id of the account
+ * @property {string} name The name of the account
+ */
+
+/**
+ * Represents a guild integration.
+ */
+class Integration extends Base {
+ constructor(client, data, guild) {
+ super(client);
+
+ /**
+ * The guild this integration belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+
+ /**
+ * The integration id
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The integration name
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The integration type (twitch, youtube, etc)
+ * @type {string}
+ */
+ this.type = data.type;
+
+ /**
+ * Whether this integration is enabled
+ * @type {boolean}
+ */
+ this.enabled = data.enabled;
+
+ /**
+ * Whether this integration is syncing
+ * @type {boolean}
+ */
+ this.syncing = data.syncing;
+
+ /**
+ * The role that this integration uses for subscribers
+ * @type {Role}
+ */
+ this.role = this.guild.roles.cache.get(data.role_id);
+
+ /**
+ * The user for this integration
+ * @type {User}
+ */
+ this.user = this.client.users.add(data.user);
+
+ /**
+ * The account integration information
+ * @type {IntegrationAccount}
+ */
+ this.account = data.account;
+
+ /**
+ * The last time this integration was last synced
+ * @type {number}
+ */
+ this.syncedAt = data.synced_at;
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The behavior of expiring subscribers
+ * @type {number}
+ */
+ this.expireBehavior = data.expire_behavior;
+
+ /**
+ * The grace period before expiring subscribers
+ * @type {number}
+ */
+ this.expireGracePeriod = data.expire_grace_period;
+ }
+
+ /**
+ * Sync this integration
+ * @returns {Promise<Integration>}
+ */
+ sync() {
+ this.syncing = true;
+ return this.client.api
+ .guilds(this.guild.id)
+ .integrations(this.id)
+ .post()
+ .then(() => {
+ this.syncing = false;
+ this.syncedAt = Date.now();
+ return this;
+ });
+ }
+
+ /**
+ * The data for editing an integration.
+ * @typedef {Object} IntegrationEditData
+ * @property {number} [expireBehavior] The new behaviour of expiring subscribers
+ * @property {number} [expireGracePeriod] The new grace period before expiring subscribers
+ */
+
+ /**
+ * Edits this integration.
+ * @param {IntegrationEditData} data The data to edit this integration with
+ * @param {string} reason Reason for editing this integration
+ * @returns {Promise<Integration>}
+ */
+ edit(data, reason) {
+ if ('expireBehavior' in data) {
+ data.expire_behavior = data.expireBehavior;
+ data.expireBehavior = null;
+ }
+ if ('expireGracePeriod' in data) {
+ data.expire_grace_period = data.expireGracePeriod;
+ data.expireGracePeriod = null;
+ }
+ // The option enable_emoticons is only available for Twitch at this moment
+ return this.client.api
+ .guilds(this.guild.id)
+ .integrations(this.id)
+ .patch({ data, reason })
+ .then(() => {
+ this._patch(data);
+ return this;
+ });
+ }
+
+ /**
+ * Deletes this integration.
+ * @returns {Promise<Integration>}
+ * @param {string} [reason] Reason for deleting this integration
+ */
+ delete(reason) {
+ return this.client.api
+ .guilds(this.guild.id)
+ .integrations(this.id)
+ .delete({ reason })
+ .then(() => this);
+ }
+
+ toJSON() {
+ return super.toJSON({
+ role: 'roleID',
+ guild: 'guildID',
+ user: 'userID',
+ });
+ }
+}
+
+module.exports = Integration;
diff --git a/node_modules/discord.js/src/structures/Invite.js b/node_modules/discord.js/src/structures/Invite.js
new file mode 100644
index 0000000..6833266
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Invite.js
@@ -0,0 +1,194 @@
+'use strict';
+
+const Base = require('./Base');
+const { Endpoints } = require('../util/Constants');
+const Permissions = require('../util/Permissions');
+
+/**
+ * Represents an invitation to a guild channel.
+ * <warn>The only guaranteed properties are `code`, `channel`, and `url`. Other properties can be missing.</warn>
+ * @extends {Base}
+ */
+class Invite extends Base {
+ constructor(client, data) {
+ super(client);
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The guild the invite is for
+ * @type {?Guild}
+ */
+ this.guild = data.guild ? this.client.guilds.add(data.guild, false) : null;
+
+ /**
+ * The code for this invite
+ * @type {string}
+ */
+ this.code = data.code;
+
+ /**
+ * The approximate number of online members of the guild this invite is for
+ * @type {?number}
+ */
+ this.presenceCount = 'approximate_presence_count' in data ? data.approximate_presence_count : null;
+
+ /**
+ * The approximate total number of members of the guild this invite is for
+ * @type {?number}
+ */
+ this.memberCount = 'approximate_member_count' in data ? data.approximate_member_count : null;
+
+ /**
+ * Whether or not this invite is temporary
+ * @type {?boolean}
+ */
+ this.temporary = 'temporary' in data ? data.temporary : null;
+
+ /**
+ * The maximum age of the invite, in seconds, 0 if never expires
+ * @type {?number}
+ */
+ this.maxAge = 'max_age' in data ? data.max_age : null;
+
+ /**
+ * How many times this invite has been used
+ * @type {?number}
+ */
+ this.uses = 'uses' in data ? data.uses : null;
+
+ /**
+ * The maximum uses of this invite
+ * @type {?number}
+ */
+ this.maxUses = 'max_uses' in data ? data.max_uses : null;
+
+ /**
+ * The user who created this invite
+ * @type {?User}
+ */
+ this.inviter = data.inviter ? this.client.users.add(data.inviter) : null;
+
+ /**
+ * The target user for this invite
+ * @type {?User}
+ */
+ this.targetUser = data.target_user ? this.client.users.add(data.target_user) : null;
+
+ /**
+ * The type of the target user:
+ * * 1: STREAM
+ * @typedef {number} TargetUser
+ */
+
+ /**
+ * The target user type
+ * @type {?TargetUser}
+ */
+ this.targetUserType = typeof data.target_user_type === 'number' ? data.target_user_type : null;
+
+ /**
+ * The channel the invite is for
+ * @type {Channel}
+ */
+ this.channel = this.client.channels.add(data.channel, this.guild, false);
+
+ /**
+ * The timestamp the invite was created at
+ * @type {?number}
+ */
+ this.createdTimestamp = 'created_at' in data ? new Date(data.created_at).getTime() : null;
+ }
+
+ /**
+ * The time the invite was created at
+ * @type {?Date}
+ * @readonly
+ */
+ get createdAt() {
+ return this.createdTimestamp ? new Date(this.createdTimestamp) : null;
+ }
+
+ /**
+ * Whether the invite is deletable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get deletable() {
+ const guild = this.guild;
+ if (!guild || !this.client.guilds.cache.has(guild.id)) return false;
+ if (!guild.me) throw new Error('GUILD_UNCACHED_ME');
+ return (
+ this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) ||
+ guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD)
+ );
+ }
+
+ /**
+ * The timestamp the invite will expire at
+ * @type {?number}
+ * @readonly
+ */
+ get expiresTimestamp() {
+ return this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1000 : null;
+ }
+
+ /**
+ * The time the invite will expire at
+ * @type {?Date}
+ * @readonly
+ */
+ get expiresAt() {
+ const { expiresTimestamp } = this;
+ return expiresTimestamp ? new Date(expiresTimestamp) : null;
+ }
+
+ /**
+ * The URL to the invite
+ * @type {string}
+ * @readonly
+ */
+ get url() {
+ return Endpoints.invite(this.client.options.http.invite, this.code);
+ }
+
+ /**
+ * Deletes this invite.
+ * @param {string} [reason] Reason for deleting this invite
+ * @returns {Promise<Invite>}
+ */
+ delete(reason) {
+ return this.client.api.invites[this.code].delete({ reason }).then(() => this);
+ }
+
+ /**
+ * When concatenated with a string, this automatically concatenates the invite's URL instead of the object.
+ * @returns {string}
+ * @example
+ * // Logs: Invite: https://discord.gg/A1b2C3
+ * console.log(`Invite: ${invite}`);
+ */
+ toString() {
+ return this.url;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ url: true,
+ expiresTimestamp: true,
+ presenceCount: false,
+ memberCount: false,
+ uses: false,
+ channel: 'channelID',
+ inviter: 'inviterID',
+ guild: 'guildID',
+ });
+ }
+
+ valueOf() {
+ return this.code;
+ }
+}
+
+module.exports = Invite;
diff --git a/node_modules/discord.js/src/structures/Message.js b/node_modules/discord.js/src/structures/Message.js
new file mode 100644
index 0000000..06ed12a
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Message.js
@@ -0,0 +1,623 @@
+'use strict';
+
+const APIMessage = require('./APIMessage');
+const Base = require('./Base');
+const ClientApplication = require('./ClientApplication');
+const MessageAttachment = require('./MessageAttachment');
+const Embed = require('./MessageEmbed');
+const Mentions = require('./MessageMentions');
+const ReactionCollector = require('./ReactionCollector');
+const { Error, TypeError } = require('../errors');
+const ReactionManager = require('../managers/ReactionManager');
+const Collection = require('../util/Collection');
+const { MessageTypes } = require('../util/Constants');
+const MessageFlags = require('../util/MessageFlags');
+const Permissions = require('../util/Permissions');
+const Util = require('../util/Util');
+
+/**
+ * Represents a message on Discord.
+ * @extends {Base}
+ */
+class Message extends Base {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the message
+ * @param {TextChannel|DMChannel} channel The channel the message was sent in
+ */
+ constructor(client, data, channel) {
+ super(client);
+
+ /**
+ * The channel that the message was sent in
+ * @type {TextChannel|DMChannel}
+ */
+ this.channel = channel;
+
+ /**
+ * Whether this message has been deleted
+ * @type {boolean}
+ */
+ this.deleted = false;
+
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The ID of the message
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The type of the message
+ * @type {MessageType}
+ */
+ this.type = MessageTypes[data.type];
+
+ /**
+ * The content of the message
+ * @type {string}
+ */
+ this.content = data.content;
+
+ /**
+ * The author of the message
+ * @type {?User}
+ */
+ this.author = data.author ? this.client.users.add(data.author, !data.webhook_id) : null;
+
+ /**
+ * Whether or not this message is pinned
+ * @type {boolean}
+ */
+ this.pinned = data.pinned;
+
+ /**
+ * Whether or not the message was Text-To-Speech
+ * @type {boolean}
+ */
+ this.tts = data.tts;
+
+ /**
+ * A random number or string used for checking message delivery
+ * <warn>This is only received after the message was sent successfully, and
+ * lost if re-fetched</warn>
+ * @type {?string}
+ */
+ this.nonce = data.nonce;
+
+ /**
+ * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
+ * @type {boolean}
+ */
+ this.system = data.type !== 0;
+
+ /**
+ * A list of embeds in the message - e.g. YouTube Player
+ * @type {MessageEmbed[]}
+ */
+ this.embeds = (data.embeds || []).map(e => new Embed(e, true));
+
+ /**
+ * A collection of attachments in the message - e.g. Pictures - mapped by their ID
+ * @type {Collection<Snowflake, MessageAttachment>}
+ */
+ this.attachments = new Collection();
+ if (data.attachments) {
+ for (const attachment of data.attachments) {
+ this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment));
+ }
+ }
+
+ /**
+ * The timestamp the message was sent at
+ * @type {number}
+ */
+ this.createdTimestamp = new Date(data.timestamp).getTime();
+
+ /**
+ * The timestamp the message was last edited at (if applicable)
+ * @type {?number}
+ */
+ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
+
+ /**
+ * A manager of the reactions belonging to this message
+ * @type {ReactionManager}
+ */
+ this.reactions = new ReactionManager(this);
+ if (data.reactions && data.reactions.length > 0) {
+ for (const reaction of data.reactions) {
+ this.reactions.add(reaction);
+ }
+ }
+
+ /**
+ * All valid mentions that the message contains
+ * @type {MessageMentions}
+ */
+ this.mentions = new Mentions(this, data.mentions, data.mention_roles, data.mention_everyone, data.mention_channels);
+
+ /**
+ * ID of the webhook that sent the message, if applicable
+ * @type {?Snowflake}
+ */
+ this.webhookID = data.webhook_id || null;
+
+ /**
+ * Supplemental application information for group activities
+ * @type {?ClientApplication}
+ */
+ this.application = data.application ? new ClientApplication(this.client, data.application) : null;
+
+ /**
+ * Group activity
+ * @type {?MessageActivity}
+ */
+ this.activity = data.activity
+ ? {
+ partyID: data.activity.party_id,
+ type: data.activity.type,
+ }
+ : null;
+
+ /**
+ * The previous versions of the message, sorted with the most recent first
+ * @type {Message[]}
+ * @private
+ */
+ this._edits = [];
+
+ if (this.member && data.member) {
+ this.member._patch(data.member);
+ } else if (data.member && this.guild && this.author) {
+ this.guild.members.add(Object.assign(data.member, { user: this.author }));
+ }
+
+ /**
+ * Flags that are applied to the message
+ * @type {Readonly<MessageFlags>}
+ */
+ this.flags = new MessageFlags(data.flags).freeze();
+
+ /**
+ * Reference data sent in a crossposted message.
+ * @typedef {Object} MessageReference
+ * @property {string} channelID ID of the channel the message was crossposted from
+ * @property {?string} guildID ID of the guild the message was crossposted from
+ * @property {?string} messageID ID of the message that was crossposted
+ */
+
+ /**
+ * Message reference data
+ * @type {?MessageReference}
+ */
+ this.reference = data.message_reference
+ ? {
+ channelID: data.message_reference.channel_id,
+ guildID: data.message_reference.guild_id,
+ messageID: data.message_reference.message_id,
+ }
+ : null;
+ }
+
+ /**
+ * Whether or not this message is a partial
+ * @type {boolean}
+ * @readonly
+ */
+ get partial() {
+ return typeof this.content !== 'string' || !this.author;
+ }
+
+ /**
+ * Updates the message.
+ * @param {Object} data Raw Discord message update data
+ * @private
+ */
+ patch(data) {
+ const clone = this._clone();
+ this._edits.unshift(clone);
+
+ if ('edited_timestamp' in data) this.editedTimestamp = new Date(data.edited_timestamp).getTime();
+ if ('content' in data) this.content = data.content;
+ if ('pinned' in data) this.pinned = data.pinned;
+ if ('tts' in data) this.tts = data.tts;
+ if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e, true));
+ else this.embeds = this.embeds.slice();
+
+ if ('attachments' in data) {
+ this.attachments = new Collection();
+ for (const attachment of data.attachments) {
+ this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment));
+ }
+ } else {
+ this.attachments = new Collection(this.attachments);
+ }
+
+ this.mentions = new Mentions(
+ this,
+ 'mentions' in data ? data.mentions : this.mentions.users,
+ 'mention_roles' in data ? data.mention_roles : this.mentions.roles,
+ 'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone,
+ 'mention_channels' in data ? data.mention_channels : this.mentions.crosspostedChannels,
+ );
+
+ this.flags = new MessageFlags('flags' in data ? data.flags : 0).freeze();
+ }
+
+ /**
+ * Represents the author of the message as a guild member.
+ * Only available if the message comes from a guild where the author is still a member
+ * @type {?GuildMember}
+ * @readonly
+ */
+ get member() {
+ return this.guild ? this.guild.member(this.author) || null : null;
+ }
+
+ /**
+ * The time the message was sent at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * The time the message was last edited at (if applicable)
+ * @type {?Date}
+ * @readonly
+ */
+ get editedAt() {
+ return this.editedTimestamp ? new Date(this.editedTimestamp) : null;
+ }
+
+ /**
+ * The guild the message was sent in (if in a guild channel)
+ * @type {?Guild}
+ * @readonly
+ */
+ get guild() {
+ return this.channel.guild || null;
+ }
+
+ /**
+ * The url to jump to this message
+ * @type {string}
+ * @readonly
+ */
+ get url() {
+ return `https://discordapp.com/channels/${this.guild ? this.guild.id : '@me'}/${this.channel.id}/${this.id}`;
+ }
+
+ /**
+ * The message contents with all mentions replaced by the equivalent text.
+ * If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted.
+ * @type {string}
+ * @readonly
+ */
+ get cleanContent() {
+ // eslint-disable-next-line eqeqeq
+ return this.content != null ? Util.cleanContent(this.content, this) : null;
+ }
+
+ /**
+ * Creates a reaction collector.
+ * @param {CollectorFilter} filter The filter to apply
+ * @param {ReactionCollectorOptions} [options={}] Options to send to the collector
+ * @returns {ReactionCollector}
+ * @example
+ * // Create a reaction collector
+ * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID';
+ * const collector = message.createReactionCollector(filter, { time: 15000 });
+ * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`));
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
+ */
+ createReactionCollector(filter, options = {}) {
+ return new ReactionCollector(this, filter, options);
+ }
+
+ /**
+ * An object containing the same properties as CollectorOptions, but a few more:
+ * @typedef {ReactionCollectorOptions} AwaitReactionsOptions
+ * @property {string[]} [errors] Stop/end reasons that cause the promise to reject
+ */
+
+ /**
+ * Similar to createReactionCollector but in promise form.
+ * Resolves with a collection of reactions that pass the specified filter.
+ * @param {CollectorFilter} filter The filter function to use
+ * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
+ * @returns {Promise<Collection<string, MessageReaction>>}
+ * @example
+ * // Create a reaction collector
+ * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID'
+ * message.awaitReactions(filter, { time: 15000 })
+ * .then(collected => console.log(`Collected ${collected.size} reactions`))
+ * .catch(console.error);
+ */
+ awaitReactions(filter, options = {}) {
+ return new Promise((resolve, reject) => {
+ const collector = this.createReactionCollector(filter, options);
+ collector.once('end', (reactions, reason) => {
+ if (options.errors && options.errors.includes(reason)) reject(reactions);
+ else resolve(reactions);
+ });
+ });
+ }
+
+ /**
+ * An array of cached versions of the message, including the current version
+ * Sorted from latest (first) to oldest (last)
+ * @type {Message[]}
+ * @readonly
+ */
+ get edits() {
+ const copy = this._edits.slice();
+ copy.unshift(this);
+ return copy;
+ }
+
+ /**
+ * Whether the message is editable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get editable() {
+ return this.author.id === this.client.user.id;
+ }
+
+ /**
+ * Whether the message is deletable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get deletable() {
+ return (
+ !this.deleted &&
+ (this.author.id === this.client.user.id ||
+ (this.guild && this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false)))
+ );
+ }
+
+ /**
+ * Whether the message is pinnable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get pinnable() {
+ return (
+ this.type === 'DEFAULT' &&
+ (!this.guild || this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false))
+ );
+ }
+
+ /**
+ * Options that can be passed into editMessage.
+ * @typedef {Object} MessageEditOptions
+ * @property {string} [content] Content to be edited
+ * @property {Object} [embed] An embed to be added/edited
+ * @property {string|boolean} [code] Language for optional codeblock formatting to apply
+ * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
+ */
+
+ /**
+ * Edits the content of the message.
+ * @param {StringResolvable|APIMessage} [content] The new content for the message
+ * @param {MessageEditOptions|MessageEmbed} [options] The options to provide
+ * @returns {Promise<Message>}
+ * @example
+ * // Update the content of a message
+ * message.edit('This is my new content!')
+ * .then(msg => console.log(`Updated the content of a message to ${msg.content}`))
+ * .catch(console.error);
+ */
+ edit(content, options) {
+ const { data } =
+ content instanceof APIMessage ? content.resolveData() : APIMessage.create(this, content, options).resolveData();
+ return this.client.api.channels[this.channel.id].messages[this.id].patch({ data }).then(d => {
+ const clone = this._clone();
+ clone._patch(d);
+ return clone;
+ });
+ }
+
+ /**
+ * Pins this message to the channel's pinned messages.
+ * @returns {Promise<Message>}
+ */
+ pin() {
+ return this.client.api
+ .channels(this.channel.id)
+ .pins(this.id)
+ .put()
+ .then(() => this);
+ }
+
+ /**
+ * Unpins this message from the channel's pinned messages.
+ * @returns {Promise<Message>}
+ */
+ unpin() {
+ return this.client.api
+ .channels(this.channel.id)
+ .pins(this.id)
+ .delete()
+ .then(() => this);
+ }
+
+ /**
+ * Adds a reaction to the message.
+ * @param {EmojiIdentifierResolvable} emoji The emoji to react with
+ * @returns {Promise<MessageReaction>}
+ * @example
+ * // React to a message with a unicode emoji
+ * message.react('🤔')
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // React to a message with a custom emoji
+ * message.react(message.guild.emojis.cache.get('123456789012345678'))
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ react(emoji) {
+ emoji = this.client.emojis.resolveIdentifier(emoji);
+ if (!emoji) throw new TypeError('EMOJI_TYPE');
+
+ return this.client.api
+ .channels(this.channel.id)
+ .messages(this.id)
+ .reactions(emoji, '@me')
+ .put()
+ .then(
+ () =>
+ this.client.actions.MessageReactionAdd.handle({
+ user: this.client.user,
+ channel: this.channel,
+ message: this,
+ emoji: Util.parseEmoji(emoji),
+ }).reaction,
+ );
+ }
+
+ /**
+ * Deletes the message.
+ * @param {Object} [options] Options
+ * @param {number} [options.timeout=0] How long to wait to delete the message in milliseconds
+ * @param {string} [options.reason] Reason for deleting this message, if it does not belong to the client user
+ * @returns {Promise<Message>}
+ * @example
+ * // Delete a message
+ * message.delete()
+ * .then(msg => console.log(`Deleted message from ${msg.author.username}`))
+ * .catch(console.error);
+ */
+ delete(options = {}) {
+ if (typeof options !== 'object') throw new TypeError('INVALID_TYPE', 'options', 'object', true);
+ const { timeout = 0, reason } = options;
+ if (timeout <= 0) {
+ return this.channel.messages.delete(this.id, reason).then(() => this);
+ } else {
+ return new Promise(resolve => {
+ this.client.setTimeout(() => {
+ resolve(this.delete({ reason }));
+ }, timeout);
+ });
+ }
+ }
+
+ /**
+ * Replies to the message.
+ * @param {StringResolvable|APIMessage} [content=''] The content for the message
+ * @param {MessageOptions|MessageAdditions} [options={}] The options to provide
+ * @returns {Promise<Message|Message[]>}
+ * @example
+ * // Reply to a message
+ * message.reply('Hey, I\'m a reply!')
+ * .then(() => console.log(`Sent a reply to ${message.author.username}`))
+ * .catch(console.error);
+ */
+ reply(content, options) {
+ return this.channel.send(
+ content instanceof APIMessage
+ ? content
+ : APIMessage.transformOptions(content, options, { reply: this.member || this.author }),
+ );
+ }
+
+ /**
+ * Fetch this message.
+ * @returns {Promise<Message>}
+ */
+ fetch() {
+ return this.channel.messages.fetch(this.id, true);
+ }
+
+ /**
+ * Fetches the webhook used to create this message.
+ * @returns {Promise<?Webhook>}
+ */
+ fetchWebhook() {
+ if (!this.webhookID) return Promise.reject(new Error('WEBHOOK_MESSAGE'));
+ return this.client.fetchWebhook(this.webhookID);
+ }
+
+ /**
+ * Suppresses or unsuppresses embeds on a message
+ * @param {boolean} [suppress=true] If the embeds should be suppressed or not
+ * @returns {Promise<Message>}
+ */
+ suppressEmbeds(suppress = true) {
+ const flags = new MessageFlags(this.flags.bitfield);
+
+ if (suppress) {
+ flags.add(MessageFlags.FLAGS.SUPPRESS_EMBEDS);
+ } else {
+ flags.remove(MessageFlags.FLAGS.SUPPRESS_EMBEDS);
+ }
+
+ return this.edit({ flags });
+ }
+
+ /**
+ * Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
+ * without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
+ * method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
+ * @param {Message} message The message to compare it to
+ * @param {Object} rawData Raw data passed through the WebSocket about this message
+ * @returns {boolean}
+ */
+ equals(message, rawData) {
+ if (!message) return false;
+ const embedUpdate = !message.author && !message.attachments;
+ if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
+
+ let equal =
+ this.id === message.id &&
+ this.author.id === message.author.id &&
+ this.content === message.content &&
+ this.tts === message.tts &&
+ this.nonce === message.nonce &&
+ this.embeds.length === message.embeds.length &&
+ this.attachments.length === message.attachments.length;
+
+ if (equal && rawData) {
+ equal =
+ this.mentions.everyone === message.mentions.everyone &&
+ this.createdTimestamp === new Date(rawData.timestamp).getTime() &&
+ this.editedTimestamp === new Date(rawData.edited_timestamp).getTime();
+ }
+
+ return equal;
+ }
+
+ /**
+ * When concatenated with a string, this automatically concatenates the message's content instead of the object.
+ * @returns {string}
+ * @example
+ * // Logs: Message: This is a message!
+ * console.log(`Message: ${message}`);
+ */
+ toString() {
+ return this.content;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ channel: 'channelID',
+ author: 'authorID',
+ application: 'applicationID',
+ guild: 'guildID',
+ cleanContent: true,
+ member: false,
+ reactions: false,
+ });
+ }
+}
+
+module.exports = Message;
diff --git a/node_modules/discord.js/src/structures/MessageAttachment.js b/node_modules/discord.js/src/structures/MessageAttachment.js
new file mode 100644
index 0000000..f5fb723
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageAttachment.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const Util = require('../util/Util');
+
+/**
+ * Represents an attachment in a message.
+ */
+class MessageAttachment {
+ /**
+ * @param {BufferResolvable|Stream} attachment The file
+ * @param {string} [name=null] The name of the file, if any
+ * @param {Object} [data] Extra data
+ */
+ constructor(attachment, name = null, data) {
+ this.attachment = attachment;
+ /**
+ * The name of this attachment
+ * @type {?string}
+ */
+ this.name = name;
+ if (data) this._patch(data);
+ }
+
+ /**
+ * Sets the file of this attachment.
+ * @param {BufferResolvable|Stream} attachment The file
+ * @param {string} [name=null] The name of the file, if any
+ * @returns {MessageAttachment} This attachment
+ */
+ setFile(attachment, name = null) {
+ this.attachment = attachment;
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Sets the name of this attachment.
+ * @param {string} name The name of the file
+ * @returns {MessageAttachment} This attachment
+ */
+ setName(name) {
+ this.name = name;
+ return this;
+ }
+
+ _patch(data) {
+ /**
+ * The ID of this attachment
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The size of this attachment in bytes
+ * @type {number}
+ */
+ this.size = data.size;
+
+ /**
+ * The URL to this attachment
+ * @type {string}
+ */
+ this.url = data.url;
+
+ /**
+ * The Proxy URL to this attachment
+ * @type {string}
+ */
+ this.proxyURL = data.proxy_url;
+
+ /**
+ * The height of this attachment (if an image or video)
+ * @type {?number}
+ */
+ this.height = typeof data.height !== 'undefined' ? data.height : null;
+
+ /**
+ * The width of this attachment (if an image or video)
+ * @type {?number}
+ */
+ this.width = typeof data.width !== 'undefined' ? data.width : null;
+ }
+
+ /**
+ * Whether or not this attachment has been marked as a spoiler
+ * @type {boolean}
+ * @readonly
+ */
+ get spoiler() {
+ return Util.basename(this.url).startsWith('SPOILER_');
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+}
+
+module.exports = MessageAttachment;
diff --git a/node_modules/discord.js/src/structures/MessageCollector.js b/node_modules/discord.js/src/structures/MessageCollector.js
new file mode 100644
index 0000000..f8f3d5a
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageCollector.js
@@ -0,0 +1,129 @@
+'use strict';
+
+const Collector = require('./interfaces/Collector');
+const { Events } = require('../util/Constants');
+
+/**
+ * @typedef {CollectorOptions} MessageCollectorOptions
+ * @property {number} max The maximum amount of messages to collect
+ * @property {number} maxProcessed The maximum amount of messages to process
+ */
+
+/**
+ * Collects messages on a channel.
+ * Will automatically stop if the channel (`'channelDelete'`) or guild (`'guildDelete'`) are deleted.
+ * @extends {Collector}
+ */
+class MessageCollector extends Collector {
+ /**
+ * @param {TextChannel|DMChannel} channel The channel
+ * @param {CollectorFilter} filter The filter to be applied to this collector
+ * @param {MessageCollectorOptions} options The options to be applied to this collector
+ * @emits MessageCollector#message
+ */
+ constructor(channel, filter, options = {}) {
+ super(channel.client, filter, options);
+
+ /**
+ * The channel
+ * @type {TextBasedChannel}
+ */
+ this.channel = channel;
+
+ /**
+ * Total number of messages that were received in the channel during message collection
+ * @type {number}
+ */
+ this.received = 0;
+
+ const bulkDeleteListener = messages => {
+ for (const message of messages.values()) this.handleDispose(message);
+ };
+ this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
+ this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
+
+ if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() + 1);
+ this.client.on(Events.MESSAGE_CREATE, this.handleCollect);
+ this.client.on(Events.MESSAGE_DELETE, this.handleDispose);
+ this.client.on(Events.MESSAGE_BULK_DELETE, bulkDeleteListener);
+ this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion);
+ this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion);
+
+ this.once('end', () => {
+ this.client.removeListener(Events.MESSAGE_CREATE, this.handleCollect);
+ this.client.removeListener(Events.MESSAGE_DELETE, this.handleDispose);
+ this.client.removeListener(Events.MESSAGE_BULK_DELETE, bulkDeleteListener);
+ this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion);
+ this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion);
+ if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() - 1);
+ });
+ }
+
+ /**
+ * Handles a message for possible collection.
+ * @param {Message} message The message that could be collected
+ * @returns {?Snowflake}
+ * @private
+ */
+ collect(message) {
+ /**
+ * Emitted whenever a message is collected.
+ * @event MessageCollector#collect
+ * @param {Message} message The message that was collected
+ */
+ if (message.channel.id !== this.channel.id) return null;
+ this.received++;
+ return message.id;
+ }
+
+ /**
+ * Handles a message for possible disposal.
+ * @param {Message} message The message that could be disposed of
+ * @returns {?Snowflake}
+ */
+ dispose(message) {
+ /**
+ * Emitted whenever a message is disposed of.
+ * @event MessageCollector#dispose
+ * @param {Message} message The message that was disposed of
+ */
+ return message.channel.id === this.channel.id ? message.id : null;
+ }
+
+ /**
+ * Checks after un/collection to see if the collector is done.
+ * @returns {?string}
+ * @private
+ */
+ endReason() {
+ if (this.options.max && this.collected.size >= this.options.max) return 'limit';
+ if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit';
+ return null;
+ }
+
+ /**
+ * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
+ * @private
+ * @param {GuildChannel} channel The channel that was deleted
+ * @returns {void}
+ */
+ _handleChannelDeletion(channel) {
+ if (channel.id === this.channel.id) {
+ this.stop('channelDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
+ * @private
+ * @param {Guild} guild The guild that was deleted
+ * @returns {void}
+ */
+ _handleGuildDeletion(guild) {
+ if (this.channel.guild && guild.id === this.channel.guild.id) {
+ this.stop('guildDelete');
+ }
+ }
+}
+
+module.exports = MessageCollector;
diff --git a/node_modules/discord.js/src/structures/MessageEmbed.js b/node_modules/discord.js/src/structures/MessageEmbed.js
new file mode 100644
index 0000000..2b993a3
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageEmbed.js
@@ -0,0 +1,454 @@
+'use strict';
+
+const { RangeError } = require('../errors');
+const Util = require('../util/Util');
+
+/**
+ * Represents an embed in a message (image/video preview, rich embed, etc.)
+ */
+class MessageEmbed {
+ /**
+ * @name MessageEmbed
+ * @kind constructor
+ * @memberof MessageEmbed
+ * @param {MessageEmbed|Object} [data={}] MessageEmbed to clone or raw embed data
+ */
+
+ constructor(data = {}, skipValidation = false) {
+ this.setup(data, skipValidation);
+ }
+
+ setup(data, skipValidation) {
+ /**
+ * The type of this embed, either:
+ * * `rich` - a rich embed
+ * * `image` - an image embed
+ * * `video` - a video embed
+ * * `gifv` - a gifv embed
+ * * `article` - an article embed
+ * * `link` - a link embed
+ * @type {string}
+ */
+ this.type = data.type;
+
+ /**
+ * The title of this embed
+ * @type {?string}
+ */
+ this.title = data.title;
+
+ /**
+ * The description of this embed
+ * @type {?string}
+ */
+ this.description = data.description;
+
+ /**
+ * The URL of this embed
+ * @type {?string}
+ */
+ this.url = data.url;
+
+ /**
+ * The color of this embed
+ * @type {?number}
+ */
+ this.color = Util.resolveColor(data.color);
+
+ /**
+ * The timestamp of this embed
+ * @type {?number}
+ */
+ this.timestamp = data.timestamp ? new Date(data.timestamp).getTime() : null;
+
+ /**
+ * @typedef {Object} EmbedField
+ * @property {string} name The name of this field
+ * @property {string} value The value of this field
+ * @property {boolean} inline If this field will be displayed inline
+ */
+
+ /**
+ * The fields of this embed
+ * @type {EmbedField[]}
+ */
+ this.fields = [];
+ if (data.fields) {
+ this.fields = skipValidation ? data.fields.map(Util.cloneObject) : this.constructor.normalizeFields(data.fields);
+ }
+
+ /**
+ * @typedef {Object} MessageEmbedThumbnail
+ * @property {string} url URL for this thumbnail
+ * @property {string} proxyURL ProxyURL for this thumbnail
+ * @property {number} height Height of this thumbnail
+ * @property {number} width Width of this thumbnail
+ */
+
+ /**
+ * The thumbnail of this embed (if there is one)
+ * @type {?MessageEmbedThumbnail}
+ */
+ this.thumbnail = data.thumbnail
+ ? {
+ url: data.thumbnail.url,
+ proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url,
+ height: data.thumbnail.height,
+ width: data.thumbnail.width,
+ }
+ : null;
+
+ /**
+ * @typedef {Object} MessageEmbedImage
+ * @property {string} url URL for this image
+ * @property {string} proxyURL ProxyURL for this image
+ * @property {number} height Height of this image
+ * @property {number} width Width of this image
+ */
+
+ /**
+ * The image of this embed, if there is one
+ * @type {?MessageEmbedImage}
+ */
+ this.image = data.image
+ ? {
+ url: data.image.url,
+ proxyURL: data.image.proxyURL || data.image.proxy_url,
+ height: data.image.height,
+ width: data.image.width,
+ }
+ : null;
+
+ /**
+ * @typedef {Object} MessageEmbedVideo
+ * @property {string} url URL of this video
+ * @property {string} proxyURL ProxyURL for this video
+ * @property {number} height Height of this video
+ * @property {number} width Width of this video
+ */
+
+ /**
+ * The video of this embed (if there is one)
+ * @type {?MessageEmbedVideo}
+ * @readonly
+ */
+ this.video = data.video
+ ? {
+ url: data.video.url,
+ proxyURL: data.video.proxyURL || data.video.proxy_url,
+ height: data.video.height,
+ width: data.video.width,
+ }
+ : null;
+
+ /**
+ * @typedef {Object} MessageEmbedAuthor
+ * @property {string} name The name of this author
+ * @property {string} url URL of this author
+ * @property {string} iconURL URL of the icon for this author
+ * @property {string} proxyIconURL Proxied URL of the icon for this author
+ */
+
+ /**
+ * The author of this embed (if there is one)
+ * @type {?MessageEmbedAuthor}
+ */
+ this.author = data.author
+ ? {
+ name: data.author.name,
+ url: data.author.url,
+ iconURL: data.author.iconURL || data.author.icon_url,
+ proxyIconURL: data.author.proxyIconURL || data.author.proxy_icon_url,
+ }
+ : null;
+
+ /**
+ * @typedef {Object} MessageEmbedProvider
+ * @property {string} name The name of this provider
+ * @property {string} url URL of this provider
+ */
+
+ /**
+ * The provider of this embed (if there is one)
+ * @type {?MessageEmbedProvider}
+ */
+ this.provider = data.provider
+ ? {
+ name: data.provider.name,
+ url: data.provider.name,
+ }
+ : null;
+
+ /**
+ * @typedef {Object} MessageEmbedFooter
+ * @property {string} text The text of this footer
+ * @property {string} iconURL URL of the icon for this footer
+ * @property {string} proxyIconURL Proxied URL of the icon for this footer
+ */
+
+ /**
+ * The footer of this embed
+ * @type {?MessageEmbedFooter}
+ */
+ this.footer = data.footer
+ ? {
+ text: data.footer.text,
+ iconURL: data.footer.iconURL || data.footer.icon_url,
+ proxyIconURL: data.footer.proxyIconURL || data.footer.proxy_icon_url,
+ }
+ : null;
+
+ /**
+ * The files of this embed
+ * @type {Array<FileOptions|string|MessageAttachment>}
+ */
+ this.files = data.files || [];
+ }
+
+ /**
+ * The date displayed on this embed
+ * @type {?Date}
+ * @readonly
+ */
+ get createdAt() {
+ return this.timestamp ? new Date(this.timestamp) : null;
+ }
+
+ /**
+ * The hexadecimal version of the embed color, with a leading hash
+ * @type {?string}
+ * @readonly
+ */
+ get hexColor() {
+ return this.color ? `#${this.color.toString(16).padStart(6, '0')}` : null;
+ }
+
+ /**
+ * The accumulated length for the embed title, description, fields and footer text
+ * @type {number}
+ * @readonly
+ */
+ get length() {
+ return (
+ (this.title ? this.title.length : 0) +
+ (this.description ? this.description.length : 0) +
+ (this.fields.length >= 1
+ ? this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0)
+ : 0) +
+ (this.footer ? this.footer.text.length : 0)
+ );
+ }
+
+ /**
+ * Adds a field to the embed (max 25).
+ * @param {StringResolvable} name The name of this field
+ * @param {StringResolvable} value The value of this field
+ * @param {boolean} [inline=false] If this field will be displayed inline
+ * @returns {MessageEmbed}
+ */
+ addField(name, value, inline) {
+ return this.addFields({ name, value, inline });
+ }
+
+ /**
+ * Adds fields to the embed (max 25).
+ * @param {...EmbedFieldData|EmbedFieldData[]} fields The fields to add
+ * @returns {MessageEmbed}
+ */
+ addFields(...fields) {
+ this.fields.push(...this.constructor.normalizeFields(fields));
+ return this;
+ }
+
+ /**
+ * Removes, replaces, and inserts fields in the embed (max 25).
+ * @param {number} index The index to start at
+ * @param {number} deleteCount The number of fields to remove
+ * @param {...EmbedFieldData|EmbedFieldData[]} [fields] The replacing field objects
+ * @returns {MessageEmbed}
+ */
+ spliceFields(index, deleteCount, ...fields) {
+ this.fields.splice(index, deleteCount, ...this.constructor.normalizeFields(...fields));
+ return this;
+ }
+
+ /**
+ * Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
+ * setting an embed image or author/footer icons. Multiple files can be attached.
+ * @param {Array<FileOptions|string|MessageAttachment>} files Files to attach
+ * @returns {MessageEmbed}
+ */
+ attachFiles(files) {
+ this.files = this.files.concat(files);
+ return this;
+ }
+
+ /**
+ * Sets the author of this embed.
+ * @param {StringResolvable} name The name of the author
+ * @param {string} [iconURL] The icon URL of the author
+ * @param {string} [url] The URL of the author
+ * @returns {MessageEmbed}
+ */
+ setAuthor(name, iconURL, url) {
+ this.author = { name: Util.resolveString(name), iconURL, url };
+ return this;
+ }
+
+ /**
+ * Sets the color of this embed.
+ * @param {ColorResolvable} color The color of the embed
+ * @returns {MessageEmbed}
+ */
+ setColor(color) {
+ this.color = Util.resolveColor(color);
+ return this;
+ }
+
+ /**
+ * Sets the description of this embed.
+ * @param {StringResolvable} description The description
+ * @returns {MessageEmbed}
+ */
+ setDescription(description) {
+ description = Util.resolveString(description);
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Sets the footer of this embed.
+ * @param {StringResolvable} text The text of the footer
+ * @param {string} [iconURL] The icon URL of the footer
+ * @returns {MessageEmbed}
+ */
+ setFooter(text, iconURL) {
+ text = Util.resolveString(text);
+ this.footer = { text, iconURL };
+ return this;
+ }
+
+ /**
+ * Sets the image of this embed.
+ * @param {string} url The URL of the image
+ * @returns {MessageEmbed}
+ */
+ setImage(url) {
+ this.image = { url };
+ return this;
+ }
+
+ /**
+ * Sets the thumbnail of this embed.
+ * @param {string} url The URL of the thumbnail
+ * @returns {MessageEmbed}
+ */
+ setThumbnail(url) {
+ this.thumbnail = { url };
+ return this;
+ }
+
+ /**
+ * Sets the timestamp of this embed.
+ * @param {Date|number} [timestamp=Date.now()] The timestamp or date
+ * @returns {MessageEmbed}
+ */
+ setTimestamp(timestamp = Date.now()) {
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
+ this.timestamp = timestamp;
+ return this;
+ }
+
+ /**
+ * Sets the title of this embed.
+ * @param {StringResolvable} title The title
+ * @returns {MessageEmbed}
+ */
+ setTitle(title) {
+ title = Util.resolveString(title);
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Sets the URL of this embed.
+ * @param {string} url The URL
+ * @returns {MessageEmbed}
+ */
+ setURL(url) {
+ this.url = url;
+ return this;
+ }
+
+ /**
+ * Transforms the embed to a plain object.
+ * @returns {Object} The raw data of this embed
+ */
+ toJSON() {
+ return {
+ title: this.title,
+ type: 'rich',
+ description: this.description,
+ url: this.url,
+ timestamp: this.timestamp ? new Date(this.timestamp) : null,
+ color: this.color,
+ fields: this.fields,
+ thumbnail: this.thumbnail,
+ image: this.image,
+ author: this.author
+ ? {
+ name: this.author.name,
+ url: this.author.url,
+ icon_url: this.author.iconURL,
+ }
+ : null,
+ footer: this.footer
+ ? {
+ text: this.footer.text,
+ icon_url: this.footer.iconURL,
+ }
+ : null,
+ };
+ }
+
+ /**
+ * Normalizes field input and resolves strings.
+ * @param {StringResolvable} name The name of the field
+ * @param {StringResolvable} value The value of the field
+ * @param {boolean} [inline=false] Set the field to display inline
+ * @returns {EmbedField}
+ */
+ static normalizeField(name, value, inline = false) {
+ name = Util.resolveString(name);
+ if (!name) throw new RangeError('EMBED_FIELD_NAME');
+ value = Util.resolveString(value);
+ if (!value) throw new RangeError('EMBED_FIELD_VALUE');
+ return { name, value, inline };
+ }
+
+ /**
+ * @typedef {Object} EmbedFieldData
+ * @property {StringResolvable} name The name of this field
+ * @property {StringResolvable} value The value of this field
+ * @property {boolean} [inline] If this field will be displayed inline
+ */
+
+ /**
+ * Normalizes field input and resolves strings.
+ * @param {...EmbedFieldData|EmbedFieldData[]} fields Fields to normalize
+ * @returns {EmbedField[]}
+ */
+ static normalizeFields(...fields) {
+ return fields
+ .flat(2)
+ .map(field =>
+ this.normalizeField(
+ field && field.name,
+ field && field.value,
+ field && typeof field.inline === 'boolean' ? field.inline : false,
+ ),
+ );
+ }
+}
+
+module.exports = MessageEmbed;
diff --git a/node_modules/discord.js/src/structures/MessageMentions.js b/node_modules/discord.js/src/structures/MessageMentions.js
new file mode 100644
index 0000000..cbdd1c7
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageMentions.js
@@ -0,0 +1,221 @@
+'use strict';
+
+const Collection = require('../util/Collection');
+const { ChannelTypes } = require('../util/Constants');
+const Util = require('../util/Util');
+
+/**
+ * Keeps track of mentions in a {@link Message}.
+ */
+class MessageMentions {
+ constructor(message, users, roles, everyone, crosspostedChannels) {
+ /**
+ * The client the message is from
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: message.client });
+
+ /**
+ * The guild the message is in
+ * @type {?Guild}
+ * @readonly
+ */
+ Object.defineProperty(this, 'guild', { value: message.guild });
+
+ /**
+ * The initial message content
+ * @type {string}
+ * @readonly
+ * @private
+ */
+ Object.defineProperty(this, '_content', { value: message.content });
+
+ /**
+ * Whether `@everyone` or `@here` were mentioned
+ * @type {boolean}
+ */
+ this.everyone = Boolean(everyone);
+
+ if (users) {
+ if (users instanceof Collection) {
+ /**
+ * Any users that were mentioned
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, User>}
+ */
+ this.users = new Collection(users);
+ } else {
+ this.users = new Collection();
+ for (const mention of users) {
+ if (mention.member && message.guild) {
+ message.guild.members.add(Object.assign(mention.member, { user: mention }));
+ }
+ const user = message.client.users.add(mention);
+ this.users.set(user.id, user);
+ }
+ }
+ } else {
+ this.users = new Collection();
+ }
+
+ if (roles) {
+ if (roles instanceof Collection) {
+ /**
+ * Any roles that were mentioned
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, Role>}
+ */
+ this.roles = new Collection(roles);
+ } else {
+ this.roles = new Collection();
+ for (const mention of roles) {
+ const role = message.channel.guild.roles.cache.get(mention);
+ if (role) this.roles.set(role.id, role);
+ }
+ }
+ } else {
+ this.roles = new Collection();
+ }
+
+ /**
+ * Cached members for {@link MessageMention#members}
+ * @type {?Collection<Snowflake, GuildMember>}
+ * @private
+ */
+ this._members = null;
+
+ /**
+ * Cached channels for {@link MessageMention#channels}
+ * @type {?Collection<Snowflake, GuildChannel>}
+ * @private
+ */
+ this._channels = null;
+
+ /**
+ * Crossposted channel data.
+ * @typedef {Object} CrosspostedChannel
+ * @property {string} channelID ID of the mentioned channel
+ * @property {string} guildID ID of the guild that has the channel
+ * @property {string} type Type of the channel
+ * @property {string} name The name of the channel
+ */
+
+ if (crosspostedChannels) {
+ if (crosspostedChannels instanceof Collection) {
+ /**
+ * A collection of crossposted channels
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {Collection<Snowflake, CrosspostedChannel>}
+ */
+ this.crosspostedChannels = new Collection(crosspostedChannels);
+ } else {
+ this.crosspostedChannels = new Collection();
+ const channelTypes = Object.keys(ChannelTypes);
+ for (const d of crosspostedChannels) {
+ const type = channelTypes[d.type];
+ this.crosspostedChannels.set(d.id, {
+ channelID: d.id,
+ guildID: d.guild_id,
+ type: type ? type.toLowerCase() : 'unknown',
+ name: d.name,
+ });
+ }
+ }
+ } else {
+ this.crosspostedChannels = new Collection();
+ }
+ }
+
+ /**
+ * Any members that were mentioned (only in {@link TextChannel}s)
+ * <info>Order as received from the API, not as they appear in the message content</info>
+ * @type {?Collection<Snowflake, GuildMember>}
+ * @readonly
+ */
+ get members() {
+ if (this._members) return this._members;
+ if (!this.guild) return null;
+ this._members = new Collection();
+ this.users.forEach(user => {
+ const member = this.guild.member(user);
+ if (member) this._members.set(member.user.id, member);
+ });
+ return this._members;
+ }
+
+ /**
+ * Any channels that were mentioned
+ * <info>Order as they appear first in the message content</info>
+ * @type {Collection<Snowflake, GuildChannel>}
+ * @readonly
+ */
+ get channels() {
+ if (this._channels) return this._channels;
+ this._channels = new Collection();
+ let matches;
+ while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) {
+ const chan = this.client.channels.cache.get(matches[1]);
+ if (chan) this._channels.set(chan.id, chan);
+ }
+ return this._channels;
+ }
+
+ /**
+ * Checks if a user, guild member, role, or channel is mentioned.
+ * Takes into account user mentions, role mentions, and @everyone/@here mentions.
+ * @param {UserResolvable|GuildMember|Role|GuildChannel} data User/GuildMember/Role/Channel to check
+ * @param {Object} [options] Options
+ * @param {boolean} [options.ignoreDirect=false] - Whether to ignore direct mentions to the item
+ * @param {boolean} [options.ignoreRoles=false] - Whether to ignore role mentions to a guild member
+ * @param {boolean} [options.ignoreEveryone=false] - Whether to ignore everyone/here mentions
+ * @returns {boolean}
+ */
+ has(data, { ignoreDirect = false, ignoreRoles = false, ignoreEveryone = false } = {}) {
+ if (!ignoreEveryone && this.everyone) return true;
+ const GuildMember = require('./GuildMember');
+ if (!ignoreRoles && data instanceof GuildMember) {
+ for (const role of this.roles.values()) if (data.roles.cache.has(role.id)) return true;
+ }
+
+ if (!ignoreDirect) {
+ const id = data.id || data;
+ return this.users.has(id) || this.channels.has(id) || this.roles.has(id);
+ }
+
+ return false;
+ }
+
+ toJSON() {
+ return Util.flatten(this, {
+ members: true,
+ channels: true,
+ });
+ }
+}
+
+/**
+ * Regular expression that globally matches `@everyone` and `@here`
+ * @type {RegExp}
+ */
+MessageMentions.EVERYONE_PATTERN = /@(everyone|here)/g;
+
+/**
+ * Regular expression that globally matches user mentions like `<@81440962496172032>`
+ * @type {RegExp}
+ */
+MessageMentions.USERS_PATTERN = /<@!?(\d{17,19})>/g;
+
+/**
+ * Regular expression that globally matches role mentions like `<@&297577916114403338>`
+ * @type {RegExp}
+ */
+MessageMentions.ROLES_PATTERN = /<@&(\d{17,19})>/g;
+
+/**
+ * Regular expression that globally matches channel mentions like `<#222079895583457280>`
+ * @type {RegExp}
+ */
+MessageMentions.CHANNELS_PATTERN = /<#(\d{17,19})>/g;
+
+module.exports = MessageMentions;
diff --git a/node_modules/discord.js/src/structures/MessageReaction.js b/node_modules/discord.js/src/structures/MessageReaction.js
new file mode 100644
index 0000000..771626e
--- /dev/null
+++ b/node_modules/discord.js/src/structures/MessageReaction.js
@@ -0,0 +1,135 @@
+'use strict';
+
+const GuildEmoji = require('./GuildEmoji');
+const ReactionEmoji = require('./ReactionEmoji');
+const ReactionUserManager = require('../managers/ReactionUserManager');
+const Util = require('../util/Util');
+
+/**
+ * Represents a reaction to a message.
+ */
+class MessageReaction {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the message reaction
+ * @param {Message} message The message the reaction refers to
+ */
+ constructor(client, data, message) {
+ /**
+ * The client that instantiated this message reaction
+ * @name MessageReaction#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+ /**
+ * The message that this reaction refers to
+ * @type {Message}
+ */
+ this.message = message;
+
+ /**
+ * Whether the client has given this reaction
+ * @type {boolean}
+ */
+ this.me = data.me;
+
+ /**
+ * A manager of the users that have given this reaction
+ * @type {ReactionUserManager}
+ */
+ this.users = new ReactionUserManager(client, undefined, this);
+
+ this._emoji = new ReactionEmoji(this, data.emoji);
+
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The number of people that have given the same reaction
+ * @type {?number}
+ * @name MessageReaction#count
+ */
+ // eslint-disable-next-line eqeqeq
+ if (this.count == undefined) this.count = data.count;
+ }
+
+ /**
+ * Removes all users from this reaction.
+ * @returns {Promise<MessageReaction>}
+ */
+ async remove() {
+ await this.client.api
+ .channels(this.message.channel.id)
+ .messages(this.message.id)
+ .reactions(this._emoji.identifier)
+ .delete();
+ return this;
+ }
+
+ /**
+ * The emoji of this reaction, either an GuildEmoji object for known custom emojis, or a ReactionEmoji
+ * object which has fewer properties. Whatever the prototype of the emoji, it will still have
+ * `name`, `id`, `identifier` and `toString()`
+ * @type {GuildEmoji|ReactionEmoji}
+ * @readonly
+ */
+ get emoji() {
+ if (this._emoji instanceof GuildEmoji) return this._emoji;
+ // Check to see if the emoji has become known to the client
+ if (this._emoji.id) {
+ const emojis = this.message.client.emojis.cache;
+ if (emojis.has(this._emoji.id)) {
+ const emoji = emojis.get(this._emoji.id);
+ this._emoji = emoji;
+ return emoji;
+ }
+ }
+ return this._emoji;
+ }
+
+ /**
+ * Whether or not this reaction is a partial
+ * @type {boolean}
+ * @readonly
+ */
+ get partial() {
+ return this.count === null;
+ }
+
+ /**
+ * Fetch this reaction.
+ * @returns {Promise<MessageReaction>}
+ */
+ async fetch() {
+ const message = await this.message.fetch();
+ const existing = message.reactions.cache.get(this.emoji.id || this.emoji.name);
+ // The reaction won't get set when it has been completely removed
+ this._patch(existing || { count: 0 });
+ return this;
+ }
+
+ toJSON() {
+ return Util.flatten(this, { emoji: 'emojiID', message: 'messageID' });
+ }
+
+ _add(user) {
+ if (this.partial) return;
+ this.users.cache.set(user.id, user);
+ if (!this.me || user.id !== this.message.client.user.id || this.count === 0) this.count++;
+ if (!this.me) this.me = user.id === this.message.client.user.id;
+ }
+
+ _remove(user) {
+ if (this.partial) return;
+ this.users.cache.delete(user.id);
+ if (!this.me || user.id !== this.message.client.user.id) this.count--;
+ if (user.id === this.message.client.user.id) this.me = false;
+ if (this.count <= 0 && this.users.cache.size === 0) {
+ this.message.reactions.cache.delete(this.emoji.id || this.emoji.name);
+ }
+ }
+}
+
+module.exports = MessageReaction;
diff --git a/node_modules/discord.js/src/structures/NewsChannel.js b/node_modules/discord.js/src/structures/NewsChannel.js
new file mode 100644
index 0000000..76727fc
--- /dev/null
+++ b/node_modules/discord.js/src/structures/NewsChannel.js
@@ -0,0 +1,18 @@
+'use strict';
+
+const TextChannel = require('./TextChannel');
+
+/**
+ * Represents a guild news channel on Discord.
+ * @extends {TextChannel}
+ */
+class NewsChannel extends TextChannel {
+ _patch(data) {
+ super._patch(data);
+
+ // News channels don't have a rate limit per user, remove it
+ this.rateLimitPerUser = undefined;
+ }
+}
+
+module.exports = NewsChannel;
diff --git a/node_modules/discord.js/src/structures/PartialGroupDMChannel.js b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js
new file mode 100644
index 0000000..e398f23
--- /dev/null
+++ b/node_modules/discord.js/src/structures/PartialGroupDMChannel.js
@@ -0,0 +1,46 @@
+'use strict';
+
+const Channel = require('./Channel');
+const { Error } = require('../errors');
+
+/**
+ * Represents a Partial Group DM Channel on Discord.
+ * @extends {Channel}
+ */
+class PartialGroupDMChannel extends Channel {
+ constructor(client, data) {
+ super(client, data);
+
+ /**
+ * The name of this Group DM Channel
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The hash of the channel icon
+ * @type {?string}
+ */
+ this.icon = data.icon;
+ }
+
+ /**
+ * The URL to this channel's icon.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ iconURL({ format, size } = {}) {
+ if (!this.icon) return null;
+ return this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size);
+ }
+
+ delete() {
+ return Promise.reject(new Error('DELETE_GROUP_DM_CHANNEL'));
+ }
+
+ fetch() {
+ return Promise.reject(new Error('FETCH_GROUP_DM_CHANNEL'));
+ }
+}
+
+module.exports = PartialGroupDMChannel;
diff --git a/node_modules/discord.js/src/structures/PermissionOverwrites.js b/node_modules/discord.js/src/structures/PermissionOverwrites.js
new file mode 100644
index 0000000..ea7a45e
--- /dev/null
+++ b/node_modules/discord.js/src/structures/PermissionOverwrites.js
@@ -0,0 +1,189 @@
+'use strict';
+
+const Role = require('./Role');
+const { TypeError } = require('../errors');
+const Permissions = require('../util/Permissions');
+const Util = require('../util/Util');
+
+/**
+ * Represents a permission overwrite for a role or member in a guild channel.
+ */
+class PermissionOverwrites {
+ constructor(guildChannel, data) {
+ /**
+ * The GuildChannel this overwrite is for
+ * @name PermissionOverwrites#channel
+ * @type {GuildChannel}
+ * @readonly
+ */
+ Object.defineProperty(this, 'channel', { value: guildChannel });
+
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The ID of this overwrite, either a user ID or a role ID
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The type of a permission overwrite. It can be one of:
+ * * member
+ * * role
+ * @typedef {string} OverwriteType
+ */
+
+ /**
+ * The type of this overwrite
+ * @type {OverwriteType}
+ */
+ this.type = data.type;
+
+ /**
+ * The permissions that are denied for the user or role.
+ * @type {Readonly<Permissions>}
+ */
+ this.deny = new Permissions(data.deny).freeze();
+
+ /**
+ * The permissions that are allowed for the user or role.
+ * @type {Readonly<Permissions>}
+ */
+ this.allow = new Permissions(data.allow).freeze();
+ }
+
+ /**
+ * Updates this permissionOverwrites.
+ * @param {PermissionOverwriteOptions} options The options for the update
+ * @param {string} [reason] Reason for creating/editing this overwrite
+ * @returns {Promise<PermissionOverwrites>}
+ * @example
+ * // Update permission overwrites
+ * permissionOverwrites.update({
+ * SEND_MESSAGES: false
+ * })
+ * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id)))
+ * .catch(console.error);
+ */
+ update(options, reason) {
+ const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this);
+
+ return this.channel.client.api
+ .channels(this.channel.id)
+ .permissions[this.id].put({
+ data: { id: this.id, type: this.type, allow: allow.bitfield, deny: deny.bitfield },
+ reason,
+ })
+ .then(() => this);
+ }
+
+ /**
+ * Deletes this Permission Overwrite.
+ * @param {string} [reason] Reason for deleting this overwrite
+ * @returns {Promise<PermissionOverwrites>}
+ */
+ delete(reason) {
+ return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({ reason }).then(() => this);
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+
+ /**
+ * An object mapping permission flags to `true` (enabled), `null` (unset) or `false` (disabled).
+ * ```js
+ * {
+ * 'SEND_MESSAGES': true,
+ * 'EMBED_LINKS': null,
+ * 'ATTACH_FILES': false,
+ * }
+ * ```
+ * @typedef {Object} PermissionOverwriteOptions
+ */
+
+ /**
+ * @typedef {object} ResolvedOverwriteOptions
+ * @property {Permissions} allow The allowed permissions
+ * @property {Permissions} deny The denied permissions
+ */
+
+ /**
+ * Resolves bitfield permissions overwrites from an object.
+ * @param {PermissionOverwriteOptions} options The options for the update
+ * @param {Object} initialPermissions The initial permissions
+ * @param {PermissionResolvable} initialPermissions.allow Initial allowed permissions
+ * @param {PermissionResolvable} initialPermissions.deny Initial denied permissions
+ * @returns {ResolvedOverwriteOptions}
+ */
+ static resolveOverwriteOptions(options, { allow, deny } = {}) {
+ allow = new Permissions(allow);
+ deny = new Permissions(deny);
+
+ for (const [perm, value] of Object.entries(options)) {
+ if (value === true) {
+ allow.add(Permissions.FLAGS[perm]);
+ deny.remove(Permissions.FLAGS[perm]);
+ } else if (value === false) {
+ allow.remove(Permissions.FLAGS[perm]);
+ deny.add(Permissions.FLAGS[perm]);
+ } else if (value === null) {
+ allow.remove(Permissions.FLAGS[perm]);
+ deny.remove(Permissions.FLAGS[perm]);
+ }
+ }
+
+ return { allow, deny };
+ }
+
+ /**
+ * The raw data for a permission overwrite
+ * @typedef {Object} RawOverwriteData
+ * @property {Snowflake} id The id of the overwrite
+ * @property {number} allow The permissions to allow
+ * @property {number} deny The permissions to deny
+ * @property {OverwriteType} type The type of this OverwriteData
+ */
+
+ /**
+ * Data that can be resolved into {@link RawOverwriteData}
+ * @typedef {PermissionOverwrites|OverwriteData} OverwriteResolvable
+ */
+
+ /**
+ * Data that can be used for a permission overwrite
+ * @typedef {Object} OverwriteData
+ * @property {GuildMemberResolvable|RoleResolvable} id Member or role this overwrite is for
+ * @property {PermissionResolvable} [allow] The permissions to allow
+ * @property {PermissionResolvable} [deny] The permissions to deny
+ * @property {OverwriteType} [type] The type of this OverwriteData
+ */
+
+ /**
+ * Resolves an overwrite into {@link RawOverwriteData}.
+ * @param {OverwriteResolvable} overwrite The overwrite-like data to resolve
+ * @param {Guild} guild The guild to resolve from
+ * @returns {RawOverwriteData}
+ */
+ static resolve(overwrite, guild) {
+ if (overwrite instanceof this) return overwrite.toJSON();
+ if (typeof overwrite.id === 'string' && ['role', 'member'].includes(overwrite.type)) {
+ return { ...overwrite, allow: Permissions.resolve(overwrite.allow), deny: Permissions.resolve(overwrite.deny) };
+ }
+
+ const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id);
+ if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role', true);
+ const type = userOrRole instanceof Role ? 'role' : 'member';
+
+ return {
+ id: userOrRole.id,
+ type,
+ allow: Permissions.resolve(overwrite.allow),
+ deny: Permissions.resolve(overwrite.deny),
+ };
+ }
+}
+
+module.exports = PermissionOverwrites;
diff --git a/node_modules/discord.js/src/structures/Presence.js b/node_modules/discord.js/src/structures/Presence.js
new file mode 100644
index 0000000..ac07a54
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Presence.js
@@ -0,0 +1,336 @@
+'use strict';
+
+const Emoji = require('./Emoji');
+const ActivityFlags = require('../util/ActivityFlags');
+const { ActivityTypes } = require('../util/Constants');
+const Util = require('../util/Util');
+
+/**
+ * Activity sent in a message.
+ * @typedef {Object} MessageActivity
+ * @property {string} [partyID] Id of the party represented in activity
+ * @property {number} [type] Type of activity sent
+ */
+
+/**
+ * The status of this presence:
+ * * **`online`** - user is online
+ * * **`idle`** - user is AFK
+ * * **`offline`** - user is offline or invisible
+ * * **`dnd`** - user is in Do Not Disturb
+ * @typedef {string} PresenceStatus
+ */
+
+/**
+ * The status of this presence:
+ * * **`online`** - user is online
+ * * **`idle`** - user is AFK
+ * * **`dnd`** - user is in Do Not Disturb
+ * @typedef {string} ClientPresenceStatus
+ */
+
+/**
+ * Represents a user's presence.
+ */
+class Presence {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} [data={}] The data for the presence
+ */
+ constructor(client, data = {}) {
+ /**
+ * The client that instantiated this
+ * @name Presence#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+ /**
+ * The user ID of this presence
+ * @type {Snowflake}
+ */
+ this.userID = data.user.id;
+
+ /**
+ * The guild of this presence
+ * @type {?Guild}
+ */
+ this.guild = data.guild || null;
+
+ this.patch(data);
+ }
+
+ /**
+ * The user of this presence
+ * @type {?User}
+ * @readonly
+ */
+ get user() {
+ return this.client.users.cache.get(this.userID) || null;
+ }
+
+ /**
+ * The member of this presence
+ * @type {?GuildMember}
+ * @readonly
+ */
+ get member() {
+ return this.guild.members.cache.get(this.userID) || null;
+ }
+
+ patch(data) {
+ /**
+ * The status of this presence
+ * @type {PresenceStatus}
+ */
+ this.status = data.status || this.status || 'offline';
+
+ if (data.activities) {
+ /**
+ * The activities of this presence
+ * @type {Activity[]}
+ */
+ this.activities = data.activities.map(activity => new Activity(this, activity));
+ } else if (data.activity || data.game) {
+ this.activities = [new Activity(this, data.game || data.activity)];
+ } else {
+ this.activities = [];
+ }
+
+ /**
+ * The devices this presence is on
+ * @type {?Object}
+ * @property {?ClientPresenceStatus} web The current presence in the web application
+ * @property {?ClientPresenceStatus} mobile The current presence in the mobile application
+ * @property {?ClientPresenceStatus} desktop The current presence in the desktop application
+ */
+ this.clientStatus = data.client_status || null;
+
+ return this;
+ }
+
+ _clone() {
+ const clone = Object.assign(Object.create(this), this);
+ if (this.activities) clone.activities = this.activities.map(activity => activity._clone());
+ return clone;
+ }
+
+ /**
+ * Whether this presence is equal to another.
+ * @param {Presence} presence The presence to compare with
+ * @returns {boolean}
+ */
+ equals(presence) {
+ return (
+ this === presence ||
+ (presence &&
+ this.status === presence.status &&
+ this.activities.length === presence.activities.length &&
+ this.activities.every((activity, index) => activity.equals(presence.activities[index])) &&
+ this.clientStatus.web === presence.clientStatus.web &&
+ this.clientStatus.mobile === presence.clientStatus.mobile &&
+ this.clientStatus.desktop === presence.clientStatus.desktop)
+ );
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+}
+
+/**
+ * Represents an activity that is part of a user's presence.
+ */
+class Activity {
+ constructor(presence, data) {
+ Object.defineProperty(this, 'presence', { value: presence });
+
+ /**
+ * The name of the activity being played
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The type of the activity status
+ * @type {ActivityType}
+ */
+ this.type = ActivityTypes[data.type];
+
+ /**
+ * If the activity is being streamed, a link to the stream
+ * @type {?string}
+ */
+ this.url = data.url || null;
+
+ /**
+ * Details about the activity
+ * @type {?string}
+ */
+ this.details = data.details || null;
+
+ /**
+ * State of the activity
+ * @type {?string}
+ */
+ this.state = data.state || null;
+
+ /**
+ * Application ID associated with this activity
+ * @type {?Snowflake}
+ */
+ this.applicationID = data.application_id || null;
+
+ /**
+ * Timestamps for the activity
+ * @type {?Object}
+ * @prop {?Date} start When the activity started
+ * @prop {?Date} end When the activity will end
+ */
+ this.timestamps = data.timestamps
+ ? {
+ start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null,
+ end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null,
+ }
+ : null;
+
+ /**
+ * Party of the activity
+ * @type {?Object}
+ * @prop {?string} id ID of the party
+ * @prop {number[]} size Size of the party as `[current, max]`
+ */
+ this.party = data.party || null;
+
+ /**
+ * Assets for rich presence
+ * @type {?RichPresenceAssets}
+ */
+ this.assets = data.assets ? new RichPresenceAssets(this, data.assets) : null;
+
+ this.syncID = data.sync_id;
+
+ /**
+ * Flags that describe the activity
+ * @type {Readonly<ActivityFlags>}
+ */
+ this.flags = new ActivityFlags(data.flags).freeze();
+
+ /**
+ * Emoji for a custom activity
+ * @type {?Emoji}
+ */
+ this.emoji = data.emoji ? new Emoji(presence.client, data.emoji) : null;
+
+ /**
+ * Creation date of the activity
+ * @type {number}
+ */
+ this.createdTimestamp = new Date(data.created_at).getTime();
+ }
+
+ /**
+ * Whether this activity is equal to another activity.
+ * @param {Activity} activity The activity to compare with
+ * @returns {boolean}
+ */
+ equals(activity) {
+ return (
+ this === activity ||
+ (activity && this.name === activity.name && this.type === activity.type && this.url === activity.url)
+ );
+ }
+
+ /**
+ * The time the activity was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the activities' name instead of the Activity object.
+ * @returns {string}
+ */
+ toString() {
+ return this.name;
+ }
+
+ _clone() {
+ return Object.assign(Object.create(this), this);
+ }
+}
+
+/**
+ * Assets for a rich presence
+ */
+class RichPresenceAssets {
+ constructor(activity, assets) {
+ Object.defineProperty(this, 'activity', { value: activity });
+
+ /**
+ * Hover text for the large image
+ * @type {?string}
+ */
+ this.largeText = assets.large_text || null;
+
+ /**
+ * Hover text for the small image
+ * @type {?string}
+ */
+ this.smallText = assets.small_text || null;
+
+ /**
+ * ID of the large image asset
+ * @type {?Snowflake}
+ */
+ this.largeImage = assets.large_image || null;
+
+ /**
+ * ID of the small image asset
+ * @type {?Snowflake}
+ */
+ this.smallImage = assets.small_image || null;
+ }
+
+ /**
+ * Gets the URL of the small image asset
+ * @param {Object} [options] Options for the image url
+ * @param {string} [options.format] Format of the image
+ * @param {number} [options.size] Size of the image
+ * @returns {?string} The small image URL
+ */
+ smallImageURL({ format, size } = {}) {
+ if (!this.smallImage) return null;
+ return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, {
+ format,
+ size,
+ });
+ }
+
+ /**
+ * Gets the URL of the large image asset
+ * @param {Object} [options] Options for the image url
+ * @param {string} [options.format] Format of the image
+ * @param {number} [options.size] Size of the image
+ * @returns {?string} The large image URL
+ */
+ largeImageURL({ format, size } = {}) {
+ if (!this.largeImage) return null;
+ if (/^spotify:/.test(this.largeImage)) {
+ return `https://i.scdn.co/image/${this.largeImage.slice(8)}`;
+ } else if (/^twitch:/.test(this.largeImage)) {
+ return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${this.largeImage.slice(7)}.png`;
+ }
+ return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.largeImage, {
+ format,
+ size,
+ });
+ }
+}
+
+exports.Presence = Presence;
+exports.Activity = Activity;
+exports.RichPresenceAssets = RichPresenceAssets;
diff --git a/node_modules/discord.js/src/structures/ReactionCollector.js b/node_modules/discord.js/src/structures/ReactionCollector.js
new file mode 100644
index 0000000..6da9d17
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ReactionCollector.js
@@ -0,0 +1,190 @@
+'use strict';
+
+const Collector = require('./interfaces/Collector');
+const Collection = require('../util/Collection');
+const { Events } = require('../util/Constants');
+
+/**
+ * @typedef {CollectorOptions} ReactionCollectorOptions
+ * @property {number} max The maximum total amount of reactions to collect
+ * @property {number} maxEmojis The maximum number of emojis to collect
+ * @property {number} maxUsers The maximum number of users to react
+ */
+
+/**
+ * Collects reactions on messages.
+ * Will automatically stop if the message (`'messageDelete'`),
+ * channel (`'channelDelete'`), or guild (`'guildDelete'`) are deleted.
+ * @extends {Collector}
+ */
+class ReactionCollector extends Collector {
+ /**
+ * @param {Message} message The message upon which to collect reactions
+ * @param {CollectorFilter} filter The filter to apply to this collector
+ * @param {ReactionCollectorOptions} [options={}] The options to apply to this collector
+ */
+ constructor(message, filter, options = {}) {
+ super(message.client, filter, options);
+
+ /**
+ * The message upon which to collect reactions
+ * @type {Message}
+ */
+ this.message = message;
+
+ /**
+ * The users which have reacted to this message
+ * @type {Collection}
+ */
+ this.users = new Collection();
+
+ /**
+ * The total number of reactions collected
+ * @type {number}
+ */
+ this.total = 0;
+
+ this.empty = this.empty.bind(this);
+ this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
+ this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
+ this._handleMessageDeletion = this._handleMessageDeletion.bind(this);
+
+ if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() + 1);
+ this.client.on(Events.MESSAGE_REACTION_ADD, this.handleCollect);
+ this.client.on(Events.MESSAGE_REACTION_REMOVE, this.handleDispose);
+ this.client.on(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty);
+ this.client.on(Events.MESSAGE_DELETE, this._handleMessageDeletion);
+ this.client.on(Events.CHANNEL_DELETE, this._handleChannelDeletion);
+ this.client.on(Events.GUILD_DELETE, this._handleGuildDeletion);
+
+ this.once('end', () => {
+ this.client.removeListener(Events.MESSAGE_REACTION_ADD, this.handleCollect);
+ this.client.removeListener(Events.MESSAGE_REACTION_REMOVE, this.handleDispose);
+ this.client.removeListener(Events.MESSAGE_REACTION_REMOVE_ALL, this.empty);
+ this.client.removeListener(Events.MESSAGE_DELETE, this._handleMessageDeletion);
+ this.client.removeListener(Events.CHANNEL_DELETE, this._handleChannelDeletion);
+ this.client.removeListener(Events.GUILD_DELETE, this._handleGuildDeletion);
+ if (this.client.getMaxListeners() !== 0) this.client.setMaxListeners(this.client.getMaxListeners() - 1);
+ });
+
+ this.on('collect', (reaction, user) => {
+ this.total++;
+ this.users.set(user.id, user);
+ });
+
+ this.on('remove', (reaction, user) => {
+ this.total--;
+ if (!this.collected.some(r => r.users.cache.has(user.id))) this.users.delete(user.id);
+ });
+ }
+
+ /**
+ * Handles an incoming reaction for possible collection.
+ * @param {MessageReaction} reaction The reaction to possibly collect
+ * @returns {?Snowflake|string}
+ * @private
+ */
+ collect(reaction) {
+ /**
+ * Emitted whenever a reaction is collected.
+ * @event ReactionCollector#collect
+ * @param {MessageReaction} reaction The reaction that was collected
+ * @param {User} user The user that added the reaction
+ */
+ if (reaction.message.id !== this.message.id) return null;
+ return ReactionCollector.key(reaction);
+ }
+
+ /**
+ * Handles a reaction deletion for possible disposal.
+ * @param {MessageReaction} reaction The reaction to possibly dispose of
+ * @param {User} user The user that removed the reaction
+ * @returns {?Snowflake|string}
+ */
+ dispose(reaction, user) {
+ /**
+ * Emitted whenever a reaction is disposed of.
+ * @event ReactionCollector#dispose
+ * @param {MessageReaction} reaction The reaction that was disposed of
+ * @param {User} user The user that removed the reaction
+ */
+ if (reaction.message.id !== this.message.id) return null;
+
+ /**
+ * Emitted whenever a reaction is removed from a message. Will emit on all reaction removals,
+ * as opposed to {@link Collector#dispose} which will only be emitted when the entire reaction
+ * is removed.
+ * @event ReactionCollector#remove
+ * @param {MessageReaction} reaction The reaction that was removed
+ * @param {User} user The user that removed the reaction
+ */
+ if (this.collected.has(ReactionCollector.key(reaction)) && this.users.has(user.id)) {
+ this.emit('remove', reaction, user);
+ }
+ return reaction.count ? null : ReactionCollector.key(reaction);
+ }
+
+ /**
+ * Empties this reaction collector.
+ */
+ empty() {
+ this.total = 0;
+ this.collected.clear();
+ this.users.clear();
+ this.checkEnd();
+ }
+
+ endReason() {
+ if (this.options.max && this.total >= this.options.max) return 'limit';
+ if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit';
+ if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit';
+ return null;
+ }
+
+ /**
+ * Handles checking if the message has been deleted, and if so, stops the collector with the reason 'messageDelete'.
+ * @private
+ * @param {Message} message The message that was deleted
+ * @returns {void}
+ */
+ _handleMessageDeletion(message) {
+ if (message.id === this.message.id) {
+ this.stop('messageDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
+ * @private
+ * @param {GuildChannel} channel The channel that was deleted
+ * @returns {void}
+ */
+ _handleChannelDeletion(channel) {
+ if (channel.id === this.message.channel.id) {
+ this.stop('channelDelete');
+ }
+ }
+
+ /**
+ * Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
+ * @private
+ * @param {Guild} guild The guild that was deleted
+ * @returns {void}
+ */
+ _handleGuildDeletion(guild) {
+ if (this.message.guild && guild.id === this.message.guild.id) {
+ this.stop('guildDelete');
+ }
+ }
+
+ /**
+ * Gets the collector key for a reaction.
+ * @param {MessageReaction} reaction The message reaction to get the key for
+ * @returns {Snowflake|string}
+ */
+ static key(reaction) {
+ return reaction.emoji.id || reaction.emoji.name;
+ }
+}
+
+module.exports = ReactionCollector;
diff --git a/node_modules/discord.js/src/structures/ReactionEmoji.js b/node_modules/discord.js/src/structures/ReactionEmoji.js
new file mode 100644
index 0000000..5c4bc13
--- /dev/null
+++ b/node_modules/discord.js/src/structures/ReactionEmoji.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const Emoji = require('./Emoji');
+const Util = require('../util/Util');
+
+/**
+ * Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
+ * will use this class opposed to the Emoji class when the client doesn't know enough
+ * information about them.
+ * @extends {Emoji}
+ */
+class ReactionEmoji extends Emoji {
+ constructor(reaction, emoji) {
+ super(reaction.message.client, emoji);
+ /**
+ * The message reaction this emoji refers to
+ * @type {MessageReaction}
+ */
+ this.reaction = reaction;
+ }
+
+ toJSON() {
+ return Util.flatten(this, { identifier: true });
+ }
+
+ valueOf() {
+ return this.id;
+ }
+}
+
+module.exports = ReactionEmoji;
diff --git a/node_modules/discord.js/src/structures/Role.js b/node_modules/discord.js/src/structures/Role.js
new file mode 100644
index 0000000..bba198e
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Role.js
@@ -0,0 +1,403 @@
+'use strict';
+
+const Base = require('./Base');
+const { Error, TypeError } = require('../errors');
+const Permissions = require('../util/Permissions');
+const Snowflake = require('../util/Snowflake');
+const Util = require('../util/Util');
+
+/**
+ * Represents a role on Discord.
+ * @extends {Base}
+ */
+class Role extends Base {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the role
+ * @param {Guild} guild The guild the role is part of
+ */
+ constructor(client, data, guild) {
+ super(client);
+
+ /**
+ * The guild that the role belongs to
+ * @type {Guild}
+ */
+ this.guild = guild;
+
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The ID of the role (unique to the guild it is part of)
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The name of the role
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The base 10 color of the role
+ * @type {number}
+ */
+ this.color = data.color;
+
+ /**
+ * If true, users that are part of this role will appear in a separate category in the users list
+ * @type {boolean}
+ */
+ this.hoist = data.hoist;
+
+ /**
+ * The raw position of the role from the API
+ * @type {number}
+ */
+ this.rawPosition = data.position;
+
+ /**
+ * The permissions of the role
+ * @type {Readonly<Permissions>}
+ */
+ this.permissions = new Permissions(data.permissions).freeze();
+
+ /**
+ * Whether or not the role is managed by an external service
+ * @type {boolean}
+ */
+ this.managed = data.managed;
+
+ /**
+ * Whether or not the role can be mentioned by anyone
+ * @type {boolean}
+ */
+ this.mentionable = data.mentionable;
+
+ /**
+ * Whether the role has been deleted
+ * @type {boolean}
+ */
+ this.deleted = false;
+ }
+
+ /**
+ * The timestamp the role was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the role was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * The hexadecimal version of the role color, with a leading hashtag
+ * @type {string}
+ * @readonly
+ */
+ get hexColor() {
+ return `#${this.color.toString(16).padStart(6, '0')}`;
+ }
+
+ /**
+ * The cached guild members that have this role
+ * @type {Collection<Snowflake, GuildMember>}
+ * @readonly
+ */
+ get members() {
+ return this.guild.members.cache.filter(m => m.roles.cache.has(this.id));
+ }
+
+ /**
+ * Whether the role is editable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get editable() {
+ if (this.managed) return false;
+ const clientMember = this.guild.member(this.client.user);
+ if (!clientMember.permissions.has(Permissions.FLAGS.MANAGE_ROLES)) return false;
+ return clientMember.roles.highest.comparePositionTo(this) > 0;
+ }
+
+ /**
+ * The position of the role in the role manager
+ * @type {number}
+ * @readonly
+ */
+ get position() {
+ const sorted = this.guild._sortedRoles();
+ return sorted.array().indexOf(sorted.get(this.id));
+ }
+
+ /**
+ * Compares this role's position to another role's.
+ * @param {RoleResolvable} role Role to compare to this one
+ * @returns {number} Negative number if this role's position is lower (other role's is higher),
+ * positive number if this one is higher (other's is lower), 0 if equal
+ */
+ comparePositionTo(role) {
+ role = this.guild.roles.resolve(role);
+ if (!role) throw new TypeError('INVALID_TYPE', 'role', 'Role nor a Snowflake');
+ return this.constructor.comparePositions(this, role);
+ }
+
+ /**
+ * The data for a role.
+ * @typedef {Object} RoleData
+ * @property {string} [name] The name of the role
+ * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
+ * @property {boolean} [hoist] Whether or not the role should be hoisted
+ * @property {number} [position] The position of the role
+ * @property {PermissionResolvable} [permissions] The permissions of the role
+ * @property {boolean} [mentionable] Whether or not the role should be mentionable
+ */
+
+ /**
+ * Edits the role.
+ * @param {RoleData} data The new data for the role
+ * @param {string} [reason] Reason for editing this role
+ * @returns {Promise<Role>}
+ * @example
+ * // Edit a role
+ * role.edit({ name: 'new role' })
+ * .then(updated => console.log(`Edited role ${updated.name} name to ${updated.name}`))
+ * .catch(console.error);
+ */
+ async edit(data, reason) {
+ if (typeof data.permissions !== 'undefined') data.permissions = Permissions.resolve(data.permissions);
+ else data.permissions = this.permissions.bitfield;
+ if (typeof data.position !== 'undefined') {
+ await Util.setPosition(
+ this,
+ data.position,
+ false,
+ this.guild._sortedRoles(),
+ this.client.api.guilds(this.guild.id).roles,
+ reason,
+ ).then(updatedRoles => {
+ this.client.actions.GuildRolesPositionUpdate.handle({
+ guild_id: this.guild.id,
+ roles: updatedRoles,
+ });
+ });
+ }
+ return this.client.api.guilds[this.guild.id].roles[this.id]
+ .patch({
+ data: {
+ name: data.name || this.name,
+ color: data.color !== null ? Util.resolveColor(data.color || this.color) : null,
+ hoist: typeof data.hoist !== 'undefined' ? data.hoist : this.hoist,
+ permissions: data.permissions,
+ mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable,
+ },
+ reason,
+ })
+ .then(role => {
+ const clone = this._clone();
+ clone._patch(role);
+ return clone;
+ });
+ }
+
+ /**
+ * Returns `channel.permissionsFor(role)`. Returns permissions for a role in a guild channel,
+ * taking into account permission overwrites.
+ * @param {ChannelResolvable} channel The guild channel to use as context
+ * @returns {Readonly<Permissions>}
+ */
+ permissionsIn(channel) {
+ channel = this.guild.channels.resolve(channel);
+ if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE');
+ return channel.rolePermissions(this);
+ }
+
+ /**
+ * Sets a new name for the role.
+ * @param {string} name The new name of the role
+ * @param {string} [reason] Reason for changing the role's name
+ * @returns {Promise<Role>}
+ * @example
+ * // Set the name of the role
+ * role.setName('new role')
+ * .then(updated => console.log(`Edited name of role ${role.name} to ${updated.name}`))
+ * .catch(console.error);
+ */
+ setName(name, reason) {
+ return this.edit({ name }, reason);
+ }
+
+ /**
+ * Sets a new color for the role.
+ * @param {ColorResolvable} color The color of the role
+ * @param {string} [reason] Reason for changing the role's color
+ * @returns {Promise<Role>}
+ * @example
+ * // Set the color of a role
+ * role.setColor('#FF0000')
+ * .then(updated => console.log(`Set color of role to ${updated.color}`))
+ * .catch(console.error);
+ */
+ setColor(color, reason) {
+ return this.edit({ color }, reason);
+ }
+
+ /**
+ * Sets whether or not the role should be hoisted.
+ * @param {boolean} hoist Whether or not to hoist the role
+ * @param {string} [reason] Reason for setting whether or not the role should be hoisted
+ * @returns {Promise<Role>}
+ * @example
+ * // Set the hoist of the role
+ * role.setHoist(true)
+ * .then(r => console.log(`Role hoisted: ${r.hoist}`))
+ * .catch(console.error);
+ */
+ setHoist(hoist, reason) {
+ return this.edit({ hoist }, reason);
+ }
+
+ /**
+ * Sets the permissions of the role.
+ * @param {PermissionResolvable} permissions The permissions of the role
+ * @param {string} [reason] Reason for changing the role's permissions
+ * @returns {Promise<Role>}
+ * @example
+ * // Set the permissions of the role
+ * role.setPermissions(['KICK_MEMBERS', 'BAN_MEMBERS'])
+ * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
+ * .catch(console.error);
+ * @example
+ * // Remove all permissions from a role
+ * role.setPermissions(0)
+ * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
+ * .catch(console.error);
+ */
+ setPermissions(permissions, reason) {
+ return this.edit({ permissions }, reason);
+ }
+
+ /**
+ * Sets whether this role is mentionable.
+ * @param {boolean} mentionable Whether this role should be mentionable
+ * @param {string} [reason] Reason for setting whether or not this role should be mentionable
+ * @returns {Promise<Role>}
+ * @example
+ * // Make the role mentionable
+ * role.setMentionable(true)
+ * .then(updated => console.log(`Role updated ${updated.name}`))
+ * .catch(console.error);
+ */
+ setMentionable(mentionable, reason) {
+ return this.edit({ mentionable }, reason);
+ }
+
+ /**
+ * Sets the position of the role.
+ * @param {number} position The position of the role
+ * @param {Object} [options] Options for setting position
+ * @param {boolean} [options.relative=false] Change the position relative to its current value
+ * @param {string} [options.reason] Reason for changing the position
+ * @returns {Promise<Role>}
+ * @example
+ * // Set the position of the role
+ * role.setPosition(1)
+ * .then(updated => console.log(`Role position: ${updated.position}`))
+ * .catch(console.error);
+ */
+ setPosition(position, { relative, reason } = {}) {
+ return Util.setPosition(
+ this,
+ position,
+ relative,
+ this.guild._sortedRoles(),
+ this.client.api.guilds(this.guild.id).roles,
+ reason,
+ ).then(updatedRoles => {
+ this.client.actions.GuildRolesPositionUpdate.handle({
+ guild_id: this.guild.id,
+ roles: updatedRoles,
+ });
+ return this;
+ });
+ }
+
+ /**
+ * Deletes the role.
+ * @param {string} [reason] Reason for deleting this role
+ * @returns {Promise<Role>}
+ * @example
+ * // Delete a role
+ * role.delete('The role needed to go')
+ * .then(deleted => console.log(`Deleted role ${deleted.name}`))
+ * .catch(console.error);
+ */
+ delete(reason) {
+ return this.client.api.guilds[this.guild.id].roles[this.id].delete({ reason }).then(() => {
+ this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: this.id });
+ return this;
+ });
+ }
+
+ /**
+ * Whether this role equals another role. It compares all properties, so for most operations
+ * it is advisable to just compare `role.id === role2.id` as it is much faster and is often
+ * what most users need.
+ * @param {Role} role Role to compare with
+ * @returns {boolean}
+ */
+ equals(role) {
+ return (
+ role &&
+ this.id === role.id &&
+ this.name === role.name &&
+ this.color === role.color &&
+ this.hoist === role.hoist &&
+ this.position === role.position &&
+ this.permissions.bitfield === role.permissions.bitfield &&
+ this.managed === role.managed
+ );
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the role's mention instead of the Role object.
+ * @returns {string}
+ * @example
+ * // Logs: Role: <@&123456789012345678>
+ * console.log(`Role: ${role}`);
+ */
+ toString() {
+ if (this.id === this.guild.id) return '@everyone';
+ return `<@&${this.id}>`;
+ }
+
+ toJSON() {
+ return super.toJSON({ createdTimestamp: true });
+ }
+
+ /**
+ * Compares the positions of two roles.
+ * @param {Role} role1 First role to compare
+ * @param {Role} role2 Second role to compare
+ * @returns {number} Negative number if the first role's position is lower (second role's is higher),
+ * positive number if the first's is higher (second's is lower), 0 if equal
+ */
+ static comparePositions(role1, role2) {
+ if (role1.position === role2.position) return role2.id - role1.id;
+ return role1.position - role2.position;
+ }
+}
+
+module.exports = Role;
diff --git a/node_modules/discord.js/src/structures/StoreChannel.js b/node_modules/discord.js/src/structures/StoreChannel.js
new file mode 100644
index 0000000..87cb040
--- /dev/null
+++ b/node_modules/discord.js/src/structures/StoreChannel.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const GuildChannel = require('./GuildChannel');
+
+/**
+ * Represents a guild store channel on Discord.
+ * @extends {GuildChannel}
+ */
+class StoreChannel extends GuildChannel {
+ _patch(data) {
+ super._patch(data);
+
+ /**
+ * If the guild considers this channel NSFW
+ * @type {boolean}
+ * @readonly
+ */
+ this.nsfw = data.nsfw;
+ }
+}
+
+module.exports = StoreChannel;
diff --git a/node_modules/discord.js/src/structures/Team.js b/node_modules/discord.js/src/structures/Team.js
new file mode 100644
index 0000000..a28c5a2
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Team.js
@@ -0,0 +1,109 @@
+'use strict';
+
+const Base = require('./Base');
+const TeamMember = require('./TeamMember');
+const Collection = require('../util/Collection');
+const Snowflake = require('../util/Snowflake');
+
+/**
+ * Represents a Client OAuth2 Application Team.
+ * @extends {Base}
+ */
+class Team extends Base {
+ constructor(client, data) {
+ super(client);
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The ID of the Team
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The name of the Team
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The Team's icon hash
+ * @type {?string}
+ */
+ this.icon = data.icon || null;
+
+ /**
+ * The Team's owner id
+ * @type {?string}
+ */
+ this.ownerID = data.owner_user_id || null;
+
+ /**
+ * The Team's members
+ * @type {Collection<Snowflake, TeamMember>}
+ */
+ this.members = new Collection();
+
+ for (const memberData of data.members) {
+ const member = new TeamMember(this, memberData);
+ this.members.set(member.id, member);
+ }
+ }
+
+ /**
+ * The owner of this team
+ * @type {?TeamMember}
+ * @readonly
+ */
+ get owner() {
+ return this.members.get(this.ownerID) || null;
+ }
+
+ /**
+ * The timestamp the team was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the team was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * A link to the teams's icon.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string} URL to the icon
+ */
+ iconURL({ format, size } = {}) {
+ if (!this.icon) return null;
+ return this.client.rest.cdn.TeamIcon(this.id, this.icon, { format, size });
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the Team's name instead of the
+ * Team object.
+ * @returns {string}
+ * @example
+ * // Logs: Team name: My Team
+ * console.log(`Team name: ${team}`);
+ */
+ toString() {
+ return this.name;
+ }
+
+ toJSON() {
+ return super.toJSON({ createdTimestamp: true });
+ }
+}
+
+module.exports = Team;
diff --git a/node_modules/discord.js/src/structures/TeamMember.js b/node_modules/discord.js/src/structures/TeamMember.js
new file mode 100644
index 0000000..ba7ecd2
--- /dev/null
+++ b/node_modules/discord.js/src/structures/TeamMember.js
@@ -0,0 +1,65 @@
+'use strict';
+
+const Base = require('./Base');
+const { MembershipStates } = require('../util/Constants');
+
+/**
+ * Represents a Client OAuth2 Application Team Member.
+ * @extends {Base}
+ */
+class TeamMember extends Base {
+ constructor(team, data) {
+ super(team.client);
+
+ /**
+ * The Team this member is part of
+ * @type {Team}
+ */
+ this.team = team;
+
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The permissions this Team Member has with regard to the team
+ * @type {string[]}
+ */
+ this.permissions = data.permissions;
+
+ /**
+ * The permissions this Team Member has with regard to the team
+ * @type {MembershipStates}
+ */
+ this.membershipState = MembershipStates[data.membership_state];
+
+ /**
+ * The user for this Team Member
+ * @type {User}
+ */
+ this.user = this.client.users.add(data.user);
+ }
+
+ /**
+ * The ID of the Team Member
+ * @type {Snowflake}
+ * @readonly
+ */
+ get id() {
+ return this.user.id;
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the team members's mention instead of the
+ * TeamMember object.
+ * @returns {string}
+ * @example
+ * // Logs: Team Member's mention: <@123456789012345678>
+ * console.log(`Team Member's mention: ${teamMember}`);
+ */
+ toString() {
+ return this.user.toString();
+ }
+}
+
+module.exports = TeamMember;
diff --git a/node_modules/discord.js/src/structures/TextChannel.js b/node_modules/discord.js/src/structures/TextChannel.js
new file mode 100644
index 0000000..65ec13d
--- /dev/null
+++ b/node_modules/discord.js/src/structures/TextChannel.js
@@ -0,0 +1,151 @@
+'use strict';
+
+const GuildChannel = require('./GuildChannel');
+const Webhook = require('./Webhook');
+const TextBasedChannel = require('./interfaces/TextBasedChannel');
+const MessageManager = require('../managers/MessageManager');
+const Collection = require('../util/Collection');
+const DataResolver = require('../util/DataResolver');
+
+/**
+ * Represents a guild text channel on Discord.
+ * @extends {GuildChannel}
+ * @implements {TextBasedChannel}
+ */
+class TextChannel extends GuildChannel {
+ /**
+ * @param {Guild} guild The guild the text channel is part of
+ * @param {Object} data The data for the text channel
+ */
+ constructor(guild, data) {
+ super(guild, data);
+ /**
+ * A manager of the messages sent to this channel
+ * @type {MessageManager}
+ */
+ this.messages = new MessageManager(this);
+ this._typing = new Map();
+ }
+
+ _patch(data) {
+ super._patch(data);
+
+ /**
+ * The topic of the text channel
+ * @type {?string}
+ */
+ this.topic = data.topic;
+
+ /**
+ * If the guild considers this channel NSFW
+ * @type {boolean}
+ * @readonly
+ */
+ this.nsfw = data.nsfw;
+
+ /**
+ * The ID of the last message sent in this channel, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageID = data.last_message_id;
+
+ /**
+ * The ratelimit per user for this channel in seconds
+ * @type {number}
+ */
+ this.rateLimitPerUser = data.rate_limit_per_user || 0;
+
+ /**
+ * The timestamp when the last pinned message was pinned, if there was one
+ * @type {?number}
+ */
+ this.lastPinTimestamp = data.last_pin_timestamp ? new Date(data.last_pin_timestamp).getTime() : null;
+
+ if (data.messages) for (const message of data.messages) this.messages.add(message);
+ }
+
+ /**
+ * Sets the rate limit per user for this channel.
+ * @param {number} rateLimitPerUser The new ratelimit in seconds
+ * @param {string} [reason] Reason for changing the channel's ratelimits
+ * @returns {Promise<TextChannel>}
+ */
+ setRateLimitPerUser(rateLimitPerUser, reason) {
+ return this.edit({ rateLimitPerUser }, reason);
+ }
+
+ /**
+ * Sets whether this channel is flagged as NSFW.
+ * @param {boolean} nsfw Whether the channel should be considered NSFW
+ * @param {string} [reason] Reason for changing the channel's NSFW flag
+ * @returns {Promise<TextChannel>}
+ */
+ setNSFW(nsfw, reason) {
+ return this.edit({ nsfw }, reason);
+ }
+
+ /**
+ * Fetches all webhooks for the channel.
+ * @returns {Promise<Collection<Snowflake, Webhook>>}
+ * @example
+ * // Fetch webhooks
+ * channel.fetchWebhooks()
+ * .then(hooks => console.log(`This channel has ${hooks.size} hooks`))
+ * .catch(console.error);
+ */
+ fetchWebhooks() {
+ return this.client.api.channels[this.id].webhooks.get().then(data => {
+ const hooks = new Collection();
+ for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook));
+ return hooks;
+ });
+ }
+
+ /**
+ * Creates a webhook for the channel.
+ * @param {string} name The name of the webhook
+ * @param {Object} [options] Options for creating the webhook
+ * @param {BufferResolvable|Base64Resolvable} [options.avatar] Avatar for the webhook
+ * @param {string} [options.reason] Reason for creating the webhook
+ * @returns {Promise<Webhook>} webhook The created webhook
+ * @example
+ * // Create a webhook for the current channel
+ * channel.createWebhook('Snek', {
+ * avatar: 'https://i.imgur.com/mI8XcpG.jpg',
+ * reason: 'Needed a cool new Webhook'
+ * })
+ * .then(console.log)
+ * .catch(console.error)
+ */
+ async createWebhook(name, { avatar, reason } = {}) {
+ if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
+ avatar = await DataResolver.resolveImage(avatar);
+ }
+ return this.client.api.channels[this.id].webhooks
+ .post({
+ data: {
+ name,
+ avatar,
+ },
+ reason,
+ })
+ .then(data => new Webhook(this.client, data));
+ }
+
+ // These are here only for documentation purposes - they are implemented by TextBasedChannel
+ /* eslint-disable no-empty-function */
+ get lastMessage() {}
+ get lastPinAt() {}
+ send() {}
+ startTyping() {}
+ stopTyping() {}
+ get typing() {}
+ get typingCount() {}
+ createMessageCollector() {}
+ awaitMessages() {}
+ bulkDelete() {}
+}
+
+TextBasedChannel.applyToClass(TextChannel, true);
+
+module.exports = TextChannel;
diff --git a/node_modules/discord.js/src/structures/User.js b/node_modules/discord.js/src/structures/User.js
new file mode 100644
index 0000000..b2a6500
--- /dev/null
+++ b/node_modules/discord.js/src/structures/User.js
@@ -0,0 +1,318 @@
+'use strict';
+
+const Base = require('./Base');
+const { Presence } = require('./Presence');
+const TextBasedChannel = require('./interfaces/TextBasedChannel');
+const { Error } = require('../errors');
+const Snowflake = require('../util/Snowflake');
+const UserFlags = require('../util/UserFlags');
+
+/**
+ * Represents a user on Discord.
+ * @implements {TextBasedChannel}
+ * @extends {Base}
+ */
+class User extends Base {
+ /**
+ * @param {Client} client The instantiating client
+ * @param {Object} data The data for the user
+ */
+ constructor(client, data) {
+ super(client);
+
+ /**
+ * The ID of the user
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * Whether or not the user is a bot
+ * @type {boolean}
+ * @name User#bot
+ */
+ this.bot = Boolean(data.bot);
+
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The username of the user
+ * @type {?string}
+ * @name User#username
+ */
+ if (data.username) this.username = data.username;
+
+ /**
+ * A discriminator based on username for the user
+ * @type {?string}
+ * @name User#discriminator
+ */
+ if (data.discriminator) this.discriminator = data.discriminator;
+
+ /**
+ * The ID of the user's avatar
+ * @type {?string}
+ * @name User#avatar
+ */
+ if (typeof data.avatar !== 'undefined') this.avatar = data.avatar;
+
+ if (typeof data.bot !== 'undefined') this.bot = Boolean(data.bot);
+
+ /**
+ * Whether the user is an Official Discord System user (part of the urgent message system)
+ * @type {?boolean}
+ * @name User#system
+ */
+ if (typeof data.system !== 'undefined') this.system = Boolean(data.system);
+
+ /**
+ * The locale of the user's client (ISO 639-1)
+ * @type {?string}
+ * @name User#locale
+ */
+ if (data.locale) this.locale = data.locale;
+
+ /**
+ * The flags for this user
+ * @type {?UserFlags}
+ */
+ if (typeof data.public_flags !== 'undefined') this.flags = new UserFlags(data.public_flags);
+
+ /**
+ * The ID of the last message sent by the user, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageID = null;
+
+ /**
+ * The ID of the channel for the last message sent by the user, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageChannelID = null;
+ }
+
+ /**
+ * Whether this User is a partial
+ * @type {boolean}
+ * @readonly
+ */
+ get partial() {
+ return typeof this.username !== 'string';
+ }
+
+ /**
+ * The timestamp the user was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the user was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * The Message object of the last message sent by the user, if one was sent
+ * @type {?Message}
+ * @readonly
+ */
+ get lastMessage() {
+ const channel = this.client.channels.cache.get(this.lastMessageChannelID);
+ return (channel && channel.messages.cache.get(this.lastMessageID)) || null;
+ }
+
+ /**
+ * The presence of this user
+ * @type {Presence}
+ * @readonly
+ */
+ get presence() {
+ for (const guild of this.client.guilds.cache.values()) {
+ if (guild.presences.cache.has(this.id)) return guild.presences.cache.get(this.id);
+ }
+ return new Presence(this.client, { user: { id: this.id } });
+ }
+
+ /**
+ * A link to the user's avatar.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ avatarURL({ format, size, dynamic } = {}) {
+ if (!this.avatar) return null;
+ return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size, dynamic);
+ }
+
+ /**
+ * A link to the user's default avatar
+ * @type {string}
+ * @readonly
+ */
+ get defaultAvatarURL() {
+ return this.client.rest.cdn.DefaultAvatar(this.discriminator % 5);
+ }
+
+ /**
+ * A link to the user's avatar if they have one.
+ * Otherwise a link to their default avatar will be returned.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {string}
+ */
+ displayAvatarURL(options) {
+ return this.avatarURL(options) || this.defaultAvatarURL;
+ }
+
+ /**
+ * The Discord "tag" (e.g. `hydrabolt#0001`) for this user
+ * @type {?string}
+ * @readonly
+ */
+ get tag() {
+ return typeof this.username === 'string' ? `${this.username}#${this.discriminator}` : null;
+ }
+
+ /**
+ * Checks whether the user is typing in a channel.
+ * @param {ChannelResolvable} channel The channel to check in
+ * @returns {boolean}
+ */
+ typingIn(channel) {
+ channel = this.client.channels.resolve(channel);
+ return channel._typing.has(this.id);
+ }
+
+ /**
+ * Gets the time that the user started typing.
+ * @param {ChannelResolvable} channel The channel to get the time in
+ * @returns {?Date}
+ */
+ typingSinceIn(channel) {
+ channel = this.client.channels.resolve(channel);
+ return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null;
+ }
+
+ /**
+ * Gets the amount of time the user has been typing in a channel for (in milliseconds), or -1 if they're not typing.
+ * @param {ChannelResolvable} channel The channel to get the time in
+ * @returns {number}
+ */
+ typingDurationIn(channel) {
+ channel = this.client.channels.resolve(channel);
+ return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1;
+ }
+
+ /**
+ * The DM between the client's user and this user
+ * @type {?DMChannel}
+ * @readonly
+ */
+ get dmChannel() {
+ return this.client.channels.cache.find(c => c.type === 'dm' && c.recipient.id === this.id) || null;
+ }
+
+ /**
+ * Creates a DM channel between the client and the user.
+ * @returns {Promise<DMChannel>}
+ */
+ async createDM() {
+ const { dmChannel } = this;
+ if (dmChannel && !dmChannel.partial) return dmChannel;
+ const data = await this.client.api.users(this.client.user.id).channels.post({
+ data: {
+ recipient_id: this.id,
+ },
+ });
+ return this.client.actions.ChannelCreate.handle(data).channel;
+ }
+
+ /**
+ * Deletes a DM channel (if one exists) between the client and the user. Resolves with the channel if successful.
+ * @returns {Promise<DMChannel>}
+ */
+ async deleteDM() {
+ const { dmChannel } = this;
+ if (!dmChannel) throw new Error('USER_NO_DMCHANNEL');
+ const data = await this.client.api.channels(dmChannel.id).delete();
+ return this.client.actions.ChannelDelete.handle(data).channel;
+ }
+
+ /**
+ * Checks if the user is equal to another. It compares ID, username, discriminator, avatar, and bot flags.
+ * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.
+ * @param {User} user User to compare with
+ * @returns {boolean}
+ */
+ equals(user) {
+ let equal =
+ user &&
+ this.id === user.id &&
+ this.username === user.username &&
+ this.discriminator === user.discriminator &&
+ this.avatar === user.avatar;
+
+ return equal;
+ }
+
+ /**
+ * Fetches this user's flags.
+ * @returns {Promise<UserFlags>}
+ */
+ async fetchFlags() {
+ if (this.flags) return this.flags;
+ const data = await this.client.api.users(this.id).get();
+ this._patch(data);
+ return this.flags;
+ }
+
+ /**
+ * Fetches this user.
+ * @returns {Promise<User>}
+ */
+ fetch() {
+ return this.client.users.fetch(this.id, true);
+ }
+
+ /**
+ * When concatenated with a string, this automatically returns the user's mention instead of the User object.
+ * @returns {string}
+ * @example
+ * // Logs: Hello from <@123456789012345678>!
+ * console.log(`Hello from ${user}!`);
+ */
+ toString() {
+ return `<@${this.id}>`;
+ }
+
+ toJSON(...props) {
+ const json = super.toJSON(
+ {
+ createdTimestamp: true,
+ defaultAvatarURL: true,
+ tag: true,
+ lastMessage: false,
+ lastMessageID: false,
+ },
+ ...props,
+ );
+ json.avatarURL = this.avatarURL();
+ json.displayAvatarURL = this.displayAvatarURL();
+ return json;
+ }
+
+ // These are here only for documentation purposes - they are implemented by TextBasedChannel
+ /* eslint-disable no-empty-function */
+ send() {}
+}
+
+TextBasedChannel.applyToClass(User);
+
+module.exports = User;
diff --git a/node_modules/discord.js/src/structures/VoiceChannel.js b/node_modules/discord.js/src/structures/VoiceChannel.js
new file mode 100644
index 0000000..6fb5ab7
--- /dev/null
+++ b/node_modules/discord.js/src/structures/VoiceChannel.js
@@ -0,0 +1,151 @@
+'use strict';
+
+const GuildChannel = require('./GuildChannel');
+const { Error } = require('../errors');
+const Collection = require('../util/Collection');
+const { browser } = require('../util/Constants');
+const Permissions = require('../util/Permissions');
+
+/**
+ * Represents a guild voice channel on Discord.
+ * @extends {GuildChannel}
+ */
+class VoiceChannel extends GuildChannel {
+ _patch(data) {
+ super._patch(data);
+ /**
+ * The bitrate of this voice channel
+ * @type {number}
+ */
+ this.bitrate = data.bitrate;
+
+ /**
+ * The maximum amount of users allowed in this channel - 0 means unlimited.
+ * @type {number}
+ */
+ this.userLimit = data.user_limit;
+ }
+
+ /**
+ * The members in this voice channel
+ * @type {Collection<Snowflake, GuildMember>}
+ * @name VoiceChannel#members
+ * @readonly
+ */
+ get members() {
+ const coll = new Collection();
+ for (const state of this.guild.voiceStates.cache.values()) {
+ if (state.channelID === this.id && state.member) {
+ coll.set(state.id, state.member);
+ }
+ }
+ return coll;
+ }
+
+ /**
+ * Checks if the voice channel is full
+ * @type {boolean}
+ * @readonly
+ */
+ get full() {
+ return this.userLimit > 0 && this.members.size >= this.userLimit;
+ }
+
+ /**
+ * Whether the channel is deletable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get deletable() {
+ return super.deletable && this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false);
+ }
+
+ /**
+ * Whether the channel is editable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get editable() {
+ return this.manageable && this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false);
+ }
+
+ /**
+ * Whether the channel is joinable by the client user
+ * @type {boolean}
+ * @readonly
+ */
+ get joinable() {
+ if (browser) return false;
+ if (!this.viewable) return false;
+ if (!this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT, false)) return false;
+ if (this.full && !this.permissionsFor(this.client.user).has(Permissions.FLAGS.MOVE_MEMBERS, false)) return false;
+ return true;
+ }
+
+ /**
+ * Checks if the client has permission to send audio to the voice channel
+ * @type {boolean}
+ * @readonly
+ */
+ get speakable() {
+ return this.permissionsFor(this.client.user).has(Permissions.FLAGS.SPEAK, false);
+ }
+
+ /**
+ * Sets the bitrate of the channel.
+ * @param {number} bitrate The new bitrate
+ * @param {string} [reason] Reason for changing the channel's bitrate
+ * @returns {Promise<VoiceChannel>}
+ * @example
+ * // Set the bitrate of a voice channel
+ * voiceChannel.setBitrate(48000)
+ * .then(vc => console.log(`Set bitrate to ${vc.bitrate}bps for ${vc.name}`))
+ * .catch(console.error);
+ */
+ setBitrate(bitrate, reason) {
+ return this.edit({ bitrate }, reason);
+ }
+
+ /**
+ * Sets the user limit of the channel.
+ * @param {number} userLimit The new user limit
+ * @param {string} [reason] Reason for changing the user limit
+ * @returns {Promise<VoiceChannel>}
+ * @example
+ * // Set the user limit of a voice channel
+ * voiceChannel.setUserLimit(42)
+ * .then(vc => console.log(`Set user limit to ${vc.userLimit} for ${vc.name}`))
+ * .catch(console.error);
+ */
+ setUserLimit(userLimit, reason) {
+ return this.edit({ userLimit }, reason);
+ }
+
+ /**
+ * Attempts to join this voice channel.
+ * @returns {Promise<VoiceConnection>}
+ * @example
+ * // Join a voice channel
+ * voiceChannel.join()
+ * .then(connection => console.log('Connected!'))
+ * .catch(console.error);
+ */
+ join() {
+ if (browser) return Promise.reject(new Error('VOICE_NO_BROWSER'));
+ return this.client.voice.joinChannel(this);
+ }
+
+ /**
+ * Leaves this voice channel.
+ * @example
+ * // Leave a voice channel
+ * voiceChannel.leave();
+ */
+ leave() {
+ if (browser) return;
+ const connection = this.client.voice.connections.get(this.guild.id);
+ if (connection && connection.channel.id === this.id) connection.disconnect();
+ }
+}
+
+module.exports = VoiceChannel;
diff --git a/node_modules/discord.js/src/structures/VoiceRegion.js b/node_modules/discord.js/src/structures/VoiceRegion.js
new file mode 100644
index 0000000..9626195
--- /dev/null
+++ b/node_modules/discord.js/src/structures/VoiceRegion.js
@@ -0,0 +1,52 @@
+'use strict';
+
+const Util = require('../util/Util');
+
+/**
+ * Represents a Discord voice region for guilds.
+ */
+class VoiceRegion {
+ constructor(data) {
+ /**
+ * The ID of the region
+ * @type {string}
+ */
+ this.id = data.id;
+
+ /**
+ * Name of the region
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * Whether the region is VIP-only
+ * @type {boolean}
+ */
+ this.vip = data.vip;
+
+ /**
+ * Whether the region is deprecated
+ * @type {boolean}
+ */
+ this.deprecated = data.deprecated;
+
+ /**
+ * Whether the region is optimal
+ * @type {boolean}
+ */
+ this.optimal = data.optimal;
+
+ /**
+ * Whether the region is custom
+ * @type {boolean}
+ */
+ this.custom = data.custom;
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+}
+
+module.exports = VoiceRegion;
diff --git a/node_modules/discord.js/src/structures/VoiceState.js b/node_modules/discord.js/src/structures/VoiceState.js
new file mode 100644
index 0000000..cc9bcde
--- /dev/null
+++ b/node_modules/discord.js/src/structures/VoiceState.js
@@ -0,0 +1,208 @@
+'use strict';
+
+const Base = require('./Base');
+const { Error, TypeError } = require('../errors');
+const { browser } = require('../util/Constants');
+
+/**
+ * Represents the voice state for a Guild Member.
+ */
+class VoiceState extends Base {
+ /**
+ * @param {Guild} guild The guild the voice state is part of
+ * @param {Object} data The data for the voice state
+ */
+ constructor(guild, data) {
+ super(guild.client);
+ /**
+ * The guild of this voice state
+ * @type {Guild}
+ */
+ this.guild = guild;
+ /**
+ * The ID of the member of this voice state
+ * @type {Snowflake}
+ */
+ this.id = data.user_id;
+ this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * Whether this member is deafened server-wide
+ * @type {?boolean}
+ */
+ this.serverDeaf = data.deaf;
+ /**
+ * Whether this member is muted server-wide
+ * @type {?boolean}
+ */
+ this.serverMute = data.mute;
+ /**
+ * Whether this member is self-deafened
+ * @type {?boolean}
+ */
+ this.selfDeaf = data.self_deaf;
+ /**
+ * Whether this member is self-muted
+ * @type {?boolean}
+ */
+ this.selfMute = data.self_mute;
+ /**
+ * The session ID of this member's connection
+ * @type {?string}
+ */
+ this.sessionID = data.session_id;
+ /**
+ * Whether this member is streaming using "Go Live"
+ * @type {boolean}
+ */
+ this.streaming = data.self_stream || false;
+ /**
+ * The ID of the voice channel that this member is in
+ * @type {?Snowflake}
+ */
+ this.channelID = data.channel_id;
+ return this;
+ }
+
+ /**
+ * The member that this voice state belongs to
+ * @type {?GuildMember}
+ * @readonly
+ */
+ get member() {
+ return this.guild.members.cache.get(this.id) || null;
+ }
+
+ /**
+ * The channel that the member is connected to
+ * @type {?VoiceChannel}
+ * @readonly
+ */
+ get channel() {
+ return this.guild.channels.cache.get(this.channelID) || null;
+ }
+
+ /**
+ * If this is a voice state of the client user, then this will refer to the active VoiceConnection for this guild
+ * @type {?VoiceConnection}
+ * @readonly
+ */
+ get connection() {
+ if (browser || this.id !== this.client.user.id) return null;
+ return this.client.voice.connections.get(this.guild.id) || null;
+ }
+
+ /**
+ * Whether this member is either self-deafened or server-deafened
+ * @type {?boolean}
+ * @readonly
+ */
+ get deaf() {
+ return this.serverDeaf || this.selfDeaf;
+ }
+
+ /**
+ * Whether this member is either self-muted or server-muted
+ * @type {?boolean}
+ * @readonly
+ */
+ get mute() {
+ return this.serverMute || this.selfMute;
+ }
+
+ /**
+ * Whether this member is currently speaking. A boolean if the information is available (aka
+ * the bot is connected to any voice channel in the guild), otherwise this is null
+ * @type {?boolean}
+ * @readonly
+ */
+ get speaking() {
+ return this.channel && this.channel.connection ? Boolean(this.channel.connection._speaking.get(this.id)) : null;
+ }
+
+ /**
+ * Mutes/unmutes the member of this voice state.
+ * @param {boolean} mute Whether or not the member should be muted
+ * @param {string} [reason] Reason for muting or unmuting
+ * @returns {Promise<GuildMember>}
+ */
+ setMute(mute, reason) {
+ return this.member ? this.member.edit({ mute }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER'));
+ }
+
+ /**
+ * Deafens/undeafens the member of this voice state.
+ * @param {boolean} deaf Whether or not the member should be deafened
+ * @param {string} [reason] Reason for deafening or undeafening
+ * @returns {Promise<GuildMember>}
+ */
+ setDeaf(deaf, reason) {
+ return this.member ? this.member.edit({ deaf }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER'));
+ }
+
+ /**
+ * Kicks the member from the voice channel.
+ * @param {string} [reason] Reason for kicking member from the channel
+ * @returns {Promise<GuildMember>}
+ */
+ kick(reason) {
+ return this.setChannel(null, reason);
+ }
+
+ /**
+ * Moves the member to a different channel, or disconnects them from the one they're in.
+ * @param {ChannelResolvable|null} [channel] Channel to move the member to, or `null` if you want to disconnect them
+ * from voice. Requires the `MOVE_MEMBERS` permission.
+ * @param {string} [reason] Reason for moving member to another channel or disconnecting
+ * @returns {Promise<GuildMember>}
+ */
+ setChannel(channel, reason) {
+ return this.member
+ ? this.member.edit({ channel }, reason)
+ : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER'));
+ }
+
+ /**
+ * Self-mutes/unmutes the bot for this voice state.
+ * @param {boolean} mute Whether or not the bot should be self-muted
+ * @returns {Promise<boolean>} true if the voice state was successfully updated, otherwise false
+ */
+ async setSelfMute(mute) {
+ if (this.id !== this.client.user.id) throw new Error('VOICE_STATE_NOT_OWN');
+ if (typeof mute !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'mute');
+ if (!this.connection) return false;
+ this.selfMute = mute;
+ await this.connection.sendVoiceStateUpdate();
+ return true;
+ }
+
+ /**
+ * Self-deafens/undeafens the bot for this voice state.
+ * @param {boolean} deaf Whether or not the bot should be self-deafened
+ * @returns {Promise<boolean>} true if the voice state was successfully updated, otherwise false
+ */
+ async setSelfDeaf(deaf) {
+ if (this.id !== this.client.user.id) return new Error('VOICE_STATE_NOT_OWN');
+ if (typeof deaf !== 'boolean') return new TypeError('VOICE_STATE_INVALID_TYPE', 'deaf');
+ if (!this.connection) return false;
+ this.selfDeaf = deaf;
+ await this.connection.sendVoiceStateUpdate();
+ return true;
+ }
+
+ toJSON() {
+ return super.toJSON({
+ id: true,
+ serverDeaf: true,
+ serverMute: true,
+ selfDeaf: true,
+ selfMute: true,
+ sessionID: true,
+ channelID: 'channel',
+ });
+ }
+}
+
+module.exports = VoiceState;
diff --git a/node_modules/discord.js/src/structures/Webhook.js b/node_modules/discord.js/src/structures/Webhook.js
new file mode 100644
index 0000000..b9aed9d
--- /dev/null
+++ b/node_modules/discord.js/src/structures/Webhook.js
@@ -0,0 +1,273 @@
+'use strict';
+
+const APIMessage = require('./APIMessage');
+const Channel = require('./Channel');
+const { WebhookTypes } = require('../util/Constants');
+const DataResolver = require('../util/DataResolver');
+const Snowflake = require('../util/Snowflake');
+
+/**
+ * Represents a webhook.
+ */
+class Webhook {
+ constructor(client, data) {
+ /**
+ * The client that instantiated the webhook
+ * @name Webhook#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+ if (data) this._patch(data);
+ }
+
+ _patch(data) {
+ /**
+ * The name of the webhook
+ * @type {string}
+ */
+ this.name = data.name;
+
+ /**
+ * The token for the webhook
+ * @name Webhook#token
+ * @type {?string}
+ */
+ Object.defineProperty(this, 'token', { value: data.token || null, writable: true, configurable: true });
+
+ /**
+ * The avatar for the webhook
+ * @type {?string}
+ */
+ this.avatar = data.avatar;
+
+ /**
+ * The ID of the webhook
+ * @type {Snowflake}
+ */
+ this.id = data.id;
+
+ /**
+ * The type of the webhook
+ * @type {WebhookTypes}
+ */
+ this.type = WebhookTypes[data.type];
+
+ /**
+ * The guild the webhook belongs to
+ * @type {Snowflake}
+ */
+ this.guildID = data.guild_id;
+
+ /**
+ * The channel the webhook belongs to
+ * @type {Snowflake}
+ */
+ this.channelID = data.channel_id;
+
+ if (data.user) {
+ /**
+ * The owner of the webhook
+ * @type {?User|Object}
+ */
+ this.owner = this.client.users ? this.client.users.cache.get(data.user.id) : data.user;
+ } else {
+ this.owner = null;
+ }
+ }
+
+ /**
+ * Options that can be passed into send.
+ * @typedef {Object} WebhookMessageOptions
+ * @property {string} [username=this.name] Username override for the message
+ * @property {string} [avatarURL] Avatar URL override for the message
+ * @property {boolean} [tts=false] Whether or not the message should be spoken aloud
+ * @property {string} [nonce=''] The nonce for the message
+ * @property {Object[]} [embeds] An array of embeds for the message
+ * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
+ * (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
+ * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or
+ * everyone/here mentions should be sanitized to prevent unexpected mentions
+ * @property {FileOptions[]|string[]} [files] Files to send with the message
+ * @property {string|boolean} [code] Language for optional codeblock formatting to apply
+ * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
+ * it exceeds the character limit. If an object is provided, these are the options for splitting the message.
+ */
+
+ /**
+ * Sends a message with this webhook.
+ * @param {StringResolvable|APIMessage} [content=''] The content to send
+ * @param {WebhookMessageOptions|MessageAdditions} [options={}] The options to provide
+ * @returns {Promise<Message|Object>}
+ * @example
+ * // Send a basic message
+ * webhook.send('hello!')
+ * .then(message => console.log(`Sent message: ${message.content}`))
+ * .catch(console.error);
+ * @example
+ * // Send a remote file
+ * webhook.send({
+ * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048']
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Send a local file
+ * webhook.send({
+ * files: [{
+ * attachment: 'entire/path/to/file.jpg',
+ * name: 'file.jpg'
+ * }]
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Send an embed with a local image inside
+ * webhook.send('This is an embed', {
+ * embeds: [{
+ * thumbnail: {
+ * url: 'attachment://file.jpg'
+ * }
+ * }],
+ * files: [{
+ * attachment: 'entire/path/to/file.jpg',
+ * name: 'file.jpg'
+ * }]
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ async send(content, options) {
+ let apiMessage;
+
+ if (content instanceof APIMessage) {
+ apiMessage = content.resolveData();
+ } else {
+ apiMessage = APIMessage.create(this, content, options).resolveData();
+ if (Array.isArray(apiMessage.data.content)) {
+ return Promise.all(apiMessage.split().map(this.send.bind(this)));
+ }
+ }
+
+ const { data, files } = await apiMessage.resolveFiles();
+ return this.client.api
+ .webhooks(this.id, this.token)
+ .post({
+ data,
+ files,
+ query: { wait: true },
+ auth: false,
+ })
+ .then(d => {
+ const channel = this.client.channels ? this.client.channels.cache.get(d.channel_id) : undefined;
+ if (!channel) return d;
+ return channel.messages.add(d, false);
+ });
+ }
+
+ /**
+ * Sends a raw slack message with this webhook.
+ * @param {Object} body The raw body to send
+ * @returns {Promise<boolean>}
+ * @example
+ * // Send a slack message
+ * webhook.sendSlackMessage({
+ * 'username': 'Wumpus',
+ * 'attachments': [{
+ * 'pretext': 'this looks pretty cool',
+ * 'color': '#F0F',
+ * 'footer_icon': 'http://snek.s3.amazonaws.com/topSnek.png',
+ * 'footer': 'Powered by sneks',
+ * 'ts': Date.now() / 1000
+ * }]
+ * }).catch(console.error);
+ */
+ sendSlackMessage(body) {
+ return this.client.api
+ .webhooks(this.id, this.token)
+ .slack.post({
+ query: { wait: true },
+ auth: false,
+ data: body,
+ })
+ .then(data => data.toString() === 'ok');
+ }
+
+ /**
+ * Edits the webhook.
+ * @param {Object} options Options
+ * @param {string} [options.name=this.name] New name for this webhook
+ * @param {BufferResolvable} [options.avatar] New avatar for this webhook
+ * @param {ChannelResolvable} [options.channel] New channel for this webhook
+ * @param {string} [reason] Reason for editing this webhook
+ * @returns {Promise<Webhook>}
+ */
+ async edit({ name = this.name, avatar, channel }, reason) {
+ if (avatar && typeof avatar === 'string' && !avatar.startsWith('data:')) {
+ avatar = await DataResolver.resolveImage(avatar);
+ }
+ if (channel) channel = channel instanceof Channel ? channel.id : channel;
+ const data = await this.client.api.webhooks(this.id, channel ? undefined : this.token).patch({
+ data: { name, avatar, channel_id: channel },
+ reason,
+ });
+
+ this.name = data.name;
+ this.avatar = data.avatar;
+ this.channelID = data.channel_id;
+ return this;
+ }
+
+ /**
+ * Deletes the webhook.
+ * @param {string} [reason] Reason for deleting this webhook
+ * @returns {Promise}
+ */
+ delete(reason) {
+ return this.client.api.webhooks(this.id, this.token).delete({ reason });
+ }
+ /**
+ * The timestamp the webhook was created at
+ * @type {number}
+ * @readonly
+ */
+ get createdTimestamp() {
+ return Snowflake.deconstruct(this.id).timestamp;
+ }
+
+ /**
+ * The time the webhook was created at
+ * @type {Date}
+ * @readonly
+ */
+ get createdAt() {
+ return new Date(this.createdTimestamp);
+ }
+
+ /**
+ * The url of this webhook
+ * @type {string}
+ * @readonly
+ */
+ get url() {
+ return this.client.options.http.api + this.client.api.webhooks(this.id, this.token);
+ }
+
+ /**
+ * A link to the webhook's avatar.
+ * @param {ImageURLOptions} [options={}] Options for the Image URL
+ * @returns {?string}
+ */
+ avatarURL({ format, size } = {}) {
+ if (!this.avatar) return null;
+ return this.client.rest.cdn.Avatar(this.id, this.avatar, format, size);
+ }
+
+ static applyToClass(structure) {
+ for (const prop of ['send', 'sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt', 'url']) {
+ Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop));
+ }
+ }
+}
+
+module.exports = Webhook;
diff --git a/node_modules/discord.js/src/structures/interfaces/Collector.js b/node_modules/discord.js/src/structures/interfaces/Collector.js
new file mode 100644
index 0000000..21d01ca
--- /dev/null
+++ b/node_modules/discord.js/src/structures/interfaces/Collector.js
@@ -0,0 +1,281 @@
+'use strict';
+
+const EventEmitter = require('events');
+const Collection = require('../../util/Collection');
+const Util = require('../../util/Util');
+
+/**
+ * Filter to be applied to the collector.
+ * @typedef {Function} CollectorFilter
+ * @param {...*} args Any arguments received by the listener
+ * @param {Collection} collection The items collected by this collector
+ * @returns {boolean}
+ */
+
+/**
+ * Options to be applied to the collector.
+ * @typedef {Object} CollectorOptions
+ * @property {number} [time] How long to run the collector for in milliseconds
+ * @property {number} [idle] How long to stop the collector after inactivity in milliseconds
+ * @property {boolean} [dispose=false] Whether to dispose data when it's deleted
+ */
+
+/**
+ * Abstract class for defining a new Collector.
+ * @abstract
+ */
+class Collector extends EventEmitter {
+ constructor(client, filter, options = {}) {
+ super();
+
+ /**
+ * The client that instantiated this Collector
+ * @name Collector#client
+ * @type {Client}
+ * @readonly
+ */
+ Object.defineProperty(this, 'client', { value: client });
+
+ /**
+ * The filter applied to this collector
+ * @type {CollectorFilter}
+ */
+ this.filter = filter;
+
+ /**
+ * The options of this collector
+ * @type {CollectorOptions}
+ */
+ this.options = options;
+
+ /**
+ * The items collected by this collector
+ * @type {Collection}
+ */
+ this.collected = new Collection();
+
+ /**
+ * Whether this collector has finished collecting
+ * @type {boolean}
+ */
+ this.ended = false;
+
+ /**
+ * Timeout for cleanup
+ * @type {?Timeout}
+ * @private
+ */
+ this._timeout = null;
+
+ /**
+ * Timeout for cleanup due to inactivity
+ * @type {?Timeout}
+ * @private
+ */
+ this._idletimeout = null;
+
+ this.handleCollect = this.handleCollect.bind(this);
+ this.handleDispose = this.handleDispose.bind(this);
+
+ if (options.time) this._timeout = this.client.setTimeout(() => this.stop('time'), options.time);
+ if (options.idle) this._idletimeout = this.client.setTimeout(() => this.stop('idle'), options.idle);
+ }
+
+ /**
+ * Call this to handle an event as a collectable element. Accepts any event data as parameters.
+ * @param {...*} args The arguments emitted by the listener
+ * @emits Collector#collect
+ */
+ handleCollect(...args) {
+ const collect = this.collect(...args);
+
+ if (collect && this.filter(...args, this.collected)) {
+ this.collected.set(collect, args[0]);
+
+ /**
+ * Emitted whenever an element is collected.
+ * @event Collector#collect
+ * @param {...*} args The arguments emitted by the listener
+ */
+ this.emit('collect', ...args);
+
+ if (this._idletimeout) {
+ this.client.clearTimeout(this._idletimeout);
+ this._idletimeout = this.client.setTimeout(() => this.stop('idle'), this.options.idle);
+ }
+ }
+ this.checkEnd();
+ }
+
+ /**
+ * Call this to remove an element from the collection. Accepts any event data as parameters.
+ * @param {...*} args The arguments emitted by the listener
+ * @emits Collector#dispose
+ */
+ handleDispose(...args) {
+ if (!this.options.dispose) return;
+
+ const dispose = this.dispose(...args);
+ if (!dispose || !this.filter(...args) || !this.collected.has(dispose)) return;
+ this.collected.delete(dispose);
+
+ /**
+ * Emitted whenever an element is disposed of.
+ * @event Collector#dispose
+ * @param {...*} args The arguments emitted by the listener
+ */
+ this.emit('dispose', ...args);
+ this.checkEnd();
+ }
+
+ /**
+ * Returns a promise that resolves with the next collected element;
+ * rejects with collected elements if the collector finishes without receiving a next element
+ * @type {Promise}
+ * @readonly
+ */
+ get next() {
+ return new Promise((resolve, reject) => {
+ if (this.ended) {
+ reject(this.collected);
+ return;
+ }
+
+ const cleanup = () => {
+ this.removeListener('collect', onCollect);
+ this.removeListener('end', onEnd);
+ };
+
+ const onCollect = item => {
+ cleanup();
+ resolve(item);
+ };
+
+ const onEnd = () => {
+ cleanup();
+ reject(this.collected); // eslint-disable-line prefer-promise-reject-errors
+ };
+
+ this.on('collect', onCollect);
+ this.on('end', onEnd);
+ });
+ }
+
+ /**
+ * Stops this collector and emits the `end` event.
+ * @param {string} [reason='user'] The reason this collector is ending
+ * @emits Collector#end
+ */
+ stop(reason = 'user') {
+ if (this.ended) return;
+
+ if (this._timeout) {
+ this.client.clearTimeout(this._timeout);
+ this._timeout = null;
+ }
+ if (this._idletimeout) {
+ this.client.clearTimeout(this._idletimeout);
+ this._idletimeout = null;
+ }
+ this.ended = true;
+
+ /**
+ * Emitted when the collector is finished collecting.
+ * @event Collector#end
+ * @param {Collection} collected The elements collected by the collector
+ * @param {string} reason The reason the collector ended
+ */
+ this.emit('end', this.collected, reason);
+ }
+
+ /**
+ * Resets the collectors timeout and idle timer.
+ * @param {Object} [options] Options
+ * @param {number} [options.time] How long to run the collector for in milliseconds
+ * @param {number} [options.idle] How long to stop the collector after inactivity in milliseconds
+ */
+ resetTimer({ time, idle } = {}) {
+ if (this._timeout) {
+ this.client.clearTimeout(this._timeout);
+ this._timeout = this.client.setTimeout(() => this.stop('time'), time || this.options.time);
+ }
+ if (this._idletimeout) {
+ this.client.clearTimeout(this._idletimeout);
+ this._idletimeout = this.client.setTimeout(() => this.stop('idle'), idle || this.options.idle);
+ }
+ }
+
+ /**
+ * Checks whether the collector should end, and if so, ends it.
+ */
+ checkEnd() {
+ const reason = this.endReason();
+ if (reason) this.stop(reason);
+ }
+
+ /**
+ * Allows collectors to be consumed with for-await-of loops
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of}
+ */
+ async *[Symbol.asyncIterator]() {
+ const queue = [];
+ const onCollect = item => queue.push(item);
+ this.on('collect', onCollect);
+
+ try {
+ while (queue.length || !this.ended) {
+ if (queue.length) {
+ yield queue.shift();
+ } else {
+ // eslint-disable-next-line no-await-in-loop
+ await new Promise(resolve => {
+ const tick = () => {
+ this.removeListener('collect', tick);
+ this.removeListener('end', tick);
+ return resolve();
+ };
+ this.on('collect', tick);
+ this.on('end', tick);
+ });
+ }
+ }
+ } finally {
+ this.removeListener('collect', onCollect);
+ }
+ }
+
+ toJSON() {
+ return Util.flatten(this);
+ }
+
+ /* eslint-disable no-empty-function, valid-jsdoc */
+ /**
+ * Handles incoming events from the `handleCollect` function. Returns null if the event should not
+ * be collected, or returns an object describing the data that should be stored.
+ * @see Collector#handleCollect
+ * @param {...*} args Any args the event listener emits
+ * @returns {?{key, value}} Data to insert into collection, if any
+ * @abstract
+ */
+ collect() {}
+
+ /**
+ * Handles incoming events from the `handleDispose`. Returns null if the event should not
+ * be disposed, or returns the key that should be removed.
+ * @see Collector#handleDispose
+ * @param {...*} args Any args the event listener emits
+ * @returns {?*} Key to remove from the collection, if any
+ * @abstract
+ */
+ dispose() {}
+
+ /**
+ * The reason this collector has ended or will end with.
+ * @returns {?string} Reason to end the collector, if any
+ * @abstract
+ */
+ endReason() {}
+ /* eslint-enable no-empty-function, valid-jsdoc */
+}
+
+module.exports = Collector;
diff --git a/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js
new file mode 100644
index 0000000..b63c92a
--- /dev/null
+++ b/node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js
@@ -0,0 +1,396 @@
+'use strict';
+
+/* eslint-disable import/order */
+const MessageCollector = require('../MessageCollector');
+const APIMessage = require('../APIMessage');
+const Snowflake = require('../../util/Snowflake');
+const Collection = require('../../util/Collection');
+const { RangeError, TypeError } = require('../../errors');
+
+/**
+ * Interface for classes that have text-channel-like features.
+ * @interface
+ */
+class TextBasedChannel {
+ constructor() {
+ /**
+ * A manager of the messages sent to this channel
+ * @type {MessageManager}
+ */
+ this.messages = new MessageManager(this);
+
+ /**
+ * The ID of the last message in the channel, if one was sent
+ * @type {?Snowflake}
+ */
+ this.lastMessageID = null;
+
+ /**
+ * The timestamp when the last pinned message was pinned, if there was one
+ * @type {?number}
+ */
+ this.lastPinTimestamp = null;
+ }
+
+ /**
+ * The Message object of the last message in the channel, if one was sent
+ * @type {?Message}
+ * @readonly
+ */
+ get lastMessage() {
+ return this.messages.cache.get(this.lastMessageID) || null;
+ }
+
+ /**
+ * The date when the last pinned message was pinned, if there was one
+ * @type {?Date}
+ * @readonly
+ */
+ get lastPinAt() {
+ return this.lastPinTimestamp ? new Date(this.lastPinTimestamp) : null;
+ }
+
+ /**
+ * Options provided when sending or editing a message.
+ * @typedef {Object} MessageOptions
+ * @property {boolean} [tts=false] Whether or not the message should be spoken aloud
+ * @property {string} [nonce=''] The nonce for the message
+ * @property {string} [content=''] The content for the message
+ * @property {MessageEmbed|Object} [embed] An embed for the message
+ * (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
+ * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
+ * @property {DisableMentionType} [disableMentions=this.client.options.disableMentions] Whether or not all mentions or
+ * everyone/here mentions should be sanitized to prevent unexpected mentions
+ * @property {FileOptions[]|BufferResolvable[]} [files] Files to send with the message
+ * @property {string|boolean} [code] Language for optional codeblock formatting to apply
+ * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
+ * it exceeds the character limit. If an object is provided, these are the options for splitting the message
+ * @property {UserResolvable} [reply] User to reply to (prefixes the message with a mention, except in DMs)
+ */
+
+ /**
+ * Options provided to control parsing of mentions by Discord
+ * @typedef {Object} MessageMentionOptions
+ * @property {MessageMentionTypes[]} [parse] Types of mentions to be parsed
+ * @property {Snowflake[]} [users] Snowflakes of Users to be parsed as mentions
+ * @property {Snowflake[]} [roles] Snowflakes of Roles to be parsed as mentions
+ */
+
+ /**
+ * Types of mentions to enable in MessageMentionOptions.
+ * - `roles`
+ * - `users`
+ * - `everyone`
+ * @typedef {string} MessageMentionTypes
+ */
+
+ /**
+ * The type of mentions to disable.
+ * - `none`
+ * - `all`
+ * - `everyone`
+ * @typedef {string} DisableMentionType
+ */
+
+ /**
+ * @typedef {Object} FileOptions
+ * @property {BufferResolvable} attachment File to attach
+ * @property {string} [name='file.jpg'] Filename of the attachment
+ */
+
+ /**
+ * Options for splitting a message.
+ * @typedef {Object} SplitOptions
+ * @property {number} [maxLength=2000] Maximum character length per message piece
+ * @property {string} [char='\n'] Character to split the message with
+ * @property {string} [prepend=''] Text to prepend to every piece except the first
+ * @property {string} [append=''] Text to append to every piece except the last
+ */
+
+ /**
+ * Sends a message to this channel.
+ * @param {StringResolvable|APIMessage} [content=''] The content to send
+ * @param {MessageOptions|MessageAdditions} [options={}] The options to provide
+ * @returns {Promise<Message|Message[]>}
+ * @example
+ * // Send a basic message
+ * channel.send('hello!')
+ * .then(message => console.log(`Sent message: ${message.content}`))
+ * .catch(console.error);
+ * @example
+ * // Send a remote file
+ * channel.send({
+ * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048']
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Send a local file
+ * channel.send({
+ * files: [{
+ * attachment: 'entire/path/to/file.jpg',
+ * name: 'file.jpg'
+ * }]
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ * @example
+ * // Send an embed with a local image inside
+ * channel.send('This is an embed', {
+ * embed: {
+ * thumbnail: {
+ * url: 'attachment://file.jpg'
+ * }
+ * },
+ * files: [{
+ * attachment: 'entire/path/to/file.jpg',
+ * name: 'file.jpg'
+ * }]
+ * })
+ * .then(console.log)
+ * .catch(console.error);
+ */
+ async send(content, options) {
+ const User = require('../User');
+ const GuildMember = require('../GuildMember');
+
+ if (this instanceof User || this instanceof GuildMember) {
+ return this.createDM().then(dm => dm.send(content, options));
+ }
+
+ let apiMessage;
+
+ if (content instanceof APIMessage) {
+ apiMessage = content.resolveData();
+ } else {
+ apiMessage = APIMessage.create(this, content, options).resolveData();
+ if (Array.isArray(apiMessage.data.content)) {
+ return Promise.all(apiMessage.split().map(this.send.bind(this)));
+ }
+ }
+
+ const { data, files } = await apiMessage.resolveFiles();
+ return this.client.api.channels[this.id].messages
+ .post({ data, files })
+ .then(d => this.client.actions.MessageCreate.handle(d).message);
+ }
+
+ /**
+ * Starts a typing indicator in the channel.
+ * @param {number} [count=1] The number of times startTyping should be considered to have been called
+ * @returns {Promise} Resolves once the bot stops typing gracefully, or rejects when an error occurs
+ * @example
+ * // Start typing in a channel, or increase the typing count by one
+ * channel.startTyping();
+ * @example
+ * // Start typing in a channel with a typing count of five, or set it to five
+ * channel.startTyping(5);
+ */
+ startTyping(count) {
+ if (typeof count !== 'undefined' && count < 1) throw new RangeError('TYPING_COUNT');
+ if (this.client.user._typing.has(this.id)) {
+ const entry = this.client.user._typing.get(this.id);
+ entry.count = count || entry.count + 1;
+ return entry.promise;
+ }
+
+ const entry = {};
+ entry.promise = new Promise((resolve, reject) => {
+ const endpoint = this.client.api.channels[this.id].typing;
+ Object.assign(entry, {
+ count: count || 1,
+ interval: this.client.setInterval(() => {
+ endpoint.post().catch(error => {
+ this.client.clearInterval(entry.interval);
+ this.client.user._typing.delete(this.id);
+ reject(error);
+ });
+ }, 9000),
+ resolve,
+ });
+ endpoint.post().catch(error => {
+ this.client.clearInterval(entry.interval);
+ this.client.user._typing.delete(this.id);
+ reject(error);
+ });
+ this.client.user._typing.set(this.id, entry);
+ });
+ return entry.promise;
+ }
+
+ /**
+ * Stops the typing indicator in the channel.
+ * The indicator will only stop if this is called as many times as startTyping().
+ * <info>It can take a few seconds for the client user to stop typing.</info>
+ * @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop
+ * @example
+ * // Reduce the typing count by one and stop typing if it reached 0
+ * channel.stopTyping();
+ * @example
+ * // Force typing to fully stop regardless of typing count
+ * channel.stopTyping(true);
+ */
+ stopTyping(force = false) {
+ if (this.client.user._typing.has(this.id)) {
+ const entry = this.client.user._typing.get(this.id);
+ entry.count--;
+ if (entry.count <= 0 || force) {
+ this.client.clearInterval(entry.interval);
+ this.client.user._typing.delete(this.id);
+ entry.resolve();
+ }
+ }
+ }
+
+ /**
+ * Whether or not the typing indicator is being shown in the channel
+ * @type {boolean}
+ * @readonly
+ */
+ get typing() {
+ return this.client.user._typing.has(this.id);
+ }
+
+ /**
+ * Number of times `startTyping` has been called
+ * @type {number}
+ * @readonly
+ */
+ get typingCount() {
+ if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count;
+ return 0;
+ }
+
+ /**
+ * Creates a Message Collector.
+ * @param {CollectorFilter} filter The filter to create the collector with
+ * @param {MessageCollectorOptions} [options={}] The options to pass to the collector
+ * @returns {MessageCollector}
+ * @example
+ * // Create a message collector
+ * const filter = m => m.content.includes('discord');
+ * const collector = channel.createMessageCollector(filter, { time: 15000 });
+ * collector.on('collect', m => console.log(`Collected ${m.content}`));
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
+ */
+ createMessageCollector(filter, options = {}) {
+ return new MessageCollector(this, filter, options);
+ }
+
+ /**
+ * An object containing the same properties as CollectorOptions, but a few more:
+ * @typedef {MessageCollectorOptions} AwaitMessagesOptions
+ * @property {string[]} [errors] Stop/end reasons that cause the promise to reject
+ */
+
+ /**
+ * Similar to createMessageCollector but in promise form.
+ * Resolves with a collection of messages that pass the specified filter.
+ * @param {CollectorFilter} filter The filter function to use
+ * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector
+ * @returns {Promise<Collection<Snowflake, Message>>}
+ * @example
+ * // Await !vote messages
+ * const filter = m => m.content.startsWith('!vote');
+ * // Errors: ['time'] treats ending because of the time limit as an error
+ * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] })
+ * .then(collected => console.log(collected.size))
+ * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`));
+ */
+ awaitMessages(filter, options = {}) {
+ return new Promise((resolve, reject) => {
+ const collector = this.createMessageCollector(filter, options);
+ collector.once('end', (collection, reason) => {
+ if (options.errors && options.errors.includes(reason)) {
+ reject(collection);
+ } else {
+ resolve(collection);
+ }
+ });
+ });
+ }
+
+ /**
+ * Bulk deletes given messages that are newer than two weeks.
+ * @param {Collection<Snowflake, Message>|Message[]|Snowflake[]|number} messages
+ * Messages or number of messages to delete
+ * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically
+ * @returns {Promise<Collection<Snowflake, Message>>} Deleted messages
+ * @example
+ * // Bulk delete messages
+ * channel.bulkDelete(5)
+ * .then(messages => console.log(`Bulk deleted ${messages.size} messages`))
+ * .catch(console.error);
+ */
+ async bulkDelete(messages, filterOld = false) {
+ if (Array.isArray(messages) || messages instanceof Collection) {
+ let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m);
+ if (filterOld) {
+ messageIDs = messageIDs.filter(id => Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000);
+ }
+ if (messageIDs.length === 0) return new Collection();
+ if (messageIDs.length === 1) {
+ await this.client.api
+ .channels(this.id)
+ .messages(messageIDs[0])
+ .delete();
+ const message = this.client.actions.MessageDelete.getMessage(
+ {
+ message_id: messageIDs[0],
+ },
+ this,
+ );
+ return message ? new Collection([[message.id, message]]) : new Collection();
+ }
+ await this.client.api.channels[this.id].messages['bulk-delete'].post({ data: { messages: messageIDs } });
+ return messageIDs.reduce(
+ (col, id) =>
+ col.set(
+ id,
+ this.client.actions.MessageDeleteBulk.getMessage(
+ {
+ message_id: id,
+ },
+ this,
+ ),
+ ),
+ new Collection(),
+ );
+ }
+ if (!isNaN(messages)) {
+ const msgs = await this.messages.fetch({ limit: messages });
+ return this.bulkDelete(msgs, filterOld);
+ }
+ throw new TypeError('MESSAGE_BULK_DELETE_TYPE');
+ }
+
+ static applyToClass(structure, full = false, ignore = []) {
+ const props = ['send'];
+ if (full) {
+ props.push(
+ 'lastMessage',
+ 'lastPinAt',
+ 'bulkDelete',
+ 'startTyping',
+ 'stopTyping',
+ 'typing',
+ 'typingCount',
+ 'createMessageCollector',
+ 'awaitMessages',
+ );
+ }
+ for (const prop of props) {
+ if (ignore.includes(prop)) continue;
+ Object.defineProperty(
+ structure.prototype,
+ prop,
+ Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop),
+ );
+ }
+ }
+}
+
+module.exports = TextBasedChannel;
+
+// Fixes Circular
+const MessageManager = require('../../managers/MessageManager');
diff --git a/node_modules/discord.js/src/util/ActivityFlags.js b/node_modules/discord.js/src/util/ActivityFlags.js
new file mode 100644
index 0000000..40c9e7e
--- /dev/null
+++ b/node_modules/discord.js/src/util/ActivityFlags.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with an {@link Activity#flags} bitfield.
+ * @extends {BitField}
+ */
+class ActivityFlags extends BitField {}
+
+/**
+ * @name ActivityFlags
+ * @kind constructor
+ * @memberof ActivityFlags
+ * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Numeric activity flags. All available properties:
+ * * `INSTANCE`
+ * * `JOIN`
+ * * `SPECTATE`
+ * * `JOIN_REQUEST`
+ * * `SYNC`
+ * * `PLAY`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/topics/gateway#activity-object-activity-flags}
+ */
+ActivityFlags.FLAGS = {
+ INSTANCE: 1 << 0,
+ JOIN: 1 << 1,
+ SPECTATE: 1 << 2,
+ JOIN_REQUEST: 1 << 3,
+ SYNC: 1 << 4,
+ PLAY: 1 << 5,
+};
+
+module.exports = ActivityFlags;
diff --git a/node_modules/discord.js/src/util/BitField.js b/node_modules/discord.js/src/util/BitField.js
new file mode 100644
index 0000000..ec1f8dc
--- /dev/null
+++ b/node_modules/discord.js/src/util/BitField.js
@@ -0,0 +1,162 @@
+'use strict';
+
+const { RangeError } = require('../errors');
+
+/**
+ * Data structure that makes it easy to interact with a bitfield.
+ */
+class BitField {
+ /**
+ * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
+ */
+ constructor(bits) {
+ /**
+ * Bitfield of the packed bits
+ * @type {number}
+ */
+ this.bitfield = this.constructor.resolve(bits);
+ }
+
+ /**
+ * Checks whether the bitfield has a bit, or any of multiple bits.
+ * @param {BitFieldResolvable} bit Bit(s) to check for
+ * @returns {boolean}
+ */
+ any(bit) {
+ return (this.bitfield & this.constructor.resolve(bit)) !== 0;
+ }
+
+ /**
+ * Checks if this bitfield equals another
+ * @param {BitFieldResolvable} bit Bit(s) to check for
+ * @returns {boolean}
+ */
+ equals(bit) {
+ return this.bitfield === this.constructor.resolve(bit);
+ }
+
+ /**
+ * Checks whether the bitfield has a bit, or multiple bits.
+ * @param {BitFieldResolvable} bit Bit(s) to check for
+ * @returns {boolean}
+ */
+ has(bit) {
+ if (Array.isArray(bit)) return bit.every(p => this.has(p));
+ bit = this.constructor.resolve(bit);
+ return (this.bitfield & bit) === bit;
+ }
+
+ /**
+ * Gets all given bits that are missing from the bitfield.
+ * @param {BitFieldResolvable} bits Bit(s) to check for
+ * @param {...*} hasParams Additional parameters for the has method, if any
+ * @returns {string[]}
+ */
+ missing(bits, ...hasParams) {
+ if (!Array.isArray(bits)) bits = new this.constructor(bits).toArray(false);
+ return bits.filter(p => !this.has(p, ...hasParams));
+ }
+
+ /**
+ * Freezes these bits, making them immutable.
+ * @returns {Readonly<BitField>} These bits
+ */
+ freeze() {
+ return Object.freeze(this);
+ }
+
+ /**
+ * Adds bits to these ones.
+ * @param {...BitFieldResolvable} [bits] Bits to add
+ * @returns {BitField} These bits or new BitField if the instance is frozen.
+ */
+ add(...bits) {
+ let total = 0;
+ for (const bit of bits) {
+ total |= this.constructor.resolve(bit);
+ }
+ if (Object.isFrozen(this)) return new this.constructor(this.bitfield | total);
+ this.bitfield |= total;
+ return this;
+ }
+
+ /**
+ * Removes bits from these.
+ * @param {...BitFieldResolvable} [bits] Bits to remove
+ * @returns {BitField} These bits or new BitField if the instance is frozen.
+ */
+ remove(...bits) {
+ let total = 0;
+ for (const bit of bits) {
+ total |= this.constructor.resolve(bit);
+ }
+ if (Object.isFrozen(this)) return new this.constructor(this.bitfield & ~total);
+ this.bitfield &= ~total;
+ return this;
+ }
+
+ /**
+ * Gets an object mapping field names to a {@link boolean} indicating whether the
+ * bit is available.
+ * @param {...*} hasParams Additional parameters for the has method, if any
+ * @returns {Object}
+ */
+ serialize(...hasParams) {
+ const serialized = {};
+ for (const [flag, bit] of Object.entries(this.constructor.FLAGS)) serialized[flag] = this.has(bit, ...hasParams);
+ return serialized;
+ }
+
+ /**
+ * Gets an {@link Array} of bitfield names based on the bits available.
+ * @param {...*} hasParams Additional parameters for the has method, if any
+ * @returns {string[]}
+ */
+ toArray(...hasParams) {
+ return Object.keys(this.constructor.FLAGS).filter(bit => this.has(bit, ...hasParams));
+ }
+
+ toJSON() {
+ return this.bitfield;
+ }
+
+ valueOf() {
+ return this.bitfield;
+ }
+
+ *[Symbol.iterator]() {
+ yield* this.toArray();
+ }
+
+ /**
+ * Data that can be resolved to give a bitfield. This can be:
+ * * A string (see {@link BitField.FLAGS})
+ * * A bit number
+ * * An instance of BitField
+ * * An Array of BitFieldResolvable
+ * @typedef {string|number|BitField|BitFieldResolvable[]} BitFieldResolvable
+ */
+
+ /**
+ * Resolves bitfields to their numeric form.
+ * @param {BitFieldResolvable} [bit=0] - bit(s) to resolve
+ * @returns {number}
+ */
+ static resolve(bit = 0) {
+ if (typeof bit === 'number' && bit >= 0) return bit;
+ if (bit instanceof BitField) return bit.bitfield;
+ if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0);
+ if (typeof bit === 'string' && typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit];
+ throw new RangeError('BITFIELD_INVALID');
+ }
+}
+
+/**
+ * Numeric bitfield flags.
+ * <info>Defined in extension classes</info>
+ * @type {Object}
+ * @abstract
+ */
+BitField.FLAGS = {};
+
+module.exports = BitField;
diff --git a/node_modules/discord.js/src/util/Collection.js b/node_modules/discord.js/src/util/Collection.js
new file mode 100644
index 0000000..3219fb8
--- /dev/null
+++ b/node_modules/discord.js/src/util/Collection.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const BaseCollection = require('@discordjs/collection');
+const Util = require('./Util');
+
+class Collection extends BaseCollection {
+ toJSON() {
+ return this.map(e => (typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e)));
+ }
+}
+
+module.exports = Collection;
+
+/**
+ * @external Collection
+ * @see {@link https://discord.js.org/#/docs/collection/master/class/Collection}
+ */
diff --git a/node_modules/discord.js/src/util/Constants.js b/node_modules/discord.js/src/util/Constants.js
new file mode 100644
index 0000000..74a58ff
--- /dev/null
+++ b/node_modules/discord.js/src/util/Constants.js
@@ -0,0 +1,650 @@
+'use strict';
+
+const Package = (exports.Package = require('../../package.json'));
+const { Error, RangeError } = require('../errors');
+const browser = (exports.browser = typeof window !== 'undefined');
+
+/**
+ * Options for a client.
+ * @typedef {Object} ClientOptions
+ * @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified,
+ * the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the
+ * recommended amount of shards from Discord and spawn that amount
+ * @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
+ * (e.g. recommended shard count, shard count of the ShardingManager)
+ * @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel
+ * (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb
+ * indefinitely)
+ * @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered
+ * sweepable (in seconds, 0 for forever)
+ * @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than
+ * the message cache lifetime (in seconds, 0 for never)
+ * @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as
+ * upon joining a guild (should be avoided whenever possible)
+ * @property {DisableMentionType} [disableMentions='none'] Default value for {@link MessageOptions#disableMentions}
+ * @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions}
+ * @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when
+ * they're missing all the data for a particular structure. See the "Partials" topic listed in the sidebar for some
+ * important usage information, as partials require you to put checks in place when handling data.
+ * @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their
+ * corresponding websocket events
+ * @property {number} [restTimeOffset=500] Extra time in millseconds to wait before continuing to make REST
+ * requests (higher values will reduce rate-limiting errors on bad connections)
+ * @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds
+ * @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds
+ * (or 0 for never)
+ * @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries)
+ * @property {PresenceData} [presence] Presence data to use upon login
+ * @property {WebsocketOptions} [ws] Options for the WebSocket
+ * @property {HTTPOptions} [http] HTTP options
+ */
+exports.DefaultOptions = {
+ shardCount: 1,
+ messageCacheMaxSize: 200,
+ messageCacheLifetime: 0,
+ messageSweepInterval: 0,
+ fetchAllMembers: false,
+ disableMentions: 'none',
+ partials: [],
+ restWsBridgeTimeout: 5000,
+ restRequestTimeout: 15000,
+ retryLimit: 1,
+ restTimeOffset: 500,
+ restSweepInterval: 60,
+ presence: {},
+
+ /**
+ * WebSocket options (these are left as snake_case to match the API)
+ * @typedef {Object} WebsocketOptions
+ * @property {number} [large_threshold=250] Number of members in a guild to be considered large
+ * @property {IntentsResolvable} [intents] Intents to enable for this connection
+ */
+ ws: {
+ large_threshold: 250,
+ compress: false,
+ properties: {
+ $os: browser ? 'browser' : process.platform,
+ $browser: 'discord.js',
+ $device: 'discord.js',
+ },
+ version: 6,
+ },
+
+ /**
+ * HTTP options
+ * @typedef {Object} HTTPOptions
+ * @property {number} [version=7] API version to use
+ * @property {string} [api='https://discordapp.com/api'] Base url of the API
+ * @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN
+ * @property {string} [invite='https://discord.gg'] Base url of invites
+ */
+ http: {
+ version: 7,
+ api: 'https://discordapp.com/api',
+ cdn: 'https://cdn.discordapp.com',
+ invite: 'https://discord.gg',
+ },
+};
+
+exports.UserAgent = browser
+ ? null
+ : `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`;
+
+exports.WSCodes = {
+ 1000: 'WS_CLOSE_REQUESTED',
+ 4004: 'TOKEN_INVALID',
+ 4010: 'SHARDING_INVALID',
+ 4011: 'SHARDING_REQUIRED',
+ 4013: 'INVALID_INTENTS',
+ 4014: 'DISALLOWED_INTENTS',
+};
+
+const AllowedImageFormats = ['webp', 'png', 'jpg', 'jpeg', 'gif'];
+
+const AllowedImageSizes = Array.from({ length: 9 }, (e, i) => 2 ** (i + 4));
+
+function makeImageUrl(root, { format = 'webp', size } = {}) {
+ if (format && !AllowedImageFormats.includes(format)) throw new Error('IMAGE_FORMAT', format);
+ if (size && !AllowedImageSizes.includes(size)) throw new RangeError('IMAGE_SIZE', size);
+ return `${root}.${format}${size ? `?size=${size}` : ''}`;
+}
+/**
+ * Options for Image URLs.
+ * @typedef {Object} ImageURLOptions
+ * @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided,
+ * defaults to `webp`.
+ * @property {boolean} [dynamic] If true, the format will dynamically change to `gif` for
+ * animated avatars; the default is false.
+ * @property {number} [size] One of `16`, `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096`
+ */
+
+exports.Endpoints = {
+ CDN(root) {
+ return {
+ Emoji: (emojiID, format = 'png') => `${root}/emojis/${emojiID}.${format}`,
+ Asset: name => `${root}/assets/${name}`,
+ DefaultAvatar: discriminator => `${root}/embed/avatars/${discriminator}.png`,
+ Avatar: (userID, hash, format = 'webp', size, dynamic = false) => {
+ if (dynamic) format = hash.startsWith('a_') ? 'gif' : format;
+ return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size });
+ },
+ Banner: (guildID, hash, format = 'webp', size) =>
+ makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }),
+ Icon: (guildID, hash, format = 'webp', size, dynamic = false) => {
+ if (dynamic) format = hash.startsWith('a_') ? 'gif' : format;
+ return makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size });
+ },
+ AppIcon: (clientID, hash, { format = 'webp', size } = {}) =>
+ makeImageUrl(`${root}/app-icons/${clientID}/${hash}`, { size, format }),
+ AppAsset: (clientID, hash, { format = 'webp', size } = {}) =>
+ makeImageUrl(`${root}/app-assets/${clientID}/${hash}`, { size, format }),
+ GDMIcon: (channelID, hash, format = 'webp', size) =>
+ makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }),
+ Splash: (guildID, hash, format = 'webp', size) =>
+ makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }),
+ DiscoverySplash: (guildID, hash, format = 'webp', size) =>
+ makeImageUrl(`${root}/discovery-splashes/${guildID}/${hash}`, { size, format }),
+ TeamIcon: (teamID, hash, { format = 'webp', size } = {}) =>
+ makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }),
+ };
+ },
+ invite: (root, code) => `${root}/${code}`,
+ botGateway: '/gateway/bot',
+};
+
+/**
+ * The current status of the client. Here are the available statuses:
+ * * READY: 0
+ * * CONNECTING: 1
+ * * RECONNECTING: 2
+ * * IDLE: 3
+ * * NEARLY: 4
+ * * DISCONNECTED: 5
+ * * WAITING_FOR_GUILDS: 6
+ * * IDENTIFYING: 7
+ * * RESUMING: 8
+ * @typedef {number} Status
+ */
+exports.Status = {
+ READY: 0,
+ CONNECTING: 1,
+ RECONNECTING: 2,
+ IDLE: 3,
+ NEARLY: 4,
+ DISCONNECTED: 5,
+ WAITING_FOR_GUILDS: 6,
+ IDENTIFYING: 7,
+ RESUMING: 8,
+};
+
+/**
+ * The current status of a voice connection. Here are the available statuses:
+ * * CONNECTED: 0
+ * * CONNECTING: 1
+ * * AUTHENTICATING: 2
+ * * RECONNECTING: 3
+ * * DISCONNECTED: 4
+ * @typedef {number} VoiceStatus
+ */
+exports.VoiceStatus = {
+ CONNECTED: 0,
+ CONNECTING: 1,
+ AUTHENTICATING: 2,
+ RECONNECTING: 3,
+ DISCONNECTED: 4,
+};
+
+exports.OPCodes = {
+ DISPATCH: 0,
+ HEARTBEAT: 1,
+ IDENTIFY: 2,
+ STATUS_UPDATE: 3,
+ VOICE_STATE_UPDATE: 4,
+ VOICE_GUILD_PING: 5,
+ RESUME: 6,
+ RECONNECT: 7,
+ REQUEST_GUILD_MEMBERS: 8,
+ INVALID_SESSION: 9,
+ HELLO: 10,
+ HEARTBEAT_ACK: 11,
+};
+
+exports.VoiceOPCodes = {
+ IDENTIFY: 0,
+ SELECT_PROTOCOL: 1,
+ READY: 2,
+ HEARTBEAT: 3,
+ SESSION_DESCRIPTION: 4,
+ SPEAKING: 5,
+ HELLO: 8,
+ CLIENT_CONNECT: 12,
+ CLIENT_DISCONNECT: 13,
+};
+
+exports.Events = {
+ RATE_LIMIT: 'rateLimit',
+ CLIENT_READY: 'ready',
+ GUILD_CREATE: 'guildCreate',
+ GUILD_DELETE: 'guildDelete',
+ GUILD_UPDATE: 'guildUpdate',
+ GUILD_UNAVAILABLE: 'guildUnavailable',
+ GUILD_AVAILABLE: 'guildAvailable',
+ GUILD_MEMBER_ADD: 'guildMemberAdd',
+ GUILD_MEMBER_REMOVE: 'guildMemberRemove',
+ GUILD_MEMBER_UPDATE: 'guildMemberUpdate',
+ GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable',
+ GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking',
+ GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
+ GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate',
+ GUILD_ROLE_CREATE: 'roleCreate',
+ GUILD_ROLE_DELETE: 'roleDelete',
+ INVITE_CREATE: 'inviteCreate',
+ INVITE_DELETE: 'inviteDelete',
+ GUILD_ROLE_UPDATE: 'roleUpdate',
+ GUILD_EMOJI_CREATE: 'emojiCreate',
+ GUILD_EMOJI_DELETE: 'emojiDelete',
+ GUILD_EMOJI_UPDATE: 'emojiUpdate',
+ GUILD_BAN_ADD: 'guildBanAdd',
+ GUILD_BAN_REMOVE: 'guildBanRemove',
+ CHANNEL_CREATE: 'channelCreate',
+ CHANNEL_DELETE: 'channelDelete',
+ CHANNEL_UPDATE: 'channelUpdate',
+ CHANNEL_PINS_UPDATE: 'channelPinsUpdate',
+ MESSAGE_CREATE: 'message',
+ MESSAGE_DELETE: 'messageDelete',
+ MESSAGE_UPDATE: 'messageUpdate',
+ MESSAGE_BULK_DELETE: 'messageDeleteBulk',
+ MESSAGE_REACTION_ADD: 'messageReactionAdd',
+ MESSAGE_REACTION_REMOVE: 'messageReactionRemove',
+ MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll',
+ MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji',
+ USER_UPDATE: 'userUpdate',
+ PRESENCE_UPDATE: 'presenceUpdate',
+ VOICE_SERVER_UPDATE: 'voiceServerUpdate',
+ VOICE_STATE_UPDATE: 'voiceStateUpdate',
+ VOICE_BROADCAST_SUBSCRIBE: 'subscribe',
+ VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe',
+ TYPING_START: 'typingStart',
+ TYPING_STOP: 'typingStop',
+ WEBHOOKS_UPDATE: 'webhookUpdate',
+ ERROR: 'error',
+ WARN: 'warn',
+ DEBUG: 'debug',
+ SHARD_DISCONNECT: 'shardDisconnect',
+ SHARD_ERROR: 'shardError',
+ SHARD_RECONNECTING: 'shardReconnecting',
+ SHARD_READY: 'shardReady',
+ SHARD_RESUME: 'shardResume',
+ INVALIDATED: 'invalidated',
+ RAW: 'raw',
+};
+
+exports.ShardEvents = {
+ CLOSE: 'close',
+ DESTROYED: 'destroyed',
+ INVALID_SESSION: 'invalidSession',
+ READY: 'ready',
+ RESUMED: 'resumed',
+ ALL_READY: 'allReady',
+};
+
+/**
+ * The type of Structure allowed to be a partial:
+ * * USER
+ * * CHANNEL (only affects DMChannels)
+ * * GUILD_MEMBER
+ * * MESSAGE
+ * * REACTION
+ * <warn>Partials require you to put checks in place when handling data, read the Partials topic listed in the
+ * sidebar for more information.</warn>
+ * @typedef {string} PartialType
+ */
+exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'REACTION']);
+
+/**
+ * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
+ * * READY
+ * * RESUMED
+ * * GUILD_CREATE
+ * * GUILD_DELETE
+ * * GUILD_UPDATE
+ * * INVITE_CREATE
+ * * INVITE_DELETE
+ * * GUILD_MEMBER_ADD
+ * * GUILD_MEMBER_REMOVE
+ * * GUILD_MEMBER_UPDATE
+ * * GUILD_MEMBERS_CHUNK
+ * * GUILD_INTEGRATIONS_UPDATE
+ * * GUILD_ROLE_CREATE
+ * * GUILD_ROLE_DELETE
+ * * GUILD_ROLE_UPDATE
+ * * GUILD_BAN_ADD
+ * * GUILD_BAN_REMOVE
+ * * GUILD_EMOJIS_UPDATE
+ * * CHANNEL_CREATE
+ * * CHANNEL_DELETE
+ * * CHANNEL_UPDATE
+ * * CHANNEL_PINS_UPDATE
+ * * MESSAGE_CREATE
+ * * MESSAGE_DELETE
+ * * MESSAGE_UPDATE
+ * * MESSAGE_DELETE_BULK
+ * * MESSAGE_REACTION_ADD
+ * * MESSAGE_REACTION_REMOVE
+ * * MESSAGE_REACTION_REMOVE_ALL
+ * * MESSAGE_REACTION_REMOVE_EMOJI
+ * * USER_UPDATE
+ * * PRESENCE_UPDATE
+ * * TYPING_START
+ * * VOICE_STATE_UPDATE
+ * * VOICE_SERVER_UPDATE
+ * * WEBHOOKS_UPDATE
+ * @typedef {string} WSEventType
+ */
+exports.WSEvents = keyMirror([
+ 'READY',
+ 'RESUMED',
+ 'GUILD_CREATE',
+ 'GUILD_DELETE',
+ 'GUILD_UPDATE',
+ 'INVITE_CREATE',
+ 'INVITE_DELETE',
+ 'GUILD_MEMBER_ADD',
+ 'GUILD_MEMBER_REMOVE',
+ 'GUILD_MEMBER_UPDATE',
+ 'GUILD_MEMBERS_CHUNK',
+ 'GUILD_INTEGRATIONS_UPDATE',
+ 'GUILD_ROLE_CREATE',
+ 'GUILD_ROLE_DELETE',
+ 'GUILD_ROLE_UPDATE',
+ 'GUILD_BAN_ADD',
+ 'GUILD_BAN_REMOVE',
+ 'GUILD_EMOJIS_UPDATE',
+ 'CHANNEL_CREATE',
+ 'CHANNEL_DELETE',
+ 'CHANNEL_UPDATE',
+ 'CHANNEL_PINS_UPDATE',
+ 'MESSAGE_CREATE',
+ 'MESSAGE_DELETE',
+ 'MESSAGE_UPDATE',
+ 'MESSAGE_DELETE_BULK',
+ 'MESSAGE_REACTION_ADD',
+ 'MESSAGE_REACTION_REMOVE',
+ 'MESSAGE_REACTION_REMOVE_ALL',
+ 'MESSAGE_REACTION_REMOVE_EMOJI',
+ 'USER_UPDATE',
+ 'PRESENCE_UPDATE',
+ 'TYPING_START',
+ 'VOICE_STATE_UPDATE',
+ 'VOICE_SERVER_UPDATE',
+ 'WEBHOOKS_UPDATE',
+]);
+
+/**
+ * The type of a message, e.g. `DEFAULT`. Here are the available types:
+ * * DEFAULT
+ * * RECIPIENT_ADD
+ * * RECIPIENT_REMOVE
+ * * CALL
+ * * CHANNEL_NAME_CHANGE
+ * * CHANNEL_ICON_CHANGE
+ * * PINS_ADD
+ * * GUILD_MEMBER_JOIN
+ * * USER_PREMIUM_GUILD_SUBSCRIPTION
+ * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1
+ * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2
+ * * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3
+ * * CHANNEL_FOLLOW_ADD
+ * * GUILD_DISCOVERY_DISQUALIFIED
+ * * GUILD_DISCOVERY_REQUALIFIED
+ * @typedef {string} MessageType
+ */
+exports.MessageTypes = [
+ 'DEFAULT',
+ 'RECIPIENT_ADD',
+ 'RECIPIENT_REMOVE',
+ 'CALL',
+ 'CHANNEL_NAME_CHANGE',
+ 'CHANNEL_ICON_CHANGE',
+ 'PINS_ADD',
+ 'GUILD_MEMBER_JOIN',
+ 'USER_PREMIUM_GUILD_SUBSCRIPTION',
+ 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1',
+ 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2',
+ 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3',
+ 'CHANNEL_FOLLOW_ADD',
+ // 13 isn't yet documented
+ null,
+ 'GUILD_DISCOVERY_DISQUALIFIED',
+ 'GUILD_DISCOVERY_REQUALIFIED',
+];
+
+/**
+ * <info>Bots cannot set a `CUSTOM_STATUS`, it is only for custom statuses received from users</info>
+ * The type of an activity of a users presence, e.g. `PLAYING`. Here are the available types:
+ * * PLAYING
+ * * STREAMING
+ * * LISTENING
+ * * WATCHING
+ * * CUSTOM_STATUS
+ * @typedef {string} ActivityType
+ */
+exports.ActivityTypes = ['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM_STATUS'];
+
+exports.ChannelTypes = {
+ TEXT: 0,
+ DM: 1,
+ VOICE: 2,
+ GROUP: 3,
+ CATEGORY: 4,
+ NEWS: 5,
+ STORE: 6,
+};
+
+exports.ClientApplicationAssetTypes = {
+ SMALL: 1,
+ BIG: 2,
+};
+
+exports.Colors = {
+ DEFAULT: 0x000000,
+ WHITE: 0xffffff,
+ AQUA: 0x1abc9c,
+ GREEN: 0x2ecc71,
+ BLUE: 0x3498db,
+ YELLOW: 0xffff00,
+ PURPLE: 0x9b59b6,
+ LUMINOUS_VIVID_PINK: 0xe91e63,
+ GOLD: 0xf1c40f,
+ ORANGE: 0xe67e22,
+ RED: 0xe74c3c,
+ GREY: 0x95a5a6,
+ NAVY: 0x34495e,
+ DARK_AQUA: 0x11806a,
+ DARK_GREEN: 0x1f8b4c,
+ DARK_BLUE: 0x206694,
+ DARK_PURPLE: 0x71368a,
+ DARK_VIVID_PINK: 0xad1457,
+ DARK_GOLD: 0xc27c0e,
+ DARK_ORANGE: 0xa84300,
+ DARK_RED: 0x992d22,
+ DARK_GREY: 0x979c9f,
+ DARKER_GREY: 0x7f8c8d,
+ LIGHT_GREY: 0xbcc0c0,
+ DARK_NAVY: 0x2c3e50,
+ BLURPLE: 0x7289da,
+ GREYPLE: 0x99aab5,
+ DARK_BUT_NOT_BLACK: 0x2c2f33,
+ NOT_QUITE_BLACK: 0x23272a,
+};
+
+/**
+ * The value set for the explicit content filter levels for a guild:
+ * * DISABLED
+ * * MEMBERS_WITHOUT_ROLES
+ * * ALL_MEMBERS
+ * @typedef {string} ExplicitContentFilterLevel
+ */
+exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS'];
+
+/**
+ * The value set for the verification levels for a guild:
+ * * NONE
+ * * LOW
+ * * MEDIUM
+ * * HIGH
+ * * VERY_HIGH
+ * @typedef {string} VerificationLevel
+ */
+exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH'];
+
+/**
+ * An error encountered while performing an API request. Here are the potential errors:
+ * * UNKNOWN_ACCOUNT
+ * * UNKNOWN_APPLICATION
+ * * UNKNOWN_CHANNEL
+ * * UNKNOWN_GUILD
+ * * UNKNOWN_INTEGRATION
+ * * UNKNOWN_INVITE
+ * * UNKNOWN_MEMBER
+ * * UNKNOWN_MESSAGE
+ * * UNKNOWN_OVERWRITE
+ * * UNKNOWN_PROVIDER
+ * * UNKNOWN_ROLE
+ * * UNKNOWN_TOKEN
+ * * UNKNOWN_USER
+ * * UNKNOWN_EMOJI
+ * * UNKNOWN_WEBHOOK
+ * * BOT_PROHIBITED_ENDPOINT
+ * * BOT_ONLY_ENDPOINT
+ * * MAXIMUM_GUILDS
+ * * MAXIMUM_FRIENDS
+ * * MAXIMUM_PINS
+ * * MAXIMUM_ROLES
+ * * MAXIMUM_REACTIONS
+ * * MAXIMUM_CHANNELS
+ * * MAXIMUM_INVITES
+ * * UNAUTHORIZED
+ * * USER_BANNED
+ * * MISSING_ACCESS
+ * * INVALID_ACCOUNT_TYPE
+ * * CANNOT_EXECUTE_ON_DM
+ * * EMBED_DISABLED
+ * * CANNOT_EDIT_MESSAGE_BY_OTHER
+ * * CANNOT_SEND_EMPTY_MESSAGE
+ * * CANNOT_MESSAGE_USER
+ * * CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL
+ * * CHANNEL_VERIFICATION_LEVEL_TOO_HIGH
+ * * OAUTH2_APPLICATION_BOT_ABSENT
+ * * MAXIMUM_OAUTH2_APPLICATIONS
+ * * INVALID_OAUTH_STATE
+ * * MISSING_PERMISSIONS
+ * * INVALID_AUTHENTICATION_TOKEN
+ * * NOTE_TOO_LONG
+ * * INVALID_BULK_DELETE_QUANTITY
+ * * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL
+ * * INVALID_OR_TAKEN_INVITE_CODE
+ * * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE
+ * * INVALID_OAUTH_TOKEN
+ * * BULK_DELETE_MESSAGE_TOO_OLD
+ * * INVALID_FORM_BODY
+ * * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT
+ * * INVALID_API_VERSION
+ * * REACTION_BLOCKED
+ * * RESOURCE_OVERLOADED
+ * @typedef {string} APIError
+ */
+exports.APIErrors = {
+ UNKNOWN_ACCOUNT: 10001,
+ UNKNOWN_APPLICATION: 10002,
+ UNKNOWN_CHANNEL: 10003,
+ UNKNOWN_GUILD: 10004,
+ UNKNOWN_INTEGRATION: 10005,
+ UNKNOWN_INVITE: 10006,
+ UNKNOWN_MEMBER: 10007,
+ UNKNOWN_MESSAGE: 10008,
+ UNKNOWN_OVERWRITE: 10009,
+ UNKNOWN_PROVIDER: 10010,
+ UNKNOWN_ROLE: 10011,
+ UNKNOWN_TOKEN: 10012,
+ UNKNOWN_USER: 10013,
+ UNKNOWN_EMOJI: 10014,
+ UNKNOWN_WEBHOOK: 10015,
+ BOT_PROHIBITED_ENDPOINT: 20001,
+ BOT_ONLY_ENDPOINT: 20002,
+ MAXIMUM_GUILDS: 30001,
+ MAXIMUM_FRIENDS: 30002,
+ MAXIMUM_PINS: 30003,
+ MAXIMUM_ROLES: 30005,
+ MAXIMUM_REACTIONS: 30010,
+ MAXIMUM_CHANNELS: 30013,
+ MAXIMUM_INVITES: 30016,
+ UNAUTHORIZED: 40001,
+ USER_BANNED: 40007,
+ MISSING_ACCESS: 50001,
+ INVALID_ACCOUNT_TYPE: 50002,
+ CANNOT_EXECUTE_ON_DM: 50003,
+ EMBED_DISABLED: 50004,
+ CANNOT_EDIT_MESSAGE_BY_OTHER: 50005,
+ CANNOT_SEND_EMPTY_MESSAGE: 50006,
+ CANNOT_MESSAGE_USER: 50007,
+ CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008,
+ CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009,
+ OAUTH2_APPLICATION_BOT_ABSENT: 50010,
+ MAXIMUM_OAUTH2_APPLICATIONS: 50011,
+ INVALID_OAUTH_STATE: 50012,
+ MISSING_PERMISSIONS: 50013,
+ INVALID_AUTHENTICATION_TOKEN: 50014,
+ NOTE_TOO_LONG: 50015,
+ INVALID_BULK_DELETE_QUANTITY: 50016,
+ CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019,
+ INVALID_OR_TAKEN_INVITE_CODE: 50020,
+ CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021,
+ INVALID_OAUTH_TOKEN: 50025,
+ BULK_DELETE_MESSAGE_TOO_OLD: 50034,
+ INVALID_FORM_BODY: 50035,
+ INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036,
+ INVALID_API_VERSION: 50041,
+ REACTION_BLOCKED: 90001,
+ RESOURCE_OVERLOADED: 130000,
+};
+
+/**
+ * The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types:
+ * * ALL
+ * * MENTIONS
+ * @typedef {string} DefaultMessageNotifications
+ */
+exports.DefaultMessageNotifications = ['ALL', 'MENTIONS'];
+
+/**
+ * The value set for a team members's membership state:
+ * * INVITED
+ * * ACCEPTED
+ * @typedef {string} MembershipStates
+ */
+exports.MembershipStates = [
+ // They start at 1
+ null,
+ 'INVITED',
+ 'ACCEPTED',
+];
+
+/**
+ * The value set for a webhook's type:
+ * * Incoming
+ * * Channel Follower
+ * @typedef {string} WebhookTypes
+ */
+exports.WebhookTypes = [
+ // They start at 1
+ null,
+ 'Incoming',
+ 'Channel Follower',
+];
+
+function keyMirror(arr) {
+ let tmp = Object.create(null);
+ for (const value of arr) tmp[value] = value;
+ return tmp;
+}
diff --git a/node_modules/discord.js/src/util/DataResolver.js b/node_modules/discord.js/src/util/DataResolver.js
new file mode 100644
index 0000000..71f690c
--- /dev/null
+++ b/node_modules/discord.js/src/util/DataResolver.js
@@ -0,0 +1,127 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const stream = require('stream');
+const fetch = require('node-fetch');
+const { Error: DiscordError, TypeError } = require('../errors');
+const { browser } = require('../util/Constants');
+const Util = require('../util/Util');
+
+/**
+ * The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
+ * @private
+ */
+class DataResolver {
+ constructor() {
+ throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+ }
+
+ /**
+ * Data that can be resolved to give an invite code. This can be:
+ * * An invite code
+ * * An invite URL
+ * @typedef {string} InviteResolvable
+ */
+
+ /**
+ * Resolves InviteResolvable to an invite code.
+ * @param {InviteResolvable} data The invite resolvable to resolve
+ * @returns {string}
+ */
+ static resolveInviteCode(data) {
+ const inviteRegex = /discord(?:app\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i;
+ const match = inviteRegex.exec(data);
+ if (match && match[1]) return match[1];
+ return data;
+ }
+
+ /**
+ * Resolves a Base64Resolvable, a string, or a BufferResolvable to a Base 64 image.
+ * @param {BufferResolvable|Base64Resolvable} image The image to be resolved
+ * @returns {Promise<?string>}
+ */
+ static async resolveImage(image) {
+ if (!image) return null;
+ if (typeof image === 'string' && image.startsWith('data:')) {
+ return image;
+ }
+ const file = await this.resolveFileAsBuffer(image);
+ return DataResolver.resolveBase64(file);
+ }
+
+ /**
+ * Data that resolves to give a Base64 string, typically for image uploading. This can be:
+ * * A Buffer
+ * * A base64 string
+ * @typedef {Buffer|string} Base64Resolvable
+ */
+
+ /**
+ * Resolves a Base64Resolvable to a Base 64 image.
+ * @param {Base64Resolvable} data The base 64 resolvable you want to resolve
+ * @returns {?string}
+ */
+ static resolveBase64(data) {
+ if (Buffer.isBuffer(data)) return `data:image/jpg;base64,${data.toString('base64')}`;
+ return data;
+ }
+
+ /**
+ * Data that can be resolved to give a Buffer. This can be:
+ * * A Buffer
+ * * The path to a local file
+ * * A URL
+ * @typedef {string|Buffer} BufferResolvable
+ */
+
+ /**
+ * @external Stream
+ * @see {@link https://nodejs.org/api/stream.html}
+ */
+
+ /**
+ * Resolves a BufferResolvable to a Buffer or a Stream.
+ * @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
+ * @returns {Promise<Buffer|Stream>}
+ */
+ static async resolveFile(resource) {
+ if (!browser && Buffer.isBuffer(resource)) return resource;
+ if (browser && resource instanceof ArrayBuffer) return Util.convertToBuffer(resource);
+ if (resource instanceof stream.Readable) return resource;
+
+ if (typeof resource === 'string') {
+ if (/^https?:\/\//.test(resource)) {
+ const res = await fetch(resource);
+ return browser ? res.blob() : res.body;
+ } else if (!browser) {
+ return new Promise((resolve, reject) => {
+ const file = path.resolve(resource);
+ fs.stat(file, (err, stats) => {
+ if (err) return reject(err);
+ if (!stats.isFile()) return reject(new DiscordError('FILE_NOT_FOUND', file));
+ return resolve(fs.createReadStream(file));
+ });
+ });
+ }
+ }
+
+ throw new TypeError('REQ_RESOURCE_TYPE');
+ }
+
+ /**
+ * Resolves a BufferResolvable to a Buffer.
+ * @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
+ * @returns {Promise<Buffer>}
+ */
+ static async resolveFileAsBuffer(resource) {
+ const file = await this.resolveFile(resource);
+ if (Buffer.isBuffer(file)) return file;
+
+ const buffers = [];
+ for await (const data of file) buffers.push(data);
+ return Buffer.concat(buffers);
+ }
+}
+
+module.exports = DataResolver;
diff --git a/node_modules/discord.js/src/util/Intents.js b/node_modules/discord.js/src/util/Intents.js
new file mode 100644
index 0000000..dc85e55
--- /dev/null
+++ b/node_modules/discord.js/src/util/Intents.js
@@ -0,0 +1,83 @@
+'use strict';
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to calculate intents.
+ * @extends {BitField}
+ */
+class Intents extends BitField {}
+
+/**
+ * @name Intents
+ * @kind constructor
+ * @memberof Intents
+ * @param {IntentsResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Data that can be resolved to give a permission number. This can be:
+ * * A string (see {@link Intents.FLAGS})
+ * * An intents flag
+ * * An instance of Intents
+ * * An array of IntentsResolvable
+ * @typedef {string|number|Intents|IntentsResolvable[]} IntentsResolvable
+ */
+
+/**
+ * Numeric websocket intents. All available properties:
+ * * `GUILDS`
+ * * `GUILD_MEMBERS`
+ * * `GUILD_BANS`
+ * * `GUILD_EMOJIS`
+ * * `GUILD_INTEGRATIONS`
+ * * `GUILD_WEBHOOKS`
+ * * `GUILD_INVITES`
+ * * `GUILD_VOICE_STATES`
+ * * `GUILD_PRESENCES`
+ * * `GUILD_MESSAGES`
+ * * `GUILD_MESSAGE_REACTIONS`
+ * * `GUILD_MESSAGE_TYPING`
+ * * `DIRECT_MESSAGES`
+ * * `DIRECT_MESSAGE_REACTIONS`
+ * * `DIRECT_MESSAGE_TYPING`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/topics/gateway#list-of-intents}
+ */
+Intents.FLAGS = {
+ GUILDS: 1 << 0,
+ GUILD_MEMBERS: 1 << 1,
+ GUILD_BANS: 1 << 2,
+ GUILD_EMOJIS: 1 << 3,
+ GUILD_INTEGRATIONS: 1 << 4,
+ GUILD_WEBHOOKS: 1 << 5,
+ GUILD_INVITES: 1 << 6,
+ GUILD_VOICE_STATES: 1 << 7,
+ GUILD_PRESENCES: 1 << 8,
+ GUILD_MESSAGES: 1 << 9,
+ GUILD_MESSAGE_REACTIONS: 1 << 10,
+ GUILD_MESSAGE_TYPING: 1 << 11,
+ DIRECT_MESSAGES: 1 << 12,
+ DIRECT_MESSAGE_REACTIONS: 1 << 13,
+ DIRECT_MESSAGE_TYPING: 1 << 14,
+};
+
+/**
+ * Bitfield representing all privileged intents
+ * @type {number}
+ * @see {@link https://discordapp.com/developers/docs/topics/gateway#privileged-intents}
+ */
+Intents.PRIVILEGED = Intents.FLAGS.GUILD_MEMBERS | Intents.FLAGS.GUILD_PRESENCES;
+
+/**
+ * Bitfield representing all intents combined
+ * @type {number}
+ */
+Intents.ALL = Object.values(Intents.FLAGS).reduce((acc, p) => acc | p, 0);
+
+/**
+ * Bitfield representing all non-privileged intents
+ * @type {number}
+ */
+Intents.NON_PRIVILEGED = Intents.ALL & ~Intents.PRIVILEGED;
+
+module.exports = Intents;
diff --git a/node_modules/discord.js/src/util/LimitedCollection.js b/node_modules/discord.js/src/util/LimitedCollection.js
new file mode 100644
index 0000000..caa4978
--- /dev/null
+++ b/node_modules/discord.js/src/util/LimitedCollection.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const Collection = require('./Collection.js');
+
+/**
+ * A Collection which holds a max amount of entries. The first key is deleted if the Collection has
+ * reached max size.
+ * @extends {Collection}
+ * @param {number} [maxSize=0] The maximum size of the Collection
+ * @param {Iterable} [iterable=null] Optional entries passed to the Map constructor.
+ * @private
+ */
+class LimitedCollection extends Collection {
+ constructor(maxSize = 0, iterable = null) {
+ super(iterable);
+ /**
+ * The max size of the Collection.
+ * @type {number}
+ */
+ this.maxSize = maxSize;
+ }
+
+ set(key, value) {
+ if (this.maxSize === 0) return this;
+ if (this.size >= this.maxSize && !this.has(key)) this.delete(this.firstKey());
+ return super.set(key, value);
+ }
+
+ static get [Symbol.species]() {
+ return Collection;
+ }
+}
+
+module.exports = LimitedCollection;
diff --git a/node_modules/discord.js/src/util/MessageFlags.js b/node_modules/discord.js/src/util/MessageFlags.js
new file mode 100644
index 0000000..f2bccc9
--- /dev/null
+++ b/node_modules/discord.js/src/util/MessageFlags.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with an {@link Message#flags} bitfield.
+ * @extends {BitField}
+ */
+class MessageFlags extends BitField {}
+
+/**
+ * @name MessageFlags
+ * @kind constructor
+ * @memberof MessageFlags
+ * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Numeric message flags. All available properties:
+ * * `CROSSPOSTED`
+ * * `IS_CROSSPOST`
+ * * `SUPPRESS_EMBEDS`
+ * * `SOURCE_MESSAGE_DELETED`
+ * * `URGENT`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/resources/channel#message-object-message-flags}
+ */
+MessageFlags.FLAGS = {
+ CROSSPOSTED: 1 << 0,
+ IS_CROSSPOST: 1 << 1,
+ SUPPRESS_EMBEDS: 1 << 2,
+ SOURCE_MESSAGE_DELETED: 1 << 3,
+ URGENT: 1 << 4,
+};
+
+module.exports = MessageFlags;
diff --git a/node_modules/discord.js/src/util/Permissions.js b/node_modules/discord.js/src/util/Permissions.js
new file mode 100644
index 0000000..6d32527
--- /dev/null
+++ b/node_modules/discord.js/src/util/Permissions.js
@@ -0,0 +1,131 @@
+'use strict';
+
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
+ * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
+ * that override their default permissions.
+ * @extends {BitField}
+ */
+class Permissions extends BitField {
+ /**
+ * @name Permissions
+ * @kind constructor
+ * @memberof Permissions
+ * @param {PermissionResolvable} [bits=0] Bit(s) to read from
+ */
+
+ /**
+ * Data that can be resolved to give a permission number. This can be:
+ * * A string (see {@link Permissions.FLAGS})
+ * * A permission number
+ * * An instance of Permissions
+ * * An Array of PermissionResolvable
+ * @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable
+ */
+
+ /**
+ * Checks whether the bitfield has a permission, or any of multiple permissions.
+ * @param {PermissionResolvable} permission Permission(s) to check for
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
+ * @returns {boolean}
+ */
+ any(permission, checkAdmin = true) {
+ return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.any(permission);
+ }
+
+ /**
+ * Checks whether the bitfield has a permission, or multiple permissions.
+ * @param {PermissionResolvable} permission Permission(s) to check for
+ * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
+ * @returns {boolean}
+ */
+ has(permission, checkAdmin = true) {
+ return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.has(permission);
+ }
+}
+
+/**
+ * Numeric permission flags. All available properties:
+ * * `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
+ * * `CREATE_INSTANT_INVITE` (create invitations to the guild)
+ * * `KICK_MEMBERS`
+ * * `BAN_MEMBERS`
+ * * `MANAGE_CHANNELS` (edit and reorder channels)
+ * * `MANAGE_GUILD` (edit the guild information, region, etc.)
+ * * `ADD_REACTIONS` (add new reactions to messages)
+ * * `VIEW_AUDIT_LOG`
+ * * `PRIORITY_SPEAKER`
+ * * `STREAM`
+ * * `VIEW_CHANNEL`
+ * * `SEND_MESSAGES`
+ * * `SEND_TTS_MESSAGES`
+ * * `MANAGE_MESSAGES` (delete messages and reactions)
+ * * `EMBED_LINKS` (links posted will have a preview embedded)
+ * * `ATTACH_FILES`
+ * * `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
+ * * `MENTION_EVERYONE`
+ * * `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
+ * * `VIEW_GUILD_INSIGHTS`
+ * * `CONNECT` (connect to a voice channel)
+ * * `SPEAK` (speak in a voice channel)
+ * * `MUTE_MEMBERS` (mute members across all voice channels)
+ * * `DEAFEN_MEMBERS` (deafen members across all voice channels)
+ * * `MOVE_MEMBERS` (move members between voice channels)
+ * * `USE_VAD` (use voice activity detection)
+ * * `CHANGE_NICKNAME`
+ * * `MANAGE_NICKNAMES` (change other members' nicknames)
+ * * `MANAGE_ROLES`
+ * * `MANAGE_WEBHOOKS`
+ * * `MANAGE_EMOJIS`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/topics/permissions}
+ */
+Permissions.FLAGS = {
+ CREATE_INSTANT_INVITE: 1 << 0,
+ KICK_MEMBERS: 1 << 1,
+ BAN_MEMBERS: 1 << 2,
+ ADMINISTRATOR: 1 << 3,
+ MANAGE_CHANNELS: 1 << 4,
+ MANAGE_GUILD: 1 << 5,
+ ADD_REACTIONS: 1 << 6,
+ VIEW_AUDIT_LOG: 1 << 7,
+ PRIORITY_SPEAKER: 1 << 8,
+ STREAM: 1 << 9,
+ VIEW_CHANNEL: 1 << 10,
+ SEND_MESSAGES: 1 << 11,
+ SEND_TTS_MESSAGES: 1 << 12,
+ MANAGE_MESSAGES: 1 << 13,
+ EMBED_LINKS: 1 << 14,
+ ATTACH_FILES: 1 << 15,
+ READ_MESSAGE_HISTORY: 1 << 16,
+ MENTION_EVERYONE: 1 << 17,
+ USE_EXTERNAL_EMOJIS: 1 << 18,
+ VIEW_GUILD_INSIGHTS: 1 << 19,
+ CONNECT: 1 << 20,
+ SPEAK: 1 << 21,
+ MUTE_MEMBERS: 1 << 22,
+ DEAFEN_MEMBERS: 1 << 23,
+ MOVE_MEMBERS: 1 << 24,
+ USE_VAD: 1 << 25,
+ CHANGE_NICKNAME: 1 << 26,
+ MANAGE_NICKNAMES: 1 << 27,
+ MANAGE_ROLES: 1 << 28,
+ MANAGE_WEBHOOKS: 1 << 29,
+ MANAGE_EMOJIS: 1 << 30,
+};
+
+/**
+ * Bitfield representing every permission combined
+ * @type {number}
+ */
+Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0);
+
+/**
+ * Bitfield representing the default permissions for users
+ * @type {number}
+ */
+Permissions.DEFAULT = 104324673;
+
+module.exports = Permissions;
diff --git a/node_modules/discord.js/src/util/Snowflake.js b/node_modules/discord.js/src/util/Snowflake.js
new file mode 100644
index 0000000..ec71033
--- /dev/null
+++ b/node_modules/discord.js/src/util/Snowflake.js
@@ -0,0 +1,87 @@
+'use strict';
+
+const Util = require('../util/Util');
+
+// Discord epoch (2015-01-01T00:00:00.000Z)
+const EPOCH = 1420070400000;
+let INCREMENT = 0;
+
+/**
+ * A container for useful snowflake-related methods.
+ */
+class SnowflakeUtil {
+ constructor() {
+ throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+ }
+
+ /**
+ * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z
+ * ```
+ * If we have a snowflake '266241948824764416' we can represent it as binary:
+ *
+ * 64 22 17 12 0
+ * 000000111011000111100001101001000101000000 00001 00000 000000000000
+ * number of ms since Discord epoch worker pid increment
+ * ```
+ * @typedef {string} Snowflake
+ */
+
+ /**
+ * Generates a Discord snowflake.
+ * <info>This hardcodes the worker ID as 1 and the process ID as 0.</info>
+ * @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate
+ * @returns {Snowflake} The generated snowflake
+ */
+ static generate(timestamp = Date.now()) {
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
+ if (typeof timestamp !== 'number' || isNaN(timestamp)) {
+ throw new TypeError(
+ `"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`,
+ );
+ }
+ if (INCREMENT >= 4095) INCREMENT = 0;
+ // eslint-disable-next-line max-len
+ const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++)
+ .toString(2)
+ .padStart(12, '0')}`;
+ return Util.binaryToID(BINARY);
+ }
+
+ /**
+ * A deconstructed snowflake.
+ * @typedef {Object} DeconstructedSnowflake
+ * @property {number} timestamp Timestamp the snowflake was created
+ * @property {Date} date Date the snowflake was created
+ * @property {number} workerID Worker ID in the snowflake
+ * @property {number} processID Process ID in the snowflake
+ * @property {number} increment Increment in the snowflake
+ * @property {string} binary Binary representation of the snowflake
+ */
+
+ /**
+ * Deconstructs a Discord snowflake.
+ * @param {Snowflake} snowflake Snowflake to deconstruct
+ * @returns {DeconstructedSnowflake} Deconstructed snowflake
+ */
+ static deconstruct(snowflake) {
+ const BINARY = Util.idToBinary(snowflake)
+ .toString(2)
+ .padStart(64, '0');
+ const res = {
+ timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH,
+ workerID: parseInt(BINARY.substring(42, 47), 2),
+ processID: parseInt(BINARY.substring(47, 52), 2),
+ increment: parseInt(BINARY.substring(52, 64), 2),
+ binary: BINARY,
+ };
+ Object.defineProperty(res, 'date', {
+ get: function get() {
+ return new Date(this.timestamp);
+ },
+ enumerable: true,
+ });
+ return res;
+ }
+}
+
+module.exports = SnowflakeUtil;
diff --git a/node_modules/discord.js/src/util/Speaking.js b/node_modules/discord.js/src/util/Speaking.js
new file mode 100644
index 0000000..8f819d1
--- /dev/null
+++ b/node_modules/discord.js/src/util/Speaking.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with a {@link VoiceConnection#speaking}
+ * and {@link guildMemberSpeaking} event bitfields.
+ * @extends {BitField}
+ */
+class Speaking extends BitField {}
+
+/**
+ * @name Speaking
+ * @kind constructor
+ * @memberof Speaking
+ * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Numeric speaking flags. All available properties:
+ * * `SPEAKING`
+ * * `SOUNDSHARE`
+ * * `PRIORITY_SPEAKING`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/topics/voice-connections#speaking}
+ */
+Speaking.FLAGS = {
+ SPEAKING: 1 << 0,
+ SOUNDSHARE: 1 << 1,
+ PRIORITY_SPEAKING: 1 << 2,
+};
+
+module.exports = Speaking;
diff --git a/node_modules/discord.js/src/util/Structures.js b/node_modules/discord.js/src/util/Structures.js
new file mode 100644
index 0000000..0c6ab35
--- /dev/null
+++ b/node_modules/discord.js/src/util/Structures.js
@@ -0,0 +1,112 @@
+'use strict';
+
+/**
+ * An extendable structure:
+ * * **`GuildEmoji`**
+ * * **`DMChannel`**
+ * * **`TextChannel`**
+ * * **`VoiceChannel`**
+ * * **`CategoryChannel`**
+ * * **`NewsChannel`**
+ * * **`StoreChannel`**
+ * * **`GuildMember`**
+ * * **`Guild`**
+ * * **`Message`**
+ * * **`MessageReaction`**
+ * * **`Presence`**
+ * * **`ClientPresence`**
+ * * **`VoiceState`**
+ * * **`Role`**
+ * * **`User`**
+ * @typedef {string} ExtendableStructure
+ */
+
+/**
+ * Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}.
+ */
+class Structures {
+ constructor() {
+ throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+ }
+
+ /**
+ * Retrieves a structure class.
+ * @param {string} structure Name of the structure to retrieve
+ * @returns {Function}
+ */
+ static get(structure) {
+ if (typeof structure === 'string') return structures[structure];
+ throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`);
+ }
+
+ /**
+ * Extends a structure.
+ * <warn> Make sure to extend all structures before instantiating your client.
+ * Extending after doing so may not work as expected. </warn>
+ * @param {ExtendableStructure} structure Name of the structure class to extend
+ * @param {Function} extender Function that takes the base class to extend as its only parameter and returns the
+ * extended class/prototype
+ * @returns {Function} Extended class/prototype returned from the extender
+ * @example
+ * const { Structures } = require('discord.js');
+ *
+ * Structures.extend('Guild', Guild => {
+ * class CoolGuild extends Guild {
+ * constructor(client, data) {
+ * super(client, data);
+ * this.cool = true;
+ * }
+ * }
+ *
+ * return CoolGuild;
+ * });
+ */
+ static extend(structure, extender) {
+ if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`);
+ if (typeof extender !== 'function') {
+ const received = `(received ${typeof extender})`;
+ throw new TypeError(
+ `"extender" argument must be a function that returns the extended structure class/prototype ${received}.`,
+ );
+ }
+
+ const extended = extender(structures[structure]);
+ if (typeof extended !== 'function') {
+ const received = `(received ${typeof extended})`;
+ throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`);
+ }
+
+ if (!(extended.prototype instanceof structures[structure])) {
+ const prototype = Object.getPrototypeOf(extended);
+ const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`;
+ throw new Error(
+ 'The class/prototype returned from the extender function must extend the existing structure class/prototype' +
+ ` (received function ${received}; expected extension of ${structures[structure].name}).`,
+ );
+ }
+
+ structures[structure] = extended;
+ return extended;
+ }
+}
+
+const structures = {
+ GuildEmoji: require('../structures/GuildEmoji'),
+ DMChannel: require('../structures/DMChannel'),
+ TextChannel: require('../structures/TextChannel'),
+ VoiceChannel: require('../structures/VoiceChannel'),
+ CategoryChannel: require('../structures/CategoryChannel'),
+ NewsChannel: require('../structures/NewsChannel'),
+ StoreChannel: require('../structures/StoreChannel'),
+ GuildMember: require('../structures/GuildMember'),
+ Guild: require('../structures/Guild'),
+ Message: require('../structures/Message'),
+ MessageReaction: require('../structures/MessageReaction'),
+ Presence: require('../structures/Presence').Presence,
+ ClientPresence: require('../structures/ClientPresence'),
+ VoiceState: require('../structures/VoiceState'),
+ Role: require('../structures/Role'),
+ User: require('../structures/User'),
+};
+
+module.exports = Structures;
diff --git a/node_modules/discord.js/src/util/SystemChannelFlags.js b/node_modules/discord.js/src/util/SystemChannelFlags.js
new file mode 100644
index 0000000..4d08b76
--- /dev/null
+++ b/node_modules/discord.js/src/util/SystemChannelFlags.js
@@ -0,0 +1,40 @@
+'use strict';
+
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with a {@link Guild#systemChannelFlags} bitfield.
+ * <info>Note that all event message types are enabled by default,
+ * and by setting their corresponding flags you are disabling them</info>
+ * @extends {BitField}
+ */
+class SystemChannelFlags extends BitField {}
+
+/**
+ * @name SystemChannelFlags
+ * @kind constructor
+ * @memberof SystemChannelFlags
+ * @param {SystemChannelFlagsResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Data that can be resolved to give a sytem channel flag bitfield. This can be:
+ * * A string (see {@link SystemChannelFlags.FLAGS})
+ * * A sytem channel flag
+ * * An instance of SystemChannelFlags
+ * * An Array of SystemChannelFlagsResolvable
+ * @typedef {string|number|SystemChannelFlags|SystemChannelFlagsResolvable[]} SystemChannelFlagsResolvable
+ */
+
+/**
+ * Numeric system channel flags. All available properties:
+ * * `WELCOME_MESSAGE_DISABLED`
+ * * `BOOST_MESSAGE_DISABLED`
+ * @type {Object}
+ */
+SystemChannelFlags.FLAGS = {
+ WELCOME_MESSAGE_DISABLED: 1 << 0,
+ BOOST_MESSAGE_DISABLED: 1 << 1,
+};
+
+module.exports = SystemChannelFlags;
diff --git a/node_modules/discord.js/src/util/UserFlags.js b/node_modules/discord.js/src/util/UserFlags.js
new file mode 100644
index 0000000..120cb4f
--- /dev/null
+++ b/node_modules/discord.js/src/util/UserFlags.js
@@ -0,0 +1,51 @@
+'use strict';
+const BitField = require('./BitField');
+
+/**
+ * Data structure that makes it easy to interact with a {@link User#flags} bitfield.
+ * @extends {BitField}
+ */
+class UserFlags extends BitField {}
+
+/**
+ * @name UserFlags
+ * @kind constructor
+ * @memberof UserFlags
+ * @param {BitFieldResolvable} [bits=0] Bit(s) to read from
+ */
+
+/**
+ * Numeric user flags. All available properties:
+ * * `DISCORD_EMPLOYEE`
+ * * `DISCORD_PARTNER`
+ * * `HYPESQUAD_EVENTS`
+ * * `BUGHUNTER_LEVEL_1`
+ * * `HOUSE_BRAVERY`
+ * * `HOUSE_BRILLIANCE`
+ * * `HOUSE_BALANCE`
+ * * `EARLY_SUPPORTER`
+ * * `TEAM_USER`
+ * * `SYSTEM`
+ * * `BUGHUNTER_LEVEL_2`
+ * * `VERIFIED_BOT`
+ * * `VERIFIED_DEVELOPER`
+ * @type {Object}
+ * @see {@link https://discordapp.com/developers/docs/resources/user#user-object-user-flags}
+ */
+UserFlags.FLAGS = {
+ DISCORD_EMPLOYEE: 1 << 0,
+ DISCORD_PARTNER: 1 << 1,
+ HYPESQUAD_EVENTS: 1 << 2,
+ BUGHUNTER_LEVEL_1: 1 << 3,
+ HOUSE_BRAVERY: 1 << 6,
+ HOUSE_BRILLIANCE: 1 << 7,
+ HOUSE_BALANCE: 1 << 8,
+ EARLY_SUPPORTER: 1 << 9,
+ TEAM_USER: 1 << 10,
+ SYSTEM: 1 << 12,
+ BUGHUNTER_LEVEL_2: 1 << 14,
+ VERIFIED_BOT: 1 << 16,
+ VERIFIED_DEVELOPER: 1 << 17,
+};
+
+module.exports = UserFlags;
diff --git a/node_modules/discord.js/src/util/Util.js b/node_modules/discord.js/src/util/Util.js
new file mode 100644
index 0000000..c4fcf48
--- /dev/null
+++ b/node_modules/discord.js/src/util/Util.js
@@ -0,0 +1,621 @@
+'use strict';
+
+const { parse } = require('path');
+const fetch = require('node-fetch');
+const { Colors, DefaultOptions, Endpoints } = require('./Constants');
+const { Error: DiscordError, RangeError, TypeError } = require('../errors');
+const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
+const isObject = d => typeof d === 'object' && d !== null;
+
+/**
+ * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
+ */
+class Util {
+ constructor() {
+ throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
+ }
+
+ /**
+ * Flatten an object. Any properties that are collections will get converted to an array of keys.
+ * @param {Object} obj The object to flatten.
+ * @param {...Object<string, boolean|string>} [props] Specific properties to include/exclude.
+ * @returns {Object}
+ */
+ static flatten(obj, ...props) {
+ if (!isObject(obj)) return obj;
+
+ props = Object.assign(
+ ...Object.keys(obj)
+ .filter(k => !k.startsWith('_'))
+ .map(k => ({ [k]: true })),
+ ...props,
+ );
+
+ const out = {};
+
+ for (let [prop, newProp] of Object.entries(props)) {
+ if (!newProp) continue;
+ newProp = newProp === true ? prop : newProp;
+
+ const element = obj[prop];
+ const elemIsObj = isObject(element);
+ const valueOf = elemIsObj && typeof element.valueOf === 'function' ? element.valueOf() : null;
+
+ // If it's a Collection, make the array of keys
+ if (element instanceof require('./Collection')) out[newProp] = Array.from(element.keys());
+ // If the valueOf is a Collection, use its array of keys
+ else if (valueOf instanceof require('./Collection')) out[newProp] = Array.from(valueOf.keys());
+ // If it's an array, flatten each element
+ else if (Array.isArray(element)) out[newProp] = element.map(e => Util.flatten(e));
+ // If it's an object with a primitive `valueOf`, use that value
+ else if (typeof valueOf !== 'object') out[newProp] = valueOf;
+ // If it's a primitive
+ else if (!elemIsObj) out[newProp] = element;
+ }
+
+ return out;
+ }
+
+ /**
+ * Splits a string into multiple chunks at a designated character that do not exceed a specific length.
+ * @param {StringResolvable} text Content to split
+ * @param {SplitOptions} [options] Options controlling the behavior of the split
+ * @returns {string[]}
+ */
+ static splitMessage(text, { maxLength = 2000, char = '\n', prepend = '', append = '' } = {}) {
+ text = Util.resolveString(text);
+ if (text.length <= maxLength) return [text];
+ const splitText = text.split(char);
+ if (splitText.some(chunk => chunk.length > maxLength)) throw new RangeError('SPLIT_MAX_LEN');
+ const messages = [];
+ let msg = '';
+ for (const chunk of splitText) {
+ if (msg && (msg + char + chunk + append).length > maxLength) {
+ messages.push(msg + append);
+ msg = prepend;
+ }
+ msg += (msg && msg !== prepend ? char : '') + chunk;
+ }
+ return messages.concat(msg).filter(m => m);
+ }
+
+ /**
+ * Escapes any Discord-flavour markdown in a string.
+ * @param {string} text Content to escape
+ * @param {Object} [options={}] What types of markdown to escape
+ * @param {boolean} [options.codeBlock=true] Whether to escape code blocks or not
+ * @param {boolean} [options.inlineCode=true] Whether to escape inline code or not
+ * @param {boolean} [options.bold=true] Whether to escape bolds or not
+ * @param {boolean} [options.italic=true] Whether to escape italics or not
+ * @param {boolean} [options.underline=true] Whether to escape underlines or not
+ * @param {boolean} [options.strikethrough=true] Whether to escape strikethroughs or not
+ * @param {boolean} [options.spoiler=true] Whether to escape spoilers or not
+ * @param {boolean} [options.codeBlockContent=true] Whether to escape text inside code blocks or not
+ * @param {boolean} [options.inlineCodeContent=true] Whether to escape text inside inline code or not
+ * @returns {string}
+ */
+ static escapeMarkdown(
+ text,
+ {
+ codeBlock = true,
+ inlineCode = true,
+ bold = true,
+ italic = true,
+ underline = true,
+ strikethrough = true,
+ spoiler = true,
+ codeBlockContent = true,
+ inlineCodeContent = true,
+ } = {},
+ ) {
+ if (!codeBlockContent) {
+ return text
+ .split('```')
+ .map((subString, index, array) => {
+ if (index % 2 && index !== array.length - 1) return subString;
+ return Util.escapeMarkdown(subString, {
+ inlineCode,
+ bold,
+ italic,
+ underline,
+ strikethrough,
+ spoiler,
+ inlineCodeContent,
+ });
+ })
+ .join(codeBlock ? '\\`\\`\\`' : '```');
+ }
+ if (!inlineCodeContent) {
+ return text
+ .split(/(?<=^|[^`])`(?=[^`]|$)/g)
+ .map((subString, index, array) => {
+ if (index % 2 && index !== array.length - 1) return subString;
+ return Util.escapeMarkdown(subString, {
+ codeBlock,
+ bold,
+ italic,
+ underline,
+ strikethrough,
+ spoiler,
+ });
+ })
+ .join(inlineCode ? '\\`' : '`');
+ }
+ if (inlineCode) text = Util.escapeInlineCode(text);
+ if (codeBlock) text = Util.escapeCodeBlock(text);
+ if (italic) text = Util.escapeItalic(text);
+ if (bold) text = Util.escapeBold(text);
+ if (underline) text = Util.escapeUnderline(text);
+ if (strikethrough) text = Util.escapeStrikethrough(text);
+ if (spoiler) text = Util.escapeSpoiler(text);
+ return text;
+ }
+
+ /**
+ * Escapes code block markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeCodeBlock(text) {
+ return text.replace(/```/g, '\\`\\`\\`');
+ }
+
+ /**
+ * Escapes inline code markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeInlineCode(text) {
+ return text.replace(/(?<=^|[^`])`(?=[^`]|$)/g, '\\`');
+ }
+
+ /**
+ * Escapes italic markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeItalic(text) {
+ let i = 0;
+ text = text.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g, (_, match) => {
+ if (match === '**') return ++i % 2 ? `\\*${match}` : `${match}\\*`;
+ return `\\*${match}`;
+ });
+ i = 0;
+ return text.replace(/(?<=^|[^_])_([^_]|__|$)/g, (_, match) => {
+ if (match === '__') return ++i % 2 ? `\\_${match}` : `${match}\\_`;
+ return `\\_${match}`;
+ });
+ }
+
+ /**
+ * Escapes bold markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeBold(text) {
+ let i = 0;
+ return text.replace(/\*\*(\*)?/g, (_, match) => {
+ if (match) return ++i % 2 ? `${match}\\*\\*` : `\\*\\*${match}`;
+ return '\\*\\*';
+ });
+ }
+
+ /**
+ * Escapes underline markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeUnderline(text) {
+ let i = 0;
+ return text.replace(/__(_)?/g, (_, match) => {
+ if (match) return ++i % 2 ? `${match}\\_\\_` : `\\_\\_${match}`;
+ return '\\_\\_';
+ });
+ }
+
+ /**
+ * Escapes strikethrough markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeStrikethrough(text) {
+ return text.replace(/~~/g, '\\~\\~');
+ }
+
+ /**
+ * Escapes spoiler markdown in a string.
+ * @param {string} text Content to escape
+ * @returns {string}
+ */
+ static escapeSpoiler(text) {
+ return text.replace(/\|\|/g, '\\|\\|');
+ }
+
+ /**
+ * Gets the recommended shard count from Discord.
+ * @param {string} token Discord auth token
+ * @param {number} [guildsPerShard=1000] Number of guilds per shard
+ * @returns {Promise<number>} The recommended number of shards
+ */
+ static fetchRecommendedShards(token, guildsPerShard = 1000) {
+ if (!token) throw new DiscordError('TOKEN_MISSING');
+ return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, {
+ method: 'GET',
+ headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` },
+ })
+ .then(res => {
+ if (res.ok) return res.json();
+ throw res;
+ })
+ .then(data => data.shards * (1000 / guildsPerShard));
+ }
+
+ /**
+ * Parses emoji info out of a string. The string must be one of:
+ * * A UTF-8 emoji (no ID)
+ * * A URL-encoded UTF-8 emoji (no ID)
+ * * A Discord custom emoji (`<:name:id>` or `<a:name:id>`)
+ * @param {string} text Emoji string to parse
+ * @returns {Object} Object with `animated`, `name`, and `id` properties
+ * @private
+ */
+ static parseEmoji(text) {
+ if (text.includes('%')) text = decodeURIComponent(text);
+ if (!text.includes(':')) return { animated: false, name: text, id: null };
+ const m = text.match(/<?(?:(a):)?(\w{2,32}):(\d{17,19})?>?/);
+ if (!m) return null;
+ return { animated: Boolean(m[1]), name: m[2], id: m[3] || null };
+ }
+
+ /**
+ * Shallow-copies an object with its class/prototype intact.
+ * @param {Object} obj Object to clone
+ * @returns {Object}
+ * @private
+ */
+ static cloneObject(obj) {
+ return Object.assign(Object.create(obj), obj);
+ }
+
+ /**
+ * Sets default properties on an object that aren't already specified.
+ * @param {Object} def Default properties
+ * @param {Object} given Object to assign defaults to
+ * @returns {Object}
+ * @private
+ */
+ static mergeDefault(def, given) {
+ if (!given) return def;
+ for (const key in def) {
+ if (!has(given, key) || given[key] === undefined) {
+ given[key] = def[key];
+ } else if (given[key] === Object(given[key])) {
+ given[key] = Util.mergeDefault(def[key], given[key]);
+ }
+ }
+
+ return given;
+ }
+
+ /**
+ * Converts an ArrayBuffer or string to a Buffer.
+ * @param {ArrayBuffer|string} ab ArrayBuffer to convert
+ * @returns {Buffer}
+ * @private
+ */
+ static convertToBuffer(ab) {
+ if (typeof ab === 'string') ab = Util.str2ab(ab);
+ return Buffer.from(ab);
+ }
+
+ /**
+ * Converts a string to an ArrayBuffer.
+ * @param {string} str String to convert
+ * @returns {ArrayBuffer}
+ * @private
+ */
+ static str2ab(str) {
+ const buffer = new ArrayBuffer(str.length * 2);
+ const view = new Uint16Array(buffer);
+ for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i);
+ return buffer;
+ }
+
+ /**
+ * Makes an Error from a plain info object.
+ * @param {Object} obj Error info
+ * @param {string} obj.name Error type
+ * @param {string} obj.message Message for the error
+ * @param {string} obj.stack Stack for the error
+ * @returns {Error}
+ * @private
+ */
+ static makeError(obj) {
+ const err = new Error(obj.message);
+ err.name = obj.name;
+ err.stack = obj.stack;
+ return err;
+ }
+
+ /**
+ * Makes a plain error info object from an Error.
+ * @param {Error} err Error to get info from
+ * @returns {Object}
+ * @private
+ */
+ static makePlainError(err) {
+ return {
+ name: err.name,
+ message: err.message,
+ stack: err.stack,
+ };
+ }
+
+ /**
+ * Moves an element in an array *in place*.
+ * @param {Array<*>} array Array to modify
+ * @param {*} element Element to move
+ * @param {number} newIndex Index or offset to move the element to
+ * @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index
+ * @returns {number}
+ * @private
+ */
+ static moveElementInArray(array, element, newIndex, offset = false) {
+ const index = array.indexOf(element);
+ newIndex = (offset ? index : 0) + newIndex;
+ if (newIndex > -1 && newIndex < array.length) {
+ const removedElement = array.splice(index, 1)[0];
+ array.splice(newIndex, 0, removedElement);
+ }
+ return array.indexOf(element);
+ }
+
+ /**
+ * Data that can be resolved to give a string. This can be:
+ * * A string
+ * * An array (joined with a new line delimiter to give a string)
+ * * Any value
+ * @typedef {string|Array|*} StringResolvable
+ */
+
+ /**
+ * Resolves a StringResolvable to a string.
+ * @param {StringResolvable} data The string resolvable to resolve
+ * @returns {string}
+ */
+ static resolveString(data) {
+ if (typeof data === 'string') return data;
+ if (Array.isArray(data)) return data.join('\n');
+ return String(data);
+ }
+
+ /**
+ * Can be a number, hex string, an RGB array like:
+ * ```js
+ * [255, 0, 255] // purple
+ * ```
+ * or one of the following strings:
+ * - `DEFAULT`
+ * - `WHITE`
+ * - `AQUA`
+ * - `GREEN`
+ * - `BLUE`
+ * - `YELLOW`
+ * - `PURPLE`
+ * - `LUMINOUS_VIVID_PINK`
+ * - `GOLD`
+ * - `ORANGE`
+ * - `RED`
+ * - `GREY`
+ * - `DARKER_GREY`
+ * - `NAVY`
+ * - `DARK_AQUA`
+ * - `DARK_GREEN`
+ * - `DARK_BLUE`
+ * - `DARK_PURPLE`
+ * - `DARK_VIVID_PINK`
+ * - `DARK_GOLD`
+ * - `DARK_ORANGE`
+ * - `DARK_RED`
+ * - `DARK_GREY`
+ * - `LIGHT_GREY`
+ * - `DARK_NAVY`
+ * - `RANDOM`
+ * @typedef {string|number|number[]} ColorResolvable
+ */
+
+ /**
+ * Resolves a ColorResolvable into a color number.
+ * @param {ColorResolvable} color Color to resolve
+ * @returns {number} A color
+ */
+ static resolveColor(color) {
+ if (typeof color === 'string') {
+ if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1));
+ if (color === 'DEFAULT') return 0;
+ color = Colors[color] || parseInt(color.replace('#', ''), 16);
+ } else if (Array.isArray(color)) {
+ color = (color[0] << 16) + (color[1] << 8) + color[2];
+ }
+
+ if (color < 0 || color > 0xffffff) throw new RangeError('COLOR_RANGE');
+ else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT');
+
+ return color;
+ }
+
+ /**
+ * Sorts by Discord's position and ID.
+ * @param {Collection} collection Collection of objects to sort
+ * @returns {Collection}
+ */
+ static discordSort(collection) {
+ return collection.sorted(
+ (a, b) =>
+ a.rawPosition - b.rawPosition ||
+ parseInt(b.id.slice(0, -10)) - parseInt(a.id.slice(0, -10)) ||
+ parseInt(b.id.slice(10)) - parseInt(a.id.slice(10)),
+ );
+ }
+
+ /**
+ * Sets the position of a Channel or Role.
+ * @param {Channel|Role} item Object to set the position of
+ * @param {number} position New position for the object
+ * @param {boolean} relative Whether `position` is relative to its current position
+ * @param {Collection<string, Channel|Role>} sorted A collection of the objects sorted properly
+ * @param {APIRouter} route Route to call PATCH on
+ * @param {string} [reason] Reason for the change
+ * @returns {Promise<Object[]>} Updated item list, with `id` and `position` properties
+ * @private
+ */
+ static setPosition(item, position, relative, sorted, route, reason) {
+ let updatedItems = sorted.array();
+ Util.moveElementInArray(updatedItems, item, position, relative);
+ updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i }));
+ return route.patch({ data: updatedItems, reason }).then(() => updatedItems);
+ }
+
+ /**
+ * Alternative to Node's `path.basename`, removing query string after the extension if it exists.
+ * @param {string} path Path to get the basename of
+ * @param {string} [ext] File extension to remove
+ * @returns {string} Basename of the path
+ * @private
+ */
+ static basename(path, ext) {
+ let res = parse(path);
+ return ext && res.ext.startsWith(ext) ? res.name : res.base.split('?')[0];
+ }
+
+ /**
+ * Transforms a snowflake from a decimal string to a bit string.
+ * @param {Snowflake} num Snowflake to be transformed
+ * @returns {string}
+ * @private
+ */
+ static idToBinary(num) {
+ let bin = '';
+ let high = parseInt(num.slice(0, -10)) || 0;
+ let low = parseInt(num.slice(-10));
+ while (low > 0 || high > 0) {
+ bin = String(low & 1) + bin;
+ low = Math.floor(low / 2);
+ if (high > 0) {
+ low += 5000000000 * (high % 2);
+ high = Math.floor(high / 2);
+ }
+ }
+ return bin;
+ }
+
+ /**
+ * Transforms a snowflake from a bit string to a decimal string.
+ * @param {string} num Bit string to be transformed
+ * @returns {Snowflake}
+ * @private
+ */
+ static binaryToID(num) {
+ let dec = '';
+
+ while (num.length > 50) {
+ const high = parseInt(num.slice(0, -32), 2);
+ const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);
+
+ dec = (low % 10).toString() + dec;
+ num =
+ Math.floor(high / 10).toString(2) +
+ Math.floor(low / 10)
+ .toString(2)
+ .padStart(32, '0');
+ }
+
+ num = parseInt(num, 2);
+ while (num > 0) {
+ dec = (num % 10).toString() + dec;
+ num = Math.floor(num / 10);
+ }
+
+ return dec;
+ }
+
+ /**
+ * Breaks user, role and everyone/here mentions by adding a zero width space after every @ character
+ * @param {string} str The string to sanitize
+ * @returns {string}
+ */
+ static removeMentions(str) {
+ return str.replace(/@/g, '@\u200b');
+ }
+
+ /**
+ * The content to have all mentions replaced by the equivalent text.
+ * @param {string} str The string to be converted
+ * @param {Message} message The message object to reference
+ * @returns {string}
+ */
+ static cleanContent(str, message) {
+ str = str
+ .replace(/<@!?[0-9]+>/g, input => {
+ const id = input.replace(/<|!|>|@/g, '');
+ if (message.channel.type === 'dm') {
+ const user = message.client.users.cache.get(id);
+ return user ? `@${user.username}` : input;
+ }
+
+ const member = message.channel.guild.members.cache.get(id);
+ if (member) {
+ return `@${member.displayName}`;
+ } else {
+ const user = message.client.users.cache.get(id);
+ return user ? `@${user.username}` : input;
+ }
+ })
+ .replace(/<#[0-9]+>/g, input => {
+ const channel = message.client.channels.cache.get(input.replace(/<|#|>/g, ''));
+ return channel ? `#${channel.name}` : input;
+ })
+ .replace(/<@&[0-9]+>/g, input => {
+ if (message.channel.type === 'dm') return input;
+ const role = message.guild.roles.cache.get(input.replace(/<|@|>|&/g, ''));
+ return role ? `@${role.name}` : input;
+ });
+ if (message.client.options.disableMentions === 'everyone') {
+ str = str.replace(/@([^<>@ ]*)/gmsu, (match, target) => {
+ if (target.match(/^[&!]?\d+$/)) {
+ return `@${target}`;
+ } else {
+ return `@\u200b${target}`;
+ }
+ });
+ }
+ if (message.client.options.disableMentions === 'all') {
+ return Util.removeMentions(str);
+ } else {
+ return str;
+ }
+ }
+
+ /**
+ * The content to put in a codeblock with all codeblock fences replaced by the equivalent backticks.
+ * @param {string} text The string to be converted
+ * @returns {string}
+ */
+ static cleanCodeBlockContent(text) {
+ return text.replace(/```/g, '`\u200b``');
+ }
+
+ /**
+ * Creates a Promise that resolves after a specified duration.
+ * @param {number} ms How long to wait before resolving (in milliseconds)
+ * @returns {Promise<void>}
+ * @private
+ */
+ static delayFor(ms) {
+ return new Promise(resolve => {
+ setTimeout(resolve, ms);
+ });
+ }
+}
+
+module.exports = Util;
diff --git a/node_modules/discord.js/typings/index.d.ts b/node_modules/discord.js/typings/index.d.ts
new file mode 100644
index 0000000..0470ca6
--- /dev/null
+++ b/node_modules/discord.js/typings/index.d.ts
@@ -0,0 +1,3080 @@
+declare enum ChannelType {
+ text = 0,
+ dm = 1,
+ voice = 2,
+ group = 3,
+ category = 4,
+ news = 5,
+ store = 6,
+ unknown = 7,
+}
+
+declare module 'discord.js' {
+ import BaseCollection from '@discordjs/collection';
+ import { ChildProcess } from 'child_process';
+ import { EventEmitter } from 'events';
+ import { PathLike } from 'fs';
+ import { Readable, Stream, Writable } from 'stream';
+ import * as WebSocket from 'ws';
+
+ export const version: string;
+
+ //#region Classes
+
+ export class Activity {
+ constructor(presence: Presence, data?: object);
+ public applicationID: Snowflake | null;
+ public assets: RichPresenceAssets | null;
+ public readonly createdAt: Date;
+ public createdTimestamp: number;
+ public details: string | null;
+ public emoji: Emoji | null;
+ public name: string;
+ public party: {
+ id: string | null;
+ size: [number, number];
+ } | null;
+ public state: string | null;
+ public timestamps: {
+ start: Date | null;
+ end: Date | null;
+ } | null;
+ public type: ActivityType;
+ public url: string | null;
+ public equals(activity: Activity): boolean;
+ }
+
+ export class ActivityFlags extends BitField<ActivityFlagsString> {
+ public static FLAGS: Record<ActivityFlagsString, number>;
+ public static resolve(bit?: BitFieldResolvable<ActivityFlagsString>): number;
+ }
+
+ export class APIMessage {
+ constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions);
+ public data: object | null;
+ public readonly isUser: boolean;
+ public readonly isWebhook: boolean;
+ public files: object[] | null;
+ public options: MessageOptions | WebhookMessageOptions;
+ public target: MessageTarget;
+
+ public static create(
+ target: MessageTarget,
+ content?: StringResolvable,
+ options?: MessageOptions | WebhookMessageOptions | MessageAdditions,
+ extra?: MessageOptions | WebhookMessageOptions,
+ ): APIMessage;
+ public static partitionMessageAdditions(
+ items: (MessageEmbed | MessageAttachment)[],
+ ): [MessageEmbed[], MessageAttachment[]];
+ public static resolveFile(fileLike: BufferResolvable | Stream | FileOptions | MessageAttachment): Promise<object>;
+ public static transformOptions(
+ content: StringResolvable,
+ options: MessageOptions | WebhookMessageOptions | MessageAdditions,
+ extra?: MessageOptions | WebhookMessageOptions,
+ isWebhook?: boolean,
+ ): MessageOptions | WebhookMessageOptions;
+
+ public makeContent(): string | string[] | undefined;
+ public resolve(): Promise<this>;
+ public resolveData(): this;
+ public resolveFiles(): Promise<this>;
+ public split(): APIMessage[];
+ }
+
+ export class Base {
+ constructor(client: Client);
+ public readonly client: Client;
+ public toJSON(...props: { [key: string]: boolean | string }[]): object;
+ public valueOf(): string;
+ }
+
+ export class BaseClient extends EventEmitter {
+ constructor(options?: ClientOptions);
+ private _timeouts: Set<NodeJS.Timer>;
+ private _intervals: Set<NodeJS.Timer>;
+ private _immediates: Set<NodeJS.Immediate>;
+ private readonly api: object;
+ private rest: object;
+
+ public options: ClientOptions;
+ public clearInterval(interval: NodeJS.Timer): void;
+ public clearTimeout(timeout: NodeJS.Timer): void;
+ public clearImmediate(timeout: NodeJS.Immediate): void;
+ public destroy(): void;
+ public setInterval(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timer;
+ public setTimeout(fn: (...args: any[]) => void, delay: number, ...args: any[]): NodeJS.Timer;
+ public setImmediate(fn: (...args: any[]) => void, ...args: any[]): NodeJS.Immediate;
+ public toJSON(...props: { [key: string]: boolean | string }[]): object;
+ }
+
+ export class BaseGuildEmoji extends Emoji {
+ constructor(client: Client, data: object, guild: Guild);
+ private _roles: string[];
+
+ public available: boolean;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public guild: Guild | GuildPreview;
+ public id: Snowflake;
+ public managed: boolean;
+ public requiresColons: boolean;
+ }
+
+ class BroadcastDispatcher extends VolumeMixin(StreamDispatcher) {
+ public broadcast: VoiceBroadcast;
+ }
+
+ export class BitField<S extends string> {
+ constructor(bits?: BitFieldResolvable<S>);
+ public bitfield: number;
+ public add(...bits: BitFieldResolvable<S>[]): BitField<S>;
+ public any(bit: BitFieldResolvable<S>): boolean;
+ public equals(bit: BitFieldResolvable<S>): boolean;
+ public freeze(): Readonly<BitField<S>>;
+ public has(bit: BitFieldResolvable<S>): boolean;
+ public missing(bits: BitFieldResolvable<S>, ...hasParam: readonly unknown[]): S[];
+ public remove(...bits: BitFieldResolvable<S>[]): BitField<S>;
+ public serialize(...hasParam: readonly unknown[]): Record<S, boolean>;
+ public toArray(...hasParam: readonly unknown[]): S[];
+ public toJSON(): number;
+ public valueOf(): number;
+ public [Symbol.iterator](): IterableIterator<S>;
+ public static FLAGS: object;
+ public static resolve(bit?: BitFieldResolvable<any>): number;
+ }
+
+ export class CategoryChannel extends GuildChannel {
+ public readonly children: Collection<Snowflake, GuildChannel>;
+ public type: 'category';
+ }
+
+ export class Channel extends Base {
+ constructor(client: Client, data?: object);
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public deleted: boolean;
+ public id: Snowflake;
+ public type: keyof typeof ChannelType;
+ public delete(reason?: string): Promise<this>;
+ public fetch(): Promise<this>;
+ public toString(): string;
+ }
+
+ export class Client extends BaseClient {
+ constructor(options?: ClientOptions);
+ private actions: object;
+ private _eval(script: string): any;
+ private _validateOptions(options?: ClientOptions): void;
+
+ public channels: ChannelManager;
+ public readonly emojis: GuildEmojiManager;
+ public guilds: GuildManager;
+ public readyAt: Date | null;
+ public readonly readyTimestamp: number | null;
+ public shard: ShardClientUtil | null;
+ public token: string | null;
+ public readonly uptime: number | null;
+ public user: ClientUser | null;
+ public users: UserManager;
+ public voice: ClientVoiceManager | null;
+ public ws: WebSocketManager;
+ public destroy(): void;
+ public fetchApplication(): Promise<ClientApplication>;
+ public fetchGuildPreview(guild: GuildResolvable): Promise<GuildPreview>;
+ public fetchInvite(invite: InviteResolvable): Promise<Invite>;
+ public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>;
+ public fetchWebhook(id: Snowflake, token?: string): Promise<Webhook>;
+ public generateInvite(permissions?: PermissionResolvable): Promise<string>;
+ public login(token?: string): Promise<string>;
+ public sweepMessages(lifetime?: number): number;
+ public toJSON(): object;
+
+ public on<K extends keyof ClientEvents>(event: K, listener: (...args: ClientEvents[K]) => void): this;
+
+ public once<K extends keyof ClientEvents>(event: K, listener: (...args: ClientEvents[K]) => void): this;
+
+ public emit<K extends keyof ClientEvents>(event: K, ...args: ClientEvents[K]): boolean;
+ }
+
+ export class ClientApplication extends Base {
+ constructor(client: Client, data: object);
+ public botPublic: boolean | null;
+ public botRequireCodeGrant: boolean | null;
+ public cover: string | null;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public description: string;
+ public icon: string;
+ public id: Snowflake;
+ public name: string;
+ public owner: User | Team | null;
+ public rpcOrigins: string[];
+ public coverImage(options?: ImageURLOptions): string;
+ public fetchAssets(): Promise<ClientApplicationAsset[]>;
+ public iconURL(options?: ImageURLOptions): string;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class ClientUser extends User {
+ public mfaEnabled: boolean;
+ public verified: boolean;
+ public setActivity(options?: ActivityOptions): Promise<Presence>;
+ public setActivity(name: string, options?: ActivityOptions): Promise<Presence>;
+ public setAFK(afk: boolean): Promise<Presence>;
+ public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise<ClientUser>;
+ public setPresence(data: PresenceData): Promise<Presence>;
+ public setStatus(status: PresenceStatusData, shardID?: number | number[]): Promise<Presence>;
+ public setUsername(username: string): Promise<ClientUser>;
+ }
+
+ export class ClientVoiceManager {
+ constructor(client: Client);
+ public readonly client: Client;
+ public connections: Collection<Snowflake, VoiceConnection>;
+ public broadcasts: VoiceBroadcast[];
+
+ private joinChannel(channel: VoiceChannel): Promise<VoiceConnection>;
+
+ public createBroadcast(): VoiceBroadcast;
+ }
+
+ export abstract class Collector<K, V> extends EventEmitter {
+ constructor(client: Client, filter: CollectorFilter, options?: CollectorOptions);
+ private _timeout: NodeJS.Timer | null;
+ private _idletimeout: NodeJS.Timer | null;
+
+ public readonly client: Client;
+ public collected: Collection<K, V>;
+ public ended: boolean;
+ public filter: CollectorFilter;
+ public readonly next: Promise<V>;
+ public options: CollectorOptions;
+ public checkEnd(): void;
+ public handleCollect(...args: any[]): void;
+ public handleDispose(...args: any[]): void;
+ public stop(reason?: string): void;
+ public resetTimer(options?: { time?: number; idle?: number }): void;
+ public [Symbol.asyncIterator](): AsyncIterableIterator<V>;
+ public toJSON(): object;
+
+ protected listener: (...args: any[]) => void;
+ public abstract collect(...args: any[]): K;
+ public abstract dispose(...args: any[]): K;
+ public abstract endReason(): void;
+
+ public on(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this;
+ public on(event: 'end', listener: (collected: Collection<K, V>, reason: string) => void): this;
+
+ public once(event: 'collect' | 'dispose', listener: (...args: any[]) => void): this;
+ public once(event: 'end', listener: (collected: Collection<K, V>, reason: string) => void): this;
+ }
+
+ type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif';
+
+ export const Constants: {
+ Package: {
+ name: string;
+ version: string;
+ description: string;
+ author: string;
+ license: string;
+ main: PathLike;
+ types: PathLike;
+ homepage: string;
+ keywords: string[];
+ bugs: { url: string };
+ repository: { type: string; url: string };
+ browser: { [key: string]: boolean };
+ scripts: { [key: string]: string };
+ engines: { [key: string]: string };
+ dependencies: { [key: string]: string };
+ peerDependencies: { [key: string]: string };
+ devDependencies: { [key: string]: string };
+ [key: string]: any;
+ };
+ browser: boolean;
+ DefaultOptions: ClientOptions;
+ UserAgent: string | null;
+ Endpoints: {
+ botGateway: string;
+ invite: (root: string, code: string) => string;
+ CDN: (
+ root: string,
+ ) => {
+ Asset: (name: string) => string;
+ DefaultAvatar: (id: string | number) => string;
+ Emoji: (emojiID: string, format: 'png' | 'gif') => string;
+ Avatar: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string;
+ Banner: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ Icon: (userID: string | number, hash: string, format: 'default' | AllowedImageFormat, size: number) => string;
+ AppIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ AppAsset: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ GDMIcon: (userID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ Splash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ DiscoverySplash: (guildID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ TeamIcon: (teamID: string | number, hash: string, format: AllowedImageFormat, size: number) => string;
+ };
+ };
+ WSCodes: {
+ 1000: 'WS_CLOSE_REQUESTED';
+ 4004: 'TOKEN_INVALID';
+ 4010: 'SHARDING_INVALID';
+ 4011: 'SHARDING_REQUIRED';
+ };
+ Events: {
+ RATE_LIMIT: 'rateLimit';
+ CLIENT_READY: 'ready';
+ RESUMED: 'resumed';
+ GUILD_CREATE: 'guildCreate';
+ GUILD_DELETE: 'guildDelete';
+ GUILD_UPDATE: 'guildUpdate';
+ INVITE_CREATE: 'inviteCreate';
+ INVITE_DELETE: 'inviteDelete';
+ GUILD_UNAVAILABLE: 'guildUnavailable';
+ GUILD_MEMBER_ADD: 'guildMemberAdd';
+ GUILD_MEMBER_REMOVE: 'guildMemberRemove';
+ GUILD_MEMBER_UPDATE: 'guildMemberUpdate';
+ GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable';
+ GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking';
+ GUILD_MEMBERS_CHUNK: 'guildMembersChunk';
+ GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate';
+ GUILD_ROLE_CREATE: 'roleCreate';
+ GUILD_ROLE_DELETE: 'roleDelete';
+ GUILD_ROLE_UPDATE: 'roleUpdate';
+ GUILD_EMOJI_CREATE: 'emojiCreate';
+ GUILD_EMOJI_DELETE: 'emojiDelete';
+ GUILD_EMOJI_UPDATE: 'emojiUpdate';
+ GUILD_BAN_ADD: 'guildBanAdd';
+ GUILD_BAN_REMOVE: 'guildBanRemove';
+ CHANNEL_CREATE: 'channelCreate';
+ CHANNEL_DELETE: 'channelDelete';
+ CHANNEL_UPDATE: 'channelUpdate';
+ CHANNEL_PINS_UPDATE: 'channelPinsUpdate';
+ MESSAGE_CREATE: 'message';
+ MESSAGE_DELETE: 'messageDelete';
+ MESSAGE_UPDATE: 'messageUpdate';
+ MESSAGE_BULK_DELETE: 'messageDeleteBulk';
+ MESSAGE_REACTION_ADD: 'messageReactionAdd';
+ MESSAGE_REACTION_REMOVE: 'messageReactionRemove';
+ MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll';
+ USER_UPDATE: 'userUpdate';
+ PRESENCE_UPDATE: 'presenceUpdate';
+ VOICE_STATE_UPDATE: 'voiceStateUpdate';
+ VOICE_BROADCAST_SUBSCRIBE: 'subscribe';
+ VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe';
+ TYPING_START: 'typingStart';
+ WEBHOOKS_UPDATE: 'webhookUpdate';
+ DISCONNECT: 'disconnect';
+ RECONNECTING: 'reconnecting';
+ ERROR: 'error';
+ WARN: 'warn';
+ DEBUG: 'debug';
+ SHARD_DISCONNECT: 'shardDisconnect';
+ SHARD_ERROR: 'shardError';
+ SHARD_RECONNECTING: 'shardReconnecting';
+ SHARD_READY: 'shardReady';
+ SHARD_RESUME: 'shardResume';
+ INVALIDATED: 'invalidated';
+ RAW: 'raw';
+ };
+ ShardEvents: {
+ CLOSE: 'close';
+ DESTROYED: 'destroyed';
+ INVALID_SESSION: 'invalidSession';
+ READY: 'ready';
+ RESUMED: 'resumed';
+ };
+ PartialTypes: {
+ [K in PartialTypes]: K;
+ };
+ WSEvents: {
+ [K in WSEventType]: K;
+ };
+ Colors: {
+ DEFAULT: 0x000000;
+ WHITE: 0xffffff;
+ AQUA: 0x1abc9c;
+ GREEN: 0x2ecc71;
+ BLUE: 0x3498db;
+ YELLOW: 0xffff00;
+ PURPLE: 0x9b59b6;
+ LUMINOUS_VIVID_PINK: 0xe91e63;
+ GOLD: 0xf1c40f;
+ ORANGE: 0xe67e22;
+ RED: 0xe74c3c;
+ GREY: 0x95a5a6;
+ NAVY: 0x34495e;
+ DARK_AQUA: 0x11806a;
+ DARK_GREEN: 0x1f8b4c;
+ DARK_BLUE: 0x206694;
+ DARK_PURPLE: 0x71368a;
+ DARK_VIVID_PINK: 0xad1457;
+ DARK_GOLD: 0xc27c0e;
+ DARK_ORANGE: 0xa84300;
+ DARK_RED: 0x992d22;
+ DARK_GREY: 0x979c9f;
+ DARKER_GREY: 0x7f8c8d;
+ LIGHT_GREY: 0xbcc0c0;
+ DARK_NAVY: 0x2c3e50;
+ BLURPLE: 0x7289da;
+ GREYPLE: 0x99aab5;
+ DARK_BUT_NOT_BLACK: 0x2c2f33;
+ NOT_QUITE_BLACK: 0x23272a;
+ };
+ Status: {
+ READY: 0;
+ CONNECTING: 1;
+ RECONNECTING: 2;
+ IDLE: 3;
+ NEARLY: 4;
+ DISCONNECTED: 5;
+ };
+ OPCodes: {
+ DISPATCH: 0;
+ HEARTBEAT: 1;
+ IDENTIFY: 2;
+ STATUS_UPDATE: 3;
+ VOICE_STATE_UPDATE: 4;
+ VOICE_GUILD_PING: 5;
+ RESUME: 6;
+ RECONNECT: 7;
+ REQUEST_GUILD_MEMBERS: 8;
+ INVALID_SESSION: 9;
+ HELLO: 10;
+ HEARTBEAT_ACK: 11;
+ };
+ APIErrors: {
+ UNKNOWN_ACCOUNT: 10001;
+ UNKNOWN_APPLICATION: 10002;
+ UNKNOWN_CHANNEL: 10003;
+ UNKNOWN_GUILD: 10004;
+ UNKNOWN_INTEGRATION: 10005;
+ UNKNOWN_INVITE: 10006;
+ UNKNOWN_MEMBER: 10007;
+ UNKNOWN_MESSAGE: 10008;
+ UNKNOWN_OVERWRITE: 10009;
+ UNKNOWN_PROVIDER: 10010;
+ UNKNOWN_ROLE: 10011;
+ UNKNOWN_TOKEN: 10012;
+ UNKNOWN_USER: 10013;
+ UNKNOWN_EMOJI: 10014;
+ UNKNOWN_WEBHOOK: 10015;
+ BOT_PROHIBITED_ENDPOINT: 20001;
+ BOT_ONLY_ENDPOINT: 20002;
+ MAXIMUM_GUILDS: 30001;
+ MAXIMUM_FRIENDS: 30002;
+ MAXIMUM_PINS: 30003;
+ MAXIMUM_ROLES: 30005;
+ MAXIMUM_REACTIONS: 30010;
+ MAXIMUM_CHANNELS: 30013;
+ MAXIMUM_INVITES: 30016;
+ UNAUTHORIZED: 40001;
+ USER_BANNED: 40007;
+ MISSING_ACCESS: 50001;
+ INVALID_ACCOUNT_TYPE: 50002;
+ CANNOT_EXECUTE_ON_DM: 50003;
+ EMBED_DISABLED: 50004;
+ CANNOT_EDIT_MESSAGE_BY_OTHER: 50005;
+ CANNOT_SEND_EMPTY_MESSAGE: 50006;
+ CANNOT_MESSAGE_USER: 50007;
+ CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008;
+ CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009;
+ OAUTH2_APPLICATION_BOT_ABSENT: 50010;
+ MAXIMUM_OAUTH2_APPLICATIONS: 50011;
+ INVALID_OAUTH_STATE: 50012;
+ MISSING_PERMISSIONS: 50013;
+ INVALID_AUTHENTICATION_TOKEN: 50014;
+ NOTE_TOO_LONG: 50015;
+ INVALID_BULK_DELETE_QUANTITY: 50016;
+ CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019;
+ CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021;
+ INVALID_OAUTH_TOKEN: 50025;
+ BULK_DELETE_MESSAGE_TOO_OLD: 50034;
+ INVALID_FORM_BODY: 50035;
+ INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036;
+ INVALID_API_VERSION: 50041;
+ REACTION_BLOCKED: 90001;
+ RESOURCE_OVERLOADED: 130000;
+ };
+ VoiceStatus: {
+ CONNECTED: 0;
+ CONNECTING: 1;
+ AUTHENTICATING: 2;
+ RECONNECTING: 3;
+ DISCONNECTED: 4;
+ };
+ VoiceOPCodes: {
+ IDENTIFY: 0;
+ SELECT_PROTOCOL: 1;
+ READY: 2;
+ HEARTBEAT: 3;
+ SESSION_DESCRIPTION: 4;
+ SPEAKING: 5;
+ HELLO: 8;
+ CLIENT_CONNECT: 12;
+ CLIENT_DISCONNECT: 13;
+ };
+ ChannelTypes: {
+ TEXT: 0;
+ DM: 1;
+ VOICE: 2;
+ GROUP: 3;
+ CATEGORY: 4;
+ NEWS: 5;
+ STORE: 6;
+ };
+ ClientApplicationAssetTypes: {
+ SMALL: 1;
+ BIG: 2;
+ };
+ MessageTypes: MessageType[];
+ ActivityTypes: ActivityType[];
+ ExplicitContentFilterLevels: ExplicitContentFilterLevel[];
+ DefaultMessageNotifications: DefaultMessageNotifications[];
+ VerificationLevels: VerificationLevel[];
+ MembershipStates: 'INVITED' | 'ACCEPTED';
+ };
+
+ export class DataResolver {
+ public static resolveBase64(data: Base64Resolvable): string;
+ public static resolveFile(resource: BufferResolvable | Stream): Promise<Buffer | Stream>;
+ public static resolveFileAsBuffer(resource: BufferResolvable | Stream): Promise<Buffer>;
+ public static resolveImage(resource: BufferResolvable | Base64Resolvable): Promise<string>;
+ public static resolveInviteCode(data: InviteResolvable): string;
+ }
+
+ export class DiscordAPIError extends Error {
+ constructor(path: string, error: object, method: string, httpStatus: number);
+ private static flattenErrors(obj: object, key: string): string[];
+
+ public code: number;
+ public method: string;
+ public path: string;
+ public httpStatus: number;
+ }
+
+ export class DMChannel extends TextBasedChannel(Channel) {
+ constructor(client: Client, data?: object);
+ public messages: MessageManager;
+ public recipient: User;
+ public readonly partial: false;
+ public type: 'dm';
+ public fetch(): Promise<this>;
+ }
+
+ export class Emoji extends Base {
+ constructor(client: Client, emoji: object);
+ public animated: boolean;
+ public readonly createdAt: Date | null;
+ public readonly createdTimestamp: number | null;
+ public deleted: boolean;
+ public id: Snowflake | null;
+ public name: string;
+ public readonly identifier: string;
+ public readonly url: string | null;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class Guild extends Base {
+ constructor(client: Client, data: object);
+ private _sortedRoles(): Collection<Snowflake, Role>;
+ private _sortedChannels(channel: Channel): Collection<Snowflake, GuildChannel>;
+ private _memberSpeakUpdate(user: Snowflake, speaking: boolean): void;
+
+ public readonly afkChannel: VoiceChannel | null;
+ public afkChannelID: Snowflake | null;
+ public afkTimeout: number;
+ public applicationID: Snowflake | null;
+ public available: boolean;
+ public banner: string | null;
+ public channels: GuildChannelManager;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public defaultMessageNotifications: DefaultMessageNotifications | number;
+ public deleted: boolean;
+ public description: string | null;
+ public embedChannel: GuildChannel | null;
+ public embedChannelID: Snowflake | null;
+ public embedEnabled: boolean;
+ public emojis: GuildEmojiManager;
+ public explicitContentFilter: ExplicitContentFilterLevel;
+ public features: GuildFeatures[];
+ public icon: string | null;
+ public id: Snowflake;
+ public readonly joinedAt: Date;
+ public joinedTimestamp: number;
+ public large: boolean;
+ public maximumMembers: number | null;
+ public maximumPresences: number | null;
+ public readonly me: GuildMember | null;
+ public memberCount: number;
+ public members: GuildMemberManager;
+ public mfaLevel: number;
+ public name: string;
+ public readonly nameAcronym: string;
+ public readonly owner: GuildMember | null;
+ public ownerID: Snowflake;
+ public readonly partnered: boolean;
+ public premiumSubscriptionCount: number | null;
+ public premiumTier: PremiumTier;
+ public presences: PresenceManager;
+ public readonly publicUpdatesChannel: TextChannel | null;
+ public publicUpdatesChannelID: Snowflake | null;
+ public region: string;
+ public roles: RoleManager;
+ public readonly rulesChannel: TextChannel | null;
+ public rulesChannelID: Snowflake | null;
+ public readonly shard: WebSocketShard;
+ public shardID: number;
+ public splash: string | null;
+ public readonly systemChannel: TextChannel | null;
+ public systemChannelFlags: Readonly<SystemChannelFlags>;
+ public systemChannelID: Snowflake | null;
+ public vanityURLCode: string | null;
+ public verificationLevel: VerificationLevel;
+ public readonly verified: boolean;
+ public readonly voice: VoiceState | null;
+ public readonly voiceStates: VoiceStateManager;
+ public readonly widgetChannel: TextChannel | null;
+ public widgetChannelID: Snowflake | null;
+ public widgetEnabled: boolean | null;
+ public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise<GuildMember>;
+ public bannerURL(options?: ImageURLOptions): string | null;
+ public createIntegration(data: IntegrationData, reason?: string): Promise<Guild>;
+ public delete(): Promise<Guild>;
+ public edit(data: GuildEditData, reason?: string): Promise<Guild>;
+ public equals(guild: Guild): boolean;
+ public fetch(): Promise<Guild>;
+ public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise<GuildAuditLogs>;
+ public fetchBan(user: UserResolvable): Promise<{ user: User; reason: string }>;
+ public fetchBans(): Promise<Collection<Snowflake, { user: User; reason: string }>>;
+ public fetchEmbed(): Promise<GuildEmbedData>;
+ public fetchIntegrations(): Promise<Collection<string, Integration>>;
+ public fetchInvites(): Promise<Collection<string, Invite>>;
+ public fetchPreview(): Promise<GuildPreview>;
+ public fetchVanityCode(): Promise<string>;
+ public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>;
+ public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
+ public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null;
+ public leave(): Promise<Guild>;
+ public member(user: UserResolvable): GuildMember | null;
+ public setAFKChannel(afkChannel: ChannelResolvable | null, reason?: string): Promise<Guild>;
+ public setAFKTimeout(afkTimeout: number, reason?: string): Promise<Guild>;
+ public setBanner(banner: Base64Resolvable | null, reason?: string): Promise<Guild>;
+ public setChannelPositions(channelPositions: ChannelPosition[]): Promise<Guild>;
+ public setDefaultMessageNotifications(
+ defaultMessageNotifications: DefaultMessageNotifications | number,
+ reason?: string,
+ ): Promise<Guild>;
+ public setEmbed(embed: GuildEmbedData, reason?: string): Promise<Guild>;
+ public setExplicitContentFilter(explicitContentFilter: ExplicitContentFilterLevel, reason?: string): Promise<Guild>;
+ public setIcon(icon: Base64Resolvable | null, reason?: string): Promise<Guild>;
+ public setName(name: string, reason?: string): Promise<Guild>;
+ public setOwner(owner: GuildMemberResolvable, reason?: string): Promise<Guild>;
+ public setRegion(region: string, reason?: string): Promise<Guild>;
+ public setRolePositions(rolePositions: RolePosition[]): Promise<Guild>;
+ public setSplash(splash: Base64Resolvable | null, reason?: string): Promise<Guild>;
+ public setSystemChannel(systemChannel: ChannelResolvable | null, reason?: string): Promise<Guild>;
+ public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise<Guild>;
+ public setVerificationLevel(verificationLevel: VerificationLevel, reason?: string): Promise<Guild>;
+ public splashURL(options?: ImageURLOptions): string | null;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class GuildAuditLogs {
+ constructor(guild: Guild, data: object);
+ private webhooks: Collection<Snowflake, Webhook>;
+ private integrations: Collection<Snowflake, Integration>;
+
+ public entries: Collection<Snowflake, GuildAuditLogsEntry>;
+
+ public static Actions: GuildAuditLogsActions;
+ public static Targets: GuildAuditLogsTargets;
+ public static Entry: typeof GuildAuditLogsEntry;
+ public static actionType(action: number): GuildAuditLogsActionType;
+ public static build(...args: any[]): Promise<GuildAuditLogs>;
+ public static targetType(target: number): GuildAuditLogsTarget;
+ public toJSON(): object;
+ }
+
+ class GuildAuditLogsEntry {
+ constructor(logs: GuildAuditLogs, guild: Guild, data: object);
+ public action: GuildAuditLogsAction;
+ public actionType: GuildAuditLogsActionType;
+ public changes: AuditLogChange[] | null;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public executor: User;
+ public extra: object | Role | GuildMember | null;
+ public id: Snowflake;
+ public reason: string | null;
+ public target: Guild | User | Role | GuildEmoji | Invite | Webhook | Integration | null;
+ public targetType: GuildAuditLogsTarget;
+ public toJSON(): object;
+ }
+
+ export class GuildChannel extends Channel {
+ constructor(guild: Guild, data?: object);
+ private memberPermissions(member: GuildMember): Readonly<Permissions>;
+ private rolePermissions(role: Role): Readonly<Permissions>;
+
+ public readonly calculatedPosition: number;
+ public readonly deletable: boolean;
+ public guild: Guild;
+ public readonly manageable: boolean;
+ public readonly members: Collection<Snowflake, GuildMember>;
+ public name: string;
+ public readonly parent: CategoryChannel | null;
+ public parentID: Snowflake | null;
+ public permissionOverwrites: Collection<Snowflake, PermissionOverwrites>;
+ public readonly permissionsLocked: boolean | null;
+ public readonly position: number;
+ public rawPosition: number;
+ public type: Exclude<keyof typeof ChannelType, 'dm' | 'group' | 'unknown'>;
+ public readonly viewable: boolean;
+ public clone(options?: GuildChannelCloneOptions): Promise<this>;
+ public createInvite(options?: InviteOptions): Promise<Invite>;
+ public createOverwrite(
+ userOrRole: RoleResolvable | UserResolvable,
+ options: PermissionOverwriteOption,
+ reason?: string,
+ ): Promise<this>;
+ public edit(data: ChannelData, reason?: string): Promise<this>;
+ public equals(channel: GuildChannel): boolean;
+ public fetchInvites(): Promise<Collection<string, Invite>>;
+ public lockPermissions(): Promise<this>;
+ public overwritePermissions(
+ overwrites: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>,
+ reason?: string,
+ ): Promise<this>;
+ public permissionsFor(memberOrRole: GuildMemberResolvable | RoleResolvable): Readonly<Permissions> | null;
+ public setName(name: string, reason?: string): Promise<this>;
+ public setParent(
+ channel: CategoryChannel | Snowflake,
+ options?: { lockPermissions?: boolean; reason?: string },
+ ): Promise<this>;
+ public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise<this>;
+ public setTopic(topic: string, reason?: string): Promise<this>;
+ public updateOverwrite(
+ userOrRole: RoleResolvable | UserResolvable,
+ options: PermissionOverwriteOption,
+ reason?: string,
+ ): Promise<this>;
+ }
+
+ export class GuildEmoji extends BaseGuildEmoji {
+ public readonly deletable: boolean;
+ public guild: Guild;
+ public readonly roles: GuildEmojiRoleManager;
+ public readonly url: string;
+ public delete(reason?: string): Promise<GuildEmoji>;
+ public edit(data: GuildEmojiEditData, reason?: string): Promise<GuildEmoji>;
+ public equals(other: GuildEmoji | object): boolean;
+ public fetchAuthor(): Promise<User>;
+ public setName(name: string, reason?: string): Promise<GuildEmoji>;
+ }
+
+ export class GuildMember extends PartialTextBasedChannel(Base) {
+ constructor(client: Client, data: object, guild: Guild);
+ public readonly bannable: boolean;
+ public deleted: boolean;
+ public readonly displayColor: number;
+ public readonly displayHexColor: string;
+ public readonly displayName: string;
+ public guild: Guild;
+ public readonly id: Snowflake;
+ public readonly joinedAt: Date | null;
+ public joinedTimestamp: number | null;
+ public readonly kickable: boolean;
+ public lastMessageChannelID: Snowflake | null;
+ public readonly manageable: boolean;
+ public nickname: string | null;
+ public readonly partial: false;
+ public readonly permissions: Readonly<Permissions>;
+ public readonly premiumSince: Date | null;
+ public premiumSinceTimestamp: number | null;
+ public readonly presence: Presence;
+ public readonly roles: GuildMemberRoleManager;
+ public user: User;
+ public readonly voice: VoiceState;
+ public ban(options?: BanOptions): Promise<GuildMember>;
+ public fetch(): Promise<GuildMember>;
+ public createDM(): Promise<DMChannel>;
+ public deleteDM(): Promise<DMChannel>;
+ public edit(data: GuildMemberEditData, reason?: string): Promise<GuildMember>;
+ public hasPermission(
+ permission: PermissionResolvable,
+ options?: { checkAdmin?: boolean; checkOwner?: boolean },
+ ): boolean;
+ public kick(reason?: string): Promise<GuildMember>;
+ public permissionsIn(channel: ChannelResolvable): Readonly<Permissions>;
+ public setNickname(nickname: string, reason?: string): Promise<GuildMember>;
+ public toJSON(): object;
+ public toString(): string;
+ public valueOf(): string;
+ }
+
+ export class GuildPreview extends Base {
+ constructor(client: Client, data: object);
+ public approximateMemberCount: number;
+ public approximatePresenceCount: number;
+ public description?: string;
+ public discoverySplash: string | null;
+ public emojis: Collection<Snowflake, GuildPreviewEmoji>;
+ public features: GuildFeatures[];
+ public icon: string | null;
+ public id: string;
+ public name: string;
+ public splash: string | null;
+ public discoverySplashURL(options?: ImageURLOptions): string | null;
+ public iconURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null;
+ public splashURL(options?: ImageURLOptions): string | null;
+ public fetch(): Promise<GuildPreview>;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class GuildPreviewEmoji extends BaseGuildEmoji {
+ constructor(client: Client, data: object, guild: GuildPreview);
+ public guild: GuildPreview;
+ public readonly roles: Set<Snowflake>;
+ }
+
+ export class HTTPError extends Error {
+ constructor(message: string, name: string, code: number, method: string, path: string);
+ public code: number;
+ public method: string;
+ public name: string;
+ public path: string;
+ }
+
+ export class Integration extends Base {
+ constructor(client: Client, data: object, guild: Guild);
+ public account: IntegrationAccount;
+ public enabled: boolean;
+ public expireBehavior: number;
+ public expireGracePeriod: number;
+ public guild: Guild;
+ public id: Snowflake;
+ public name: string;
+ public role: Role;
+ public syncedAt: number;
+ public syncing: boolean;
+ public type: string;
+ public user: User;
+ public delete(reason?: string): Promise<Integration>;
+ public edit(data: IntegrationEditData, reason?: string): Promise<Integration>;
+ public sync(): Promise<Integration>;
+ }
+
+ export class Intents extends BitField<IntentsString> {
+ public static FLAGS: Record<IntentsString, number>;
+ public static PRIVILEGED: number;
+ public static ALL: number;
+ public static NON_PRIVILEGED: number;
+ public static resolve(bit?: BitFieldResolvable<IntentsString>): number;
+ }
+
+ export class Invite extends Base {
+ constructor(client: Client, data: object);
+ public channel: GuildChannel | PartialGroupDMChannel;
+ public code: string;
+ public readonly deletable: boolean;
+ public readonly createdAt: Date | null;
+ public createdTimestamp: number | null;
+ public readonly expiresAt: Date | null;
+ public readonly expiresTimestamp: number | null;
+ public guild: Guild | null;
+ public inviter: User | null;
+ public maxAge: number | null;
+ public maxUses: number | null;
+ public memberCount: number;
+ public presenceCount: number;
+ public targetUser: User | null;
+ public targetUserType: TargetUser | null;
+ public temporary: boolean | null;
+ public readonly url: string;
+ public uses: number | null;
+ public delete(reason?: string): Promise<Invite>;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class Message extends Base {
+ constructor(client: Client, data: object, channel: TextChannel | DMChannel);
+ private _edits: Message[];
+ private patch(data: object): void;
+
+ public activity: MessageActivity | null;
+ public application: ClientApplication | null;
+ public attachments: Collection<Snowflake, MessageAttachment>;
+ public author: User;
+ public channel: TextChannel | DMChannel | NewsChannel;
+ public readonly cleanContent: string;
+ public content: string;
+ public readonly createdAt: Date;
+ public createdTimestamp: number;
+ public readonly deletable: boolean;
+ public deleted: boolean;
+ public readonly editable: boolean;
+ public readonly editedAt: Date | null;
+ public editedTimestamp: number | null;
+ public readonly edits: Message[];
+ public embeds: MessageEmbed[];
+ public readonly guild: Guild | null;
+ public id: Snowflake;
+ public readonly member: GuildMember | null;
+ public mentions: MessageMentions;
+ public nonce: string | null;
+ public readonly partial: false;
+ public readonly pinnable: boolean;
+ public pinned: boolean;
+ public reactions: ReactionManager;
+ public system: boolean;
+ public tts: boolean;
+ public type: MessageType;
+ public readonly url: string;
+ public webhookID: Snowflake | null;
+ public flags: Readonly<MessageFlags>;
+ public reference: MessageReference | null;
+ public awaitReactions(
+ filter: CollectorFilter,
+ options?: AwaitReactionsOptions,
+ ): Promise<Collection<Snowflake, MessageReaction>>;
+ public createReactionCollector(filter: CollectorFilter, options?: ReactionCollectorOptions): ReactionCollector;
+ public delete(options?: { timeout?: number; reason?: string }): Promise<Message>;
+ public edit(content: StringResolvable, options?: MessageEditOptions | MessageEmbed): Promise<Message>;
+ public edit(options: MessageEditOptions | MessageEmbed | APIMessage): Promise<Message>;
+ public equals(message: Message, rawData: object): boolean;
+ public fetchWebhook(): Promise<Webhook>;
+ public fetch(): Promise<Message>;
+ public pin(): Promise<Message>;
+ public react(emoji: EmojiIdentifierResolvable): Promise<MessageReaction>;
+ public reply(
+ content?: StringResolvable,
+ options?: MessageOptions | MessageAdditions | (MessageOptions & { split?: false }) | MessageAdditions,
+ ): Promise<Message>;
+ public reply(
+ content?: StringResolvable,
+ options?: (MessageOptions & { split: true | SplitOptions }) | MessageAdditions,
+ ): Promise<Message[]>;
+ public reply(
+ options?:
+ | MessageOptions
+ | MessageAdditions
+ | APIMessage
+ | (MessageOptions & { split?: false })
+ | MessageAdditions
+ | APIMessage,
+ ): Promise<Message>;
+ public reply(
+ options?: (MessageOptions & { split: true | SplitOptions }) | MessageAdditions | APIMessage,
+ ): Promise<Message[]>;
+ public suppressEmbeds(suppress?: boolean): Promise<Message>;
+ public toJSON(): object;
+ public toString(): string;
+ public unpin(): Promise<Message>;
+ }
+
+ export class MessageAttachment {
+ constructor(attachment: BufferResolvable | Stream, name?: string, data?: object);
+
+ public attachment: BufferResolvable | Stream;
+ public height: number | null;
+ public id: Snowflake;
+ public name?: string;
+ public proxyURL: string;
+ public size: number;
+ public readonly spoiler: boolean;
+ public url: string;
+ public width: number | null;
+ public setFile(attachment: BufferResolvable | Stream, name?: string): this;
+ public setName(name: string): this;
+ public toJSON(): object;
+ }
+
+ export class MessageCollector extends Collector<Snowflake, Message> {
+ constructor(channel: TextChannel | DMChannel, filter: CollectorFilter, options?: MessageCollectorOptions);
+ private _handleChannelDeletion(channel: GuildChannel): void;
+ private _handleGuildDeletion(guild: Guild): void;
+
+ public channel: Channel;
+ public options: MessageCollectorOptions;
+ public received: number;
+
+ public collect(message: Message): Snowflake;
+ public dispose(message: Message): Snowflake;
+ public endReason(): string;
+ }
+
+ export class MessageEmbed {
+ constructor(data?: MessageEmbed | MessageEmbedOptions);
+ public author: MessageEmbedAuthor | null;
+ public color?: number;
+ public readonly createdAt: Date | null;
+ public description?: string;
+ public fields: EmbedField[];
+ public files: (MessageAttachment | string | FileOptions)[];
+ public footer: MessageEmbedFooter | null;
+ public readonly hexColor: string | null;
+ public image: MessageEmbedImage | null;
+ public readonly length: number;
+ public provider: MessageEmbedProvider | null;
+ public thumbnail: MessageEmbedThumbnail | null;
+ public timestamp: number | null;
+ public title?: string;
+ public type: string;
+ public url?: string;
+ public readonly video: MessageEmbedVideo | null;
+ public addField(name: StringResolvable, value: StringResolvable, inline?: boolean): this;
+ public addFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): this;
+ public attachFiles(file: (MessageAttachment | FileOptions | string)[]): this;
+ public setAuthor(name: StringResolvable, iconURL?: string, url?: string): this;
+ public setColor(color: ColorResolvable): this;
+ public setDescription(description: StringResolvable): this;
+ public setFooter(text: StringResolvable, iconURL?: string): this;
+ public setImage(url: string): this;
+ public setThumbnail(url: string): this;
+ public setTimestamp(timestamp?: Date | number): this;
+ public setTitle(title: StringResolvable): this;
+ public setURL(url: string): this;
+ public spliceFields(index: number, deleteCount: number, ...fields: EmbedFieldData[] | EmbedFieldData[][]): this;
+ public toJSON(): object;
+
+ public static normalizeField(
+ name: StringResolvable,
+ value: StringResolvable,
+ inline?: boolean,
+ ): Required<EmbedFieldData>;
+ public static normalizeFields(...fields: EmbedFieldData[] | EmbedFieldData[][]): Required<EmbedFieldData>[];
+ }
+
+ export class MessageFlags extends BitField<MessageFlagsString> {
+ public static FLAGS: Record<MessageFlagsString, number>;
+ public static resolve(bit?: BitFieldResolvable<MessageFlagsString>): number;
+ }
+
+ export class MessageMentions {
+ constructor(
+ message: Message,
+ users: object[] | Collection<Snowflake, User>,
+ roles: Snowflake[] | Collection<Snowflake, Role>,
+ everyone: boolean,
+ );
+ private _channels: Collection<Snowflake, GuildChannel> | null;
+ private readonly _content: Message;
+ private _members: Collection<Snowflake, GuildMember> | null;
+
+ public readonly channels: Collection<Snowflake, TextChannel>;
+ public readonly client: Client;
+ public everyone: boolean;
+ public readonly guild: Guild;
+ public has(
+ data: User | GuildMember | Role | GuildChannel,
+ options?: {
+ ignoreDirect?: boolean;
+ ignoreRoles?: boolean;
+ ignoreEveryone?: boolean;
+ },
+ ): boolean;
+ public readonly members: Collection<Snowflake, GuildMember> | null;
+ public roles: Collection<Snowflake, Role>;
+ public users: Collection<Snowflake, User>;
+ public crosspostedChannels: Collection<Snowflake, CrosspostedChannel>;
+ public toJSON(): object;
+
+ public static CHANNELS_PATTERN: RegExp;
+ public static EVERYONE_PATTERN: RegExp;
+ public static ROLES_PATTERN: RegExp;
+ public static USERS_PATTERN: RegExp;
+ }
+
+ export class MessageReaction {
+ constructor(client: Client, data: object, message: Message);
+ private _emoji: GuildEmoji | ReactionEmoji;
+
+ public count: number | null;
+ public readonly emoji: GuildEmoji | ReactionEmoji;
+ public me: boolean;
+ public message: Message;
+ public readonly partial: boolean;
+ public users: ReactionUserManager;
+ public remove(): Promise<MessageReaction>;
+ public fetch(): Promise<MessageReaction>;
+ public toJSON(): object;
+ }
+
+ export class NewsChannel extends TextBasedChannel(GuildChannel) {
+ constructor(guild: Guild, data?: object);
+ public messages: MessageManager;
+ public nsfw: boolean;
+ public topic: string | null;
+ public type: 'news';
+ public createWebhook(
+ name: string,
+ options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string },
+ ): Promise<Webhook>;
+ public setNSFW(nsfw: boolean, reason?: string): Promise<NewsChannel>;
+ public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
+ }
+
+ export class PartialGroupDMChannel extends Channel {
+ constructor(client: Client, data: object);
+ public name: string;
+ public icon: string | null;
+ public iconURL(options?: ImageURLOptions): string | null;
+ }
+
+ export class PermissionOverwrites {
+ constructor(guildChannel: GuildChannel, data?: object);
+ public allow: Readonly<Permissions>;
+ public readonly channel: GuildChannel;
+ public deny: Readonly<Permissions>;
+ public id: Snowflake;
+ public type: OverwriteType;
+ public update(options: PermissionOverwriteOption, reason?: string): Promise<PermissionOverwrites>;
+ public delete(reason?: string): Promise<PermissionOverwrites>;
+ public toJSON(): object;
+ public static resolveOverwriteOptions(
+ options: ResolvedOverwriteOptions,
+ initialPermissions: { allow?: PermissionResolvable; deny?: PermissionResolvable },
+ ): ResolvedOverwriteOptions;
+ public static resolve(overwrite: OverwriteResolvable, guild: Guild): RawOverwriteData;
+ }
+
+ export class Permissions extends BitField<PermissionString> {
+ public any(permission: PermissionResolvable, checkAdmin?: boolean): boolean;
+ public has(permission: PermissionResolvable, checkAdmin?: boolean): boolean;
+ public missing(bits: BitFieldResolvable<PermissionString>, checkAdmin?: boolean): PermissionString[];
+ public serialize(checkAdmin?: boolean): Record<PermissionString, boolean>;
+ public toArray(checkAdmin?: boolean): PermissionString[];
+
+ public static ALL: number;
+ public static DEFAULT: number;
+ public static FLAGS: PermissionFlags;
+ public static resolve(permission?: PermissionResolvable): number;
+ }
+
+ export class Presence {
+ constructor(client: Client, data?: object);
+ public activities: Activity[];
+ public clientStatus: ClientPresenceStatusData | null;
+ public flags: Readonly<ActivityFlags>;
+ public guild: Guild | null;
+ public readonly member: GuildMember | null;
+ public status: PresenceStatus;
+ public readonly user: User | null;
+ public userID: Snowflake;
+ public equals(presence: Presence): boolean;
+ }
+
+ export class ReactionCollector extends Collector<Snowflake, MessageReaction> {
+ constructor(message: Message, filter: CollectorFilter, options?: ReactionCollectorOptions);
+ private _handleChannelDeletion(channel: GuildChannel): void;
+ private _handleGuildDeletion(guild: Guild): void;
+ private _handleMessageDeletion(message: Message): void;
+
+ public message: Message;
+ public options: ReactionCollectorOptions;
+ public total: number;
+ public users: Collection<Snowflake, User>;
+
+ public static key(reaction: MessageReaction): Snowflake | string;
+
+ public collect(reaction: MessageReaction): Snowflake | string;
+ public dispose(reaction: MessageReaction, user: User): Snowflake | string;
+ public empty(): void;
+ public endReason(): string | null;
+
+ public on(event: 'collect' | 'dispose' | 'remove', listener: (reaction: MessageReaction, user: User) => void): this;
+ public on(
+ event: 'end',
+ listener: (collected: Collection<Snowflake, MessageReaction>, reason: string) => void,
+ ): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(
+ event: 'collect' | 'dispose' | 'remove',
+ listener: (reaction: MessageReaction, user: User) => void,
+ ): this;
+ public once(
+ event: 'end',
+ listener: (collected: Collection<Snowflake, MessageReaction>, reason: string) => void,
+ ): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ export class ReactionEmoji extends Emoji {
+ constructor(reaction: MessageReaction, emoji: object);
+ public reaction: MessageReaction;
+ public toJSON(): object;
+ }
+
+ export class RichPresenceAssets {
+ constructor(activity: Activity, assets: object);
+ public largeImage: Snowflake | null;
+ public largeText: string | null;
+ public smallImage: Snowflake | null;
+ public smallText: string | null;
+ public largeImageURL(options?: ImageURLOptions): string | null;
+ public smallImageURL(options?: ImageURLOptions): string | null;
+ }
+
+ export class Role extends Base {
+ constructor(client: Client, data: object, guild: Guild);
+ public color: number;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public deleted: boolean;
+ public readonly editable: boolean;
+ public guild: Guild;
+ public readonly hexColor: string;
+ public hoist: boolean;
+ public id: Snowflake;
+ public managed: boolean;
+ public readonly members: Collection<Snowflake, GuildMember>;
+ public mentionable: boolean;
+ public name: string;
+ public permissions: Readonly<Permissions>;
+ public readonly position: number;
+ public rawPosition: number;
+ public comparePositionTo(role: Role): number;
+ public delete(reason?: string): Promise<Role>;
+ public edit(data: RoleData, reason?: string): Promise<Role>;
+ public equals(role: Role): boolean;
+ public permissionsIn(channel: ChannelResolvable): Readonly<Permissions>;
+ public setColor(color: ColorResolvable, reason?: string): Promise<Role>;
+ public setHoist(hoist: boolean, reason?: string): Promise<Role>;
+ public setMentionable(mentionable: boolean, reason?: string): Promise<Role>;
+ public setName(name: string, reason?: string): Promise<Role>;
+ public setPermissions(permissions: PermissionResolvable, reason?: string): Promise<Role>;
+ public setPosition(position: number, options?: { relative?: boolean; reason?: string }): Promise<Role>;
+ public toJSON(): object;
+ public toString(): string;
+
+ public static comparePositions(role1: Role, role2: Role): number;
+ }
+
+ export class Shard extends EventEmitter {
+ constructor(manager: ShardingManager, id: number);
+ private _evals: Map<string, Promise<any>>;
+ private _exitListener: (...args: any[]) => void;
+ private _fetches: Map<string, Promise<any>>;
+ private _handleExit(respawn?: boolean): void;
+ private _handleMessage(message: any): void;
+
+ public args: string[];
+ public execArgv: string[];
+ public env: object;
+ public id: number;
+ public manager: ShardingManager;
+ public process: ChildProcess | null;
+ public ready: boolean;
+ public worker: any | null;
+ public eval(script: string): Promise<any>;
+ public eval<T>(fn: (client: Client) => T): Promise<T[]>;
+ public fetchClientValue(prop: string): Promise<any>;
+ public kill(): void;
+ public respawn(delay?: number, spawnTimeout?: number): Promise<ChildProcess>;
+ public send(message: any): Promise<Shard>;
+ public spawn(spawnTimeout?: number): Promise<ChildProcess>;
+
+ public on(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this;
+ public on(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this;
+ public on(event: 'error', listener: (error: Error) => void): this;
+ public on(event: 'message', listener: (message: any) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(event: 'spawn' | 'death', listener: (child: ChildProcess) => void): this;
+ public once(event: 'disconnect' | 'ready' | 'reconnecting', listener: () => void): this;
+ public once(event: 'error', listener: (error: Error) => void): this;
+ public once(event: 'message', listener: (message: any) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ export class ShardClientUtil {
+ constructor(client: Client, mode: ShardingManagerMode);
+ private _handleMessage(message: any): void;
+ private _respond(type: string, message: any): void;
+
+ public client: Client;
+ public readonly count: number;
+ public readonly ids: number[];
+ public mode: ShardingManagerMode;
+ public parentPort: any | null;
+ public broadcastEval(script: string): Promise<any[]>;
+ public broadcastEval<T>(fn: (client: Client) => T): Promise<T[]>;
+ public fetchClientValues(prop: string): Promise<any[]>;
+ public respawnAll(shardDelay?: number, respawnDelay?: number, spawnTimeout?: number): Promise<void>;
+ public send(message: any): Promise<void>;
+
+ public static singleton(client: Client, mode: ShardingManagerMode): ShardClientUtil;
+ }
+
+ export class ShardingManager extends EventEmitter {
+ constructor(
+ file: string,
+ options?: {
+ totalShards?: number | 'auto';
+ shardList?: number[] | 'auto';
+ mode?: ShardingManagerMode;
+ respawn?: boolean;
+ shardArgs?: string[];
+ token?: string;
+ execArgv?: string[];
+ },
+ );
+
+ public file: string;
+ public respawn: boolean;
+ public shardArgs: string[];
+ public shards: Collection<number, Shard>;
+ public token: string | null;
+ public totalShards: number | 'auto';
+ public broadcast(message: any): Promise<Shard[]>;
+ public broadcastEval(script: string): Promise<any[]>;
+ public createShard(id: number): Shard;
+ public fetchClientValues(prop: string): Promise<any[]>;
+ public respawnAll(
+ shardDelay?: number,
+ respawnDelay?: number,
+ spawnTimeout?: number,
+ ): Promise<Collection<number, Shard>>;
+ public spawn(amount?: number | 'auto', delay?: number, spawnTimeout?: number): Promise<Collection<number, Shard>>;
+
+ public on(event: 'shardCreate', listener: (shard: Shard) => void): this;
+
+ public once(event: 'shardCreate', listener: (shard: Shard) => void): this;
+ }
+
+ export class SnowflakeUtil {
+ public static deconstruct(snowflake: Snowflake): DeconstructedSnowflake;
+ public static generate(timestamp?: number | Date): Snowflake;
+ }
+
+ export class Speaking extends BitField<SpeakingString> {
+ public static FLAGS: Record<SpeakingString, number>;
+ public static resolve(bit?: BitFieldResolvable<SpeakingString>): number;
+ }
+
+ export class StoreChannel extends GuildChannel {
+ constructor(guild: Guild, data?: object);
+ public nsfw: boolean;
+ public type: 'store';
+ }
+
+ class StreamDispatcher extends VolumeMixin(Writable) {
+ constructor(player: object, options?: StreamOptions, streams?: object);
+ public readonly bitrateEditable: boolean;
+ public broadcast: VoiceBroadcast | null;
+ public readonly paused: boolean;
+ public pausedSince: number | null;
+ public readonly pausedTime: number;
+ public player: object;
+ public readonly streamTime: number;
+ public readonly totalStreamTime: number;
+
+ public pause(silence?: boolean): void;
+ public resume(): void;
+ public setBitrate(value: number | 'auto'): boolean;
+ public setFEC(enabled: boolean): boolean;
+ public setPLP(value: number): boolean;
+
+ public on(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this;
+ public on(event: 'debug', listener: (info: string) => void): this;
+ public on(event: 'error', listener: (err: Error) => void): this;
+ public on(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this;
+ public on(event: 'speaking', listener: (speaking: boolean) => void): this;
+ public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(event: 'close' | 'drain' | 'finish' | 'start', listener: () => void): this;
+ public once(event: 'debug', listener: (info: string) => void): this;
+ public once(event: 'error', listener: (err: Error) => void): this;
+ public once(event: 'pipe' | 'unpipe', listener: (src: Readable) => void): this;
+ public once(event: 'speaking', listener: (speaking: boolean) => void): this;
+ public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ export class Structures {
+ public static get<K extends keyof Extendable>(structure: K): Extendable[K];
+ public static get(structure: string): (...args: any[]) => void;
+ public static extend<K extends keyof Extendable, T extends Extendable[K]>(
+ structure: K,
+ extender: (baseClass: Extendable[K]) => T,
+ ): T;
+ public static extend<T extends (...args: any[]) => void>(
+ structure: string,
+ extender: (baseClass: typeof Function) => T,
+ ): T;
+ }
+
+ export class SystemChannelFlags extends BitField<SystemChannelFlagsString> {
+ public static FLAGS: Record<SystemChannelFlagsString, number>;
+ public static resolve(bit?: BitFieldResolvable<SystemChannelFlagsString>): number;
+ }
+
+ export class Team extends Base {
+ constructor(client: Client, data: object);
+ public id: Snowflake;
+ public name: string;
+ public icon: string | null;
+ public ownerID: Snowflake | null;
+ public members: Collection<Snowflake, TeamMember>;
+
+ public readonly owner: TeamMember;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+
+ public iconURL(options?: ImageURLOptions): string;
+ public toJSON(): object;
+ public toString(): string;
+ }
+
+ export class TeamMember extends Base {
+ constructor(team: Team, data: object);
+ public team: Team;
+ public readonly id: Snowflake;
+ public permissions: string[];
+ public membershipState: MembershipStates;
+ public user: User;
+
+ public toString(): string;
+ }
+
+ export class TextChannel extends TextBasedChannel(GuildChannel) {
+ constructor(guild: Guild, data?: object);
+ public messages: MessageManager;
+ public nsfw: boolean;
+ public type: 'text';
+ public rateLimitPerUser: number;
+ public topic: string | null;
+ public createWebhook(
+ name: string,
+ options?: { avatar?: BufferResolvable | Base64Resolvable; reason?: string },
+ ): Promise<Webhook>;
+ public setNSFW(nsfw: boolean, reason?: string): Promise<TextChannel>;
+ public setRateLimitPerUser(rateLimitPerUser: number, reason?: string): Promise<TextChannel>;
+ public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
+ }
+
+ export class User extends PartialTextBasedChannel(Base) {
+ constructor(client: Client, data: object);
+ public avatar: string | null;
+ public bot: boolean;
+ public readonly createdAt: Date;
+ public readonly createdTimestamp: number;
+ public discriminator: string;
+ public readonly defaultAvatarURL: string;
+ public readonly dmChannel: DMChannel;
+ public flags: Readonly<UserFlags>;
+ public id: Snowflake;
+ public lastMessageID: Snowflake | null;
+ public locale: string;
+ public readonly partial: false;
+ public readonly presence: Presence;
+ public system?: boolean;
+ public readonly tag: string;
+ public username: string;
+ public avatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string | null;
+ public createDM(): Promise<DMChannel>;
+ public deleteDM(): Promise<DMChannel>;
+ public displayAvatarURL(options?: ImageURLOptions & { dynamic?: boolean }): string;
+ public equals(user: User): boolean;
+ public fetch(): Promise<User>;
+ public toString(): string;
+ public typingDurationIn(channel: ChannelResolvable): number;
+ public typingIn(channel: ChannelResolvable): boolean;
+ public typingSinceIn(channel: ChannelResolvable): Date;
+ }
+
+ export class UserFlags extends BitField<UserFlagsString> {
+ public static FLAGS: Record<UserFlagsString, number>;
+ public static resolve(bit?: BitFieldResolvable<UserFlagsString>): number;
+ }
+
+ export class Util {
+ public static basename(path: string, ext?: string): string;
+ public static binaryToID(num: string): Snowflake;
+ public static cleanContent(str: string, message: Message): string;
+ public static removeMentions(str: string): string;
+ public static cloneObject(obj: object): object;
+ public static convertToBuffer(ab: ArrayBuffer | string): Buffer;
+ public static delayFor(ms: number): Promise<void>;
+ public static discordSort<K, V extends { rawPosition: number; id: string }>(
+ collection: Collection<K, V>,
+ ): Collection<K, V>;
+ public static escapeMarkdown(text: string, options?: EscapeMarkdownOptions): string;
+ public static escapeCodeBlock(text: string): string;
+ public static escapeInlineCode(text: string): string;
+ public static escapeBold(text: string): string;
+ public static escapeItalic(text: string): string;
+ public static escapeUnderline(text: string): string;
+ public static escapeStrikethrough(text: string): string;
+ public static escapeSpoiler(text: string): string;
+ public static cleanCodeBlockContent(text: string): string;
+ public static fetchRecommendedShards(token: string, guildsPerShard?: number): Promise<number>;
+ public static flatten(obj: object, ...props: { [key: string]: boolean | string }[]): object;
+ public static idToBinary(num: Snowflake): string;
+ public static makeError(obj: { name: string; message: string; stack: string }): Error;
+ public static makePlainError(err: Error): { name: string; message: string; stack: string };
+ public static mergeDefault(def: object, given: object): object;
+ public static moveElementInArray(array: any[], element: any, newIndex: number, offset?: boolean): number;
+ public static parseEmoji(text: string): { animated: boolean; name: string; id: string | null } | null;
+ public static resolveColor(color: ColorResolvable): number;
+ public static resolveString(data: StringResolvable): string;
+ public static setPosition<T extends Channel | Role>(
+ item: T,
+ position: number,
+ relative: boolean,
+ sorted: Collection<Snowflake, T>,
+ route: object,
+ reason?: string,
+ ): Promise<{ id: Snowflake; position: number }[]>;
+ public static splitMessage(text: StringResolvable, options?: SplitOptions): string[];
+ public static str2ab(str: string): ArrayBuffer;
+ }
+
+ class VoiceBroadcast extends EventEmitter {
+ constructor(client: Client);
+ public client: Client;
+ public subscribers: StreamDispatcher[];
+ public readonly dispatcher?: BroadcastDispatcher;
+ public play(input: string | Readable, options?: StreamOptions): BroadcastDispatcher;
+ public end(): void;
+
+ public on(event: 'end', listener: () => void): this;
+ public on(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(event: 'end', listener: () => void): this;
+ public once(event: 'subscribe' | 'unsubscribe', listener: (dispatcher: StreamDispatcher) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ export class VoiceChannel extends GuildChannel {
+ constructor(guild: Guild, data?: object);
+ public bitrate: number;
+ public readonly editable: boolean;
+ public readonly full: boolean;
+ public readonly joinable: boolean;
+ public readonly speakable: boolean;
+ public type: 'voice';
+ public userLimit: number;
+ public join(): Promise<VoiceConnection>;
+ public leave(): void;
+ public setBitrate(bitrate: number, reason?: string): Promise<VoiceChannel>;
+ public setUserLimit(userLimit: number, reason?: string): Promise<VoiceChannel>;
+ }
+
+ class VoiceConnection extends EventEmitter {
+ constructor(voiceManager: ClientVoiceManager, channel: VoiceChannel);
+ private authentication: object;
+ private sockets: object;
+ private ssrcMap: Map<number, boolean>;
+ private _speaking: Map<Snowflake, Readonly<Speaking>>;
+ private _disconnect(): void;
+ private authenticate(): void;
+ private authenticateFailed(reason: string): void;
+ private checkAuthenticated(): void;
+ private cleanup(): void;
+ private connect(): void;
+ private onReady(data: object): void;
+ private onSessionDescription(mode: string, secret: string): void;
+ private onSpeaking(data: object): void;
+ private reconnect(token: string, endpoint: string): void;
+ private sendVoiceStateUpdate(options: object): Promise<Shard>;
+ private setSessionID(sessionID: string): void;
+ private setSpeaking(value: BitFieldResolvable<SpeakingString>): void;
+ private setTokenAndEndpoint(token: string, endpoint: string): void;
+ private updateChannel(channel: VoiceChannel): void;
+
+ public channel: VoiceChannel;
+ public readonly client: Client;
+ public readonly dispatcher: StreamDispatcher;
+ public player: object;
+ public receiver: VoiceReceiver;
+ public speaking: Readonly<Speaking>;
+ public status: VoiceStatus;
+ public readonly voice: VoiceState;
+ public voiceManager: ClientVoiceManager;
+ public disconnect(): void;
+ public play(input: VoiceBroadcast | Readable | string, options?: StreamOptions): StreamDispatcher;
+
+ public on(event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', listener: () => void): this;
+ public on(event: 'debug', listener: (message: string) => void): this;
+ public on(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this;
+ public on(event: 'speaking', listener: (user: User, speaking: Readonly<Speaking>) => void): this;
+ public on(event: 'warn', listener: (warning: string | Error) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(
+ event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting',
+ listener: () => void,
+ ): this;
+ public once(event: 'debug', listener: (message: string) => void): this;
+ public once(event: 'error' | 'failed' | 'disconnect', listener: (error: Error) => void): this;
+ public once(event: 'speaking', listener: (user: User, speaking: Readonly<Speaking>) => void): this;
+ public once(event: 'warn', listener: (warning: string | Error) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ class VoiceReceiver extends EventEmitter {
+ constructor(connection: VoiceConnection);
+ public createStream(
+ user: UserResolvable,
+ options?: { mode?: 'opus' | 'pcm'; end?: 'silence' | 'manual' },
+ ): Readable;
+
+ public on(event: 'debug', listener: (error: Error | string) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(event: 'debug', listener: (error: Error | string) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ export class VoiceRegion {
+ constructor(data: object);
+ public custom: boolean;
+ public deprecated: boolean;
+ public id: string;
+ public name: string;
+ public optimal: boolean;
+ public vip: boolean;
+ public toJSON(): object;
+ }
+
+ export class VoiceState extends Base {
+ constructor(guild: Guild, data: object);
+ public readonly channel: VoiceChannel | null;
+ public channelID?: Snowflake;
+ public readonly connection: VoiceConnection | null;
+ public readonly deaf?: boolean;
+ public guild: Guild;
+ public id: Snowflake;
+ public readonly member: GuildMember | null;
+ public readonly mute?: boolean;
+ public selfDeaf?: boolean;
+ public selfMute?: boolean;
+ public serverDeaf?: boolean;
+ public serverMute?: boolean;
+ public sessionID?: string;
+ public streaming: boolean;
+ public readonly speaking: boolean | null;
+
+ public setDeaf(deaf: boolean, reason?: string): Promise<GuildMember>;
+ public setMute(mute: boolean, reason?: string): Promise<GuildMember>;
+ public kick(reason?: string): Promise<GuildMember>;
+ public setChannel(channel: ChannelResolvable | null, reason?: string): Promise<GuildMember>;
+ public setSelfDeaf(deaf: boolean): Promise<boolean>;
+ public setSelfMute(mute: boolean): Promise<boolean>;
+ }
+
+ class VolumeInterface extends EventEmitter {
+ constructor(options?: { volume?: number });
+ public readonly volume: number;
+ public readonly volumeDecibels: number;
+ public readonly volumeEditable: boolean;
+ public readonly volumeLogarithmic: number;
+ public setVolume(volume: number): void;
+ public setVolumeDecibels(db: number): void;
+ public setVolumeLogarithmic(value: number): void;
+
+ public on(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this;
+
+ public once(event: 'volumeChange', listener: (oldVolume: number, newVolume: number) => void): this;
+ }
+
+ export class Webhook extends WebhookMixin() {
+ constructor(client: Client, data?: object);
+ public avatar: string;
+ public avatarURL(options?: ImageURLOptions): string | null;
+ public channelID: Snowflake;
+ public client: Client;
+ public guildID: Snowflake;
+ public name: string;
+ public owner: User | object | null;
+ public token: string | null;
+ public type: WebhookTypes;
+ }
+
+ export class WebhookClient extends WebhookMixin(BaseClient) {
+ constructor(id: string, token: string, options?: ClientOptions);
+ public client: this;
+ public token: string;
+ }
+
+ export class WebSocketManager extends EventEmitter {
+ constructor(client: Client);
+ private totalShards: number | string;
+ private shardQueue: Set<WebSocketShard>;
+ private packetQueue: object[];
+ private destroyed: boolean;
+ private reconnecting: boolean;
+ private sessionStartLimit?: { total: number; remaining: number; reset_after: number };
+
+ public readonly client: Client;
+ public gateway?: string;
+ public shards: Collection<number, WebSocketShard>;
+ public status: Status;
+ public readonly ping: number;
+
+ public on(event: WSEventType, listener: (data: any, shardID: number) => void): this;
+ public once(event: WSEventType, listener: (data: any, shardID: number) => void): this;
+
+ private debug(message: string, shard?: WebSocketShard): void;
+ private connect(): Promise<void>;
+ private createShards(): Promise<void>;
+ private reconnect(): Promise<void>;
+ private broadcast(packet: object): void;
+ private destroy(): void;
+ private _handleSessionLimit(remaining?: number, resetAfter?: number): Promise<void>;
+ private handlePacket(packet?: object, shard?: WebSocketShard): boolean;
+ private checkShardsReady(): Promise<void>;
+ private triggerClientReady(): void;
+ }
+
+ export class WebSocketShard extends EventEmitter {
+ constructor(manager: WebSocketManager, id: number);
+ private sequence: number;
+ private closeSequence: number;
+ private sessionID?: string;
+ private lastPingTimestamp: number;
+ private lastHeartbeatAcked: boolean;
+ private ratelimit: { queue: object[]; total: number; remaining: number; time: 60e3; timer: NodeJS.Timeout | null };
+ private connection: WebSocket | null;
+ private helloTimeout: NodeJS.Timeout | undefined;
+ private eventsAttached: boolean;
+ private expectedGuilds: Set<Snowflake> | undefined;
+ private readyTimeout: NodeJS.Timeout | undefined;
+
+ public manager: WebSocketManager;
+ public id: number;
+ public status: Status;
+ public ping: number;
+
+ private debug(message: string): void;
+ private connect(): Promise<void>;
+ private onOpen(): void;
+ private onMessage(event: MessageEvent): void;
+ private onError(error: ErrorEvent | object): void;
+ private onClose(event: CloseEvent): void;
+ private onPacket(packet: object): void;
+ private checkReady(): void;
+ private setHelloTimeout(time?: number): void;
+ private setHeartbeatTimer(time: number): void;
+ private sendHeartbeat(): void;
+ private ackHeartbeat(): void;
+ private identify(): void;
+ private identifyNew(): void;
+ private identifyResume(): void;
+ private _send(data: object): void;
+ private processQueue(): void;
+ private destroy(destroyOptions?: { closeCode?: number; reset?: boolean; emit?: boolean; log?: boolean }): void;
+ private _cleanupConnection(): void;
+ private _emitDestroyed(): void;
+
+ public send(data: object): void;
+ public on(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this;
+ public on(event: 'close', listener: (event: CloseEvent) => void): this;
+ public on(event: 'allReady', listener: (unavailableGuilds?: Set<Snowflake>) => void): this;
+ public on(event: string, listener: (...args: any[]) => void): this;
+
+ public once(event: 'ready' | 'resumed' | 'invalidSession', listener: () => void): this;
+ public once(event: 'close', listener: (event: CloseEvent) => void): this;
+ public once(event: 'allReady', listener: (unavailableGuilds?: Set<Snowflake>) => void): this;
+ public once(event: string, listener: (...args: any[]) => void): this;
+ }
+
+ //#endregion
+
+ //#region Collections
+
+ export class Collection<K, V> extends BaseCollection<K, V> {
+ public flatMap<T>(
+ fn: (value: V, key: K, collection: this) => Collection<K, T>,
+ thisArg?: unknown,
+ ): Collection<K, T>;
+ public flatMap<T, This>(
+ fn: (this: This, value: V, key: K, collection: this) => Collection<K, T>,
+ thisArg: This,
+ ): Collection<K, T>;
+ public mapValues<T>(fn: (value: V, key: K, collection: this) => T, thisArg?: unknown): Collection<K, T>;
+ public mapValues<This, T>(
+ fn: (this: This, value: V, key: K, collection: this) => T,
+ thisArg: This,
+ ): Collection<K, T>;
+ public toJSON(): object;
+ }
+
+ //#endregion
+
+ //#region Managers
+
+ export class ChannelManager extends BaseManager<Snowflake, Channel, ChannelResolvable> {
+ constructor(client: Client, iterable: Iterable<any>);
+ public fetch(id: Snowflake, cache?: boolean): Promise<Channel>;
+ }
+
+ export abstract class BaseManager<K, Holds, R> {
+ constructor(client: Client, iterable: Iterable<any>, holds: Constructable<Holds>, cacheType: Collection<K, Holds>);
+ public holds: Constructable<Holds>;
+ public cache: Collection<K, Holds>;
+ public cacheType: Collection<K, Holds>;
+ public readonly client: Client;
+ public add(data: any, cache?: boolean, { id, extras }?: { id: K; extras: any[] }): Holds;
+ public resolve(resolvable: R): Holds | null;
+ public resolveID(resolvable: R): K | null;
+ }
+
+ export class GuildChannelManager extends BaseManager<Snowflake, GuildChannel, GuildChannelResolvable> {
+ constructor(guild: Guild, iterable?: Iterable<any>);
+ public guild: Guild;
+ public create(name: string, options: GuildCreateChannelOptions & { type: 'voice' }): Promise<VoiceChannel>;
+ public create(name: string, options: GuildCreateChannelOptions & { type: 'category' }): Promise<CategoryChannel>;
+ public create(name: string, options?: GuildCreateChannelOptions & { type?: 'text' }): Promise<TextChannel>;
+ public create(
+ name: string,
+ options: GuildCreateChannelOptions,
+ ): Promise<TextChannel | VoiceChannel | CategoryChannel>;
+ }
+
+ export class GuildEmojiManager extends BaseManager<Snowflake, GuildEmoji, EmojiResolvable> {
+ constructor(guild: Guild, iterable?: Iterable<any>);
+ public guild: Guild;
+ public create(
+ attachment: BufferResolvable | Base64Resolvable,
+ name: string,
+ options?: GuildEmojiCreateOptions,
+ ): Promise<GuildEmoji>;
+ public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null;
+ }
+
+ export class GuildEmojiRoleManager {
+ constructor(emoji: GuildEmoji);
+ public emoji: GuildEmoji;
+ public guild: Guild;
+ public cache: Collection<Snowflake, Role>;
+ public add(roleOrRoles: RoleResolvable | RoleResolvable[] | Collection<Snowflake, Role>): Promise<GuildEmoji>;
+ public set(roles: RoleResolvable[] | Collection<Snowflake, Role>): Promise<GuildEmoji>;
+ public remove(roleOrRoles: RoleResolvable | RoleResolvable[] | Collection<Snowflake, Role>): Promise<GuildEmoji>;
+ }
+
+ export class GuildManager extends BaseManager<Snowflake, Guild, GuildResolvable> {
+ constructor(client: Client, iterable?: Iterable<any>);
+ public create(
+ name: string,
+ options?: { region?: string; icon: BufferResolvable | Base64Resolvable | null },
+ ): Promise<Guild>;
+ }
+
+ export class GuildMemberManager extends BaseManager<Snowflake, GuildMember, GuildMemberResolvable> {
+ constructor(guild: Guild, iterable?: Iterable<any>);
+ public guild: Guild;
+ public ban(user: UserResolvable, options?: BanOptions): Promise<GuildMember | User | Snowflake>;
+ public fetch(
+ options: UserResolvable | FetchMemberOptions | (FetchMembersOptions & { user: UserResolvable }),
+ ): Promise<GuildMember>;
+ public fetch(options?: FetchMembersOptions): Promise<Collection<Snowflake, GuildMember>>;
+ public prune(options: GuildPruneMembersOptions & { dry?: false; count: false }): Promise<null>;
+ public prune(options?: GuildPruneMembersOptions): Promise<number>;
+ public unban(user: UserResolvable, reason?: string): Promise<User>;
+ }
+
+ export class GuildMemberRoleManager extends OverridableManager<Snowflake, Role, RoleResolvable> {
+ constructor(member: GuildMember);
+ public readonly hoist: Role | null;
+ public readonly color: Role | null;
+ public readonly highest: Role;
+ public member: GuildMember;
+ public guild: Guild;
+
+ public add(
+ roleOrRoles: RoleResolvable | RoleResolvable[] | Collection<Snowflake, Role>,
+ reason?: string,
+ ): Promise<GuildMember>;
+ public set(roles: RoleResolvable[] | Collection<Snowflake, Role>, reason?: string): Promise<GuildMember>;
+ public remove(
+ roleOrRoles: RoleResolvable | RoleResolvable[] | Collection<Snowflake, Role>,
+ reason?: string,
+ ): Promise<GuildMember>;
+ }
+
+ export class MessageManager extends BaseManager<Snowflake, Message, MessageResolvable> {
+ constructor(channel: TextChannel | DMChannel, iterable?: Iterable<any>);
+ public channel: TextBasedChannelFields;
+ public cache: Collection<Snowflake, Message>;
+ public fetch(message: Snowflake, cache?: boolean): Promise<Message>;
+ public fetch(options?: ChannelLogsQueryOptions, cache?: boolean): Promise<Collection<Snowflake, Message>>;
+ public fetchPinned(cache?: boolean): Promise<Collection<Snowflake, Message>>;
+ public delete(message: MessageResolvable, reason?: string): Promise<void>;
+ }
+
+ // Hacky workaround because changing the signature of an overridden method errors
+ class OverridableManager<V, K, R = any> extends BaseManager<V, K, R> {
+ public add(data: any, cache: any): any;
+ public set(key: any): any;
+ }
+
+ export class PresenceManager extends BaseManager<Snowflake, Presence, PresenceResolvable> {
+ constructor(client: Client, iterable?: Iterable<any>);
+ }
+
+ export class ReactionManager extends BaseManager<Snowflake, MessageReaction, MessageReactionResolvable> {
+ constructor(message: Message, iterable?: Iterable<any>);
+ public message: Message;
+ public removeAll(): Promise<Message>;
+ }
+
+ export class ReactionUserManager extends BaseManager<Snowflake, User, UserResolvable> {
+ constructor(client: Client, iterable: Iterable<any> | undefined, reaction: MessageReaction);
+ public reaction: MessageReaction;
+ public fetch(options?: {
+ limit?: number;
+ after?: Snowflake;
+ before?: Snowflake;
+ }): Promise<Collection<Snowflake, User>>;
+ public remove(user?: UserResolvable): Promise<MessageReaction>;
+ }
+
+ export class RoleManager extends BaseManager<Snowflake, Role, RoleResolvable> {
+ constructor(guild: Guild, iterable?: Iterable<any>);
+ public readonly everyone: Role;
+ public readonly highest: Role;
+ public guild: Guild;
+
+ public create(options?: { data?: RoleData; reason?: string }): Promise<Role>;
+ public fetch(id: Snowflake, cache?: boolean): Promise<Role | null>;
+ public fetch(id?: Snowflake, cache?: boolean): Promise<this>;
+ }
+
+ export class UserManager extends BaseManager<Snowflake, User, UserResolvable> {
+ constructor(client: Client, iterable?: Iterable<any>);
+ public fetch(id: Snowflake, cache?: boolean): Promise<User>;
+ }
+
+ export class VoiceStateManager extends BaseManager<Snowflake, VoiceState, typeof VoiceState> {
+ constructor(guild: Guild, iterable?: Iterable<any>);
+ public guild: Guild;
+ }
+
+ //#endregion
+
+ //#region Mixins
+
+ // Model the TextBasedChannel mixin system, allowing application of these fields
+ // to the classes that use these methods without having to manually add them
+ // to each of those classes
+
+ type Constructable<T> = new (...args: any[]) => T;
+ function PartialTextBasedChannel<T>(Base?: Constructable<T>): Constructable<T & PartialTextBasedChannelFields>;
+ function TextBasedChannel<T>(Base?: Constructable<T>): Constructable<T & TextBasedChannelFields>;
+
+ interface PartialTextBasedChannelFields {
+ lastMessageID: Snowflake | null;
+ readonly lastMessage: Message | null;
+ send(
+ options: MessageOptions | (MessageOptions & { split?: false }) | MessageAdditions | APIMessage,
+ ): Promise<Message>;
+ send(
+ options: (MessageOptions & { split: true | SplitOptions; content: StringResolvable }) | APIMessage,
+ ): Promise<Message[]>;
+ send(
+ content: StringResolvable,
+ options?: MessageOptions | (MessageOptions & { split?: false }) | MessageAdditions,
+ ): Promise<Message>;
+ send(content: StringResolvable, options?: MessageOptions & { split: true | SplitOptions }): Promise<Message[]>;
+ }
+
+ interface TextBasedChannelFields extends PartialTextBasedChannelFields {
+ _typing: Map<string, TypingData>;
+ lastPinTimestamp: number | null;
+ readonly lastPinAt: Date;
+ typing: boolean;
+ typingCount: number;
+ awaitMessages(filter: CollectorFilter, options?: AwaitMessagesOptions): Promise<Collection<Snowflake, Message>>;
+ bulkDelete(
+ messages: Collection<Snowflake, Message> | Message[] | Snowflake[] | number,
+ filterOld?: boolean,
+ ): Promise<Collection<Snowflake, Message>>;
+ createMessageCollector(filter: CollectorFilter, options?: MessageCollectorOptions): MessageCollector;
+ startTyping(count?: number): Promise<void>;
+ stopTyping(force?: boolean): void;
+ }
+
+ function WebhookMixin<T>(Base?: Constructable<T>): Constructable<T & WebhookFields>;
+
+ function VolumeMixin<T>(base: Constructable<T>): Constructable<T & VolumeInterface>;
+
+ interface WebhookFields {
+ id: Snowflake;
+ readonly createdAt: Date;
+ readonly createdTimestamp: number;
+ readonly url: string;
+ delete(reason?: string): Promise<void>;
+ edit(options: WebhookEditData): Promise<Webhook>;
+ send(
+ content?: StringResolvable,
+ options?: (WebhookMessageOptions & { split?: false }) | MessageAdditions,
+ ): Promise<Message>;
+ send(
+ content?: StringResolvable,
+ options?: (WebhookMessageOptions & { split: true | SplitOptions }) | MessageAdditions,
+ ): Promise<Message[]>;
+ send(options?: (WebhookMessageOptions & { split?: false }) | MessageAdditions | APIMessage): Promise<Message>;
+ send(
+ options?: (WebhookMessageOptions & { split: true | SplitOptions }) | MessageAdditions | APIMessage,
+ ): Promise<Message[]>;
+ sendSlackMessage(body: object): Promise<boolean>;
+ }
+
+ //#endregion
+
+ //#region Typedefs
+
+ type ActivityFlagsString = 'INSTANCE' | 'JOIN' | 'SPECTATE' | 'JOIN_REQUEST' | 'SYNC' | 'PLAY';
+
+ interface ActivityOptions {
+ name?: string;
+ url?: string;
+ type?: ActivityType | number;
+ shardID?: number | number[];
+ }
+
+ type ActivityType = 'PLAYING' | 'STREAMING' | 'LISTENING' | 'WATCHING' | 'CUSTOM_STATUS';
+
+ interface AddGuildMemberOptions {
+ accessToken: string;
+ nick?: string;
+ roles?: Collection<Snowflake, Role> | RoleResolvable[];
+ mute?: boolean;
+ deaf?: boolean;
+ }
+
+ interface APIErrror {
+ UNKNOWN_ACCOUNT: number;
+ UNKNOWN_APPLICATION: number;
+ UNKNOWN_CHANNEL: number;
+ UNKNOWN_GUILD: number;
+ UNKNOWN_INTEGRATION: number;
+ UNKNOWN_INVITE: number;
+ UNKNOWN_MEMBER: number;
+ UNKNOWN_MESSAGE: number;
+ UNKNOWN_OVERWRITE: number;
+ UNKNOWN_PROVIDER: number;
+ UNKNOWN_ROLE: number;
+ UNKNOWN_TOKEN: number;
+ UNKNOWN_USER: number;
+ UNKNOWN_EMOJI: number;
+ UNKNOWN_WEBHOOK: number;
+ BOT_PROHIBITED_ENDPOINT: number;
+ BOT_ONLY_ENDPOINT: number;
+ MAXIMUM_GUILDS: number;
+ MAXIMUM_FRIENDS: number;
+ MAXIMUM_PINS: number;
+ MAXIMUM_ROLES: number;
+ MAXIMUM_REACTIONS: number;
+ UNAUTHORIZED: number;
+ MISSING_ACCESS: number;
+ INVALID_ACCOUNT_TYPE: number;
+ CANNOT_EXECUTE_ON_DM: number;
+ EMBED_DISABLED: number;
+ CANNOT_EDIT_MESSAGE_BY_OTHER: number;
+ CANNOT_SEND_EMPTY_MESSAGE: number;
+ CANNOT_MESSAGE_USER: number;
+ CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: number;
+ CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: number;
+ OAUTH2_APPLICATION_BOT_ABSENT: number;
+ MAXIMUM_OAUTH2_APPLICATIONS: number;
+ INVALID_OAUTH_STATE: number;
+ MISSING_PERMISSIONS: number;
+ INVALID_AUTHENTICATION_TOKEN: number;
+ NOTE_TOO_LONG: number;
+ INVALID_BULK_DELETE_QUANTITY: number;
+ CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: number;
+ CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: number;
+ BULK_DELETE_MESSAGE_TOO_OLD: number;
+ INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: number;
+ REACTION_BLOCKED: number;
+ }
+
+ interface AuditLogChange {
+ key: string;
+ old?: any;
+ new?: any;
+ }
+
+ interface AwaitMessagesOptions extends MessageCollectorOptions {
+ errors?: string[];
+ }
+
+ interface AwaitReactionsOptions extends ReactionCollectorOptions {
+ errors?: string[];
+ }
+
+ interface BanOptions {
+ days?: number;
+ reason?: string;
+ }
+
+ type Base64Resolvable = Buffer | Base64String;
+
+ type Base64String = string;
+
+ type BitFieldResolvable<T extends string> =
+ | RecursiveArray<T | number | Readonly<BitField<T>>>
+ | T
+ | number
+ | Readonly<BitField<T>>;
+
+ type BufferResolvable = Buffer | string;
+
+ interface ChannelCreationOverwrites {
+ allow?: PermissionResolvable | number;
+ deny?: PermissionResolvable | number;
+ id: RoleResolvable | UserResolvable;
+ }
+
+ interface ChannelData {
+ name?: string;
+ position?: number;
+ topic?: string;
+ nsfw?: boolean;
+ bitrate?: number;
+ userLimit?: number;
+ parentID?: Snowflake;
+ rateLimitPerUser?: number;
+ lockPermissions?: boolean;
+ permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>;
+ }
+
+ interface ChannelLogsQueryOptions {
+ limit?: number;
+ before?: Snowflake;
+ after?: Snowflake;
+ around?: Snowflake;
+ }
+
+ interface ChannelPosition {
+ channel: ChannelResolvable;
+ position: number;
+ }
+
+ type ChannelResolvable = Channel | Snowflake;
+
+ interface ClientApplicationAsset {
+ name: string;
+ id: Snowflake;
+ type: 'BIG' | 'SMALL';
+ }
+
+ interface ClientEvents {
+ channelCreate: [Channel];
+ channelDelete: [Channel | PartialDMChannel];
+ channelPinsUpdate: [Channel | PartialDMChannel, Date];
+ channelUpdate: [Channel, Channel];
+ debug: [string];
+ warn: [string];
+ disconnect: [any, number];
+ emojiCreate: [GuildEmoji];
+ emojiDelete: [GuildEmoji];
+ emojiUpdate: [GuildEmoji, GuildEmoji];
+ error: [Error];
+ guildBanAdd: [Guild, User | PartialUser];
+ guildBanRemove: [Guild, User | PartialUser];
+ guildCreate: [Guild];
+ guildDelete: [Guild];
+ guildUnavailable: [Guild];
+ guildIntegrationsUpdate: [Guild];
+ guildMemberAdd: [GuildMember | PartialGuildMember];
+ guildMemberAvailable: [GuildMember | PartialGuildMember];
+ guildMemberRemove: [GuildMember | PartialGuildMember];
+ guildMembersChunk: [Collection<Snowflake, GuildMember | PartialGuildMember>, Guild];
+ guildMemberSpeaking: [GuildMember | PartialGuildMember, Readonly<Speaking>];
+ guildMemberUpdate: [GuildMember | PartialGuildMember, GuildMember | PartialGuildMember];
+ guildUpdate: [Guild, Guild];
+ inviteCreate: [Invite];
+ inviteDelete: [Invite];
+ message: [Message];
+ messageDelete: [Message | PartialMessage];
+ messageReactionRemoveAll: [Message | PartialMessage];
+ messageReactionRemoveEmoji: [MessageReaction];
+ messageDeleteBulk: [Collection<Snowflake, Message | PartialMessage>];
+ messageReactionAdd: [MessageReaction, User | PartialUser];
+ messageReactionRemove: [MessageReaction, User | PartialUser];
+ messageUpdate: [Message | PartialMessage, Message | PartialMessage];
+ presenceUpdate: [Presence | undefined, Presence];
+ rateLimit: [RateLimitData];
+ ready: [];
+ invalidated: [];
+ roleCreate: [Role];
+ roleDelete: [Role];
+ roleUpdate: [Role, Role];
+ typingStart: [Channel | PartialDMChannel, User | PartialUser];
+ userUpdate: [User | PartialUser, User | PartialUser];
+ voiceStateUpdate: [VoiceState, VoiceState];
+ webhookUpdate: [TextChannel];
+ shardDisconnect: [CloseEvent, number];
+ shardError: [Error, number];
+ shardReady: [number];
+ shardReconnecting: [number];
+ shardResume: [number, number];
+ }
+
+ interface ClientOptions {
+ shards?: number | number[] | 'auto';
+ shardCount?: number;
+ messageCacheMaxSize?: number;
+ messageCacheLifetime?: number;
+ messageSweepInterval?: number;
+ fetchAllMembers?: boolean;
+ disableMentions?: 'none' | 'all' | 'everyone';
+ allowedMentions?: MessageMentionOptions;
+ partials?: PartialTypes[];
+ restWsBridgeTimeout?: number;
+ restTimeOffset?: number;
+ restRequestTimeout?: number;
+ restSweepInterval?: number;
+ retryLimit?: number;
+ presence?: PresenceData;
+ ws?: WebSocketOptions;
+ http?: HTTPOptions;
+ }
+
+ type ClientPresenceStatus = 'online' | 'idle' | 'dnd';
+
+ interface ClientPresenceStatusData {
+ web?: ClientPresenceStatus;
+ mobile?: ClientPresenceStatus;
+ desktop?: ClientPresenceStatus;
+ }
+
+ interface CloseEvent {
+ wasClean: boolean;
+ code: number;
+ reason: string;
+ target: WebSocket;
+ }
+
+ type CollectorFilter = (...args: any[]) => boolean;
+
+ interface CollectorOptions {
+ time?: number;
+ idle?: number;
+ dispose?: boolean;
+ }
+
+ type ColorResolvable =
+ | 'DEFAULT'
+ | 'WHITE'
+ | 'AQUA'
+ | 'GREEN'
+ | 'BLUE'
+ | 'YELLOW'
+ | 'PURPLE'
+ | 'LUMINOUS_VIVID_PINK'
+ | 'GOLD'
+ | 'ORANGE'
+ | 'RED'
+ | 'GREY'
+ | 'DARKER_GREY'
+ | 'NAVY'
+ | 'DARK_AQUA'
+ | 'DARK_GREEN'
+ | 'DARK_BLUE'
+ | 'DARK_PURPLE'
+ | 'DARK_VIVID_PINK'
+ | 'DARK_GOLD'
+ | 'DARK_ORANGE'
+ | 'DARK_RED'
+ | 'DARK_GREY'
+ | 'LIGHT_GREY'
+ | 'DARK_NAVY'
+ | 'RANDOM'
+ | [number, number, number]
+ | number
+ | string;
+
+ interface CrosspostedChannel {
+ channelID: Snowflake;
+ guildID: Snowflake;
+ type: keyof typeof ChannelType;
+ name: string;
+ }
+
+ interface DeconstructedSnowflake {
+ timestamp: number;
+ readonly date: Date;
+ workerID: number;
+ processID: number;
+ increment: number;
+ binary: string;
+ }
+
+ type DefaultMessageNotifications = 'ALL' | 'MENTIONS';
+
+ interface EmbedField {
+ name: string;
+ value: string;
+ inline: boolean;
+ }
+
+ interface EmbedFieldData {
+ name: StringResolvable;
+ value: StringResolvable;
+ inline?: boolean;
+ }
+
+ type EmojiIdentifierResolvable = string | EmojiResolvable;
+
+ type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji;
+
+ interface ErrorEvent {
+ error: any;
+ message: string;
+ type: string;
+ target: WebSocket;
+ }
+
+ interface EscapeMarkdownOptions {
+ codeBlock?: boolean;
+ inlineCode?: boolean;
+ bold?: boolean;
+ italic?: boolean;
+ underline?: boolean;
+ strikethrough?: boolean;
+ spoiler?: boolean;
+ inlineCodeContent?: boolean;
+ codeBlockContent?: boolean;
+ }
+
+ type ExplicitContentFilterLevel = 'DISABLED' | 'MEMBERS_WITHOUT_ROLES' | 'ALL_MEMBERS';
+
+ interface Extendable {
+ GuildEmoji: typeof GuildEmoji;
+ DMChannel: typeof DMChannel;
+ TextChannel: typeof TextChannel;
+ VoiceChannel: typeof VoiceChannel;
+ CategoryChannel: typeof CategoryChannel;
+ NewsChannel: typeof NewsChannel;
+ StoreChannel: typeof StoreChannel;
+ GuildMember: typeof GuildMember;
+ Guild: typeof Guild;
+ Message: typeof Message;
+ MessageReaction: typeof MessageReaction;
+ Presence: typeof Presence;
+ VoiceState: typeof VoiceState;
+ Role: typeof Role;
+ User: typeof User;
+ }
+
+ interface FetchMemberOptions {
+ user: UserResolvable;
+ cache?: boolean;
+ }
+
+ interface FetchMembersOptions {
+ user?: UserResolvable | UserResolvable[];
+ query?: string;
+ limit?: number;
+ withPresences?: boolean;
+ time?: number;
+ }
+
+ interface FileOptions {
+ attachment: BufferResolvable | Stream;
+ name?: string;
+ }
+
+ type GuildAuditLogsAction = keyof GuildAuditLogsActions;
+
+ interface GuildAuditLogsActions {
+ ALL?: null;
+ GUILD_UPDATE?: number;
+ CHANNEL_CREATE?: number;
+ CHANNEL_UPDATE?: number;
+ CHANNEL_DELETE?: number;
+ CHANNEL_OVERWRITE_CREATE?: number;
+ CHANNEL_OVERWRITE_UPDATE?: number;
+ CHANNEL_OVERWRITE_DELETE?: number;
+ MEMBER_KICK?: number;
+ MEMBER_PRUNE?: number;
+ MEMBER_BAN_ADD?: number;
+ MEMBER_BAN_REMOVE?: number;
+ MEMBER_UPDATE?: number;
+ MEMBER_ROLE_UPDATE?: number;
+ MEMBER_MOVE?: number;
+ MEMBER_DISCONNECT?: number;
+ BOT_ADD?: number;
+ ROLE_CREATE?: number;
+ ROLE_UPDATE?: number;
+ ROLE_DELETE?: number;
+ INVITE_CREATE?: number;
+ INVITE_UPDATE?: number;
+ INVITE_DELETE?: number;
+ WEBHOOK_CREATE?: number;
+ WEBHOOK_UPDATE?: number;
+ WEBHOOK_DELETE?: number;
+ EMOJI_CREATE?: number;
+ EMOJI_UPDATE?: number;
+ EMOJI_DELETE?: number;
+ MESSAGE_DELETE?: number;
+ MESSAGE_BULK_DELETE?: number;
+ MESSAGE_PIN?: number;
+ MESSAGE_UNPIN?: number;
+ INTEGRATION_CREATE?: number;
+ INTEGRATION_UPDATE?: number;
+ INTEGRATION_DELETE?: number;
+ }
+
+ type GuildAuditLogsActionType = 'CREATE' | 'DELETE' | 'UPDATE' | 'ALL';
+
+ interface GuildAuditLogsFetchOptions {
+ before?: Snowflake | GuildAuditLogsEntry;
+ limit?: number;
+ user?: UserResolvable;
+ type?: GuildAuditLogsAction | number;
+ }
+
+ type GuildAuditLogsTarget = keyof GuildAuditLogsTargets;
+
+ interface GuildAuditLogsTargets {
+ ALL?: string;
+ GUILD?: string;
+ CHANNEL?: string;
+ USER?: string;
+ ROLE?: string;
+ INVITE?: string;
+ WEBHOOK?: string;
+ EMOJI?: string;
+ MESSAGE?: string;
+ INTEGRATION?: string;
+ UNKNOWN?: string;
+ }
+
+ type GuildChannelResolvable = Snowflake | GuildChannel;
+
+ interface GuildCreateChannelOptions {
+ permissionOverwrites?: OverwriteResolvable[] | Collection<Snowflake, OverwriteResolvable>;
+ topic?: string;
+ type?: Exclude<
+ keyof typeof ChannelType | ChannelType,
+ 'dm' | 'group' | 'unknown' | ChannelType.dm | ChannelType.group | ChannelType.unknown
+ >;
+ nsfw?: boolean;
+ parent?: ChannelResolvable;
+ bitrate?: number;
+ userLimit?: number;
+ rateLimitPerUser?: number;
+ position?: number;
+ reason?: string;
+ }
+
+ interface GuildChannelCloneOptions extends GuildCreateChannelOptions {
+ name?: string;
+ }
+
+ interface GuildEditData {
+ name?: string;
+ region?: string;
+ verificationLevel?: VerificationLevel;
+ explicitContentFilter?: ExplicitContentFilterLevel;
+ defaultMessageNotifications?: DefaultMessageNotifications | number;
+ afkChannel?: ChannelResolvable;
+ systemChannel?: ChannelResolvable;
+ systemChannelFlags?: SystemChannelFlagsResolvable;
+ afkTimeout?: number;
+ icon?: Base64Resolvable;
+ owner?: GuildMemberResolvable;
+ splash?: Base64Resolvable;
+ banner?: Base64Resolvable;
+ }
+
+ interface GuildEmbedData {
+ enabled: boolean;
+ channel: GuildChannelResolvable | null;
+ }
+
+ interface GuildEmojiCreateOptions {
+ roles?: Collection<Snowflake, Role> | RoleResolvable[];
+ reason?: string;
+ }
+
+ interface GuildEmojiEditData {
+ name?: string;
+ roles?: Collection<Snowflake, Role> | RoleResolvable[];
+ }
+
+ type GuildFeatures =
+ | 'ANIMATED_ICON'
+ | 'BANNER'
+ | 'COMMERCE'
+ | 'DISCOVERABLE'
+ | 'FEATURABLE'
+ | 'INVITE_SPLASH'
+ | 'NEWS'
+ | 'PARTNERED'
+ | 'PUBLIC'
+ | 'PUBLIC_DISABLED'
+ | 'VANITY_URL'
+ | 'VERIFIED'
+ | 'VIP_REGIONS'
+ | 'WELCOME_SCREEN_ENABLED';
+
+ interface GuildMemberEditData {
+ nick?: string;
+ roles?: Collection<Snowflake, Role> | RoleResolvable[];
+ mute?: boolean;
+ deaf?: boolean;
+ channel?: ChannelResolvable | null;
+ }
+
+ type GuildMemberResolvable = GuildMember | UserResolvable;
+
+ type GuildResolvable = Guild | GuildChannel | GuildMember | GuildEmoji | Invite | Role | Snowflake;
+
+ interface GuildPruneMembersOptions {
+ count?: boolean;
+ days?: number;
+ dry?: boolean;
+ reason?: string;
+ }
+
+ interface HTTPOptions {
+ api?: string;
+ version?: number;
+ host?: string;
+ cdn?: string;
+ invite?: string;
+ }
+
+ type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096;
+
+ interface ImageURLOptions {
+ format?: AllowedImageFormat;
+ size?: ImageSize;
+ }
+
+ interface IntegrationData {
+ id: string;
+ type: string;
+ }
+
+ interface IntegrationEditData {
+ expireBehavior?: number;
+ expireGracePeriod?: number;
+ }
+
+ interface IntegrationAccount {
+ id: string;
+ name: string;
+ }
+
+ type IntentsString =
+ | 'GUILDS'
+ | 'GUILD_MEMBERS'
+ | 'GUILD_BANS'
+ | 'GUILD_EMOJIS'
+ | 'GUILD_INTEGRATIONS'
+ | 'GUILD_WEBHOOKS'
+ | 'GUILD_INVITES'
+ | 'GUILD_VOICE_STATES'
+ | 'GUILD_PRESENCES'
+ | 'GUILD_MESSAGES'
+ | 'GUILD_MESSAGE_REACTIONS'
+ | 'GUILD_MESSAGE_TYPING'
+ | 'DIRECT_MESSAGES'
+ | 'DIRECT_MESSAGE_REACTIONS'
+ | 'DIRECT_MESSAGE_TYPING';
+
+ interface InviteOptions {
+ temporary?: boolean;
+ maxAge?: number;
+ maxUses?: number;
+ unique?: boolean;
+ reason?: string;
+ }
+
+ type InviteResolvable = string;
+
+ type MembershipStates = 'INVITED' | 'ACCEPTED';
+
+ type MessageAdditions = MessageEmbed | MessageAttachment | (MessageEmbed | MessageAttachment)[];
+
+ interface MessageActivity {
+ partyID: string;
+ type: number;
+ }
+
+ interface MessageCollectorOptions extends CollectorOptions {
+ max?: number;
+ maxProcessed?: number;
+ }
+
+ interface MessageEditOptions {
+ content?: string;
+ embed?: MessageEmbedOptions | null;
+ code?: string | boolean;
+ flags?: BitFieldResolvable<MessageFlagsString>;
+ allowedMentions?: MessageMentionOptions;
+ }
+
+ interface MessageEmbedAuthor {
+ name?: string;
+ url?: string;
+ iconURL?: string;
+ proxyIconURL?: string;
+ }
+
+ interface MessageEmbedFooter {
+ text?: string;
+ iconURL?: string;
+ proxyIconURL?: string;
+ }
+
+ interface MessageEmbedImage {
+ url: string;
+ proxyURL?: string;
+ height?: number;
+ width?: number;
+ }
+
+ interface MessageEmbedOptions {
+ title?: string;
+ description?: string;
+ url?: string;
+ timestamp?: Date | number;
+ color?: ColorResolvable;
+ fields?: EmbedFieldData[];
+ files?: (MessageAttachment | string | FileOptions)[];
+ author?: Partial<MessageEmbedAuthor> & { icon_url?: string; proxy_icon_url?: string };
+ thumbnail?: Partial<MessageEmbedThumbnail> & { proxy_url?: string };
+ image?: Partial<MessageEmbedImage> & { proxy_url?: string };
+ video?: Partial<MessageEmbedVideo> & { proxy_url?: string };
+ footer?: Partial<MessageEmbedFooter> & { icon_url?: string; proxy_icon_url?: string };
+ }
+
+ interface MessageEmbedProvider {
+ name: string;
+ url: string;
+ }
+
+ interface MessageEmbedThumbnail {
+ url: string;
+ proxyURL?: string;
+ height?: number;
+ width?: number;
+ }
+
+ interface MessageEmbedVideo {
+ url?: string;
+ proxyURL?: string;
+ height?: number;
+ width?: number;
+ }
+
+ interface MessageEvent {
+ data: WebSocket.Data;
+ type: string;
+ target: WebSocket;
+ }
+
+ type MessageFlagsString = 'CROSSPOSTED' | 'IS_CROSSPOST' | 'SUPPRESS_EMBEDS' | 'SOURCE_MESSAGE_DELETED' | 'URGENT';
+
+ interface MessageMentionOptions {
+ parse?: MessageMentionTypes[];
+ roles?: Snowflake[];
+ users?: Snowflake[];
+ }
+
+ type MessageMentionTypes = 'roles' | 'users' | 'everyone';
+
+ interface MessageOptions {
+ tts?: boolean;
+ nonce?: string;
+ content?: string;
+ embed?: MessageEmbed | MessageEmbedOptions;
+ disableMentions?: 'none' | 'all' | 'everyone';
+ allowedMentions?: MessageMentionOptions;
+ files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[];
+ code?: string | boolean;
+ split?: boolean | SplitOptions;
+ reply?: UserResolvable;
+ }
+
+ type MessageReactionResolvable = MessageReaction | Snowflake;
+
+ interface MessageReference {
+ channelID: string;
+ guildID: string;
+ messageID: string | null;
+ }
+
+ type MessageResolvable = Message | Snowflake;
+
+ type MessageTarget = TextChannel | DMChannel | User | GuildMember | Webhook | WebhookClient;
+
+ type MessageType =
+ | 'DEFAULT'
+ | 'RECIPIENT_ADD'
+ | 'RECIPIENT_REMOVE'
+ | 'CALL'
+ | 'CHANNEL_NAME_CHANGE'
+ | 'CHANNEL_ICON_CHANGE'
+ | 'PINS_ADD'
+ | 'GUILD_MEMBER_JOIN'
+ | 'USER_PREMIUM_GUILD_SUBSCRIPTION'
+ | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1'
+ | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2'
+ | 'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3'
+ | 'CHANNEL_FOLLOW_ADD'
+ | 'GUILD_DISCOVERY_DISQUALIFIED'
+ | 'GUILD_DISCOVERY_REQUALIFIED';
+
+ interface OverwriteData {
+ allow?: PermissionResolvable;
+ deny?: PermissionResolvable;
+ id: GuildMemberResolvable | RoleResolvable;
+ type?: OverwriteType;
+ }
+
+ type OverwriteResolvable = PermissionOverwrites | OverwriteData;
+
+ type OverwriteType = 'member' | 'role';
+
+ interface PermissionFlags extends Record<PermissionString, number> {}
+
+ interface PermissionObject extends Record<PermissionString, boolean> {}
+
+ interface PermissionOverwriteOption extends Partial<Record<PermissionString, boolean | null>> {}
+
+ type PermissionResolvable = BitFieldResolvable<PermissionString>;
+
+ type PermissionString =
+ | 'CREATE_INSTANT_INVITE'
+ | 'KICK_MEMBERS'
+ | 'BAN_MEMBERS'
+ | 'ADMINISTRATOR'
+ | 'MANAGE_CHANNELS'
+ | 'MANAGE_GUILD'
+ | 'ADD_REACTIONS'
+ | 'VIEW_AUDIT_LOG'
+ | 'PRIORITY_SPEAKER'
+ | 'STREAM'
+ | 'VIEW_CHANNEL'
+ | 'SEND_MESSAGES'
+ | 'SEND_TTS_MESSAGES'
+ | 'MANAGE_MESSAGES'
+ | 'EMBED_LINKS'
+ | 'ATTACH_FILES'
+ | 'READ_MESSAGE_HISTORY'
+ | 'MENTION_EVERYONE'
+ | 'USE_EXTERNAL_EMOJIS'
+ | 'VIEW_GUILD_INSIGHTS'
+ | 'CONNECT'
+ | 'SPEAK'
+ | 'MUTE_MEMBERS'
+ | 'DEAFEN_MEMBERS'
+ | 'MOVE_MEMBERS'
+ | 'USE_VAD'
+ | 'CHANGE_NICKNAME'
+ | 'MANAGE_NICKNAMES'
+ | 'MANAGE_ROLES'
+ | 'MANAGE_WEBHOOKS'
+ | 'MANAGE_EMOJIS';
+
+ interface RecursiveArray<T> extends Array<T | RecursiveArray<T>> {}
+
+ interface PermissionOverwriteOptions {
+ allow: PermissionResolvable;
+ deny: PermissionResolvable;
+ id: UserResolvable | RoleResolvable;
+ }
+
+ type PremiumTier = number;
+
+ interface PresenceData {
+ status?: PresenceStatusData;
+ afk?: boolean;
+ activity?: {
+ name?: string;
+ type?: ActivityType | number;
+ url?: string;
+ };
+ shardID?: number | number[];
+ }
+
+ type PresenceResolvable = Presence | UserResolvable | Snowflake;
+
+ type Partialize<T, O extends string> = {
+ readonly client: Client;
+ readonly createdAt: Date;
+ readonly createdTimestamp: number;
+ deleted: boolean;
+ id: string;
+ partial: true;
+ fetch(): Promise<T>;
+ } & {
+ [K in keyof Omit<
+ T,
+ 'client' | 'createdAt' | 'createdTimestamp' | 'id' | 'partial' | 'fetch' | O
+ >]: T[K] extends Function ? T[K] : T[K] | null; // tslint:disable-line:ban-types
+ };
+
+ interface PartialDMChannel
+ extends Partialize<
+ DMChannel,
+ 'lastMessage' | 'lastMessageID' | 'messages' | 'recipient' | 'type' | 'typing' | 'typingCount'
+ > {
+ lastMessage: null;
+ lastMessageID: undefined;
+ messages: MessageManager;
+ recipient: User | PartialUser;
+ type: 'dm';
+ readonly typing: boolean;
+ readonly typingCount: number;
+ }
+
+ interface PartialChannelData {
+ id?: number;
+ name: string;
+ topic?: string;
+ type?: ChannelType;
+ parentID?: number;
+ permissionOverwrites?: {
+ id: number | Snowflake;
+ type?: OverwriteType;
+ allow?: PermissionResolvable;
+ deny?: PermissionResolvable;
+ }[];
+ }
+
+ interface PartialGuildMember
+ extends Partialize<
+ GuildMember,
+ 'bannable' | 'displayColor' | 'displayHexColor' | 'displayName' | 'guild' | 'kickable' | 'permissions' | 'roles'
+ > {
+ readonly bannable: boolean;
+ readonly displayColor: number;
+ readonly displayHexColor: string;
+ readonly displayName: string;
+ guild: Guild;
+ joinedAt: null;
+ joinedTimestamp: null;
+ readonly kickable: boolean;
+ readonly permissions: GuildMember['permissions'];
+ readonly roles: GuildMember['roles'];
+ }
+
+ interface PartialMessage
+ extends Partialize<
+ Message,
+ 'attachments' | 'channel' | 'deletable' | 'editable' | 'mentions' | 'pinnable' | 'system' | 'url'
+ > {
+ attachments: Message['attachments'];
+ channel: Message['channel'];
+ readonly deletable: boolean;
+ readonly editable: boolean;
+ mentions: Message['mentions'];
+ readonly pinnable: boolean;
+ reactions: Message['reactions'];
+ system: boolean;
+ readonly url: string;
+ }
+
+ interface PartialRoleData extends RoleData {
+ id?: number;
+ }
+
+ type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION';
+
+ interface PartialUser extends Partialize<User, 'discriminator' | 'username' | 'tag'> {
+ discriminator: undefined;
+ username: undefined;
+ readonly tag: null;
+ }
+
+ type PresenceStatus = ClientPresenceStatus | 'offline';
+
+ type PresenceStatusData = ClientPresenceStatus | 'invisible';
+
+ interface RateLimitData {
+ timeout: number;
+ limit: number;
+ timeDifference: number;
+ method: string;
+ path: string;
+ route: string;
+ }
+
+ interface RawOverwriteData {
+ id: Snowflake;
+ allow: number;
+ deny: number;
+ type: OverwriteType;
+ }
+
+ interface ReactionCollectorOptions extends CollectorOptions {
+ max?: number;
+ maxEmojis?: number;
+ maxUsers?: number;
+ }
+
+ interface ResolvedOverwriteOptions {
+ allow: Permissions;
+ deny: Permissions;
+ }
+
+ interface RoleData {
+ name?: string;
+ color?: ColorResolvable;
+ hoist?: boolean;
+ position?: number;
+ permissions?: PermissionResolvable;
+ mentionable?: boolean;
+ }
+
+ interface RolePosition {
+ role: RoleResolvable;
+ position: number;
+ }
+
+ type RoleResolvable = Role | string;
+
+ type ShardingManagerMode = 'process' | 'worker';
+
+ type Snowflake = string;
+
+ interface SplitOptions {
+ maxLength?: number;
+ char?: string;
+ prepend?: string;
+ append?: string;
+ }
+
+ type Status = number;
+
+ interface StreamOptions {
+ type?: StreamType;
+ seek?: number;
+ volume?: number | boolean;
+ plp?: number;
+ fec?: boolean;
+ bitrate?: number | 'auto';
+ highWaterMark?: number;
+ }
+
+ type SpeakingString = 'SPEAKING' | 'SOUNDSHARE' | 'PRIORITY_SPEAKING';
+
+ type StreamType = 'unknown' | 'converted' | 'opus' | 'ogg/opus' | 'webm/opus';
+
+ type StringResolvable = string | string[] | any;
+
+ type SystemChannelFlagsString = 'WELCOME_MESSAGE_DISABLED' | 'BOOST_MESSAGE_DISABLED';
+
+ type SystemChannelFlagsResolvable = BitFieldResolvable<SystemChannelFlagsString>;
+
+ type TargetUser = number;
+
+ interface TypingData {
+ user: User | PartialUser;
+ since: Date;
+ lastTimestamp: Date;
+ elapsedTime: number;
+ timeout: NodeJS.Timeout;
+ }
+
+ type UserFlagsString =
+ | 'DISCORD_EMPLOYEE'
+ | 'DISCORD_PARTNER'
+ | 'HYPESQUAD_EVENTS'
+ | 'BUGHUNTER_LEVEL_1'
+ | 'HOUSE_BRAVERY'
+ | 'HOUSE_BRILLIANCE'
+ | 'HOUSE_BALANCE'
+ | 'EARLY_SUPPORTER'
+ | 'TEAM_USER'
+ | 'SYSTEM'
+ | 'BUGHUNTER_LEVEL_2'
+ | 'VERIFIED_BOT'
+ | 'VERIFIED_DEVELOPER';
+
+ type UserResolvable = User | Snowflake | Message | GuildMember;
+
+ type VerificationLevel = 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'VERY_HIGH';
+
+ type VoiceStatus = number;
+
+ interface WebhookEditData {
+ name?: string;
+ avatar?: BufferResolvable;
+ channel?: ChannelResolvable;
+ reason?: string;
+ }
+
+ interface WebhookMessageOptions {
+ username?: string;
+ avatarURL?: string;
+ tts?: boolean;
+ nonce?: string;
+ embeds?: (MessageEmbed | object)[];
+ disableMentions?: 'none' | 'all' | 'everyone';
+ allowedMentions?: MessageMentionOptions;
+ files?: (FileOptions | BufferResolvable | Stream | MessageAttachment)[];
+ code?: string | boolean;
+ split?: boolean | SplitOptions;
+ }
+
+ type WebhookTypes = 'Incoming' | 'Channel Follower';
+
+ interface WebSocketOptions {
+ large_threshold?: number;
+ compress?: boolean;
+ intents?: BitFieldResolvable<IntentsString> | number;
+ }
+
+ type WSEventType =
+ | 'READY'
+ | 'RESUMED'
+ | 'GUILD_CREATE'
+ | 'GUILD_DELETE'
+ | 'GUILD_UPDATE'
+ | 'INVITE_CREATE'
+ | 'INVITE_DELETE'
+ | 'GUILD_MEMBER_ADD'
+ | 'GUILD_MEMBER_REMOVE'
+ | 'GUILD_MEMBER_UPDATE'
+ | 'GUILD_MEMBERS_CHUNK'
+ | 'GUILD_ROLE_CREATE'
+ | 'GUILD_ROLE_DELETE'
+ | 'GUILD_ROLE_UPDATE'
+ | 'GUILD_BAN_ADD'
+ | 'GUILD_BAN_REMOVE'
+ | 'GUILD_EMOJIS_UPDATE'
+ | 'GUILD_INTEGRATIONS_UPDATE'
+ | 'CHANNEL_CREATE'
+ | 'CHANNEL_DELETE'
+ | 'CHANNEL_UPDATE'
+ | 'CHANNEL_PINS_UPDATE'
+ | 'MESSAGE_CREATE'
+ | 'MESSAGE_DELETE'
+ | 'MESSAGE_UPDATE'
+ | 'MESSAGE_DELETE_BULK'
+ | 'MESSAGE_REACTION_ADD'
+ | 'MESSAGE_REACTION_REMOVE'
+ | 'MESSAGE_REACTION_REMOVE_ALL'
+ | 'MESSAGE_REACTION_REMOVE_EMOJI'
+ | 'USER_UPDATE'
+ | 'PRESENCE_UPDATE'
+ | 'TYPING_START'
+ | 'VOICE_STATE_UPDATE'
+ | 'VOICE_SERVER_UPDATE'
+ | 'WEBHOOKS_UPDATE';
+
+ //#endregion
+}
diff --git a/node_modules/discord.js/typings/index.ts b/node_modules/discord.js/typings/index.ts
new file mode 100644
index 0000000..26708a4
--- /dev/null
+++ b/node_modules/discord.js/typings/index.ts
@@ -0,0 +1,28 @@
+/// <reference path="index.d.ts" />
+
+import { Client } from 'discord.js';
+
+const client: Client = new Client();
+
+client.on('ready', () => {
+ console.log(`Client is logged in as ${client.user!.tag} and ready!`);
+});
+
+client.on('guildCreate', g => {
+ const channel = g.channels.cache.random();
+ if (!channel) return;
+
+ channel.setName('foo').then(updatedChannel => {
+ console.log(`New channel name: ${updatedChannel.name}`);
+ });
+});
+
+client.on('messageReactionRemoveAll', async message => {
+ console.log(`messageReactionRemoveAll - id: ${message.id} (${message.id.length})`);
+
+ if (message.partial) message = await message.fetch();
+
+ console.log(`messageReactionRemoveAll - content: ${message.content}`);
+});
+
+client.login('absolutely-valid-token');
diff --git a/node_modules/discord.js/webpack/discord.min.js b/node_modules/discord.js/webpack/discord.min.js
new file mode 100644
index 0000000..24d1987
--- /dev/null
+++ b/node_modules/discord.js/webpack/discord.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Discord=t():e.Discord=t()}(window,(function(){return function(e){var t={};function i(s){if(t[s])return t[s].exports;var n=t[s]={i:s,l:!1,exports:{}};return e[s].call(n.exports,n,n.exports,i),n.l=!0,n.exports}return i.m=e,i.c=t,i.d=function(e,t,s){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:s})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var s=Object.create(null);if(i.r(s),Object.defineProperty(s,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(s,n,function(t){return e[t]}.bind(null,n));return s},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=97)}([function(e,t,i){"use strict";(function(e){const s=t.Package=i(58),{Error:n,RangeError:r}=i(3),o=t.browser="undefined"!=typeof window;t.DefaultOptions={shardCount:1,messageCacheMaxSize:200,messageCacheLifetime:0,messageSweepInterval:0,fetchAllMembers:!1,disableMentions:"none",partials:[],restWsBridgeTimeout:5e3,restRequestTimeout:15e3,retryLimit:1,restTimeOffset:500,restSweepInterval:60,presence:{},ws:{large_threshold:250,compress:!1,properties:{$os:o?"browser":e.platform,$browser:"discord.js",$device:"discord.js"},version:6},http:{version:7,api:"https://discordapp.com/api",cdn:"https://cdn.discordapp.com",invite:"https://discord.gg"}},t.UserAgent=o?null:`DiscordBot (${s.homepage.split("#")[0]}, ${s.version}) Node.js/${e.version}`,t.WSCodes={1e3:"WS_CLOSE_REQUESTED",4004:"TOKEN_INVALID",4010:"SHARDING_INVALID",4011:"SHARDING_REQUIRED",4013:"INVALID_INTENTS",4014:"DISALLOWED_INTENTS"};const a=["webp","png","jpg","jpeg","gif"],c=Array.from({length:9},(e,t)=>2**(t+4));function l(e,{format:t="webp",size:i}={}){if(t&&!a.includes(t))throw new n("IMAGE_FORMAT",t);if(i&&!c.includes(i))throw new r("IMAGE_SIZE",i);return`${e}.${t}${i?`?size=${i}`:""}`}function h(e){let t=Object.create(null);for(const i of e)t[i]=i;return t}t.Endpoints={CDN:e=>({Emoji:(t,i="png")=>`${e}/emojis/${t}.${i}`,Asset:t=>`${e}/assets/${t}`,DefaultAvatar:t=>`${e}/embed/avatars/${t}.png`,Avatar:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),l(`${e}/avatars/${t}/${i}`,{format:s,size:n})),Banner:(t,i,s="webp",n)=>l(`${e}/banners/${t}/${i}`,{format:s,size:n}),Icon:(t,i,s="webp",n,r=!1)=>(r&&(s=i.startsWith("a_")?"gif":s),l(`${e}/icons/${t}/${i}`,{format:s,size:n})),AppIcon:(t,i,{format:s="webp",size:n}={})=>l(`${e}/app-icons/${t}/${i}`,{size:n,format:s}),AppAsset:(t,i,{format:s="webp",size:n}={})=>l(`${e}/app-assets/${t}/${i}`,{size:n,format:s}),GDMIcon:(t,i,s="webp",n)=>l(`${e}/channel-icons/${t}/${i}`,{size:n,format:s}),Splash:(t,i,s="webp",n)=>l(`${e}/splashes/${t}/${i}`,{size:n,format:s}),DiscoverySplash:(t,i,s="webp",n)=>l(`${e}/discovery-splashes/${t}/${i}`,{size:n,format:s}),TeamIcon:(t,i,{format:s="webp",size:n}={})=>l(`${e}/team-icons/${t}/${i}`,{size:n,format:s})}),invite:(e,t)=>`${e}/${t}`,botGateway:"/gateway/bot"},t.Status={READY:0,CONNECTING:1,RECONNECTING:2,IDLE:3,NEARLY:4,DISCONNECTED:5,WAITING_FOR_GUILDS:6,IDENTIFYING:7,RESUMING:8},t.VoiceStatus={CONNECTED:0,CONNECTING:1,AUTHENTICATING:2,RECONNECTING:3,DISCONNECTED:4},t.OPCodes={DISPATCH:0,HEARTBEAT:1,IDENTIFY:2,STATUS_UPDATE:3,VOICE_STATE_UPDATE:4,VOICE_GUILD_PING:5,RESUME:6,RECONNECT:7,REQUEST_GUILD_MEMBERS:8,INVALID_SESSION:9,HELLO:10,HEARTBEAT_ACK:11},t.VoiceOPCodes={IDENTIFY:0,SELECT_PROTOCOL:1,READY:2,HEARTBEAT:3,SESSION_DESCRIPTION:4,SPEAKING:5,HELLO:8,CLIENT_CONNECT:12,CLIENT_DISCONNECT:13},t.Events={RATE_LIMIT:"rateLimit",CLIENT_READY:"ready",GUILD_CREATE:"guildCreate",GUILD_DELETE:"guildDelete",GUILD_UPDATE:"guildUpdate",GUILD_UNAVAILABLE:"guildUnavailable",GUILD_AVAILABLE:"guildAvailable",GUILD_MEMBER_ADD:"guildMemberAdd",GUILD_MEMBER_REMOVE:"guildMemberRemove",GUILD_MEMBER_UPDATE:"guildMemberUpdate",GUILD_MEMBER_AVAILABLE:"guildMemberAvailable",GUILD_MEMBER_SPEAKING:"guildMemberSpeaking",GUILD_MEMBERS_CHUNK:"guildMembersChunk",GUILD_INTEGRATIONS_UPDATE:"guildIntegrationsUpdate",GUILD_ROLE_CREATE:"roleCreate",GUILD_ROLE_DELETE:"roleDelete",INVITE_CREATE:"inviteCreate",INVITE_DELETE:"inviteDelete",GUILD_ROLE_UPDATE:"roleUpdate",GUILD_EMOJI_CREATE:"emojiCreate",GUILD_EMOJI_DELETE:"emojiDelete",GUILD_EMOJI_UPDATE:"emojiUpdate",GUILD_BAN_ADD:"guildBanAdd",GUILD_BAN_REMOVE:"guildBanRemove",CHANNEL_CREATE:"channelCreate",CHANNEL_DELETE:"channelDelete",CHANNEL_UPDATE:"channelUpdate",CHANNEL_PINS_UPDATE:"channelPinsUpdate",MESSAGE_CREATE:"message",MESSAGE_DELETE:"messageDelete",MESSAGE_UPDATE:"messageUpdate",MESSAGE_BULK_DELETE:"messageDeleteBulk",MESSAGE_REACTION_ADD:"messageReactionAdd",MESSAGE_REACTION_REMOVE:"messageReactionRemove",MESSAGE_REACTION_REMOVE_ALL:"messageReactionRemoveAll",MESSAGE_REACTION_REMOVE_EMOJI:"messageReactionRemoveEmoji",USER_UPDATE:"userUpdate",PRESENCE_UPDATE:"presenceUpdate",VOICE_SERVER_UPDATE:"voiceServerUpdate",VOICE_STATE_UPDATE:"voiceStateUpdate",VOICE_BROADCAST_SUBSCRIBE:"subscribe",VOICE_BROADCAST_UNSUBSCRIBE:"unsubscribe",TYPING_START:"typingStart",TYPING_STOP:"typingStop",WEBHOOKS_UPDATE:"webhookUpdate",ERROR:"error",WARN:"warn",DEBUG:"debug",SHARD_DISCONNECT:"shardDisconnect",SHARD_ERROR:"shardError",SHARD_RECONNECTING:"shardReconnecting",SHARD_READY:"shardReady",SHARD_RESUME:"shardResume",INVALIDATED:"invalidated",RAW:"raw"},t.ShardEvents={CLOSE:"close",DESTROYED:"destroyed",INVALID_SESSION:"invalidSession",READY:"ready",RESUMED:"resumed",ALL_READY:"allReady"},t.PartialTypes=h(["USER","CHANNEL","GUILD_MEMBER","MESSAGE","REACTION"]),t.WSEvents=h(["READY","RESUMED","GUILD_CREATE","GUILD_DELETE","GUILD_UPDATE","INVITE_CREATE","INVITE_DELETE","GUILD_MEMBER_ADD","GUILD_MEMBER_REMOVE","GUILD_MEMBER_UPDATE","GUILD_MEMBERS_CHUNK","GUILD_INTEGRATIONS_UPDATE","GUILD_ROLE_CREATE","GUILD_ROLE_DELETE","GUILD_ROLE_UPDATE","GUILD_BAN_ADD","GUILD_BAN_REMOVE","GUILD_EMOJIS_UPDATE","CHANNEL_CREATE","CHANNEL_DELETE","CHANNEL_UPDATE","CHANNEL_PINS_UPDATE","MESSAGE_CREATE","MESSAGE_DELETE","MESSAGE_UPDATE","MESSAGE_DELETE_BULK","MESSAGE_REACTION_ADD","MESSAGE_REACTION_REMOVE","MESSAGE_REACTION_REMOVE_ALL","MESSAGE_REACTION_REMOVE_EMOJI","USER_UPDATE","PRESENCE_UPDATE","TYPING_START","VOICE_STATE_UPDATE","VOICE_SERVER_UPDATE","WEBHOOKS_UPDATE"]),t.MessageTypes=["DEFAULT","RECIPIENT_ADD","RECIPIENT_REMOVE","CALL","CHANNEL_NAME_CHANGE","CHANNEL_ICON_CHANGE","PINS_ADD","GUILD_MEMBER_JOIN","USER_PREMIUM_GUILD_SUBSCRIPTION","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2","USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3","CHANNEL_FOLLOW_ADD",null,"GUILD_DISCOVERY_DISQUALIFIED","GUILD_DISCOVERY_REQUALIFIED"],t.ActivityTypes=["PLAYING","STREAMING","LISTENING","WATCHING","CUSTOM_STATUS"],t.ChannelTypes={TEXT:0,DM:1,VOICE:2,GROUP:3,CATEGORY:4,NEWS:5,STORE:6},t.ClientApplicationAssetTypes={SMALL:1,BIG:2},t.Colors={DEFAULT:0,WHITE:16777215,AQUA:1752220,GREEN:3066993,BLUE:3447003,YELLOW:16776960,PURPLE:10181046,LUMINOUS_VIVID_PINK:15277667,GOLD:15844367,ORANGE:15105570,RED:15158332,GREY:9807270,NAVY:3426654,DARK_AQUA:1146986,DARK_GREEN:2067276,DARK_BLUE:2123412,DARK_PURPLE:7419530,DARK_VIVID_PINK:11342935,DARK_GOLD:12745742,DARK_ORANGE:11027200,DARK_RED:10038562,DARK_GREY:9936031,DARKER_GREY:8359053,LIGHT_GREY:12370112,DARK_NAVY:2899536,BLURPLE:7506394,GREYPLE:10070709,DARK_BUT_NOT_BLACK:2895667,NOT_QUITE_BLACK:2303786},t.ExplicitContentFilterLevels=["DISABLED","MEMBERS_WITHOUT_ROLES","ALL_MEMBERS"],t.VerificationLevels=["NONE","LOW","MEDIUM","HIGH","VERY_HIGH"],t.APIErrors={UNKNOWN_ACCOUNT:10001,UNKNOWN_APPLICATION:10002,UNKNOWN_CHANNEL:10003,UNKNOWN_GUILD:10004,UNKNOWN_INTEGRATION:10005,UNKNOWN_INVITE:10006,UNKNOWN_MEMBER:10007,UNKNOWN_MESSAGE:10008,UNKNOWN_OVERWRITE:10009,UNKNOWN_PROVIDER:10010,UNKNOWN_ROLE:10011,UNKNOWN_TOKEN:10012,UNKNOWN_USER:10013,UNKNOWN_EMOJI:10014,UNKNOWN_WEBHOOK:10015,BOT_PROHIBITED_ENDPOINT:20001,BOT_ONLY_ENDPOINT:20002,MAXIMUM_GUILDS:30001,MAXIMUM_FRIENDS:30002,MAXIMUM_PINS:30003,MAXIMUM_ROLES:30005,MAXIMUM_REACTIONS:30010,MAXIMUM_CHANNELS:30013,MAXIMUM_INVITES:30016,UNAUTHORIZED:40001,USER_BANNED:40007,MISSING_ACCESS:50001,INVALID_ACCOUNT_TYPE:50002,CANNOT_EXECUTE_ON_DM:50003,EMBED_DISABLED:50004,CANNOT_EDIT_MESSAGE_BY_OTHER:50005,CANNOT_SEND_EMPTY_MESSAGE:50006,CANNOT_MESSAGE_USER:50007,CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL:50008,CHANNEL_VERIFICATION_LEVEL_TOO_HIGH:50009,OAUTH2_APPLICATION_BOT_ABSENT:50010,MAXIMUM_OAUTH2_APPLICATIONS:50011,INVALID_OAUTH_STATE:50012,MISSING_PERMISSIONS:50013,INVALID_AUTHENTICATION_TOKEN:50014,NOTE_TOO_LONG:50015,INVALID_BULK_DELETE_QUANTITY:50016,CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL:50019,INVALID_OR_TAKEN_INVITE_CODE:50020,CANNOT_EXECUTE_ON_SYSTEM_MESSAGE:50021,INVALID_OAUTH_TOKEN:50025,BULK_DELETE_MESSAGE_TOO_OLD:50034,INVALID_FORM_BODY:50035,INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT:50036,INVALID_API_VERSION:50041,REACTION_BLOCKED:90001,RESOURCE_OVERLOADED:13e4},t.DefaultMessageNotifications=["ALL","MENTIONS"],t.MembershipStates=[null,"INVITED","ACCEPTED"],t.WebhookTypes=[null,"Incoming","Channel Follower"]}).call(this,i(14))},function(e,t,i){"use strict";const{PartialTypes:s}=i(0);e.exports=class GenericAction{constructor(e){this.client=e}handle(e){return e}getPayload(e,t,i,s,n){const r=t.cache.get(i);return!r&&this.client.options.partials.includes(s)?t.add(e,n):r}getChannel(e){const t=e.channel_id||e.id;return e.channel||this.getPayload({id:t,guild_id:e.guild_id,recipients:[e.author||{id:e.user_id}]},this.client.channels,t,s.CHANNEL)}getMessage(e,t,i){const n=e.message_id||e.id;return e.message||this.getPayload({id:n,channel_id:t.id,guild_id:e.guild_id||(t.guild?t.guild.id:null)},t.messages,n,s.MESSAGE,i)}getReaction(e,t,i){const n=e.emoji.id||decodeURIComponent(e.emoji.name);return this.getPayload({emoji:e.emoji,count:t.partial?null:0,me:!!i&&i.id===this.client.user.id},t.reactions,n,s.REACTION)}getMember(e,t){const i=e.user.id;return this.getPayload({user:{id:i}},t.members,i,s.GUILD_MEMBER)}getUser(e){const t=e.user_id;return e.user||this.getPayload({id:t},this.client.users,t,s.USER)}}},function(e,t,i){"use strict";const s=i(99),n=i(4);e.exports=class Collection extends s{toJSON(){return this.map(e=>"function"==typeof e.toJSON?e.toJSON():n.flatten(e))}}},function(e,t,i){"use strict";e.exports=i(59),e.exports.Messages=i(98)},function(e,t,i){"use strict";const{parse:s}=i(35),n=i(36),{Colors:r,DefaultOptions:o,Endpoints:a}=i(0),{Error:c,RangeError:l,TypeError:h}=i(3),u=e=>"object"==typeof e&&null!==e;class Util{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static flatten(e,...t){if(!u(e))return e;t=Object.assign(...Object.keys(e).filter(e=>!e.startsWith("_")).map(e=>({[e]:!0})),...t);const s={};for(let[n,r]of Object.entries(t)){if(!r)continue;r=!0===r?n:r;const t=e[n],o=u(t),a=o&&"function"==typeof t.valueOf?t.valueOf():null;t instanceof i(2)?s[r]=Array.from(t.keys()):a instanceof i(2)?s[r]=Array.from(a.keys()):Array.isArray(t)?s[r]=t.map(e=>Util.flatten(e)):"object"!=typeof a?s[r]=a:o||(s[r]=t)}return s}static splitMessage(e,{maxLength:t=2e3,char:i="\n",prepend:s="",append:n=""}={}){if((e=Util.resolveString(e)).length<=t)return[e];const r=e.split(i);if(r.some(e=>e.length>t))throw new l("SPLIT_MAX_LEN");const o=[];let a="";for(const e of r)a&&(a+i+e+n).length>t&&(o.push(a+n),a=s),a+=(a&&a!==s?i:"")+e;return o.concat(a).filter(e=>e)}static escapeMarkdown(e,{codeBlock:t=!0,inlineCode:i=!0,bold:s=!0,italic:n=!0,underline:r=!0,strikethrough:o=!0,spoiler:a=!0,codeBlockContent:c=!0,inlineCodeContent:l=!0}={}){return c?l?(i&&(e=Util.escapeInlineCode(e)),t&&(e=Util.escapeCodeBlock(e)),n&&(e=Util.escapeItalic(e)),s&&(e=Util.escapeBold(e)),r&&(e=Util.escapeUnderline(e)),o&&(e=Util.escapeStrikethrough(e)),a&&(e=Util.escapeSpoiler(e)),e):e.split(/(?<=^|[^`])`(?=[^`]|$)/g).map((e,i,c)=>i%2&&i!==c.length-1?e:Util.escapeMarkdown(e,{codeBlock:t,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a})).join(i?"\\`":"`"):e.split("```").map((e,t,c)=>t%2&&t!==c.length-1?e:Util.escapeMarkdown(e,{inlineCode:i,bold:s,italic:n,underline:r,strikethrough:o,spoiler:a,inlineCodeContent:l})).join(t?"\\`\\`\\`":"```")}static escapeCodeBlock(e){return e.replace(/```/g,"\\`\\`\\`")}static escapeInlineCode(e){return e.replace(/(?<=^|[^`])`(?=[^`]|$)/g,"\\`")}static escapeItalic(e){let t=0;return e=e.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g,(e,i)=>"**"===i?++t%2?`\\*${i}`:`${i}\\*`:`\\*${i}`),t=0,e.replace(/(?<=^|[^_])_([^_]|__|$)/g,(e,i)=>"__"===i?++t%2?`\\_${i}`:`${i}\\_`:`\\_${i}`)}static escapeBold(e){let t=0;return e.replace(/\*\*(\*)?/g,(e,i)=>i?++t%2?`${i}\\*\\*`:`\\*\\*${i}`:"\\*\\*")}static escapeUnderline(e){let t=0;return e.replace(/__(_)?/g,(e,i)=>i?++t%2?`${i}\\_\\_`:`\\_\\_${i}`:"\\_\\_")}static escapeStrikethrough(e){return e.replace(/~~/g,"\\~\\~")}static escapeSpoiler(e){return e.replace(/\|\|/g,"\\|\\|")}static fetchRecommendedShards(e,t=1e3){if(!e)throw new c("TOKEN_MISSING");return n(`${o.http.api}/v${o.http.version}${a.botGateway}`,{method:"GET",headers:{Authorization:`Bot ${e.replace(/^Bot\s*/i,"")}`}}).then(e=>{if(e.ok)return e.json();throw e}).then(e=>e.shards*(1e3/t))}static parseEmoji(e){if(e.includes("%")&&(e=decodeURIComponent(e)),!e.includes(":"))return{animated:!1,name:e,id:null};const t=e.match(/<?(?:(a):)?(\w{2,32}):(\d{17,19})?>?/);return t?{animated:Boolean(t[1]),name:t[2],id:t[3]||null}:null}static cloneObject(e){return Object.assign(Object.create(e),e)}static mergeDefault(e,t){if(!t)return e;for(const n in e)i=t,s=n,Object.prototype.hasOwnProperty.call(i,s)&&void 0!==t[n]?t[n]===Object(t[n])&&(t[n]=Util.mergeDefault(e[n],t[n])):t[n]=e[n];var i,s;return t}static convertToBuffer(e){return"string"==typeof e&&(e=Util.str2ab(e)),Buffer.from(e)}static str2ab(e){const t=new ArrayBuffer(2*e.length),i=new Uint16Array(t);for(var s=0,n=e.length;s<n;s++)i[s]=e.charCodeAt(s);return t}static makeError(e){const t=new Error(e.message);return t.name=e.name,t.stack=e.stack,t}static makePlainError(e){return{name:e.name,message:e.message,stack:e.stack}}static moveElementInArray(e,t,i,s=!1){const n=e.indexOf(t);if((i=(s?n:0)+i)>-1&&i<e.length){const t=e.splice(n,1)[0];e.splice(i,0,t)}return e.indexOf(t)}static resolveString(e){return"string"==typeof e?e:Array.isArray(e)?e.join("\n"):String(e)}static resolveColor(e){if("string"==typeof e){if("RANDOM"===e)return Math.floor(16777216*Math.random());if("DEFAULT"===e)return 0;e=r[e]||parseInt(e.replace("#",""),16)}else Array.isArray(e)&&(e=(e[0]<<16)+(e[1]<<8)+e[2]);if(e<0||e>16777215)throw new l("COLOR_RANGE");if(e&&isNaN(e))throw new h("COLOR_CONVERT");return e}static discordSort(e){return e.sorted((e,t)=>e.rawPosition-t.rawPosition||parseInt(t.id.slice(0,-10))-parseInt(e.id.slice(0,-10))||parseInt(t.id.slice(10))-parseInt(e.id.slice(10)))}static setPosition(e,t,i,s,n,r){let o=s.array();return Util.moveElementInArray(o,e,t,i),o=o.map((e,t)=>({id:e.id,position:t})),n.patch({data:o,reason:r}).then(()=>o)}static basename(e,t){let i=s(e);return t&&i.ext.startsWith(t)?i.name:i.base.split("?")[0]}static idToBinary(e){let t="",i=parseInt(e.slice(0,-10))||0,s=parseInt(e.slice(-10));for(;s>0||i>0;)t=String(1&s)+t,s=Math.floor(s/2),i>0&&(s+=i%2*5e9,i=Math.floor(i/2));return t}static binaryToID(e){let t="";for(;e.length>50;){const i=parseInt(e.slice(0,-32),2),s=parseInt((i%10).toString(2)+e.slice(-32),2);t=(s%10).toString()+t,e=Math.floor(i/10).toString(2)+Math.floor(s/10).toString(2).padStart(32,"0")}for(e=parseInt(e,2);e>0;)t=(e%10).toString()+t,e=Math.floor(e/10);return t}static removeMentions(e){return e.replace(/@/g,"@​")}static cleanContent(e,t){return e=e.replace(/<@!?[0-9]+>/g,e=>{const i=e.replace(/<|!|>|@/g,"");if("dm"===t.channel.type){const s=t.client.users.cache.get(i);return s?`@${s.username}`:e}const s=t.channel.guild.members.cache.get(i);if(s)return`@${s.displayName}`;{const s=t.client.users.cache.get(i);return s?`@${s.username}`:e}}).replace(/<#[0-9]+>/g,e=>{const i=t.client.channels.cache.get(e.replace(/<|#|>/g,""));return i?`#${i.name}`:e}).replace(/<@&[0-9]+>/g,e=>{if("dm"===t.channel.type)return e;const i=t.guild.roles.cache.get(e.replace(/<|@|>|&/g,""));return i?`@${i.name}`:e}),"everyone"===t.client.options.disableMentions&&(e=e.replace(/@([^<>@ ]*)/gmus,(e,t)=>t.match(/^[&!]?\d+$/)?`@${t}`:`@​${t}`)),"all"===t.client.options.disableMentions?Util.removeMentions(e):e}static cleanCodeBlockContent(e){return e.replace(/```/g,"`​``")}static delayFor(e){return new Promise(t=>{setTimeout(t,e)})}}e.exports=Util},function(e,t,i){"use strict";const s=i(4);e.exports=class Base{constructor(e){Object.defineProperty(this,"client",{value:e})}_clone(){return Object.assign(Object.create(this),this)}_patch(e){return e}_update(e){const t=this._clone();return this._patch(e),t}toJSON(...e){return s.flatten(this,...e)}valueOf(){return this.id}}},function(e,t,i){"use strict";const s=i(2);let n;e.exports=class BaseManager{constructor(e,t,r,o=s,...a){if(n||(n=i(23)),Object.defineProperty(this,"holds",{value:n.get(r.name)||r}),Object.defineProperty(this,"client",{value:e}),this.cacheType=o,this.cache=new o(...a),t)for(const e of t)this.add(e)}add(e,t=!0,{id:i,extras:s=[]}={}){const n=this.cache.get(i||e.id);if(n&&n._patch&&t&&n._patch(e),n)return n;const r=this.holds?new this.holds(this.client,e,...s):e;return t&&this.cache.set(i||r.id,r),r}resolve(e){return e instanceof this.holds?e:"string"==typeof e&&this.cache.get(e)||null}resolveID(e){return e instanceof this.holds?e.id:"string"==typeof e?e:null}valueOf(){return this.cache}}},function(e,t,i){"use strict";const s=i(4);let n=0;e.exports=class SnowflakeUtil{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static generate(e=Date.now()){if(e instanceof Date&&(e=e.getTime()),"number"!=typeof e||isNaN(e))throw new TypeError(`"timestamp" argument must be a number (received ${isNaN(e)?"NaN":typeof e})`);n>=4095&&(n=0);const t=`${(e-14200704e5).toString(2).padStart(42,"0")}0000100000${(n++).toString(2).padStart(12,"0")}`;return s.binaryToID(t)}static deconstruct(e){const t=s.idToBinary(e).toString(2).padStart(64,"0"),i={timestamp:parseInt(t.substring(0,42),2)+14200704e5,workerID:parseInt(t.substring(42,47),2),processID:parseInt(t.substring(47,52),2),increment:parseInt(t.substring(52,64),2),binary:t};return Object.defineProperty(i,"date",{get:function(){return new Date(this.timestamp)},enumerable:!0}),i}}},function(e,t,i){"use strict";const s=i(11);class Permissions extends s{any(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.any(e)}has(e,t=!0){return t&&super.has(this.constructor.FLAGS.ADMINISTRATOR)||super.has(e)}}Permissions.FLAGS={CREATE_INSTANT_INVITE:1,KICK_MEMBERS:2,BAN_MEMBERS:4,ADMINISTRATOR:8,MANAGE_CHANNELS:16,MANAGE_GUILD:32,ADD_REACTIONS:64,VIEW_AUDIT_LOG:128,PRIORITY_SPEAKER:256,STREAM:512,VIEW_CHANNEL:1024,SEND_MESSAGES:2048,SEND_TTS_MESSAGES:4096,MANAGE_MESSAGES:8192,EMBED_LINKS:16384,ATTACH_FILES:32768,READ_MESSAGE_HISTORY:65536,MENTION_EVERYONE:1<<17,USE_EXTERNAL_EMOJIS:1<<18,VIEW_GUILD_INSIGHTS:1<<19,CONNECT:1<<20,SPEAK:1<<21,MUTE_MEMBERS:1<<22,DEAFEN_MEMBERS:1<<23,MOVE_MEMBERS:1<<24,USE_VAD:1<<25,CHANGE_NICKNAME:1<<26,MANAGE_NICKNAMES:1<<27,MANAGE_ROLES:1<<28,MANAGE_WEBHOOKS:1<<29,MANAGE_EMOJIS:1<<30},Permissions.ALL=Object.values(Permissions.FLAGS).reduce((e,t)=>e|t,0),Permissions.DEFAULT=104324673,e.exports=Permissions},function(e,t,i){"use strict";const s=i(35),n=i(35),r=i(119),o=i(36),{Error:a,TypeError:c}=i(3),{browser:l}=i(0),h=i(4);class DataResolver{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static resolveInviteCode(e){const t=/discord(?:app\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i.exec(e);return t&&t[1]?t[1]:e}static async resolveImage(e){if(!e)return null;if("string"==typeof e&&e.startsWith("data:"))return e;const t=await this.resolveFileAsBuffer(e);return DataResolver.resolveBase64(t)}static resolveBase64(e){return Buffer.isBuffer(e)?`data:image/jpg;base64,${e.toString("base64")}`:e}static async resolveFile(e){if(!l&&Buffer.isBuffer(e))return e;if(l&&e instanceof ArrayBuffer)return h.convertToBuffer(e);if(e instanceof r.Readable)return e;if("string"==typeof e){if(/^https?:\/\//.test(e)){const t=await o(e);return l?t.blob():t.body}if(!l)return new Promise((t,i)=>{const r=n.resolve(e);s.stat(r,(e,n)=>e?i(e):n.isFile()?t(s.createReadStream(r)):i(new a("FILE_NOT_FOUND",r)))})}throw new c("REQ_RESOURCE_TYPE")}static async resolveFileAsBuffer(e){const t=await this.resolveFile(e);if(Buffer.isBuffer(t))return t;const i=[];for await(const e of t)i.push(e);return Buffer.concat(i)}}e.exports=DataResolver},function(e,t,i){"use strict";const s=i(5),{Presence:n}=i(13),r=i(19),o=i(27),a=i(33),{Error:c}=i(3),l=i(72),h=i(8);class GuildMember extends s{constructor(e,t,i){super(e),this.guild=i,t.user&&(this.user=e.users.add(t.user,!0)),this.joinedTimestamp=null,this.lastMessageID=null,this.lastMessageChannelID=null,this.premiumSinceTimestamp=null,this.deleted=!1,this._roles=[],t&&this._patch(t)}_patch(e){void 0!==e.nick&&(this.nickname=e.nick),e.joined_at&&(this.joinedTimestamp=new Date(e.joined_at).getTime()),e.premium_since&&(this.premiumSinceTimestamp=new Date(e.premium_since).getTime()),e.user&&(this.user=this.guild.client.users.add(e.user)),e.roles&&(this._roles=e.roles)}_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}get partial(){return!this.joinedTimestamp}get roles(){return new l(this)}get lastMessage(){const e=this.guild.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get voice(){return this.guild.voiceStates.cache.get(this.id)||new o(this.guild,{user_id:this.id})}get joinedAt(){return this.joinedTimestamp?new Date(this.joinedTimestamp):null}get premiumSince(){return this.premiumSinceTimestamp?new Date(this.premiumSinceTimestamp):null}get presence(){return this.guild.presences.cache.get(this.id)||new n(this.client,{user:{id:this.id},guild:this.guild})}get displayColor(){const e=this.roles.color;return e&&e.color||0}get displayHexColor(){const e=this.roles.color;return e&&e.hexColor||"#000000"}get id(){return this.user.id}get displayName(){return this.nickname||this.user.username}get permissions(){return this.user.id===this.guild.ownerID?new h(h.ALL).freeze():new h(this.roles.cache.map(e=>e.permissions)).freeze()}get manageable(){if(this.user.id===this.guild.ownerID)return!1;if(this.user.id===this.client.user.id)return!1;if(this.client.user.id===this.guild.ownerID)return!0;if(!this.guild.me)throw new c("GUILD_UNCACHED_ME");return this.guild.me.roles.highest.comparePositionTo(this.roles.highest)>0}get kickable(){return this.manageable&&this.guild.me.permissions.has(h.FLAGS.KICK_MEMBERS)}get bannable(){return this.manageable&&this.guild.me.permissions.has(h.FLAGS.BAN_MEMBERS)}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new c("GUILD_CHANNEL_RESOLVE");return e.memberPermissions(this)}hasPermission(e,{checkAdmin:t=!0,checkOwner:i=!0}={}){return!(!i||this.user.id!==this.guild.ownerID)||this.roles.cache.some(i=>i.permissions.has(e,t))}async edit(e,t){if(e.channel){if(e.channel=this.guild.channels.resolve(e.channel),!e.channel||"voice"!==e.channel.type)throw new c("GUILD_VOICE_CHANNEL_RESOLVE");e.channel_id=e.channel.id,e.channel=void 0}else null===e.channel&&(e.channel_id=null,e.channel=void 0);e.roles&&(e.roles=e.roles.map(e=>e instanceof r?e.id:e));let i=this.client.api.guilds(this.guild.id);if(this.user.id===this.client.user.id){const t=Object.keys(e);i=1===t.length&&"nick"===t[0]?i.members("@me").nick:i.members(this.id)}else i=i.members(this.id);await i.patch({data:e,reason:t});const s=this._clone();return e.user=this.user,s._patch(e),s}setNickname(e,t){return this.edit({nick:e},t)}createDM(){return this.user.createDM()}deleteDM(){return this.user.deleteDM()}kick(e){return this.client.api.guilds(this.guild.id).members(this.user.id).delete({reason:e}).then(()=>this)}ban(e){return this.guild.members.ban(this,e)}fetch(){return this.guild.members.fetch(this.id,!0)}toString(){return`<@${this.nickname?"!":""}${this.user.id}>`}toJSON(){return super.toJSON({guild:"guildID",user:"userID",displayName:!0,speaking:!1,lastMessage:!1,lastMessageID:!1,roles:!0})}send(){}}a.applyToClass(GuildMember),e.exports=GuildMember},function(e,t,i){"use strict";const{RangeError:s}=i(3);class BitField{constructor(e){this.bitfield=this.constructor.resolve(e)}any(e){return 0!=(this.bitfield&this.constructor.resolve(e))}equals(e){return this.bitfield===this.constructor.resolve(e)}has(e){return Array.isArray(e)?e.every(e=>this.has(e)):(e=this.constructor.resolve(e),(this.bitfield&e)===e)}missing(e,...t){return Array.isArray(e)||(e=new this.constructor(e).toArray(!1)),e.filter(e=>!this.has(e,...t))}freeze(){return Object.freeze(this)}add(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield|t):(this.bitfield|=t,this)}remove(...e){let t=0;for(const i of e)t|=this.constructor.resolve(i);return Object.isFrozen(this)?new this.constructor(this.bitfield&~t):(this.bitfield&=~t,this)}serialize(...e){const t={};for(const[i,s]of Object.entries(this.constructor.FLAGS))t[i]=this.has(s,...e);return t}toArray(...e){return Object.keys(this.constructor.FLAGS).filter(t=>this.has(t,...e))}toJSON(){return this.bitfield}valueOf(){return this.bitfield}*[Symbol.iterator](){yield*this.toArray()}static resolve(e=0){if("number"==typeof e&&e>=0)return e;if(e instanceof BitField)return e.bitfield;if(Array.isArray(e))return e.map(e=>this.resolve(e)).reduce((e,t)=>e|t,0);if("string"==typeof e&&void 0!==this.FLAGS[e])return this.FLAGS[e];throw new s("BITFIELD_INVALID")}}BitField.FLAGS={},e.exports=BitField},function(e,t,i){"use strict";const s=i(30),n=i(16),{WebhookTypes:r}=i(0),o=i(9),a=i(7);class Webhook{constructor(e,t){Object.defineProperty(this,"client",{value:e}),t&&this._patch(t)}_patch(e){this.name=e.name,Object.defineProperty(this,"token",{value:e.token||null,writable:!0,configurable:!0}),this.avatar=e.avatar,this.id=e.id,this.type=r[e.type],this.guildID=e.guild_id,this.channelID=e.channel_id,e.user?this.owner=this.client.users?this.client.users.cache.get(e.user.id):e.user:this.owner=null}async send(e,t){let i;if(e instanceof s)i=e.resolveData();else if(i=s.create(this,e,t).resolveData(),Array.isArray(i.data.content))return Promise.all(i.split().map(this.send.bind(this)));const{data:n,files:r}=await i.resolveFiles();return this.client.api.webhooks(this.id,this.token).post({data:n,files:r,query:{wait:!0},auth:!1}).then(e=>{const t=this.client.channels?this.client.channels.cache.get(e.channel_id):void 0;return t?t.messages.add(e,!1):e})}sendSlackMessage(e){return this.client.api.webhooks(this.id,this.token).slack.post({query:{wait:!0},auth:!1,data:e}).then(e=>"ok"===e.toString())}async edit({name:e=this.name,avatar:t,channel:i},s){t&&"string"==typeof t&&!t.startsWith("data:")&&(t=await o.resolveImage(t)),i&&(i=i instanceof n?i.id:i);const r=await this.client.api.webhooks(this.id,i?void 0:this.token).patch({data:{name:e,avatar:t,channel_id:i},reason:s});return this.name=r.name,this.avatar=r.avatar,this.channelID=r.channel_id,this}delete(e){return this.client.api.webhooks(this.id,this.token).delete({reason:e})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get url(){return this.client.options.http.api+this.client.api.webhooks(this.id,this.token)}avatarURL({format:e,size:t}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t):null}static applyToClass(e){for(const t of["send","sendSlackMessage","edit","delete","createdTimestamp","createdAt","url"])Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(Webhook.prototype,t))}}e.exports=Webhook},function(e,t,i){"use strict";const s=i(29),n=i(70),{ActivityTypes:r}=i(0),o=i(4);class Activity{constructor(e,t){Object.defineProperty(this,"presence",{value:e}),this.name=t.name,this.type=r[t.type],this.url=t.url||null,this.details=t.details||null,this.state=t.state||null,this.applicationID=t.application_id||null,this.timestamps=t.timestamps?{start:t.timestamps.start?new Date(Number(t.timestamps.start)):null,end:t.timestamps.end?new Date(Number(t.timestamps.end)):null}:null,this.party=t.party||null,this.assets=t.assets?new RichPresenceAssets(this,t.assets):null,this.syncID=t.sync_id,this.flags=new n(t.flags).freeze(),this.emoji=t.emoji?new s(e.client,t.emoji):null,this.createdTimestamp=new Date(t.created_at).getTime()}equals(e){return this===e||e&&this.name===e.name&&this.type===e.type&&this.url===e.url}get createdAt(){return new Date(this.createdTimestamp)}toString(){return this.name}_clone(){return Object.assign(Object.create(this),this)}}class RichPresenceAssets{constructor(e,t){Object.defineProperty(this,"activity",{value:e}),this.largeText=t.large_text||null,this.smallText=t.small_text||null,this.largeImage=t.large_image||null,this.smallImage=t.small_image||null}smallImageURL({format:e,size:t}={}){return this.smallImage?this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID,this.smallImage,{format:e,size:t}):null}largeImageURL({format:e,size:t}={}){return this.largeImage?/^spotify:/.test(this.largeImage)?`https://i.scdn.co/image/${this.largeImage.slice(8)}`:/^twitch:/.test(this.largeImage)?`https://static-cdn.jtvnw.net/previews-ttv/live_user_${this.largeImage.slice(7)}.png`:this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID,this.largeImage,{format:e,size:t}):null}}t.Presence=class Presence{constructor(e,t={}){Object.defineProperty(this,"client",{value:e}),this.userID=t.user.id,this.guild=t.guild||null,this.patch(t)}get user(){return this.client.users.cache.get(this.userID)||null}get member(){return this.guild.members.cache.get(this.userID)||null}patch(e){return this.status=e.status||this.status||"offline",e.activities?this.activities=e.activities.map(e=>new Activity(this,e)):e.activity||e.game?this.activities=[new Activity(this,e.game||e.activity)]:this.activities=[],this.clientStatus=e.client_status||null,this}_clone(){const e=Object.assign(Object.create(this),this);return this.activities&&(e.activities=this.activities.map(e=>e._clone())),e}equals(e){return this===e||e&&this.status===e.status&&this.activities.length===e.activities.length&&this.activities.every((t,i)=>t.equals(e.activities[i]))&&this.clientStatus.web===e.clientStatus.web&&this.clientStatus.mobile===e.clientStatus.mobile&&this.clientStatus.desktop===e.clientStatus.desktop}toJSON(){return o.flatten(this)}},t.Activity=Activity,t.RichPresenceAssets=RichPresenceAssets},function(e,t){var i,s,n=e.exports={};function r(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function a(e){if(i===setTimeout)return setTimeout(e,0);if((i===r||!i)&&setTimeout)return i=setTimeout,setTimeout(e,0);try{return i(e,0)}catch(t){try{return i.call(null,e,0)}catch(t){return i.call(this,e,0)}}}!function(){try{i="function"==typeof setTimeout?setTimeout:r}catch(e){i=r}try{s="function"==typeof clearTimeout?clearTimeout:o}catch(e){s=o}}();var c,l=[],h=!1,u=-1;function d(){h&&c&&(h=!1,c.length?l=c.concat(l):u=-1,l.length&&p())}function p(){if(!h){var e=a(d);h=!0;for(var t=l.length;t;){for(c=l,l=[];++u<t;)c&&c[u].run();u=-1,t=l.length}c=null,h=!1,function(e){if(s===clearTimeout)return clearTimeout(e);if((s===o||!s)&&clearTimeout)return s=clearTimeout,clearTimeout(e);try{s(e)}catch(t){try{return s.call(null,e)}catch(t){return s.call(this,e)}}}(e)}}function f(e,t){this.fun=e,this.array=t}function m(){}n.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var i=1;i<arguments.length;i++)t[i-1]=arguments[i];l.push(new f(e,t)),1!==l.length||h||a(p)},f.prototype.run=function(){this.fun.apply(null,this.array)},n.title="browser",n.browser=!0,n.env={},n.argv=[],n.version="",n.versions={},n.on=m,n.addListener=m,n.once=m,n.off=m,n.removeListener=m,n.removeAllListeners=m,n.emit=m,n.prependListener=m,n.prependOnceListener=m,n.listeners=function(e){return[]},n.binding=function(e){throw new Error("process.binding is not supported")},n.cwd=function(){return"/"},n.chdir=function(e){throw new Error("process.chdir is not supported")},n.umask=function(){return 0}},function(e,t,i){"use strict";var s,n="object"==typeof Reflect?Reflect:null,r=n&&"function"==typeof n.apply?n.apply:function(e,t,i){return Function.prototype.apply.call(e,t,i)};s=n&&"function"==typeof n.ownKeys?n.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var o=Number.isNaN||function(e){return e!=e};function a(){a.init.call(this)}e.exports=a,a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var c=10;function l(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function h(e){return void 0===e._maxListeners?a.defaultMaxListeners:e._maxListeners}function u(e,t,i,s){var n,r,o,a;if(l(i),void 0===(r=e._events)?(r=e._events=Object.create(null),e._eventsCount=0):(void 0!==r.newListener&&(e.emit("newListener",t,i.listener?i.listener:i),r=e._events),o=r[t]),void 0===o)o=r[t]=i,++e._eventsCount;else if("function"==typeof o?o=r[t]=s?[i,o]:[o,i]:s?o.unshift(i):o.push(i),(n=h(e))>0&&o.length>n&&!o.warned){o.warned=!0;var c=new Error("Possible EventEmitter memory leak detected. "+o.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");c.name="MaxListenersExceededWarning",c.emitter=e,c.type=t,c.count=o.length,a=c,console&&console.warn&&console.warn(a)}return e}function d(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function p(e,t,i){var s={fired:!1,wrapFn:void 0,target:e,type:t,listener:i},n=d.bind(s);return n.listener=i,s.wrapFn=n,n}function f(e,t,i){var s=e._events;if(void 0===s)return[];var n=s[t];return void 0===n?[]:"function"==typeof n?i?[n.listener||n]:[n]:i?function(e){for(var t=new Array(e.length),i=0;i<t.length;++i)t[i]=e[i].listener||e[i];return t}(n):g(n,n.length)}function m(e){var t=this._events;if(void 0!==t){var i=t[e];if("function"==typeof i)return 1;if(void 0!==i)return i.length}return 0}function g(e,t){for(var i=new Array(t),s=0;s<t;++s)i[s]=e[s];return i}Object.defineProperty(a,"defaultMaxListeners",{enumerable:!0,get:function(){return c},set:function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");c=e}}),a.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},a.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||o(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},a.prototype.getMaxListeners=function(){return h(this)},a.prototype.emit=function(e){for(var t=[],i=1;i<arguments.length;i++)t.push(arguments[i]);var s="error"===e,n=this._events;if(void 0!==n)s=s&&void 0===n.error;else if(!s)return!1;if(s){var o;if(t.length>0&&(o=t[0]),o instanceof Error)throw o;var a=new Error("Unhandled error."+(o?" ("+o.message+")":""));throw a.context=o,a}var c=n[e];if(void 0===c)return!1;if("function"==typeof c)r(c,this,t);else{var l=c.length,h=g(c,l);for(i=0;i<l;++i)r(h[i],this,t)}return!0},a.prototype.addListener=function(e,t){return u(this,e,t,!1)},a.prototype.on=a.prototype.addListener,a.prototype.prependListener=function(e,t){return u(this,e,t,!0)},a.prototype.once=function(e,t){return l(t),this.on(e,p(this,e,t)),this},a.prototype.prependOnceListener=function(e,t){return l(t),this.prependListener(e,p(this,e,t)),this},a.prototype.removeListener=function(e,t){var i,s,n,r,o;if(l(t),void 0===(s=this._events))return this;if(void 0===(i=s[e]))return this;if(i===t||i.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete s[e],s.removeListener&&this.emit("removeListener",e,i.listener||t));else if("function"!=typeof i){for(n=-1,r=i.length-1;r>=0;r--)if(i[r]===t||i[r].listener===t){o=i[r].listener,n=r;break}if(n<0)return this;0===n?i.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(i,n),1===i.length&&(s[e]=i[0]),void 0!==s.removeListener&&this.emit("removeListener",e,o||t)}return this},a.prototype.off=a.prototype.removeListener,a.prototype.removeAllListeners=function(e){var t,i,s;if(void 0===(i=this._events))return this;if(void 0===i.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==i[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete i[e]),this;if(0===arguments.length){var n,r=Object.keys(i);for(s=0;s<r.length;++s)"removeListener"!==(n=r[s])&&this.removeAllListeners(n);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=i[e]))this.removeListener(e,t);else if(void 0!==t)for(s=t.length-1;s>=0;s--)this.removeListener(e,t[s]);return this},a.prototype.listeners=function(e){return f(this,e,!0)},a.prototype.rawListeners=function(e){return f(this,e,!1)},a.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):m.call(e,t)},a.prototype.listenerCount=m,a.prototype.eventNames=function(){return this._eventsCount>0?s(this._events):[]}},function(e,t,i){"use strict";const s=i(5),{ChannelTypes:n}=i(0),r=i(7);e.exports=class Channel extends s{constructor(e,t){super(e);const i=Object.keys(n)[t.type];this.type=i?i.toLowerCase():"unknown",this.deleted=!1,t&&this._patch(t)}_patch(e){this.id=e.id}get createdTimestamp(){return r.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toString(){return`<#${this.id}>`}delete(){return this.client.api.channels(this.id).delete().then(()=>this)}fetch(){return this.client.channels.fetch(this.id,!0)}static create(e,t,s){const r=i(23);let o;if(t.guild_id||s){if(s=s||e.guilds.cache.get(t.guild_id)){switch(t.type){case n.TEXT:o=new(r.get("TextChannel"))(s,t);break;case n.VOICE:o=new(r.get("VoiceChannel"))(s,t);break;case n.CATEGORY:o=new(r.get("CategoryChannel"))(s,t);break;case n.NEWS:o=new(r.get("NewsChannel"))(s,t);break;case n.STORE:o=new(r.get("StoreChannel"))(s,t);break}o&&s.channels.cache.set(o.id,o)}}else if(t.recipients&&t.type!==n.GROUP||t.type===n.DM){o=new(r.get("DMChannel"))(e,t)}else if(t.type===n.GROUP){o=new(i(136))(e,t)}return o}toJSON(...e){return super.toJSON({createdTimestamp:!0},...e)}}},function(e,t,i){"use strict";const s=i(16),n=i(18),r=i(42),o=i(19),{Error:a,TypeError:c}=i(3),l=i(2),h=i(8),u=i(4);e.exports=class GuildChannel extends s{constructor(e,t){super(e.client,t),this.guild=e}_patch(e){if(super._patch(e),this.name=e.name,this.rawPosition=e.position,this.parentID=e.parent_id,this.permissionOverwrites=new l,e.permission_overwrites)for(const t of e.permission_overwrites)this.permissionOverwrites.set(t.id,new r(this,t))}get parent(){return this.guild.channels.cache.get(this.parentID)||null}get permissionsLocked(){return this.parent?this.permissionOverwrites.size===this.parent.permissionOverwrites.size&&this.permissionOverwrites.every((e,t)=>{const i=this.parent.permissionOverwrites.get(t);return void 0!==i&&i.deny.bitfield===e.deny.bitfield&&i.allow.bitfield===e.allow.bitfield}):null}get position(){const e=this.guild._sortedChannels(this);return e.array().indexOf(e.get(this.id))}permissionsFor(e){const t=this.guild.members.resolve(e);if(t)return this.memberPermissions(t);const i=this.guild.roles.resolve(e);return i?this.rolePermissions(i):null}overwritesFor(e,t=!1,i=null){if(t||(e=this.guild.members.resolve(e)),!e)return[];i=i||e.roles.cache;const s=[];let n,r;for(const t of this.permissionOverwrites.values())t.id===this.guild.id?r=t:i.has(t.id)?s.push(t):t.id===e.id&&(n=t);return{everyone:r,roles:s,member:n}}memberPermissions(e){if(e.id===this.guild.ownerID)return new h(h.ALL).freeze();const t=e.roles.cache,i=new h(t.map(e=>e.permissions));if(i.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const s=this.overwritesFor(e,!0,t);return i.remove(s.everyone?s.everyone.deny:0).add(s.everyone?s.everyone.allow:0).remove(s.roles.length>0?s.roles.map(e=>e.deny):0).add(s.roles.length>0?s.roles.map(e=>e.allow):0).remove(s.member?s.member.deny:0).add(s.member?s.member.allow:0).freeze()}rolePermissions(e){if(e.permissions.has(h.FLAGS.ADMINISTRATOR))return new h(h.ALL).freeze();const t=this.permissionOverwrites.get(this.guild.id),i=this.permissionOverwrites.get(e.id);return e.permissions.remove(t?t.deny:0).add(t?t.allow:0).remove(i?i.deny:0).add(i?i.allow:0).freeze()}overwritePermissions(e,t){return Array.isArray(e)||e instanceof l?this.edit({permissionOverwrites:e,reason:t}).then(()=>this):Promise.reject(new c("INVALID_TYPE","overwrites","Array or Collection of Permission Overwrites",!0))}updateOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role",!0));const s=this.permissionOverwrites.get(e.id);return s?s.update(t,i).then(()=>this):this.createOverwrite(e,t,i)}createOverwrite(e,t,i){if(!(e=this.guild.roles.resolve(e)||this.client.users.resolve(e)))return Promise.reject(new c("INVALID_TYPE","parameter","User nor a Role",!0));const s=e instanceof o?"role":"member",{allow:n,deny:a}=r.resolveOverwriteOptions(t);return this.client.api.channels(this.id).permissions[e.id].put({data:{id:e.id,type:s,allow:n.bitfield,deny:a.bitfield},reason:i}).then(()=>this)}lockPermissions(){if(!this.parent)return Promise.reject(new a("GUILD_CHANNEL_ORPHAN"));const e=this.parent.permissionOverwrites.map(e=>e.toJSON());return this.edit({permissionOverwrites:e})}get members(){const e=new l;for(const t of this.guild.members.cache.values())this.permissionsFor(t).has("VIEW_CHANNEL",!1)&&e.set(t.id,t);return e}async edit(e,t){void 0!==e.position&&await u.setPosition(this,e.position,!1,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,t).then(e=>{this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e})});const i=e.permissionOverwrites&&e.permissionOverwrites.map(e=>r.resolve(e,this.guild)),s=await this.client.api.channels(this.id).patch({data:{name:(e.name||this.name).trim(),topic:e.topic,nsfw:e.nsfw,bitrate:e.bitrate||this.bitrate,user_limit:void 0!==e.userLimit?e.userLimit:this.userLimit,parent_id:e.parentID,lock_permissions:e.lockPermissions,rate_limit_per_user:e.rateLimitPerUser,permission_overwrites:i},reason:t}),n=this._clone();return n._patch(s),n}setName(e,t){return this.edit({name:e},t)}setParent(e,{lockPermissions:t=!0,reason:i}={}){return this.edit({parentID:null!==e?e.hasOwnProperty("id")?e.id:e:null,lockPermissions:t},i)}setTopic(e,t){return this.edit({topic:e},t)}setPosition(e,{relative:t,reason:i}={}){return u.setPosition(this,e,t,this.guild._sortedChannels(this),this.client.api.guilds(this.guild.id).channels,i).then(e=>(this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.guild.id,channels:e}),this))}createInvite({temporary:e=!1,maxAge:t=86400,maxUses:i=0,unique:s,reason:r}={}){return this.client.api.channels(this.id).invites.post({data:{temporary:e,max_age:t,max_uses:i,unique:s},reason:r}).then(e=>new n(this.client,e))}async fetchInvites(){const e=await this.client.api.channels(this.id).invites.get(),t=new l;for(const i of e){const e=new n(this.client,i);t.set(e.code,e)}return t}clone(e={}){return u.mergeDefault({name:this.name,permissionOverwrites:this.permissionOverwrites,topic:this.topic,type:this.type,nsfw:this.nsfw,parent:this.parent,bitrate:this.bitrate,userLimit:this.userLimit,rateLimitPerUser:this.rateLimitPerUser,reason:null},e),this.guild.channels.create(e.name,e)}equals(e){let t=e&&this.id===e.id&&this.type===e.type&&this.topic===e.topic&&this.position===e.position&&this.name===e.name;return t&&(t=this.permissionOverwrites&&e.permissionOverwrites?this.permissionOverwrites.equals(e.permissionOverwrites):!this.permissionOverwrites&&!e.permissionOverwrites),t}get deletable(){return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get manageable(){if(this.client.user.id===this.guild.ownerID)return!0;if("voice"===this.type){if(!this.permissionsFor(this.client.user).has(h.FLAGS.CONNECT,!1))return!1}else if(!this.viewable)return!1;return this.permissionsFor(this.client.user).has(h.FLAGS.MANAGE_CHANNELS,!1)}get viewable(){if(this.client.user.id===this.guild.ownerID)return!0;const e=this.permissionsFor(this.client.user);return!!e&&e.has(h.FLAGS.VIEW_CHANNEL,!1)}delete(e){return this.client.api.channels(this.id).delete({reason:e}).then(()=>this)}}},function(e,t,i){"use strict";const s=i(5),{Endpoints:n}=i(0),r=i(8);e.exports=class Invite extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.guild=e.guild?this.client.guilds.add(e.guild,!1):null,this.code=e.code,this.presenceCount="approximate_presence_count"in e?e.approximate_presence_count:null,this.memberCount="approximate_member_count"in e?e.approximate_member_count:null,this.temporary="temporary"in e?e.temporary:null,this.maxAge="max_age"in e?e.max_age:null,this.uses="uses"in e?e.uses:null,this.maxUses="max_uses"in e?e.max_uses:null,this.inviter=e.inviter?this.client.users.add(e.inviter):null,this.targetUser=e.target_user?this.client.users.add(e.target_user):null,this.targetUserType="number"==typeof e.target_user_type?e.target_user_type:null,this.channel=this.client.channels.add(e.channel,this.guild,!1),this.createdTimestamp="created_at"in e?new Date(e.created_at).getTime():null}get createdAt(){return this.createdTimestamp?new Date(this.createdTimestamp):null}get deletable(){const e=this.guild;if(!e||!this.client.guilds.cache.has(e.id))return!1;if(!e.me)throw new Error("GUILD_UNCACHED_ME");return this.channel.permissionsFor(this.client.user).has(r.FLAGS.MANAGE_CHANNELS,!1)||e.me.permissions.has(r.FLAGS.MANAGE_GUILD)}get expiresTimestamp(){return this.createdTimestamp&&this.maxAge?this.createdTimestamp+1e3*this.maxAge:null}get expiresAt(){const{expiresTimestamp:e}=this;return e?new Date(e):null}get url(){return n.invite(this.client.options.http.invite,this.code)}delete(e){return this.client.api.invites[this.code].delete({reason:e}).then(()=>this)}toString(){return this.url}toJSON(){return super.toJSON({url:!0,expiresTimestamp:!0,presenceCount:!1,memberCount:!1,uses:!1,channel:"channelID",inviter:"inviterID",guild:"guildID"})}valueOf(){return this.code}}},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(3),o=i(8),a=i(7),c=i(4);e.exports=class Role extends s{constructor(e,t,i){super(e),this.guild=i,t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.color=e.color,this.hoist=e.hoist,this.rawPosition=e.position,this.permissions=new o(e.permissions).freeze(),this.managed=e.managed,this.mentionable=e.mentionable,this.deleted=!1}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get hexColor(){return`#${this.color.toString(16).padStart(6,"0")}`}get members(){return this.guild.members.cache.filter(e=>e.roles.cache.has(this.id))}get editable(){if(this.managed)return!1;const e=this.guild.member(this.client.user);return!!e.permissions.has(o.FLAGS.MANAGE_ROLES)&&e.roles.highest.comparePositionTo(this)>0}get position(){const e=this.guild._sortedRoles();return e.array().indexOf(e.get(this.id))}comparePositionTo(e){if(!(e=this.guild.roles.resolve(e)))throw new r("INVALID_TYPE","role","Role nor a Snowflake");return this.constructor.comparePositions(this,e)}async edit(e,t){return void 0!==e.permissions?e.permissions=o.resolve(e.permissions):e.permissions=this.permissions.bitfield,void 0!==e.position&&await c.setPosition(this,e.position,!1,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,t).then(e=>{this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e})}),this.client.api.guilds[this.guild.id].roles[this.id].patch({data:{name:e.name||this.name,color:null!==e.color?c.resolveColor(e.color||this.color):null,hoist:void 0!==e.hoist?e.hoist:this.hoist,permissions:e.permissions,mentionable:void 0!==e.mentionable?e.mentionable:this.mentionable},reason:t}).then(e=>{const t=this._clone();return t._patch(e),t})}permissionsIn(e){if(!(e=this.guild.channels.resolve(e)))throw new n("GUILD_CHANNEL_RESOLVE");return e.rolePermissions(this)}setName(e,t){return this.edit({name:e},t)}setColor(e,t){return this.edit({color:e},t)}setHoist(e,t){return this.edit({hoist:e},t)}setPermissions(e,t){return this.edit({permissions:e},t)}setMentionable(e,t){return this.edit({mentionable:e},t)}setPosition(e,{relative:t,reason:i}={}){return c.setPosition(this,e,t,this.guild._sortedRoles(),this.client.api.guilds(this.guild.id).roles,i).then(e=>(this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.guild.id,roles:e}),this))}delete(e){return this.client.api.guilds[this.guild.id].roles[this.id].delete({reason:e}).then(()=>(this.client.actions.GuildRoleDelete.handle({guild_id:this.guild.id,role_id:this.id}),this))}equals(e){return e&&this.id===e.id&&this.name===e.name&&this.color===e.color&&this.hoist===e.hoist&&this.position===e.position&&this.permissions.bitfield===e.permissions.bitfield&&this.managed===e.managed}toString(){return this.id===this.guild.id?"@everyone":`<@&${this.id}>`}toJSON(){return super.toJSON({createdTimestamp:!0})}static comparePositions(e,t){return e.position===t.position?t.id-e.id:e.position-t.position}}},function(e,t,i){"use strict";var s=i(31),n=Object.keys||function(e){var t=[];for(var i in e)t.push(i);return t};e.exports=u;var r=Object.create(i(25));r.inherits=i(22);var o=i(64),a=i(46);r.inherits(u,o);for(var c=n(a.prototype),l=0;l<c.length;l++){var h=c[l];u.prototype[h]||(u.prototype[h]=a.prototype[h])}function u(e){if(!(this instanceof u))return new u(e);o.call(this,e),a.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",d)}function d(){this.allowHalfOpen||this._writableState.ended||s.nextTick(p,this)}function p(e){e.end()}Object.defineProperty(u.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(u.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),u.prototype._destroy=function(e,t){this.push(null),this.end(),s.nextTick(t,e)}},function(e,t){var i;i=function(){return this}();try{i=i||new Function("return this")()}catch(e){"object"==typeof window&&(i=window)}e.exports=i},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var i=function(){};i.prototype=t.prototype,e.prototype=new i,e.prototype.constructor=e}}},function(e,t,i){"use strict";const s={GuildEmoji:i(24),DMChannel:i(39),TextChannel:i(41),VoiceChannel:i(79),CategoryChannel:i(80),NewsChannel:i(81),StoreChannel:i(82),GuildMember:i(10),Guild:i(53),Message:i(28),MessageReaction:i(51),Presence:i(13).Presence,ClientPresence:i(89),VoiceState:i(27),Role:i(19),User:i(26)};e.exports=class Structures{constructor(){throw new Error(`The ${this.constructor.name} class may not be instantiated.`)}static get(e){if("string"==typeof e)return s[e];throw new TypeError(`"structure" argument must be a string (received ${typeof e})`)}static extend(e,t){if(!s[e])throw new RangeError(`"${e}" is not a valid extensible structure.`);if("function"!=typeof t){throw new TypeError(`"extender" argument must be a function that returns the extended structure class/prototype ${`(received ${typeof t})`}.`)}const i=t(s[e]);if("function"!=typeof i){throw new TypeError(`The extender function must return the extended structure class/prototype ${`(received ${typeof i})`}.`)}if(!(i.prototype instanceof s[e])){const t=Object.getPrototypeOf(i),n=`${i.name||"unnamed"}${t.name?` extends ${t.name}`:""}`;throw new Error("The class/prototype returned from the extender function must extend the existing structure class/prototype"+` (received function ${n}; expected extension of ${s[e].name}).`)}return s[e]=i,i}}},function(e,t,i){"use strict";const s=i(40),{Error:n}=i(3),r=i(63),o=i(8);class GuildEmoji extends s{_clone(){const e=super._clone();return e._roles=this._roles.slice(),e}get deletable(){if(!this.guild.me)throw new n("GUILD_UNCACHED_ME");return!this.managed&&this.guild.me.hasPermission(o.FLAGS.MANAGE_EMOJIS)}get roles(){return new r(this)}fetchAuthor(){return this.managed?Promise.reject(new n("EMOJI_MANAGED")):this.guild.me?this.guild.me.permissions.has(o.FLAGS.MANAGE_EMOJIS)?this.client.api.guilds(this.guild.id).emojis(this.id).get().then(e=>this.client.users.add(e.user)):Promise.reject(new n("MISSING_MANAGE_EMOJIS_PERMISSION",this.guild)):Promise.reject(new n("GUILD_UNCACHED_ME"))}edit(e,t){const i=e.roles?e.roles.map(e=>e.id||e):void 0;return this.client.api.guilds(this.guild.id).emojis(this.id).patch({data:{name:e.name,roles:i},reason:t}).then(e=>{const t=this._clone();return t._patch(e),t})}setName(e,t){return this.edit({name:e},t)}delete(e){return this.client.api.guilds(this.guild.id).emojis(this.id).delete({reason:e}).then(()=>this)}equals(e){return e instanceof GuildEmoji?e.id===this.id&&e.name===this.name&&e.managed===this.managed&&e.requiresColons===this.requiresColons&&e.roles.cache.size===this.roles.cache.size&&e.roles.cache.every(e=>this.roles.cache.has(e.id)):e.id===this.id&&e.name===this.name&&e.roles.length===this.roles.cache.size&&e.roles.every(e=>this.roles.cache.has(e))}}e.exports=GuildEmoji},function(e,t){function i(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===i(e)},t.isBoolean=function(e){return"boolean"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return"[object RegExp]"===i(e)},t.isObject=function(e){return"object"==typeof e&&null!==e},t.isDate=function(e){return"[object Date]"===i(e)},t.isError=function(e){return"[object Error]"===i(e)||e instanceof Error},t.isFunction=function(e){return"function"==typeof e},t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=Buffer.isBuffer},function(e,t,i){"use strict";const s=i(5),{Presence:n}=i(13),r=i(33),{Error:o}=i(3),a=i(7),c=i(78);class User extends s{constructor(e,t){super(e),this.id=t.id,this.bot=Boolean(t.bot),this._patch(t)}_patch(e){e.username&&(this.username=e.username),e.discriminator&&(this.discriminator=e.discriminator),void 0!==e.avatar&&(this.avatar=e.avatar),void 0!==e.bot&&(this.bot=Boolean(e.bot)),void 0!==e.system&&(this.system=Boolean(e.system)),e.locale&&(this.locale=e.locale),void 0!==e.public_flags&&(this.flags=new c(e.public_flags)),this.lastMessageID=null,this.lastMessageChannelID=null}get partial(){return"string"!=typeof this.username}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get lastMessage(){const e=this.client.channels.cache.get(this.lastMessageChannelID);return e&&e.messages.cache.get(this.lastMessageID)||null}get presence(){for(const e of this.client.guilds.cache.values())if(e.presences.cache.has(this.id))return e.presences.cache.get(this.id);return new n(this.client,{user:{id:this.id}})}avatarURL({format:e,size:t,dynamic:i}={}){return this.avatar?this.client.rest.cdn.Avatar(this.id,this.avatar,e,t,i):null}get defaultAvatarURL(){return this.client.rest.cdn.DefaultAvatar(this.discriminator%5)}displayAvatarURL(e){return this.avatarURL(e)||this.defaultAvatarURL}get tag(){return"string"==typeof this.username?`${this.username}#${this.discriminator}`:null}typingIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)}typingSinceIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?new Date(e._typing.get(this.id).since):null}typingDurationIn(e){return(e=this.client.channels.resolve(e))._typing.has(this.id)?e._typing.get(this.id).elapsedTime:-1}get dmChannel(){return this.client.channels.cache.find(e=>"dm"===e.type&&e.recipient.id===this.id)||null}async createDM(){const{dmChannel:e}=this;if(e&&!e.partial)return e;const t=await this.client.api.users(this.client.user.id).channels.post({data:{recipient_id:this.id}});return this.client.actions.ChannelCreate.handle(t).channel}async deleteDM(){const{dmChannel:e}=this;if(!e)throw new o("USER_NO_DMCHANNEL");const t=await this.client.api.channels(e.id).delete();return this.client.actions.ChannelDelete.handle(t).channel}equals(e){return e&&this.id===e.id&&this.username===e.username&&this.discriminator===e.discriminator&&this.avatar===e.avatar}async fetchFlags(){if(this.flags)return this.flags;const e=await this.client.api.users(this.id).get();return this._patch(e),this.flags}fetch(){return this.client.users.fetch(this.id,!0)}toString(){return`<@${this.id}>`}toJSON(...e){const t=super.toJSON({createdTimestamp:!0,defaultAvatarURL:!0,tag:!0,lastMessage:!1,lastMessageID:!1},...e);return t.avatarURL=this.avatarURL(),t.displayAvatarURL=this.displayAvatarURL(),t}send(){}}r.applyToClass(User),e.exports=User},function(e,t,i){"use strict";const s=i(5),{Error:n,TypeError:r}=i(3),{browser:o}=i(0);e.exports=class VoiceState extends s{constructor(e,t){super(e.client),this.guild=e,this.id=t.user_id,this._patch(t)}_patch(e){return this.serverDeaf=e.deaf,this.serverMute=e.mute,this.selfDeaf=e.self_deaf,this.selfMute=e.self_mute,this.sessionID=e.session_id,this.streaming=e.self_stream||!1,this.channelID=e.channel_id,this}get member(){return this.guild.members.cache.get(this.id)||null}get channel(){return this.guild.channels.cache.get(this.channelID)||null}get connection(){return o||this.id!==this.client.user.id?null:this.client.voice.connections.get(this.guild.id)||null}get deaf(){return this.serverDeaf||this.selfDeaf}get mute(){return this.serverMute||this.selfMute}get speaking(){return this.channel&&this.channel.connection?Boolean(this.channel.connection._speaking.get(this.id)):null}setMute(e,t){return this.member?this.member.edit({mute:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}setDeaf(e,t){return this.member?this.member.edit({deaf:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}kick(e){return this.setChannel(null,e)}setChannel(e,t){return this.member?this.member.edit({channel:e},t):Promise.reject(new n("VOICE_STATE_UNCACHED_MEMBER"))}async setSelfMute(e){if(this.id!==this.client.user.id)throw new n("VOICE_STATE_NOT_OWN");if("boolean"!=typeof e)throw new r("VOICE_STATE_INVALID_TYPE","mute");return!!this.connection&&(this.selfMute=e,await this.connection.sendVoiceStateUpdate(),!0)}async setSelfDeaf(e){return this.id!==this.client.user.id?new n("VOICE_STATE_NOT_OWN"):"boolean"!=typeof e?new r("VOICE_STATE_INVALID_TYPE","deaf"):!!this.connection&&(this.selfDeaf=e,await this.connection.sendVoiceStateUpdate(),!0)}toJSON(){return super.toJSON({id:!0,serverDeaf:!0,serverMute:!0,selfDeaf:!0,selfMute:!0,sessionID:!0,channelID:"channel"})}}},function(e,t,i){"use strict";const s=i(30),n=i(5),r=i(50),o=i(43),a=i(44),c=i(75),l=i(76),{Error:h,TypeError:u}=i(3),d=i(132),p=i(2),{MessageTypes:f}=i(0),m=i(47),g=i(8),E=i(4);e.exports=class Message extends n{constructor(e,t,i){super(e),this.channel=i,this.deleted=!1,t&&this._patch(t)}_patch(e){if(this.id=e.id,this.type=f[e.type],this.content=e.content,this.author=e.author?this.client.users.add(e.author,!e.webhook_id):null,this.pinned=e.pinned,this.tts=e.tts,this.nonce=e.nonce,this.system=0!==e.type,this.embeds=(e.embeds||[]).map(e=>new a(e,!0)),this.attachments=new p,e.attachments)for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t));if(this.createdTimestamp=new Date(e.timestamp).getTime(),this.editedTimestamp=e.edited_timestamp?new Date(e.edited_timestamp).getTime():null,this.reactions=new d(this),e.reactions&&e.reactions.length>0)for(const t of e.reactions)this.reactions.add(t);this.mentions=new c(this,e.mentions,e.mention_roles,e.mention_everyone,e.mention_channels),this.webhookID=e.webhook_id||null,this.application=e.application?new r(this.client,e.application):null,this.activity=e.activity?{partyID:e.activity.party_id,type:e.activity.type}:null,this._edits=[],this.member&&e.member?this.member._patch(e.member):e.member&&this.guild&&this.author&&this.guild.members.add(Object.assign(e.member,{user:this.author})),this.flags=new m(e.flags).freeze(),this.reference=e.message_reference?{channelID:e.message_reference.channel_id,guildID:e.message_reference.guild_id,messageID:e.message_reference.message_id}:null}get partial(){return"string"!=typeof this.content||!this.author}patch(e){const t=this._clone();if(this._edits.unshift(t),"edited_timestamp"in e&&(this.editedTimestamp=new Date(e.edited_timestamp).getTime()),"content"in e&&(this.content=e.content),"pinned"in e&&(this.pinned=e.pinned),"tts"in e&&(this.tts=e.tts),this.embeds="embeds"in e?e.embeds.map(e=>new a(e,!0)):this.embeds.slice(),"attachments"in e){this.attachments=new p;for(const t of e.attachments)this.attachments.set(t.id,new o(t.url,t.filename,t))}else this.attachments=new p(this.attachments);this.mentions=new c(this,"mentions"in e?e.mentions:this.mentions.users,"mention_roles"in e?e.mention_roles:this.mentions.roles,"mention_everyone"in e?e.mention_everyone:this.mentions.everyone,"mention_channels"in e?e.mention_channels:this.mentions.crosspostedChannels),this.flags=new m("flags"in e?e.flags:0).freeze()}get member(){return this.guild&&this.guild.member(this.author)||null}get createdAt(){return new Date(this.createdTimestamp)}get editedAt(){return this.editedTimestamp?new Date(this.editedTimestamp):null}get guild(){return this.channel.guild||null}get url(){return`https://discordapp.com/channels/${this.guild?this.guild.id:"@me"}/${this.channel.id}/${this.id}`}get cleanContent(){return null!=this.content?E.cleanContent(this.content,this):null}createReactionCollector(e,t={}){return new l(this,e,t)}awaitReactions(e,t={}){return new Promise((i,s)=>{this.createReactionCollector(e,t).once("end",(e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)})})}get edits(){const e=this._edits.slice();return e.unshift(this),e}get editable(){return this.author.id===this.client.user.id}get deletable(){return!this.deleted&&(this.author.id===this.client.user.id||this.guild&&this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}get pinnable(){return"DEFAULT"===this.type&&(!this.guild||this.channel.permissionsFor(this.client.user).has(g.FLAGS.MANAGE_MESSAGES,!1))}edit(e,t){const{data:i}=e instanceof s?e.resolveData():s.create(this,e,t).resolveData();return this.client.api.channels[this.channel.id].messages[this.id].patch({data:i}).then(e=>{const t=this._clone();return t._patch(e),t})}pin(){return this.client.api.channels(this.channel.id).pins(this.id).put().then(()=>this)}unpin(){return this.client.api.channels(this.channel.id).pins(this.id).delete().then(()=>this)}react(e){if(!(e=this.client.emojis.resolveIdentifier(e)))throw new u("EMOJI_TYPE");return this.client.api.channels(this.channel.id).messages(this.id).reactions(e,"@me").put().then(()=>this.client.actions.MessageReactionAdd.handle({user:this.client.user,channel:this.channel,message:this,emoji:E.parseEmoji(e)}).reaction)}delete(e={}){if("object"!=typeof e)throw new u("INVALID_TYPE","options","object",!0);const{timeout:t=0,reason:i}=e;return t<=0?this.channel.messages.delete(this.id,i).then(()=>this):new Promise(e=>{this.client.setTimeout(()=>{e(this.delete({reason:i}))},t)})}reply(e,t){return this.channel.send(e instanceof s?e:s.transformOptions(e,t,{reply:this.member||this.author}))}fetch(){return this.channel.messages.fetch(this.id,!0)}fetchWebhook(){return this.webhookID?this.client.fetchWebhook(this.webhookID):Promise.reject(new h("WEBHOOK_MESSAGE"))}suppressEmbeds(e=!0){const t=new m(this.flags.bitfield);return e?t.add(m.FLAGS.SUPPRESS_EMBEDS):t.remove(m.FLAGS.SUPPRESS_EMBEDS),this.edit({flags:t})}equals(e,t){if(!e)return!1;if(!e.author&&!e.attachments)return this.id===e.id&&this.embeds.length===e.embeds.length;let i=this.id===e.id&&this.author.id===e.author.id&&this.content===e.content&&this.tts===e.tts&&this.nonce===e.nonce&&this.embeds.length===e.embeds.length&&this.attachments.length===e.attachments.length;return i&&t&&(i=this.mentions.everyone===e.mentions.everyone&&this.createdTimestamp===new Date(t.timestamp).getTime()&&this.editedTimestamp===new Date(t.edited_timestamp).getTime()),i}toString(){return this.content}toJSON(){return super.toJSON({channel:"channelID",author:"authorID",application:"applicationID",guild:"guildID",cleanContent:!0,member:!1,reactions:!1})}}},function(e,t,i){"use strict";const s=i(5),n=i(7);e.exports=class Emoji extends s{constructor(e,t){super(e),this.animated=t.animated,this.name=t.name,this.id=t.id,this.deleted=!1}get identifier(){return this.id?`${this.animated?"a:":""}${this.name}:${this.id}`:encodeURIComponent(this.name)}get url(){return this.id?this.client.rest.cdn.Emoji(this.id,this.animated?"gif":"png"):null}get createdTimestamp(){return this.id?n.deconstruct(this.id).timestamp:null}get createdAt(){return this.id?new Date(this.createdTimestamp):null}toString(){return this.id?`<${this.animated?"a":""}:${this.name}:${this.id}>`:this.name}toJSON(){return super.toJSON({guild:"guildID",createdTimestamp:!0,url:!0,identifier:!0})}}},function(e,t,i){"use strict";const s=i(43),n=i(44),{RangeError:r}=i(3),{browser:o}=i(0),a=i(9),c=i(47),l=i(4);class APIMessage{constructor(e,t){this.target=e,this.options=t,this.data=null,this.files=null}get isWebhook(){const e=i(12),t=i(48);return this.target instanceof e||this.target instanceof t}get isUser(){const e=i(26),t=i(10);return this.target instanceof e||this.target instanceof t}get isMessage(){const e=i(28);return this.target instanceof e}makeContent(){const e=i(10);let t;null===this.options.content?t="":void 0!==this.options.content&&(t=l.resolveString(this.options.content));const s=void 0===this.options.disableMentions?this.target.client.options.disableMentions:this.options.disableMentions;"all"===s?t=l.removeMentions(t||""):"everyone"===s&&(t=(t||"").replace(/@([^<>@ ]*)/gmus,(e,t)=>t.match(/^[&!]?\d+$/)?`@${t}`:`@​${t}`));const n=void 0!==this.options.split&&!1!==this.options.split,r=void 0!==this.options.code&&!1!==this.options.code,o=n?{...this.options.split}:void 0;let a="";if(this.options.reply&&!this.isUser&&"dm"!==this.target.type){const t=this.target.client.users.resolveID(this.options.reply);a=`<@${this.options.reply instanceof e&&this.options.reply.nickname?"!":""}${t}>, `,n&&(o.prepend=`${a}${o.prepend||""}`)}if(t||a){if(r){const e="string"==typeof this.options.code?this.options.code:"";t=`${a}\`\`\`${e}\n${l.cleanCodeBlockContent(t||"")}\n\`\`\``,n&&(o.prepend=`${o.prepend||""}\`\`\`${e}\n`,o.append=`\n\`\`\`${o.append||""}`)}else a&&(t=`${a}${t||""}`);n&&(t=l.splitMessage(t||"",o))}return t}resolveData(){if(this.data)return this;const e=this.makeContent(),t=Boolean(this.options.tts);let i;if(void 0!==this.options.nonce&&(i=parseInt(this.options.nonce),isNaN(i)||i<0))throw new r("MESSAGE_NONCE_TYPE");const s=[];this.isWebhook?this.options.embeds&&s.push(...this.options.embeds):this.options.embed&&s.push(this.options.embed);const o=s.map(e=>new n(e).toJSON());let a,l,h;this.isWebhook&&(a=this.options.username||this.target.name,this.options.avatarURL&&(l=this.options.avatarURL)),this.isMessage&&(h=null!=this.options.flags?new c(this.options.flags).bitfield:this.target.flags.bitfield);const u=void 0===this.options.allowedMentions?this.target.client.options.allowedMentions:this.options.allowedMentions;return this.data={content:e,tts:t,nonce:i,embed:null===this.options.embed?null:o[0],embeds:o,username:a,avatar_url:l,allowed_mentions:u,flags:h},this}async resolveFiles(){if(this.files)return this;const e=[];this.isWebhook?this.options.embeds&&e.push(...this.options.embeds):this.options.embed&&e.push(this.options.embed);const t=[];this.options.files&&t.push(...this.options.files);for(const i of e)i.files&&t.push(...i.files);return this.files=await Promise.all(t.map(e=>this.constructor.resolveFile(e))),this}split(){if(this.data||this.resolveData(),!Array.isArray(this.data.content))return[this];const e=[];for(let t=0;t<this.data.content.length;t++){let i,s;t===this.data.content.length-1?(i={...this.data,content:this.data.content[t]},s={...this.options,content:this.data.content[t]}):(i={content:this.data.content[t],tts:this.data.tts},s={content:this.data.content[t],tts:this.data.tts});const n=new APIMessage(this.target,s);n.data=i,e.push(n)}return e}static async resolveFile(e){let t,i;const s=e=>"string"==typeof e?l.basename(e):e.path?l.basename(e.path):"file.jpg";return"string"==typeof e||e instanceof(o?ArrayBuffer:Buffer)||"function"==typeof e.pipe?(t=e,i=s(t)):(t=e.attachment,i=e.name||s(t)),{attachment:t,name:i,file:await a.resolveFile(t)}}static partitionMessageAdditions(e){const t=[],i=[];for(const r of e)r instanceof n?t.push(r):r instanceof s&&i.push(r);return[t,i]}static transformOptions(e,t,i={},r=!1){if(t||"object"!=typeof e||Array.isArray(e)||(t=e,e=void 0),t){if(t instanceof n)return r?{content:e,embeds:[t],...i}:{content:e,embed:t,...i};if(t instanceof s)return{content:e,files:[t],...i}}else t={};if(Array.isArray(t)){const[s,n]=this.partitionMessageAdditions(t);return r?{content:e,embeds:s,files:n,...i}:{content:e,embed:s[0],files:n,...i}}if(Array.isArray(e)){const[t,s]=this.partitionMessageAdditions(e);if(t.length||s.length)return r?{embeds:t,files:s,...i}:{embed:t[0],files:s,...i}}return{content:e,...t,...i}}static create(e,t,s,n={}){const r=i(12),o=i(48),a=e instanceof r||e instanceof o;return new this(e,this.transformOptions(t,s,n,a))}}e.exports=APIMessage},function(e,t,i){"use strict";(function(t){void 0===t||!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function(e,i,s,n){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var r,o,a=arguments.length;switch(a){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick((function(){e.call(null,i)}));case 3:return t.nextTick((function(){e.call(null,i,s)}));case 4:return t.nextTick((function(){e.call(null,i,s,n)}));default:for(r=new Array(a-1),o=0;o<r.length;)r[o++]=arguments[o];return t.nextTick((function(){e.apply(null,r)}))}}}:e.exports=t}).call(this,i(14))},function(e,t,i){var s=i(120),n=s.Buffer;function r(e,t){for(var i in e)t[i]=e[i]}function o(e,t,i){return n(e,t,i)}n.from&&n.alloc&&n.allocUnsafe&&n.allocUnsafeSlow?e.exports=s:(r(s,t),t.Buffer=o),r(n,o),o.from=function(e,t,i){if("number"==typeof e)throw new TypeError("Argument must not be a number");return n(e,t,i)},o.alloc=function(e,t,i){if("number"!=typeof e)throw new TypeError("Argument must be a number");var s=n(e);return void 0!==t?"string"==typeof i?s.fill(t,i):s.fill(t):s.fill(0),s},o.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return n(e)},o.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return s.SlowBuffer(e)}},function(e,t,i){"use strict";const s=i(71),n=i(30),r=i(7),o=i(2),{RangeError:a,TypeError:c}=i(3);class TextBasedChannel{constructor(){this.messages=new l(this),this.lastMessageID=null,this.lastPinTimestamp=null}get lastMessage(){return this.messages.cache.get(this.lastMessageID)||null}get lastPinAt(){return this.lastPinTimestamp?new Date(this.lastPinTimestamp):null}async send(e,t){const s=i(26),r=i(10);if(this instanceof s||this instanceof r)return this.createDM().then(i=>i.send(e,t));let o;if(e instanceof n)o=e.resolveData();else if(o=n.create(this,e,t).resolveData(),Array.isArray(o.data.content))return Promise.all(o.split().map(this.send.bind(this)));const{data:a,files:c}=await o.resolveFiles();return this.client.api.channels[this.id].messages.post({data:a,files:c}).then(e=>this.client.actions.MessageCreate.handle(e).message)}startTyping(e){if(void 0!==e&&e<1)throw new a("TYPING_COUNT");if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);return t.count=e||t.count+1,t.promise}const t={};return t.promise=new Promise((i,s)=>{const n=this.client.api.channels[this.id].typing;Object.assign(t,{count:e||1,interval:this.client.setInterval(()=>{n.post().catch(e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)})},9e3),resolve:i}),n.post().catch(e=>{this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),s(e)}),this.client.user._typing.set(this.id,t)}),t.promise}stopTyping(e=!1){if(this.client.user._typing.has(this.id)){const t=this.client.user._typing.get(this.id);t.count--,(t.count<=0||e)&&(this.client.clearInterval(t.interval),this.client.user._typing.delete(this.id),t.resolve())}}get typing(){return this.client.user._typing.has(this.id)}get typingCount(){return this.client.user._typing.has(this.id)?this.client.user._typing.get(this.id).count:0}createMessageCollector(e,t={}){return new s(this,e,t)}awaitMessages(e,t={}){return new Promise((i,s)=>{this.createMessageCollector(e,t).once("end",(e,n)=>{t.errors&&t.errors.includes(n)?s(e):i(e)})})}async bulkDelete(e,t=!1){if(Array.isArray(e)||e instanceof o){let i=e instanceof o?e.keyArray():e.map(e=>e.id||e);if(t&&(i=i.filter(e=>Date.now()-r.deconstruct(e).date.getTime()<12096e5)),0===i.length)return new o;if(1===i.length){await this.client.api.channels(this.id).messages(i[0]).delete();const e=this.client.actions.MessageDelete.getMessage({message_id:i[0]},this);return e?new o([[e.id,e]]):new o}return await this.client.api.channels[this.id].messages["bulk-delete"].post({data:{messages:i}}),i.reduce((e,t)=>e.set(t,this.client.actions.MessageDeleteBulk.getMessage({message_id:t},this)),new o)}if(!isNaN(e)){const i=await this.messages.fetch({limit:e});return this.bulkDelete(i,t)}throw new c("MESSAGE_BULK_DELETE_TYPE")}static applyToClass(e,t=!1,i=[]){const s=["send"];t&&s.push("lastMessage","lastPinAt","bulkDelete","startTyping","stopTyping","typing","typingCount","createMessageCollector","awaitMessages");for(const t of s)i.includes(t)||Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(TextBasedChannel.prototype,t))}}e.exports=TextBasedChannel;const l=i(34)},function(e,t,i){"use strict";const s=i(6),n=i(28),r=i(2),o=i(133);e.exports=class MessageManager extends s{constructor(e,t){super(e.client,t,n,o,e.client.options.messageCacheMaxSize),this.channel=e}add(e,t){return super.add(e,t,{extras:[this.channel]})}fetch(e,t=!0){return"string"==typeof e?this._fetchId(e,t):this._fetchMany(e,t)}fetchPinned(e=!0){return this.client.api.channels[this.channel.id].pins.get().then(t=>{const i=new r;for(const s of t)i.set(s.id,this.add(s,e));return i})}async delete(e,t){(e=this.resolveID(e))&&await this.client.api.channels(this.channel.id).messages(e).delete({reason:t})}async _fetchId(e,t){const i=this.cache.get(e);if(i&&!i.partial)return i;const s=await this.client.api.channels[this.channel.id].messages[e].get();return this.add(s,t)}async _fetchMany(e={},t){const i=await this.client.api.channels[this.channel.id].messages.get({query:e}),s=new r;for(const e of i)s.set(e.id,this.add(e,t));return s}}},function(e,t){},function(e,t,i){"use strict";var s=function(){if("undefined"!=typeof self)return self;if("undefined"!=typeof window)return window;if(void 0!==s)return s;throw new Error("unable to locate global object")}();e.exports=t=s.fetch,t.default=s.fetch.bind(s),t.Headers=s.Headers,t.Request=s.Request,t.Response=s.Response},function(e,t,i){"use strict";(function(t,s){i(60);const n=i(15),r=i(100),{DefaultOptions:o}=i(0),a=i(4);e.exports=class BaseClient extends n{constructor(e={}){super(),this._timeouts=new Set,this._intervals=new Set,this._immediates=new Set,this.options=a.mergeDefault(o,e),this.rest=new r(this,e._tokenType)}get api(){return this.rest.api}destroy(){for(const e of this._timeouts)this.clearTimeout(e);for(const e of this._intervals)this.clearInterval(e);for(const e of this._immediates)this.clearImmediate(e);this._timeouts.clear(),this._intervals.clear(),this._immediates.clear()}setTimeout(e,t,...i){const s=setTimeout(()=>{e(...i),this._timeouts.delete(s)},t);return this._timeouts.add(s),s}clearTimeout(e){clearTimeout(e),this._timeouts.delete(e)}setInterval(e,t,...i){const s=setInterval(e,t,...i);return this._intervals.add(s),s}clearInterval(e){clearInterval(e),this._intervals.delete(e)}setImmediate(e,...i){const s=t(e,...i);return this._immediates.add(s),s}clearImmediate(e){s(e),this._immediates.delete(e)}toJSON(...e){return a.flatten(this,{domain:!1},...e)}}}).call(this,i(38).setImmediate,i(38).clearImmediate)},function(e,t,i){(function(e){var s=void 0!==e&&e||"undefined"!=typeof self&&self||window,n=Function.prototype.apply;function r(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new r(n.call(setTimeout,s,arguments),clearTimeout)},t.setInterval=function(){return new r(n.call(setInterval,s,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},r.prototype.unref=r.prototype.ref=function(){},r.prototype.close=function(){this._clearFn.call(s,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout((function(){e._onTimeout&&e._onTimeout()}),t))},i(60),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,i(21))},function(e,t,i){"use strict";const s=i(16),n=i(33),r=i(34);class DMChannel extends s{constructor(e,t){super(e,t),this.type="dm",this.messages=new r(this),this._typing=new Map}_patch(e){super._patch(e),e.recipients&&(this.recipient=this.client.users.add(e.recipients[0])),this.lastMessageID=e.last_message_id,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null}get partial(){return void 0===this.lastMessageID}fetch(){return this.recipient.createDM()}toString(){return this.recipient.toString()}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}}n.applyToClass(DMChannel,!0,["bulkDelete"]),e.exports=DMChannel},function(e,t,i){"use strict";const s=i(29);e.exports=class BaseGuildEmoji extends s{constructor(e,t,i){super(e,t),this.guild=i,Object.defineProperty(this,"_roles",{value:[],writable:!0}),this._patch(t)}_patch(e){e.name&&(this.name=e.name),void 0!==e.require_colons&&(this.requiresColons=e.require_colons),void 0!==e.managed&&(this.managed=e.managed),void 0!==e.available&&(this.available=e.available),e.roles&&(this._roles=e.roles)}}},function(e,t,i){"use strict";const s=i(17),n=i(12),r=i(33),o=i(34),a=i(2),c=i(9);class TextChannel extends s{constructor(e,t){super(e,t),this.messages=new o(this),this._typing=new Map}_patch(e){if(super._patch(e),this.topic=e.topic,this.nsfw=e.nsfw,this.lastMessageID=e.last_message_id,this.rateLimitPerUser=e.rate_limit_per_user||0,this.lastPinTimestamp=e.last_pin_timestamp?new Date(e.last_pin_timestamp).getTime():null,e.messages)for(const t of e.messages)this.messages.add(t)}setRateLimitPerUser(e,t){return this.edit({rateLimitPerUser:e},t)}setNSFW(e,t){return this.edit({nsfw:e},t)}fetchWebhooks(){return this.client.api.channels[this.id].webhooks.get().then(e=>{const t=new a;for(const i of e)t.set(i.id,new n(this.client,i));return t})}async createWebhook(e,{avatar:t,reason:i}={}){return"string"!=typeof t||t.startsWith("data:")||(t=await c.resolveImage(t)),this.client.api.channels[this.id].webhooks.post({data:{name:e,avatar:t},reason:i}).then(e=>new n(this.client,e))}get lastMessage(){}get lastPinAt(){}send(){}startTyping(){}stopTyping(){}get typing(){}get typingCount(){}createMessageCollector(){}awaitMessages(){}bulkDelete(){}}r.applyToClass(TextChannel,!0),e.exports=TextChannel},function(e,t,i){"use strict";const s=i(19),{TypeError:n}=i(3),r=i(8),o=i(4);e.exports=class PermissionOverwrites{constructor(e,t){Object.defineProperty(this,"channel",{value:e}),t&&this._patch(t)}_patch(e){this.id=e.id,this.type=e.type,this.deny=new r(e.deny).freeze(),this.allow=new r(e.allow).freeze()}update(e,t){const{allow:i,deny:s}=this.constructor.resolveOverwriteOptions(e,this);return this.channel.client.api.channels(this.channel.id).permissions[this.id].put({data:{id:this.id,type:this.type,allow:i.bitfield,deny:s.bitfield},reason:t}).then(()=>this)}delete(e){return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({reason:e}).then(()=>this)}toJSON(){return o.flatten(this)}static resolveOverwriteOptions(e,{allow:t,deny:i}={}){t=new r(t),i=new r(i);for(const[s,n]of Object.entries(e))!0===n?(t.add(r.FLAGS[s]),i.remove(r.FLAGS[s])):!1===n?(t.remove(r.FLAGS[s]),i.add(r.FLAGS[s])):null===n&&(t.remove(r.FLAGS[s]),i.remove(r.FLAGS[s]));return{allow:t,deny:i}}static resolve(e,t){if(e instanceof this)return e.toJSON();if("string"==typeof e.id&&["role","member"].includes(e.type))return{...e,allow:r.resolve(e.allow),deny:r.resolve(e.deny)};const i=t.roles.resolve(e.id)||t.client.users.resolve(e.id);if(!i)throw new n("INVALID_TYPE","parameter","User nor a Role",!0);const o=i instanceof s?"role":"member";return{id:i.id,type:o,allow:r.resolve(e.allow),deny:r.resolve(e.deny)}}}},function(e,t,i){"use strict";const s=i(4);e.exports=class MessageAttachment{constructor(e,t=null,i){this.attachment=e,this.name=t,i&&this._patch(i)}setFile(e,t=null){return this.attachment=e,this.name=t,this}setName(e){return this.name=e,this}_patch(e){this.id=e.id,this.size=e.size,this.url=e.url,this.proxyURL=e.proxy_url,this.height=void 0!==e.height?e.height:null,this.width=void 0!==e.width?e.width:null}get spoiler(){return s.basename(this.url).startsWith("SPOILER_")}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const{RangeError:s}=i(3),n=i(4);e.exports=class MessageEmbed{constructor(e={},t=!1){this.setup(e,t)}setup(e,t){this.type=e.type,this.title=e.title,this.description=e.description,this.url=e.url,this.color=n.resolveColor(e.color),this.timestamp=e.timestamp?new Date(e.timestamp).getTime():null,this.fields=[],e.fields&&(this.fields=t?e.fields.map(n.cloneObject):this.constructor.normalizeFields(e.fields)),this.thumbnail=e.thumbnail?{url:e.thumbnail.url,proxyURL:e.thumbnail.proxyURL||e.thumbnail.proxy_url,height:e.thumbnail.height,width:e.thumbnail.width}:null,this.image=e.image?{url:e.image.url,proxyURL:e.image.proxyURL||e.image.proxy_url,height:e.image.height,width:e.image.width}:null,this.video=e.video?{url:e.video.url,proxyURL:e.video.proxyURL||e.video.proxy_url,height:e.video.height,width:e.video.width}:null,this.author=e.author?{name:e.author.name,url:e.author.url,iconURL:e.author.iconURL||e.author.icon_url,proxyIconURL:e.author.proxyIconURL||e.author.proxy_icon_url}:null,this.provider=e.provider?{name:e.provider.name,url:e.provider.name}:null,this.footer=e.footer?{text:e.footer.text,iconURL:e.footer.iconURL||e.footer.icon_url,proxyIconURL:e.footer.proxyIconURL||e.footer.proxy_icon_url}:null,this.files=e.files||[]}get createdAt(){return this.timestamp?new Date(this.timestamp):null}get hexColor(){return this.color?`#${this.color.toString(16).padStart(6,"0")}`:null}get length(){return(this.title?this.title.length:0)+(this.description?this.description.length:0)+(this.fields.length>=1?this.fields.reduce((e,t)=>e+t.name.length+t.value.length,0):0)+(this.footer?this.footer.text.length:0)}addField(e,t,i){return this.addFields({name:e,value:t,inline:i})}addFields(...e){return this.fields.push(...this.constructor.normalizeFields(e)),this}spliceFields(e,t,...i){return this.fields.splice(e,t,...this.constructor.normalizeFields(...i)),this}attachFiles(e){return this.files=this.files.concat(e),this}setAuthor(e,t,i){return this.author={name:n.resolveString(e),iconURL:t,url:i},this}setColor(e){return this.color=n.resolveColor(e),this}setDescription(e){return e=n.resolveString(e),this.description=e,this}setFooter(e,t){return e=n.resolveString(e),this.footer={text:e,iconURL:t},this}setImage(e){return this.image={url:e},this}setThumbnail(e){return this.thumbnail={url:e},this}setTimestamp(e=Date.now()){return e instanceof Date&&(e=e.getTime()),this.timestamp=e,this}setTitle(e){return e=n.resolveString(e),this.title=e,this}setURL(e){return this.url=e,this}toJSON(){return{title:this.title,type:"rich",description:this.description,url:this.url,timestamp:this.timestamp?new Date(this.timestamp):null,color:this.color,fields:this.fields,thumbnail:this.thumbnail,image:this.image,author:this.author?{name:this.author.name,url:this.author.url,icon_url:this.author.iconURL}:null,footer:this.footer?{text:this.footer.text,icon_url:this.footer.iconURL}:null}}static normalizeField(e,t,i=!1){if(!(e=n.resolveString(e)))throw new s("EMBED_FIELD_NAME");if(!(t=n.resolveString(t)))throw new s("EMBED_FIELD_VALUE");return{name:e,value:t,inline:i}}static normalizeFields(...e){return e.flat(2).map(e=>this.normalizeField(e&&e.name,e&&e.value,!(!e||"boolean"!=typeof e.inline)&&e.inline))}}},function(e,t,i){(t=e.exports=i(64)).Stream=t,t.Readable=t,t.Writable=i(46),t.Duplex=i(20),t.Transform=i(69),t.PassThrough=i(127)},function(e,t,i){"use strict";(function(t,s,n){var r=i(31);function o(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,i){var s=e.entry;e.entry=null;for(;s;){var n=s.callback;t.pendingcb--,n(i),s=s.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=_;var a,c=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?s:r.nextTick;_.WritableState=E;var l=Object.create(i(25));l.inherits=i(22);var h={deprecate:i(126)},u=i(66),d=i(32).Buffer,p=n.Uint8Array||function(){};var f,m=i(67);function g(){}function E(e,t){a=a||i(20),e=e||{};var s=t instanceof a;this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var n=e.highWaterMark,l=e.writableHighWaterMark,h=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(l||0===l)?l:h,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var u=!1===e.decodeStrings;this.decodeStrings=!u,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var i=e._writableState,s=i.sync,n=i.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(i),t)!function(e,t,i,s,n){--t.pendingcb,i?(r.nextTick(n,s),r.nextTick(S,e,t),e._writableState.errorEmitted=!0,e.emit("error",s)):(n(s),e._writableState.errorEmitted=!0,e.emit("error",s),S(e,t))}(e,i,s,t,n);else{var o=w(i);o||i.corked||i.bufferProcessing||!i.bufferedRequest||v(e,i),s?c(b,e,i,o,n):b(e,i,o,n)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new o(this)}function _(e){if(a=a||i(20),!(f.call(_,this)||this instanceof a))return new _(e);this._writableState=new E(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),u.call(this)}function y(e,t,i,s,n,r,o){t.writelen=s,t.writecb=o,t.writing=!0,t.sync=!0,i?e._writev(n,t.onwrite):e._write(n,r,t.onwrite),t.sync=!1}function b(e,t,i,s){i||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,s(),S(e,t)}function v(e,t){t.bufferProcessing=!0;var i=t.bufferedRequest;if(e._writev&&i&&i.next){var s=t.bufferedRequestCount,n=new Array(s),r=t.corkedRequestsFree;r.entry=i;for(var a=0,c=!0;i;)n[a]=i,i.isBuf||(c=!1),i=i.next,a+=1;n.allBuffers=c,y(e,t,!0,t.length,n,"",r.finish),t.pendingcb++,t.lastBufferedRequest=null,r.next?(t.corkedRequestsFree=r.next,r.next=null):t.corkedRequestsFree=new o(t),t.bufferedRequestCount=0}else{for(;i;){var l=i.chunk,h=i.encoding,u=i.callback;if(y(e,t,!1,t.objectMode?1:l.length,l,h,u),i=i.next,t.bufferedRequestCount--,t.writing)break}null===i&&(t.lastBufferedRequest=null)}t.bufferedRequest=i,t.bufferProcessing=!1}function w(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function A(e,t){e._final((function(i){t.pendingcb--,i&&e.emit("error",i),t.prefinished=!0,e.emit("prefinish"),S(e,t)}))}function S(e,t){var i=w(t);return i&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,r.nextTick(A,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),i}l.inherits(_,u),E.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(E.prototype,"buffer",{get:h.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(_,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===_&&(e&&e._writableState instanceof E)}})):f=function(e){return e instanceof this},_.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},_.prototype.write=function(e,t,i){var s,n=this._writableState,o=!1,a=!n.objectMode&&(s=e,d.isBuffer(s)||s instanceof p);return a&&!d.isBuffer(e)&&(e=function(e){return d.from(e)}(e)),"function"==typeof t&&(i=t,t=null),a?t="buffer":t||(t=n.defaultEncoding),"function"!=typeof i&&(i=g),n.ended?function(e,t){var i=new Error("write after end");e.emit("error",i),r.nextTick(t,i)}(this,i):(a||function(e,t,i,s){var n=!0,o=!1;return null===i?o=new TypeError("May not write null values to stream"):"string"==typeof i||void 0===i||t.objectMode||(o=new TypeError("Invalid non-string/buffer chunk")),o&&(e.emit("error",o),r.nextTick(s,o),n=!1),n}(this,n,e,i))&&(n.pendingcb++,o=function(e,t,i,s,n,r){if(!i){var o=function(e,t,i){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=d.from(t,i));return t}(t,s,n);s!==o&&(i=!0,n="buffer",s=o)}var a=t.objectMode?1:s.length;t.length+=a;var c=t.length<t.highWaterMark;c||(t.needDrain=!0);if(t.writing||t.corked){var l=t.lastBufferedRequest;t.lastBufferedRequest={chunk:s,encoding:n,isBuf:i,callback:r,next:null},l?l.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else y(e,t,!1,a,s,n,r);return c}(this,n,a,e,t,i)),o},_.prototype.cork=function(){this._writableState.corked++},_.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||v(this,e))},_.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(_.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),_.prototype._write=function(e,t,i){i(new Error("_write() is not implemented"))},_.prototype._writev=null,_.prototype.end=function(e,t,i){var s=this._writableState;"function"==typeof e?(i=e,e=null,t=null):"function"==typeof t&&(i=t,t=null),null!=e&&this.write(e,t),s.corked&&(s.corked=1,this.uncork()),s.ending||s.finished||function(e,t,i){t.ending=!0,S(e,t),i&&(t.finished?r.nextTick(i):e.once("finish",i));t.ended=!0,e.writable=!1}(this,s,i)},Object.defineProperty(_.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),_.prototype.destroy=m.destroy,_.prototype._undestroy=m.undestroy,_.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,i(14),i(38).setImmediate,i(21))},function(e,t,i){"use strict";const s=i(11);class MessageFlags extends s{}MessageFlags.FLAGS={CROSSPOSTED:1,IS_CROSSPOST:2,SUPPRESS_EMBEDS:4,SOURCE_MESSAGE_DELETED:8,URGENT:16},e.exports=MessageFlags},function(e,t,i){"use strict";const s=i(37);class WebhookClient extends s{constructor(e,t,i){super(i),Object.defineProperty(this,"client",{value:this}),this.id=e,Object.defineProperty(this,"token",{value:t,writable:!0,configurable:!0})}}i(12).applyToClass(WebhookClient),e.exports=WebhookClient},function(e,t,i){"use strict";const s=i(15),n=i(2),r=i(4);e.exports=class Collector extends s{constructor(e,t,i={}){super(),Object.defineProperty(this,"client",{value:e}),this.filter=t,this.options=i,this.collected=new n,this.ended=!1,this._timeout=null,this._idletimeout=null,this.handleCollect=this.handleCollect.bind(this),this.handleDispose=this.handleDispose.bind(this),i.time&&(this._timeout=this.client.setTimeout(()=>this.stop("time"),i.time)),i.idle&&(this._idletimeout=this.client.setTimeout(()=>this.stop("idle"),i.idle))}handleCollect(...e){const t=this.collect(...e);t&&this.filter(...e,this.collected)&&(this.collected.set(t,e[0]),this.emit("collect",...e),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout(()=>this.stop("idle"),this.options.idle))),this.checkEnd()}handleDispose(...e){if(!this.options.dispose)return;const t=this.dispose(...e);t&&this.filter(...e)&&this.collected.has(t)&&(this.collected.delete(t),this.emit("dispose",...e),this.checkEnd())}get next(){return new Promise((e,t)=>{if(this.ended)return void t(this.collected);const i=()=>{this.removeListener("collect",s),this.removeListener("end",n)},s=t=>{i(),e(t)},n=()=>{i(),t(this.collected)};this.on("collect",s),this.on("end",n)})}stop(e="user"){this.ended||(this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=null),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=null),this.ended=!0,this.emit("end",this.collected,e))}resetTimer({time:e,idle:t}={}){this._timeout&&(this.client.clearTimeout(this._timeout),this._timeout=this.client.setTimeout(()=>this.stop("time"),e||this.options.time)),this._idletimeout&&(this.client.clearTimeout(this._idletimeout),this._idletimeout=this.client.setTimeout(()=>this.stop("idle"),t||this.options.idle))}checkEnd(){const e=this.endReason();e&&this.stop(e)}async*[Symbol.asyncIterator](){const e=[],t=t=>e.push(t);this.on("collect",t);try{for(;e.length||!this.ended;)e.length?yield e.shift():await new Promise(e=>{const t=()=>(this.removeListener("collect",t),this.removeListener("end",t),e());this.on("collect",t),this.on("end",t)})}finally{this.removeListener("collect",t)}}toJSON(){return r.flatten(this)}collect(){}dispose(){}endReason(){}}},function(e,t,i){"use strict";const s=i(5),n=i(73),{ClientApplicationAssetTypes:r,Endpoints:o}=i(0),a=i(7),c=Object.keys(r);e.exports=class ClientApplication extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.description=e.description,this.icon=e.icon,this.cover=e.cover_image||null,this.rpcOrigins=e.rpc_origins||[],this.botRequireCodeGrant=void 0!==e.bot_require_code_grant?e.bot_require_code_grant:null,this.botPublic=void 0!==e.bot_public?e.bot_public:null,this.owner=e.team?new n(this.client,e.team):e.owner?this.client.users.add(e.owner):null}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.AppIcon(this.id,this.icon,{format:e,size:t}):null}coverImage({format:e,size:t}={}){return this.cover?o.CDN(this.client.options.http.cdn).AppIcon(this.id,this.cover,{format:e,size:t}):null}fetchAssets(){return this.client.api.oauth2.applications(this.id).assets.get().then(e=>e.map(e=>({id:e.id,name:e.name,type:c[e.type-1]})))}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(24),n=i(52),r=i(77),o=i(4);e.exports=class MessageReaction{constructor(e,t,i){Object.defineProperty(this,"client",{value:e}),this.message=i,this.me=t.me,this.users=new r(e,void 0,this),this._emoji=new n(this,t.emoji),this._patch(t)}_patch(e){null==this.count&&(this.count=e.count)}async remove(){return await this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions(this._emoji.identifier).delete(),this}get emoji(){if(this._emoji instanceof s)return this._emoji;if(this._emoji.id){const e=this.message.client.emojis.cache;if(e.has(this._emoji.id)){const t=e.get(this._emoji.id);return this._emoji=t,t}}return this._emoji}get partial(){return null===this.count}async fetch(){const e=(await this.message.fetch()).reactions.cache.get(this.emoji.id||this.emoji.name);return this._patch(e||{count:0}),this}toJSON(){return o.flatten(this,{emoji:"emojiID",message:"messageID"})}_add(e){this.partial||(this.users.cache.set(e.id,e),this.me&&e.id===this.message.client.user.id&&0!==this.count||this.count++,this.me||(this.me=e.id===this.message.client.user.id))}_remove(e){this.partial||(this.users.cache.delete(e.id),this.me&&e.id===this.message.client.user.id||this.count--,e.id===this.message.client.user.id&&(this.me=!1),this.count<=0&&0===this.users.cache.size&&this.message.reactions.cache.delete(this.emoji.id||this.emoji.name))}}},function(e,t,i){"use strict";const s=i(29),n=i(4);e.exports=class ReactionEmoji extends s{constructor(e,t){super(e.message.client,t),this.reaction=e}toJSON(){return n.flatten(this,{identifier:!0})}valueOf(){return this.id}}},function(e,t,i){"use strict";const s=i(5),n=i(83),r=i(55),o=i(54),a=i(18),c=i(56),l=i(12),h=i(84),u=i(57),d=i(85),p=i(86),f=i(87),m=i(135),g=i(2),{ChannelTypes:E,DefaultMessageNotifications:_,PartialTypes:y,VerificationLevels:b,ExplicitContentFilterLevels:v}=i(0),w=i(9),A=i(7),S=i(88),I=i(4);e.exports=class Guild extends s{constructor(e,t){super(e),this.members=new d(this),this.channels=new h(this),this.roles=new f(this),this.presences=new p(this.client),this.voiceStates=new m(this),this.deleted=!1,t&&(t.unavailable?(this.available=!1,this.id=t.id):(this._patch(t),t.channels||(this.available=!1)),this.shardID=t.shardID)}get shard(){return this.client.ws.shards.get(this.shardID)}_patch(e){if(this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.region=e.region,this.memberCount=e.member_count||this.memberCount,this.large=Boolean("large"in e?e.large:this.large),this.features=e.features,this.applicationID=e.application_id,this.afkTimeout=e.afk_timeout,this.afkChannelID=e.afk_channel_id,this.systemChannelID=e.system_channel_id,this.embedEnabled=e.embed_enabled,this.premiumTier=e.premium_tier,void 0!==e.premium_subscription_count&&(this.premiumSubscriptionCount=e.premium_subscription_count),void 0!==e.widget_enabled&&(this.widgetEnabled=e.widget_enabled),void 0!==e.widget_channel_id&&(this.widgetChannelID=e.widget_channel_id),void 0!==e.embed_channel_id&&(this.embedChannelID=e.embed_channel_id),this.verificationLevel=b[e.verification_level],this.explicitContentFilter=v[e.explicit_content_filter],this.mfaLevel=e.mfa_level,this.joinedTimestamp=e.joined_at?new Date(e.joined_at).getTime():this.joinedTimestamp,this.defaultMessageNotifications=_[e.default_message_notifications]||e.default_message_notifications,this.systemChannelFlags=new S(e.system_channel_flags).freeze(),void 0!==e.max_members&&(this.maximumMembers=e.max_members||25e4),void 0!==e.max_presences&&(this.maximumPresences=e.max_presences||25e3),this.vanityURLCode=e.vanity_url_code,this.description=e.description,this.banner=e.banner,this.id=e.id,this.available=!e.unavailable,this.features=e.features||this.features||[],this.rulesChannelID=e.rules_channel_id,this.publicUpdatesChannelID=e.public_updates_channel_id,e.channels){this.channels.cache.clear();for(const t of e.channels)this.client.channels.add(t,this)}if(e.roles){this.roles.cache.clear();for(const t of e.roles)this.roles.add(t)}if(e.members){this.members.cache.clear();for(const t of e.members)this.members.add(t)}if(e.owner_id&&(this.ownerID=e.owner_id),e.presences)for(const t of e.presences)this.presences.add(Object.assign(t,{guild:this}));if(e.voice_states){this.voiceStates.cache.clear();for(const t of e.voice_states)this.voiceStates.add(t)}if(this.emojis)e.emojis&&this.client.actions.GuildEmojisUpdate.handle({guild_id:this.id,emojis:e.emojis});else if(this.emojis=new u(this),e.emojis)for(const t of e.emojis)this.emojis.add(t)}bannerURL({format:e,size:t}={}){return this.banner?this.client.rest.cdn.Banner(this.id,this.banner,e,t):null}get createdTimestamp(){return A.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}get joinedAt(){return new Date(this.joinedTimestamp)}get partnered(){return this.features.includes("PARTNERED")}get verified(){return this.features.includes("VERIFIED")}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}get nameAcronym(){return this.name.replace(/\w+/g,e=>e[0]).replace(/\s/g,"")}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}get owner(){return this.members.cache.get(this.ownerID)||(this.client.options.partials.includes(y.GUILD_MEMBER)?this.members.add({user:{id:this.ownerID}},!0):null)}get afkChannel(){return this.client.channels.cache.get(this.afkChannelID)||null}get systemChannel(){return this.client.channels.cache.get(this.systemChannelID)||null}get widgetChannel(){return this.client.channels.cache.get(this.widgetChannelID)||null}get embedChannel(){return this.client.channels.cache.get(this.embedChannelID)||null}get rulesChannel(){return this.client.channels.cache.get(this.rulesChannelID)||null}get publicUpdatesChannel(){return this.client.channels.cache.get(this.publicUpdatesChannelID)||null}get me(){return this.members.cache.get(this.client.user.id)||(this.client.options.partials.includes(y.GUILD_MEMBER)?this.members.add({user:{id:this.client.user.id}},!0):null)}get voice(){return this.voiceStates.cache.get(this.client.user.id)}member(e){return this.members.resolve(e)}fetch(){return this.client.api.guilds(this.id).get().then(e=>(this._patch(e),this))}fetchBan(e){const t=this.client.users.resolveID(e);if(!t)throw new Error("FETCH_BAN_RESOLVE_ID");return this.client.api.guilds(this.id).bans(t).get().then(e=>({reason:e.reason,user:this.client.users.add(e.user)}))}fetchBans(){return this.client.api.guilds(this.id).bans.get().then(e=>e.reduce((e,t)=>(e.set(t.user.id,{reason:t.reason,user:this.client.users.add(t.user)}),e),new g))}fetchIntegrations(){return this.client.api.guilds(this.id).integrations.get().then(e=>e.reduce((e,t)=>e.set(t.id,new o(this.client,t,this)),new g))}createIntegration(e,t){return this.client.api.guilds(this.id).integrations.post({data:e,reason:t}).then(()=>this)}fetchInvites(){return this.client.api.guilds(this.id).invites.get().then(e=>{const t=new g;for(const i of e){const e=new a(this.client,i);t.set(e.code,e)}return t})}fetchPreview(){return this.client.api.guilds(this.id).preview.get().then(e=>new r(this.client,e))}fetchVanityCode(){return this.features.includes("VANITY_URL")?this.client.api.guilds(this.id,"vanity-url").get().then(e=>e.code):Promise.reject(new Error("VANITY_URL"))}fetchWebhooks(){return this.client.api.guilds(this.id).webhooks.get().then(e=>{const t=new g;for(const i of e)t.set(i.id,new l(this.client,i));return t})}fetchVoiceRegions(){return this.client.api.guilds(this.id).regions.get().then(e=>{const t=new g;for(const i of e)t.set(i.id,new c(i));return t})}fetchEmbed(){return this.client.api.guilds(this.id).embed.get().then(e=>({enabled:e.enabled,channel:e.channel_id?this.channels.cache.get(e.channel_id):null}))}fetchAuditLogs(e={}){return e.before&&e.before instanceof n.Entry&&(e.before=e.before.id),"string"==typeof e.type&&(e.type=n.Actions[e.type]),this.client.api.guilds(this.id)["audit-logs"].get({query:{before:e.before,limit:e.limit,user_id:this.client.users.resolveID(e.user),action_type:e.type}}).then(e=>n.build(this,e))}addMember(e,t){if(!(e=this.client.users.resolveID(e)))return Promise.reject(new TypeError("INVALID_TYPE","user","UserResolvable"));if(this.members.cache.has(e))return Promise.resolve(this.members.cache.get(e));if(t.access_token=t.accessToken,t.roles){const e=[];for(let i of t.roles instanceof g?t.roles.values():t.roles){if(i=this.roles.resolve(i),!i)return Promise.reject(new TypeError("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0));e.push(i.id)}t.roles=e}return this.client.api.guilds(this.id).members(e).put({data:t}).then(e=>this.members.add(e))}edit(e,t){const i={};return e.name&&(i.name=e.name),e.region&&(i.region=e.region),void 0!==e.verificationLevel&&(i.verification_level="number"==typeof e.verificationLevel?Number(e.verificationLevel):b.indexOf(e.verificationLevel)),void 0!==e.afkChannel&&(i.afk_channel_id=this.client.channels.resolveID(e.afkChannel)),void 0!==e.systemChannel&&(i.system_channel_id=this.client.channels.resolveID(e.systemChannel)),e.afkTimeout&&(i.afk_timeout=Number(e.afkTimeout)),void 0!==e.icon&&(i.icon=e.icon),e.owner&&(i.owner_id=this.client.users.resolveID(e.owner)),e.splash&&(i.splash=e.splash),e.banner&&(i.banner=e.banner),void 0!==e.explicitContentFilter&&(i.explicit_content_filter="number"==typeof e.explicitContentFilter?e.explicitContentFilter:v.indexOf(e.explicitContentFilter)),void 0!==e.defaultMessageNotifications&&(i.default_message_notifications="string"==typeof e.defaultMessageNotifications?_.indexOf(e.defaultMessageNotifications):e.defaultMessageNotifications),void 0!==e.systemChannelFlags&&(i.system_channel_flags=S.resolve(e.systemChannelFlags)),this.client.api.guilds(this.id).patch({data:i,reason:t}).then(e=>this.client.actions.GuildUpdate.handle(e).updated)}setExplicitContentFilter(e,t){return this.edit({explicitContentFilter:e},t)}setDefaultMessageNotifications(e,t){return this.edit({defaultMessageNotifications:e},t)}setSystemChannelFlags(e,t){return this.edit({systemChannelFlags:e},t)}setName(e,t){return this.edit({name:e},t)}setRegion(e,t){return this.edit({region:e},t)}setVerificationLevel(e,t){return this.edit({verificationLevel:e},t)}setAFKChannel(e,t){return this.edit({afkChannel:e},t)}setSystemChannel(e,t){return this.edit({systemChannel:e},t)}setAFKTimeout(e,t){return this.edit({afkTimeout:e},t)}async setIcon(e,t){return this.edit({icon:await w.resolveImage(e),reason:t})}setOwner(e,t){return this.edit({owner:e},t)}async setSplash(e,t){return this.edit({splash:await w.resolveImage(e),reason:t})}async setBanner(e,t){return this.edit({banner:await w.resolveImage(e),reason:t})}setChannelPositions(e){const t=e.map(e=>({id:this.client.channels.resolveID(e.channel),position:e.position}));return this.client.api.guilds(this.id).channels.patch({data:t}).then(()=>this.client.actions.GuildChannelsPositionUpdate.handle({guild_id:this.id,channels:t}).guild)}setRolePositions(e){return e=e.map(e=>({id:this.roles.resolveID(e.role),position:e.position})),this.client.api.guilds(this.id).roles.patch({data:e}).then(()=>this.client.actions.GuildRolesPositionUpdate.handle({guild_id:this.id,roles:e}).guild)}setEmbed(e,t){return this.client.api.guilds(this.id).embed.patch({data:{enabled:e.enabled,channel_id:this.channels.resolveID(e.channel)},reason:t}).then(()=>this)}leave(){return this.ownerID===this.client.user.id?Promise.reject(new Error("GUILD_OWNED")):this.client.api.users("@me").guilds(this.id).delete().then(()=>this.client.actions.GuildDelete.handle({id:this.id}).guild)}delete(){return this.client.api.guilds(this.id).delete().then(()=>this.client.actions.GuildDelete.handle({id:this.id}).guild)}equals(e){let t=e&&e instanceof this.constructor&&this.id===e.id&&this.available===e.available&&this.splash===e.splash&&this.region===e.region&&this.name===e.name&&this.memberCount===e.memberCount&&this.large===e.large&&this.icon===e.icon&&this.ownerID===e.ownerID&&this.verificationLevel===e.verificationLevel&&this.embedEnabled===e.embedEnabled&&(this.features===e.features||this.features.length===e.features.length&&this.features.every((t,i)=>t===e.features[i]));return t&&(this.embedChannel?e.embedChannel&&this.embedChannel.id===e.embedChannel.id||(t=!1):e.embedChannel&&(t=!1)),t}toString(){return this.name}toJSON(){const e=super.toJSON({available:!1,createdTimestamp:!0,nameAcronym:!0,presences:!1,voiceStates:!1});return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e.bannerURL=this.bannerURL(),e}_sortedRoles(){return I.discordSort(this.roles.cache)}_sortedChannels(e){const t=e.type===E.CATEGORY;return I.discordSort(this.channels.cache.filter(i=>(["text","news","store"].includes(e.type)?["text","news","store"].includes(i.type):i.type===e.type)&&(t||i.parent===e.parent)))}}},function(e,t,i){"use strict";const s=i(5);e.exports=class Integration extends s{constructor(e,t,i){super(e),this.guild=i,this.id=t.id,this.name=t.name,this.type=t.type,this.enabled=t.enabled,this.syncing=t.syncing,this.role=this.guild.roles.cache.get(t.role_id),this.user=this.client.users.add(t.user),this.account=t.account,this.syncedAt=t.synced_at,this._patch(t)}_patch(e){this.expireBehavior=e.expire_behavior,this.expireGracePeriod=e.expire_grace_period}sync(){return this.syncing=!0,this.client.api.guilds(this.guild.id).integrations(this.id).post().then(()=>(this.syncing=!1,this.syncedAt=Date.now(),this))}edit(e,t){return"expireBehavior"in e&&(e.expire_behavior=e.expireBehavior,e.expireBehavior=null),"expireGracePeriod"in e&&(e.expire_grace_period=e.expireGracePeriod,e.expireGracePeriod=null),this.client.api.guilds(this.guild.id).integrations(this.id).patch({data:e,reason:t}).then(()=>(this._patch(e),this))}delete(e){return this.client.api.guilds(this.guild.id).integrations(this.id).delete({reason:e}).then(()=>this)}toJSON(){return super.toJSON({role:"roleID",guild:"guildID",user:"userID"})}}},function(e,t,i){"use strict";const s=i(5),n=i(134),r=i(2);e.exports=class GuildPreview extends s{constructor(e,t){super(e),t&&this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon,this.splash=e.splash,this.discoverySplash=e.discovery_splash,this.features=e.features,this.approximateMemberCount=e.approximate_member_count,this.approximatePresenceCount=e.approximate_presence_count,this.description=e.description,this.emojis?this.emojis.clear():this.emojis=new r;for(const t of e.emojis)this.emojis.set(t.id,new n(this.client,t,this))}splashURL({format:e,size:t}={}){return this.splash?this.client.rest.cdn.Splash(this.id,this.splash,e,t):null}discoverySplashURL({format:e,size:t}={}){return this.discoverySplash?this.client.rest.cdn.DiscoverySplash(this.id,this.discoverySplash,e,t):null}iconURL({format:e,size:t,dynamic:i}={}){return this.icon?this.client.rest.cdn.Icon(this.id,this.icon,e,t,i):null}fetch(){return this.client.api.guilds(this.id).preview.get().then(e=>(this._patch(e),this))}toString(){return this.name}toJSON(){const e=super.toJSON();return e.iconURL=this.iconURL(),e.splashURL=this.splashURL(),e}}},function(e,t,i){"use strict";const s=i(4);e.exports=class VoiceRegion{constructor(e){this.id=e.id,this.name=e.name,this.vip=e.vip,this.deprecated=e.deprecated,this.optimal=e.optimal,this.custom=e.custom}toJSON(){return s.flatten(this)}}},function(e,t,i){"use strict";const s=i(6),{TypeError:n}=i(3),r=i(24),o=i(52),a=i(2),c=i(9);e.exports=class GuildEmojiManager extends s{constructor(e,t){super(e.client,t,r),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async create(e,t,{roles:i,reason:s}={}){if(!(e=await c.resolveImage(e)))throw new n("REQ_RESOURCE_TYPE");const r={image:e,name:t};if(i){r.roles=[];for(let e of i instanceof a?i.values():i){if(e=this.guild.roles.resolve(e),!e)return Promise.reject(new n("INVALID_TYPE","options.roles","Array or Collection of Roles or Snowflakes",!0));r.roles.push(e.id)}}return this.client.api.guilds(this.guild.id).emojis.post({data:r,reason:s}).then(e=>this.client.actions.GuildEmojiCreate.handle(this.guild,e).emoji)}resolve(e){return e instanceof o?super.resolve(e.id):super.resolve(e)}resolveID(e){return e instanceof o?e.id:super.resolveID(e)}resolveIdentifier(e){const t=this.resolve(e);return t?t.identifier:e instanceof o?e.identifier:"string"==typeof e?e.includes("%")?e:encodeURIComponent(e):null}}},function(e,t){e.exports={version:"12.2.0",homepage:"https://github.com/discordjs/discord.js#readme"}},function(e,t,i){"use strict";const s=Symbol("code"),n=new Map;function r(e){return class DiscordjsError extends e{constructor(e,...t){super(function(e,t){if("string"!=typeof e)throw new Error("Error message key must be a string");const i=n.get(e);if(!i)throw new Error(`An invalid error message key was used: ${e}.`);return"function"==typeof i?i(...t):void 0===t||0===t.length?i:(t.unshift(i),String(...t))}(e,t)),this[s]=e,Error.captureStackTrace&&Error.captureStackTrace(this,DiscordjsError)}get name(){return`${super.name} [${this[s]}]`}get code(){return this[s]}}}e.exports={register:function(e,t){n.set(e,"function"==typeof t?t:String(t))},Error:r(Error),TypeError:r(TypeError),RangeError:r(RangeError)}},function(e,t,i){(function(e,t){!function(e,i){"use strict";if(!e.setImmediate){var s,n,r,o,a,c=1,l={},h=!1,u=e.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(e);d=d&&d.setTimeout?d:e,"[object process]"==={}.toString.call(e.process)?s=function(e){t.nextTick((function(){f(e)}))}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,i=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=i,t}}()?e.MessageChannel?((r=new MessageChannel).port1.onmessage=function(e){f(e.data)},s=function(e){r.port2.postMessage(e)}):u&&"onreadystatechange"in u.createElement("script")?(n=u.documentElement,s=function(e){var t=u.createElement("script");t.onreadystatechange=function(){f(e),t.onreadystatechange=null,n.removeChild(t),t=null},n.appendChild(t)}):s=function(e){setTimeout(f,0,e)}:(o="setImmediate$"+Math.random()+"$",a=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(o)&&f(+t.data.slice(o.length))},e.addEventListener?e.addEventListener("message",a,!1):e.attachEvent("onmessage",a),s=function(t){e.postMessage(o+t,"*")}),d.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),i=0;i<t.length;i++)t[i]=arguments[i+1];var n={callback:e,args:t};return l[c]=n,s(c),c++},d.clearImmediate=p}function p(e){delete l[e]}function f(e){if(h)setTimeout(f,0,e);else{var t=l[e];if(t){h=!0;try{!function(e){var t=e.callback,i=e.args;switch(i.length){case 0:t();break;case 1:t(i[0]);break;case 2:t(i[0],i[1]);break;case 3:t(i[0],i[1],i[2]);break;default:t.apply(void 0,i)}}(t)}finally{p(e),h=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,i(21),i(14))},function(e,t,i){"use strict";class DiscordAPIError extends Error{constructor(e,t,i,s){super();const n=this.constructor.flattenErrors(t.errors||t).join("\n");this.name="DiscordAPIError",this.message=t.message&&n?`${t.message}\n${n}`:t.message||n,this.method=i,this.path=e,this.code=t.code,this.httpStatus=s}static flattenErrors(e,t=""){let i=[];for(const[s,n]of Object.entries(e)){if("message"===s)continue;const e=t?isNaN(s)?`${t}.${s}`:`${t}[${s}]`:s;n._errors?i.push(`${e}: ${n._errors.map(e=>e.message).join(" ")}`):n.code||n.message?i.push(`${n.code?`${n.code}: `:""}${n.message}`.trim()):"string"==typeof n?i.push(n):i=i.concat(this.flattenErrors(n,e))}return i}}e.exports=DiscordAPIError},function(e,t,i){"use strict";class HTTPError extends Error{constructor(e,t,i,s,n){super(e),this.name=t,this.code=i||500,this.method=s,this.path=n}}e.exports=HTTPError},function(e,t,i){"use strict";const{TypeError:s}=i(3),n=i(2);e.exports=class GuildEmojiRoleManager{constructor(e){this.emoji=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){return this.guild.roles.cache.filter(e=>this.emoji._roles.includes(e.id))}get cache(){return this._roles}add(e){if(e instanceof n)return this.add(e.keyArray());if(!Array.isArray(e))return this.add([e]);if((e=e.map(e=>this.guild.roles.resolve(e))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=[...new Set(e.concat(...this._roles.values()))];return this.set(t)}remove(e){if(e instanceof n)return this.remove(e.keyArray());if(!Array.isArray(e))return this.remove([e]);if((e=e.map(e=>this.guild.roles.resolveID(e))).includes(null))return Promise.reject(new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0));const t=this._roles.keyArray().filter(t=>!e.includes(t));return this.set(t)}set(e){return this.emoji.edit({roles:e})}clone(){const e=new this.constructor(this.emoji);return e._patch(this._roles.keyArray().slice()),e}_patch(e){this.emoji._roles=e}}},function(e,t,i){"use strict";(function(t,s){var n=i(31);e.exports=y;var r,o=i(65);y.ReadableState=_;i(15).EventEmitter;var a=function(e,t){return e.listeners(t).length},c=i(66),l=i(32).Buffer,h=t.Uint8Array||function(){};var u=Object.create(i(25));u.inherits=i(22);var d=i(123),p=void 0;p=d&&d.debuglog?d.debuglog("stream"):function(){};var f,m=i(124),g=i(67);u.inherits(y,c);var E=["error","close","destroy","pause","resume"];function _(e,t){e=e||{};var s=t instanceof(r=r||i(20));this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var n=e.highWaterMark,o=e.readableHighWaterMark,a=this.objectMode?16:16384;this.highWaterMark=n||0===n?n:s&&(o||0===o)?o:a,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new m,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(f||(f=i(68).StringDecoder),this.decoder=new f(e.encoding),this.encoding=e.encoding)}function y(e){if(r=r||i(20),!(this instanceof y))return new y(e);this._readableState=new _(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),c.call(this)}function b(e,t,i,s,n){var r,o=e._readableState;null===t?(o.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var i=t.decoder.end();i&&i.length&&(t.buffer.push(i),t.length+=t.objectMode?1:i.length)}t.ended=!0,A(e)}(e,o)):(n||(r=function(e,t){var i;s=t,l.isBuffer(s)||s instanceof h||"string"==typeof t||void 0===t||e.objectMode||(i=new TypeError("Invalid non-string/buffer chunk"));var s;return i}(o,t)),r?e.emit("error",r):o.objectMode||t&&t.length>0?("string"==typeof t||o.objectMode||Object.getPrototypeOf(t)===l.prototype||(t=function(e){return l.from(e)}(t)),s?o.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):v(e,o,t,!0):o.ended?e.emit("error",new Error("stream.push() after EOF")):(o.reading=!1,o.decoder&&!i?(t=o.decoder.write(t),o.objectMode||0!==t.length?v(e,o,t,!1):I(e,o)):v(e,o,t,!1))):s||(o.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(o)}function v(e,t,i,s){t.flowing&&0===t.length&&!t.sync?(e.emit("data",i),e.read(0)):(t.length+=t.objectMode?1:i.length,s?t.buffer.unshift(i):t.buffer.push(i),t.needReadable&&A(e)),I(e,t)}Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),y.prototype.destroy=g.destroy,y.prototype._undestroy=g.undestroy,y.prototype._destroy=function(e,t){this.push(null),t(e)},y.prototype.push=function(e,t){var i,s=this._readableState;return s.objectMode?i=!0:"string"==typeof e&&((t=t||s.defaultEncoding)!==s.encoding&&(e=l.from(e,t),t=""),i=!0),b(this,e,t,!1,i)},y.prototype.unshift=function(e){return b(this,e,null,!0,!1)},y.prototype.isPaused=function(){return!1===this._readableState.flowing},y.prototype.setEncoding=function(e){return f||(f=i(68).StringDecoder),this._readableState.decoder=new f(e),this._readableState.encoding=e,this};function w(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=8388608?e=8388608:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function A(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(p("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?n.nextTick(S,e):S(e))}function S(e){p("emit readable"),e.emit("readable"),R(e)}function I(e,t){t.readingMore||(t.readingMore=!0,n.nextTick(T,e,t))}function T(e,t){for(var i=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(p("maybeReadMore read 0"),e.read(0),i!==t.length);)i=t.length;t.readingMore=!1}function D(e){p("readable nexttick read 0"),e.read(0)}function N(e,t){t.reading||(p("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),R(e),t.flowing&&!t.reading&&e.read(0)}function R(e){var t=e._readableState;for(p("flow",t.flowing);t.flowing&&null!==e.read(););}function O(e,t){return 0===t.length?null:(t.objectMode?i=t.buffer.shift():!e||e>=t.length?(i=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):i=function(e,t,i){var s;e<t.head.data.length?(s=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):s=e===t.head.data.length?t.shift():i?function(e,t){var i=t.head,s=1,n=i.data;e-=n.length;for(;i=i.next;){var r=i.data,o=e>r.length?r.length:e;if(o===r.length?n+=r:n+=r.slice(0,e),0===(e-=o)){o===r.length?(++s,i.next?t.head=i.next:t.head=t.tail=null):(t.head=i,i.data=r.slice(o));break}++s}return t.length-=s,n}(e,t):function(e,t){var i=l.allocUnsafe(e),s=t.head,n=1;s.data.copy(i),e-=s.data.length;for(;s=s.next;){var r=s.data,o=e>r.length?r.length:e;if(r.copy(i,i.length-e,0,o),0===(e-=o)){o===r.length?(++n,s.next?t.head=s.next:t.head=t.tail=null):(t.head=s,s.data=r.slice(o));break}++n}return t.length-=n,i}(e,t);return s}(e,t.buffer,t.decoder),i);var i}function C(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,n.nextTick(L,t,e))}function L(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function M(e,t){for(var i=0,s=e.length;i<s;i++)if(e[i]===t)return i;return-1}y.prototype.read=function(e){p("read",e),e=parseInt(e,10);var t=this._readableState,i=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return p("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?C(this):A(this),null;if(0===(e=w(e,t))&&t.ended)return 0===t.length&&C(this),null;var s,n=t.needReadable;return p("need readable",n),(0===t.length||t.length-e<t.highWaterMark)&&p("length less than watermark",n=!0),t.ended||t.reading?p("reading or ended",n=!1):n&&(p("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=w(i,t))),null===(s=e>0?O(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),i!==e&&t.ended&&C(this)),null!==s&&this.emit("data",s),s},y.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},y.prototype.pipe=function(e,t){var i=this,r=this._readableState;switch(r.pipesCount){case 0:r.pipes=e;break;case 1:r.pipes=[r.pipes,e];break;default:r.pipes.push(e)}r.pipesCount+=1,p("pipe count=%d opts=%j",r.pipesCount,t);var c=(!t||!1!==t.end)&&e!==s.stdout&&e!==s.stderr?h:y;function l(t,s){p("onunpipe"),t===i&&s&&!1===s.hasUnpiped&&(s.hasUnpiped=!0,p("cleanup"),e.removeListener("close",E),e.removeListener("finish",_),e.removeListener("drain",u),e.removeListener("error",g),e.removeListener("unpipe",l),i.removeListener("end",h),i.removeListener("end",y),i.removeListener("data",m),d=!0,!r.awaitDrain||e._writableState&&!e._writableState.needDrain||u())}function h(){p("onend"),e.end()}r.endEmitted?n.nextTick(c):i.once("end",c),e.on("unpipe",l);var u=function(e){return function(){var t=e._readableState;p("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,R(e))}}(i);e.on("drain",u);var d=!1;var f=!1;function m(t){p("ondata"),f=!1,!1!==e.write(t)||f||((1===r.pipesCount&&r.pipes===e||r.pipesCount>1&&-1!==M(r.pipes,e))&&!d&&(p("false write response, pause",i._readableState.awaitDrain),i._readableState.awaitDrain++,f=!0),i.pause())}function g(t){p("onerror",t),y(),e.removeListener("error",g),0===a(e,"error")&&e.emit("error",t)}function E(){e.removeListener("finish",_),y()}function _(){p("onfinish"),e.removeListener("close",E),y()}function y(){p("unpipe"),i.unpipe(e)}return i.on("data",m),function(e,t,i){if("function"==typeof e.prependListener)return e.prependListener(t,i);e._events&&e._events[t]?o(e._events[t])?e._events[t].unshift(i):e._events[t]=[i,e._events[t]]:e.on(t,i)}(e,"error",g),e.once("close",E),e.once("finish",_),e.emit("pipe",i),r.flowing||(p("pipe resume"),i.resume()),e},y.prototype.unpipe=function(e){var t=this._readableState,i={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,i)),this;if(!e){var s=t.pipes,n=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var r=0;r<n;r++)s[r].emit("unpipe",this,i);return this}var o=M(t.pipes,e);return-1===o||(t.pipes.splice(o,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,i)),this},y.prototype.on=function(e,t){var i=c.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var s=this._readableState;s.endEmitted||s.readableListening||(s.readableListening=s.needReadable=!0,s.emittedReadable=!1,s.reading?s.length&&A(this):n.nextTick(D,this))}return i},y.prototype.addListener=y.prototype.on,y.prototype.resume=function(){var e=this._readableState;return e.flowing||(p("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,n.nextTick(N,e,t))}(this,e)),this},y.prototype.pause=function(){return p("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(p("pause"),this._readableState.flowing=!1,this.emit("pause")),this},y.prototype.wrap=function(e){var t=this,i=this._readableState,s=!1;for(var n in e.on("end",(function(){if(p("wrapped end"),i.decoder&&!i.ended){var e=i.decoder.end();e&&e.length&&t.push(e)}t.push(null)})),e.on("data",(function(n){(p("wrapped data"),i.decoder&&(n=i.decoder.write(n)),i.objectMode&&null==n)||(i.objectMode||n&&n.length)&&(t.push(n)||(s=!0,e.pause()))})),e)void 0===this[n]&&"function"==typeof e[n]&&(this[n]=function(t){return function(){return e[t].apply(e,arguments)}}(n));for(var r=0;r<E.length;r++)e.on(E[r],this.emit.bind(this,E[r]));return this._read=function(t){p("wrapped _read",t),s&&(s=!1,e.resume())},this},Object.defineProperty(y.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),y._fromList=O}).call(this,i(21),i(14))},function(e,t){var i={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==i.call(e)}},function(e,t,i){e.exports=i(15).EventEmitter},function(e,t,i){"use strict";var s=i(31);function n(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var i=this,r=this._readableState&&this._readableState.destroyed,o=this._writableState&&this._writableState.destroyed;return r||o?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||s.nextTick(n,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,(function(e){!t&&e?(s.nextTick(n,i,e),i._writableState&&(i._writableState.errorEmitted=!0)):t&&t(e)})),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,i){"use strict";var s=i(32).Buffer,n=s.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function r(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(s.isEncoding===n||!n(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=c,this.end=l,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=h,this.end=u,t=3;break;default:return this.write=d,void(this.end=p)}this.lastNeed=0,this.lastTotal=0,this.lastChar=s.allocUnsafe(t)}function o(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,i=function(e,t,i){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==i?i:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function c(e,t){if((e.length-t)%2==0){var i=e.toString("utf16le",t);if(i){var s=i.charCodeAt(i.length-1);if(s>=55296&&s<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],i.slice(0,-1)}return i}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function l(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var i=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,i)}return t}function h(e,t){var i=(e.length-t)%3;return 0===i?e.toString("base64",t):(this.lastNeed=3-i,this.lastTotal=3,1===i?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-i))}function u(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function d(e){return e.toString(this.encoding)}function p(e){return e&&e.length?this.write(e):""}t.StringDecoder=r,r.prototype.write=function(e){if(0===e.length)return"";var t,i;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";i=this.lastNeed,this.lastNeed=0}else i=0;return i<e.length?t?t+this.text(e,i):this.text(e,i):t||""},r.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},r.prototype.text=function(e,t){var i=function(e,t,i){var s=t.length-1;if(s<i)return 0;var n=o(t[s]);if(n>=0)return n>0&&(e.lastNeed=n-1),n;if(--s<i||-2===n)return 0;if((n=o(t[s]))>=0)return n>0&&(e.lastNeed=n-2),n;if(--s<i||-2===n)return 0;if((n=o(t[s]))>=0)return n>0&&(2===n?n=0:e.lastNeed=n-3),n;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=i;var s=e.length-(i-this.lastNeed);return e.copy(this.lastChar,0,s),e.toString("utf8",t,s)},r.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,i){"use strict";e.exports=o;var s=i(20),n=Object.create(i(25));function r(e,t){var i=this._transformState;i.transforming=!1;var s=i.writecb;if(!s)return this.emit("error",new Error("write callback called multiple times"));i.writechunk=null,i.writecb=null,null!=t&&this.push(t),s(e);var n=this._readableState;n.reading=!1,(n.needReadable||n.length<n.highWaterMark)&&this._read(n.highWaterMark)}function o(e){if(!(this instanceof o))return new o(e);s.call(this,e),this._transformState={afterTransform:r.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",a)}function a(){var e=this;"function"==typeof this._flush?this._flush((function(t,i){c(e,t,i)})):c(this,null,null)}function c(e,t,i){if(t)return e.emit("error",t);if(null!=i&&e.push(i),e._writableState.length)throw new Error("Calling transform done when ws.length != 0");if(e._transformState.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}n.inherits=i(22),n.inherits(o,s),o.prototype.push=function(e,t){return this._transformState.needTransform=!1,s.prototype.push.call(this,e,t)},o.prototype._transform=function(e,t,i){throw new Error("_transform() is not implemented")},o.prototype._write=function(e,t,i){var s=this._transformState;if(s.writecb=i,s.writechunk=e,s.writeencoding=t,!s.transforming){var n=this._readableState;(s.needTransform||n.needReadable||n.length<n.highWaterMark)&&this._read(n.highWaterMark)}},o.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},o.prototype._destroy=function(e,t){var i=this;s.prototype._destroy.call(this,e,(function(e){t(e),i.emit("close")}))}},function(e,t,i){"use strict";const s=i(11);class ActivityFlags extends s{}ActivityFlags.FLAGS={INSTANCE:1,JOIN:2,SPECTATE:4,JOIN_REQUEST:8,SYNC:16,PLAY:32},e.exports=ActivityFlags},function(e,t,i){"use strict";const s=i(49),{Events:n}=i(0);e.exports=class MessageCollector extends s{constructor(e,t,i={}){super(e.client,t,i),this.channel=e,this.received=0;const s=e=>{for(const t of e.values())this.handleDispose(t)};this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),0!==this.client.getMaxListeners()&&this.client.setMaxListeners(this.client.getMaxListeners()+1),this.client.on(n.MESSAGE_CREATE,this.handleCollect),this.client.on(n.MESSAGE_DELETE,this.handleDispose),this.client.on(n.MESSAGE_BULK_DELETE,s),this.client.on(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(n.GUILD_DELETE,this._handleGuildDeletion),this.once("end",()=>{this.client.removeListener(n.MESSAGE_CREATE,this.handleCollect),this.client.removeListener(n.MESSAGE_DELETE,this.handleDispose),this.client.removeListener(n.MESSAGE_BULK_DELETE,s),this.client.removeListener(n.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(n.GUILD_DELETE,this._handleGuildDeletion),0!==this.client.getMaxListeners()&&this.client.setMaxListeners(this.client.getMaxListeners()-1)})}collect(e){return e.channel.id!==this.channel.id?null:(this.received++,e.id)}dispose(e){return e.channel.id===this.channel.id?e.id:null}endReason(){return this.options.max&&this.collected.size>=this.options.max?"limit":this.options.maxProcessed&&this.received===this.options.maxProcessed?"processedLimit":null}_handleChannelDeletion(e){e.id===this.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.channel.guild&&e.id===this.channel.guild.id&&this.stop("guildDelete")}}},function(e,t,i){"use strict";const{TypeError:s}=i(3),n=i(2);e.exports=class GuildMemberRoleManager{constructor(e){this.member=e,this.guild=e.guild,Object.defineProperty(this,"client",{value:e.client})}get _roles(){const e=this.guild.roles.everyone;return this.guild.roles.cache.filter(e=>this.member._roles.includes(e.id)).set(e.id,e)}get cache(){return this._roles}get hoist(){const e=this._roles.filter(e=>e.hoist);return e.size?e.reduce((e,t)=>!e||t.comparePositionTo(e)>0?t:e):null}get color(){const e=this._roles.filter(e=>e.color);return e.size?e.reduce((e,t)=>!e||t.comparePositionTo(e)>0?t:e):null}get highest(){return this._roles.reduce((e,t)=>t.comparePositionTo(e)>0?t:e,this._roles.first())}async add(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map(e=>this.guild.roles.resolve(e))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=[...new Set(e.concat(...this._roles.values()))];return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Role, Snowflake or Array or Collection of Roles or Snowflakes",!0);await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].put({reason:t});const i=this.member._clone();return i._roles=[...this._roles.keys(),e.id],i}}async remove(e,t){if(e instanceof n||Array.isArray(e)){if((e=e.map(e=>this.guild.roles.resolve(e))).includes(null))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);const i=this._roles.filter(t=>!e.includes(t));return this.set(i,t)}{if(null===(e=this.guild.roles.resolve(e)))throw new s("INVALID_TYPE","roles","Array or Collection of Roles or Snowflakes",!0);await this.client.api.guilds[this.guild.id].members[this.member.id].roles[e.id].delete({reason:t});const i=this.member._clone(),n=this._roles.filter(t=>t.id!==e.id);return i._roles=[...n.keys()],i}}set(e,t){return this.member.edit({roles:e},t)}clone(){const e=new this.constructor(this.member);return e.member._roles=[...this._roles.keyArray()],e}}},function(e,t,i){"use strict";const s=i(5),n=i(74),r=i(2),o=i(7);e.exports=class Team extends s{constructor(e,t){super(e),this._patch(t)}_patch(e){this.id=e.id,this.name=e.name,this.icon=e.icon||null,this.ownerID=e.owner_user_id||null,this.members=new r;for(const t of e.members){const e=new n(this,t);this.members.set(e.id,e)}}get owner(){return this.members.get(this.ownerID)||null}get createdTimestamp(){return o.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.TeamIcon(this.id,this.icon,{format:e,size:t}):null}toString(){return this.name}toJSON(){return super.toJSON({createdTimestamp:!0})}}},function(e,t,i){"use strict";const s=i(5),{MembershipStates:n}=i(0);e.exports=class TeamMember extends s{constructor(e,t){super(e.client),this.team=e,this._patch(t)}_patch(e){this.permissions=e.permissions,this.membershipState=n[e.membership_state],this.user=this.client.users.add(e.user)}get id(){return this.user.id}toString(){return this.user.toString()}}},function(e,t,i){"use strict";const s=i(2),{ChannelTypes:n}=i(0),r=i(4);class MessageMentions{constructor(e,t,i,r,o){if(Object.defineProperty(this,"client",{value:e.client}),Object.defineProperty(this,"guild",{value:e.guild}),Object.defineProperty(this,"_content",{value:e.content}),this.everyone=Boolean(r),t)if(t instanceof s)this.users=new s(t);else{this.users=new s;for(const i of t){i.member&&e.guild&&e.guild.members.add(Object.assign(i.member,{user:i}));const t=e.client.users.add(i);this.users.set(t.id,t)}}else this.users=new s;if(i)if(i instanceof s)this.roles=new s(i);else{this.roles=new s;for(const t of i){const i=e.channel.guild.roles.cache.get(t);i&&this.roles.set(i.id,i)}}else this.roles=new s;if(this._members=null,this._channels=null,o)if(o instanceof s)this.crosspostedChannels=new s(o);else{this.crosspostedChannels=new s;const e=Object.keys(n);for(const t of o){const i=e[t.type];this.crosspostedChannels.set(t.id,{channelID:t.id,guildID:t.guild_id,type:i?i.toLowerCase():"unknown",name:t.name})}}else this.crosspostedChannels=new s}get members(){return this._members?this._members:this.guild?(this._members=new s,this.users.forEach(e=>{const t=this.guild.member(e);t&&this._members.set(t.user.id,t)}),this._members):null}get channels(){if(this._channels)return this._channels;let e;for(this._channels=new s;null!==(e=this.constructor.CHANNELS_PATTERN.exec(this._content));){const t=this.client.channels.cache.get(e[1]);t&&this._channels.set(t.id,t)}return this._channels}has(e,{ignoreDirect:t=!1,ignoreRoles:s=!1,ignoreEveryone:n=!1}={}){if(!n&&this.everyone)return!0;const r=i(10);if(!s&&e instanceof r)for(const t of this.roles.values())if(e.roles.cache.has(t.id))return!0;if(!t){const t=e.id||e;return this.users.has(t)||this.channels.has(t)||this.roles.has(t)}return!1}toJSON(){return r.flatten(this,{members:!0,channels:!0})}}MessageMentions.EVERYONE_PATTERN=/@(everyone|here)/g,MessageMentions.USERS_PATTERN=/<@!?(\d{17,19})>/g,MessageMentions.ROLES_PATTERN=/<@&(\d{17,19})>/g,MessageMentions.CHANNELS_PATTERN=/<#(\d{17,19})>/g,e.exports=MessageMentions},function(e,t,i){"use strict";const s=i(49),n=i(2),{Events:r}=i(0);class ReactionCollector extends s{constructor(e,t,i={}){super(e.client,t,i),this.message=e,this.users=new n,this.total=0,this.empty=this.empty.bind(this),this._handleChannelDeletion=this._handleChannelDeletion.bind(this),this._handleGuildDeletion=this._handleGuildDeletion.bind(this),this._handleMessageDeletion=this._handleMessageDeletion.bind(this),0!==this.client.getMaxListeners()&&this.client.setMaxListeners(this.client.getMaxListeners()+1),this.client.on(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.on(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.on(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.on(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.on(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.on(r.GUILD_DELETE,this._handleGuildDeletion),this.once("end",()=>{this.client.removeListener(r.MESSAGE_REACTION_ADD,this.handleCollect),this.client.removeListener(r.MESSAGE_REACTION_REMOVE,this.handleDispose),this.client.removeListener(r.MESSAGE_REACTION_REMOVE_ALL,this.empty),this.client.removeListener(r.MESSAGE_DELETE,this._handleMessageDeletion),this.client.removeListener(r.CHANNEL_DELETE,this._handleChannelDeletion),this.client.removeListener(r.GUILD_DELETE,this._handleGuildDeletion),0!==this.client.getMaxListeners()&&this.client.setMaxListeners(this.client.getMaxListeners()-1)}),this.on("collect",(e,t)=>{this.total++,this.users.set(t.id,t)}),this.on("remove",(e,t)=>{this.total--,this.collected.some(e=>e.users.cache.has(t.id))||this.users.delete(t.id)})}collect(e){return e.message.id!==this.message.id?null:ReactionCollector.key(e)}dispose(e,t){return e.message.id!==this.message.id?null:(this.collected.has(ReactionCollector.key(e))&&this.users.has(t.id)&&this.emit("remove",e,t),e.count?null:ReactionCollector.key(e))}empty(){this.total=0,this.collected.clear(),this.users.clear(),this.checkEnd()}endReason(){return this.options.max&&this.total>=this.options.max?"limit":this.options.maxEmojis&&this.collected.size>=this.options.maxEmojis?"emojiLimit":this.options.maxUsers&&this.users.size>=this.options.maxUsers?"userLimit":null}_handleMessageDeletion(e){e.id===this.message.id&&this.stop("messageDelete")}_handleChannelDeletion(e){e.id===this.message.channel.id&&this.stop("channelDelete")}_handleGuildDeletion(e){this.message.guild&&e.id===this.message.guild.id&&this.stop("guildDelete")}static key(e){return e.emoji.id||e.emoji.name}}e.exports=ReactionCollector},function(e,t,i){"use strict";const s=i(6),{Error:n}=i(3),r=i(2);e.exports=class ReactionUserManager extends s{constructor(e,t,i){super(e,t,{name:"User"}),this.reaction=i}async fetch({limit:e=100,after:t,before:i}={}){const s=this.reaction.message,n=await this.client.api.channels[s.channel.id].messages[s.id].reactions[this.reaction.emoji.identifier].get({query:{limit:e,before:i,after:t}}),o=new r;for(const e of n){const t=this.client.users.add(e);this.cache.set(t.id,t),o.set(t.id,t)}return o}remove(e=this.reaction.message.client.user){const t=this.reaction.message,i=t.client.users.resolveID(e);return i?t.client.api.channels[t.channel.id].messages[t.id].reactions[this.reaction.emoji.identifier][i===t.client.user.id?"@me":i].delete().then(()=>this.reaction):Promise.reject(new n("REACTION_RESOLVE_USER"))}}},function(e,t,i){"use strict";const s=i(11);class UserFlags extends s{}UserFlags.FLAGS={DISCORD_EMPLOYEE:1,DISCORD_PARTNER:2,HYPESQUAD_EVENTS:4,BUGHUNTER_LEVEL_1:8,HOUSE_BRAVERY:64,HOUSE_BRILLIANCE:128,HOUSE_BALANCE:256,EARLY_SUPPORTER:512,TEAM_USER:1024,SYSTEM:4096,BUGHUNTER_LEVEL_2:16384,VERIFIED_BOT:65536,VERIFIED_DEVELOPER:1<<17},e.exports=UserFlags},function(e,t,i){"use strict";const s=i(17),{Error:n}=i(3),r=i(2),{browser:o}=i(0),a=i(8);e.exports=class VoiceChannel extends s{_patch(e){super._patch(e),this.bitrate=e.bitrate,this.userLimit=e.user_limit}get members(){const e=new r;for(const t of this.guild.voiceStates.cache.values())t.channelID===this.id&&t.member&&e.set(t.id,t.member);return e}get full(){return this.userLimit>0&&this.members.size>=this.userLimit}get deletable(){return super.deletable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get editable(){return this.manageable&&this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)}get joinable(){return!o&&(!!this.viewable&&(!!this.permissionsFor(this.client.user).has(a.FLAGS.CONNECT,!1)&&!(this.full&&!this.permissionsFor(this.client.user).has(a.FLAGS.MOVE_MEMBERS,!1))))}get speakable(){return this.permissionsFor(this.client.user).has(a.FLAGS.SPEAK,!1)}setBitrate(e,t){return this.edit({bitrate:e},t)}setUserLimit(e,t){return this.edit({userLimit:e},t)}join(){return o?Promise.reject(new n("VOICE_NO_BROWSER")):this.client.voice.joinChannel(this)}leave(){if(o)return;const e=this.client.voice.connections.get(this.guild.id);e&&e.channel.id===this.id&&e.disconnect()}}},function(e,t,i){"use strict";const s=i(17);e.exports=class CategoryChannel extends s{get children(){return this.guild.channels.cache.filter(e=>e.parentID===this.id)}}},function(e,t,i){"use strict";const s=i(41);e.exports=class NewsChannel extends s{_patch(e){super._patch(e),this.rateLimitPerUser=void 0}}},function(e,t,i){"use strict";const s=i(17);e.exports=class StoreChannel extends s{_patch(e){super._patch(e),this.nsfw=e.nsfw}}},function(e,t,i){"use strict";const s=i(54),n=i(12),r=i(2),{PartialTypes:o}=i(0),a=i(7),c=i(4),l={ALL:"ALL",GUILD:"GUILD",CHANNEL:"CHANNEL",USER:"USER",ROLE:"ROLE",INVITE:"INVITE",WEBHOOK:"WEBHOOK",EMOJI:"EMOJI",MESSAGE:"MESSAGE",INTEGRATION:"INTEGRATION",UNKNOWN:"UNKNOWN"},h={ALL:null,GUILD_UPDATE:1,CHANNEL_CREATE:10,CHANNEL_UPDATE:11,CHANNEL_DELETE:12,CHANNEL_OVERWRITE_CREATE:13,CHANNEL_OVERWRITE_UPDATE:14,CHANNEL_OVERWRITE_DELETE:15,MEMBER_KICK:20,MEMBER_PRUNE:21,MEMBER_BAN_ADD:22,MEMBER_BAN_REMOVE:23,MEMBER_UPDATE:24,MEMBER_ROLE_UPDATE:25,MEMBER_MOVE:26,MEMBER_DISCONNECT:27,BOT_ADD:28,ROLE_CREATE:30,ROLE_UPDATE:31,ROLE_DELETE:32,INVITE_CREATE:40,INVITE_UPDATE:41,INVITE_DELETE:42,WEBHOOK_CREATE:50,WEBHOOK_UPDATE:51,WEBHOOK_DELETE:52,EMOJI_CREATE:60,EMOJI_UPDATE:61,EMOJI_DELETE:62,MESSAGE_DELETE:72,MESSAGE_BULK_DELETE:73,MESSAGE_PIN:74,MESSAGE_UNPIN:75,INTEGRATION_CREATE:80,INTEGRATION_UPDATE:81,INTEGRATION_DELETE:82};class GuildAuditLogs{constructor(e,t){if(t.users)for(const i of t.users)e.client.users.add(i);if(this.webhooks=new r,t.webhooks)for(const i of t.webhooks)this.webhooks.set(i.id,new n(e.client,i));if(this.integrations=new r,t.integrations)for(const i of t.integrations)this.integrations.set(i.id,new s(e.client,i,e));this.entries=new r;for(const i of t.audit_log_entries){const t=new GuildAuditLogsEntry(this,e,i);this.entries.set(t.id,t)}}static build(...e){const t=new GuildAuditLogs(...e);return Promise.all(t.entries.map(e=>e.target)).then(()=>t)}static targetType(e){return e<10?l.GUILD:e<20?l.CHANNEL:e<30?l.USER:e<40?l.ROLE:e<50?l.INVITE:e<60?l.WEBHOOK:e<70?l.EMOJI:e<80?l.MESSAGE:e<90?l.INTEGRATION:l.UNKNOWN}static actionType(e){return[h.CHANNEL_CREATE,h.CHANNEL_OVERWRITE_CREATE,h.MEMBER_BAN_REMOVE,h.BOT_ADD,h.ROLE_CREATE,h.INVITE_CREATE,h.WEBHOOK_CREATE,h.EMOJI_CREATE,h.MESSAGE_PIN,h.INTEGRATION_CREATE].includes(e)?"CREATE":[h.CHANNEL_DELETE,h.CHANNEL_OVERWRITE_DELETE,h.MEMBER_KICK,h.MEMBER_PRUNE,h.MEMBER_BAN_ADD,h.MEMBER_DISCONNECT,h.ROLE_DELETE,h.INVITE_DELETE,h.WEBHOOK_DELETE,h.EMOJI_DELETE,h.MESSAGE_DELETE,h.MESSAGE_BULK_DELETE,h.MESSAGE_UNPIN,h.INTEGRATION_DELETE].includes(e)?"DELETE":[h.GUILD_UPDATE,h.CHANNEL_UPDATE,h.CHANNEL_OVERWRITE_UPDATE,h.MEMBER_UPDATE,h.MEMBER_ROLE_UPDATE,h.MEMBER_MOVE,h.ROLE_UPDATE,h.INVITE_UPDATE,h.WEBHOOK_UPDATE,h.EMOJI_UPDATE,h.INTEGRATION_UPDATE].includes(e)?"UPDATE":"ALL"}toJSON(){return c.flatten(this)}}class GuildAuditLogsEntry{constructor(e,t,i){const r=GuildAuditLogs.targetType(i.action_type);switch(this.targetType=r,this.actionType=GuildAuditLogs.actionType(i.action_type),this.action=Object.keys(h).find(e=>h[e]===i.action_type),this.reason=i.reason||null,this.executor=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.user_id}):t.client.users.cache.get(i.user_id),this.changes=i.changes?i.changes.map(e=>({key:e.key,old:e.old_value,new:e.new_value})):null,this.id=i.id,this.extra=null,i.action_type){case h.MEMBER_PRUNE:this.extra={removed:Number(i.options.members_removed),days:Number(i.options.delete_member_days)};break;case h.MEMBER_MOVE:case h.MESSAGE_DELETE:case h.MESSAGE_BULK_DELETE:this.extra={channel:t.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},count:Number(i.options.count)};break;case h.MESSAGE_PIN:case h.MESSAGE_UNPIN:this.extra={channel:t.client.channels.cache.get(i.options.channel_id)||{id:i.options.channel_id},messageID:i.options.message_id};break;case h.MEMBER_DISCONNECT:this.extra={count:Number(i.options.count)};break;case h.CHANNEL_OVERWRITE_CREATE:case h.CHANNEL_OVERWRITE_UPDATE:case h.CHANNEL_OVERWRITE_DELETE:switch(i.options.type){case"member":this.extra=t.members.cache.get(i.options.id)||{id:i.options.id,type:"member"};break;case"role":this.extra=t.roles.cache.get(i.options.id)||{id:i.options.id,name:i.options.role_name,type:"role"}}}this.target=null,r===l.UNKNOWN?(this.target=this.changes.reduce((e,t)=>(e[t.key]=t.new||t.old,e),{}),this.target.id=i.target_id):r===l.USER&&i.target_id?this.target=t.client.options.partials.includes(o.USER)?t.client.users.add({id:i.target_id}):t.client.users.cache.get(i.target_id):r===l.GUILD?this.target=t.client.guilds.cache.get(i.target_id):r===l.WEBHOOK?this.target=e.webhooks.get(i.target_id)||new n(t.client,this.changes.reduce((e,t)=>(e[t.key]=t.new||t.old,e),{id:i.target_id,guild_id:t.id})):r===l.INVITE?this.target=t.members.fetch(t.client.user.id).then(e=>{if(e.permissions.has("MANAGE_GUILD")){const e=this.changes.find(e=>"code"===e.key);return t.fetchInvites().then(t=>{this.target=t.find(t=>t.code===(e.new||e.old))})}return this.target=this.changes.reduce((e,t)=>(e[t.key]=t.new||t.old,e),{}),this.target}):r===l.MESSAGE?this.target=i.action_type===h.MESSAGE_BULK_DELETE?t.channels.cache.get(i.target_id)||{id:i.target_id}:t.client.users.cache.get(i.target_id):r===l.INTEGRATION?this.target=e.integrations.get(i.target_id)||new s(t.client,this.changes.reduce((e,t)=>(e[t.key]=t.new||t.old,e),{id:i.target_id}),t):i.target_id&&(this.target=t[`${r.toLowerCase()}s`].cache.get(i.target_id)||{id:i.target_id})}get createdTimestamp(){return a.deconstruct(this.id).timestamp}get createdAt(){return new Date(this.createdTimestamp)}toJSON(){return c.flatten(this,{createdTimestamp:!0})}}GuildAuditLogs.Actions=h,GuildAuditLogs.Targets=l,GuildAuditLogs.Entry=GuildAuditLogsEntry,e.exports=GuildAuditLogs},function(e,t,i){"use strict";const s=i(6),n=i(17),r=i(42),{ChannelTypes:o}=i(0);e.exports=class GuildChannelManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e){const t=this.cache.get(e.id);return t||(this.cache.set(e.id,e),e)}async create(e,t={}){let{type:i,topic:s,nsfw:n,bitrate:a,userLimit:c,parent:l,permissionOverwrites:h,position:u,rateLimitPerUser:d,reason:p}=t;l&&(l=this.client.channels.resolveID(l)),h&&(h=h.map(e=>r.resolve(e,this.guild)));const f=await this.client.api.guilds(this.guild.id).channels.post({data:{name:e,topic:s,type:i?o[i.toUpperCase()]:o.TEXT,nsfw:n,bitrate:a,user_limit:c,parent_id:l,position:u,permission_overwrites:h,rate_limit_per_user:d},reason:p});return this.client.actions.ChannelCreate.handle(f).channel}}},function(e,t,i){"use strict";const s=i(6),{Error:n,TypeError:r}=i(3),o=i(10),a=i(2),{Events:c,OPCodes:l}=i(0);e.exports=class GuildMemberManager extends s{constructor(e,t){super(e.client,t,o),this.guild=e}add(e,t=!0){return super.add(e,t,{id:e.user.id,extras:[this.guild]})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return i?super.resolve(i):null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}fetch(e){if(!e)return this._fetchMany();const t=this.client.users.resolveID(e);if(t)return this._fetchSingle({user:t,cache:!0});if(e.user){if(Array.isArray(e.user))return e.user=e.user.map(e=>this.client.users.resolveID(e)),this._fetchMany(e);if(e.user=this.client.users.resolveID(e.user),!e.limit&&!e.withPresences)return this._fetchSingle(e)}return this._fetchMany(e)}prune({days:e=7,dry:t=!1,count:i=!0,reason:s}={}){if("number"!=typeof e)throw new r("PRUNE_DAYS_TYPE");return this.client.api.guilds(this.guild.id).prune[t?"get":"post"]({query:{days:e,compute_prune_count:i},reason:s}).then(e=>e.pruned)}ban(e,t={days:0}){t.days&&(t["delete-message-days"]=t.days);const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].put({query:t}).then(()=>{if(e instanceof o)return e;const t=this.client.users.resolve(i);if(t){return this.resolve(t)||t}return i}):Promise.reject(new n("BAN_RESOLVE_ID",!0))}unban(e,t){const i=this.client.users.resolveID(e);return i?this.client.api.guilds(this.guild.id).bans[i].delete({reason:t}).then(()=>this.client.users.resolve(e)):Promise.reject(new n("BAN_RESOLVE_ID"))}_fetchSingle({user:e,cache:t}){const i=this.cache.get(e);return i&&!i.partial?Promise.resolve(i):this.client.api.guilds(this.guild.id).members(e).get().then(e=>this.add(e,t))}_fetchMany({limit:e=0,withPresences:t=!1,user:i,query:s,time:r=12e4}={}){return new Promise((o,h)=>{if(!(this.guild.memberCount!==this.cache.size||s||e||t||i))return void o(this.cache);s||i||(s=""),this.guild.shard.send({op:l.REQUEST_GUILD_MEMBERS,d:{guild_id:this.guild.id,presences:t,user_ids:i,query:s,limit:e}});const u=new a,d=s||e||t||i,p=(t,s)=>{if(s.id===this.guild.id){f.refresh();for(const e of t.values())d&&u.set(e.id,e);if(this.guild.memberCount<=this.cache.size||d&&t.size<1e3||e&&u.size>=e){this.guild.client.removeListener(c.GUILD_MEMBERS_CHUNK,p);let e=d?u:this.cache;i&&!Array.isArray(i)&&e.size&&(e=e.first()),o(e)}}},f=this.guild.client.setTimeout(()=>{this.guild.client.removeListener(c.GUILD_MEMBERS_CHUNK,p),h(new n("GUILD_MEMBERS_TIMEOUT"))},r);this.guild.client.on(c.GUILD_MEMBERS_CHUNK,p)})}}},function(e,t,i){"use strict";const s=i(6),{Presence:n}=i(13);e.exports=class PresenceManager extends s{constructor(e,t){super(e,t,n)}add(e,t){const i=this.cache.get(e.user.id);return i?i.patch(e):super.add(e,t,{id:e.user.id})}resolve(e){const t=super.resolve(e);if(t)return t;const i=this.client.users.resolveID(e);return super.resolve(i)||null}resolveID(e){const t=super.resolveID(e);if(t)return t;const i=this.client.users.resolveID(e);return this.cache.has(i)?i:null}}},function(e,t,i){"use strict";const s=i(6),n=i(19),r=i(8),{resolveColor:o}=i(4);e.exports=class RoleManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e,t){return super.add(e,t,{extras:[this.guild]})}async fetch(e,t=!0){if(e){const t=this.cache.get(e);if(t)return t}const i=await this.client.api.guilds(this.guild.id).roles.get();for(const e of i)this.add(e,t);return e?this.cache.get(e)||null:this}create({data:e={},reason:t}={}){return e.color&&(e.color=o(e.color)),e.permissions&&(e.permissions=r.resolve(e.permissions)),this.guild.client.api.guilds(this.guild.id).roles.post({data:e,reason:t}).then(i=>{const{role:s}=this.client.actions.GuildRoleCreate.handle({guild_id:this.guild.id,role:i});return e.position?s.setPosition(e.position,t):s})}get everyone(){return this.cache.get(this.guild.id)}get highest(){return this.cache.reduce((e,t)=>t.comparePositionTo(e)>0?t:e,this.cache.first())}}},function(e,t,i){"use strict";const s=i(11);class SystemChannelFlags extends s{}SystemChannelFlags.FLAGS={WELCOME_MESSAGE_DISABLED:1,BOOST_MESSAGE_DISABLED:2},e.exports=SystemChannelFlags},function(e,t,i){"use strict";const{Presence:s}=i(13),{TypeError:n}=i(3),r=i(2),{ActivityTypes:o,OPCodes:a}=i(0);e.exports=class ClientPresence extends s{constructor(e,t={}){super(e,Object.assign(t,{status:"online",user:{id:null}}))}async set(e){const t=await this._parse(e);if(this.patch(t),void 0===e.shardID)this.client.ws.broadcast({op:a.STATUS_UPDATE,d:t});else if(Array.isArray(e.shardID))for(const i of e.shardID)this.client.ws.shards.get(i).send({op:a.STATUS_UPDATE,d:t});else this.client.ws.shards.get(e.shardID).send({op:a.STATUS_UPDATE,d:t});return this}async _parse({status:e,since:t,afk:i,activity:s}){const a=s&&(s.application?s.application.id||s.application:null);let c=new r;if(s){if("string"!=typeof s.name)throw new n("INVALID_TYPE","name","string");if(s.type||(s.type=0),s.assets&&a)try{const e=await this.client.api.oauth2.applications(a).assets.get();for(const t of e)c.set(t.name,t.id)}catch{}}const l={afk:null!=i&&i,since:null!=t?t:null,status:e||this.status,game:s?{type:s.type,name:s.name,url:s.url,details:s.details||void 0,state:s.state||void 0,assets:s.assets?{large_text:s.assets.largeText||void 0,small_text:s.assets.smallText||void 0,large_image:c.get(s.assets.largeImage)||s.assets.largeImage,small_image:c.get(s.assets.smallImage)||s.assets.smallImage}:void 0,timestamps:s.timestamps||void 0,party:s.party||void 0,application_id:a||void 0,secrets:s.secrets||void 0,instance:s.instance||void 0}:null};return(e||i||t)&&!s&&(l.game=this.activities[0]||null),l.game&&(l.game.type="number"==typeof l.game.type?l.game.type:o.indexOf(l.game.type)),l}}},function(e,t,i){"use strict";const{browser:s}=i(0);let n,r;try{n=i(161),n.pack||(n=null)}catch{}s?(r=window.TextDecoder,t.WebSocket=window.WebSocket):(r=i(162).TextDecoder,t.WebSocket=i(165));const o=new r;t.encoding=n?"etf":"json",t.pack=n?n.pack:JSON.stringify,t.unpack=(e,i)=>"json"===t.encoding||"json"===i?("string"!=typeof e&&(e=o.decode(e)),JSON.parse(e)):(Buffer.isBuffer(e)||(e=Buffer.from(new Uint8Array(e))),n.unpack(e)),t.create=(e,i={},...n)=>{const[r,o]=e.split("?");i.encoding=t.encoding,i=new URLSearchParams(i),o&&new URLSearchParams(o).forEach((e,t)=>i.set(t,e));const a=new t.WebSocket(`${r}?${i}`,...n);return s&&(a.binaryType="arraybuffer"),a};for(const e of["CONNECTING","OPEN","CLOSING","CLOSED"])t[e]=t.WebSocket[e]},function(e,t,i){"use strict";const{WSEvents:s}=i(0),n={};for(const e of Object.keys(s))try{n[e]=i(167)(`./${e}.js`)}catch{}e.exports=n},function(e,t,i){"use strict";const s=i(9),n=i(23);class ClientUser extends(n.get("User")){constructor(e,t){super(e,t),this._typing=new Map}_patch(e){super._patch(e),"verified"in e&&(this.verified=e.verified),"mfa_enabled"in e?this.mfaEnabled="boolean"==typeof e.mfa_enabled?e.mfa_enabled:null:void 0===this.mfaEnabled&&(this.mfaEnabled=null),e.token&&(this.client.token=e.token)}get presence(){return this.client.presence}edit(e){return this.client.api.users("@me").patch({data:e}).then(e=>{this.client.token=e.token;const{updated:t}=this.client.actions.UserUpdate.handle(e);return t||this})}setUsername(e){return this.edit({username:e})}async setAvatar(e){return this.edit({avatar:await s.resolveImage(e)})}setPresence(e){return this.client.presence.set(e)}setStatus(e,t){return this.setPresence({status:e,shardID:t})}setActivity(e,t={}){if(!e)return this.setPresence({activity:null,shardID:t.shardID});const i=Object.assign({},t,"object"==typeof e?e:{name:e});return this.setPresence({activity:i,shardID:i.shardID})}setAFK(e){return this.setPresence({afk:e})}}e.exports=ClientUser},function(e,t,i){"use strict";const s=i(6),n=i(16),{Events:r}=i(0);e.exports=class ChannelManager extends s{constructor(e,t){super(e,t,n)}add(e,t,i=!0){const s=this.cache.get(e.id);if(s)return s._patch&&i&&s._patch(e),t&&t.channels.add(s),s;const o=n.create(this.client,e,t);return o?(i&&this.cache.set(o.id,o),o):(this.client.emit(r.DEBUG,`Failed to find guild, or unknown type for channel ${e.id} ${e.type}`),null)}remove(e){const t=this.cache.get(e);t.guild&&t.guild.channels.cache.delete(e),this.cache.delete(e)}async fetch(e,t=!0){const i=this.cache.get(e);if(i&&!i.partial)return i;const s=await this.client.api.channels(e).get();return this.add(s,null,t)}}},function(e,t,i){"use strict";const s=i(6),n=i(53),r=i(17),o=i(24),a=i(10),c=i(18),l=i(19),{Events:h,VerificationLevels:u,DefaultMessageNotifications:d,ExplicitContentFilterLevels:p}=i(0),f=i(9),m=i(8),{resolveColor:g}=i(4);e.exports=class GuildManager extends s{constructor(e,t){super(e,t,n)}resolve(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolve(e.guild):super.resolve(e)}resolveID(e){return e instanceof r||e instanceof a||e instanceof o||e instanceof l||e instanceof c&&e.guild?super.resolveID(e.guild.id):super.resolveID(e)}async create(e,{channels:t=[],defaultMessageNotifications:i,explicitContentFilter:s,icon:n=null,region:r,roles:o=[],verificationLevel:a}={}){n=await f.resolveImage(n),void 0!==a&&"number"!=typeof a&&(a=u.indexOf(a)),void 0!==i&&"number"!=typeof i&&(i=d.indexOf(i)),void 0!==s&&"number"!=typeof s&&(s=p.indexOf(s));for(const e of t)if(e.parent_id=e.parentID,delete e.parentID,e.permissionOverwrites){for(const t of e.permissionOverwrites)t.allow&&(t.allow=m.resolve(t.allow)),t.deny&&(t.deny=m.resolve(t.deny));e.permission_overwrites=e.permissionOverwrites,delete e.permissionOverwrites}for(const e of o)e.color&&(e.color=g(e.color)),e.permissions&&(e.permissions=m.resolve(e.permissions));return new Promise((c,l)=>this.client.api.guilds.post({data:{name:e,region:r,icon:n,verification_level:a,default_message_notifications:i,explicit_content_filter:s,channels:t,roles:o}}).then(e=>{if(this.client.guilds.cache.has(e.id))return c(this.client.guilds.cache.get(e.id));const t=s=>{s.id===e.id&&(this.client.removeListener(h.GUILD_CREATE,t),this.client.clearTimeout(i),c(s))};this.client.on(h.GUILD_CREATE,t);const i=this.client.setTimeout(()=>{this.client.removeListener(h.GUILD_CREATE,t),c(this.client.guilds.add(e))},1e4)},l))}}},function(e,t,i){"use strict";const s=i(6),n=i(10),r=i(28),o=i(26);e.exports=class UserManager extends s{constructor(e,t){super(e,t,o)}resolve(e){return e instanceof n?e.user:e instanceof r?e.author:super.resolve(e)}resolveID(e){return e instanceof n?e.user.id:e instanceof r?e.author.id:super.resolveID(e)}async fetch(e,t=!0){const i=this.cache.get(e);if(i&&!i.partial)return i;const s=await this.client.api.users(e).get();return this.add(s,t)}}},function(e,t,i){"use strict";const s=i(11);class Intents extends s{}Intents.FLAGS={GUILDS:1,GUILD_MEMBERS:2,GUILD_BANS:4,GUILD_EMOJIS:8,GUILD_INTEGRATIONS:16,GUILD_WEBHOOKS:32,GUILD_INVITES:64,GUILD_VOICE_STATES:128,GUILD_PRESENCES:256,GUILD_MESSAGES:512,GUILD_MESSAGE_REACTIONS:1024,GUILD_MESSAGE_TYPING:2048,DIRECT_MESSAGES:4096,DIRECT_MESSAGE_REACTIONS:8192,DIRECT_MESSAGE_TYPING:16384},Intents.PRIVILEGED=Intents.FLAGS.GUILD_MEMBERS|Intents.FLAGS.GUILD_PRESENCES,Intents.ALL=Object.values(Intents.FLAGS).reduce((e,t)=>e|t,0),Intents.NON_PRIVILEGED=Intents.ALL&~Intents.PRIVILEGED,e.exports=Intents},function(e,t,i){"use strict";const s=i(4);e.exports={BaseClient:i(37),Client:i(107),Shard:i(206),ShardClientUtil:i(207),ShardingManager:i(208),WebhookClient:i(48),ActivityFlags:i(70),BitField:i(11),Collection:i(2),Constants:i(0),DataResolver:i(9),BaseManager:i(6),DiscordAPIError:i(61),HTTPError:i(62),MessageFlags:i(47),Intents:i(96),Permissions:i(8),Speaking:i(209),Snowflake:i(7),SnowflakeUtil:i(7),Structures:i(23),SystemChannelFlags:i(88),UserFlags:i(78),Util:s,version:i(58).version,ChannelManager:i(93),GuildChannelManager:i(84),GuildEmojiManager:i(57),GuildEmojiRoleManager:i(63),GuildMemberManager:i(85),GuildMemberRoleManager:i(72),GuildManager:i(94),ReactionUserManager:i(77),MessageManager:i(34),PresenceManager:i(86),RoleManager:i(87),UserManager:i(95),discordSort:s.discordSort,escapeMarkdown:s.escapeMarkdown,fetchRecommendedShards:s.fetchRecommendedShards,resolveColor:s.resolveColor,resolveString:s.resolveString,splitMessage:s.splitMessage,Base:i(5),Activity:i(13).Activity,APIMessage:i(30),BaseGuildEmoji:i(40),CategoryChannel:i(80),Channel:i(16),ClientApplication:i(50),get ClientUser(){return i(92)},Collector:i(49),DMChannel:i(39),Emoji:i(29),Guild:i(53),GuildAuditLogs:i(83),GuildChannel:i(17),GuildEmoji:i(24),GuildMember:i(10),GuildPreview:i(55),Integration:i(54),Invite:i(18),Message:i(28),MessageAttachment:i(43),MessageCollector:i(71),MessageEmbed:i(44),MessageMentions:i(75),MessageReaction:i(51),NewsChannel:i(81),PermissionOverwrites:i(42),Presence:i(13).Presence,ClientPresence:i(89),ReactionCollector:i(76),ReactionEmoji:i(52),RichPresenceAssets:i(13).RichPresenceAssets,Role:i(19),StoreChannel:i(82),Team:i(73),TeamMember:i(74),TextChannel:i(41),User:i(26),VoiceChannel:i(79),VoiceRegion:i(56),VoiceState:i(27),Webhook:i(12),WebSocket:i(90)}},function(e,t,i){"use strict";const{register:s}=i(59),n={CLIENT_INVALID_OPTION:(e,t)=>`The ${e} option must be ${t}`,CLIENT_INVALID_PROVIDED_SHARDS:"None of the provided shards were valid.",TOKEN_INVALID:"An invalid token was provided.",TOKEN_MISSING:"Request to use token, but token was unavailable to the client.",WS_CLOSE_REQUESTED:"WebSocket closed due to user request.",WS_CONNECTION_EXISTS:"There is already an existing WebSocket connection.",WS_NOT_OPEN:(e="data")=>`Websocket not open to send ${e}`,BITFIELD_INVALID:"Invalid bitfield flag or number.",SHARDING_INVALID:"Invalid shard settings were provided.",SHARDING_REQUIRED:"This session would have handled too many guilds - Sharding is required.",INVALID_INTENTS:"Invalid intent provided for WebSocket intents.",DISALLOWED_INTENTS:"Privileged intent provided is not enabled or whitelisted.",SHARDING_NO_SHARDS:"No shards have been spawned.",SHARDING_IN_PROCESS:"Shards are still being spawned.",SHARDING_ALREADY_SPAWNED:e=>`Already spawned ${e} shards.`,SHARDING_PROCESS_EXISTS:e=>`Shard ${e} already has an active process.`,SHARDING_READY_TIMEOUT:e=>`Shard ${e}'s Client took too long to become ready.`,SHARDING_READY_DISCONNECTED:e=>`Shard ${e}'s Client disconnected before becoming ready.`,SHARDING_READY_DIED:e=>`Shard ${e}'s process exited before its Client became ready.`,COLOR_RANGE:"Color must be within the range 0 - 16777215 (0xFFFFFF).",COLOR_CONVERT:"Unable to convert color to a number.",EMBED_FIELD_NAME:"MessageEmbed field names may not be empty.",EMBED_FIELD_VALUE:"MessageEmbed field values may not be empty.",FILE_NOT_FOUND:e=>`File could not be found: ${e}`,USER_NO_DMCHANNEL:"No DM Channel exists!",VOICE_INVALID_HEARTBEAT:"Tried to set voice heartbeat but no valid interval was specified.",VOICE_USER_MISSING:"Couldn't resolve the user to create stream.",VOICE_JOIN_CHANNEL:(e=!1)=>`You do not have permission to join this voice channel${e?"; it is full.":"."}`,VOICE_CONNECTION_TIMEOUT:"Connection not established within 15 seconds.",VOICE_TOKEN_ABSENT:"Token not provided from voice server packet.",VOICE_SESSION_ABSENT:"Session ID not supplied.",VOICE_INVALID_ENDPOINT:"Invalid endpoint received.",VOICE_NO_BROWSER:"Voice connections are not available in browsers.",VOICE_CONNECTION_ATTEMPTS_EXCEEDED:e=>`Too many connection attempts (${e}).`,VOICE_JOIN_SOCKET_CLOSED:"Tried to send join packet, but the WebSocket is not open.",VOICE_PLAY_INTERFACE_NO_BROADCAST:"A broadcast cannot be played in this context.",VOICE_PLAY_INTERFACE_BAD_TYPE:"Unknown stream type",VOICE_PRISM_DEMUXERS_NEED_STREAM:"To play a webm/ogg stream, you need to pass a ReadableStream.",VOICE_STATE_UNCACHED_MEMBER:"The member of this voice state is uncached.",VOICE_STATE_NOT_OWN:"You cannot self-deafen/mute on VoiceStates that do not belong to the ClientUser.",VOICE_STATE_INVALID_TYPE:e=>`${e} must be a boolean.`,UDP_SEND_FAIL:"Tried to send a UDP packet, but there is no socket available.",UDP_ADDRESS_MALFORMED:"Malformed UDP address or port.",UDP_CONNECTION_EXISTS:"There is already an existing UDP connection.",REQ_RESOURCE_TYPE:"The resource must be a string, Buffer or a valid file stream.",IMAGE_FORMAT:e=>`Invalid image format: ${e}`,IMAGE_SIZE:e=>`Invalid image size: ${e}`,MESSAGE_BULK_DELETE_TYPE:"The messages must be an Array, Collection, or number.",MESSAGE_NONCE_TYPE:"Message nonce must fit in an unsigned 64-bit integer.",TYPING_COUNT:"Count must be at least 1",SPLIT_MAX_LEN:"Chunk exceeds the max length and contains no split characters.",BAN_RESOLVE_ID:(e=!1)=>`Couldn't resolve the user ID to ${e?"ban":"unban"}.`,FETCH_BAN_RESOLVE_ID:"Couldn't resolve the user ID to fetch the ban.",PRUNE_DAYS_TYPE:"Days must be a number",GUILD_CHANNEL_RESOLVE:"Could not resolve channel to a guild channel.",GUILD_VOICE_CHANNEL_RESOLVE:"Could not resolve channel to a guild voice channel.",GUILD_CHANNEL_ORPHAN:"Could not find a parent to this guild channel.",GUILD_OWNED:"Guild is owned by the client.",GUILD_MEMBERS_TIMEOUT:"Members didn't arrive in time.",GUILD_UNCACHED_ME:"The client user as a member of this guild is uncached.",INVALID_TYPE:(e,t,i=!1)=>`Supplied ${e} is not a${i?"n":""} ${t}.`,WEBHOOK_MESSAGE:"The message was not sent by a webhook.",EMOJI_TYPE:"Emoji must be a string or GuildEmoji/ReactionEmoji",EMOJI_MANAGED:"Emoji is managed and has no Author.",MISSING_MANAGE_EMOJIS_PERMISSION:e=>`Client must have Manage Emoji permission in guild ${e} to see emoji authors.`,REACTION_RESOLVE_USER:"Couldn't resolve the user ID to remove from the reaction.",VANITY_URL:"This guild does not have the VANITY_URL feature enabled.",DELETE_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot delete them",FETCH_GROUP_DM_CHANNEL:"Bots don't have access to Group DM Channels and cannot fetch them"};for(const[e,t]of Object.entries(n))s(e,t)},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0});class Collection extends Map{constructor(e){super(e),Object.defineProperty(this,"_array",{value:null,writable:!0,configurable:!0}),Object.defineProperty(this,"_keyArray",{value:null,writable:!0,configurable:!0})}get(e){return super.get(e)}set(e,t){return this._array=null,this._keyArray=null,super.set(e,t)}has(e){return super.has(e)}delete(e){return this._array=null,this._keyArray=null,super.delete(e)}clear(){return super.clear()}array(){return this._array&&this._array.length===this.size||(this._array=[...this.values()]),this._array}keyArray(){return this._keyArray&&this._keyArray.length===this.size||(this._keyArray=[...this.keys()]),this._keyArray}first(e){if(void 0===e)return this.values().next().value;if(e<0)return this.last(-1*e);e=Math.min(this.size,e);const t=this.values();return Array.from({length:e},()=>t.next().value)}firstKey(e){if(void 0===e)return this.keys().next().value;if(e<0)return this.lastKey(-1*e);e=Math.min(this.size,e);const t=this.keys();return Array.from({length:e},()=>t.next().value)}last(e){const t=this.array();return void 0===e?t[t.length-1]:e<0?this.first(-1*e):e?t.slice(-e):[]}lastKey(e){const t=this.keyArray();return void 0===e?t[t.length-1]:e<0?this.firstKey(-1*e):e?t.slice(-e):[]}random(e){let t=this.array();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},()=>t.splice(Math.floor(Math.random()*t.length),1)[0])):[]}randomKey(e){let t=this.keyArray();return void 0===e?t[Math.floor(Math.random()*t.length)]:0!==t.length&&e?(t=t.slice(),Array.from({length:e},()=>t.splice(Math.floor(Math.random()*t.length),1)[0])):[]}find(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return i}findKey(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return t}sweep(e,t){void 0!==t&&(e=e.bind(t));const i=this.size;for(const[t,i]of this)e(i,t,this)&&this.delete(t);return i-this.size}filter(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)e(s,t,this)&&i.set(t,s);return i}partition(e,t){void 0!==t&&(e=e.bind(t));const i=[new this.constructor[Symbol.species],new this.constructor[Symbol.species]];for(const[t,s]of this)e(s,t,this)?i[0].set(t,s):i[1].set(t,s);return i}flatMap(e,t){const i=this.map(e,t);return(new this.constructor[Symbol.species]).concat(...i)}map(e,t){void 0!==t&&(e=e.bind(t));const i=this.entries();return Array.from({length:this.size},()=>{const[t,s]=i.next().value;return e(s,t,this)})}mapValues(e,t){void 0!==t&&(e=e.bind(t));const i=new this.constructor[Symbol.species];for(const[t,s]of this)i.set(t,e(s,t,this));return i}some(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(e(i,t,this))return!0;return!1}every(e,t){void 0!==t&&(e=e.bind(t));for(const[t,i]of this)if(!e(i,t,this))return!1;return!0}reduce(e,t){let i;if(void 0!==t){i=t;for(const[t,s]of this)i=e(i,s,t,this);return i}let s=!0;for(const[t,n]of this)s?(i=n,s=!1):i=e(i,n,t,this);if(s)throw new TypeError("Reduce of empty collection with no initial value");return i}each(e,t){return this.forEach(e,t),this}tap(e,t){return void 0!==t&&(e=e.bind(t)),e(this),this}clone(){return new this.constructor[Symbol.species](this)}concat(...e){const t=this.clone();for(const i of e)for(const[e,s]of i)t.set(e,s);return t}equals(e){if(!e)return!1;if(this===e)return!0;if(this.size!==e.size)return!1;for(const[t,i]of this)if(!e.has(t)||i!==e.get(t))return!1;return!0}sort(e=((e,t)=>Number(e>t)||Number(e===t)-1)){const t=[...this.entries()];t.sort((t,i)=>e(t[1],i[1],t[0],i[0])),super.clear(),this._array=null,this._keyArray=null;for(const[e,i]of t)super.set(e,i);return this}intersect(e){return e.filter((e,t)=>this.has(t))}difference(e){return e.filter((e,t)=>!this.has(t)).concat(this.filter((t,i)=>!e.has(i)))}sorted(e=((e,t)=>Number(e>t)||Number(e===t)-1)){return new this.constructor[Symbol.species]([...this.entries()]).sort((t,i,s,n)=>e(t,i,s,n))}}t.Collection=Collection,Collection.default=Collection,t.default=Collection,e.exports=Collection},function(e,t,i){"use strict";const s=i(101),n=i(105),r=i(106),{Error:o}=i(3),a=i(2),{Endpoints:c}=i(0);e.exports=class RESTManager{constructor(e,t="Bot"){this.client=e,this.handlers=new a,this.tokenPrefix=t,this.versioned=!0,this.globalTimeout=null,e.options.restSweepInterval>0&&e.setInterval(()=>{this.handlers.sweep(e=>e._inactive)},1e3*e.options.restSweepInterval)}get api(){return n(this)}getAuth(){const e=this.client.token||this.client.accessToken;if(e)return`${this.tokenPrefix} ${e}`;throw new o("TOKEN_MISSING")}get cdn(){return c.CDN(this.client.options.http.cdn)}push(e,t){return new Promise((i,s)=>{e.push({request:t,resolve:i,reject:s,retries:0}).catch(s)})}request(e,t,i={}){const n=new s(this,e,t,i);let o=this.handlers.get(n.route);return o||(o=new r(this),this.handlers.set(n.route,o)),this.push(o,n)}set endpoint(e){this.client.options.http.api=e}}},function(e,t,i){"use strict";const s=i(102),n=i(103),r=i(104),o=i(36),{browser:a,UserAgent:c}=i(0);if(s.Agent)var l=new s.Agent({keepAlive:!0});e.exports=class APIRequest{constructor(e,t,i,s){this.rest=e,this.client=e.client,this.method=t,this.route=s.route,this.options=s;let n="";if(s.query){const e=Object.entries(s.query).filter(([,e])=>null!=e);n=new URLSearchParams(e).toString()}this.path=`${i}${n&&`?${n}`}`}make(){const e=(!1===this.options.versioned?this.client.options.http.api:`${this.client.options.http.api}/v${this.client.options.http.version}`)+this.path;let t,i={};if(!1!==this.options.auth&&(i.Authorization=this.rest.getAuth()),this.options.reason&&(i["X-Audit-Log-Reason"]=encodeURIComponent(this.options.reason)),a||(i["User-Agent"]=c),this.options.headers&&(i=Object.assign(i,this.options.headers)),this.options.files&&this.options.files.length){t=new n;for(const e of this.options.files)e&&e.file&&t.append(e.name,e.file,e.name);void 0!==this.options.data&&t.append("payload_json",JSON.stringify(this.options.data)),a||(i=Object.assign(i,t.getHeaders()))}else null!=this.options.data&&(t=JSON.stringify(this.options.data),i["Content-Type"]="application/json");const s=new r,h=this.client.setTimeout(()=>s.abort(),this.client.options.restRequestTimeout);return o(e,{method:this.method,headers:i,agent:l,body:t,signal:s.signal}).finally(()=>this.client.clearTimeout(h))}}},function(e,t){},function(e,t){e.exports="object"==typeof self?self.FormData:window.FormData},function(e,t,i){"use strict";const{AbortController:s,AbortSignal:n}="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0;e.exports=s,e.exports.AbortSignal=n,e.exports.default=s},function(e,t,i){"use strict";const s=()=>{},n=["get","post","delete","patch","put"],r=["toString","valueOf","inspect","constructor",Symbol.toPrimitive,Symbol.for("nodejs.util.inspect.custom")];e.exports=function(e){const t=[""],i={get(o,a){if(r.includes(a))return()=>t.join("/");if(n.includes(a)){const i=[];for(let e=0;e<t.length&&"reactions"!==t[e-1];e++)/\d{16,19}/g.test(t[e])&&!/channels|guilds/.test(t[e-1])?i.push(":id"):i.push(t[e]);return s=>e.request(a,t.join("/"),Object.assign({versioned:e.versioned,route:i.join("/")},s))}return t.push(a),new Proxy(s,i)},apply:(e,n,r)=>(t.push(...r.filter(e=>null!=e)),new Proxy(s,i))};return new Proxy(s,i)}},function(e,t,i){"use strict";const s=i(61),n=i(62),{Events:{RATE_LIMIT:r},browser:o}=i(0),a=i(4);function c(e){return e.headers.get("content-type").startsWith("application/json")?e.json():o?e.blob():e.buffer()}function l(e){return new Date(e).getTime()-Date.now()}e.exports=class RequestHandler{constructor(e){this.manager=e,this.busy=!1,this.queue=[],this.reset=-1,this.remaining=-1,this.limit=-1,this.retryAfter=-1}push(e){return this.busy?(this.queue.push(e),this.run()):this.execute(e)}run(){return 0===this.queue.length?Promise.resolve():this.execute(this.queue.shift())}get limited(){return Boolean(this.manager.globalTimeout)||this.remaining<=0&&Date.now()<this.reset}get _inactive(){return 0===this.queue.length&&!this.limited&&!0!==this.busy}async execute(e){if(this.busy)return this.queue.unshift(e),null;this.busy=!0;const{reject:t,request:i,resolve:o}=e;if(this.limited){const e=this.reset+this.manager.client.options.restTimeOffset-Date.now();this.manager.client.listenerCount(r)&&this.manager.client.emit(r,{timeout:e,limit:this.limit,method:i.method,path:i.path,route:i.route}),this.manager.globalTimeout?await this.manager.globalTimeout:await a.delayFor(e)}let h;try{h=await i.make()}catch(e){return this.busy=!1,t(new n(e.message,e.constructor.name,e.status,i.method,i.path))}if(h&&h.headers){const t=h.headers.get("date"),i=h.headers.get("x-ratelimit-limit"),s=h.headers.get("x-ratelimit-remaining"),n=h.headers.get("x-ratelimit-reset"),r=h.headers.get("retry-after");this.limit=i?Number(i):1/0,this.remaining=s?Number(s):1,this.reset=n?function(e,t){return new Date(1e3*Number(e)).getTime()-l(t)}(n,t):Date.now(),this.retryAfter=r?Number(r):-1,e.request.route.includes("reactions")&&(this.reset=new Date(t).getTime()-l(t)+250),h.headers.get("x-ratelimit-global")&&(this.manager.globalTimeout=a.delayFor(this.retryAfter),await this.manager.globalTimeout,this.manager.globalTimeout=null)}if(this.busy=!1,h.ok){return o(await c(h)),this.run()}if(429===h.status)return this.queue.unshift(e),this.manager.client.emit("debug",`429 hit on route ${e.request.route}`),await a.delayFor(this.retryAfter),this.run();if(h.status>=500&&h.status<600)return e.retries===this.manager.client.options.retryLimit?t(new n(h.statusText,h.constructor.name,h.status,e.request.method,i.path)):(e.retries++,this.queue.unshift(e),this.run());try{const e=await c(h);return h.status>=400&&h.status<500?t(new s(i.path,e,i.method,h.status)):null}catch(e){return t(new n(e.message,e.constructor.name,e.status,i.method,i.path))}}}},function(module,exports,__webpack_require__){"use strict";(function(process){const BaseClient=__webpack_require__(37),ActionsManager=__webpack_require__(108),ClientVoiceManager=__webpack_require__(158),WebSocketManager=__webpack_require__(159),{Error:Error,TypeError:TypeError,RangeError:RangeError}=__webpack_require__(3),ChannelManager=__webpack_require__(93),GuildEmojiManager=__webpack_require__(57),GuildManager=__webpack_require__(94),UserManager=__webpack_require__(95),ShardClientUtil=__webpack_require__(204),ClientApplication=__webpack_require__(50),GuildPreview=__webpack_require__(55),Invite=__webpack_require__(18),VoiceRegion=__webpack_require__(56),Webhook=__webpack_require__(12),Collection=__webpack_require__(2),{Events:Events,browser:browser,DefaultOptions:DefaultOptions}=__webpack_require__(0),DataResolver=__webpack_require__(9),Intents=__webpack_require__(96),Permissions=__webpack_require__(8),Structures=__webpack_require__(23);class Client extends BaseClient{constructor(e={}){super(Object.assign({_tokenType:"Bot"},e));let t=process.env;try{t=__webpack_require__(205).workerData||t}catch{}this.options.shards===DefaultOptions.shards&&"SHARDS"in t&&(this.options.shards=JSON.parse(t.SHARDS)),this.options.shardCount===DefaultOptions.shardCount&&("SHARD_COUNT"in t?this.options.shardCount=Number(t.SHARD_COUNT):Array.isArray(this.options.shards)&&(this.options.shardCount=this.options.shards.length));const i=typeof this.options.shards;"undefined"===i&&"number"==typeof this.options.shardCount&&(this.options.shards=Array.from({length:this.options.shardCount},(e,t)=>t)),"number"===i&&(this.options.shards=[this.options.shards]),Array.isArray(this.options.shards)&&(this.options.shards=[...new Set(this.options.shards.filter(e=>!isNaN(e)&&e>=0&&e<1/0&&e===(0|e)))]),this._validateOptions(),this.ws=new WebSocketManager(this),this.actions=new ActionsManager(this),this.voice=browser?null:new ClientVoiceManager(this),this.shard=!browser&&process.env.SHARDING_MANAGER?ShardClientUtil.singleton(this,process.env.SHARDING_MANAGER_MODE):null,this.users=new UserManager(this),this.guilds=new GuildManager(this),this.channels=new ChannelManager(this);const s=Structures.get("ClientPresence");this.presence=new s(this),Object.defineProperty(this,"token",{writable:!0}),browser||this.token||!("DISCORD_TOKEN"in process.env)?this.token=null:this.token=process.env.DISCORD_TOKEN,this.user=null,this.readyAt=null,this.options.messageSweepInterval>0&&this.setInterval(this.sweepMessages.bind(this),1e3*this.options.messageSweepInterval)}get emojis(){const e=new GuildEmojiManager({client:this});for(const t of this.guilds.cache.values())if(t.available)for(const i of t.emojis.cache.values())e.cache.set(i.id,i);return e}get readyTimestamp(){return this.readyAt?this.readyAt.getTime():null}get uptime(){return this.readyAt?Date.now()-this.readyAt:null}async login(e=this.token){if(!e||"string"!=typeof e)throw new Error("TOKEN_INVALID");this.token=e=e.replace(/^(Bot|Bearer)\s*/i,""),this.emit(Events.DEBUG,`Provided token: ${e.split(".").map((e,t)=>t>1?e.replace(/./g,"*"):e).join(".")}`),this.options.presence&&(this.options.ws.presence=await this.presence._parse(this.options.presence)),this.emit(Events.DEBUG,"Preparing to connect to the gateway...");try{return await this.ws.connect(),this.token}catch(e){throw this.destroy(),e}}destroy(){super.destroy(),this.ws.destroy(),this.token=null}fetchInvite(e){const t=DataResolver.resolveInviteCode(e);return this.api.invites(t).get({query:{with_counts:!0}}).then(e=>new Invite(this,e))}fetchWebhook(e,t){return this.api.webhooks(e,t).get().then(e=>new Webhook(this,e))}fetchVoiceRegions(){return this.api.voice.regions.get().then(e=>{const t=new Collection;for(const i of e)t.set(i.id,new VoiceRegion(i));return t})}sweepMessages(e=this.options.messageCacheLifetime){if("number"!=typeof e||isNaN(e))throw new TypeError("INVALID_TYPE","lifetime","number");if(e<=0)return this.emit(Events.DEBUG,"Didn't sweep messages - lifetime is unlimited"),-1;const t=1e3*e,i=Date.now();let s=0,n=0;for(const e of this.channels.cache.values())e.messages&&(s++,n+=e.messages.cache.sweep(e=>i-(e.editedTimestamp||e.createdTimestamp)>t));return this.emit(Events.DEBUG,`Swept ${n} messages older than ${e} seconds in ${s} text-based channels`),n}fetchApplication(){return this.api.oauth2.applications("@me").get().then(e=>new ClientApplication(this,e))}fetchGuildPreview(e){const t=this.guilds.resolveID(e);if(!t)throw new TypeError("INVALID_TYPE","guild","GuildResolvable");return this.api.guilds(t).preview.get().then(e=>new GuildPreview(this,e))}async generateInvite(e){e=Permissions.resolve(e);const t=await this.fetchApplication(),i=new URLSearchParams({client_id:t.id,permissions:e,scope:"bot"});return`${this.options.http.api}${this.api.oauth2.authorize}?${i}`}toJSON(){return super.toJSON({readyAt:!1,presences:!1})}_eval(script){return eval(script)}_validateOptions(e=this.options){if(void 0!==e.ws.intents&&(e.ws.intents=Intents.resolve(e.ws.intents)),"number"!=typeof e.shardCount||isNaN(e.shardCount)||e.shardCount<1)throw new TypeError("CLIENT_INVALID_OPTION","shardCount","a number greater than or equal to 1");if(e.shards&&"auto"!==e.shards&&!Array.isArray(e.shards))throw new TypeError("CLIENT_INVALID_OPTION","shards","'auto', a number or array of numbers");if(e.shards&&!e.shards.length)throw new RangeError("CLIENT_INVALID_PROVIDED_SHARDS");if("number"!=typeof e.messageCacheMaxSize||isNaN(e.messageCacheMaxSize))throw new TypeError("CLIENT_INVALID_OPTION","messageCacheMaxSize","a number");if("number"!=typeof e.messageCacheLifetime||isNaN(e.messageCacheLifetime))throw new TypeError("CLIENT_INVALID_OPTION","The messageCacheLifetime","a number");if("number"!=typeof e.messageSweepInterval||isNaN(e.messageSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","messageSweepInterval","a number");if("boolean"!=typeof e.fetchAllMembers)throw new TypeError("CLIENT_INVALID_OPTION","fetchAllMembers","a boolean");if("string"!=typeof e.disableMentions)throw new TypeError("CLIENT_INVALID_OPTION","disableMentions","a string");if(!Array.isArray(e.partials))throw new TypeError("CLIENT_INVALID_OPTION","partials","an Array");if("number"!=typeof e.restWsBridgeTimeout||isNaN(e.restWsBridgeTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restWsBridgeTimeout","a number");if("number"!=typeof e.restRequestTimeout||isNaN(e.restRequestTimeout))throw new TypeError("CLIENT_INVALID_OPTION","restRequestTimeout","a number");if("number"!=typeof e.restSweepInterval||isNaN(e.restSweepInterval))throw new TypeError("CLIENT_INVALID_OPTION","restSweepInterval","a number");if("number"!=typeof e.retryLimit||isNaN(e.retryLimit))throw new TypeError("CLIENT_INVALID_OPTION","retryLimit","a number")}}module.exports=Client}).call(this,__webpack_require__(14))},function(e,t,i){"use strict";e.exports=class ActionsManager{constructor(e){this.client=e,this.register(i(109)),this.register(i(110)),this.register(i(111)),this.register(i(112)),this.register(i(113)),this.register(i(114)),this.register(i(115)),this.register(i(116)),this.register(i(117)),this.register(i(118)),this.register(i(137)),this.register(i(138)),this.register(i(139)),this.register(i(140)),this.register(i(141)),this.register(i(142)),this.register(i(143)),this.register(i(144)),this.register(i(145)),this.register(i(146)),this.register(i(147)),this.register(i(148)),this.register(i(149)),this.register(i(150)),this.register(i(151)),this.register(i(152)),this.register(i(153)),this.register(i(154)),this.register(i(155)),this.register(i(156)),this.register(i(157))}register(e){this[e.name.replace(/Action$/,"")]=new e(this.client)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=i.messages.cache.get(e.id);if(s)return{message:s};const r=i.messages.add(e),o=r.author;let a=r.member;return i.lastMessageID=e.id,o&&(o.lastMessageID=e.id,o.lastMessageChannelID=i.id),a&&(a.lastMessageID=e.id,a.lastMessageChannelID=i.id),t.emit(n.MESSAGE_CREATE,r),{message:r}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageDeleteAction extends s{handle(e){const t=this.client,i=this.getChannel(e);let s;return i&&(s=this.getMessage(e,i),s&&(i.messages.cache.delete(s.id),s.deleted=!0,t.emit(n.MESSAGE_DELETE,s))),{message:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(2),{Events:r}=i(0);e.exports=class MessageDeleteBulkAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);if(i){const s=e.ids,o=new n;for(const t of s){const s=this.getMessage({id:t,guild_id:e.guild_id},i,!1);s&&(s.deleted=!0,o.set(s.id,s),i.messages.cache.delete(t))}return o.size>0&&t.emit(r.MESSAGE_BULK_DELETE,o),{messages:o}}return{}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class MessageUpdateAction extends s{handle(e){const t=this.getChannel(e);if(t){const{id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a}=e,c=this.getMessage({id:i,channel_id:s,guild_id:n,author:r,timestamp:o,type:a},t);if(c)return c.patch(e),{old:c._edits[0],updated:c}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0),{PartialTypes:r}=i(0);e.exports=class MessageReactionAdd extends s{handle(e){if(!e.emoji)return!1;const t=this.getUser(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;if(s.partial&&!this.client.options.partials.includes(r.REACTION))return!1;const o=s.reactions.add({emoji:e.emoji,count:s.partial?null:0,me:t.id===this.client.user.id});return!!o&&(o._add(t),this.client.emit(n.MESSAGE_REACTION_ADD,o,t),{message:s,reaction:o,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemove extends s{handle(e){if(!e.emoji)return!1;const t=this.getUser(e);if(!t)return!1;const i=this.getChannel(e);if(!i||"voice"===i.type)return!1;const s=this.getMessage(e,i);if(!s)return!1;const r=this.getReaction(e,s,t);return!!r&&(r._remove(t),this.client.emit(n.MESSAGE_REACTION_REMOVE,r,t),{message:s,reaction:r,user:t})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveAll extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);return!!i&&(i.reactions.cache.clear(),this.client.emit(n.MESSAGE_REACTION_REMOVE_ALL,i),{message:i})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class MessageReactionRemoveEmoji extends s{handle(e){const t=this.getChannel(e);if(!t||"voice"===t.type)return!1;const i=this.getMessage(e,t);if(!i)return!1;const s=this.getReaction(e,i);return!!s&&(i.partial||i.reactions.cache.delete(s.emoji.id||s.emoji.name),this.client.emit(n.MESSAGE_REACTION_REMOVE_EMOJI,s),{reaction:s})}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class ChannelCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.has(e.id),s=t.channels.add(e);return!i&&s&&t.emit(n.CHANNEL_CREATE,s),{channel:s}}}},function(e,t,i){"use strict";const s=i(1),n=i(39),{Events:r}=i(0);e.exports=class ChannelDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.channels.cache.get(e.id);if(i){if(t.channels.remove(i.id),i.deleted=!0,i.messages&&!(i instanceof n))for(const e of i.messages.cache.values())e.deleted=!0;t.emit(r.CHANNEL_DELETE,i)}return{channel:i}}}},function(e,t,i){e.exports=n;var s=i(15).EventEmitter;function n(){s.call(this)}i(22)(n,s),n.Readable=i(45),n.Writable=i(128),n.Duplex=i(129),n.Transform=i(130),n.PassThrough=i(131),n.Stream=n,n.prototype.pipe=function(e,t){var i=this;function n(t){e.writable&&!1===e.write(t)&&i.pause&&i.pause()}function r(){i.readable&&i.resume&&i.resume()}i.on("data",n),e.on("drain",r),e._isStdio||t&&!1===t.end||(i.on("end",a),i.on("close",c));var o=!1;function a(){o||(o=!0,e.end())}function c(){o||(o=!0,"function"==typeof e.destroy&&e.destroy())}function l(e){if(h(),0===s.listenerCount(this,"error"))throw e}function h(){i.removeListener("data",n),e.removeListener("drain",r),i.removeListener("end",a),i.removeListener("close",c),i.removeListener("error",l),e.removeListener("error",l),i.removeListener("end",h),i.removeListener("close",h),e.removeListener("close",h)}return i.on("error",l),e.on("error",l),i.on("end",h),i.on("close",h),e.on("close",h),e.emit("pipe",i),e}},function(e,t,i){"use strict";(function(e){var s=i(121),n=i(122),r=i(65);function o(){return c.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(o()<t)throw new RangeError("Invalid typed array length");return c.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=c.prototype:(null===e&&(e=new c(t)),e.length=t),e}function c(e,t,i){if(!(c.TYPED_ARRAY_SUPPORT||this instanceof c))return new c(e,t,i);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return u(this,e)}return l(this,e,t,i)}function l(e,t,i,s){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,i,s){if(t.byteLength,i<0||t.byteLength<i)throw new RangeError("'offset' is out of bounds");if(t.byteLength<i+(s||0))throw new RangeError("'length' is out of bounds");t=void 0===i&&void 0===s?new Uint8Array(t):void 0===s?new Uint8Array(t,i):new Uint8Array(t,i,s);c.TYPED_ARRAY_SUPPORT?(e=t).__proto__=c.prototype:e=d(e,t);return e}(e,t,i,s):"string"==typeof t?function(e,t,i){"string"==typeof i&&""!==i||(i="utf8");if(!c.isEncoding(i))throw new TypeError('"encoding" must be a valid string encoding');var s=0|f(t,i),n=(e=a(e,s)).write(t,i);n!==s&&(e=e.slice(0,n));return e}(e,t,i):function(e,t){if(c.isBuffer(t)){var i=0|p(t.length);return 0===(e=a(e,i)).length||t.copy(e,0,0,i),e}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(s=t.length)!=s?a(e,0):d(e,t);if("Buffer"===t.type&&r(t.data))return d(e,t.data)}var s;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function h(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function u(e,t){if(h(t),e=a(e,t<0?0:0|p(t)),!c.TYPED_ARRAY_SUPPORT)for(var i=0;i<t;++i)e[i]=0;return e}function d(e,t){var i=t.length<0?0:0|p(t.length);e=a(e,i);for(var s=0;s<i;s+=1)e[s]=255&t[s];return e}function p(e){if(e>=o())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o().toString(16)+" bytes");return 0|e}function f(e,t){if(c.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var i=e.length;if(0===i)return 0;for(var s=!1;;)switch(t){case"ascii":case"latin1":case"binary":return i;case"utf8":case"utf-8":case void 0:return B(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*i;case"hex":return i>>>1;case"base64":return V(e).length;default:if(s)return B(e).length;t=(""+t).toLowerCase(),s=!0}}function m(e,t,i){var s=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===i||i>this.length)&&(i=this.length),i<=0)return"";if((i>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return R(this,t,i);case"utf8":case"utf-8":return T(this,t,i);case"ascii":return D(this,t,i);case"latin1":case"binary":return N(this,t,i);case"base64":return I(this,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return O(this,t,i);default:if(s)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),s=!0}}function g(e,t,i){var s=e[t];e[t]=e[i],e[i]=s}function E(e,t,i,s,n){if(0===e.length)return-1;if("string"==typeof i?(s=i,i=0):i>2147483647?i=2147483647:i<-2147483648&&(i=-2147483648),i=+i,isNaN(i)&&(i=n?0:e.length-1),i<0&&(i=e.length+i),i>=e.length){if(n)return-1;i=e.length-1}else if(i<0){if(!n)return-1;i=0}if("string"==typeof t&&(t=c.from(t,s)),c.isBuffer(t))return 0===t.length?-1:_(e,t,i,s,n);if("number"==typeof t)return t&=255,c.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?n?Uint8Array.prototype.indexOf.call(e,t,i):Uint8Array.prototype.lastIndexOf.call(e,t,i):_(e,[t],i,s,n);throw new TypeError("val must be string, number or Buffer")}function _(e,t,i,s,n){var r,o=1,a=e.length,c=t.length;if(void 0!==s&&("ucs2"===(s=String(s).toLowerCase())||"ucs-2"===s||"utf16le"===s||"utf-16le"===s)){if(e.length<2||t.length<2)return-1;o=2,a/=2,c/=2,i/=2}function l(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(n){var h=-1;for(r=i;r<a;r++)if(l(e,r)===l(t,-1===h?0:r-h)){if(-1===h&&(h=r),r-h+1===c)return h*o}else-1!==h&&(r-=r-h),h=-1}else for(i+c>a&&(i=a-c),r=i;r>=0;r--){for(var u=!0,d=0;d<c;d++)if(l(e,r+d)!==l(t,d)){u=!1;break}if(u)return r}return-1}function y(e,t,i,s){i=Number(i)||0;var n=e.length-i;s?(s=Number(s))>n&&(s=n):s=n;var r=t.length;if(r%2!=0)throw new TypeError("Invalid hex string");s>r/2&&(s=r/2);for(var o=0;o<s;++o){var a=parseInt(t.substr(2*o,2),16);if(isNaN(a))return o;e[i+o]=a}return o}function b(e,t,i,s){return H(B(t,e.length-i),e,i,s)}function v(e,t,i,s){return H(function(e){for(var t=[],i=0;i<e.length;++i)t.push(255&e.charCodeAt(i));return t}(t),e,i,s)}function w(e,t,i,s){return v(e,t,i,s)}function A(e,t,i,s){return H(V(t),e,i,s)}function S(e,t,i,s){return H(function(e,t){for(var i,s,n,r=[],o=0;o<e.length&&!((t-=2)<0);++o)i=e.charCodeAt(o),s=i>>8,n=i%256,r.push(n),r.push(s);return r}(t,e.length-i),e,i,s)}function I(e,t,i){return 0===t&&i===e.length?s.fromByteArray(e):s.fromByteArray(e.slice(t,i))}function T(e,t,i){i=Math.min(e.length,i);for(var s=[],n=t;n<i;){var r,o,a,c,l=e[n],h=null,u=l>239?4:l>223?3:l>191?2:1;if(n+u<=i)switch(u){case 1:l<128&&(h=l);break;case 2:128==(192&(r=e[n+1]))&&(c=(31&l)<<6|63&r)>127&&(h=c);break;case 3:r=e[n+1],o=e[n+2],128==(192&r)&&128==(192&o)&&(c=(15&l)<<12|(63&r)<<6|63&o)>2047&&(c<55296||c>57343)&&(h=c);break;case 4:r=e[n+1],o=e[n+2],a=e[n+3],128==(192&r)&&128==(192&o)&&128==(192&a)&&(c=(15&l)<<18|(63&r)<<12|(63&o)<<6|63&a)>65535&&c<1114112&&(h=c)}null===h?(h=65533,u=1):h>65535&&(h-=65536,s.push(h>>>10&1023|55296),h=56320|1023&h),s.push(h),n+=u}return function(e){var t=e.length;if(t<=4096)return String.fromCharCode.apply(String,e);var i="",s=0;for(;s<t;)i+=String.fromCharCode.apply(String,e.slice(s,s+=4096));return i}(s)}t.Buffer=c,t.SlowBuffer=function(e){+e!=e&&(e=0);return c.alloc(+e)},t.INSPECT_MAX_BYTES=50,c.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=o(),c.poolSize=8192,c._augment=function(e){return e.__proto__=c.prototype,e},c.from=function(e,t,i){return l(null,e,t,i)},c.TYPED_ARRAY_SUPPORT&&(c.prototype.__proto__=Uint8Array.prototype,c.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&c[Symbol.species]===c&&Object.defineProperty(c,Symbol.species,{value:null,configurable:!0})),c.alloc=function(e,t,i){return function(e,t,i,s){return h(t),t<=0?a(e,t):void 0!==i?"string"==typeof s?a(e,t).fill(i,s):a(e,t).fill(i):a(e,t)}(null,e,t,i)},c.allocUnsafe=function(e){return u(null,e)},c.allocUnsafeSlow=function(e){return u(null,e)},c.isBuffer=function(e){return!(null==e||!e._isBuffer)},c.compare=function(e,t){if(!c.isBuffer(e)||!c.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var i=e.length,s=t.length,n=0,r=Math.min(i,s);n<r;++n)if(e[n]!==t[n]){i=e[n],s=t[n];break}return i<s?-1:s<i?1:0},c.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},c.concat=function(e,t){if(!r(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return c.alloc(0);var i;if(void 0===t)for(t=0,i=0;i<e.length;++i)t+=e[i].length;var s=c.allocUnsafe(t),n=0;for(i=0;i<e.length;++i){var o=e[i];if(!c.isBuffer(o))throw new TypeError('"list" argument must be an Array of Buffers');o.copy(s,n),n+=o.length}return s},c.byteLength=f,c.prototype._isBuffer=!0,c.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)g(this,t,t+1);return this},c.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)g(this,t,t+3),g(this,t+1,t+2);return this},c.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)g(this,t,t+7),g(this,t+1,t+6),g(this,t+2,t+5),g(this,t+3,t+4);return this},c.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?T(this,0,e):m.apply(this,arguments)},c.prototype.equals=function(e){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===c.compare(this,e)},c.prototype.inspect=function(){var e="",i=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,i).match(/.{2}/g).join(" "),this.length>i&&(e+=" ... ")),"<Buffer "+e+">"},c.prototype.compare=function(e,t,i,s,n){if(!c.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===i&&(i=e?e.length:0),void 0===s&&(s=0),void 0===n&&(n=this.length),t<0||i>e.length||s<0||n>this.length)throw new RangeError("out of range index");if(s>=n&&t>=i)return 0;if(s>=n)return-1;if(t>=i)return 1;if(this===e)return 0;for(var r=(n>>>=0)-(s>>>=0),o=(i>>>=0)-(t>>>=0),a=Math.min(r,o),l=this.slice(s,n),h=e.slice(t,i),u=0;u<a;++u)if(l[u]!==h[u]){r=l[u],o=h[u];break}return r<o?-1:o<r?1:0},c.prototype.includes=function(e,t,i){return-1!==this.indexOf(e,t,i)},c.prototype.indexOf=function(e,t,i){return E(this,e,t,i,!0)},c.prototype.lastIndexOf=function(e,t,i){return E(this,e,t,i,!1)},c.prototype.write=function(e,t,i,s){if(void 0===t)s="utf8",i=this.length,t=0;else if(void 0===i&&"string"==typeof t)s=t,i=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(i)?(i|=0,void 0===s&&(s="utf8")):(s=i,i=void 0)}var n=this.length-t;if((void 0===i||i>n)&&(i=n),e.length>0&&(i<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");s||(s="utf8");for(var r=!1;;)switch(s){case"hex":return y(this,e,t,i);case"utf8":case"utf-8":return b(this,e,t,i);case"ascii":return v(this,e,t,i);case"latin1":case"binary":return w(this,e,t,i);case"base64":return A(this,e,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,t,i);default:if(r)throw new TypeError("Unknown encoding: "+s);s=(""+s).toLowerCase(),r=!0}},c.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function D(e,t,i){var s="";i=Math.min(e.length,i);for(var n=t;n<i;++n)s+=String.fromCharCode(127&e[n]);return s}function N(e,t,i){var s="";i=Math.min(e.length,i);for(var n=t;n<i;++n)s+=String.fromCharCode(e[n]);return s}function R(e,t,i){var s=e.length;(!t||t<0)&&(t=0),(!i||i<0||i>s)&&(i=s);for(var n="",r=t;r<i;++r)n+=j(e[r]);return n}function O(e,t,i){for(var s=e.slice(t,i),n="",r=0;r<s.length;r+=2)n+=String.fromCharCode(s[r]+256*s[r+1]);return n}function C(e,t,i){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>i)throw new RangeError("Trying to access beyond buffer length")}function L(e,t,i,s,n,r){if(!c.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>n||t<r)throw new RangeError('"value" argument is out of bounds');if(i+s>e.length)throw new RangeError("Index out of range")}function M(e,t,i,s){t<0&&(t=65535+t+1);for(var n=0,r=Math.min(e.length-i,2);n<r;++n)e[i+n]=(t&255<<8*(s?n:1-n))>>>8*(s?n:1-n)}function U(e,t,i,s){t<0&&(t=4294967295+t+1);for(var n=0,r=Math.min(e.length-i,4);n<r;++n)e[i+n]=t>>>8*(s?n:3-n)&255}function P(e,t,i,s,n,r){if(i+s>e.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("Index out of range")}function x(e,t,i,s,r){return r||P(e,0,i,4),n.write(e,t,i,s,23,4),i+4}function G(e,t,i,s,r){return r||P(e,0,i,8),n.write(e,t,i,s,52,8),i+8}c.prototype.slice=function(e,t){var i,s=this.length;if((e=~~e)<0?(e+=s)<0&&(e=0):e>s&&(e=s),(t=void 0===t?s:~~t)<0?(t+=s)<0&&(t=0):t>s&&(t=s),t<e&&(t=e),c.TYPED_ARRAY_SUPPORT)(i=this.subarray(e,t)).__proto__=c.prototype;else{var n=t-e;i=new c(n,void 0);for(var r=0;r<n;++r)i[r]=this[r+e]}return i},c.prototype.readUIntLE=function(e,t,i){e|=0,t|=0,i||C(e,t,this.length);for(var s=this[e],n=1,r=0;++r<t&&(n*=256);)s+=this[e+r]*n;return s},c.prototype.readUIntBE=function(e,t,i){e|=0,t|=0,i||C(e,t,this.length);for(var s=this[e+--t],n=1;t>0&&(n*=256);)s+=this[e+--t]*n;return s},c.prototype.readUInt8=function(e,t){return t||C(e,1,this.length),this[e]},c.prototype.readUInt16LE=function(e,t){return t||C(e,2,this.length),this[e]|this[e+1]<<8},c.prototype.readUInt16BE=function(e,t){return t||C(e,2,this.length),this[e]<<8|this[e+1]},c.prototype.readUInt32LE=function(e,t){return t||C(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},c.prototype.readUInt32BE=function(e,t){return t||C(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},c.prototype.readIntLE=function(e,t,i){e|=0,t|=0,i||C(e,t,this.length);for(var s=this[e],n=1,r=0;++r<t&&(n*=256);)s+=this[e+r]*n;return s>=(n*=128)&&(s-=Math.pow(2,8*t)),s},c.prototype.readIntBE=function(e,t,i){e|=0,t|=0,i||C(e,t,this.length);for(var s=t,n=1,r=this[e+--s];s>0&&(n*=256);)r+=this[e+--s]*n;return r>=(n*=128)&&(r-=Math.pow(2,8*t)),r},c.prototype.readInt8=function(e,t){return t||C(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},c.prototype.readInt16LE=function(e,t){t||C(e,2,this.length);var i=this[e]|this[e+1]<<8;return 32768&i?4294901760|i:i},c.prototype.readInt16BE=function(e,t){t||C(e,2,this.length);var i=this[e+1]|this[e]<<8;return 32768&i?4294901760|i:i},c.prototype.readInt32LE=function(e,t){return t||C(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},c.prototype.readInt32BE=function(e,t){return t||C(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},c.prototype.readFloatLE=function(e,t){return t||C(e,4,this.length),n.read(this,e,!0,23,4)},c.prototype.readFloatBE=function(e,t){return t||C(e,4,this.length),n.read(this,e,!1,23,4)},c.prototype.readDoubleLE=function(e,t){return t||C(e,8,this.length),n.read(this,e,!0,52,8)},c.prototype.readDoubleBE=function(e,t){return t||C(e,8,this.length),n.read(this,e,!1,52,8)},c.prototype.writeUIntLE=function(e,t,i,s){(e=+e,t|=0,i|=0,s)||L(this,e,t,i,Math.pow(2,8*i)-1,0);var n=1,r=0;for(this[t]=255&e;++r<i&&(n*=256);)this[t+r]=e/n&255;return t+i},c.prototype.writeUIntBE=function(e,t,i,s){(e=+e,t|=0,i|=0,s)||L(this,e,t,i,Math.pow(2,8*i)-1,0);var n=i-1,r=1;for(this[t+n]=255&e;--n>=0&&(r*=256);)this[t+n]=e/r&255;return t+i},c.prototype.writeUInt8=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,1,255,0),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},c.prototype.writeUInt16LE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):M(this,e,t,!0),t+2},c.prototype.writeUInt16BE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,2,65535,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):M(this,e,t,!1),t+2},c.prototype.writeUInt32LE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):U(this,e,t,!0),t+4},c.prototype.writeUInt32BE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,4,4294967295,0),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):U(this,e,t,!1),t+4},c.prototype.writeIntLE=function(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);L(this,e,t,i,n-1,-n)}var r=0,o=1,a=0;for(this[t]=255&e;++r<i&&(o*=256);)e<0&&0===a&&0!==this[t+r-1]&&(a=1),this[t+r]=(e/o>>0)-a&255;return t+i},c.prototype.writeIntBE=function(e,t,i,s){if(e=+e,t|=0,!s){var n=Math.pow(2,8*i-1);L(this,e,t,i,n-1,-n)}var r=i-1,o=1,a=0;for(this[t+r]=255&e;--r>=0&&(o*=256);)e<0&&0===a&&0!==this[t+r+1]&&(a=1),this[t+r]=(e/o>>0)-a&255;return t+i},c.prototype.writeInt8=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,1,127,-128),c.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},c.prototype.writeInt16LE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):M(this,e,t,!0),t+2},c.prototype.writeInt16BE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,2,32767,-32768),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):M(this,e,t,!1),t+2},c.prototype.writeInt32LE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,4,2147483647,-2147483648),c.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):U(this,e,t,!0),t+4},c.prototype.writeInt32BE=function(e,t,i){return e=+e,t|=0,i||L(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),c.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):U(this,e,t,!1),t+4},c.prototype.writeFloatLE=function(e,t,i){return x(this,e,t,!0,i)},c.prototype.writeFloatBE=function(e,t,i){return x(this,e,t,!1,i)},c.prototype.writeDoubleLE=function(e,t,i){return G(this,e,t,!0,i)},c.prototype.writeDoubleBE=function(e,t,i){return G(this,e,t,!1,i)},c.prototype.copy=function(e,t,i,s){if(i||(i=0),s||0===s||(s=this.length),t>=e.length&&(t=e.length),t||(t=0),s>0&&s<i&&(s=i),s===i)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(i<0||i>=this.length)throw new RangeError("sourceStart out of bounds");if(s<0)throw new RangeError("sourceEnd out of bounds");s>this.length&&(s=this.length),e.length-t<s-i&&(s=e.length-t+i);var n,r=s-i;if(this===e&&i<t&&t<s)for(n=r-1;n>=0;--n)e[n+t]=this[n+i];else if(r<1e3||!c.TYPED_ARRAY_SUPPORT)for(n=0;n<r;++n)e[n+t]=this[n+i];else Uint8Array.prototype.set.call(e,this.subarray(i,i+r),t);return r},c.prototype.fill=function(e,t,i,s){if("string"==typeof e){if("string"==typeof t?(s=t,t=0,i=this.length):"string"==typeof i&&(s=i,i=this.length),1===e.length){var n=e.charCodeAt(0);n<256&&(e=n)}if(void 0!==s&&"string"!=typeof s)throw new TypeError("encoding must be a string");if("string"==typeof s&&!c.isEncoding(s))throw new TypeError("Unknown encoding: "+s)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<i)throw new RangeError("Out of range index");if(i<=t)return this;var r;if(t>>>=0,i=void 0===i?this.length:i>>>0,e||(e=0),"number"==typeof e)for(r=t;r<i;++r)this[r]=e;else{var o=c.isBuffer(e)?e:B(new c(e,s).toString()),a=o.length;for(r=0;r<i-t;++r)this[r+t]=o[r%a]}return this};var k=/[^+\/0-9A-Za-z-_]/g;function j(e){return e<16?"0"+e.toString(16):e.toString(16)}function B(e,t){var i;t=t||1/0;for(var s=e.length,n=null,r=[],o=0;o<s;++o){if((i=e.charCodeAt(o))>55295&&i<57344){if(!n){if(i>56319){(t-=3)>-1&&r.push(239,191,189);continue}if(o+1===s){(t-=3)>-1&&r.push(239,191,189);continue}n=i;continue}if(i<56320){(t-=3)>-1&&r.push(239,191,189),n=i;continue}i=65536+(n-55296<<10|i-56320)}else n&&(t-=3)>-1&&r.push(239,191,189);if(n=null,i<128){if((t-=1)<0)break;r.push(i)}else if(i<2048){if((t-=2)<0)break;r.push(i>>6|192,63&i|128)}else if(i<65536){if((t-=3)<0)break;r.push(i>>12|224,i>>6&63|128,63&i|128)}else{if(!(i<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;r.push(i>>18|240,i>>12&63|128,i>>6&63|128,63&i|128)}}return r}function V(e){return s.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(k,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function H(e,t,i,s){for(var n=0;n<s&&!(n+i>=t.length||n>=e.length);++n)t[n+i]=e[n];return n}}).call(this,i(21))},function(e,t,i){"use strict";t.byteLength=function(e){var t=l(e),i=t[0],s=t[1];return 3*(i+s)/4-s},t.toByteArray=function(e){var t,i,s=l(e),o=s[0],a=s[1],c=new r(function(e,t,i){return 3*(t+i)/4-i}(0,o,a)),h=0,u=a>0?o-4:o;for(i=0;i<u;i+=4)t=n[e.charCodeAt(i)]<<18|n[e.charCodeAt(i+1)]<<12|n[e.charCodeAt(i+2)]<<6|n[e.charCodeAt(i+3)],c[h++]=t>>16&255,c[h++]=t>>8&255,c[h++]=255&t;2===a&&(t=n[e.charCodeAt(i)]<<2|n[e.charCodeAt(i+1)]>>4,c[h++]=255&t);1===a&&(t=n[e.charCodeAt(i)]<<10|n[e.charCodeAt(i+1)]<<4|n[e.charCodeAt(i+2)]>>2,c[h++]=t>>8&255,c[h++]=255&t);return c},t.fromByteArray=function(e){for(var t,i=e.length,n=i%3,r=[],o=0,a=i-n;o<a;o+=16383)r.push(h(e,o,o+16383>a?a:o+16383));1===n?(t=e[i-1],r.push(s[t>>2]+s[t<<4&63]+"==")):2===n&&(t=(e[i-2]<<8)+e[i-1],r.push(s[t>>10]+s[t>>4&63]+s[t<<2&63]+"="));return r.join("")};for(var s=[],n=[],r="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,c=o.length;a<c;++a)s[a]=o[a],n[o.charCodeAt(a)]=a;function l(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var i=e.indexOf("=");return-1===i&&(i=t),[i,i===t?0:4-i%4]}function h(e,t,i){for(var n,r,o=[],a=t;a<i;a+=3)n=(e[a]<<16&16711680)+(e[a+1]<<8&65280)+(255&e[a+2]),o.push(s[(r=n)>>18&63]+s[r>>12&63]+s[r>>6&63]+s[63&r]);return o.join("")}n["-".charCodeAt(0)]=62,n["_".charCodeAt(0)]=63},function(e,t){t.read=function(e,t,i,s,n){var r,o,a=8*n-s-1,c=(1<<a)-1,l=c>>1,h=-7,u=i?n-1:0,d=i?-1:1,p=e[t+u];for(u+=d,r=p&(1<<-h)-1,p>>=-h,h+=a;h>0;r=256*r+e[t+u],u+=d,h-=8);for(o=r&(1<<-h)-1,r>>=-h,h+=s;h>0;o=256*o+e[t+u],u+=d,h-=8);if(0===r)r=1-l;else{if(r===c)return o?NaN:1/0*(p?-1:1);o+=Math.pow(2,s),r-=l}return(p?-1:1)*o*Math.pow(2,r-s)},t.write=function(e,t,i,s,n,r){var o,a,c,l=8*r-n-1,h=(1<<l)-1,u=h>>1,d=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,p=s?0:r-1,f=s?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=h):(o=Math.floor(Math.log(t)/Math.LN2),t*(c=Math.pow(2,-o))<1&&(o--,c*=2),(t+=o+u>=1?d/c:d*Math.pow(2,1-u))*c>=2&&(o++,c/=2),o+u>=h?(a=0,o=h):o+u>=1?(a=(t*c-1)*Math.pow(2,n),o+=u):(a=t*Math.pow(2,u-1)*Math.pow(2,n),o=0));n>=8;e[i+p]=255&a,p+=f,a/=256,n-=8);for(o=o<<n|a,l+=n;l>0;e[i+p]=255&o,p+=f,o/=256,l-=8);e[i+p-f]|=128*m}},function(e,t){},function(e,t,i){"use strict";var s=i(32).Buffer,n=i(125);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,i=""+t.data;t=t.next;)i+=e+t.data;return i},e.prototype.concat=function(e){if(0===this.length)return s.alloc(0);if(1===this.length)return this.head.data;for(var t,i,n,r=s.allocUnsafe(e>>>0),o=this.head,a=0;o;)t=o.data,i=r,n=a,t.copy(i,n),a+=o.data.length,o=o.next;return r},e}(),n&&n.inspect&&n.inspect.custom&&(e.exports.prototype[n.inspect.custom]=function(){var e=n.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,i){(function(t){function i(e){try{if(!t.localStorage)return!1}catch(e){return!1}var i=t.localStorage[e];return null!=i&&"true"===String(i).toLowerCase()}e.exports=function(e,t){if(i("noDeprecation"))return e;var s=!1;return function(){if(!s){if(i("throwDeprecation"))throw new Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),s=!0}return e.apply(this,arguments)}}}).call(this,i(21))},function(e,t,i){"use strict";e.exports=r;var s=i(69),n=Object.create(i(25));function r(e){if(!(this instanceof r))return new r(e);s.call(this,e)}n.inherits=i(22),n.inherits(r,s),r.prototype._transform=function(e,t,i){i(null,e)}},function(e,t,i){e.exports=i(46)},function(e,t,i){e.exports=i(20)},function(e,t,i){e.exports=i(45).Transform},function(e,t,i){e.exports=i(45).PassThrough},function(e,t,i){"use strict";const s=i(6),n=i(51);e.exports=class ReactionManager extends s{constructor(e,t){super(e.client,t,n),this.message=e}add(e,t){return super.add(e,t,{id:e.emoji.id||e.emoji.name,extras:[this.message]})}removeAll(){return this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions.delete().then(()=>this.message)}}},function(e,t,i){"use strict";const s=i(2);e.exports=class LimitedCollection extends s{constructor(e=0,t=null){super(t),this.maxSize=e}set(e,t){return 0===this.maxSize?this:(this.size>=this.maxSize&&!this.has(e)&&this.delete(this.firstKey()),super.set(e,t))}static get[Symbol.species](){return s}}},function(e,t,i){"use strict";const s=i(40);e.exports=class GuildPreviewEmoji extends s{get roles(){return new Set(this._roles)}}},function(e,t,i){"use strict";const s=i(6),n=i(27);e.exports=class VoiceStateManager extends s{constructor(e,t){super(e.client,t,n),this.guild=e}add(e,t=!0){const i=this.cache.get(e.user_id);if(i)return i._patch(e);const s=new n(this.guild,e);return t&&this.cache.set(e.user_id,s),s}}},function(e,t,i){"use strict";const s=i(16),{Error:n}=i(3);e.exports=class PartialGroupDMChannel extends s{constructor(e,t){super(e,t),this.name=t.name,this.icon=t.icon}iconURL({format:e,size:t}={}){return this.icon?this.client.rest.cdn.GDMIcon(this.id,this.icon,e,t):null}delete(){return Promise.reject(new n("DELETE_GROUP_DM_CHANNEL"))}fetch(){return Promise.reject(new n("FETCH_GROUP_DM_CHANNEL"))}}},function(e,t,i){"use strict";const s=i(1),n=i(16),{ChannelTypes:r}=i(0);e.exports=class ChannelUpdateAction extends s{handle(e){let t=this.client.channels.cache.get(e.id);if(t){const i=t._update(e);if(r[t.type.toUpperCase()]!==e.type){const i=n.create(this.client,e,t.guild);for(const[e,s]of t.messages.cache)i.messages.cache.set(e,s);i._typing=new Map(t._typing),t=i,this.client.channels.cache.set(t.id,t)}return{old:i,updated:t}}return{}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildDeleteAction extends s{constructor(e){super(e),this.deleted=new Map}handle(e){const t=this.client;let i=t.guilds.cache.get(e.id);if(i){for(const e of i.channels.cache.values())"text"===e.type&&e.stopTyping(!0);if(e.unavailable)return i.available=!1,t.emit(n.GUILD_UNAVAILABLE,i),{guild:null};for(const e of i.channels.cache.values())this.client.channels.remove(e.id);i.voice&&i.voice.connection&&i.voice.connection.disconnect(),t.guilds.cache.delete(i.id),i.deleted=!0,t.emit(n.GUILD_DELETE,i),this.deleted.set(i.id,i),this.scheduleForDeletion(i.id)}else i=this.deleted.get(e.id)||null;return{guild:i}}scheduleForDeletion(e){this.client.setTimeout(()=>this.deleted.delete(e),this.client.options.restWsBridgeTimeout)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.id);if(i){const s=i._update(e);return t.emit(n.GUILD_UPDATE,s,i),{old:s,updated:i}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),n=i(18),{Events:r}=i(0);e.exports=class InviteCreateAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i&&!s)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_CREATE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),n=i(18),{Events:r}=i(0);e.exports=class InviteDeleteAction extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id),s=t.guilds.cache.get(e.guild_id);if(!i&&!s)return!1;const o=Object.assign(e,{channel:i,guild:s}),a=new n(t,o);return t.emit(r.INVITE_DELETE,a),{invite:a}}}},function(e,t,i){"use strict";const s=i(1),{Events:n,Status:r}=i(0);e.exports=class GuildMemberRemoveAction extends s{handle(e,t){const i=this.client,s=i.guilds.cache.get(e.guild_id);let o=null;return s&&(o=this.getMember(e,s),s.memberCount--,o&&(o.deleted=!0,s.members.cache.delete(o.id),t.status===r.READY&&i.emit(n.GUILD_MEMBER_REMOVE,o)),s.voiceStates.cache.delete(e.user.id)),{guild:s,member:o}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildBanRemove extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id),s=t.users.add(e.user);i&&s&&t.emit(n.GUILD_BAN_REMOVE,i,s)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleCreate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;if(i){const r=i.roles.cache.has(e.role.id);s=i.roles.add(e.role),r||t.emit(n.GUILD_ROLE_CREATE,s)}return{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleDeleteAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);let s;return i&&(s=i.roles.cache.get(e.role_id),s&&(i.roles.cache.delete(e.role_id),s.deleted=!0,t.emit(n.GUILD_ROLE_DELETE,s))),{role:s}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildRoleUpdateAction extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){let s=null;const r=i.roles.cache.get(e.role.id);return r&&(s=r._update(e.role),t.emit(n.GUILD_ROLE_UPDATE,s,r)),{old:s,updated:r}}return{old:null,updated:null}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class PresenceUpdateAction extends s{handle(e){let t=this.client.users.cache.get(e.user.id);if(!t&&e.user.username&&(t=this.client.users.add(e.user)),!t)return;e.user&&e.user.username&&(t.equals(e.user)||this.client.actions.UserUpdate.handle(e.user));const i=this.client.guilds.cache.get(e.guild_id);if(!i)return;let s=i.presences.cache.get(t.id);s&&(s=s._clone());let r=i.members.cache.get(t.id);r||"offline"===e.status||(r=i.members.add({user:t,roles:e.roles,deaf:!1,mute:!1}),this.client.emit(n.GUILD_MEMBER_AVAILABLE,r)),i.presences.add(Object.assign(e,{guild:i})),r&&this.client.listenerCount(n.PRESENCE_UPDATE)&&this.client.emit(n.PRESENCE_UPDATE,s,r.presence)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class UserUpdateAction extends s{handle(e){const t=this.client,i=t.users.cache.get(e.id),s=i._update(e);return s.equals(i)?{old:null,updated:null}:(t.emit(n.USER_UPDATE,s,i),{old:s,updated:i})}}},function(e,t,i){"use strict";const s=i(1),n=i(27),{Events:r}=i(0);e.exports=class VoiceStateUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);if(i){const s=i.voiceStates.cache.has(e.user_id)?i.voiceStates.cache.get(e.user_id)._clone():new n(i,{user_id:e.user_id}),o=i.voiceStates.add(e);let a=i.members.cache.get(e.user_id);a&&e.member?a._patch(e.member):e.member&&e.member.user&&e.member.joined_at&&(a=i.members.add(e.member)),a&&a.user.id===t.user.id&&(t.emit("debug",`[VOICE] received voice state update: ${JSON.stringify(e)}`),t.voice.onVoiceStateUpdate(e)),t.emit(r.VOICE_STATE_UPDATE,s,o)}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiCreateAction extends s{handle(e,t){const i=e.emojis.add(t);return this.client.emit(n.GUILD_EMOJI_CREATE,i),{emoji:i}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiDeleteAction extends s{handle(e){return e.guild.emojis.cache.delete(e.id),e.deleted=!0,this.client.emit(n.GUILD_EMOJI_DELETE,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildEmojiUpdateAction extends s{handle(e,t){const i=e._update(t);return this.client.emit(n.GUILD_EMOJI_UPDATE,i,e),{emoji:e}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildEmojisUpdateAction extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(!t||!t.emojis)return;const i=new Map(t.emojis.cache);for(const s of e.emojis){const e=t.emojis.cache.get(s.id);e?(i.delete(s.id),e.equals(s)||this.client.actions.GuildEmojiUpdate.handle(e,s)):this.client.actions.GuildEmojiCreate.handle(t,s)}for(const e of i.values())this.client.actions.GuildEmojiDelete.handle(e)}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildRolesPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.roles){const e=t.roles.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1);e.exports=class GuildChannelsPositionUpdate extends s{handle(e){const t=this.client.guilds.cache.get(e.guild_id);if(t)for(const i of e.channels){const e=t.channels.cache.get(i.id);e&&(e.rawPosition=i.position)}return{guild:t}}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class GuildIntegrationsUpdate extends s{handle(e){const t=this.client,i=t.guilds.cache.get(e.guild_id);i&&t.emit(n.GUILD_INTEGRATIONS_UPDATE,i)}}},function(e,t,i){"use strict";const s=i(1),{Events:n}=i(0);e.exports=class WebhooksUpdate extends s{handle(e){const t=this.client,i=t.channels.cache.get(e.channel_id);i&&t.emit(n.WEBHOOKS_UPDATE,i)}}},function(e,t){},function(e,t,i){"use strict";const s=i(15),n=i(160),r=i(91),{Error:o}=i(3),a=i(2),{Events:c,ShardEvents:l,Status:h,WSCodes:u,WSEvents:d}=i(0),p=i(4),f=[d.READY,d.RESUMED,d.GUILD_CREATE,d.GUILD_DELETE,d.GUILD_MEMBERS_CHUNK,d.GUILD_MEMBER_ADD,d.GUILD_MEMBER_REMOVE],m=Object.keys(u).slice(1).map(Number),g=[1e3,4006,4007];e.exports=class WebSocketManager extends s{constructor(e){super(),Object.defineProperty(this,"client",{value:e}),this.gateway=void 0,this.totalShards=this.client.options.shards.length,this.shards=new a,Object.defineProperty(this,"shardQueue",{value:new Set,writable:!0}),Object.defineProperty(this,"packetQueue",{value:[]}),this.status=h.IDLE,this.destroyed=!1,this.reconnecting=!1,this.sessionStartLimit=void 0}get ping(){return this.shards.reduce((e,t)=>e+t.ping,0)/this.shards.size}debug(e,t){this.client.emit(c.DEBUG,`[WS => ${t?`Shard ${t.id}`:"Manager"}] ${e}`)}async connect(){const e=new o(u[4004]),{url:t,shards:i,session_start_limit:s}=await this.client.api.gateway.bot.get().catch(t=>{throw 401===t.httpStatus?e:t});this.sessionStartLimit=s;const{total:r,remaining:a,reset_after:c}=s;this.debug(`Fetched Gateway Information\n URL: ${t}\n Recommended Shards: ${i}`),this.debug(`Session Limit Information\n Total: ${r}\n Remaining: ${a}`),this.gateway=`${t}/`;let{shards:l}=this.client.options;return"auto"===l&&(this.debug(`Using the recommended shard count provided by Discord: ${i}`),this.totalShards=this.client.options.shardCount=i,l=this.client.options.shards=Array.from({length:i},(e,t)=>t)),this.totalShards=l.length,this.debug(`Spawning shards: ${l.join(", ")}`),this.shardQueue=new Set(l.map(e=>new n(this,e))),await this._handleSessionLimit(a,c),this.createShards()}async createShards(){if(!this.shardQueue.size)return!1;const[e]=this.shardQueue;this.shardQueue.delete(e),e.eventsAttached||(e.on(l.ALL_READY,t=>{this.client.emit(c.SHARD_READY,e.id,t),this.shardQueue.size||(this.reconnecting=!1),this.checkShardsReady()}),e.on(l.CLOSE,t=>{if(1e3===t.code?this.destroyed:m.includes(t.code))return this.client.emit(c.SHARD_DISCONNECT,t,e.id),void this.debug(u[t.code],e);g.includes(t.code)&&(e.sessionID=void 0),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),e.sessionID?(this.debug("Session ID is present, attempting an immediate reconnect...",e),this.reconnect(!0)):(e.destroy({reset:!0,emit:!1,log:!1}),this.reconnect())}),e.on(l.INVALID_SESSION,()=>{this.client.emit(c.SHARD_RECONNECTING,e.id)}),e.on(l.DESTROYED,()=>{this.debug("Shard was destroyed but no WebSocket connection was present! Reconnecting...",e),this.client.emit(c.SHARD_RECONNECTING,e.id),this.shardQueue.add(e),this.reconnect()}),e.eventsAttached=!0),this.shards.set(e.id,e);try{await e.connect()}catch(t){if(t&&t.code&&m.includes(t.code))throw new o(u[t.code]);if(t&&!t.code)throw t;this.debug("Failed to connect to the gateway, requeueing...",e),this.shardQueue.add(e)}return!this.shardQueue.size||(this.debug(`Shard Queue Size: ${this.shardQueue.size}; continuing in 5 seconds...`),await p.delayFor(5e3),await this._handleSessionLimit(),this.createShards())}async reconnect(e=!1){if(this.reconnecting||this.status!==h.READY)return!1;this.reconnecting=!0;try{e||await this._handleSessionLimit(),await this.createShards()}catch(e){if(this.debug(`Couldn't reconnect or fetch information about the gateway. ${e}`),401!==e.httpStatus)return this.debug("Possible network error occurred. Retrying in 5s..."),await p.delayFor(5e3),this.reconnecting=!1,this.reconnect();this.client.listenerCount(c.INVALIDATED)?(this.client.emit(c.INVALIDATED),this.destroy()):this.client.destroy()}finally{this.reconnecting=!1}return!0}broadcast(e){for(const t of this.shards.values())t.send(e)}destroy(){if(!this.destroyed){this.debug(`Manager was destroyed. Called by:\n${new Error("MANAGER_DESTROYED").stack}`),this.destroyed=!0,this.shardQueue.clear();for(const e of this.shards.values())e.destroy({closeCode:1e3,reset:!0,emit:!1,log:!1})}}async _handleSessionLimit(e,t){if(void 0===e&&void 0===t){const{session_start_limit:i}=await this.client.api.gateway.bot.get();this.sessionStartLimit=i,e=i.remaining,t=i.reset_after,this.debug(`Session Limit Information\n Total: ${i.total}\n Remaining: ${e}`)}e||(this.debug(`Exceeded identify threshold. Will attempt a connection in ${t}ms`),await p.delayFor(t))}handlePacket(e,t){if(e&&this.status!==h.READY&&!f.includes(e.t))return this.packetQueue.push({packet:e,shard:t}),!1;if(this.packetQueue.length){const e=this.packetQueue.shift();this.client.setImmediate(()=>{this.handlePacket(e.packet,e.shard)})}return e&&r[e.t]&&r[e.t](this.client,e,t),!0}async checkShardsReady(){if(this.status!==h.READY&&this.shards.size===this.totalShards&&!this.shards.some(e=>e.status!==h.READY)){if(this.status=h.NEARLY,this.client.options.fetchAllMembers)try{const e=this.client.guilds.cache.map(e=>e.available?e.members.fetch():Promise.resolve());await Promise.all(e)}catch(e){this.debug(`Failed to fetch all members before ready! ${e}\n${e.stack}`)}this.triggerClientReady()}}triggerClientReady(){this.status=h.READY,this.client.readyAt=new Date,this.client.emit(c.CLIENT_READY),this.handlePacket()}}},function(e,t,i){"use strict";const s=i(15),n=i(90),{browser:r,Status:o,Events:a,ShardEvents:c,OPCodes:l,WSEvents:h}=i(0),u=Object.keys(o),d=Object.keys(n.WebSocket);let p;if(!r)try{p=i(166)}catch{}e.exports=class WebSocketShard extends s{constructor(e,t){super(),this.manager=e,this.id=t,this.status=o.IDLE,this.sequence=-1,this.closeSequence=0,this.sessionID=void 0,this.ping=-1,this.lastPingTimestamp=-1,this.lastHeartbeatAcked=!0,Object.defineProperty(this,"ratelimit",{value:{queue:[],total:120,remaining:120,time:6e4,timer:null}}),Object.defineProperty(this,"connection",{value:null,writable:!0}),Object.defineProperty(this,"inflate",{value:null,writable:!0}),Object.defineProperty(this,"helloTimeout",{value:void 0,writable:!0}),Object.defineProperty(this,"eventsAttached",{value:!1,writable:!0}),Object.defineProperty(this,"expectedGuilds",{value:void 0,writable:!0}),Object.defineProperty(this,"readyTimeout",{value:void 0,writable:!0}),Object.defineProperty(this,"connectedAt",{value:0,writable:!0})}debug(e){this.manager.debug(e,this)}connect(){const{gateway:e,client:t}=this.manager;return this.connection&&this.connection.readyState===n.OPEN&&this.status===o.READY?Promise.resolve():new Promise((i,s)=>{const r=()=>{this.removeListener(c.CLOSE,h),this.removeListener(c.READY,a),this.removeListener(c.RESUMED,l),this.removeListener(c.INVALID_SESSION,u),this.removeListener(c.DESTROYED,u)},a=()=>{r(),i()},l=()=>{r(),i()},h=e=>{r(),s(e)},u=()=>{r(),s()};if(this.once(c.READY,a),this.once(c.RESUMED,l),this.once(c.CLOSE,h),this.once(c.INVALID_SESSION,u),this.once(c.DESTROYED,u),this.connection&&this.connection.readyState===n.OPEN)return this.debug("An open connection was found, attempting an immediate identify."),void this.identify();this.connection&&(this.debug(`A connection object was found. Cleaning up before continuing.\n State: ${d[this.connection.readyState]}`),this.destroy({emit:!1}));const f={v:t.options.ws.version};p&&(this.inflate=new p.Inflate({chunkSize:65535,flush:p.Z_SYNC_FLUSH,to:"json"===n.encoding?"string":""}),f.compress="zlib-stream"),this.debug(`[CONNECT]\n Gateway : ${e}\n Version : ${t.options.ws.version}\n Encoding : ${n.encoding}\n Compression: ${p?"zlib-stream":"none"}`),this.status=this.status===o.DISCONNECTED?o.RECONNECTING:o.CONNECTING,this.setHelloTimeout(),this.connectedAt=Date.now();const m=this.connection=n.create(e,f);m.onopen=this.onOpen.bind(this),m.onmessage=this.onMessage.bind(this),m.onerror=this.onError.bind(this),m.onclose=this.onClose.bind(this)})}onOpen(){this.debug(`[CONNECTED] ${this.connection.url} in ${Date.now()-this.connectedAt}ms`),this.status=o.NEARLY}onMessage({data:e}){let t,i;if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),p){const i=e.length,s=i>=4&&0===e[i-4]&&0===e[i-3]&&255===e[i-2]&&255===e[i-1];if(this.inflate.push(e,s&&p.Z_SYNC_FLUSH),!s)return;t=this.inflate.result}else t=e;try{i=n.unpack(t),this.manager.client.emit(a.RAW,i,this.id),i.op===l.DISPATCH&&this.manager.emit(i.t,i.d,this.id)}catch(e){return void this.manager.client.emit(a.SHARD_ERROR,e,this.id)}this.onPacket(i)}onError(e){const t=e&&e.error?e.error:e;t&&this.manager.client.emit(a.SHARD_ERROR,t,this.id)}onClose(e){-1!==this.sequence&&(this.closeSequence=this.sequence),this.sequence=-1,this.debug(`[CLOSE]\n Event Code: ${e.code}\n Clean : ${e.wasClean}\n Reason : ${e.reason||"No reason received"}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection&&this._cleanupConnection(),this.status=o.DISCONNECTED,this.emit(c.CLOSE,e)}onPacket(e){if(e){switch(e.t){case h.READY:this.emit(c.READY),this.sessionID=e.d.session_id,this.expectedGuilds=new Set(e.d.guilds.map(e=>e.id)),this.status=o.WAITING_FOR_GUILDS,this.debug(`[READY] Session ${this.sessionID}.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ReadyHeartbeat");break;case h.RESUMED:{this.emit(c.RESUMED),this.status=o.READY;const t=e.s-this.closeSequence;this.debug(`[RESUMED] Session ${this.sessionID} | Replayed ${t} events.`),this.lastHeartbeatAcked=!0,this.sendHeartbeat("ResumeHeartbeat");break}}switch(e.s>this.sequence&&(this.sequence=e.s),e.op){case l.HELLO:this.setHelloTimeout(-1),this.setHeartbeatTimer(e.d.heartbeat_interval),this.identify();break;case l.RECONNECT:this.debug("[RECONNECT] Discord asked us to reconnect"),this.destroy({closeCode:4e3});break;case l.INVALID_SESSION:if(this.debug(`[INVALID SESSION] Resumable: ${e.d}.`),e.d)return void this.identifyResume();this.sequence=-1,this.sessionID=void 0,this.status=o.RECONNECTING,this.emit(c.INVALID_SESSION);break;case l.HEARTBEAT_ACK:this.ackHeartbeat();break;case l.HEARTBEAT:this.sendHeartbeat("HeartbeatRequest",!0);break;default:this.manager.handlePacket(e,this),this.status===o.WAITING_FOR_GUILDS&&e.t===h.GUILD_CREATE&&(this.expectedGuilds.delete(e.d.id),this.checkReady())}}else this.debug(`Received broken packet: '${e}'.`)}checkReady(){if(this.readyTimeout&&(this.manager.client.clearTimeout(this.readyTimeout),this.readyTimeout=void 0),!this.expectedGuilds.size)return this.debug("Shard received all its guilds. Marking as fully ready."),this.status=o.READY,void this.emit(c.ALL_READY);this.readyTimeout=this.manager.client.setTimeout(()=>{this.debug(`Shard did not receive any more guild packets in 15 seconds.\n Unavailable guild count: ${this.expectedGuilds.size}`),this.readyTimeout=void 0,this.status=o.READY,this.emit(c.ALL_READY,this.expectedGuilds)},15e3)}setHelloTimeout(e){-1!==e?(this.debug("Setting a HELLO timeout for 20s."),this.helloTimeout=this.manager.client.setTimeout(()=>{this.debug("Did not receive HELLO in time. Destroying and connecting again."),this.destroy({reset:!0,closeCode:4009})},2e4)):this.helloTimeout&&(this.debug("Clearing the HELLO timeout."),this.manager.client.clearTimeout(this.helloTimeout),this.helloTimeout=void 0)}setHeartbeatTimer(e){-1!==e?(this.debug(`Setting a heartbeat interval for ${e}ms.`),this.heartbeatInterval&&this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=this.manager.client.setInterval(()=>this.sendHeartbeat(),e)):this.heartbeatInterval&&(this.debug("Clearing the heartbeat interval."),this.manager.client.clearInterval(this.heartbeatInterval),this.heartbeatInterval=void 0)}sendHeartbeat(e="HeartbeatTimer",t=[o.WAITING_FOR_GUILDS,o.IDENTIFYING,o.RESUMING].includes(this.status)){if(t&&!this.lastHeartbeatAcked)this.debug(`[${e}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);else if(!this.lastHeartbeatAcked)return this.debug(`[${e}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.\n Status : ${u[this.status]}\n Sequence : ${this.sequence}\n Connection State: ${this.connection?d[this.connection.readyState]:"No Connection??"}`),void this.destroy({closeCode:4009,reset:!0});this.debug(`[${e}] Sending a heartbeat.`),this.lastHeartbeatAcked=!1,this.lastPingTimestamp=Date.now(),this.send({op:l.HEARTBEAT,d:this.sequence},!0)}ackHeartbeat(){this.lastHeartbeatAcked=!0;const e=Date.now()-this.lastPingTimestamp;this.debug(`Heartbeat acknowledged, latency of ${e}ms.`),this.ping=e}identify(){return this.sessionID?this.identifyResume():this.identifyNew()}identifyNew(){const{client:e}=this.manager;if(!e.token)return void this.debug("[IDENTIFY] No token available to identify a new session.");this.status=o.IDENTIFYING;const t={...e.options.ws,token:e.token,shard:[this.id,Number(e.options.shardCount)]};this.debug(`[IDENTIFY] Shard ${this.id}/${e.options.shardCount}`),this.send({op:l.IDENTIFY,d:t},!0)}identifyResume(){if(!this.sessionID)return this.debug("[RESUME] No session ID was present; identifying as a new session."),void this.identifyNew();this.status=o.RESUMING,this.debug(`[RESUME] Session ${this.sessionID}, sequence ${this.closeSequence}`);const e={token:this.manager.client.token,session_id:this.sessionID,seq:this.closeSequence};this.send({op:l.RESUME,d:e},!0)}send(e,t=!1){this.ratelimit.queue[t?"unshift":"push"](e),this.processQueue()}_send(e){if(!this.connection||this.connection.readyState!==n.OPEN)return this.debug(`Tried to send packet '${JSON.stringify(e)}' but no WebSocket is available!`),void this.destroy({close:4e3});this.connection.send(n.pack(e),e=>{e&&this.manager.client.emit(a.SHARD_ERROR,e,this.id)})}processQueue(){if(0!==this.ratelimit.remaining&&0!==this.ratelimit.queue.length)for(this.ratelimit.remaining===this.ratelimit.total&&(this.ratelimit.timer=this.manager.client.setTimeout(()=>{this.ratelimit.remaining=this.ratelimit.total,this.processQueue()},this.ratelimit.time));this.ratelimit.remaining>0;){const e=this.ratelimit.queue.shift();if(!e)return;this._send(e),this.ratelimit.remaining--}}destroy({closeCode:e=1e3,reset:t=!1,emit:i=!0,log:s=!0}={}){if(s&&this.debug(`[DESTROY]\n Close Code : ${e}\n Reset : ${t}\n Emit DESTROYED: ${i}`),this.setHeartbeatTimer(-1),this.setHelloTimeout(-1),this.connection)if(this.connection.readyState===n.OPEN)this.connection.close(e);else{this.debug(`WS State: ${d[this.connection.readyState]}`),this._cleanupConnection();try{this.connection.close(e)}catch{}i&&this._emitDestroyed()}else i&&this._emitDestroyed();this.connection=null,this.status=o.DISCONNECTED,-1!==this.sequence&&(this.closeSequence=this.sequence),t&&(this.sequence=-1,this.sessionID=void 0),this.ratelimit.remaining=this.ratelimit.total,this.ratelimit.queue.length=0,this.ratelimit.timer&&(this.manager.client.clearTimeout(this.ratelimit.timer),this.ratelimit.timer=null)}_cleanupConnection(){this.connection.onopen=this.connection.onclose=this.connection.onerror=this.connection.onmessage=null}_emitDestroyed(){this.emit(c.DESTROYED)}}},function(e,t){},function(e,t,i){(function(e){var s=Object.getOwnPropertyDescriptors||function(e){for(var t=Object.keys(e),i={},s=0;s<t.length;s++)i[t[s]]=Object.getOwnPropertyDescriptor(e,t[s]);return i},n=/%[sdj%]/g;t.format=function(e){if(!E(e)){for(var t=[],i=0;i<arguments.length;i++)t.push(a(arguments[i]));return t.join(" ")}i=1;for(var s=arguments,r=s.length,o=String(e).replace(n,(function(e){if("%%"===e)return"%";if(i>=r)return e;switch(e){case"%s":return String(s[i++]);case"%d":return Number(s[i++]);case"%j":try{return JSON.stringify(s[i++])}catch(e){return"[Circular]"}default:return e}})),c=s[i];i<r;c=s[++i])m(c)||!b(c)?o+=" "+c:o+=" "+a(c);return o},t.deprecate=function(i,s){if(void 0!==e&&!0===e.noDeprecation)return i;if(void 0===e)return function(){return t.deprecate(i,s).apply(this,arguments)};var n=!1;return function(){if(!n){if(e.throwDeprecation)throw new Error(s);e.traceDeprecation?console.trace(s):console.error(s),n=!0}return i.apply(this,arguments)}};var r,o={};function a(e,i){var s={seen:[],stylize:l};return arguments.length>=3&&(s.depth=arguments[2]),arguments.length>=4&&(s.colors=arguments[3]),f(i)?s.showHidden=i:i&&t._extend(s,i),_(s.showHidden)&&(s.showHidden=!1),_(s.depth)&&(s.depth=2),_(s.colors)&&(s.colors=!1),_(s.customInspect)&&(s.customInspect=!0),s.colors&&(s.stylize=c),h(s,e,s.depth)}function c(e,t){var i=a.styles[t];return i?"["+a.colors[i][0]+"m"+e+"["+a.colors[i][1]+"m":e}function l(e,t){return e}function h(e,i,s){if(e.customInspect&&i&&A(i.inspect)&&i.inspect!==t.inspect&&(!i.constructor||i.constructor.prototype!==i)){var n=i.inspect(s,e);return E(n)||(n=h(e,n,s)),n}var r=function(e,t){if(_(t))return e.stylize("undefined","undefined");if(E(t)){var i="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(i,"string")}if(g(t))return e.stylize(""+t,"number");if(f(t))return e.stylize(""+t,"boolean");if(m(t))return e.stylize("null","null")}(e,i);if(r)return r;var o=Object.keys(i),a=function(e){var t={};return e.forEach((function(e,i){t[e]=!0})),t}(o);if(e.showHidden&&(o=Object.getOwnPropertyNames(i)),w(i)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return u(i);if(0===o.length){if(A(i)){var c=i.name?": "+i.name:"";return e.stylize("[Function"+c+"]","special")}if(y(i))return e.stylize(RegExp.prototype.toString.call(i),"regexp");if(v(i))return e.stylize(Date.prototype.toString.call(i),"date");if(w(i))return u(i)}var l,b="",S=!1,I=["{","}"];(p(i)&&(S=!0,I=["[","]"]),A(i))&&(b=" [Function"+(i.name?": "+i.name:"")+"]");return y(i)&&(b=" "+RegExp.prototype.toString.call(i)),v(i)&&(b=" "+Date.prototype.toUTCString.call(i)),w(i)&&(b=" "+u(i)),0!==o.length||S&&0!=i.length?s<0?y(i)?e.stylize(RegExp.prototype.toString.call(i),"regexp"):e.stylize("[Object]","special"):(e.seen.push(i),l=S?function(e,t,i,s,n){for(var r=[],o=0,a=t.length;o<a;++o)N(t,String(o))?r.push(d(e,t,i,s,String(o),!0)):r.push("");return n.forEach((function(n){n.match(/^\d+$/)||r.push(d(e,t,i,s,n,!0))})),r}(e,i,s,a,o):o.map((function(t){return d(e,i,s,a,t,S)})),e.seen.pop(),function(e,t,i){if(e.reduce((function(e,t){return t.indexOf("\n")>=0&&0,e+t.replace(/\u001b\[\d\d?m/g,"").length+1}),0)>60)return i[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+i[1];return i[0]+t+" "+e.join(", ")+" "+i[1]}(l,b,I)):I[0]+b+I[1]}function u(e){return"["+Error.prototype.toString.call(e)+"]"}function d(e,t,i,s,n,r){var o,a,c;if((c=Object.getOwnPropertyDescriptor(t,n)||{value:t[n]}).get?a=c.set?e.stylize("[Getter/Setter]","special"):e.stylize("[Getter]","special"):c.set&&(a=e.stylize("[Setter]","special")),N(s,n)||(o="["+n+"]"),a||(e.seen.indexOf(c.value)<0?(a=m(i)?h(e,c.value,null):h(e,c.value,i-1)).indexOf("\n")>-1&&(a=r?a.split("\n").map((function(e){return" "+e})).join("\n").substr(2):"\n"+a.split("\n").map((function(e){return" "+e})).join("\n")):a=e.stylize("[Circular]","special")),_(o)){if(r&&n.match(/^\d+$/))return a;(o=JSON.stringify(""+n)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=e.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=e.stylize(o,"string"))}return o+": "+a}function p(e){return Array.isArray(e)}function f(e){return"boolean"==typeof e}function m(e){return null===e}function g(e){return"number"==typeof e}function E(e){return"string"==typeof e}function _(e){return void 0===e}function y(e){return b(e)&&"[object RegExp]"===S(e)}function b(e){return"object"==typeof e&&null!==e}function v(e){return b(e)&&"[object Date]"===S(e)}function w(e){return b(e)&&("[object Error]"===S(e)||e instanceof Error)}function A(e){return"function"==typeof e}function S(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}t.debuglog=function(i){if(_(r)&&(r=e.env.NODE_DEBUG||""),i=i.toUpperCase(),!o[i])if(new RegExp("\\b"+i+"\\b","i").test(r)){var s=e.pid;o[i]=function(){var e=t.format.apply(t,arguments);console.error("%s %d: %s",i,s,e)}}else o[i]=function(){};return o[i]},t.inspect=a,a.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},a.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},t.isArray=p,t.isBoolean=f,t.isNull=m,t.isNullOrUndefined=function(e){return null==e},t.isNumber=g,t.isString=E,t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=_,t.isRegExp=y,t.isObject=b,t.isDate=v,t.isError=w,t.isFunction=A,t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=i(163);var T=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function D(){var e=new Date,t=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":");return[e.getDate(),T[e.getMonth()],t].join(" ")}function N(e,t){return Object.prototype.hasOwnProperty.call(e,t)}t.log=function(){console.log("%s - %s",D(),t.format.apply(t,arguments))},t.inherits=i(164),t._extend=function(e,t){if(!t||!b(t))return e;for(var i=Object.keys(t),s=i.length;s--;)e[i[s]]=t[i[s]];return e};var R="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function O(e,t){if(!e){var i=new Error("Promise was rejected with a falsy value");i.reason=e,e=i}return t(e)}t.promisify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');if(R&&e[R]){var t;if("function"!=typeof(t=e[R]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(t,R,{value:t,enumerable:!1,writable:!1,configurable:!0}),t}function t(){for(var t,i,s=new Promise((function(e,s){t=e,i=s})),n=[],r=0;r<arguments.length;r++)n.push(arguments[r]);n.push((function(e,s){e?i(e):t(s)}));try{e.apply(this,n)}catch(e){i(e)}return s}return Object.setPrototypeOf(t,Object.getPrototypeOf(e)),R&&Object.defineProperty(t,R,{value:t,enumerable:!1,writable:!1,configurable:!0}),Object.defineProperties(t,s(e))},t.promisify.custom=R,t.callbackify=function(t){if("function"!=typeof t)throw new TypeError('The "original" argument must be of type Function');function i(){for(var i=[],s=0;s<arguments.length;s++)i.push(arguments[s]);var n=i.pop();if("function"!=typeof n)throw new TypeError("The last argument must be of type Function");var r=this,o=function(){return n.apply(r,arguments)};t.apply(this,i).then((function(t){e.nextTick(o,null,t)}),(function(t){e.nextTick(O,t,o)}))}return Object.setPrototypeOf(i,Object.getPrototypeOf(t)),Object.defineProperties(i,s(t)),i}}).call(this,i(14))},function(e,t){e.exports=function(e){return e&&"object"==typeof e&&"function"==typeof e.copy&&"function"==typeof e.fill&&"function"==typeof e.readUInt8}},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}})}:e.exports=function(e,t){e.super_=t;var i=function(){};i.prototype=t.prototype,e.prototype=new i,e.prototype.constructor=e}},function(e,t){},function(e,t){},function(e,t,i){var s={"./CHANNEL_CREATE.js":168,"./CHANNEL_DELETE.js":169,"./CHANNEL_PINS_UPDATE.js":170,"./CHANNEL_UPDATE.js":171,"./GUILD_BAN_ADD.js":172,"./GUILD_BAN_REMOVE.js":173,"./GUILD_CREATE.js":174,"./GUILD_DELETE.js":175,"./GUILD_EMOJIS_UPDATE.js":176,"./GUILD_INTEGRATIONS_UPDATE.js":177,"./GUILD_MEMBERS_CHUNK.js":178,"./GUILD_MEMBER_ADD.js":179,"./GUILD_MEMBER_REMOVE.js":180,"./GUILD_MEMBER_UPDATE.js":181,"./GUILD_ROLE_CREATE.js":182,"./GUILD_ROLE_DELETE.js":183,"./GUILD_ROLE_UPDATE.js":184,"./GUILD_UPDATE.js":185,"./INVITE_CREATE.js":186,"./INVITE_DELETE.js":187,"./MESSAGE_CREATE.js":188,"./MESSAGE_DELETE.js":189,"./MESSAGE_DELETE_BULK.js":190,"./MESSAGE_REACTION_ADD.js":191,"./MESSAGE_REACTION_REMOVE.js":192,"./MESSAGE_REACTION_REMOVE_ALL.js":193,"./MESSAGE_REACTION_REMOVE_EMOJI.js":194,"./MESSAGE_UPDATE.js":195,"./PRESENCE_UPDATE.js":196,"./READY.js":197,"./RESUMED.js":198,"./TYPING_START.js":199,"./USER_UPDATE.js":200,"./VOICE_SERVER_UPDATE.js":201,"./VOICE_STATE_UPDATE.js":202,"./WEBHOOKS_UPDATE.js":203,"./index.js":91};function n(e){var t=r(e);return i(t)}function r(e){if(!i.o(s,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return s[e]}n.keys=function(){return Object.keys(s)},n.resolve=r,e.exports=n,n.id=167},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.ChannelDelete.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.channels.cache.get(t.channel_id),n=new Date(t.last_pin_timestamp);i&&!Number.isNaN(n.getTime())&&(i.lastPinTimestamp=n.getTime()||null,e.emit(s.CHANNEL_PINS_UPDATE,i,n))}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.ChannelUpdate.handle(t.d);i&&n&&e.emit(s.CHANNEL_UPDATE,i,n)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id),n=e.users.add(t.user);i&&n&&e.emit(s.GUILD_BAN_ADD,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildBanRemove.handle(t.d)}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=async(e,{d:t},i)=>{let r=e.guilds.cache.get(t.id);r?r.available||t.unavailable||(r._patch(t),e.ws.status===n.READY&&e.options.fetchAllMembers&&await r.members.fetch().catch(t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`))):(t.shardID=i.id,r=e.guilds.add(t),e.ws.status===n.READY&&(e.options.fetchAllMembers&&await r.members.fetch().catch(t=>e.emit(s.DEBUG,`Failed to fetch all members: ${t}\n${t.stack}`)),e.emit(s.GUILD_CREATE,r)))}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildEmojisUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildIntegrationsUpdate.handle(t.d)}},function(e,t,i){"use strict";const s=i(2),{Events:n}=i(0);e.exports=(e,{d:t})=>{const i=e.guilds.cache.get(t.guild_id);if(!i)return;const r=new s;for(const e of t.members)r.set(e.user.id,i.members.add(e));if(t.presences)for(const e of t.presences)i.presences.cache.add(Object.assign(e,{guild:i}));e.emit(n.GUILD_MEMBERS_CHUNK,r,i)}},function(e,t,i){"use strict";const{Events:s,Status:n}=i(0);e.exports=(e,{d:t},i)=>{const r=e.guilds.cache.get(t.guild_id);if(r){r.memberCount++;const o=r.members.add(t);i.status===n.READY&&e.emit(s.GUILD_MEMBER_ADD,o)}}},function(e,t,i){"use strict";e.exports=(e,t,i)=>{e.actions.GuildMemberRemove.handle(t.d,i)}},function(e,t,i){"use strict";const{Status:s,Events:n}=i(0);e.exports=(e,{d:t},i)=>{const r=e.guilds.cache.get(t.guild_id);if(r){const o=r.members.cache.get(t.user.id);if(o){const r=o._update(t);i.status===s.READY&&e.emit(n.GUILD_MEMBER_UPDATE,r,o)}}}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildRoleUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.GuildUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.InviteDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageCreate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDelete.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageDeleteBulk.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionAdd.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemove.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveAll.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.MessageReactionRemoveEmoji.handle(t.d)}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t)=>{const{old:i,updated:n}=e.actions.MessageUpdate.handle(t.d);i&&n&&e.emit(s.MESSAGE_UPDATE,i,n)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.PresenceUpdate.handle(t.d)}},function(e,t,i){"use strict";let s;e.exports=(e,{d:t},n)=>{if(e.user)e.user._patch(t.user);else{s||(s=i(92));const n=new s(e,t.user);e.user=n,e.users.cache.set(n.id,n)}for(const i of t.guilds)i.shardID=n.id,e.guilds.add(i);n.checkReady()}},function(e,t,i){"use strict";const{Events:s}=i(0);e.exports=(e,t,i)=>{const n=i.sequence-i.closeSequence;e.emit(s.SHARD_RESUME,i.id,n)}},function(e,t,i){"use strict";const{Events:s}=i(0);function n(e,t){return e.client.setTimeout(()=>{e._typing.delete(t.id)},1e4)}e.exports=(e,{d:t})=>{const i=e.channels.cache.get(t.channel_id),r=e.users.cache.get(t.user_id),o=new Date(1e3*t.timestamp);if(i&&r){if("voice"===i.type)return void e.emit(s.WARN,`Discord sent a typing packet to a voice channel ${i.id}`);if(i._typing.has(r.id)){const t=i._typing.get(r.id);t.lastTimestamp=o,t.elapsedTime=Date.now()-t.since,e.clearTimeout(t.timeout),t.timeout=n(i,r)}else{const t=new Date,o=new Date;i._typing.set(r.id,{user:r,since:t,lastTimestamp:o,elapsedTime:Date.now()-t,timeout:n(i,r)}),e.emit(s.TYPING_START,i,r)}}}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.UserUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.emit("debug",`[VOICE] received voice server: ${JSON.stringify(t)}`),e.voice.onVoiceServer(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.VoiceStateUpdate.handle(t.d)}},function(e,t,i){"use strict";e.exports=(e,t)=>{e.actions.WebhooksUpdate.handle(t.d)}},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t){},function(e,t,i){"use strict";const s=i(11);class Speaking extends s{}Speaking.FLAGS={SPEAKING:1,SOUNDSHARE:2,PRIORITY_SPEAKING:4},e.exports=Speaking}])})); \ No newline at end of file