discord.js-selfbot-dmallfriends-v13 0.0.1-security → 2.16.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discord.js-selfbot-dmallfriends-v13 might be problematic. Click here for more details.

Files changed (343) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +127 -5
  3. package/package.json +101 -6
  4. package/src/WebSocket.js +39 -0
  5. package/src/client/BaseClient.js +87 -0
  6. package/src/client/Client.js +1154 -0
  7. package/src/client/WebhookClient.js +61 -0
  8. package/src/client/actions/Action.js +115 -0
  9. package/src/client/actions/ActionsManager.js +72 -0
  10. package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -0
  11. package/src/client/actions/AutoModerationActionExecution.js +26 -0
  12. package/src/client/actions/AutoModerationRuleCreate.js +27 -0
  13. package/src/client/actions/AutoModerationRuleDelete.js +31 -0
  14. package/src/client/actions/AutoModerationRuleUpdate.js +29 -0
  15. package/src/client/actions/ChannelCreate.js +23 -0
  16. package/src/client/actions/ChannelDelete.js +39 -0
  17. package/src/client/actions/ChannelUpdate.js +34 -0
  18. package/src/client/actions/GuildAuditLogEntryCreate.js +29 -0
  19. package/src/client/actions/GuildBanAdd.js +20 -0
  20. package/src/client/actions/GuildBanRemove.js +25 -0
  21. package/src/client/actions/GuildChannelsPositionUpdate.js +21 -0
  22. package/src/client/actions/GuildDelete.js +65 -0
  23. package/src/client/actions/GuildEmojiCreate.js +20 -0
  24. package/src/client/actions/GuildEmojiDelete.js +21 -0
  25. package/src/client/actions/GuildEmojiUpdate.js +20 -0
  26. package/src/client/actions/GuildEmojisUpdate.js +34 -0
  27. package/src/client/actions/GuildIntegrationsUpdate.js +19 -0
  28. package/src/client/actions/GuildMemberRemove.js +33 -0
  29. package/src/client/actions/GuildMemberUpdate.js +44 -0
  30. package/src/client/actions/GuildRoleCreate.js +25 -0
  31. package/src/client/actions/GuildRoleDelete.js +31 -0
  32. package/src/client/actions/GuildRoleUpdate.js +39 -0
  33. package/src/client/actions/GuildRolesPositionUpdate.js +21 -0
  34. package/src/client/actions/GuildScheduledEventCreate.js +27 -0
  35. package/src/client/actions/GuildScheduledEventDelete.js +31 -0
  36. package/src/client/actions/GuildScheduledEventUpdate.js +30 -0
  37. package/src/client/actions/GuildScheduledEventUserAdd.js +32 -0
  38. package/src/client/actions/GuildScheduledEventUserRemove.js +32 -0
  39. package/src/client/actions/GuildStickerCreate.js +20 -0
  40. package/src/client/actions/GuildStickerDelete.js +21 -0
  41. package/src/client/actions/GuildStickerUpdate.js +20 -0
  42. package/src/client/actions/GuildStickersUpdate.js +34 -0
  43. package/src/client/actions/GuildUpdate.js +33 -0
  44. package/src/client/actions/InteractionCreate.js +115 -0
  45. package/src/client/actions/InviteCreate.js +28 -0
  46. package/src/client/actions/InviteDelete.js +30 -0
  47. package/src/client/actions/MessageCreate.js +50 -0
  48. package/src/client/actions/MessageDelete.js +32 -0
  49. package/src/client/actions/MessageDeleteBulk.js +46 -0
  50. package/src/client/actions/MessageReactionAdd.js +56 -0
  51. package/src/client/actions/MessageReactionRemove.js +45 -0
  52. package/src/client/actions/MessageReactionRemoveAll.js +33 -0
  53. package/src/client/actions/MessageReactionRemoveEmoji.js +28 -0
  54. package/src/client/actions/MessageUpdate.js +26 -0
  55. package/src/client/actions/PresenceUpdate.js +45 -0
  56. package/src/client/actions/StageInstanceCreate.js +28 -0
  57. package/src/client/actions/StageInstanceDelete.js +33 -0
  58. package/src/client/actions/StageInstanceUpdate.js +30 -0
  59. package/src/client/actions/ThreadCreate.js +24 -0
  60. package/src/client/actions/ThreadDelete.js +32 -0
  61. package/src/client/actions/ThreadListSync.js +59 -0
  62. package/src/client/actions/ThreadMemberUpdate.js +30 -0
  63. package/src/client/actions/ThreadMembersUpdate.js +34 -0
  64. package/src/client/actions/TypingStart.js +29 -0
  65. package/src/client/actions/UserUpdate.js +35 -0
  66. package/src/client/actions/VoiceStateUpdate.js +57 -0
  67. package/src/client/actions/WebhooksUpdate.js +20 -0
  68. package/src/client/voice/ClientVoiceManager.js +51 -0
  69. package/src/client/websocket/WebSocketManager.js +412 -0
  70. package/src/client/websocket/WebSocketShard.js +908 -0
  71. package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +23 -0
  72. package/src/client/websocket/handlers/APPLICATION_COMMAND_CREATE.js +18 -0
  73. package/src/client/websocket/handlers/APPLICATION_COMMAND_DELETE.js +20 -0
  74. package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js +5 -0
  75. package/src/client/websocket/handlers/APPLICATION_COMMAND_UPDATE.js +20 -0
  76. package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js +5 -0
  77. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js +5 -0
  78. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js +5 -0
  79. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js +5 -0
  80. package/src/client/websocket/handlers/CALL_CREATE.js +14 -0
  81. package/src/client/websocket/handlers/CALL_DELETE.js +11 -0
  82. package/src/client/websocket/handlers/CALL_UPDATE.js +11 -0
  83. package/src/client/websocket/handlers/CHANNEL_CREATE.js +5 -0
  84. package/src/client/websocket/handlers/CHANNEL_DELETE.js +5 -0
  85. package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +22 -0
  86. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +16 -0
  87. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +16 -0
  88. package/src/client/websocket/handlers/CHANNEL_UPDATE.js +16 -0
  89. package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +11 -0
  90. package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js +5 -0
  91. package/src/client/websocket/handlers/GUILD_BAN_ADD.js +5 -0
  92. package/src/client/websocket/handlers/GUILD_BAN_REMOVE.js +5 -0
  93. package/src/client/websocket/handlers/GUILD_CREATE.js +46 -0
  94. package/src/client/websocket/handlers/GUILD_DELETE.js +5 -0
  95. package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js +5 -0
  96. package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js +5 -0
  97. package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +39 -0
  98. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +20 -0
  99. package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +55 -0
  100. package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js +5 -0
  101. package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js +5 -0
  102. package/src/client/websocket/handlers/GUILD_ROLE_CREATE.js +5 -0
  103. package/src/client/websocket/handlers/GUILD_ROLE_DELETE.js +5 -0
  104. package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js +5 -0
  105. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.js +5 -0
  106. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.js +5 -0
  107. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.js +5 -0
  108. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.js +5 -0
  109. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.js +5 -0
  110. package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.js +5 -0
  111. package/src/client/websocket/handlers/GUILD_UPDATE.js +5 -0
  112. package/src/client/websocket/handlers/INTERACTION_CREATE.js +16 -0
  113. package/src/client/websocket/handlers/INTERACTION_FAILURE.js +18 -0
  114. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +11 -0
  115. package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +30 -0
  116. package/src/client/websocket/handlers/INVITE_CREATE.js +5 -0
  117. package/src/client/websocket/handlers/INVITE_DELETE.js +5 -0
  118. package/src/client/websocket/handlers/MESSAGE_ACK.js +16 -0
  119. package/src/client/websocket/handlers/MESSAGE_CREATE.js +5 -0
  120. package/src/client/websocket/handlers/MESSAGE_DELETE.js +5 -0
  121. package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js +5 -0
  122. package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js +5 -0
  123. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js +5 -0
  124. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js +5 -0
  125. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js +5 -0
  126. package/src/client/websocket/handlers/MESSAGE_UPDATE.js +16 -0
  127. package/src/client/websocket/handlers/PRESENCE_UPDATE.js +5 -0
  128. package/src/client/websocket/handlers/READY.js +172 -0
  129. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +17 -0
  130. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +15 -0
  131. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +18 -0
  132. package/src/client/websocket/handlers/RESUMED.js +14 -0
  133. package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.js +5 -0
  134. package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.js +5 -0
  135. package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.js +5 -0
  136. package/src/client/websocket/handlers/THREAD_CREATE.js +5 -0
  137. package/src/client/websocket/handlers/THREAD_DELETE.js +5 -0
  138. package/src/client/websocket/handlers/THREAD_LIST_SYNC.js +5 -0
  139. package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.js +5 -0
  140. package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.js +5 -0
  141. package/src/client/websocket/handlers/THREAD_UPDATE.js +16 -0
  142. package/src/client/websocket/handlers/TYPING_START.js +5 -0
  143. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +12 -0
  144. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +5 -0
  145. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +9 -0
  146. package/src/client/websocket/handlers/USER_UPDATE.js +5 -0
  147. package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +6 -0
  148. package/src/client/websocket/handlers/VOICE_STATE_UPDATE.js +5 -0
  149. package/src/client/websocket/handlers/WEBHOOKS_UPDATE.js +5 -0
  150. package/src/client/websocket/handlers/index.js +86 -0
  151. package/src/errors/DJSError.js +61 -0
  152. package/src/errors/Messages.js +227 -0
  153. package/src/errors/index.js +4 -0
  154. package/src/index.js +190 -0
  155. package/src/main.js +48 -0
  156. package/src/managers/ApplicationCommandManager.js +267 -0
  157. package/src/managers/ApplicationCommandPermissionsManager.js +425 -0
  158. package/src/managers/AutoModerationRuleManager.js +296 -0
  159. package/src/managers/BaseGuildEmojiManager.js +80 -0
  160. package/src/managers/BaseManager.js +19 -0
  161. package/src/managers/BillingManager.js +66 -0
  162. package/src/managers/CachedManager.js +71 -0
  163. package/src/managers/ChannelManager.js +139 -0
  164. package/src/managers/ClientUserSettingManager.js +490 -0
  165. package/src/managers/DataManager.js +61 -0
  166. package/src/managers/DeveloperPortalManager.js +104 -0
  167. package/src/managers/GuildApplicationCommandManager.js +28 -0
  168. package/src/managers/GuildBanManager.js +204 -0
  169. package/src/managers/GuildChannelManager.js +502 -0
  170. package/src/managers/GuildEmojiManager.js +171 -0
  171. package/src/managers/GuildEmojiRoleManager.js +118 -0
  172. package/src/managers/GuildFolderManager.js +24 -0
  173. package/src/managers/GuildForumThreadManager.js +114 -0
  174. package/src/managers/GuildInviteManager.js +213 -0
  175. package/src/managers/GuildManager.js +304 -0
  176. package/src/managers/GuildMemberManager.js +724 -0
  177. package/src/managers/GuildMemberRoleManager.js +191 -0
  178. package/src/managers/GuildScheduledEventManager.js +296 -0
  179. package/src/managers/GuildSettingManager.js +148 -0
  180. package/src/managers/GuildStickerManager.js +179 -0
  181. package/src/managers/GuildTextThreadManager.js +98 -0
  182. package/src/managers/InteractionManager.js +39 -0
  183. package/src/managers/MessageManager.js +393 -0
  184. package/src/managers/PermissionOverwriteManager.js +166 -0
  185. package/src/managers/PresenceManager.js +58 -0
  186. package/src/managers/ReactionManager.js +67 -0
  187. package/src/managers/ReactionUserManager.js +71 -0
  188. package/src/managers/RelationshipManager.js +258 -0
  189. package/src/managers/RoleManager.js +352 -0
  190. package/src/managers/SessionManager.js +57 -0
  191. package/src/managers/StageInstanceManager.js +162 -0
  192. package/src/managers/ThreadManager.js +207 -0
  193. package/src/managers/ThreadMemberManager.js +186 -0
  194. package/src/managers/UserManager.js +150 -0
  195. package/src/managers/VoiceStateManager.js +37 -0
  196. package/src/rest/APIRequest.js +136 -0
  197. package/src/rest/APIRouter.js +53 -0
  198. package/src/rest/CaptchaSolver.js +78 -0
  199. package/src/rest/DiscordAPIError.js +103 -0
  200. package/src/rest/HTTPError.js +62 -0
  201. package/src/rest/RESTManager.js +81 -0
  202. package/src/rest/RateLimitError.js +55 -0
  203. package/src/rest/RequestHandler.js +446 -0
  204. package/src/sharding/Shard.js +443 -0
  205. package/src/sharding/ShardClientUtil.js +275 -0
  206. package/src/sharding/ShardingManager.js +318 -0
  207. package/src/structures/AnonymousGuild.js +98 -0
  208. package/src/structures/ApplicationCommand.js +1028 -0
  209. package/src/structures/ApplicationRoleConnectionMetadata.js +45 -0
  210. package/src/structures/AutoModerationActionExecution.js +89 -0
  211. package/src/structures/AutoModerationRule.js +294 -0
  212. package/src/structures/AutocompleteInteraction.js +106 -0
  213. package/src/structures/Base.js +43 -0
  214. package/src/structures/BaseCommandInteraction.js +211 -0
  215. package/src/structures/BaseGuild.js +116 -0
  216. package/src/structures/BaseGuildEmoji.js +56 -0
  217. package/src/structures/BaseGuildTextChannel.js +193 -0
  218. package/src/structures/BaseGuildVoiceChannel.js +243 -0
  219. package/src/structures/BaseMessageComponent.js +114 -0
  220. package/src/structures/ButtonInteraction.js +11 -0
  221. package/src/structures/Call.js +58 -0
  222. package/src/structures/CategoryChannel.js +83 -0
  223. package/src/structures/Channel.js +271 -0
  224. package/src/structures/ClientApplication.js +204 -0
  225. package/src/structures/ClientPresence.js +84 -0
  226. package/src/structures/ClientUser.js +624 -0
  227. package/src/structures/CommandInteraction.js +41 -0
  228. package/src/structures/CommandInteractionOptionResolver.js +276 -0
  229. package/src/structures/ContextMenuInteraction.js +65 -0
  230. package/src/structures/DMChannel.js +280 -0
  231. package/src/structures/DeveloperPortalApplication.js +520 -0
  232. package/src/structures/DirectoryChannel.js +20 -0
  233. package/src/structures/Emoji.js +148 -0
  234. package/src/structures/ForumChannel.js +271 -0
  235. package/src/structures/Guild.js +1744 -0
  236. package/src/structures/GuildAuditLogs.js +734 -0
  237. package/src/structures/GuildBan.js +59 -0
  238. package/src/structures/GuildBoost.js +108 -0
  239. package/src/structures/GuildChannel.js +454 -0
  240. package/src/structures/GuildEmoji.js +161 -0
  241. package/src/structures/GuildFolder.js +75 -0
  242. package/src/structures/GuildMember.js +686 -0
  243. package/src/structures/GuildPreview.js +191 -0
  244. package/src/structures/GuildPreviewEmoji.js +27 -0
  245. package/src/structures/GuildScheduledEvent.js +441 -0
  246. package/src/structures/GuildTemplate.js +236 -0
  247. package/src/structures/Integration.js +188 -0
  248. package/src/structures/IntegrationApplication.js +96 -0
  249. package/src/structures/Interaction.js +351 -0
  250. package/src/structures/InteractionCollector.js +248 -0
  251. package/src/structures/InteractionResponse.js +114 -0
  252. package/src/structures/InteractionWebhook.js +43 -0
  253. package/src/structures/Invite.js +375 -0
  254. package/src/structures/InviteGuild.js +23 -0
  255. package/src/structures/InviteStageInstance.js +86 -0
  256. package/src/structures/Message.js +1188 -0
  257. package/src/structures/MessageActionRow.js +103 -0
  258. package/src/structures/MessageAttachment.js +193 -0
  259. package/src/structures/MessageButton.js +231 -0
  260. package/src/structures/MessageCollector.js +146 -0
  261. package/src/structures/MessageComponentInteraction.js +120 -0
  262. package/src/structures/MessageContextMenuInteraction.js +20 -0
  263. package/src/structures/MessageEmbed.js +586 -0
  264. package/src/structures/MessageMentions.js +272 -0
  265. package/src/structures/MessagePayload.js +358 -0
  266. package/src/structures/MessageReaction.js +171 -0
  267. package/src/structures/MessageSelectMenu.js +391 -0
  268. package/src/structures/Modal.js +279 -0
  269. package/src/structures/ModalSubmitFieldsResolver.js +53 -0
  270. package/src/structures/ModalSubmitInteraction.js +119 -0
  271. package/src/structures/NewsChannel.js +32 -0
  272. package/src/structures/OAuth2Guild.js +28 -0
  273. package/src/structures/PartialGroupDMChannel.js +430 -0
  274. package/src/structures/PermissionOverwrites.js +196 -0
  275. package/src/structures/Presence.js +441 -0
  276. package/src/structures/ReactionCollector.js +229 -0
  277. package/src/structures/ReactionEmoji.js +31 -0
  278. package/src/structures/RichPresence.js +722 -0
  279. package/src/structures/Role.js +515 -0
  280. package/src/structures/SelectMenuInteraction.js +170 -0
  281. package/src/structures/Session.js +81 -0
  282. package/src/structures/StageChannel.js +104 -0
  283. package/src/structures/StageInstance.js +208 -0
  284. package/src/structures/Sticker.js +310 -0
  285. package/src/structures/StickerPack.js +95 -0
  286. package/src/structures/StoreChannel.js +56 -0
  287. package/src/structures/Team.js +167 -0
  288. package/src/structures/TeamMember.js +71 -0
  289. package/src/structures/TextChannel.js +33 -0
  290. package/src/structures/TextInputComponent.js +201 -0
  291. package/src/structures/ThreadChannel.js +626 -0
  292. package/src/structures/ThreadMember.js +105 -0
  293. package/src/structures/Typing.js +74 -0
  294. package/src/structures/User.js +697 -0
  295. package/src/structures/UserContextMenuInteraction.js +29 -0
  296. package/src/structures/VoiceChannel.js +110 -0
  297. package/src/structures/VoiceRegion.js +53 -0
  298. package/src/structures/VoiceState.js +306 -0
  299. package/src/structures/WebEmbed.js +401 -0
  300. package/src/structures/Webhook.js +461 -0
  301. package/src/structures/WelcomeChannel.js +60 -0
  302. package/src/structures/WelcomeScreen.js +48 -0
  303. package/src/structures/Widget.js +87 -0
  304. package/src/structures/WidgetMember.js +99 -0
  305. package/src/structures/interfaces/Application.js +190 -0
  306. package/src/structures/interfaces/Collector.js +300 -0
  307. package/src/structures/interfaces/InteractionResponses.js +313 -0
  308. package/src/structures/interfaces/TextBasedChannel.js +566 -0
  309. package/src/util/ActivityFlags.js +44 -0
  310. package/src/util/ApplicationFlags.js +74 -0
  311. package/src/util/BitField.js +170 -0
  312. package/src/util/ChannelFlags.js +45 -0
  313. package/src/util/Constants.js +1917 -0
  314. package/src/util/DataResolver.js +145 -0
  315. package/src/util/Formatters.js +214 -0
  316. package/src/util/GuildMemberFlags.js +43 -0
  317. package/src/util/Intents.js +74 -0
  318. package/src/util/LimitedCollection.js +131 -0
  319. package/src/util/MessageFlags.js +54 -0
  320. package/src/util/Options.js +360 -0
  321. package/src/util/Permissions.js +187 -0
  322. package/src/util/PremiumUsageFlags.js +31 -0
  323. package/src/util/PurchasedFlags.js +31 -0
  324. package/src/util/RemoteAuth.js +522 -0
  325. package/src/util/SnowflakeUtil.js +92 -0
  326. package/src/util/Sweepers.js +466 -0
  327. package/src/util/SystemChannelFlags.js +55 -0
  328. package/src/util/ThreadMemberFlags.js +30 -0
  329. package/src/util/UserFlags.js +104 -0
  330. package/src/util/Util.js +741 -0
  331. package/src/util/Voice.js +1456 -0
  332. package/src/util/arRPC/index.js +229 -0
  333. package/src/util/arRPC/process/detectable.json +1 -0
  334. package/src/util/arRPC/process/index.js +102 -0
  335. package/src/util/arRPC/process/native/index.js +5 -0
  336. package/src/util/arRPC/process/native/linux.js +37 -0
  337. package/src/util/arRPC/process/native/win32.js +25 -0
  338. package/src/util/arRPC/transports/ipc.js +281 -0
  339. package/src/util/arRPC/transports/websocket.js +128 -0
  340. package/typings/enums.d.ts +346 -0
  341. package/typings/index.d.ts +7725 -0
  342. package/typings/index.test-d.ts +0 -0
  343. package/typings/rawDataTypes.d.ts +283 -0
