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,722 @@
1
+ 'use strict';
2
+ const { ActivityTypes } = require('../util/Constants');
3
+ const { resolvePartialEmoji } = require('../util/Util');
4
+
5
+ // eslint-disable-next-line
6
+ const getUUID = () =>
7
+ ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, a => (a ^ ((Math.random() * 16) >> (a / 4))).toString(16));
8
+ // Function check url valid (ok copilot)
9
+ // eslint-disable-next-line
10
+ const checkUrl = url => {
11
+ try {
12
+ return new URL(url);
13
+ } catch {
14
+ return false;
15
+ }
16
+ };
17
+
18
+ class CustomStatus {
19
+ /**
20
+ * @typedef {Object} CustomStatusOptions
21
+ * @property {string} [state] The state to be displayed
22
+ * @property {EmojiIdentifierResolvable} [emoji] The emoji to be displayed
23
+ */
24
+
25
+ /**
26
+ * @param {CustomStatus|CustomStatusOptions} [data={}] CustomStatus to clone or raw data
27
+ * @param {Presence} [presence] The presence this activity is part of
28
+ */
29
+ constructor(data = {}, presence) {
30
+ Object.defineProperty(this, 'presence', { value: presence });
31
+ this.name = 'Custom Status';
32
+ /**
33
+ * The emoji to be displayed
34
+ * @type {?EmojiIdentifierResolvable}
35
+ */
36
+ this.emoji = null;
37
+ this.type = ActivityTypes.CUSTOM;
38
+ /**
39
+ * The state to be displayed
40
+ * @type {?string}
41
+ */
42
+ this.state = null;
43
+ this.setup(data);
44
+ }
45
+ /**
46
+ * Sets the status from a JSON object
47
+ * @param {CustomStatus|CustomStatusOptions} data CustomStatus to clone or raw data
48
+ * @private
49
+ */
50
+ setup(data) {
51
+ this.emoji = data.emoji ? resolvePartialEmoji(data.emoji) : null;
52
+ this.state = data.state;
53
+ }
54
+ /**
55
+ * Set the emoji of this activity
56
+ * @param {EmojiIdentifierResolvable} emoji The emoji to be displayed
57
+ * @returns {CustomStatus}
58
+ */
59
+ setEmoji(emoji) {
60
+ this.emoji = resolvePartialEmoji(emoji);
61
+ return this;
62
+ }
63
+ /**
64
+ * Set state of this activity
65
+ * @param {string | null} state The state to be displayed
66
+ * @returns {CustomStatus}
67
+ */
68
+ setState(state) {
69
+ if (typeof state == 'string' && state.length > 128) throw new Error('State must be less than 128 characters');
70
+ this.state = state;
71
+ return this;
72
+ }
73
+
74
+ /**
75
+ * Returns an object that can be used to set the status
76
+ * @returns {CustomStatus}
77
+ */
78
+ toJSON() {
79
+ if (!this.emoji & !this.state) throw new Error('CustomStatus must have at least one of emoji or state');
80
+ return {
81
+ name: this.name,
82
+ emoji: this.emoji,
83
+ type: this.type,
84
+ state: this.state,
85
+ };
86
+ }
87
+
88
+ /**
89
+ * When concatenated with a string, this automatically returns the activities' name instead of the Activity object.
90
+ * @returns {string}
91
+ */
92
+ toString() {
93
+ return this.name;
94
+ }
95
+
96
+ _clone() {
97
+ return Object.assign(Object.create(this), this);
98
+ }
99
+ }
100
+
101
+ class RichPresence {
102
+ /**
103
+ * @param {Client} [client] Discord client
104
+ * @param {RichPresence} [data={}] RichPresence to clone or raw data
105
+ * @param {boolean} [IPC=false] Whether to use IPC (RPC for Discord Apps)
106
+ * @param {Presence} [presence] The presence this activity is part of
107
+ */
108
+ constructor(client = {}, data = {}, IPC = false, presence) {
109
+ Object.defineProperty(this, 'client', { value: client });
110
+ Object.defineProperty(this, 'presence', { value: presence });
111
+ /**
112
+ * The activity's name
113
+ * @type {string}
114
+ */
115
+ this.name = null;
116
+ /**
117
+ * The activity status's type
118
+ * @type {ActivityType}
119
+ */
120
+ this.type = ActivityTypes.PLAYING;
121
+ /**
122
+ * If the activity is being streamed, a link to the stream
123
+ * @type {?string}
124
+ */
125
+ this.url = null;
126
+ /**
127
+ * The id of the application associated with this activity
128
+ * @type {?Snowflake}
129
+ */
130
+ this.application_id = null;
131
+ /**
132
+ * State of the activity
133
+ * @type {?string}
134
+ */
135
+ this.state = null;
136
+ /**
137
+ * Details about the activity
138
+ * @type {?string}
139
+ */
140
+ this.details = null;
141
+ /**
142
+ * Party of the activity
143
+ * @type {?ActivityParty}
144
+ */
145
+ this.party = null;
146
+ /**
147
+ * Timestamps for the activity
148
+ * @type {?ActivityTimestamps}
149
+ */
150
+ this.timestamps = null;
151
+ /**
152
+ * Assets for rich presence
153
+ * @type {?RichPresenceAssets}
154
+ */
155
+ this.assets = null;
156
+ /**
157
+ * The labels of the buttons of this rich presence
158
+ * @type {string[]}
159
+ */
160
+ this.buttons = null;
161
+
162
+ this.ipc = IPC;
163
+
164
+ this.setup(data);
165
+ }
166
+ /**
167
+ * Sets the status from a JSON object
168
+ * @param {RichPresence} data data
169
+ * @private
170
+ */
171
+ setup(data) {
172
+ this.name = data.name;
173
+ this.type = typeof data.type != 'number' ? ActivityTypes[data.type?.toUpperCase()] : data.type;
174
+ this.application_id = data.application_id;
175
+ this.url = data.url;
176
+ this.state = data.state;
177
+ this.details = data.details;
178
+ this.party = data.party;
179
+ this.timestamps = data.timestamps;
180
+ this.created_at = data.created_at;
181
+ this.secrets = data.secrets;
182
+ this.assets = data.assets;
183
+ this.buttons = data.buttons;
184
+ this.metadata = data.metadata;
185
+ }
186
+ /**
187
+ * Set the large image of this activity
188
+ * @param {?any} image The large image asset's id
189
+ * @returns {RichPresence}
190
+ */
191
+ setAssetsLargeImage(image) {
192
+ if (!(this.assets instanceof Object)) this.assets = {};
193
+ if (typeof image != 'string') {
194
+ image = null;
195
+ } else if (['http:', 'https:'].includes(checkUrl(image)?.protocol)) {
196
+ // Discord URL:
197
+ image = image
198
+ .replace('https://cdn.discordapp.com/', 'mp:')
199
+ .replace('http://cdn.discordapp.com/', 'mp:')
200
+ .replace('https://media.discordapp.net/', 'mp:')
201
+ .replace('http://media.discordapp.net/', 'mp:');
202
+ //
203
+ if (!image.startsWith('mp:') && !this.ipc) {
204
+ throw new Error(
205
+ 'INVALID_URL',
206
+ `
207
+ If you want to set the URL directly, it should be the Discord URL (cdn.discordapp.com | media.discordapp.net)
208
+ Or follow these instructions:
209
+ https://github.com/aiko-chan-ai/discord.js-selfbot-v13/blob/main/Documents/RichPresence.md#method-3-custom-url-2378
210
+ `,
211
+ );
212
+ }
213
+ } else if (/^[0-9]{17,19}$/.test(image)) {
214
+ // ID Assets
215
+ } else if (image.startsWith('mp:') || image.startsWith('youtube:') || image.startsWith('spotify:')) {
216
+ // Image
217
+ } else if (image.startsWith('external/')) {
218
+ image = `mp:${image}`;
219
+ }
220
+ this.assets.large_image = image;
221
+ return this;
222
+ }
223
+ /**
224
+ * Set the small image of this activity
225
+ * @param {?any} image The small image asset's id
226
+ * @returns {RichPresence}
227
+ */
228
+ setAssetsSmallImage(image) {
229
+ if (!(this.assets instanceof Object)) this.assets = {};
230
+ if (typeof image != 'string') {
231
+ image = null;
232
+ } else if (['http:', 'https:'].includes(checkUrl(image)?.protocol)) {
233
+ // Discord URL:
234
+ image = image
235
+ .replace('https://cdn.discordapp.com/', 'mp:')
236
+ .replace('http://cdn.discordapp.com/', 'mp:')
237
+ .replace('https://media.discordapp.net/', 'mp:')
238
+ .replace('http://media.discordapp.net/', 'mp:');
239
+ //
240
+ if (!image.startsWith('mp:') && !this.ipc) {
241
+ throw new Error(
242
+ 'INVALID_URL',
243
+ `
244
+ If you want to set the URL directly, it should be the Discord URL (cdn.discordapp.com | media.discordapp.net)
245
+ Or follow these instructions:
246
+ https://github.com/aiko-chan-ai/discord.js-selfbot-v13/blob/main/Documents/RichPresence.md#method-3-custom-url-2378
247
+ `,
248
+ );
249
+ }
250
+ } else if (/^[0-9]{17,19}$/.test(image)) {
251
+ // ID Assets
252
+ } else if (image.startsWith('mp:') || image.startsWith('youtube:') || image.startsWith('spotify:')) {
253
+ // Image
254
+ } else if (image.startsWith('external/')) {
255
+ image = `mp:${image}`;
256
+ }
257
+ this.assets.small_image = image;
258
+ return this;
259
+ }
260
+ /**
261
+ * Hover text for the large image
262
+ * @param {string} text Assets text
263
+ * @returns {RichPresence}
264
+ */
265
+ setAssetsLargeText(text) {
266
+ if (typeof this.assets !== 'object') this.assets = {};
267
+ this.assets.large_text = text;
268
+ return this;
269
+ }
270
+ /**
271
+ * Hover text for the small image
272
+ * @param {string} text Assets text
273
+ * @returns {RichPresence}
274
+ */
275
+ setAssetsSmallText(text) {
276
+ if (typeof this.assets !== 'object') this.assets = {};
277
+ this.assets.small_text = text;
278
+ return this;
279
+ }
280
+ /**
281
+ * Set the name of the activity
282
+ * @param {?string} name The activity's name
283
+ * @returns {RichPresence}
284
+ */
285
+ setName(name) {
286
+ this.name = name;
287
+ return this;
288
+ }
289
+ /**
290
+ * If the activity is being streamed, a link to the stream
291
+ * @param {?string} url URL of the stream
292
+ * @returns {RichPresence}
293
+ */
294
+ setURL(url) {
295
+ if (typeof url == 'string' && !checkUrl(url)) throw new Error('URL must be a valid URL');
296
+ if (typeof url != 'string') url = null;
297
+ this.url = url;
298
+ return this;
299
+ }
300
+ /**
301
+ * The activity status's type
302
+ * @param {?ActivityTypes} type The type of activity
303
+ * @returns {RichPresence}
304
+ */
305
+ setType(type) {
306
+ this.type = ActivityTypes[type];
307
+ if (typeof this.type == 'string') this.type = ActivityTypes[this.type];
308
+ if (typeof this.type != 'number') throw new Error('Type must be a valid ActivityType');
309
+ return this;
310
+ }
311
+ /**
312
+ * Set the application id of this activity
313
+ * @param {?Snowflake} id Bot's id
314
+ * @returns {RichPresence}
315
+ */
316
+ setApplicationId(id) {
317
+ this.application_id = id;
318
+ return this;
319
+ }
320
+ /**
321
+ * Set the state of the activity
322
+ * @param {?string} state The state of the activity
323
+ * @returns {RichPresence}
324
+ */
325
+ setState(state) {
326
+ this.state = state;
327
+ return this;
328
+ }
329
+ /**
330
+ * Set the details of the activity
331
+ * @param {?string} details The details of the activity
332
+ * @returns {RichPresence}
333
+ */
334
+ setDetails(details) {
335
+ this.details = details;
336
+ return this;
337
+ }
338
+ /**
339
+ * @typedef {Object} RichParty
340
+ * @property {string} id The id of the party
341
+ * @property {number} max The maximum number of members in the party
342
+ * @property {number} current The current number of members in the party
343
+ */
344
+ /**
345
+ * Set the party of this activity
346
+ * @param {?RichParty} party The party to be displayed
347
+ * @returns {RichPresence}
348
+ */
349
+ setParty(party) {
350
+ if (typeof party == 'object') {
351
+ if (!party.max || typeof party.max != 'number') throw new Error('Party must have max number');
352
+ if (!party.current || typeof party.current != 'number') throw new Error('Party must have current');
353
+ if (party.current > party.max) throw new Error('Party current must be less than max number');
354
+ if (!party.id || typeof party.id != 'string') party.id = getUUID();
355
+ this.party = {
356
+ size: [party.current, party.max],
357
+ id: party.id,
358
+ };
359
+ } else {
360
+ this.party = null;
361
+ }
362
+ return this;
363
+ }
364
+ /**
365
+ * Sets the start timestamp of the activity
366
+ * @param {?number} timestamp The timestamp of the start of the activity
367
+ * @returns {RichPresence}
368
+ */
369
+ setStartTimestamp(timestamp) {
370
+ if (!this.timestamps) this.timestamps = {};
371
+ this.timestamps.start = timestamp;
372
+ return this;
373
+ }
374
+ /**
375
+ * Sets the end timestamp of the activity
376
+ * @param {?number} timestamp The timestamp of the end of the activity
377
+ * @returns {RichPresence}
378
+ */
379
+ setEndTimestamp(timestamp) {
380
+ if (!this.timestamps) this.timestamps = {};
381
+ this.timestamps.end = timestamp;
382
+ return this;
383
+ }
384
+ /**
385
+ * @typedef {object} RichButton
386
+ * @property {string} name The name of the button
387
+ * @property {string} url The url of the button
388
+ */
389
+ /**
390
+ * Set the buttons of the rich presence
391
+ * @param {...?RichButton} button A list of buttons to set
392
+ * @returns {RichPresence}
393
+ */
394
+ setButtons(...button) {
395
+ if (button.length == 0) {
396
+ this.buttons = null;
397
+ delete this.metadata;
398
+ return this;
399
+ } else if (button.length > 2) {
400
+ throw new Error('RichPresence can only have up to 2 buttons');
401
+ }
402
+ this.buttons = [];
403
+ this.metadata = {
404
+ button_urls: [],
405
+ };
406
+ button.flat(2).forEach(b => {
407
+ if (b.name && b.url) {
408
+ this.buttons.push(b.name);
409
+ if (!checkUrl(b.url)) throw new Error('Button url must be a valid url');
410
+ this.metadata.button_urls.push(b.url);
411
+ } else {
412
+ throw new Error('Button must have name and url');
413
+ }
414
+ });
415
+ return this;
416
+ }
417
+ /**
418
+ * Add a button to the rich presence
419
+ * @param {string} name The name of the button
420
+ * @param {string} url The url of the button
421
+ * @returns {RichPresence}
422
+ */
423
+ addButton(name, url) {
424
+ if (!name || !url) {
425
+ throw new Error('Button must have name and url');
426
+ }
427
+ if (typeof name !== 'string') throw new Error('Button name must be a string');
428
+ if (!checkUrl(url)) throw new Error('Button url must be a valid url');
429
+ if (!this.buttons) {
430
+ this.buttons = [];
431
+ this.metadata = {
432
+ button_urls: [],
433
+ };
434
+ }
435
+ this.buttons.push(name);
436
+ this.metadata.button_urls.push(url);
437
+ return this;
438
+ }
439
+ /**
440
+ * Convert the rich presence to a JSON object
441
+ * @returns {Object}
442
+ */
443
+ toJSON() {
444
+ /**
445
+ * * Verify Timestamps
446
+ */
447
+ if (this.timestamps?.start || this.timestamps?.end) {
448
+ if (this.timestamps?.start instanceof Date) {
449
+ this.timestamps.start = Math.round(this.timestamps?.start.getTime());
450
+ }
451
+ if (this.timestamps.end instanceof Date) {
452
+ this.timestamps.end = Math.round(this.timestamps.end.getTime());
453
+ }
454
+ if (this.timestamps.start > 2147483647000) {
455
+ throw new RangeError('timestamps.start must fit into a unix timestamp');
456
+ }
457
+ if (this.timestamps.end > 2147483647000) {
458
+ throw new RangeError('timestamps.end must fit into a unix timestamp');
459
+ }
460
+ }
461
+ const obj = {
462
+ name: this.name,
463
+ type: this.type || 0, // PLAYING
464
+ application_id: this.application_id,
465
+ url: this.url,
466
+ state: this.state,
467
+ details: this.details,
468
+ party: this.party,
469
+ timestamps: this.timestamps || {},
470
+ secrets: this.secrets,
471
+ assets: this.assets || {},
472
+ buttons: this.buttons,
473
+ metadata: this.metadata,
474
+ };
475
+ Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
476
+ if (!this.ipc) {
477
+ return obj;
478
+ } else {
479
+ delete obj.application_id;
480
+ delete obj.name;
481
+ delete obj.url;
482
+ obj.type = 0;
483
+ if (obj.buttons?.length) {
484
+ obj.buttons = obj.buttons.map((b, i) => ({ label: b, url: obj.metadata.button_urls[i] }));
485
+ delete obj.metadata;
486
+ }
487
+ return obj;
488
+ }
489
+ }
490
+
491
+ /**
492
+ * Get random UUID string (Util)
493
+ * @returns {string}
494
+ */
495
+ static getUUID() {
496
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, a =>
497
+ (a ^ ((Math.random() * 16) >> (a / 4))).toString(16),
498
+ );
499
+ }
500
+
501
+ /**
502
+ * Get Assets from a RichPresence (Util)
503
+ * @param {Client} client Discord Client
504
+ * @param {Snowflake} applicationId Application id
505
+ * @param {string} image1 URL image 1 (not from Discord)
506
+ * @param {string} image2 URL image 2 (not from Discord)
507
+ * @returns {ExternalAssets[]}
508
+ */
509
+ static async getExternal(client, applicationId, image1 = '', image2 = '') {
510
+ const checkURL = url => {
511
+ try {
512
+ // eslint-disable-next-line no-new
513
+ new URL(url);
514
+ return true;
515
+ } catch (e) {
516
+ return false;
517
+ }
518
+ };
519
+ if (!client || !client.token || !client.api) throw new Error('Client must be set');
520
+ // Check if applicationId is discord snowflake (17 , 18, 19 numbers)
521
+ if (!/^[0-9]{17,19}$/.test(applicationId)) {
522
+ throw new Error('Application id must be a Discord Snowflake');
523
+ }
524
+ // Check if large_image is a valid url
525
+ if (image1 && image1.length > 0 && !checkURL(image1)) {
526
+ throw new Error('Image 1 must be a valid url');
527
+ }
528
+ // Check if small_image is a valid url
529
+ if (image2 && image2.length > 0 && !checkURL(image2)) {
530
+ throw new Error('Image 2 must be a valid url');
531
+ }
532
+ const data_ = [];
533
+ if (image1) data_.push(image1);
534
+ if (image2) data_.push(image2);
535
+ const res = await client.api.applications[applicationId]['external-assets'].post({
536
+ data: {
537
+ urls: data_,
538
+ },
539
+ });
540
+ return res;
541
+ }
542
+
543
+ /**
544
+ * When concatenated with a string, this automatically returns the activities' name instead of the Activity object.
545
+ * @returns {string}
546
+ */
547
+ toString() {
548
+ return this.name;
549
+ }
550
+
551
+ _clone() {
552
+ return Object.assign(Object.create(this), this);
553
+ }
554
+ }
555
+
556
+ /**
557
+ * @extends {RichPresence}
558
+ */
559
+ class SpotifyRPC extends RichPresence {
560
+ /**
561
+ * Create a new RichPresence (Spotify style)
562
+ * @param {Client} client Discord Client
563
+ * @param {SpotifyRPC} options Options for the Spotify RPC
564
+ * @param {Presence} presence Presence
565
+ */
566
+ constructor(client, options = {}, presence) {
567
+ if (!client) throw new Error('Client must be set');
568
+ super(client, options, false, presence);
569
+ this.setup(options);
570
+ }
571
+ /**
572
+ * Sets the status from a JSON object
573
+ * @param {SpotifyRPC} options data
574
+ * @private
575
+ */
576
+ setup(options) {
577
+ this.name = options.name || 'Spotify';
578
+
579
+ this.type = ActivityTypes.LISTENING;
580
+
581
+ this.party = {
582
+ id: `spotify:${this.client.user.id}`,
583
+ };
584
+ /**
585
+ * The Spotify song's id
586
+ * @type {?string}
587
+ */
588
+ this.sync_id = options.sync_id;
589
+ /**
590
+ * The activity's id
591
+ * @type {string}
592
+ */
593
+ this.id = 'spotify:1';
594
+ /**
595
+ * Flags that describe the activity
596
+ * @type {ActivityFlags}
597
+ */
598
+ this.flags = 48; // Sync + Play (ActivityFlags)
599
+
600
+ /**
601
+ * @typedef {Object} SpotifyMetadata
602
+ * @property {string} album_id Album id
603
+ * @property {Array<string>} artist_ids Artist ids
604
+ */
605
+
606
+ /**
607
+ * Spotify metadata
608
+ * @type {SpotifyMetadata}
609
+ */
610
+ this.metadata = {
611
+ album_id: options.metadata?.album_id || null,
612
+ artist_ids: options.metadata?.artist_ids || [],
613
+ context_uri: null,
614
+ };
615
+ }
616
+
617
+ /**
618
+ * Set the large image of this activity
619
+ * @param {?string} image Spotify song's image ID
620
+ * @returns {SpotifyRPC}
621
+ */
622
+ setAssetsLargeImage(image) {
623
+ if (image.startsWith('spotify:')) image = image.replace('spotify:', '');
624
+ super.setAssetsLargeImage(`spotify:${image}`);
625
+ return this;
626
+ }
627
+
628
+ /**
629
+ * Set the small image of this activity
630
+ * @param {?string} image Spotify song's image ID
631
+ * @returns {RichPresence}
632
+ */
633
+ setAssetsSmallImage(image) {
634
+ if (image.startsWith('spotify:')) image = image.replace('spotify:', '');
635
+ super.setAssetsSmallImage(`spotify:${image}`);
636
+ return this;
637
+ }
638
+
639
+ /**
640
+ * Set Spotify song id to sync with
641
+ * @param {string} id Song id
642
+ * @returns {SpotifyRPC}
643
+ */
644
+ setSongId(id) {
645
+ this.sync_id = id;
646
+ return this;
647
+ }
648
+
649
+ /**
650
+ * Add the artist id
651
+ * @param {string} id Artist id
652
+ * @returns {SpotifyRPC}
653
+ */
654
+ addArtistId(id) {
655
+ if (!this.metadata.artist_ids) this.metadata.artist_ids = [];
656
+ this.metadata.artist_ids.push(id);
657
+ return this;
658
+ }
659
+
660
+ /**
661
+ * Set the artist ids
662
+ * @param {string | Array<string>} ids Artist ids
663
+ * @returns {SpotifyRPC}
664
+ */
665
+ setArtistIds(...ids) {
666
+ if (!ids?.length) {
667
+ this.metadata.artist_ids = [];
668
+ return this;
669
+ }
670
+ if (!this.metadata.artist_ids) this.metadata.artist_ids = [];
671
+ ids.flat(2).forEach(id => this.metadata.artist_ids.push(id));
672
+ return this;
673
+ }
674
+
675
+ /**
676
+ * Set the album id
677
+ * @param {string} id Album id
678
+ * @returns {SpotifyRPC}
679
+ */
680
+ setAlbumId(id) {
681
+ this.metadata.album_id = id;
682
+ this.metadata.context_uri = `spotify:album:${id}`;
683
+ return this;
684
+ }
685
+
686
+ /**
687
+ * Convert the rich presence to a JSON object
688
+ * @returns {SpotifyRPC}
689
+ */
690
+ toJSON() {
691
+ if (!this.sync_id) throw new Error('Song id is required');
692
+ const obj = {
693
+ name: this.name,
694
+ type: this.type,
695
+ application_id: this.application_id,
696
+ url: this.url,
697
+ state: this.state,
698
+ details: this.details,
699
+ party: this.party,
700
+ timestamps: this.timestamps || {},
701
+ assets: this.assets || {},
702
+ sync_id: this.sync_id,
703
+ flags: this.flags,
704
+ metadata: this.metadata,
705
+ };
706
+ Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key]);
707
+ return obj;
708
+ }
709
+ }
710
+
711
+ /**
712
+ * @typedef {Object} ExternalAssets
713
+ * @property {?string} url Orginal url of the image
714
+ * @property {?string} external_asset_path Proxy url of the image (Using to RPC)
715
+ */
716
+
717
+ module.exports = {
718
+ CustomStatus,
719
+ RichPresence,
720
+ SpotifyRPC,
721
+ getUUID,
722
+ };