safeness-sb-new 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +115 -0
  2. package/package.json +96 -0
  3. package/src/WebSocket.js +39 -0
  4. package/src/client/BaseClient.js +86 -0
  5. package/src/client/Client.js +836 -0
  6. package/src/client/WebhookClient.js +61 -0
  7. package/src/client/actions/Action.js +120 -0
  8. package/src/client/actions/ActionsManager.js +78 -0
  9. package/src/client/actions/ApplicationCommandPermissionsUpdate.js +34 -0
  10. package/src/client/actions/AutoModerationActionExecution.js +27 -0
  11. package/src/client/actions/AutoModerationRuleCreate.js +28 -0
  12. package/src/client/actions/AutoModerationRuleDelete.js +32 -0
  13. package/src/client/actions/AutoModerationRuleUpdate.js +30 -0
  14. package/src/client/actions/ChannelCreate.js +23 -0
  15. package/src/client/actions/ChannelDelete.js +39 -0
  16. package/src/client/actions/ChannelUpdate.js +43 -0
  17. package/src/client/actions/GuildAuditLogEntryCreate.js +29 -0
  18. package/src/client/actions/GuildBanAdd.js +20 -0
  19. package/src/client/actions/GuildBanRemove.js +25 -0
  20. package/src/client/actions/GuildChannelsPositionUpdate.js +21 -0
  21. package/src/client/actions/GuildDelete.js +65 -0
  22. package/src/client/actions/GuildEmojiCreate.js +20 -0
  23. package/src/client/actions/GuildEmojiDelete.js +21 -0
  24. package/src/client/actions/GuildEmojiUpdate.js +20 -0
  25. package/src/client/actions/GuildEmojisUpdate.js +34 -0
  26. package/src/client/actions/GuildIntegrationsUpdate.js +19 -0
  27. package/src/client/actions/GuildMemberRemove.js +33 -0
  28. package/src/client/actions/GuildMemberUpdate.js +44 -0
  29. package/src/client/actions/GuildRoleCreate.js +25 -0
  30. package/src/client/actions/GuildRoleDelete.js +31 -0
  31. package/src/client/actions/GuildRoleUpdate.js +39 -0
  32. package/src/client/actions/GuildRolesPositionUpdate.js +21 -0
  33. package/src/client/actions/GuildScheduledEventCreate.js +27 -0
  34. package/src/client/actions/GuildScheduledEventDelete.js +31 -0
  35. package/src/client/actions/GuildScheduledEventUpdate.js +30 -0
  36. package/src/client/actions/GuildScheduledEventUserAdd.js +32 -0
  37. package/src/client/actions/GuildScheduledEventUserRemove.js +32 -0
  38. package/src/client/actions/GuildStickerCreate.js +20 -0
  39. package/src/client/actions/GuildStickerDelete.js +21 -0
  40. package/src/client/actions/GuildStickerUpdate.js +20 -0
  41. package/src/client/actions/GuildStickersUpdate.js +34 -0
  42. package/src/client/actions/GuildUpdate.js +33 -0
  43. package/src/client/actions/InviteCreate.js +28 -0
  44. package/src/client/actions/InviteDelete.js +30 -0
  45. package/src/client/actions/MessageCreate.js +46 -0
  46. package/src/client/actions/MessageDelete.js +32 -0
  47. package/src/client/actions/MessageDeleteBulk.js +46 -0
  48. package/src/client/actions/MessageReactionAdd.js +56 -0
  49. package/src/client/actions/MessageReactionRemove.js +45 -0
  50. package/src/client/actions/MessageReactionRemoveAll.js +33 -0
  51. package/src/client/actions/MessageReactionRemoveEmoji.js +28 -0
  52. package/src/client/actions/MessageUpdate.js +26 -0
  53. package/src/client/actions/PresenceUpdate.js +46 -0
  54. package/src/client/actions/StageInstanceCreate.js +28 -0
  55. package/src/client/actions/StageInstanceDelete.js +33 -0
  56. package/src/client/actions/StageInstanceUpdate.js +30 -0
  57. package/src/client/actions/ThreadCreate.js +24 -0
  58. package/src/client/actions/ThreadDelete.js +32 -0
  59. package/src/client/actions/ThreadListSync.js +59 -0
  60. package/src/client/actions/ThreadMemberUpdate.js +30 -0
  61. package/src/client/actions/ThreadMembersUpdate.js +34 -0
  62. package/src/client/actions/TypingStart.js +29 -0
  63. package/src/client/actions/UserUpdate.js +35 -0
  64. package/src/client/actions/VoiceStateUpdate.js +57 -0
  65. package/src/client/actions/WebhooksUpdate.js +20 -0
  66. package/src/client/voice/ClientVoiceManager.js +150 -0
  67. package/src/client/voice/VoiceConnection.js +849 -0
  68. package/src/client/voice/dispatcher/AnnexBDispatcher.js +120 -0
  69. package/src/client/voice/dispatcher/AudioDispatcher.js +115 -0
  70. package/src/client/voice/dispatcher/BaseDispatcher.js +405 -0
  71. package/src/client/voice/dispatcher/VPxDispatcher.js +52 -0
  72. package/src/client/voice/dispatcher/VideoDispatcher.js +31 -0
  73. package/src/client/voice/networking/VoiceUDPClient.js +188 -0
  74. package/src/client/voice/networking/VoiceWebSocket.js +280 -0
  75. package/src/client/voice/player/MediaPlayer.js +294 -0
  76. package/src/client/voice/player/processing/AnnexBNalSplitter.js +244 -0
  77. package/src/client/voice/player/processing/IvfSplitter.js +106 -0
  78. package/src/client/voice/receiver/PacketHandler.js +170 -0
  79. package/src/client/voice/receiver/Receiver.js +82 -0
  80. package/src/client/voice/receiver/video/IvfJoinner.js +106 -0
  81. package/src/client/voice/util/Function.js +14 -0
  82. package/src/client/voice/util/PlayInterface.js +122 -0
  83. package/src/client/voice/util/Secretbox.js +42 -0
  84. package/src/client/voice/util/Silence.js +16 -0
  85. package/src/client/voice/util/Socket.js +62 -0
  86. package/src/client/voice/util/VolumeInterface.js +104 -0
  87. package/src/client/websocket/WebSocketManager.js +392 -0
  88. package/src/client/websocket/WebSocketShard.js +906 -0
  89. package/src/client/websocket/handlers/APPLICATION_COMMAND_CREATE.js +18 -0
  90. package/src/client/websocket/handlers/APPLICATION_COMMAND_DELETE.js +20 -0
  91. package/src/client/websocket/handlers/APPLICATION_COMMAND_PERMISSIONS_UPDATE.js +5 -0
  92. package/src/client/websocket/handlers/APPLICATION_COMMAND_UPDATE.js +20 -0
  93. package/src/client/websocket/handlers/AUTO_MODERATION_ACTION_EXECUTION.js +5 -0
  94. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_CREATE.js +5 -0
  95. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_DELETE.js +5 -0
  96. package/src/client/websocket/handlers/AUTO_MODERATION_RULE_UPDATE.js +5 -0
  97. package/src/client/websocket/handlers/CALL_CREATE.js +14 -0
  98. package/src/client/websocket/handlers/CALL_DELETE.js +11 -0
  99. package/src/client/websocket/handlers/CALL_UPDATE.js +11 -0
  100. package/src/client/websocket/handlers/CHANNEL_CREATE.js +5 -0
  101. package/src/client/websocket/handlers/CHANNEL_DELETE.js +5 -0
  102. package/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +22 -0
  103. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +19 -0
  104. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +16 -0
  105. package/src/client/websocket/handlers/CHANNEL_UPDATE.js +16 -0
  106. package/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js +5 -0
  107. package/src/client/websocket/handlers/GUILD_BAN_ADD.js +5 -0
  108. package/src/client/websocket/handlers/GUILD_BAN_REMOVE.js +5 -0
  109. package/src/client/websocket/handlers/GUILD_CREATE.js +52 -0
  110. package/src/client/websocket/handlers/GUILD_DELETE.js +5 -0
  111. package/src/client/websocket/handlers/GUILD_EMOJIS_UPDATE.js +5 -0
  112. package/src/client/websocket/handlers/GUILD_INTEGRATIONS_UPDATE.js +5 -0
  113. package/src/client/websocket/handlers/GUILD_MEMBERS_CHUNK.js +39 -0
  114. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +20 -0
  115. package/src/client/websocket/handlers/GUILD_MEMBER_REMOVE.js +5 -0
  116. package/src/client/websocket/handlers/GUILD_MEMBER_UPDATE.js +5 -0
  117. package/src/client/websocket/handlers/GUILD_ROLE_CREATE.js +5 -0
  118. package/src/client/websocket/handlers/GUILD_ROLE_DELETE.js +5 -0
  119. package/src/client/websocket/handlers/GUILD_ROLE_UPDATE.js +5 -0
  120. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_CREATE.js +5 -0
  121. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_DELETE.js +5 -0
  122. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_UPDATE.js +5 -0
  123. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_ADD.js +5 -0
  124. package/src/client/websocket/handlers/GUILD_SCHEDULED_EVENT_USER_REMOVE.js +5 -0
  125. package/src/client/websocket/handlers/GUILD_STICKERS_UPDATE.js +5 -0
  126. package/src/client/websocket/handlers/GUILD_UPDATE.js +5 -0
  127. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +12 -0
  128. package/src/client/websocket/handlers/INVITE_CREATE.js +5 -0
  129. package/src/client/websocket/handlers/INVITE_DELETE.js +5 -0
  130. package/src/client/websocket/handlers/MESSAGE_CREATE.js +5 -0
  131. package/src/client/websocket/handlers/MESSAGE_DELETE.js +5 -0
  132. package/src/client/websocket/handlers/MESSAGE_DELETE_BULK.js +5 -0
  133. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +22 -0
  134. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +12 -0
  135. package/src/client/websocket/handlers/MESSAGE_REACTION_ADD.js +5 -0
  136. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE.js +5 -0
  137. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_ALL.js +5 -0
  138. package/src/client/websocket/handlers/MESSAGE_REACTION_REMOVE_EMOJI.js +5 -0
  139. package/src/client/websocket/handlers/MESSAGE_UPDATE.js +16 -0
  140. package/src/client/websocket/handlers/PRESENCE_UPDATE.js +5 -0
  141. package/src/client/websocket/handlers/READY.js +120 -0
  142. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +19 -0
  143. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +17 -0
  144. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +41 -0
  145. package/src/client/websocket/handlers/RESUMED.js +14 -0
  146. package/src/client/websocket/handlers/STAGE_INSTANCE_CREATE.js +5 -0
  147. package/src/client/websocket/handlers/STAGE_INSTANCE_DELETE.js +5 -0
  148. package/src/client/websocket/handlers/STAGE_INSTANCE_UPDATE.js +5 -0
  149. package/src/client/websocket/handlers/THREAD_CREATE.js +5 -0
  150. package/src/client/websocket/handlers/THREAD_DELETE.js +5 -0
  151. package/src/client/websocket/handlers/THREAD_LIST_SYNC.js +5 -0
  152. package/src/client/websocket/handlers/THREAD_MEMBERS_UPDATE.js +5 -0
  153. package/src/client/websocket/handlers/THREAD_MEMBER_UPDATE.js +5 -0
  154. package/src/client/websocket/handlers/THREAD_UPDATE.js +16 -0
  155. package/src/client/websocket/handlers/TYPING_START.js +5 -0
  156. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +6 -0
  157. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +5 -0
  158. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -0
  159. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +5 -0
  160. package/src/client/websocket/handlers/USER_UPDATE.js +5 -0
  161. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -0
  162. package/src/client/websocket/handlers/VOICE_SERVER_UPDATE.js +6 -0
  163. package/src/client/websocket/handlers/VOICE_STATE_UPDATE.js +5 -0
  164. package/src/client/websocket/handlers/WEBHOOKS_UPDATE.js +5 -0
  165. package/src/client/websocket/handlers/index.js +83 -0
  166. package/src/errors/DJSError.js +61 -0
  167. package/src/errors/Messages.js +208 -0
  168. package/src/errors/index.js +4 -0
  169. package/src/index.js +159 -0
  170. package/src/managers/ApplicationCommandManager.js +264 -0
  171. package/src/managers/ApplicationCommandPermissionsManager.js +417 -0
  172. package/src/managers/AutoModerationRuleManager.js +296 -0
  173. package/src/managers/BaseGuildEmojiManager.js +80 -0
  174. package/src/managers/BaseManager.js +19 -0
  175. package/src/managers/BillingManager.js +66 -0
  176. package/src/managers/CachedManager.js +71 -0
  177. package/src/managers/ChannelManager.js +138 -0
  178. package/src/managers/ClientUserSettingManager.js +372 -0
  179. package/src/managers/DataManager.js +61 -0
  180. package/src/managers/GuildBanManager.js +204 -0
  181. package/src/managers/GuildChannelManager.js +488 -0
  182. package/src/managers/GuildEmojiManager.js +171 -0
  183. package/src/managers/GuildEmojiRoleManager.js +118 -0
  184. package/src/managers/GuildForumThreadManager.js +108 -0
  185. package/src/managers/GuildInviteManager.js +213 -0
  186. package/src/managers/GuildManager.js +304 -0
  187. package/src/managers/GuildMemberManager.js +597 -0
  188. package/src/managers/GuildMemberRoleManager.js +191 -0
  189. package/src/managers/GuildScheduledEventManager.js +296 -0
  190. package/src/managers/GuildSettingManager.js +155 -0
  191. package/src/managers/GuildStickerManager.js +179 -0
  192. package/src/managers/GuildTextThreadManager.js +98 -0
  193. package/src/managers/InteractionManager.js +39 -0
  194. package/src/managers/MessageManager.js +391 -0
  195. package/src/managers/PermissionOverwriteManager.js +166 -0
  196. package/src/managers/PresenceManager.js +58 -0
  197. package/src/managers/ReactionManager.js +67 -0
  198. package/src/managers/ReactionUserManager.js +71 -0
  199. package/src/managers/RelationshipManager.js +265 -0
  200. package/src/managers/RoleManager.js +352 -0
  201. package/src/managers/StageInstanceManager.js +162 -0
  202. package/src/managers/ThreadManager.js +174 -0
  203. package/src/managers/ThreadMemberManager.js +186 -0
  204. package/src/managers/UserManager.js +146 -0
  205. package/src/managers/UserNoteManager.js +53 -0
  206. package/src/managers/VoiceStateManager.js +37 -0
  207. package/src/rest/APIRequest.js +159 -0
  208. package/src/rest/APIRouter.js +53 -0
  209. package/src/rest/DiscordAPIError.js +104 -0
  210. package/src/rest/HTTPError.js +62 -0
  211. package/src/rest/RESTManager.js +62 -0
  212. package/src/rest/RateLimitError.js +55 -0
  213. package/src/rest/RequestHandler.js +444 -0
  214. package/src/sharding/Shard.js +443 -0
  215. package/src/sharding/ShardClientUtil.js +275 -0
  216. package/src/sharding/ShardingManager.js +318 -0
  217. package/src/structures/AnonymousGuild.js +98 -0
  218. package/src/structures/ApplicationCommand.js +593 -0
  219. package/src/structures/ApplicationRoleConnectionMetadata.js +48 -0
  220. package/src/structures/AutoModerationActionExecution.js +89 -0
  221. package/src/structures/AutoModerationRule.js +294 -0
  222. package/src/structures/AutocompleteInteraction.js +107 -0
  223. package/src/structures/Base.js +43 -0
  224. package/src/structures/BaseCommandInteraction.js +211 -0
  225. package/src/structures/BaseGuild.js +116 -0
  226. package/src/structures/BaseGuildEmoji.js +56 -0
  227. package/src/structures/BaseGuildTextChannel.js +191 -0
  228. package/src/structures/BaseGuildVoiceChannel.js +241 -0
  229. package/src/structures/BaseMessageComponent.js +114 -0
  230. package/src/structures/ButtonInteraction.js +11 -0
  231. package/src/structures/CallState.js +63 -0
  232. package/src/structures/CategoryChannel.js +85 -0
  233. package/src/structures/Channel.js +270 -0
  234. package/src/structures/ClientPresence.js +77 -0
  235. package/src/structures/ClientUser.js +450 -0
  236. package/src/structures/CommandInteraction.js +41 -0
  237. package/src/structures/CommandInteractionOptionResolver.js +276 -0
  238. package/src/structures/ContextMenuInteraction.js +65 -0
  239. package/src/structures/DMChannel.js +217 -0
  240. package/src/structures/DirectoryChannel.js +20 -0
  241. package/src/structures/Emoji.js +148 -0
  242. package/src/structures/ForumChannel.js +261 -0
  243. package/src/structures/GroupDMChannel.js +387 -0
  244. package/src/structures/Guild.js +1608 -0
  245. package/src/structures/GuildAuditLogs.js +729 -0
  246. package/src/structures/GuildBan.js +59 -0
  247. package/src/structures/GuildBoost.js +108 -0
  248. package/src/structures/GuildChannel.js +468 -0
  249. package/src/structures/GuildEmoji.js +161 -0
  250. package/src/structures/GuildMember.js +568 -0
  251. package/src/structures/GuildPreview.js +191 -0
  252. package/src/structures/GuildPreviewEmoji.js +27 -0
  253. package/src/structures/GuildScheduledEvent.js +441 -0
  254. package/src/structures/GuildTemplate.js +236 -0
  255. package/src/structures/Integration.js +188 -0
  256. package/src/structures/IntegrationApplication.js +96 -0
  257. package/src/structures/Interaction.js +290 -0
  258. package/src/structures/InteractionCollector.js +248 -0
  259. package/src/structures/InteractionWebhook.js +43 -0
  260. package/src/structures/Invite.js +358 -0
  261. package/src/structures/InviteGuild.js +23 -0
  262. package/src/structures/InviteStageInstance.js +86 -0
  263. package/src/structures/Message.js +1227 -0
  264. package/src/structures/MessageActionRow.js +103 -0
  265. package/src/structures/MessageAttachment.js +204 -0
  266. package/src/structures/MessageButton.js +165 -0
  267. package/src/structures/MessageCollector.js +146 -0
  268. package/src/structures/MessageComponentInteraction.js +120 -0
  269. package/src/structures/MessageContextMenuInteraction.js +20 -0
  270. package/src/structures/MessageEmbed.js +586 -0
  271. package/src/structures/MessageMentions.js +273 -0
  272. package/src/structures/MessagePayload.js +318 -0
  273. package/src/structures/MessagePoll.js +238 -0
  274. package/src/structures/MessageReaction.js +171 -0
  275. package/src/structures/MessageSelectMenu.js +140 -0
  276. package/src/structures/Modal.js +161 -0
  277. package/src/structures/ModalSubmitFieldsResolver.js +53 -0
  278. package/src/structures/ModalSubmitInteraction.js +119 -0
  279. package/src/structures/NewsChannel.js +32 -0
  280. package/src/structures/OAuth2Guild.js +28 -0
  281. package/src/structures/PermissionOverwrites.js +196 -0
  282. package/src/structures/Presence.js +1131 -0
  283. package/src/structures/ReactionCollector.js +229 -0
  284. package/src/structures/ReactionEmoji.js +31 -0
  285. package/src/structures/Role.js +531 -0
  286. package/src/structures/SelectMenuInteraction.js +21 -0
  287. package/src/structures/StageChannel.js +104 -0
  288. package/src/structures/StageInstance.js +208 -0
  289. package/src/structures/Sticker.js +310 -0
  290. package/src/structures/StickerPack.js +95 -0
  291. package/src/structures/StoreChannel.js +56 -0
  292. package/src/structures/Team.js +118 -0
  293. package/src/structures/TeamMember.js +71 -0
  294. package/src/structures/TextChannel.js +33 -0
  295. package/src/structures/TextInputComponent.js +131 -0
  296. package/src/structures/ThreadChannel.js +607 -0
  297. package/src/structures/ThreadMember.js +105 -0
  298. package/src/structures/Typing.js +74 -0
  299. package/src/structures/User.js +543 -0
  300. package/src/structures/UserContextMenuInteraction.js +29 -0
  301. package/src/structures/VoiceChannel.js +110 -0
  302. package/src/structures/VoiceRegion.js +53 -0
  303. package/src/structures/VoiceState.js +345 -0
  304. package/src/structures/WebEmbed.js +373 -0
  305. package/src/structures/Webhook.js +467 -0
  306. package/src/structures/WelcomeChannel.js +60 -0
  307. package/src/structures/WelcomeScreen.js +48 -0
  308. package/src/structures/Widget.js +87 -0
  309. package/src/structures/WidgetMember.js +99 -0
  310. package/src/structures/interfaces/Application.js +313 -0
  311. package/src/structures/interfaces/Collector.js +300 -0
  312. package/src/structures/interfaces/InteractionResponses.js +313 -0
  313. package/src/structures/interfaces/TextBasedChannel.js +719 -0
  314. package/src/util/ActivityFlags.js +44 -0
  315. package/src/util/ApplicationFlags.js +76 -0
  316. package/src/util/AttachmentFlags.js +38 -0
  317. package/src/util/BitField.js +170 -0
  318. package/src/util/ChannelFlags.js +45 -0
  319. package/src/util/Constants.js +1815 -0
  320. package/src/util/DataResolver.js +145 -0
  321. package/src/util/Formatters.js +228 -0
  322. package/src/util/GuildMemberFlags.js +43 -0
  323. package/src/util/Intents.js +74 -0
  324. package/src/util/InviteFlags.js +29 -0
  325. package/src/util/LimitedCollection.js +131 -0
  326. package/src/util/MessageFlags.js +54 -0
  327. package/src/util/Options.js +336 -0
  328. package/src/util/Permissions.js +202 -0
  329. package/src/util/PremiumUsageFlags.js +31 -0
  330. package/src/util/PurchasedFlags.js +33 -0
  331. package/src/util/RemoteAuth.js +382 -0
  332. package/src/util/RoleFlags.js +37 -0
  333. package/src/util/SnowflakeUtil.js +92 -0
  334. package/src/util/Speaking.js +33 -0
  335. package/src/util/Sweepers.js +466 -0
  336. package/src/util/SystemChannelFlags.js +55 -0
  337. package/src/util/ThreadMemberFlags.js +30 -0
  338. package/src/util/UserFlags.js +104 -0
  339. package/src/util/Util.js +889 -0
  340. package/typings/enums.d.ts +297 -0
  341. package/typings/index.d.ts +7670 -0
  342. package/typings/index.test-d.ts +0 -0
  343. package/typings/rawDataTypes.d.ts +342 -0