@@ -0,0 +1,1028 @@
1
+ 'use strict';
2
+
3
+ const { setTimeout } = require('node:timers');
4
+ const { findBestMatch } = require('string-similarity');
5
+ const Base = require('./Base');
6
+ const MessagePayload = require('./MessagePayload');
7
+ const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager');
8
+ const {
9
+ ApplicationCommandOptionTypes,
10
+ ApplicationCommandTypes,
11
+ ChannelTypes,
12
+ Events,
13
+ InteractionTypes,
14
+ } = require('../util/Constants');
15
+ const Permissions = require('../util/Permissions');
16
+ const SnowflakeUtil = require('../util/SnowflakeUtil');
17
+ const { lazy, getAttachments, uploadFile } = require('../util/Util');
18
+ const Message = lazy(() => require('../structures/Message').Message);
19
+
20
+ /**
21
+ * Represents an application command.
22
+ * @extends {Base}
23
+ */
24
+ class ApplicationCommand extends Base {
25
+ constructor(client, data) {
26
+ super(client);
27
+
28
+ /**
29
+ * The command's id
30
+ * @type {Snowflake}
31
+ */
32
+ this.id = data.id;
33
+
34
+ /**
35
+ * The parent application's id
36
+ * @type {Snowflake}
37
+ */
38
+ this.applicationId = data.application_id;
39
+
40
+ /**
41
+ * The manager for permissions of this command on its guild or arbitrary guilds when the command is global
42
+ * @type {ApplicationCommandPermissionsManager}
43
+ */
44
+ this.permissions = new ApplicationCommandPermissionsManager(this, this.applicationId);
45
+
46
+ /**
47
+ * The type of this application command
48
+ * @type {ApplicationCommandType}
49
+ */
50
+ this.type = ApplicationCommandTypes[data.type];
51
+
52
+ this.user = client.users.cache.get(this.applicationId);
53
+
54
+ this._patch(data);
55
+ }
56
+
57
+ /**
58
+ * The guild this command is part of
59
+ * @type {?Guild}
60
+ * @readonly
61
+ */
62
+ get guild() {
63
+ return this.client.guilds.resolve(this.guildId);
64
+ }
65
+
66
+ _patch(data) {
67
+ if ('guild_id' in data) {
68
+ /**
69
+ * The guild's id this command is part of, this may be non-null when `guild` is `null` if the command
70
+ * was fetched from the `ApplicationCommandManager`
71
+ * @type {?Snowflake}
72
+ */
73
+ this.guildId = data.guild_id ?? null;
74
+ }
75
+
76
+ if ('name' in data) {
77
+ /**
78
+ * The name of this command
79
+ * @type {string}
80
+ */
81
+ this.name = data.name;
82
+ }
83
+
84
+ if ('name_localizations' in data) {
85
+ /**
86
+ * The name localizations for this command
87
+ * @type {?Object<Locale, string>}
88
+ */
89
+ this.nameLocalizations = data.name_localizations;
90
+ } else {
91
+ this.nameLocalizations ??= null;
92
+ }
93
+
94
+ if ('name_localized' in data) {
95
+ /**
96
+ * The localized name for this command
97
+ * @type {?string}
98
+ */
99
+ this.nameLocalized = data.name_localized;
100
+ } else {
101
+ this.nameLocalized ??= null;
102
+ }
103
+
104
+ if ('description' in data) {
105
+ /**
106
+ * The description of this command
107
+ * @type {string}
108
+ */
109
+ this.description = data.description;
110
+ }
111
+
112
+ if ('description_localizations' in data) {
113
+ /**
114
+ * The description localizations for this command
115
+ * @type {?Object<Locale, string>}
116
+ */
117
+ this.descriptionLocalizations = data.description_localizations;
118
+ } else {
119
+ this.descriptionLocalizations ??= null;
120
+ }
121
+
122
+ if ('description_localized' in data) {
123
+ /**
124
+ * The localized description for this command
125
+ * @type {?string}
126
+ */
127
+ this.descriptionLocalized = data.description_localized;
128
+ } else {
129
+ this.descriptionLocalized ??= null;
130
+ }
131
+
132
+ if ('options' in data) {
133
+ /**
134
+ * The options of this command
135
+ * @type {ApplicationCommandOption[]}
136
+ */
137
+ this.options = data.options.map(o => this.constructor.transformOption(o, true));
138
+ } else {
139
+ this.options ??= [];
140
+ }
141
+
142
+ /* eslint-disable max-len */
143
+ if ('default_permission' in data) {
144
+ /**
145
+ * Whether the command is enabled by default when the app is added to a guild
146
+ * @type {boolean}
147
+ * @deprecated Use {@link ApplicationCommand.defaultMemberPermissions} and {@link ApplicationCommand.dmPermission} instead.
148
+ */
149
+ this.defaultPermission = data.default_permission;
150
+ }
151
+
152
+ /* eslint-disable max-len */
153
+
154
+ if ('default_member_permissions' in data) {
155
+ /**
156
+ * The default bitfield used to determine whether this command be used in a guild
157
+ * @type {?Readonly<Permissions>}
158
+ */
159
+ this.defaultMemberPermissions = data.default_member_permissions
160
+ ? new Permissions(BigInt(data.default_member_permissions)).freeze()
161
+ : null;
162
+ } else {
163
+ this.defaultMemberPermissions ??= null;
164
+ }
165
+
166
+ if ('dm_permission' in data) {
167
+ /**
168
+ * Whether the command can be used in DMs
169
+ * <info>This property is always `null` on guild commands</info>
170
+ * @type {?boolean}
171
+ */
172
+ this.dmPermission = data.dm_permission;
173
+ } else {
174
+ this.dmPermission ??= null;
175
+ }
176
+
177
+ if ('version' in data) {
178
+ /**
179
+ * Autoincrementing version identifier updated during substantial record changes
180
+ * @type {Snowflake}
181
+ */
182
+ this.version = data.version;
183
+ }
184
+ }
185
+
186
+ /**
187
+ * The timestamp the command was created at
188
+ * @type {number}
189
+ * @readonly
190
+ */
191
+ get createdTimestamp() {
192
+ return SnowflakeUtil.timestampFrom(this.id);
193
+ }
194
+
195
+ /**
196
+ * The time the command was created at
197
+ * @type {Date}
198
+ * @readonly
199
+ */
200
+ get createdAt() {
201
+ return new Date(this.createdTimestamp);
202
+ }
203
+
204
+ /**
205
+ * The manager that this command belongs to
206
+ * @type {ApplicationCommandManager}
207
+ * @readonly
208
+ */
209
+ get manager() {
210
+ return (this.guild ?? this.client.application).commands;
211
+ }
212
+
213
+ /**
214
+ * Data for creating or editing an application command.
215
+ * @typedef {Object} ApplicationCommandData
216
+ * @property {string} name The name of the command
217
+ * @property {Object<Locale, string>} [nameLocalizations] The localizations for the command name
218
+ * @property {string} description The description of the command
219
+ * @property {Object<Locale, string>} [descriptionLocalizations] The localizations for the command description
220
+ * @property {ApplicationCommandType} [type] The type of the command
221
+ * @property {ApplicationCommandOptionData[]} [options] Options for the command
222
+ * @property {boolean} [defaultPermission] Whether the command is enabled by default when the app is added to a guild
223
+ * @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions
224
+ * a member needs in order to run the command
225
+ * @property {boolean} [dmPermission] Whether the command is enabled in DMs
226
+ */
227
+
228
+ /**
229
+ * An option for an application command or subcommand.
230
+ * <info>In addition to the listed properties, when used as a parameter,
231
+ * API style `snake_case` properties can be used for compatibility with generators like `@discordjs/builders`.</info>
232
+ * <warn>Note that providing a value for the `camelCase` counterpart for any `snake_case` property
233
+ * will discard the provided `snake_case` property.</warn>
234
+ * @typedef {Object} ApplicationCommandOptionData
235
+ * @property {ApplicationCommandOptionType|number} type The type of the option
236
+ * @property {string} name The name of the option
237
+ * @property {Object<Locale, string>} [nameLocalizations] The name localizations for the option
238
+ * @property {string} description The description of the option
239
+ * @property {Object<Locale, string>} [descriptionLocalizations] The description localizations for the option
240
+ * @property {boolean} [autocomplete] Whether the option is an autocomplete option
241
+ * @property {boolean} [required] Whether the option is required
242
+ * @property {ApplicationCommandOptionChoiceData[]} [choices] The choices of the option for the user to pick from
243
+ * @property {ApplicationCommandOptionData[]} [options] Additional options if this option is a subcommand (group)
244
+ * @property {ChannelType[]|number[]} [channelTypes] When the option type is channel,
245
+ * the allowed types of channels that can be selected
246
+ * @property {number} [minValue] The minimum value for an `INTEGER` or `NUMBER` option
247
+ * @property {number} [maxValue] The maximum value for an `INTEGER` or `NUMBER` option
248
+ * @property {number} [minLength] The minimum length for a `STRING` option
249
+ * (maximum of `6000`)
250
+ * @property {number} [maxLength] The maximum length for a `STRING` option
251
+ * (maximum of `6000`)
252
+ */
253
+
254
+ /**
255
+ * @typedef {Object} ApplicationCommandOptionChoiceData
256
+ * @property {string} name The name of the choice
257
+ * @property {Object<Locale, string>} [nameLocalizations] The localized names for this choice
258
+ * @property {string|number} value The value of the choice
259
+ */
260
+
261
+ /**
262
+ * Edits this application command.
263
+ * @param {Partial<ApplicationCommandData>} data The data to update the command with
264
+ * @returns {Promise<ApplicationCommand>}
265
+ * @example
266
+ * // Edit the description of this command
267
+ * command.edit({
268
+ * description: 'New description',
269
+ * })
270
+ * .then(console.log)
271
+ * .catch(console.error);
272
+ */
273
+ edit(data) {
274
+ return this.manager.edit(this, data, this.guildId);
275
+ }
276
+
277
+ /**
278
+ * Edits the name of this ApplicationCommand
279
+ * @param {string} name The new name of the command
280
+ * @returns {Promise<ApplicationCommand>}
281
+ */
282
+ setName(name) {
283
+ return this.edit({ name });
284
+ }
285
+
286
+ /**
287
+ * Edits the localized names of this ApplicationCommand
288
+ * @param {Object<Locale, string>} nameLocalizations The new localized names for the command
289
+ * @returns {Promise<ApplicationCommand>}
290
+ * @example
291
+ * // Edit the name localizations of this command
292
+ * command.setLocalizedNames({
293
+ * 'en-GB': 'test',
294
+ * 'pt-BR': 'teste',
295
+ * })
296
+ * .then(console.log)
297
+ * .catch(console.error)
298
+ */
299
+ setNameLocalizations(nameLocalizations) {
300
+ return this.edit({ nameLocalizations });
301
+ }
302
+
303
+ /**
304
+ * Edits the description of this ApplicationCommand
305
+ * @param {string} description The new description of the command
306
+ * @returns {Promise<ApplicationCommand>}
307
+ */
308
+ setDescription(description) {
309
+ return this.edit({ description });
310
+ }
311
+
312
+ /**
313
+ * Edits the localized descriptions of this ApplicationCommand
314
+ * @param {Object<Locale, string>} descriptionLocalizations The new localized descriptions for the command
315
+ * @returns {Promise<ApplicationCommand>}
316
+ * @example
317
+ * // Edit the description localizations of this command
318
+ * command.setLocalizedDescriptions({
319
+ * 'en-GB': 'A test command',
320
+ * 'pt-BR': 'Um comando de teste',
321
+ * })
322
+ * .then(console.log)
323
+ * .catch(console.error)
324
+ */
325
+ setDescriptionLocalizations(descriptionLocalizations) {
326
+ return this.edit({ descriptionLocalizations });
327
+ }
328
+
329
+ /* eslint-disable max-len */
330
+ /**
331
+ * Edits the default permission of this ApplicationCommand
332
+ * @param {boolean} [defaultPermission=true] The default permission for this command
333
+ * @returns {Promise<ApplicationCommand>}
334
+ * @deprecated Use {@link ApplicationCommand#setDefaultMemberPermissions} and {@link ApplicationCommand#setDMPermission} instead.
335
+ */
336
+ setDefaultPermission(defaultPermission = true) {
337
+ return this.edit({ defaultPermission });
338
+ }
339
+
340
+ /* eslint-enable max-len */
341
+
342
+ /**
343
+ * Edits the default member permissions of this ApplicationCommand
344
+ * @param {?PermissionResolvable} defaultMemberPermissions The default member permissions required to run this command
345
+ * @returns {Promise<ApplicationCommand>}
346
+ */
347
+ setDefaultMemberPermissions(defaultMemberPermissions) {
348
+ return this.edit({ defaultMemberPermissions });
349
+ }
350
+
351
+ /**
352
+ * Edits the DM permission of this ApplicationCommand
353
+ * @param {boolean} [dmPermission=true] Whether the command can be used in DMs
354
+ * @returns {Promise<ApplicationCommand>}
355
+ */
356
+ setDMPermission(dmPermission = true) {
357
+ return this.edit({ dmPermission });
358
+ }
359
+
360
+ /**
361
+ * Edits the options of this ApplicationCommand
362
+ * @param {ApplicationCommandOptionData[]} options The options to set for this command
363
+ * @returns {Promise<ApplicationCommand>}
364
+ */
365
+ setOptions(options) {
366
+ return this.edit({ options });
367
+ }
368
+
369
+ /**
370
+ * Deletes this command.
371
+ * @returns {Promise<ApplicationCommand>}
372
+ * @example
373
+ * // Delete this command
374
+ * command.delete()
375
+ * .then(console.log)
376
+ * .catch(console.error);
377
+ */
378
+ delete() {
379
+ return this.manager.delete(this, this.guildId);
380
+ }
381
+
382
+ /**
383
+ * Whether this command equals another command. It compares all properties, so for most operations
384
+ * it is advisable to just compare `command.id === command2.id` as it is much faster and is often
385
+ * what most users need.
386
+ * @param {ApplicationCommand|ApplicationCommandData|APIApplicationCommand} command The command to compare with
387
+ * @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options and choices are in the same
388
+ * order in the array <info>The client may not always respect this ordering!</info>
389
+ * @returns {boolean}
390
+ */
391
+ equals(command, enforceOptionOrder = false) {
392
+ // If given an id, check if the id matches
393
+ if (command.id && this.id !== command.id) return false;
394
+ let defaultMemberPermissions = null;
395
+ let dmPermission = command.dmPermission ?? command.dm_permission;
396
+
397
+ if ('default_member_permissions' in command) {
398
+ defaultMemberPermissions = command.default_member_permissions
399
+ ? new Permissions(BigInt(command.default_member_permissions)).bitfield
400
+ : null;
401
+ }
402
+
403
+ if ('defaultMemberPermissions' in command) {
404
+ defaultMemberPermissions =
405
+ command.defaultMemberPermissions !== null ? new Permissions(command.defaultMemberPermissions).bitfield : null;
406
+ }
407
+ // Check top level parameters
408
+ const commandType = typeof command.type === 'string' ? command.type : ApplicationCommandTypes[command.type];
409
+ if (
410
+ command.name !== this.name ||
411
+ ('description' in command && command.description !== this.description) ||
412
+ ('version' in command && command.version !== this.version) ||
413
+ ('autocomplete' in command && command.autocomplete !== this.autocomplete) ||
414
+ (commandType && commandType !== this.type) ||
415
+ defaultMemberPermissions !== (this.defaultMemberPermissions?.bitfield ?? null) ||
416
+ (typeof dmPermission !== 'undefined' && dmPermission !== this.dmPermission) ||
417
+ // Future proof for options being nullable
418
+ // TODO: remove ?? 0 on each when nullable
419
+ (command.options?.length ?? 0) !== (this.options?.length ?? 0) ||
420
+ (command.defaultPermission ?? command.default_permission ?? true) !== this.defaultPermission
421
+ ) {
422
+ return false;
423
+ }
424
+
425
+ if (command.options) {
426
+ return this.constructor.optionsEqual(this.options, command.options, enforceOptionOrder);
427
+ }
428
+ return true;
429
+ }
430
+
431
+ /**
432
+ * Recursively checks that all options for an {@link ApplicationCommand} are equal to the provided options.
433
+ * In most cases it is better to compare using {@link ApplicationCommand#equals}
434
+ * @param {ApplicationCommandOptionData[]} existing The options on the existing command,
435
+ * should be {@link ApplicationCommand#options}
436
+ * @param {ApplicationCommandOptionData[]|APIApplicationCommandOption[]} options The options to compare against
437
+ * @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options and choices are in the same
438
+ * order in the array <info>The client may not always respect this ordering!</info>
439
+ * @returns {boolean}
440
+ */
441
+ static optionsEqual(existing, options, enforceOptionOrder = false) {
442
+ if (existing.length !== options.length) return false;
443
+ if (enforceOptionOrder) {
444
+ return existing.every((option, index) => this._optionEquals(option, options[index], enforceOptionOrder));
445
+ }
446
+ const newOptions = new Map(options.map(option => [option.name, option]));
447
+ for (const option of existing) {
448
+ const foundOption = newOptions.get(option.name);
449
+ if (!foundOption || !this._optionEquals(option, foundOption)) {
450
+ return false;
451
+ }
452
+ }
453
+ return true;
454
+ }
455
+
456
+ /**
457
+ * Checks that an option for an {@link ApplicationCommand} is equal to the provided option
458
+ * In most cases it is better to compare using {@link ApplicationCommand#equals}
459
+ * @param {ApplicationCommandOptionData} existing The option on the existing command,
460
+ * should be from {@link ApplicationCommand#options}
461
+ * @param {ApplicationCommandOptionData|APIApplicationCommandOption} option The option to compare against
462
+ * @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options or choices are in the same
463
+ * order in their array <info>The client may not always respect this ordering!</info>
464
+ * @returns {boolean}
465
+ * @private
466
+ */
467
+ static _optionEquals(existing, option, enforceOptionOrder = false) {
468
+ const optionType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionTypes[option.type];
469
+ if (
470
+ option.name !== existing.name ||
471
+ optionType !== existing.type ||
472
+ option.description !== existing.description ||
473
+ option.autocomplete !== existing.autocomplete ||
474
+ (option.required ?? (['SUB_COMMAND', 'SUB_COMMAND_GROUP'].includes(optionType) ? undefined : false)) !==
475
+ existing.required ||
476
+ option.choices?.length !== existing.choices?.length ||
477
+ option.options?.length !== existing.options?.length ||
478
+ (option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length ||
479
+ (option.minValue ?? option.min_value) !== existing.minValue ||
480
+ (option.maxValue ?? option.max_value) !== existing.maxValue ||
481
+ (option.minLength ?? option.min_length) !== existing.minLength ||
482
+ (option.maxLength ?? option.max_length) !== existing.maxLength
483
+ ) {
484
+ return false;
485
+ }
486
+
487
+ if (existing.choices) {
488
+ if (
489
+ enforceOptionOrder &&
490
+ !existing.choices.every(
491
+ (choice, index) => choice.name === option.choices[index].name && choice.value === option.choices[index].value,
492
+ )
493
+ ) {
494
+ return false;
495
+ }
496
+ if (!enforceOptionOrder) {
497
+ const newChoices = new Map(option.choices.map(choice => [choice.name, choice]));
498
+ for (const choice of existing.choices) {
499
+ const foundChoice = newChoices.get(choice.name);
500
+ if (!foundChoice || foundChoice.value !== choice.value) return false;
501
+ }
502
+ }
503
+ }
504
+
505
+ if (existing.channelTypes) {
506
+ const newTypes = (option.channelTypes ?? option.channel_types).map(type =>
507
+ typeof type === 'number' ? ChannelTypes[type] : type,
508
+ );
509
+ for (const type of existing.channelTypes) {
510
+ if (!newTypes.includes(type)) return false;
511
+ }
512
+ }
513
+
514
+ if (existing.options) {
515
+ return this.optionsEqual(existing.options, option.options, enforceOptionOrder);
516
+ }
517
+ return true;
518
+ }
519
+
520
+ /**
521
+ * An option for an application command or subcommand.
522
+ * @typedef {Object} ApplicationCommandOption
523
+ * @property {ApplicationCommandOptionType} type The type of the option
524
+ * @property {string} name The name of the option
525
+ * @property {Object<string, string>} [nameLocalizations] The localizations for the option name
526
+ * @property {string} [nameLocalized] The localized name for this option
527
+ * @property {string} description The description of the option
528
+ * @property {Object<string, string>} [descriptionLocalizations] The localizations for the option description
529
+ * @property {string} [descriptionLocalized] The localized description for this option
530
+ * @property {boolean} [required] Whether the option is required
531
+ * @property {boolean} [autocomplete] Whether the option is an autocomplete option
532
+ * @property {ApplicationCommandOptionChoice[]} [choices] The choices of the option for the user to pick from
533
+ * @property {ApplicationCommandOption[]} [options] Additional options if this option is a subcommand (group)
534
+ * @property {ChannelType[]} [channelTypes] When the option type is channel,
535
+ * the allowed types of channels that can be selected
536
+ * @property {number} [minValue] The minimum value for an `INTEGER` or `NUMBER` option
537
+ * @property {number} [maxValue] The maximum value for an `INTEGER` or `NUMBER` option
538
+ * @property {number} [minLength] The minimum length for a `STRING` option
539
+ * (maximum of `6000`)
540
+ * @property {number} [maxLength] The maximum length for a `STRING` option
541
+ * (maximum of `6000`)
542
+ */
543
+
544
+ /**
545
+ * A choice for an application command option.
546
+ * @typedef {Object} ApplicationCommandOptionChoice
547
+ * @property {string} name The name of the choice
548
+ * @property {?string} nameLocalized The localized name of the choice in the provided locale, if any
549
+ * @property {?Object<string, string>} [nameLocalizations] The localized names for this choice
550
+ * @property {string|number} value The value of the choice
551
+ */
552
+
553
+ /**
554
+ * Transforms an {@link ApplicationCommandOptionData} object into something that can be used with the API.
555
+ * @param {ApplicationCommandOptionData|ApplicationCommandOption} option The option to transform
556
+ * @param {boolean} [received] Whether this option has been received from Discord
557
+ * @returns {APIApplicationCommandOption}
558
+ * @private
559
+ */
560
+ static transformOption(option, received) {
561
+ const stringType = typeof option.type === 'string' ? option.type : ApplicationCommandOptionTypes[option.type];
562
+ const channelTypesKey = received ? 'channelTypes' : 'channel_types';
563
+ const minValueKey = received ? 'minValue' : 'min_value';
564
+ const maxValueKey = received ? 'maxValue' : 'max_value';
565
+ const minLengthKey = received ? 'minLength' : 'min_length';
566
+ const maxLengthKey = received ? 'maxLength' : 'max_length';
567
+ const nameLocalizationsKey = received ? 'nameLocalizations' : 'name_localizations';
568
+ const nameLocalizedKey = received ? 'nameLocalized' : 'name_localized';
569
+ const descriptionLocalizationsKey = received ? 'descriptionLocalizations' : 'description_localizations';
570
+ const descriptionLocalizedKey = received ? 'descriptionLocalized' : 'description_localized';
571
+ return {
572
+ type: typeof option.type === 'number' && !received ? option.type : ApplicationCommandOptionTypes[option.type],
573
+ name: option.name,
574
+ [nameLocalizationsKey]: option.nameLocalizations ?? option.name_localizations,
575
+ [nameLocalizedKey]: option.nameLocalized ?? option.name_localized,
576
+ description: option.description,
577
+ [descriptionLocalizationsKey]: option.descriptionLocalizations ?? option.description_localizations,
578
+ [descriptionLocalizedKey]: option.descriptionLocalized ?? option.description_localized,
579
+ required:
580
+ option.required ?? (stringType === 'SUB_COMMAND' || stringType === 'SUB_COMMAND_GROUP' ? undefined : false),
581
+ autocomplete: option.autocomplete,
582
+ choices: option.choices?.map(choice => ({
583
+ name: choice.name,
584
+ [nameLocalizedKey]: choice.nameLocalized ?? choice.name_localized,
585
+ [nameLocalizationsKey]: choice.nameLocalizations ?? choice.name_localizations,
586
+ value: choice.value,
587
+ })),
588
+ options: option.options?.map(o => this.transformOption(o, received)),
589
+ [channelTypesKey]: received
590
+ ? option.channel_types?.map(type => ChannelTypes[type])
591
+ : option.channelTypes?.map(type => (typeof type === 'string' ? ChannelTypes[type] : type)) ??
592
+ // When transforming to API data, accept API data
593
+ option.channel_types,
594
+ [minValueKey]: option.minValue ?? option.min_value,
595
+ [maxValueKey]: option.maxValue ?? option.max_value,
596
+ [minLengthKey]: option.minLength ?? option.min_length,
597
+ [maxLengthKey]: option.maxLength ?? option.max_length,
598
+ };
599
+ }
600
+ /**
601
+ * Send Slash command to channel
602
+ * @param {Message} message Discord Message
603
+ * @param {Array<string>} subCommandArray SubCommand Array
604
+ * @param {Array<any>} options The options to Slash Command
605
+ * @returns {Promise<InteractionResponse>}
606
+ */
607
+ // eslint-disable-next-line consistent-return
608
+ async sendSlashCommand(message, subCommandArray = [], options = []) {
609
+ // Todo: Refactor [Done]
610
+ const buildError = (type, value, array, msg) =>
611
+ new Error(`Invalid ${type}: ${value} ${msg}\nList of ${type}:\n${array}`);
612
+ // Check Options
613
+ if (!(message instanceof Message())) {
614
+ throw new TypeError('The message must be a Discord.Message');
615
+ }
616
+ if (!Array.isArray(options)) {
617
+ throw new TypeError('The options must be an array of strings');
618
+ }
619
+ if (this.type !== 'CHAT_INPUT') throw new Error('This command is not a chat input [/]');
620
+ const optionFormat = [];
621
+ const attachments = [];
622
+ const attachmentsBuffer = [];
623
+ const parseChoices = (list_choices, value) => {
624
+ if (value !== undefined) {
625
+ if (Array.isArray(list_choices) && list_choices.length) {
626
+ const choice = list_choices.find(c => c.name === value) || list_choices.find(c => c.value === value);
627
+ if (choice) {
628
+ return choice.value;
629
+ }
630
+ throw buildError(
631
+ 'choice',
632
+ value,
633
+ list_choices.map((c, i) => ` #${i + 1} Name: ${c.name} Value: ${c.value}`).join('\n'),
634
+ 'is not a valid choice for this option',
635
+ );
636
+ } else {
637
+ return value;
638
+ }
639
+ } else {
640
+ return undefined;
641
+ }
642
+ };
643
+ const parseOption = async (optionCommand, value) => {
644
+ const data = {
645
+ type: ApplicationCommandOptionTypes[optionCommand.type],
646
+ name: optionCommand.name,
647
+ };
648
+ if (value !== undefined) {
649
+ value = parseChoices(optionCommand.choices, value);
650
+ switch (optionCommand.type) {
651
+ case 'BOOLEAN': {
652
+ data.value = Boolean(value);
653
+ break;
654
+ }
655
+ case 'INTEGER': {
656
+ data.value = Number(value);
657
+ break;
658
+ }
659
+ case 'ATTACHMENT': {
660
+ data.value = await addDataFromAttachment(value, this.client);
661
+ break;
662
+ }
663
+ case 'SUB_COMMAND_GROUP': {
664
+ break;
665
+ }
666
+ default: {
667
+ if (optionCommand.autocomplete) {
668
+ let optionsBuild;
669
+ switch (subCommandArray.length) {
670
+ case 0: {
671
+ optionsBuild = [
672
+ ...optionFormat,
673
+ {
674
+ type: ApplicationCommandOptionTypes[optionCommand.type],
675
+ name: optionCommand.name,
676
+ value,
677
+ focused: true,
678
+ },
679
+ ];
680
+ break;
681
+ }
682
+ case 1: {
683
+ const subCommand = this.options.find(o => o.name == subCommandArray[0] && o.type == 'SUB_COMMAND');
684
+ optionsBuild = [
685
+ {
686
+ type: ApplicationCommandOptionTypes[subCommand.type],
687
+ name: subCommand.name,
688
+ options: [
689
+ ...optionFormat,
690
+ {
691
+ type: ApplicationCommandOptionTypes[optionCommand.type],
692
+ name: optionCommand.name,
693
+ value,
694
+ focused: true,
695
+ },
696
+ ],
697
+ },
698
+ ];
699
+ break;
700
+ }
701
+ case 2: {
702
+ const subGroup = this.options.find(
703
+ o => o.name == subCommandArray[0] && o.type == 'SUB_COMMAND_GROUP',
704
+ );
705
+ const subCommand = subGroup.options.find(
706
+ o => o.name == subCommandArray[1] && o.type == 'SUB_COMMAND',
707
+ );
708
+ optionsBuild = [
709
+ {
710
+ type: ApplicationCommandOptionTypes[subGroup.type],
711
+ name: subGroup.name,
712
+ options: [
713
+ {
714
+ type: ApplicationCommandOptionTypes[subCommand.type],
715
+ name: subCommand.name,
716
+ options: [
717
+ ...optionFormat,
718
+ {
719
+ type: ApplicationCommandOptionTypes[optionCommand.type],
720
+ name: optionCommand.name,
721
+ value,
722
+ focused: true,
723
+ },
724
+ ],
725
+ },
726
+ ],
727
+ },
728
+ ];
729
+ break;
730
+ }
731
+ }
732
+ const autoValue = await getAutoResponse(optionsBuild, value);
733
+ data.value = autoValue;
734
+ } else {
735
+ data.value = value;
736
+ }
737
+ }
738
+ }
739
+ optionFormat.push(data);
740
+ }
741
+ return optionFormat;
742
+ };
743
+ const parseSubCommand = async (subCommandName, options, subGroup) => {
744
+ const options_sub = subGroup ? subGroup.options : this.options;
745
+ const subCommand = options_sub.find(
746
+ o => (o.name == subCommandName || o.nameLocalized == subCommandName) && o.type == 'SUB_COMMAND',
747
+ );
748
+ if (!subCommand) {
749
+ throw buildError(
750
+ 'SubCommand',
751
+ subCommandName,
752
+ options_sub.map((o, i) => ` #${i + 1} Name: ${o.name}`).join('\n'),
753
+ 'is not a valid sub command',
754
+ );
755
+ }
756
+ const valueRequired = subCommand.options?.filter(o => o.required).length || 0;
757
+ for (let i = 0; i < options.length; i++) {
758
+ const optionInput = subCommand.options[i];
759
+ const value = options[i];
760
+ await parseOption(optionInput, value);
761
+ }
762
+ if (valueRequired > options.length) {
763
+ throw new Error(`Value required missing\nDebug:
764
+ Required: ${valueRequired} - Options: ${optionFormat.length}`);
765
+ }
766
+ return {
767
+ type: ApplicationCommandOptionTypes[subCommand.type],
768
+ name: subCommand.name,
769
+ options: optionFormat,
770
+ };
771
+ };
772
+ const parseSubGroupCommand = async (subGroupName, subName) => {
773
+ const subGroup = this.options.find(
774
+ o => (o.name == subGroupName || o.nameLocalized == subGroupName) && o.type == 'SUB_COMMAND_GROUP',
775
+ );
776
+ if (!subGroup) {
777
+ throw buildError(
778
+ 'SubGroupCommand',
779
+ subGroupName,
780
+ this.options.map((o, i) => ` #${i + 1} Name: ${o.name}`).join('\n'),
781
+ 'is not a valid sub group command',
782
+ );
783
+ }
784
+ const data = await parseSubCommand(subName, options, subGroup);
785
+ return {
786
+ type: ApplicationCommandOptionTypes[subGroup.type],
787
+ name: subGroup.name,
788
+ options: [data],
789
+ };
790
+ };
791
+ async function addDataFromAttachment(data, client) {
792
+ const data_ = await MessagePayload.resolveFile(data);
793
+ if (!data_.file) {
794
+ throw new TypeError(
795
+ 'The attachment data must be a BufferResolvable or Stream or FileOptions of MessageAttachment',
796
+ );
797
+ }
798
+ if (client.options.usingNewAttachmentAPI === true) {
799
+ const attachments_ = await getAttachments(client, message.channelId, data_);
800
+ await uploadFile(data_.file, attachments_[0].upload_url);
801
+ const id = attachments.length;
802
+ attachments.push({
803
+ id: id,
804
+ filename: data_.name,
805
+ uploaded_filename: attachments_[0].upload_filename,
806
+ });
807
+ return id;
808
+ } else {
809
+ const id = attachments.length;
810
+ attachments.push({
811
+ id: id,
812
+ filename: data_.name,
813
+ });
814
+ attachmentsBuffer.push(data_);
815
+ return id;
816
+ }
817
+ }
818
+ const getDataPost = (dataAdd = [], nonce, autocomplete = false) => {
819
+ if (!Array.isArray(dataAdd) && typeof dataAdd == 'object') {
820
+ dataAdd = [dataAdd];
821
+ }
822
+ const data = {
823
+ type: autocomplete ? InteractionTypes.APPLICATION_COMMAND_AUTOCOMPLETE : InteractionTypes.APPLICATION_COMMAND,
824
+ application_id: this.applicationId,
825
+ guild_id: message.guildId,
826
+ channel_id: message.channelId,
827
+ session_id: this.client.session_id,
828
+ data: {
829
+ version: this.version,
830
+ id: this.id,
831
+ name: this.name,
832
+ type: ApplicationCommandTypes[this.type],
833
+ options: dataAdd,
834
+ attachments: attachments,
835
+ },
836
+ nonce,
837
+ };
838
+ if (this.guildId) {
839
+ data.data.guild_id = message.guildId;
840
+ }
841
+ return data;
842
+ };
843
+ const getAutoResponse = async (sendData, value) => {
844
+ let nonce = SnowflakeUtil.generate();
845
+ const data = getDataPost(sendData, nonce, true);
846
+ await this.client.api.interactions.post({
847
+ data,
848
+ files: attachmentsBuffer,
849
+ });
850
+ return new Promise(resolve => {
851
+ const handler = data => {
852
+ timeout.refresh();
853
+ if (data.nonce !== nonce) return;
854
+ clearTimeout(timeout);
855
+ this.client.removeListener(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
856
+ this.client.decrementMaxListeners();
857
+ if (data.choices.length > 1) {
858
+ // Find best match name
859
+ const bestMatch = findBestMatch(
860
+ value,
861
+ data.choices.map(c => c.name),
862
+ );
863
+ const result = data.choices.find(c => c.name == bestMatch.bestMatch.target);
864
+ resolve(result.value);
865
+ } else {
866
+ resolve(value);
867
+ }
868
+ };
869
+ const timeout = setTimeout(() => {
870
+ this.client.removeListener(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
871
+ this.client.decrementMaxListeners();
872
+ resolve(value);
873
+ }, this.client.options.interactionTimeout).unref();
874
+ this.client.incrementMaxListeners();
875
+ this.client.on(Events.APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE, handler);
876
+ });
877
+ };
878
+ const sendData = async (optionsData = []) => {
879
+ let nonce = SnowflakeUtil.generate();
880
+ const data = getDataPost(optionsData, nonce);
881
+ await this.client.api.interactions.post({
882
+ body: data,
883
+ files: attachmentsBuffer,
884
+ });
885
+ this.client._interactionCache.set(nonce, {
886
+ channelId: message.channelId,
887
+ guildId: message.guildId,
888
+ metadata: data,
889
+ });
890
+ return new Promise((resolve, reject) => {
891
+ const handler = data => {
892
+ timeout.refresh();
893
+ if (data.metadata.nonce !== nonce) return;
894
+ clearTimeout(timeout);
895
+ this.client.removeListener('interactionResponse', handler);
896
+ this.client.decrementMaxListeners();
897
+ if (data.status) {
898
+ resolve(data.metadata);
899
+ } else {
900
+ reject(
901
+ new Error('INTERACTION_ERROR', {
902
+ cause: data,
903
+ }),
904
+ );
905
+ }
906
+ };
907
+ const timeout = setTimeout(() => {
908
+ this.client.removeListener('interactionResponse', handler);
909
+ this.client.decrementMaxListeners();
910
+ reject(
911
+ new Error('INTERACTION_TIMEOUT', {
912
+ cause: data,
913
+ }),
914
+ );
915
+ }, this.client.options.interactionTimeout).unref();
916
+ this.client.incrementMaxListeners();
917
+ this.client.on('interactionResponse', handler);
918
+ });
919
+ };
920
+ // SubCommandArray length max 2
921
+ // length = 0 => no sub command
922
+ // length = 1 => sub command
923
+ // length = 2 => sub command group + sub command
924
+ switch (subCommandArray.length) {
925
+ case 0: {
926
+ const valueRequired = this.options?.filter(o => o.required).length || 0;
927
+ for (let i = 0; i < options.length; i++) {
928
+ const optionInput = this.options[i];
929
+ const value = options[i];
930
+ await parseOption(optionInput, value);
931
+ }
932
+ if (valueRequired > options.length) {
933
+ throw new Error(`Value required missing\nDebug:
934
+ Required: ${valueRequired} - Options: ${optionFormat.length}`);
935
+ }
936
+ return sendData(optionFormat);
937
+ }
938
+ case 1: {
939
+ const optionsData = await parseSubCommand(subCommandArray[0], options);
940
+ return sendData(optionsData);
941
+ }
942
+ case 2: {
943
+ const optionsData = await parseSubGroupCommand(subCommandArray[0], subCommandArray[1], options);
944
+ return sendData(optionsData);
945
+ }
946
+ }
947
+ }
948
+ /**
949
+ * Message Context Menu
950
+ * @param {Message} message Discord Message
951
+ * @returns {Promise<InteractionResponse>}
952
+ */
953
+ async sendContextMenu(message) {
954
+ if (!(message instanceof Message())) {
955
+ throw new TypeError('The message must be a Discord.Message');
956
+ }
957
+ if (this.type == 'CHAT_INPUT') return false;
958
+ const nonce = SnowflakeUtil.generate();
959
+ const data = {
960
+ type: InteractionTypes.APPLICATION_COMMAND,
961
+ application_id: this.applicationId,
962
+ guild_id: message.guildId,
963
+ channel_id: message.channelId,
964
+ session_id: this.client.session_id,
965
+ data: {
966
+ version: this.version,
967
+ id: this.id,
968
+ name: this.name,
969
+ type: ApplicationCommandTypes[this.type],
970
+ target_id: ApplicationCommandTypes[this.type] == 1 ? message.author.id : message.id,
971
+ },
972
+ nonce,
973
+ };
974
+ if (this.guildId) {
975
+ data.data.guild_id = message.guildId;
976
+ }
977
+ await this.client.api.interactions.post({
978
+ body: data,
979
+ });
980
+ this.client._interactionCache.set(nonce, {
981
+ channelId: message.channelId,
982
+ guildId: message.guildId,
983
+ metadata: data,
984
+ });
985
+ return new Promise((resolve, reject) => {
986
+ const handler = data => {
987
+ timeout.refresh();
988
+ if (data.metadata.nonce !== nonce) return;
989
+ clearTimeout(timeout);
990
+ this.client.removeListener('interactionResponse', handler);
991
+ this.client.decrementMaxListeners();
992
+ if (data.status) {
993
+ resolve(data.metadata);
994
+ } else {
995
+ reject(
996
+ new Error('INTERACTION_ERROR', {
997
+ cause: data,
998
+ }),
999
+ );
1000
+ }
1001
+ };
1002
+ const timeout = setTimeout(() => {
1003
+ this.client.removeListener('interactionResponse', handler);
1004
+ this.client.decrementMaxListeners();
1005
+ reject(
1006
+ new Error('INTERACTION_TIMEOUT', {
1007
+ cause: data,
1008
+ }),
1009
+ );
1010
+ }, this.client.options.interactionTimeout).unref();
1011
+ this.client.incrementMaxListeners();
1012
+ this.client.on('interactionResponse', handler);
1013
+ });
1014
+ }
1015
+ }
1016
+
1017
+ module.exports = ApplicationCommand;
1018
+
1019
+ /* eslint-disable max-len */
1020
+ /**
1021
+ * @external APIApplicationCommand
1022
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-structure}
1023
+ */
1024
+
1025
+ /**
1026
+ * @external APIApplicationCommandOption
1027
+ * @see {@link https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-structure}
1028
+ */