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,1188 @@
1
+ 'use strict';
2
+
3
+ const process = require('node:process');
4
+ const { Collection } = require('@discordjs/collection');
5
+ const Base = require('./Base');
6
+ const BaseMessageComponent = require('./BaseMessageComponent');
7
+ const ClientApplication = require('./ClientApplication');
8
+ const InteractionCollector = require('./InteractionCollector');
9
+ const MessageAttachment = require('./MessageAttachment');
10
+ const MessageButton = require('./MessageButton');
11
+ const Embed = require('./MessageEmbed');
12
+ const Mentions = require('./MessageMentions');
13
+ const MessagePayload = require('./MessagePayload');
14
+ const MessageSelectMenu = require('./MessageSelectMenu');
15
+ const ReactionCollector = require('./ReactionCollector');
16
+ const { Sticker } = require('./Sticker');
17
+ const { Error } = require('../errors');
18
+ const ReactionManager = require('../managers/ReactionManager');
19
+ const { InteractionTypes, MessageTypes, SystemMessageTypes, MaxBulkDeletableMessageAge } = require('../util/Constants');
20
+ const MessageFlags = require('../util/MessageFlags');
21
+ const Permissions = require('../util/Permissions');
22
+ const SnowflakeUtil = require('../util/SnowflakeUtil');
23
+ const Util = require('../util/Util');
24
+
25
+ /**
26
+ * @type {WeakSet<Message>}
27
+ * @private
28
+ * @internal
29
+ */
30
+ const deletedMessages = new WeakSet();
31
+ let deprecationEmittedForDeleted = false;
32
+
33
+ /**
34
+ * Represents a message on Discord.
35
+ * @extends {Base}
36
+ */
37
+ class Message extends Base {
38
+ constructor(client, data) {
39
+ super(client);
40
+
41
+ /**
42
+ * The id of the channel the message was sent in
43
+ * @type {Snowflake}
44
+ */
45
+ this.channelId = data.channel_id;
46
+
47
+ /**
48
+ * The id of the guild the message was sent in, if any
49
+ * @type {?Snowflake}
50
+ */
51
+ this.guildId = data.guild_id ?? this.channel?.guild?.id ?? null;
52
+
53
+ this._patch(data);
54
+ }
55
+
56
+ _patch(data) {
57
+ /**
58
+ * The message's id
59
+ * @type {Snowflake}
60
+ */
61
+ this.id = data.id;
62
+
63
+ if ('position' in data) {
64
+ /**
65
+ * A generally increasing integer (there may be gaps or duplicates) that represents
66
+ * the approximate position of the message in a thread.
67
+ * @type {?number}
68
+ */
69
+ this.position = data.position;
70
+ } else {
71
+ this.position ??= null;
72
+ }
73
+
74
+ /**
75
+ * The timestamp the message was sent at
76
+ * @type {number}
77
+ */
78
+ this.createdTimestamp = SnowflakeUtil.timestampFrom(this.id);
79
+
80
+ if ('type' in data) {
81
+ /**
82
+ * The type of the message
83
+ * @type {?MessageType}
84
+ */
85
+ this.type = MessageTypes[data.type];
86
+
87
+ /**
88
+ * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
89
+ * @type {?boolean}
90
+ */
91
+ this.system = SystemMessageTypes.includes(this.type);
92
+ } else {
93
+ this.system ??= null;
94
+ this.type ??= null;
95
+ }
96
+
97
+ if ('content' in data) {
98
+ /**
99
+ * The content of the message
100
+ * @type {?string}
101
+ */
102
+ this.content = data.content;
103
+ } else {
104
+ this.content ??= null;
105
+ }
106
+
107
+ if ('author' in data) {
108
+ /**
109
+ * The author of the message
110
+ * @type {?User}
111
+ */
112
+ this.author = this.client.users._add(data.author, !data.webhook_id);
113
+ } else {
114
+ this.author ??= null;
115
+ }
116
+
117
+ if ('pinned' in data) {
118
+ /**
119
+ * Whether or not this message is pinned
120
+ * @type {?boolean}
121
+ */
122
+ this.pinned = Boolean(data.pinned);
123
+ } else {
124
+ this.pinned ??= null;
125
+ }
126
+
127
+ if ('tts' in data) {
128
+ /**
129
+ * Whether or not the message was Text-To-Speech
130
+ * @type {?boolean}
131
+ */
132
+ this.tts = data.tts;
133
+ } else {
134
+ this.tts ??= null;
135
+ }
136
+
137
+ if ('nonce' in data) {
138
+ /**
139
+ * A random number or string used for checking message delivery
140
+ * <warn>This is only received after the message was sent successfully, and
141
+ * lost if re-fetched</warn>
142
+ * @type {?string}
143
+ */
144
+ this.nonce = data.nonce;
145
+ } else {
146
+ this.nonce ??= null;
147
+ }
148
+
149
+ if ('embeds' in data) {
150
+ /**
151
+ * A list of embeds in the message - e.g. YouTube Player
152
+ * @type {MessageEmbed[]}
153
+ */
154
+ this.embeds = data.embeds.map(e => new Embed(e, true));
155
+ } else {
156
+ this.embeds = this.embeds?.slice() ?? [];
157
+ }
158
+
159
+ if ('components' in data) {
160
+ /**
161
+ * A list of MessageActionRows in the message
162
+ * @type {MessageActionRow[]}
163
+ */
164
+ this.components = data.components.map(c => BaseMessageComponent.create(c, this.client));
165
+ } else {
166
+ this.components = this.components?.slice() ?? [];
167
+ }
168
+
169
+ if ('attachments' in data) {
170
+ /**
171
+ * A collection of attachments in the message - e.g. Pictures - mapped by their ids
172
+ * @type {Collection<Snowflake, MessageAttachment>}
173
+ */
174
+ this.attachments = new Collection();
175
+ if (data.attachments) {
176
+ for (const attachment of data.attachments) {
177
+ this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment));
178
+ }
179
+ }
180
+ } else {
181
+ this.attachments = new Collection(this.attachments);
182
+ }
183
+
184
+ if ('sticker_items' in data || 'stickers' in data) {
185
+ /**
186
+ * A collection of stickers in the message
187
+ * @type {Collection<Snowflake, Sticker>}
188
+ */
189
+ this.stickers = new Collection(
190
+ (data.sticker_items ?? data.stickers)?.map(s => [s.id, new Sticker(this.client, s)]),
191
+ );
192
+ } else {
193
+ this.stickers = new Collection(this.stickers);
194
+ }
195
+
196
+ // Discord sends null if the message has not been edited
197
+ if (data.edited_timestamp) {
198
+ /**
199
+ * The timestamp the message was last edited at (if applicable)
200
+ * @type {?number}
201
+ */
202
+ this.editedTimestamp = new Date(data.edited_timestamp).getTime();
203
+ } else {
204
+ this.editedTimestamp ??= null;
205
+ }
206
+
207
+ if ('reactions' in data) {
208
+ /**
209
+ * A manager of the reactions belonging to this message
210
+ * @type {ReactionManager}
211
+ */
212
+ this.reactions = new ReactionManager(this);
213
+ if (data.reactions?.length > 0) {
214
+ for (const reaction of data.reactions) {
215
+ this.reactions._add(reaction);
216
+ }
217
+ }
218
+ } else {
219
+ this.reactions ??= new ReactionManager(this);
220
+ }
221
+
222
+ if (!this.mentions) {
223
+ /**
224
+ * All valid mentions that the message contains
225
+ * @type {MessageMentions}
226
+ */
227
+ this.mentions = new Mentions(
228
+ this,
229
+ data.mentions,
230
+ data.mention_roles,
231
+ data.mention_everyone,
232
+ data.mention_channels,
233
+ data.referenced_message?.author,
234
+ );
235
+ } else {
236
+ this.mentions = new Mentions(
237
+ this,
238
+ data.mentions ?? this.mentions.users,
239
+ data.mention_roles ?? this.mentions.roles,
240
+ data.mention_everyone ?? this.mentions.everyone,
241
+ data.mention_channels ?? this.mentions.crosspostedChannels,
242
+ data.referenced_message?.author ?? this.mentions.repliedUser,
243
+ );
244
+ }
245
+
246
+ if ('webhook_id' in data) {
247
+ /**
248
+ * The id of the webhook that sent the message, if applicable
249
+ * @type {?Snowflake}
250
+ */
251
+ this.webhookId = data.webhook_id;
252
+ } else {
253
+ this.webhookId ??= null;
254
+ }
255
+
256
+ if ('application' in data) {
257
+ /**
258
+ * Supplemental application information for group activities
259
+ * @type {?ClientApplication}
260
+ */
261
+ this.groupActivityApplication = new ClientApplication(this.client, data.application);
262
+ } else {
263
+ this.groupActivityApplication ??= null;
264
+ }
265
+
266
+ if ('application_id' in data) {
267
+ /**
268
+ * The id of the application of the interaction that sent this message, if any
269
+ * @type {?Snowflake}
270
+ */
271
+ this.applicationId = data.application_id;
272
+ } else {
273
+ this.applicationId ??= null;
274
+ }
275
+
276
+ if ('activity' in data) {
277
+ /**
278
+ * Group activity
279
+ * @type {?MessageActivity}
280
+ */
281
+ this.activity = {
282
+ partyId: data.activity.party_id,
283
+ type: data.activity.type,
284
+ };
285
+ } else {
286
+ this.activity ??= null;
287
+ }
288
+
289
+ if ('thread' in data) {
290
+ this.client.channels._add(data.thread, this.guild);
291
+ }
292
+
293
+ if (this.member && data.member) {
294
+ this.member._patch(data.member);
295
+ } else if (data.member && this.guild && this.author) {
296
+ this.guild.members._add(Object.assign(data.member, { user: this.author }));
297
+ }
298
+
299
+ if ('flags' in data) {
300
+ /**
301
+ * Flags that are applied to the message
302
+ * @type {Readonly<MessageFlags>}
303
+ */
304
+ this.flags = new MessageFlags(data.flags).freeze();
305
+ } else {
306
+ this.flags = new MessageFlags(this.flags).freeze();
307
+ }
308
+
309
+ /**
310
+ * Reference data sent in a message that contains ids identifying the referenced message.
311
+ * This can be present in the following types of message:
312
+ * * Crossposted messages (IS_CROSSPOST {@link MessageFlags.FLAGS message flag})
313
+ * * CHANNEL_FOLLOW_ADD
314
+ * * CHANNEL_PINNED_MESSAGE
315
+ * * REPLY
316
+ * * THREAD_STARTER_MESSAGE
317
+ * @see {@link https://discord.com/developers/docs/resources/channel#message-types}
318
+ * @typedef {Object} MessageReference
319
+ * @property {Snowflake} channelId The channel's id the message was referenced
320
+ * @property {?Snowflake} guildId The guild's id the message was referenced
321
+ * @property {?Snowflake} messageId The message's id that was referenced
322
+ */
323
+
324
+ if ('message_reference' in data) {
325
+ /**
326
+ * Message reference data
327
+ * @type {?MessageReference}
328
+ */
329
+ this.reference = {
330
+ channelId: data.message_reference.channel_id,
331
+ guildId: data.message_reference.guild_id,
332
+ messageId: data.message_reference.message_id,
333
+ };
334
+ } else {
335
+ this.reference ??= null;
336
+ }
337
+
338
+ if (data.referenced_message) {
339
+ this.channel?.messages._add({ guild_id: data.message_reference?.guild_id, ...data.referenced_message });
340
+ }
341
+
342
+ /**
343
+ * Partial data of the interaction that a message is a reply to
344
+ * @typedef {Object} MessageInteraction
345
+ * @property {Snowflake} id The interaction's id
346
+ * @property {InteractionType} type The type of the interaction
347
+ * @property {string} commandName The name of the interaction's application command,
348
+ * as well as the subcommand and subcommand group, where applicable
349
+ * @property {User} user The user that invoked the interaction
350
+ */
351
+
352
+ if (data.interaction) {
353
+ /**
354
+ * Partial data of the interaction that this message is a reply to
355
+ * @type {?MessageInteraction}
356
+ */
357
+ this.interaction = {
358
+ id: data.interaction.id,
359
+ type: InteractionTypes[data.interaction.type],
360
+ commandName: data.interaction.name,
361
+ user: this.client.users._add(data.interaction.user),
362
+ };
363
+ } else {
364
+ this.interaction ??= null;
365
+ }
366
+ }
367
+
368
+ /**
369
+ * Whether or not the structure has been deleted
370
+ * @type {boolean}
371
+ * @deprecated This will be removed in the next major version, see https://github.com/discordjs/discord.js/issues/7091
372
+ */
373
+ get deleted() {
374
+ if (!deprecationEmittedForDeleted) {
375
+ deprecationEmittedForDeleted = true;
376
+ process.emitWarning(
377
+ 'Message#deleted is deprecated, see https://github.com/discordjs/discord.js/issues/7091.',
378
+ 'DeprecationWarning',
379
+ );
380
+ }
381
+
382
+ return deletedMessages.has(this);
383
+ }
384
+
385
+ set deleted(value) {
386
+ if (!deprecationEmittedForDeleted) {
387
+ deprecationEmittedForDeleted = true;
388
+ process.emitWarning(
389
+ 'Message#deleted is deprecated, see https://github.com/discordjs/discord.js/issues/7091.',
390
+ 'DeprecationWarning',
391
+ );
392
+ }
393
+
394
+ if (value) deletedMessages.add(this);
395
+ else deletedMessages.delete(this);
396
+ }
397
+
398
+ /**
399
+ * The channel that the message was sent in
400
+ * @type {TextBasedChannels}
401
+ * @readonly
402
+ */
403
+ get channel() {
404
+ return this.client.channels.resolve(this.channelId);
405
+ }
406
+
407
+ /**
408
+ * Whether or not this message is a partial
409
+ * @type {boolean}
410
+ * @readonly
411
+ */
412
+ get partial() {
413
+ return typeof this.content !== 'string' || !this.author;
414
+ }
415
+
416
+ /**
417
+ * Represents the author of the message as a guild member.
418
+ * Only available if the message comes from a guild where the author is still a member
419
+ * @type {?GuildMember}
420
+ * @readonly
421
+ */
422
+ get member() {
423
+ return this.guild?.members.resolve(this.author) ?? null;
424
+ }
425
+
426
+ /**
427
+ * The time the message was sent at
428
+ * @type {Date}
429
+ * @readonly
430
+ */
431
+ get createdAt() {
432
+ return new Date(this.createdTimestamp);
433
+ }
434
+
435
+ /**
436
+ * The time the message was last edited at (if applicable)
437
+ * @type {?Date}
438
+ * @readonly
439
+ */
440
+ get editedAt() {
441
+ return this.editedTimestamp ? new Date(this.editedTimestamp) : null;
442
+ }
443
+
444
+ /**
445
+ * The guild the message was sent in (if in a guild channel)
446
+ * @type {?Guild}
447
+ * @readonly
448
+ */
449
+ get guild() {
450
+ return this.client.guilds.resolve(this.guildId) ?? this.channel?.guild ?? null;
451
+ }
452
+
453
+ /**
454
+ * Whether this message has a thread associated with it
455
+ * @type {boolean}
456
+ * @readonly
457
+ */
458
+ get hasThread() {
459
+ return this.flags.has(MessageFlags.FLAGS.HAS_THREAD);
460
+ }
461
+
462
+ /**
463
+ * The thread started by this message
464
+ * <info>This property is not suitable for checking whether a message has a thread,
465
+ * use {@link Message#hasThread} instead.</info>
466
+ * @type {?ThreadChannel}
467
+ * @readonly
468
+ */
469
+ get thread() {
470
+ return this.channel?.threads?.resolve(this.id) ?? null;
471
+ }
472
+
473
+ /**
474
+ * The URL to jump to this message
475
+ * @type {string}
476
+ * @readonly
477
+ */
478
+ get url() {
479
+ return `https://discord.com/channels/${this.guildId ?? '@me'}/${this.channelId}/${this.id}`;
480
+ }
481
+
482
+ /**
483
+ * The message contents with all mentions replaced by the equivalent text.
484
+ * If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted.
485
+ * @type {?string}
486
+ * @readonly
487
+ */
488
+ get cleanContent() {
489
+ // eslint-disable-next-line eqeqeq
490
+ return this.content != null ? Util.cleanContent(this.content, this.channel) : null;
491
+ }
492
+
493
+ /**
494
+ * Creates a reaction collector.
495
+ * @param {ReactionCollectorOptions} [options={}] Options to send to the collector
496
+ * @returns {ReactionCollector}
497
+ * @example
498
+ * // Create a reaction collector
499
+ * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId';
500
+ * const collector = message.createReactionCollector({ filter, time: 15_000 });
501
+ * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`));
502
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
503
+ */
504
+ createReactionCollector(options = {}) {
505
+ return new ReactionCollector(this, options);
506
+ }
507
+
508
+ /**
509
+ * An object containing the same properties as CollectorOptions, but a few more:
510
+ * @typedef {ReactionCollectorOptions} AwaitReactionsOptions
511
+ * @property {string[]} [errors] Stop/end reasons that cause the promise to reject
512
+ */
513
+
514
+ /**
515
+ * Similar to createReactionCollector but in promise form.
516
+ * Resolves with a collection of reactions that pass the specified filter.
517
+ * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
518
+ * @returns {Promise<Collection<string | Snowflake, MessageReaction>>}
519
+ * @example
520
+ * // Create a reaction collector
521
+ * const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someId'
522
+ * message.awaitReactions({ filter, time: 15_000 })
523
+ * .then(collected => console.log(`Collected ${collected.size} reactions`))
524
+ * .catch(console.error);
525
+ */
526
+ awaitReactions(options = {}) {
527
+ return new Promise((resolve, reject) => {
528
+ const collector = this.createReactionCollector(options);
529
+ collector.once('end', (reactions, reason) => {
530
+ if (options.errors?.includes(reason)) reject(reactions);
531
+ else resolve(reactions);
532
+ });
533
+ });
534
+ }
535
+
536
+ /**
537
+ * @typedef {CollectorOptions} MessageComponentCollectorOptions
538
+ * @property {MessageComponentType} [componentType] The type of component to listen for
539
+ * @property {number} [max] The maximum total amount of interactions to collect
540
+ * @property {number} [maxComponents] The maximum number of components to collect
541
+ * @property {number} [maxUsers] The maximum number of users to interact
542
+ */
543
+
544
+ /**
545
+ * Creates a message component interaction collector.
546
+ * @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector
547
+ * @returns {InteractionCollector}
548
+ * @example
549
+ * // Create a message component interaction collector
550
+ * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId';
551
+ * const collector = message.createMessageComponentCollector({ filter, time: 15_000 });
552
+ * collector.on('collect', i => console.log(`Collected ${i.customId}`));
553
+ * collector.on('end', collected => console.log(`Collected ${collected.size} items`));
554
+ */
555
+ createMessageComponentCollector(options = {}) {
556
+ return new InteractionCollector(this.client, {
557
+ ...options,
558
+ interactionType: InteractionTypes.MESSAGE_COMPONENT,
559
+ message: this,
560
+ });
561
+ }
562
+
563
+ /**
564
+ * An object containing the same properties as CollectorOptions, but a few more:
565
+ * @typedef {Object} AwaitMessageComponentOptions
566
+ * @property {CollectorFilter} [filter] The filter applied to this collector
567
+ * @property {number} [time] Time to wait for an interaction before rejecting
568
+ * @property {MessageComponentType} [componentType] The type of component interaction to collect
569
+ */
570
+
571
+ /**
572
+ * Collects a single component interaction that passes the filter.
573
+ * The Promise will reject if the time expires.
574
+ * @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector
575
+ * @returns {Promise<MessageComponentInteraction>}
576
+ * @example
577
+ * // Collect a message component interaction
578
+ * const filter = (interaction) => interaction.customId === 'button' && interaction.user.id === 'someId';
579
+ * message.awaitMessageComponent({ filter, time: 15_000 })
580
+ * .then(interaction => console.log(`${interaction.customId} was clicked!`))
581
+ * .catch(console.error);
582
+ */
583
+ awaitMessageComponent(options = {}) {
584
+ const _options = { ...options, max: 1 };
585
+ return new Promise((resolve, reject) => {
586
+ const collector = this.createMessageComponentCollector(_options);
587
+ collector.once('end', (interactions, reason) => {
588
+ const interaction = interactions.first();
589
+ if (interaction) resolve(interaction);
590
+ else reject(new Error('INTERACTION_COLLECTOR_ERROR', reason));
591
+ });
592
+ });
593
+ }
594
+
595
+ /**
596
+ * Whether the message is editable by the client user
597
+ * @type {boolean}
598
+ * @readonly
599
+ */
600
+ get editable() {
601
+ const precheck = Boolean(
602
+ this.author.id === this.client.user.id && !deletedMessages.has(this) && (!this.guild || this.channel?.viewable),
603
+ );
604
+
605
+ // Regardless of permissions thread messages cannot be edited if
606
+ // the thread is archived or the thread is locked and the bot does not have permission to manage threads.
607
+ if (this.channel?.isThread()) {
608
+ if (this.channel.archived) return false;
609
+ if (this.channel.locked) {
610
+ const permissions = this.channel.permissionsFor(this.client.user);
611
+ if (!permissions?.has(Permissions.FLAGS.MANAGE_THREADS, true)) return false;
612
+ }
613
+ }
614
+
615
+ return precheck;
616
+ }
617
+
618
+ /**
619
+ * Whether the message is deletable by the client user
620
+ * @type {boolean}
621
+ * @readonly
622
+ */
623
+ get deletable() {
624
+ if (deletedMessages.has(this)) {
625
+ return false;
626
+ }
627
+ if (!this.guild) {
628
+ return this.author.id === this.client.user.id;
629
+ }
630
+ // DMChannel does not have viewable property, so check viewable after proved that message is on a guild.
631
+ if (!this.channel?.viewable) {
632
+ return false;
633
+ }
634
+
635
+ const permissions = this.channel?.permissionsFor(this.client.user);
636
+ if (!permissions) return false;
637
+ // This flag allows deleting even if timed out
638
+ if (permissions.has(Permissions.FLAGS.ADMINISTRATOR, false)) return true;
639
+
640
+ return Boolean(
641
+ this.author.id === this.client.user.id ||
642
+ (permissions.has(Permissions.FLAGS.MANAGE_MESSAGES, false) &&
643
+ this.guild.members.me.communicationDisabledUntilTimestamp < Date.now()),
644
+ );
645
+ }
646
+
647
+ /**
648
+ * Whether the message is bulk deletable by the client user
649
+ * @type {boolean}
650
+ * @readonly
651
+ * @example
652
+ * // Filter for bulk deletable messages
653
+ * channel.bulkDelete(messages.filter(message => message.bulkDeletable));
654
+ */
655
+ get bulkDeletable() {
656
+ return (
657
+ (this.inGuild() &&
658
+ this.client.user.bot &&
659
+ Date.now() - this.createdTimestamp < MaxBulkDeletableMessageAge &&
660
+ this.deletable &&
661
+ this.channel?.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false)) ??
662
+ false
663
+ );
664
+ }
665
+
666
+ /**
667
+ * Whether the message is pinnable by the client user
668
+ * @type {boolean}
669
+ * @readonly
670
+ */
671
+ get pinnable() {
672
+ const { channel } = this;
673
+ return Boolean(
674
+ !this.system &&
675
+ !deletedMessages.has(this) &&
676
+ (!this.guild ||
677
+ (channel?.viewable &&
678
+ channel?.permissionsFor(this.client.user)?.has(Permissions.FLAGS.MANAGE_MESSAGES, false))),
679
+ );
680
+ }
681
+
682
+ /**
683
+ * Fetches the Message this crosspost/reply/pin-add references, if available to the client
684
+ * @returns {Promise<Message>}
685
+ */
686
+ async fetchReference() {
687
+ if (!this.reference) throw new Error('MESSAGE_REFERENCE_MISSING');
688
+ const { channelId, messageId } = this.reference;
689
+ const channel = this.client.channels.resolve(channelId);
690
+ if (!channel) throw new Error('GUILD_CHANNEL_RESOLVE');
691
+ const message = await channel.messages.fetch(messageId);
692
+ return message;
693
+ }
694
+
695
+ /**
696
+ * Whether the message is crosspostable by the client user
697
+ * @type {boolean}
698
+ * @readonly
699
+ */
700
+ get crosspostable() {
701
+ const bitfield =
702
+ Permissions.FLAGS.SEND_MESSAGES |
703
+ (this.author.id === this.client.user.id ? Permissions.defaultBit : Permissions.FLAGS.MANAGE_MESSAGES);
704
+ const { channel } = this;
705
+ return Boolean(
706
+ channel?.type === 'GUILD_NEWS' &&
707
+ !this.flags.has(MessageFlags.FLAGS.CROSSPOSTED) &&
708
+ this.type === 'DEFAULT' &&
709
+ channel.viewable &&
710
+ channel.permissionsFor(this.client.user)?.has(bitfield, false) &&
711
+ !deletedMessages.has(this),
712
+ );
713
+ }
714
+
715
+ /**
716
+ * Options that can be passed into {@link Message#edit}.
717
+ * @typedef {Object} MessageEditOptions
718
+ * @property {?string} [content] Content to be edited
719
+ * @property {MessageEmbed[]|APIEmbed[]} [embeds] Embeds to be added/edited
720
+ * @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
721
+ * @property {MessageFlags} [flags] Which flags to set for the message. Only `SUPPRESS_EMBEDS` can be edited.
722
+ * @property {MessageAttachment[]} [attachments] An array of attachments to keep,
723
+ * all attachments will be kept if omitted
724
+ * @property {FileOptions[]|BufferResolvable[]|MessageAttachment[]} [files] Files to add to the message
725
+ * @property {Array<(MessageActionRow|MessageActionRowOptions)>} [components]
726
+ * Action rows containing interactive components for the message (buttons, select menus)
727
+ */
728
+
729
+ /**
730
+ * Edits the content of the message.
731
+ * @param {string|MessagePayload|MessageEditOptions} options The options to provide
732
+ * @returns {Promise<Message>}
733
+ * @example
734
+ * // Update the content of a message
735
+ * message.edit('This is my new content!')
736
+ * .then(msg => console.log(`Updated the content of a message to ${msg.content}`))
737
+ * .catch(console.error);
738
+ */
739
+ edit(options) {
740
+ if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED'));
741
+ return this.channel.messages.edit(this, options);
742
+ }
743
+
744
+ /**
745
+ * Publishes a message in an announcement channel to all channels following it.
746
+ * @returns {Promise<Message>}
747
+ * @example
748
+ * // Crosspost a message
749
+ * if (message.channel.type === 'GUILD_NEWS') {
750
+ * message.crosspost()
751
+ * .then(() => console.log('Crossposted message'))
752
+ * .catch(console.error);
753
+ * }
754
+ */
755
+ crosspost() {
756
+ if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED'));
757
+ return this.channel.messages.crosspost(this.id);
758
+ }
759
+
760
+ /**
761
+ * Pins this message to the channel's pinned messages.
762
+ * @param {string} [reason] Reason for pinning
763
+ * @returns {Promise<Message>}
764
+ * @example
765
+ * // Pin a message
766
+ * message.pin()
767
+ * .then(console.log)
768
+ * .catch(console.error)
769
+ */
770
+ async pin(reason) {
771
+ if (!this.channel) throw new Error('CHANNEL_NOT_CACHED');
772
+ await this.channel.messages.pin(this.id, reason);
773
+ return this;
774
+ }
775
+
776
+ /**
777
+ * Unpins this message from the channel's pinned messages.
778
+ * @param {string} [reason] Reason for unpinning
779
+ * @returns {Promise<Message>}
780
+ * @example
781
+ * // Unpin a message
782
+ * message.unpin()
783
+ * .then(console.log)
784
+ * .catch(console.error)
785
+ */
786
+ async unpin(reason) {
787
+ if (!this.channel) throw new Error('CHANNEL_NOT_CACHED');
788
+ await this.channel.messages.unpin(this.id, reason);
789
+ return this;
790
+ }
791
+
792
+ /**
793
+ * Adds a reaction to the message.
794
+ * @param {EmojiIdentifierResolvable} emoji The emoji to react with
795
+ * @param {boolean} [burst=false] Super Reactions (Discord Nitro only)
796
+ * @returns {Promise<MessageReaction>}
797
+ * @example
798
+ * // React to a message with a unicode emoji
799
+ * message.react('🤔')
800
+ * .then(console.log)
801
+ * .catch(console.error);
802
+ * @example
803
+ * // React to a message with a custom emoji
804
+ * message.react(message.guild.emojis.cache.get('123456789012345678'))
805
+ * .then(console.log)
806
+ * .catch(console.error);
807
+ */
808
+ async react(emoji, burst = false) {
809
+ if (!this.channel) throw new Error('CHANNEL_NOT_CACHED');
810
+ await this.channel.messages.react(this.id, emoji, burst);
811
+
812
+ return this.client.actions.MessageReactionAdd.handle(
813
+ {
814
+ user: this.client.user,
815
+ channel: this.channel,
816
+ message: this,
817
+ emoji: Util.resolvePartialEmoji(emoji),
818
+ me_burst: burst,
819
+ },
820
+ true,
821
+ ).reaction;
822
+ }
823
+
824
+ /**
825
+ * Deletes the message.
826
+ * @returns {Promise<Message>}
827
+ * @example
828
+ * // Delete a message
829
+ * message.delete()
830
+ * .then(msg => console.log(`Deleted message from ${msg.author.username}`))
831
+ * .catch(console.error);
832
+ */
833
+ async delete() {
834
+ if (!this.channel) throw new Error('CHANNEL_NOT_CACHED');
835
+ await this.channel.messages.delete(this.id);
836
+ return this;
837
+ }
838
+
839
+ /**
840
+ * Options provided when sending a message as an inline reply.
841
+ * @typedef {BaseMessageOptions} ReplyMessageOptions
842
+ * @property {boolean} [failIfNotExists=true] Whether to error if the referenced message
843
+ * does not exist (creates a standard message in this case when false)
844
+ * @property {StickerResolvable[]} [stickers=[]] Stickers to send in the message
845
+ */
846
+
847
+ /**
848
+ * Send an inline reply to this message.
849
+ * @param {string|MessagePayload|ReplyMessageOptions} options The options to provide
850
+ * @returns {Promise<Message>}
851
+ * @example
852
+ * // Reply to a message
853
+ * message.reply('This is a reply!')
854
+ * .then(() => console.log(`Replied to message "${message.content}"`))
855
+ * .catch(console.error);
856
+ */
857
+ reply(options) {
858
+ if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED'));
859
+ let data;
860
+
861
+ if (options instanceof MessagePayload) {
862
+ data = options;
863
+ } else {
864
+ data = MessagePayload.create(this, options, {
865
+ reply: {
866
+ messageReference: this,
867
+ failIfNotExists: options?.failIfNotExists ?? this.client.options.failIfNotExists,
868
+ },
869
+ });
870
+ }
871
+ return this.channel.send(data);
872
+ }
873
+
874
+ /**
875
+ * A number that is allowed to be the duration (in minutes) of inactivity after which a thread is automatically
876
+ * archived. This can be:
877
+ * * `60` (1 hour)
878
+ * * `1440` (1 day)
879
+ * * `4320` (3 days)
880
+ * * `10080` (7 days)
881
+ * * `'MAX'` (7 days)
882
+ * <warn>This option is deprecated and will be removed in the next major version.</warn>
883
+ * @typedef {number|string} ThreadAutoArchiveDuration
884
+ */
885
+
886
+ /**
887
+ * Options for starting a thread on a message.
888
+ * @typedef {Object} StartThreadOptions
889
+ * @property {string} name The name of the new thread
890
+ * @property {ThreadAutoArchiveDuration} [autoArchiveDuration=this.channel.defaultAutoArchiveDuration] The amount of
891
+ * time (in minutes) after which the thread should automatically archive in case of no recent activity
892
+ * @property {string} [reason] Reason for creating the thread
893
+ * @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the thread in seconds
894
+ */
895
+
896
+ /**
897
+ * Create a new public thread from this message
898
+ * @see GuildTextThreadManager#create
899
+ * @param {StartThreadOptions} [options] Options for starting a thread on this message
900
+ * @returns {Promise<ThreadChannel>}
901
+ */
902
+ startThread(options = {}) {
903
+ if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED'));
904
+ if (!['GUILD_TEXT', 'GUILD_NEWS'].includes(this.channel.type)) {
905
+ return Promise.reject(new Error('MESSAGE_THREAD_PARENT'));
906
+ }
907
+ if (this.hasThread) return Promise.reject(new Error('MESSAGE_EXISTING_THREAD'));
908
+ return this.channel.threads.create({ ...options, startMessage: this });
909
+ }
910
+
911
+ /**
912
+ * Fetch this message.
913
+ * @param {boolean} [force=true] Whether to skip the cache check and request the API
914
+ * @returns {Promise<Message>}
915
+ */
916
+ fetch(force = true) {
917
+ if (!this.channel) return Promise.reject(new Error('CHANNEL_NOT_CACHED'));
918
+ return this.channel.messages.fetch(this.id, { force });
919
+ }
920
+
921
+ /**
922
+ * Fetches the webhook used to create this message.
923
+ * @returns {Promise<?Webhook>}
924
+ */
925
+ fetchWebhook() {
926
+ if (!this.webhookId) return Promise.reject(new Error('WEBHOOK_MESSAGE'));
927
+ if (this.webhookId === this.applicationId) return Promise.reject(new Error('WEBHOOK_APPLICATION'));
928
+ return this.client.fetchWebhook(this.webhookId);
929
+ }
930
+
931
+ /**
932
+ * Suppresses or unsuppresses embeds on a message.
933
+ * @param {boolean} [suppress=true] If the embeds should be suppressed or not
934
+ * @returns {Promise<Message>}
935
+ */
936
+ suppressEmbeds(suppress = true) {
937
+ const flags = new MessageFlags(this.flags.bitfield);
938
+
939
+ if (suppress) {
940
+ flags.add(MessageFlags.FLAGS.SUPPRESS_EMBEDS);
941
+ } else {
942
+ flags.remove(MessageFlags.FLAGS.SUPPRESS_EMBEDS);
943
+ }
944
+
945
+ return this.edit({ flags });
946
+ }
947
+
948
+ /**
949
+ * Removes the attachments from this message.
950
+ * @returns {Promise<Message>}
951
+ */
952
+ removeAttachments() {
953
+ return this.edit({ attachments: [] });
954
+ }
955
+
956
+ /**
957
+ * Resolves a component by a custom id.
958
+ * @param {string} customId The custom id to resolve against
959
+ * @returns {?MessageActionRowComponent}
960
+ */
961
+ resolveComponent(customId) {
962
+ return this.components.flatMap(row => row.components).find(component => component.customId === customId) ?? null;
963
+ }
964
+
965
+ /**
966
+ * Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
967
+ * without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
968
+ * method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
969
+ * @param {Message} message The message to compare it to
970
+ * @param {APIMessage} rawData Raw data passed through the WebSocket about this message
971
+ * @returns {boolean}
972
+ */
973
+ equals(message, rawData) {
974
+ if (!message) return false;
975
+ const embedUpdate = !message.author && !message.attachments;
976
+ if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
977
+
978
+ let equal =
979
+ this.id === message.id &&
980
+ this.author.id === message.author.id &&
981
+ this.content === message.content &&
982
+ this.tts === message.tts &&
983
+ this.nonce === message.nonce &&
984
+ this.embeds.length === message.embeds.length &&
985
+ this.attachments.length === message.attachments.length;
986
+
987
+ if (equal && rawData) {
988
+ equal =
989
+ this.mentions.everyone === message.mentions.everyone &&
990
+ this.createdTimestamp === new Date(rawData.timestamp).getTime() &&
991
+ this.editedTimestamp === new Date(rawData.edited_timestamp).getTime();
992
+ }
993
+
994
+ return equal;
995
+ }
996
+
997
+ /**
998
+ * Whether this message is from a guild.
999
+ * @returns {boolean}
1000
+ */
1001
+ inGuild() {
1002
+ return Boolean(this.guildId);
1003
+ }
1004
+
1005
+ /**
1006
+ * When concatenated with a string, this automatically concatenates the message's content instead of the object.
1007
+ * @returns {string}
1008
+ * @example
1009
+ * // Logs: Message: This is a message!
1010
+ * console.log(`Message: ${message}`);
1011
+ */
1012
+ toString() {
1013
+ return this.content;
1014
+ }
1015
+
1016
+ toJSON() {
1017
+ return super.toJSON({
1018
+ channel: 'channelId',
1019
+ author: 'authorId',
1020
+ groupActivityApplication: 'groupActivityApplicationId',
1021
+ guild: 'guildId',
1022
+ cleanContent: true,
1023
+ member: false,
1024
+ reactions: false,
1025
+ });
1026
+ }
1027
+ // Added
1028
+ /**
1029
+ * Marks the message as unread.
1030
+ * @returns {Promise<boolean>}
1031
+ */
1032
+ async markUnread() {
1033
+ await this.client.api.channels[this.channelId].messages[this.id].ack.post({
1034
+ data: {
1035
+ manual: true,
1036
+ mention_count:
1037
+ this.mentions.everyone ||
1038
+ this.mentions.repliedUser?.id === this.client.user.id ||
1039
+ this.mentions.users.has(this.client.user.id) ||
1040
+ (this.guildId && this.mentions.roles.some(r => this.guild.members.me._roles?.includes(r.id)))
1041
+ ? 1
1042
+ : 0,
1043
+ },
1044
+ });
1045
+ return true;
1046
+ }
1047
+
1048
+ /**
1049
+ * Marks the message as read.
1050
+ * @returns {Promise<boolean>}
1051
+ */
1052
+ async markRead() {
1053
+ await this.client.api.channels[this.channelId].messages[this.id].ack.post({
1054
+ data: {
1055
+ token: null,
1056
+ },
1057
+ });
1058
+ return true;
1059
+ }
1060
+
1061
+ /**
1062
+ * @typedef {Object} MessageButtonLocation
1063
+ * @property {number} row Index of the row
1064
+ * @property {number} col Index of the column
1065
+ */
1066
+
1067
+ /**
1068
+ * Click specific button or automatically click first button if no button is specified.
1069
+ * @param {MessageButton|MessageButtonLocation|string} button Button ID
1070
+ * @returns {Promise<InteractionResponse>}
1071
+ * @example
1072
+ * client.on('messageCreate', async message => {
1073
+ * if (message.components.length) {
1074
+ * // Find first button and click it
1075
+ * await message.clickButton();
1076
+ * // Click with button ID
1077
+ * await message.clickButton('button-id');
1078
+ * // Click with button location
1079
+ * await message.clickButton({ row: 0, col: 0 });
1080
+ * // Click with class MessageButton
1081
+ * const button = message.components[0].components[0];
1082
+ * await message.clickButton(button);
1083
+ * // Click with class MessageButton (2)
1084
+ * button.click(message);
1085
+ * }
1086
+ * });
1087
+ */
1088
+ clickButton(button) {
1089
+ if (!button) {
1090
+ button = this.components.flatMap(row => row.components).find(b => b.type === 'BUTTON')?.customId;
1091
+ } else if (button instanceof MessageButton) {
1092
+ button = button.customId;
1093
+ } else if (typeof button === 'object') {
1094
+ if (!('row' in button) || !('col' in button)) throw new TypeError('INVALID_BUTTON_LOCATION');
1095
+ button = this.components[button.row]?.components[button.col]?.customId;
1096
+ }
1097
+ if (!button) throw new TypeError('BUTTON_NOT_FOUND');
1098
+ button = this.components.flatMap(row => row.components).find(b => b.customId === button && b.type === 'BUTTON');
1099
+ return button ? button.click(this) : Promise.reject(new TypeError('BUTTON_NOT_FOUND'));
1100
+ }
1101
+ /**
1102
+ * Select specific menu or First Menu
1103
+ * @param {MessageSelectMenu|string|number|Array<any>} menuID MenuId / MessageSelectMenu / Row of Menu / Array of Values (first menu)
1104
+ * @param {Array<any>} options Array of Values
1105
+ * @returns {Promise<InteractionResponse>}
1106
+ * @example
1107
+ * client.on('messageCreate', async message => {
1108
+ * if (message.components.length) {
1109
+ * // Row
1110
+ * await message.selectMenu(1, [message.channel]); // row 1, type: Channel, multi: false
1111
+ * // Id
1112
+ * await message.selectMenu('menu-id', ['uid1', client.user, message.member]); // MenuId, type: User, multi: true
1113
+ * // First Menu
1114
+ * await message.selectMenu(['role-id']); // First Menu, type: role, multi: false
1115
+ * // class MessageSelectMenu
1116
+ * const menu = message.components[0].components[0];
1117
+ * await message.selectMenu(menu, ['option1', 'option2']);
1118
+ * // MessageSelectMenu (2)
1119
+ * menu.select(message, ['option1', 'option2']);
1120
+ * }
1121
+ * });
1122
+ */
1123
+ selectMenu(menuID, options = []) {
1124
+ if (!this.components[0]) throw new TypeError('MESSAGE_NO_COMPONENTS');
1125
+ if (menuID instanceof MessageSelectMenu) {
1126
+ //
1127
+ } else if (/[0-4]/.test(menuID)) {
1128
+ menuID = this.components[menuID]?.components[0];
1129
+ } else {
1130
+ const menuAll = this.components
1131
+ .flatMap(row => row.components)
1132
+ .filter(b =>
1133
+ [
1134
+ 'STRING_SELECT',
1135
+ 'USER_SELECT',
1136
+ 'ROLE_SELECT',
1137
+ 'MENTIONABLE_SELECT',
1138
+ 'CHANNEL_SELECT',
1139
+ 'SELECT_MENU',
1140
+ ].includes(b.type),
1141
+ );
1142
+ if (menuAll.length == 0) throw new TypeError('MENU_NOT_FOUND');
1143
+ if (menuID) {
1144
+ menuID = menuAll.find(b => b.customId === menuID);
1145
+ } else {
1146
+ menuID = menuAll[0];
1147
+ }
1148
+ }
1149
+ if (!menuID.type.includes('SELECT')) throw new TypeError('MENU_NOT_FOUND');
1150
+ return menuID.select(this, Array.isArray(menuID) ? menuID : options);
1151
+ }
1152
+ //
1153
+ /**
1154
+ * Send context Menu v2
1155
+ * @param {Snowflake} botId Bot id
1156
+ * @param {string} commandName Command name in Context Menu
1157
+ * @returns {Promise<InteractionResponse>}
1158
+ */
1159
+ async contextMenu(botId, commandName) {
1160
+ if (!botId) throw new Error('Bot ID is required');
1161
+ const user = await this.client.users.fetch(botId).catch(() => {});
1162
+ if (!user || !user.bot || !user.application) {
1163
+ throw new Error('BotID is not a bot or does not have an application slash command');
1164
+ }
1165
+ if (!commandName || typeof commandName !== 'string') {
1166
+ throw new Error('Command name is required');
1167
+ }
1168
+ let contextCMD;
1169
+ const data = await this.channel.searchInteraction(botId, 'MESSAGE');
1170
+ for (const command of data.application_commands) {
1171
+ user.application?.commands?._add(command, true);
1172
+ }
1173
+ contextCMD = user.application?.commands?.cache.find(c => c.name == commandName && c.type === 'MESSAGE');
1174
+ if (!contextCMD) {
1175
+ throw new Error(
1176
+ 'INTERACTION_SEND_FAILURE',
1177
+ `Command ${commandName} is not found (with search)\nList command avalible: ${user.application?.commands?.cache
1178
+ .filter(a => a.type == 'MESSAGE')
1179
+ .map(a => a.name)
1180
+ .join(', ')}`,
1181
+ );
1182
+ }
1183
+ return contextCMD.sendContextMenu(this, true);
1184
+ }
1185
+ }
1186
+
1187
+ exports.Message = Message;
1188
+ exports.deletedMessages = deletedMessages;