@@ -0,0 +1,1131 @@
1
+ 'use strict';
2
+
3
+ const { randomUUID } = require('node:crypto');
4
+ const Base = require('./Base');
5
+ const ActivityFlags = require('../util/ActivityFlags');
6
+ const { ActivityTypes } = require('../util/Constants');
7
+ const Util = require('../util/Util');
8
+
9
+ /**
10
+ * Activity sent in a message.
11
+ * @typedef {Object} MessageActivity
12
+ * @property {string} [partyId] Id of the party represented in activity
13
+ * @property {MessageActivityType} type Type of activity sent
14
+ */
15
+
16
+ /**
17
+ * @external MessageActivityType
18
+ * @see {@link https://discord-api-types.dev/api/discord-api-types-v9/enum/MessageActivityType}
19
+ */
20
+
21
+ /**
22
+ * The status of this presence:
23
+ * * **`online`** - user is online
24
+ * * **`idle`** - user is AFK
25
+ * * **`offline`** - user is offline or invisible
26
+ * * **`dnd`** - user is in Do Not Disturb
27
+ * @typedef {string} PresenceStatus
28
+ */
29
+
30
+ /**
31
+ * The status of this presence:
32
+ * * **`online`** - user is online
33
+ * * **`idle`** - user is AFK
34
+ * * **`dnd`** - user is in Do Not Disturb
35
+ * @typedef {string} ClientPresenceStatus
36
+ */
37
+
38
+ /**
39
+ * Represents a user's presence.
40
+ * @extends {Base}
41
+ */
42
+ class Presence extends Base {
43
+ constructor(client, data = {}) {
44
+ super(client);
45
+
46
+ /**
47
+ * The presence's user id
48
+ * @type {Snowflake}
49
+ */
50
+ this.userId = data.user.id;
51
+
52
+ /**
53
+ * The guild this presence is in
54
+ * @type {?Guild}
55
+ */
56
+ this.guild = data.guild ?? null;
57
+
58
+ this._patch(data);
59
+ }
60
+
61
+ /**
62
+ * The user of this presence
63
+ * @type {?User}
64
+ * @readonly
65
+ */
66
+ get user() {
67
+ return this.client.users.resolve(this.userId);
68
+ }
69
+
70
+ /**
71
+ * The member of this presence
72
+ * @type {?GuildMember}
73
+ * @readonly
74
+ */
75
+ get member() {
76
+ return this.guild.members.resolve(this.userId);
77
+ }
78
+
79
+ _patch(data) {
80
+ if ('status' in data) {
81
+ /**
82
+ * The status of this presence
83
+ * @type {PresenceStatus}
84
+ */
85
+ this.status = data.status;
86
+ } else {
87
+ this.status ??= 'offline';
88
+ }
89
+
90
+ if ('activities' in data) {
91
+ /**
92
+ * The activities of this presence (Always `Activity[]` if not ClientUser)
93
+ * @type {CustomStatus[]|RichPresence[]|SpotifyRPC[]|Activity[]}
94
+ */
95
+ this.activities = data.activities.map(activity => {
96
+ if (this.userId == this.client.user.id) {
97
+ if ([ActivityTypes.CUSTOM, 'CUSTOM'].includes(activity.type)) {
98
+ return new CustomStatus(this.client, activity);
99
+ } else if (activity.id == 'spotify:1') {
100
+ return new SpotifyRPC(this.client, activity);
101
+ } else {
102
+ return new RichPresence(this.client, activity);
103
+ }
104
+ } else {
105
+ return new Activity(this, activity);
106
+ }
107
+ });
108
+ } else {
109
+ this.activities ??= [];
110
+ }
111
+
112
+ if ('client_status' in data) {
113
+ /**
114
+ * The devices this presence is on
115
+ * @type {?Object}
116
+ * @property {?ClientPresenceStatus} web The current presence in the web application
117
+ * @property {?ClientPresenceStatus} mobile The current presence in the mobile application
118
+ * @property {?ClientPresenceStatus} desktop The current presence in the desktop application
119
+ */
120
+ this.clientStatus = data.client_status;
121
+ } else {
122
+ this.clientStatus ??= null;
123
+ }
124
+
125
+ if ('last_modified' in data) {
126
+ /**
127
+ * The timestamp this presence was last updated
128
+ * @type {number}
129
+ */
130
+ this.lastModified = data.last_modified;
131
+ }
132
+
133
+ if ('afk' in data) {
134
+ this.afk = data.afk;
135
+ } else {
136
+ this.afk ??= false;
137
+ }
138
+
139
+ if ('since' in data) {
140
+ this.since = data.since;
141
+ } else {
142
+ this.since ??= 0;
143
+ }
144
+
145
+ return this;
146
+ }
147
+
148
+ _clone() {
149
+ const clone = Object.assign(Object.create(this), this);
150
+ clone.activities = this.activities.map(activity => activity._clone());
151
+ return clone;
152
+ }
153
+
154
+ /**
155
+ * Whether this presence is equal to another.
156
+ * @param {Presence} presence The presence to compare with
157
+ * @returns {boolean}
158
+ */
159
+ equals(presence) {
160
+ return (
161
+ this === presence ||
162
+ (presence &&
163
+ this.status === presence.status &&
164
+ this.activities.length === presence.activities.length &&
165
+ this.activities.every((activity, index) => activity.equals(presence.activities[index])) &&
166
+ this.clientStatus?.web === presence.clientStatus?.web &&
167
+ this.clientStatus?.mobile === presence.clientStatus?.mobile &&
168
+ this.clientStatus?.desktop === presence.clientStatus?.desktop)
169
+ );
170
+ }
171
+
172
+ toJSON() {
173
+ return Util.flatten(this);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * The platform of this activity:
179
+ * * **`desktop`**
180
+ * * **`samsung`** - playing on Samsung Galaxy
181
+ * * **`xbox`** - playing on Xbox Live
182
+ * * **`ios`**
183
+ * * **`android`**
184
+ * * **`embedded`**
185
+ * * **`ps4`**
186
+ * * **`ps5`**
187
+ * @typedef {string} ActivityPlatform
188
+ */
189
+
190
+ /**
191
+ * Represents an activity that is part of a user's presence.
192
+ */
193
+ class Activity {
194
+ constructor(presence, data) {
195
+ if (!(presence instanceof Presence)) {
196
+ throw new Error("Class constructor Activity cannot be invoked without 'presence'");
197
+ }
198
+ /**
199
+ * The presence of the Activity
200
+ * @type {Presence}
201
+ * @readonly
202
+ * @name Activity#presence
203
+ */
204
+ Object.defineProperty(this, 'presence', { value: presence });
205
+
206
+ this._patch(data);
207
+ }
208
+
209
+ _patch(data = {}) {
210
+ if ('id' in data) {
211
+ /**
212
+ * The activity's id
213
+ * @type {string}
214
+ */
215
+ this.id = data.id;
216
+ }
217
+
218
+ if ('name' in data) {
219
+ /**
220
+ * The activity's name
221
+ * @type {string}
222
+ */
223
+ this.name = data.name;
224
+ }
225
+
226
+ if ('type' in data) {
227
+ /**
228
+ * The activity status's type
229
+ * @type {ActivityType}
230
+ */
231
+ this.type = typeof data.type === 'number' ? ActivityTypes[data.type] : data.type;
232
+ }
233
+
234
+ if ('url' in data) {
235
+ /**
236
+ * If the activity is being streamed, a link to the stream
237
+ * @type {?string}
238
+ */
239
+ this.url = data.url;
240
+ } else {
241
+ this.url = null;
242
+ }
243
+
244
+ if ('created_at' in data || 'createdTimestamp' in data) {
245
+ /**
246
+ * Creation date of the activity
247
+ * @type {number}
248
+ */
249
+ this.createdTimestamp = data.created_at || data.createdTimestamp;
250
+ }
251
+
252
+ if ('session_id' in data) {
253
+ /**
254
+ * The game's or Spotify session's id
255
+ * @type {?string}
256
+ */
257
+ this.sessionId = data.session_id;
258
+ } else {
259
+ this.sessionId = this.presence.client?.sessionId;
260
+ }
261
+
262
+ if ('platform' in data) {
263
+ /**
264
+ * The platform the game is being played on
265
+ * @type {?ActivityPlatform}
266
+ */
267
+ this.platform = data.platform;
268
+ } else {
269
+ this.platform = null;
270
+ }
271
+
272
+ if ('timestamps' in data && data.timestamps) {
273
+ /**
274
+ * Represents timestamps of an activity
275
+ * @typedef {Object} ActivityTimestamps
276
+ * @property {?number} start When the activity started
277
+ * @property {?number} end When the activity will end
278
+ */
279
+
280
+ /**
281
+ * Timestamps for the activity
282
+ * @type {?ActivityTimestamps}
283
+ */
284
+ this.timestamps = {
285
+ start: data.timestamps.start ? new Date(data.timestamps.start).getTime() : null,
286
+ end: data.timestamps.end ? new Date(data.timestamps.end).getTime() : null,
287
+ };
288
+ } else {
289
+ this.timestamps = null;
290
+ }
291
+
292
+ if ('application_id' in data || 'applicationId' in data) {
293
+ /**
294
+ * The id of the application associated with this activity
295
+ * @type {?Snowflake}
296
+ */
297
+ this.applicationId = data.application_id || data.applicationId;
298
+ } else {
299
+ this.applicationId = null;
300
+ }
301
+
302
+ if ('details' in data) {
303
+ /**
304
+ * Details about the activity
305
+ * @type {?string}
306
+ */
307
+ this.details = data.details;
308
+ } else {
309
+ this.details = null;
310
+ }
311
+
312
+ if ('state' in data) {
313
+ /**
314
+ * State of the activity
315
+ * @type {?string}
316
+ */
317
+ this.state = data.state;
318
+ } else {
319
+ this.state = null;
320
+ }
321
+
322
+ if ('sync_id' in data || 'syncId' in data) {
323
+ /**
324
+ * The Spotify song's id
325
+ * @type {?string}
326
+ */
327
+ this.syncId = data.sync_id || data.syncId;
328
+ } else {
329
+ this.syncId = null;
330
+ }
331
+
332
+ if ('flags' in data) {
333
+ /**
334
+ * Flags that describe the activity
335
+ * @type {Readonly<ActivityFlags>}
336
+ */
337
+ this.flags = new ActivityFlags(data.flags).freeze();
338
+ } else {
339
+ this.flags = new ActivityFlags().freeze();
340
+ }
341
+
342
+ if ('buttons' in data) {
343
+ /**
344
+ * The labels of the buttons of this rich presence
345
+ * @type {string[]}
346
+ */
347
+ this.buttons = data.buttons;
348
+ } else {
349
+ this.buttons = [];
350
+ }
351
+
352
+ if ('emoji' in data && data.emoji) {
353
+ /**
354
+ * Emoji for a custom activity
355
+ * @type {?EmojiIdentifierResolvable}
356
+ */
357
+ this.emoji = Util.resolvePartialEmoji(data.emoji);
358
+ } else {
359
+ this.emoji = null;
360
+ }
361
+
362
+ if ('party' in data) {
363
+ /**
364
+ * Represents a party of an activity
365
+ * @typedef {Object} ActivityParty
366
+ * @property {?string} id The party's id
367
+ * @property {number[]} size Size of the party as `[current, max]`
368
+ */
369
+
370
+ /**
371
+ * Party of the activity
372
+ * @type {?ActivityParty}
373
+ */
374
+ this.party = data.party;
375
+ } else {
376
+ this.party = null;
377
+ }
378
+
379
+ /**
380
+ * Assets for rich presence
381
+ * @type {?RichPresenceAssets}
382
+ */
383
+ this.assets = new RichPresenceAssets(this, data.assets);
384
+ }
385
+
386
+ /**
387
+ * Whether this activity is equal to another activity.
388
+ * @param {Activity} activity The activity to compare with
389
+ * @returns {boolean}
390
+ */
391
+ equals(activity) {
392
+ return (
393
+ this === activity ||
394
+ (activity &&
395
+ this.name === activity.name &&
396
+ this.type === activity.type &&
397
+ this.url === activity.url &&
398
+ this.state === activity.state &&
399
+ this.details === activity.details &&
400
+ this.emoji?.id === activity.emoji?.id &&
401
+ this.emoji?.name === activity.emoji?.name)
402
+ );
403
+ }
404
+
405
+ /**
406
+ * The time the activity was created at
407
+ * @type {Date}
408
+ * @readonly
409
+ */
410
+ get createdAt() {
411
+ return new Date(this.createdTimestamp);
412
+ }
413
+
414
+ /**
415
+ * When concatenated with a string, this automatically returns the activities' name instead of the Activity object.
416
+ * @returns {string}
417
+ */
418
+ toString() {
419
+ return this.name;
420
+ }
421
+
422
+ _clone() {
423
+ return Object.assign(Object.create(this), this);
424
+ }
425
+
426
+ toJSON(...props) {
427
+ return Util.clearNullOrUndefinedObject({
428
+ ...Util.flatten(this, ...props),
429
+ type: typeof this.type === 'number' ? this.type : ActivityTypes[this.type],
430
+ });
431
+ }
432
+ }
433
+
434
+ /**
435
+ * Assets for a rich presence
436
+ */
437
+ class RichPresenceAssets {
438
+ constructor(activity, assets) {
439
+ /**
440
+ * The activity of the RichPresenceAssets
441
+ * @type {Activity}
442
+ * @readonly
443
+ * @name RichPresenceAssets#activity
444
+ */
445
+ Object.defineProperty(this, 'activity', { value: activity });
446
+
447
+ this._patch(assets);
448
+ }
449
+
450
+ _patch(assets = {}) {
451
+ if ('large_text' in assets || 'largeText' in assets) {
452
+ /**
453
+ * Hover text for the large image
454
+ * @type {?string}
455
+ */
456
+ this.largeText = assets.large_text || assets.largeText;
457
+ } else {
458
+ this.largeText = null;
459
+ }
460
+
461
+ if ('small_text' in assets || 'smallText' in assets) {
462
+ /**
463
+ * Hover text for the small image
464
+ * @type {?string}
465
+ */
466
+ this.smallText = assets.small_text || assets.smallText;
467
+ } else {
468
+ this.smallText = null;
469
+ }
470
+
471
+ if ('large_image' in assets || 'largeImage' in assets) {
472
+ /**
473
+ * The large image asset's id
474
+ * @type {?Snowflake}
475
+ */
476
+ this.largeImage = assets.large_image || assets.largeImage;
477
+ } else {
478
+ this.largeImage = null;
479
+ }
480
+
481
+ if ('small_image' in assets || 'smallImage' in assets) {
482
+ /**
483
+ * The small image asset's id
484
+ * @type {?Snowflake}
485
+ */
486
+ this.smallImage = assets.small_image || assets.smallImage;
487
+ } else {
488
+ this.smallImage = null;
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Gets the URL of the small image asset
494
+ * @param {StaticImageURLOptions} [options] Options for the image URL
495
+ * @returns {?string}
496
+ */
497
+ smallImageURL({ format, size } = {}) {
498
+ if (!this.smallImage) return null;
499
+ if (this.smallImage.includes(':')) {
500
+ const [platform, id] = this.smallImage.split(':');
501
+ switch (platform) {
502
+ case 'mp':
503
+ return `https://media.discordapp.net/${id}`;
504
+ case 'spotify':
505
+ return `https://i.scdn.co/image/${id}`;
506
+ case 'youtube':
507
+ return `https://i.ytimg.com/vi/${id}/hqdefault_live.jpg`;
508
+ case 'twitch':
509
+ return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${id}.png`;
510
+ default:
511
+ return null;
512
+ }
513
+ }
514
+
515
+ return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationId, this.smallImage, {
516
+ format,
517
+ size,
518
+ });
519
+ }
520
+
521
+ /**
522
+ * Gets the URL of the large image asset
523
+ * @param {StaticImageURLOptions} [options] Options for the image URL
524
+ * @returns {?string}
525
+ */
526
+ largeImageURL({ format, size } = {}) {
527
+ if (!this.largeImage) return null;
528
+ if (this.largeImage.includes(':')) {
529
+ const [platform, id] = this.largeImage.split(':');
530
+ switch (platform) {
531
+ case 'mp':
532
+ return `https://media.discordapp.net/${id}`;
533
+ case 'spotify':
534
+ return `https://i.scdn.co/image/${id}`;
535
+ case 'youtube':
536
+ return `https://i.ytimg.com/vi/${id}/hqdefault_live.jpg`;
537
+ case 'twitch':
538
+ return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${id}.png`;
539
+ default:
540
+ return null;
541
+ }
542
+ }
543
+
544
+ return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationId, this.largeImage, {
545
+ format,
546
+ size,
547
+ });
548
+ }
549
+
550
+ static parseImage(image) {
551
+ if (typeof image !== 'string') {
552
+ image = null;
553
+ } else {
554
+ try {
555
+ const url = new URL(image);
556
+ if (['http:', 'https:'].includes(url.protocol)) {
557
+ // Discord URL:
558
+ image = image
559
+ .replace('https://cdn.discordapp.com/', 'mp:')
560
+ .replace('http://cdn.discordapp.com/', 'mp:')
561
+ .replace('https://media.discordapp.net/', 'mp:')
562
+ .replace('http://media.discordapp.net/', 'mp:');
563
+ if (!image.startsWith('mp:')) {
564
+ throw new Error('INVALID_URL');
565
+ }
566
+ }
567
+ } catch (e) {
568
+ // L'image n'est pas une URL valide
569
+ if (/^[0-9]{17,19}$/.test(image)) {
570
+ // ID Assets
571
+ } else if (['mp:', 'youtube:', 'spotify:', 'twitch:'].some(v => image.startsWith(v))) {
572
+ // Image
573
+ } else if (image.startsWith('external/')) {
574
+ image = `mp:${image}`;
575
+ } else {
576
+ image = null; // Ou vous pouvez lancer une erreur ici si nécessaire
577
+ }
578
+ }
579
+ }
580
+ return image;
581
+ }
582
+
583
+ toJSON() {
584
+ if (!this.largeImage && !this.largeText && !this.smallImage && !this.smallText) return null;
585
+ return {
586
+ large_image: RichPresenceAssets.parseImage(this.largeImage),
587
+ large_text: this.largeText,
588
+ small_image: RichPresenceAssets.parseImage(this.smallImage),
589
+ small_text: this.smallText,
590
+ };
591
+ }
592
+
593
+ /**
594
+ * @typedef {string} RichPresenceImage
595
+ * Support:
596
+ * - cdn.discordapp.com
597
+ * - media.discordapp.net
598
+ * - Assets ID (https://discord.com/api/v9/oauth2/applications/{application_id}/assets)
599
+ * - Media Proxy (mp:external/{hash})
600
+ * - Twitch (twitch:{username})
601
+ * - YouTube (youtube:{video_id})
602
+ * - Spotify (spotify:{image_id})
603
+ */
604
+
605
+ /**
606
+ * Set the large image of this activity
607
+ * @param {?RichPresenceImage} image The large image asset's id
608
+ * @returns {RichPresenceAssets}
609
+ */
610
+ setLargeImage(image) {
611
+ image = RichPresenceAssets.parseImage(image);
612
+ this.largeImage = image;
613
+ return this;
614
+ }
615
+
616
+ /**
617
+ * Set the small image of this activity
618
+ * @param {?RichPresenceImage} image The small image asset's id
619
+ * @returns {RichPresenceAssets}
620
+ */
621
+ setSmallImage(image) {
622
+ image = RichPresenceAssets.parseImage(image);
623
+ this.smallImage = image;
624
+ return this;
625
+ }
626
+
627
+ /**
628
+ * Hover text for the large image
629
+ * @param {string} text Assets text
630
+ * @returns {RichPresenceAssets}
631
+ */
632
+ setLargeText(text) {
633
+ this.largeText = text;
634
+ return this;
635
+ }
636
+
637
+ /**
638
+ * Hover text for the small image
639
+ * @param {string} text Assets text
640
+ * @returns {RichPresenceAssets}
641
+ */
642
+ setSmallText(text) {
643
+ this.smallText = text;
644
+ return this;
645
+ }
646
+ }
647
+
648
+ class CustomStatus extends Activity {
649
+ /**
650
+ * @typedef {Object} CustomStatusOptions
651
+ * @property {string} [state] The state to be displayed
652
+ * @property {EmojiIdentifierResolvable} [emoji] The emoji to be displayed
653
+ */
654
+
655
+ /**
656
+ * @param {Client} client Discord Client
657
+ * @param {CustomStatus|CustomStatusOptions} [data={}] CustomStatus to clone or raw data
658
+ */
659
+ constructor(client, data = {}) {
660
+ if (!client) throw new Error("Class constructor CustomStatus cannot be invoked without 'client'");
661
+ super('presence' in client ? client.presence : client, {
662
+ name: 'Custom Status',
663
+ type: ActivityTypes.CUSTOM,
664
+ ...data,
665
+ });
666
+ }
667
+
668
+ /**
669
+ * Set the emoji of this activity
670
+ * @param {EmojiIdentifierResolvable} emoji The emoji to be displayed
671
+ * @returns {CustomStatus}
672
+ */
673
+ setEmoji(emoji) {
674
+ this.emoji = Util.resolvePartialEmoji(emoji);
675
+ return this;
676
+ }
677
+
678
+ /**
679
+ * Set state of this activity
680
+ * @param {string | null} state The state to be displayed
681
+ * @returns {CustomStatus}
682
+ */
683
+ setState(state) {
684
+ if (typeof state == 'string' && state.length > 128) throw new Error('State must be less than 128 characters');
685
+ this.state = state;
686
+ return this;
687
+ }
688
+
689
+ /**
690
+ * Returns an object that can be used to set the status
691
+ * @returns {CustomStatus}
692
+ */
693
+ toJSON() {
694
+ if (!this.emoji & !this.state) throw new Error('CustomStatus must have at least one of emoji or state');
695
+ return {
696
+ name: this.name,
697
+ emoji: this.emoji,
698
+ type: ActivityTypes.CUSTOM,
699
+ state: this.state,
700
+ };
701
+ }
702
+ }
703
+
704
+ class RichPresence extends Activity {
705
+ /**
706
+ * @param {Client} client Discord client
707
+ * @param {RichPresence} [data={}] RichPresence to clone or raw data
708
+ */
709
+ constructor(client, data = {}) {
710
+ if (!client) throw new Error("Class constructor RichPresence cannot be invoked without 'client'");
711
+ super('presence' in client ? client.presence : client, { type: 0, ...data });
712
+ this.setup(data);
713
+ }
714
+
715
+ /**
716
+ * Sets the status from a JSON object
717
+ * @param {RichPresence} data data
718
+ * @private
719
+ */
720
+ setup(data = {}) {
721
+ this.secrets = 'secrets' in data ? data.secrets : {};
722
+ this.metadata = 'metadata' in data ? data.metadata : {};
723
+ }
724
+
725
+ /**
726
+ * Set the large image of this activity
727
+ * @param {?RichPresenceImage} image The large image asset's id
728
+ * @returns {RichPresence}
729
+ */
730
+ setAssetsLargeImage(image) {
731
+ this.assets.setLargeImage(image);
732
+ return this;
733
+ }
734
+
735
+ /**
736
+ * Set the small image of this activity
737
+ * @param {?RichPresenceImage} image The small image asset's id
738
+ * @returns {RichPresence}
739
+ */
740
+ setAssetsSmallImage(image) {
741
+ this.assets.setSmallImage(image);
742
+ return this;
743
+ }
744
+
745
+ /**
746
+ * Hover text for the large image
747
+ * @param {string} text Assets text
748
+ * @returns {RichPresence}
749
+ */
750
+ setAssetsLargeText(text) {
751
+ this.assets.setLargeText(text);
752
+ return this;
753
+ }
754
+
755
+ /**
756
+ * Hover text for the small image
757
+ * @param {string} text Assets text
758
+ * @returns {RichPresence}
759
+ */
760
+ setAssetsSmallText(text) {
761
+ this.assets.setSmallText(text);
762
+ return this;
763
+ }
764
+
765
+ /**
766
+ * Set the name of the activity
767
+ * @param {?string} name The activity's name
768
+ * @returns {RichPresence}
769
+ */
770
+ setName(name) {
771
+ this.name = name;
772
+ return this;
773
+ }
774
+
775
+ /**
776
+ * If the activity is being streamed, a link to the stream
777
+ * @param {?string} url URL of the stream
778
+ * @returns {RichPresence}
779
+ */
780
+ setURL(url) {
781
+ if (typeof url == 'string' && !URL.canParse(url)) throw new Error('URL must be a valid URL');
782
+ this.url = url;
783
+ return this;
784
+ }
785
+
786
+ /**
787
+ * The activity status's type
788
+ * @param {?ActivityTypes} type The type of activity
789
+ * @returns {RichPresence}
790
+ */
791
+ setType(type) {
792
+ this.type = typeof type == 'number' ? type : ActivityTypes[type];
793
+ return this;
794
+ }
795
+
796
+ /**
797
+ * Set the application id of this activity
798
+ * @param {?Snowflake} id Bot's id
799
+ * @returns {RichPresence}
800
+ */
801
+ setApplicationId(id) {
802
+ this.applicationId = id;
803
+ return this;
804
+ }
805
+
806
+ /**
807
+ * Set the state of the activity
808
+ * @param {?string} state The state of the activity
809
+ * @returns {RichPresence}
810
+ */
811
+ setState(state) {
812
+ this.state = state;
813
+ return this;
814
+ }
815
+
816
+ /**
817
+ * Set the details of the activity
818
+ * @param {?string} details The details of the activity
819
+ * @returns {RichPresence}
820
+ */
821
+ setDetails(details) {
822
+ this.details = details;
823
+ return this;
824
+ }
825
+
826
+ /**
827
+ * @typedef {Object} RichParty
828
+ * @property {string} id The id of the party
829
+ * @property {number} max The maximum number of members in the party
830
+ * @property {number} current The current number of members in the party
831
+ */
832
+
833
+ /**
834
+ * Set the party of this activity
835
+ * @param {?RichParty} party The party to be displayed
836
+ * @returns {RichPresence}
837
+ */
838
+ setParty(party) {
839
+ if (typeof party == 'object') {
840
+ if (!party.max || typeof party.max != 'number') throw new Error('Party must have max number');
841
+ if (!party.current || typeof party.current != 'number') throw new Error('Party must have current');
842
+ if (party.current > party.max) throw new Error('Party current must be less than max number');
843
+ if (!party.id || typeof party.id != 'string') party.id = randomUUID();
844
+ this.party = {
845
+ size: [party.current, party.max],
846
+ id: party.id,
847
+ };
848
+ } else {
849
+ this.party = null;
850
+ }
851
+ return this;
852
+ }
853
+
854
+ /**
855
+ * Sets the start timestamp of the activity
856
+ * @param {Date|number|null} timestamp The timestamp of the start of the activity
857
+ * @returns {RichPresence}
858
+ */
859
+ setStartTimestamp(timestamp) {
860
+ if (!this.timestamps) this.timestamps = {};
861
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
862
+ this.timestamps.start = timestamp;
863
+ return this;
864
+ }
865
+
866
+ /**
867
+ * Sets the end timestamp of the activity
868
+ * @param {Date|number|null} timestamp The timestamp of the end of the activity
869
+ * @returns {RichPresence}
870
+ */
871
+ setEndTimestamp(timestamp) {
872
+ if (!this.timestamps) this.timestamps = {};
873
+ if (timestamp instanceof Date) timestamp = timestamp.getTime();
874
+ this.timestamps.end = timestamp;
875
+ return this;
876
+ }
877
+
878
+ /**
879
+ * @typedef {object} RichButton
880
+ * @property {string} name The name of the button
881
+ * @property {string} url The url of the button
882
+ */
883
+ /**
884
+ * Set the buttons of the rich presence
885
+ * @param {...?RichButton} button A list of buttons to set
886
+ * @returns {RichPresence}
887
+ */
888
+ setButtons(...button) {
889
+ if (button.length == 0) {
890
+ this.buttons = [];
891
+ delete this.metadata.button_urls;
892
+ return this;
893
+ } else if (button.length > 2) {
894
+ throw new Error('RichPresence can only have up to 2 buttons');
895
+ }
896
+
897
+ this.buttons = [];
898
+ this.metadata.button_urls = [];
899
+
900
+ button.flat(2).forEach(b => {
901
+ if (b.name && b.url) {
902
+ this.buttons.push(b.name);
903
+ if (!URL.canParse(b.url)) throw new Error('Button url must be a valid url');
904
+ this.metadata.button_urls.push(b.url);
905
+ } else {
906
+ throw new Error('Button must have name and url');
907
+ }
908
+ });
909
+ return this;
910
+ }
911
+
912
+ /**
913
+ * The platform the activity is being played on
914
+ * @param {ActivityPlatform | null} platform Any platform
915
+ * @returns {RichPresence}
916
+ */
917
+ setPlatform(platform) {
918
+ this.platform = platform;
919
+ return this;
920
+ }
921
+
922
+ /**
923
+ * Secrets for rich presence joining and spectating (send-only)
924
+ * @param {?string} join Secrets for rich presence joining
925
+ * @returns {RichPresence}
926
+ */
927
+ setJoinSecret(join) {
928
+ this.secrets.join = join;
929
+ return this;
930
+ }
931
+
932
+ /**
933
+ * Add a button to the rich presence
934
+ * @param {string} name The name of the button
935
+ * @param {string} url The url of the button
936
+ * @returns {RichPresence}
937
+ */
938
+ addButton(name, url) {
939
+ if (!name || !url) {
940
+ throw new Error('Button must have name and url');
941
+ }
942
+ if (typeof name !== 'string') throw new Error('Button name must be a string');
943
+ if (!URL.canParse(url)) throw new Error('Button url must be a valid url');
944
+ this.buttons.push(name);
945
+ if (Array.isArray(this.metadata.button_urls)) this.metadata.button_urls.push(url);
946
+ else this.metadata.button_urls = [url];
947
+ return this;
948
+ }
949
+
950
+ /**
951
+ * Convert the rich presence to a JSON object
952
+ * @returns {Object}
953
+ */
954
+ toJSON(...props) {
955
+ return super.toJSON(
956
+ {
957
+ applicationId: 'application_id',
958
+ sessionId: 'session_id',
959
+ syncId: 'sync_id',
960
+ createdTimestamp: 'created_at',
961
+ },
962
+ ...props,
963
+ );
964
+ }
965
+
966
+ /**
967
+ * @typedef {Object} ExternalAssets
968
+ * @property {?string} url Orginal url of the image
969
+ * @property {?string} external_asset_path Proxy url of the image (Using to RPC)
970
+ */
971
+
972
+ /**
973
+ * Get Assets from a RichPresence (Util)
974
+ * @param {Client} client Discord Client
975
+ * @param {Snowflake} applicationId Application id
976
+ * @param {string} image1 URL image 1 (not from Discord)
977
+ * @param {string} image2 URL image 2 (not from Discord)
978
+ * @returns {ExternalAssets[]}
979
+ */
980
+ static async getExternal(client, applicationId, image1 = '', image2 = '') {
981
+ if (!client || !client.token || !client.api) throw new Error('Client must be set');
982
+ // Check if applicationId is discord snowflake (17 , 18, 19 numbers)
983
+ if (!/^[0-9]{17,19}$/.test(applicationId)) {
984
+ throw new Error('Application id must be a Discord Snowflake');
985
+ }
986
+ // Check if large_image is a valid url
987
+ if (image1 && image1.length > 0) {
988
+ try {
989
+ new URL(image1);
990
+ } catch (_) {
991
+ throw new Error('Image 1 must be a valid URL');
992
+ }
993
+ }
994
+ // Check if small_image is a valid url
995
+ if (image2 && image2.length > 0) {
996
+ try {
997
+ new URL(image2);
998
+ } catch (_) {
999
+ throw new Error('Image 2 must be a valid URL');
1000
+ }
1001
+ }
1002
+ const data_ = [];
1003
+ if (image1) data_.push(image1);
1004
+ if (image2) data_.push(image2);
1005
+ const res = await client.api.applications[applicationId]['external-assets'].post({
1006
+ data: {
1007
+ urls: data_,
1008
+ },
1009
+ });
1010
+ return res;
1011
+ };
1012
+
1013
+ /**
1014
+ * When concatenated with a string, this automatically returns the activities' name instead of the Activity object.
1015
+ * @returns {string}
1016
+ */
1017
+ toString() {
1018
+ return this.name;
1019
+ }
1020
+
1021
+ _clone() {
1022
+ return Object.assign(Object.create(this), this);
1023
+ }
1024
+ }
1025
+
1026
+ /**
1027
+ * @extends {RichPresence}
1028
+ */
1029
+ class SpotifyRPC extends RichPresence {
1030
+ /**
1031
+ * Create a new RichPresence (Spotify style)
1032
+ * @param {Client} client Discord Client
1033
+ * @param {SpotifyRPC} [options] Options for the Spotify RPC
1034
+ */
1035
+ constructor(client, options = {}) {
1036
+ if (!client) throw new Error("Class constructor SpotifyRPC cannot be invoked without 'client'");
1037
+ super(client, {
1038
+ name: 'Spotify',
1039
+ type: ActivityTypes.LISTENING,
1040
+ party: {
1041
+ id: `spotify:${client.user.id}`,
1042
+ },
1043
+ id: 'spotify:1',
1044
+ flags: 48, // Sync + Play (ActivityFlags)
1045
+ ...options,
1046
+ });
1047
+ this.setup(options);
1048
+ }
1049
+ /**
1050
+ * Sets the status from a JSON object
1051
+ * @param {SpotifyRPC} options data
1052
+ * @private
1053
+ */
1054
+ setup(options) {
1055
+ /**
1056
+ * @typedef {Object} SpotifyMetadata
1057
+ * @property {string} album_id The Spotify ID of the album of the song being played
1058
+ * @property {Array<string>} artist_ids The Spotify IDs of the artists of the song being played
1059
+ * @property {string} context_uri The Spotify URI of the current player context
1060
+ */
1061
+
1062
+ /**
1063
+ * Spotify metadata
1064
+ * @type {SpotifyMetadata}
1065
+ */
1066
+ this.metadata = {
1067
+ album_id: options.metadata?.album_id || null,
1068
+ artist_ids: options.metadata?.artist_ids || [],
1069
+ context_uri: options.metadata?.context_uri || null,
1070
+ };
1071
+ }
1072
+
1073
+ /**
1074
+ * Set Spotify song id to sync with
1075
+ * @param {string} id Song id
1076
+ * @returns {SpotifyRPC}
1077
+ */
1078
+ setSongId(id) {
1079
+ this.syncId = id;
1080
+ return this;
1081
+ }
1082
+
1083
+ /**
1084
+ * Add the artist id
1085
+ * @param {string} id Artist id
1086
+ * @returns {SpotifyRPC}
1087
+ */
1088
+ addArtistId(id) {
1089
+ if (!this.metadata.artist_ids) this.metadata.artist_ids = [];
1090
+ this.metadata.artist_ids.push(id);
1091
+ return this;
1092
+ }
1093
+
1094
+ /**
1095
+ * Set the artist ids
1096
+ * @param {string | Array<string>} ids Artist ids
1097
+ * @returns {SpotifyRPC}
1098
+ */
1099
+ setArtistIds(...ids) {
1100
+ if (!ids?.length) {
1101
+ this.metadata.artist_ids = [];
1102
+ return this;
1103
+ }
1104
+ if (!this.metadata.artist_ids) this.metadata.artist_ids = [];
1105
+ ids.flat(2).forEach(id => this.metadata.artist_ids.push(id));
1106
+ return this;
1107
+ }
1108
+
1109
+ /**
1110
+ * Set the album id
1111
+ * @param {string} id Album id
1112
+ * @returns {SpotifyRPC}
1113
+ */
1114
+ setAlbumId(id) {
1115
+ this.metadata.album_id = id;
1116
+ this.metadata.context_uri = `spotify:album:${id}`;
1117
+ return this;
1118
+ }
1119
+
1120
+ toJSON() {
1121
+ return super.toJSON({ id: false, emoji: false, platform: false, buttons: false });
1122
+ }
1123
+ }
1124
+
1125
+ exports.Presence = Presence;
1126
+ exports.Activity = Activity;
1127
+ exports.RichPresenceAssets = RichPresenceAssets;
1128
+ exports.CustomStatus = CustomStatus;
1129
+ exports.RichPresence = RichPresence;
1130
+ exports.SpotifyRPC = SpotifyRPC;
1131
+