djs-selfbot-v13 3.1.7 → 3.2.2

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 (155) hide show
  1. package/README.md +18 -35
  2. package/package.json +85 -100
  3. package/src/client/BaseClient.js +3 -4
  4. package/src/client/Client.js +249 -530
  5. package/src/client/actions/Action.js +18 -13
  6. package/src/client/actions/ActionsManager.js +7 -1
  7. package/src/client/actions/AutoModerationActionExecution.js +1 -0
  8. package/src/client/actions/AutoModerationRuleCreate.js +1 -0
  9. package/src/client/actions/AutoModerationRuleDelete.js +1 -0
  10. package/src/client/actions/AutoModerationRuleUpdate.js +1 -0
  11. package/src/client/actions/GuildMemberRemove.js +0 -1
  12. package/src/client/actions/GuildMemberUpdate.js +0 -1
  13. package/src/client/actions/MessageCreate.js +0 -4
  14. package/src/client/actions/PresenceUpdate.js +17 -16
  15. package/src/client/websocket/WebSocketManager.js +11 -31
  16. package/src/client/websocket/WebSocketShard.js +39 -38
  17. package/src/client/websocket/handlers/CALL_CREATE.js +3 -3
  18. package/src/client/websocket/handlers/CALL_DELETE.js +2 -2
  19. package/src/client/websocket/handlers/CALL_UPDATE.js +2 -2
  20. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_ADD.js +16 -13
  21. package/src/client/websocket/handlers/CHANNEL_RECIPIENT_REMOVE.js +11 -11
  22. package/src/client/websocket/handlers/GUILD_CREATE.js +19 -13
  23. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +0 -1
  24. package/src/client/websocket/handlers/INTERACTION_MODAL_CREATE.js +1 -0
  25. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +22 -0
  26. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +12 -0
  27. package/src/client/websocket/handlers/READY.js +90 -140
  28. package/src/client/websocket/handlers/RELATIONSHIP_ADD.js +7 -5
  29. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +7 -5
  30. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +32 -9
  31. package/src/client/websocket/handlers/USER_GUILD_SETTINGS_UPDATE.js +2 -8
  32. package/src/client/websocket/handlers/USER_NOTE_UPDATE.js +1 -1
  33. package/src/client/websocket/handlers/USER_REQUIRED_ACTION_UPDATE.js +78 -0
  34. package/src/client/websocket/handlers/USER_SETTINGS_UPDATE.js +1 -5
  35. package/src/client/websocket/handlers/VOICE_CHANNEL_STATUS_UPDATE.js +12 -0
  36. package/src/client/websocket/handlers/index.js +17 -20
  37. package/src/errors/Messages.js +25 -69
  38. package/src/index.js +13 -43
  39. package/src/managers/ApplicationCommandManager.js +9 -12
  40. package/src/managers/ApplicationCommandPermissionsManager.js +3 -11
  41. package/src/managers/ChannelManager.js +2 -3
  42. package/src/managers/ClientUserSettingManager.js +162 -280
  43. package/src/managers/GuildBanManager.js +47 -1
  44. package/src/managers/GuildChannelManager.js +2 -16
  45. package/src/managers/GuildForumThreadManager.js +24 -30
  46. package/src/managers/GuildManager.js +1 -1
  47. package/src/managers/GuildMemberManager.js +50 -222
  48. package/src/managers/GuildSettingManager.js +22 -15
  49. package/src/managers/MessageManager.js +42 -44
  50. package/src/managers/PermissionOverwriteManager.js +1 -1
  51. package/src/managers/ReactionUserManager.js +5 -5
  52. package/src/managers/RelationshipManager.js +83 -76
  53. package/src/managers/ThreadManager.js +12 -45
  54. package/src/managers/ThreadMemberManager.js +1 -1
  55. package/src/managers/UserManager.js +6 -10
  56. package/src/managers/UserNoteManager.js +53 -0
  57. package/src/rest/APIRequest.js +48 -20
  58. package/src/rest/DiscordAPIError.js +17 -16
  59. package/src/rest/RESTManager.js +1 -21
  60. package/src/rest/RequestHandler.js +35 -21
  61. package/src/structures/ApplicationCommand.js +19 -456
  62. package/src/structures/ApplicationRoleConnectionMetadata.js +3 -0
  63. package/src/structures/AutoModerationRule.js +5 -5
  64. package/src/structures/AutocompleteInteraction.js +1 -0
  65. package/src/structures/BaseGuildTextChannel.js +10 -12
  66. package/src/structures/BaseGuildVoiceChannel.js +16 -18
  67. package/src/structures/{Call.js → CallState.js} +17 -12
  68. package/src/structures/CategoryChannel.js +2 -0
  69. package/src/structures/Channel.js +2 -3
  70. package/src/structures/ClientPresence.js +20 -19
  71. package/src/structures/ClientUser.js +117 -338
  72. package/src/structures/ContextMenuInteraction.js +1 -1
  73. package/src/structures/DMChannel.js +29 -92
  74. package/src/structures/ForumChannel.js +0 -10
  75. package/src/structures/GroupDMChannel.js +387 -0
  76. package/src/structures/Guild.js +135 -271
  77. package/src/structures/GuildAuditLogs.js +0 -5
  78. package/src/structures/GuildChannel.js +16 -2
  79. package/src/structures/GuildMember.js +27 -145
  80. package/src/structures/Interaction.js +1 -62
  81. package/src/structures/Invite.js +35 -52
  82. package/src/structures/Message.js +220 -203
  83. package/src/structures/MessageAttachment.js +11 -0
  84. package/src/structures/MessageButton.js +1 -67
  85. package/src/structures/MessageEmbed.js +1 -1
  86. package/src/structures/MessageMentions.js +3 -2
  87. package/src/structures/MessagePayload.js +6 -46
  88. package/src/structures/MessagePoll.js +238 -0
  89. package/src/structures/MessageReaction.js +1 -1
  90. package/src/structures/MessageSelectMenu.js +1 -252
  91. package/src/structures/Modal.js +70 -188
  92. package/src/structures/Presence.js +787 -129
  93. package/src/structures/Role.js +18 -2
  94. package/src/structures/SelectMenuInteraction.js +2 -151
  95. package/src/structures/Team.js +0 -49
  96. package/src/structures/TextInputComponent.js +0 -70
  97. package/src/structures/ThreadChannel.js +0 -19
  98. package/src/structures/User.js +145 -339
  99. package/src/structures/UserContextMenuInteraction.js +2 -2
  100. package/src/structures/VoiceState.js +74 -39
  101. package/src/structures/WebEmbed.js +38 -52
  102. package/src/structures/Webhook.js +17 -11
  103. package/src/structures/interfaces/Application.js +146 -23
  104. package/src/structures/interfaces/TextBasedChannel.js +409 -256
  105. package/src/util/ApplicationFlags.js +1 -1
  106. package/src/util/AttachmentFlags.js +38 -0
  107. package/src/util/Constants.js +120 -285
  108. package/src/util/Formatters.js +16 -2
  109. package/src/util/InviteFlags.js +29 -0
  110. package/src/util/LimitedCollection.js +1 -1
  111. package/src/util/Options.js +48 -74
  112. package/src/util/Permissions.js +15 -0
  113. package/src/util/PurchasedFlags.js +2 -0
  114. package/src/util/RemoteAuth.js +221 -356
  115. package/src/util/RoleFlags.js +37 -0
  116. package/src/util/Sweepers.js +1 -1
  117. package/src/util/Util.js +158 -32
  118. package/typings/enums.d.ts +24 -73
  119. package/typings/index.d.ts +978 -1288
  120. package/typings/rawDataTypes.d.ts +68 -9
  121. package/src/client/actions/InteractionCreate.js +0 -115
  122. package/src/client/websocket/handlers/APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE.js +0 -23
  123. package/src/client/websocket/handlers/GUILD_APPLICATION_COMMANDS_UPDATE.js +0 -11
  124. package/src/client/websocket/handlers/GUILD_MEMBER_LIST_UPDATE.js +0 -55
  125. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUNDS_UPDATE.js +0 -0
  126. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_CREATE.js +0 -0
  127. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_DELETE.js +0 -0
  128. package/src/client/websocket/handlers/GUILD_SOUNDBOARD_SOUND_UPDATE.js +0 -0
  129. package/src/client/websocket/handlers/INTERACTION_CREATE.js +0 -16
  130. package/src/client/websocket/handlers/INTERACTION_FAILURE.js +0 -18
  131. package/src/client/websocket/handlers/INTERACTION_SUCCESS.js +0 -30
  132. package/src/client/websocket/handlers/MESSAGE_ACK.js +0 -16
  133. package/src/client/websocket/handlers/SOUNDBOARD_SOUNDS.js +0 -0
  134. package/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js +0 -0
  135. package/src/managers/DeveloperPortalManager.js +0 -104
  136. package/src/managers/GuildApplicationCommandManager.js +0 -28
  137. package/src/managers/GuildFolderManager.js +0 -24
  138. package/src/managers/SessionManager.js +0 -57
  139. package/src/rest/CaptchaSolver.js +0 -132
  140. package/src/structures/ClientApplication.js +0 -204
  141. package/src/structures/DeveloperPortalApplication.js +0 -520
  142. package/src/structures/GuildFolder.js +0 -75
  143. package/src/structures/InteractionResponse.js +0 -114
  144. package/src/structures/PartialGroupDMChannel.js +0 -433
  145. package/src/structures/RichPresence.js +0 -722
  146. package/src/structures/Session.js +0 -81
  147. package/src/util/Voice.js +0 -1456
  148. package/src/util/arRPC/index.js +0 -229
  149. package/src/util/arRPC/process/detectable.json +0 -1
  150. package/src/util/arRPC/process/index.js +0 -102
  151. package/src/util/arRPC/process/native/index.js +0 -5
  152. package/src/util/arRPC/process/native/linux.js +0 -37
  153. package/src/util/arRPC/process/native/win32.js +0 -25
  154. package/src/util/arRPC/transports/ipc.js +0 -281
  155. package/src/util/arRPC/transports/websocket.js +0 -128
@@ -2,109 +2,19 @@
2
2
 
3
3
  const { Collection } = require('@discordjs/collection');
4
4
  const BaseManager = require('./BaseManager');
5
- const GuildFolderManager = require('./GuildFolderManager');
6
- const { Error, TypeError } = require('../errors/DJSError');
7
- const GuildFolder = require('../structures/GuildFolder');
8
- const { CustomStatus } = require('../structures/RichPresence');
9
- const { localeSetting, DMScanLevel, stickerAnimationMode } = require('../util/Constants');
5
+ const { TypeError } = require('../errors/DJSError');
6
+ const { CustomStatus } = require('../structures/Presence');
7
+ const { ActivityTypes } = require('../util/Constants');
8
+
10
9
  /**
11
10
  * Manages API methods for users and stores their cache.
12
11
  * @extends {BaseManager}
13
12
  * @see {@link https://luna.gitlab.io/discord-unofficial-docs/user_settings.html}
14
13
  */
15
14
  class ClientUserSettingManager extends BaseManager {
15
+ #rawSetting = {};
16
16
  constructor(client) {
17
17
  super(client);
18
- /**
19
- * Raw data
20
- * @type {Object}
21
- */
22
- this.rawSetting = {};
23
- /**
24
- * Language
25
- * @type {?string}
26
- */
27
- this.locale = null;
28
- /**
29
- * From: Setting => ACTIVITY SETTINGS => Activity Status => Display current activity as a status message
30
- * @type {?boolean}
31
- */
32
- this.activityDisplay = null;
33
- /**
34
- * Disable Direct Message from servers
35
- * @type {Collection<Snowflake, boolean>}
36
- */
37
- this.disableDMfromServer = new Collection();
38
- /**
39
- * Allow direct messages from server members
40
- * @type {?boolean}
41
- */
42
- this.DMfromServerMode = null;
43
- /**
44
- * Display images
45
- * @type {?boolean}
46
- */
47
- this.displayImage = null;
48
- /**
49
- * Display linked images
50
- * @type {?boolean}
51
- */
52
- this.linkedImageDisplay = null;
53
- /**
54
- * From: Setting => APP SETTINGS => Accessibility => Automatically play GIFs when Discord is focused.
55
- * @type {?boolean}
56
- */
57
- this.autoplayGIF = null;
58
- /**
59
- * Show embeds and preview website links pasted into chat
60
- * @type {?boolean}
61
- */
62
- this.previewLink = null;
63
- /**
64
- * From: Setting => APP SETTINGS => Accessibility => Play Animated Emojis
65
- * @type {?boolean}
66
- */
67
- this.animatedEmojis = null;
68
- /**
69
- * From: Setting => APP SETTINGS => Accessibility => Text-to-speech => Allow playback
70
- * @type {?boolean}
71
- */
72
- this.allowTTS = null;
73
- /**
74
- * From: Setting => APP SETTINGS => Appearance => Message Display => Compact Mode
75
- * @type {?boolean}
76
- */
77
- this.compactMode = null;
78
- /**
79
- * From: Setting => APP SETTINGS => Text & Images => Emoji => Convert Emoticons
80
- * @type {?boolean}
81
- */
82
- this.convertEmoticons = null;
83
- /**
84
- * SAFE DIRECT MESSAGING
85
- * @type {?DMScanLevel}
86
- */
87
- this.DMScanLevel = null;
88
- /**
89
- * From: Setting => APP SETTINGS => Appearance => Theme
90
- * @type {'dark' | 'light' | null}
91
- */
92
- this.theme = '';
93
- /**
94
- * Developer Mode (Copy ID, etc.)
95
- * @type {?boolean}
96
- */
97
- this.developerMode = null;
98
- /**
99
- * AFK timeout (receives notifications)
100
- * @type {?number}
101
- */
102
- this.afkTimeout = null;
103
- /**
104
- * Sticker animation mode
105
- * @type {?stickerAnimationMode}
106
- */
107
- this.stickerAnimationMode = null;
108
18
  /**
109
19
  * WHO CAN ADD YOU AS A FRIEND ?
110
20
  * @type {?object}
@@ -115,153 +25,240 @@ class ClientUserSettingManager extends BaseManager {
115
25
  mutual_friends: null,
116
26
  mutual_guilds: null,
117
27
  };
118
- /**
119
- * From: Setting => APP SETTINGS => Text & Images => Emoji => Show emoji reactions
120
- * @type {?boolean}
121
- */
122
- this.showEmojiReactions = null;
123
- /**
124
- * Custom Stauts
125
- * @type {?object}
126
- * @see {@link https://luna.gitlab.io/discord-unofficial-docs/custom_status.html#customstatus-structure}
127
- */
128
- this.customStatus = null;
129
- /**
130
- * Guild folder and position
131
- * @type {GuildFolderManager}
132
- */
133
- this.guildFolder = new GuildFolderManager(client);
134
- // Todo: add new method from Discum
135
28
  }
136
29
  /**
137
30
  * Patch data file
138
- * https://github.com/Merubokkusu/Discord-S.C.U.M/blob/master/discum/user/user.py
31
+ * https://luna.gitlab.io/discord-unofficial-docs/docs/user_settings
139
32
  * @private
140
33
  * @param {Object} data Raw Data to patch
141
34
  */
142
35
  _patch(data = {}) {
143
- this.rawSetting = Object.assign(this.rawSetting, data);
36
+ this.#rawSetting = Object.assign(this.#rawSetting, data);
37
+ this.client.emit('debug', `[SETTING > ClientUser] Sync setting`);
144
38
  if ('locale' in data) {
145
- this.locale = localeSetting[data.locale];
39
+ /**
40
+ * The user's chosen language option
41
+ * @type {?string}
42
+ * @see {@link https://discord.com/developers/docs/reference#locales}
43
+ */
44
+ this.locale = data.locale;
146
45
  }
147
46
  if ('show_current_game' in data) {
47
+ /**
48
+ * Show playing status for detected/added games
49
+ * <info>Setting => ACTIVITY SETTINGS => Activity Status => Display current activity as a status message</info>
50
+ * @type {?boolean}
51
+ */
148
52
  this.activityDisplay = data.show_current_game;
149
53
  }
150
54
  if ('default_guilds_restricted' in data) {
151
- this.DMfromServerMode = data.default_guilds_restricted;
55
+ /**
56
+ * Allow DMs from guild members by default on guild join
57
+ * @type {?boolean}
58
+ */
59
+ this.allowDMsFromGuild = data.default_guilds_restricted;
152
60
  }
153
61
  if ('inline_attachment_media' in data) {
62
+ /**
63
+ * Display images and video when uploaded directly
64
+ * @type {?boolean}
65
+ */
154
66
  this.displayImage = data.inline_attachment_media;
155
67
  }
156
68
  if ('inline_embed_media' in data) {
69
+ /**
70
+ * Display images and video when linked
71
+ * @type {?boolean}
72
+ */
157
73
  this.linkedImageDisplay = data.inline_embed_media;
158
74
  }
159
75
  if ('gif_auto_play' in data) {
76
+ /**
77
+ * Play GIFs without hovering over them
78
+ * <info>Setting => APP SETTINGS => Accessibility => Automatically play GIFs when Discord is focused.</info>
79
+ * @type {?boolean}
80
+ */
160
81
  this.autoplayGIF = data.gif_auto_play;
161
82
  }
162
83
  if ('render_embeds' in data) {
84
+ /**
85
+ * Show embeds and preview website links pasted into chat
86
+ * @type {?boolean}
87
+ */
163
88
  this.previewLink = data.render_embeds;
164
89
  }
165
90
  if ('animate_emoji' in data) {
166
- this.animatedEmojis = data.animate_emoji;
91
+ /**
92
+ * Play animated emoji without hovering over them
93
+ * <info>Setting => APP SETTINGS => Accessibility => Play Animated Emojis</info>
94
+ * @type {?boolean}
95
+ */
96
+ this.animatedEmoji = data.animate_emoji;
167
97
  }
168
98
  if ('enable_tts_command' in data) {
99
+ /**
100
+ * Enable /tts command and playback
101
+ * <info>Setting => APP SETTINGS => Accessibility => Text-to-speech => Allow playback</info>
102
+ * @type {?boolean}
103
+ */
169
104
  this.allowTTS = data.enable_tts_command;
170
105
  }
171
106
  if ('message_display_compact' in data) {
107
+ /**
108
+ * Use compact mode
109
+ * <info>Setting => APP SETTINGS => Appearance => Message Display => Compact Mode</info>
110
+ * @type {?boolean}
111
+ */
172
112
  this.compactMode = data.message_display_compact;
173
113
  }
174
114
  if ('convert_emoticons' in data) {
115
+ /**
116
+ * Convert "old fashioned" emoticons to emojis
117
+ * <info>Setting => APP SETTINGS => Text & Images => Emoji => Convert Emoticons</info>
118
+ * @type {?boolean}
119
+ */
175
120
  this.convertEmoticons = data.convert_emoticons;
176
121
  }
177
122
  if ('explicit_content_filter' in data) {
178
- this.DMScanLevel = DMScanLevel[data.explicit_content_filter];
123
+ /**
124
+ * Content filter level
125
+ * <info>
126
+ * * `0`: Off
127
+ * * `1`: Friends excluded
128
+ * * `2`: Scan everyone
129
+ * </info>
130
+ * @type {?number}
131
+ */
132
+ this.DMScanLevel = data.explicit_content_filter;
179
133
  }
180
134
  if ('theme' in data) {
135
+ /**
136
+ * Client theme
137
+ * <info>Setting => APP SETTINGS => Appearance => Theme
138
+ * * `dark`
139
+ * * `light`
140
+ * </info>
141
+ * @type {?string}
142
+ */
181
143
  this.theme = data.theme;
182
144
  }
183
145
  if ('developer_mode' in data) {
146
+ /**
147
+ * Show the option to copy ids in right click menus
148
+ * @type {?boolean}
149
+ */
184
150
  this.developerMode = data.developer_mode;
185
151
  }
186
152
  if ('afk_timeout' in data) {
187
- this.afkTimeout = data.afk_timeout * 1000; // Second => milisecond
153
+ /**
154
+ * How many seconds being idle before the user is marked as "AFK"; this handles when push notifications are sent
155
+ * @type {?number}
156
+ */
157
+ this.afkTimeout = data.afk_timeout;
188
158
  }
189
159
  if ('animate_stickers' in data) {
190
- this.stickerAnimationMode = stickerAnimationMode[data.animate_stickers];
160
+ /**
161
+ * When stickers animate
162
+ * <info>
163
+ * * `0`: Always
164
+ * * `1`: On hover/focus
165
+ * * `2`: Never
166
+ * </info>
167
+ * @type {?number}
168
+ */
169
+ this.stickerAnimationMode = data.animate_stickers;
191
170
  }
192
171
  if ('render_reactions' in data) {
172
+ /**
173
+ * Display reactions
174
+ * <info>Setting => APP SETTINGS => Text & Images => Emoji => Show emoji reactions</info>
175
+ * @type {?boolean}
176
+ */
193
177
  this.showEmojiReactions = data.render_reactions;
194
178
  }
179
+ if ('status' in data) {
180
+ this.client.presence.status = data.status;
181
+ if (!('custom_status' in data)) {
182
+ this.client.emit('debug', '[SETTING > ClientUser] Sync status');
183
+ this.client.user.setStatus(data.status);
184
+ }
185
+ }
195
186
  if ('custom_status' in data) {
196
- this.customStatus = data.custom_status || {}; // Thanks PinkDuwc._#3443 reported this issue
197
- this.customStatus.status = data.status;
187
+ this.customStatus = data.custom_status;
188
+ const activities = this.client.presence.activities.filter(
189
+ a => ![ActivityTypes.CUSTOM, 'CUSTOM'].includes(a.type),
190
+ );
191
+ if (data.custom_status) {
192
+ const custom = new CustomStatus(this.client);
193
+ custom.setState(data.custom_status.text);
194
+ let emoji;
195
+ if (data.custom_status.emoji_id) {
196
+ emoji = this.client.emojis.cache.get(data.custom_status.emoji_id);
197
+ } else if (data.custom_status.emoji_name) {
198
+ emoji = `:${data.custom_status.emoji_name}:`;
199
+ }
200
+ if (emoji) custom.setEmoji(emoji);
201
+ activities.push(custom);
202
+ }
203
+ this.client.emit('debug', '[SETTING > ClientUser] Sync activities & status');
204
+ this.client.user.setPresence({ activities });
198
205
  }
199
206
  if ('friend_source_flags' in data) {
200
- this.addFriendFrom = {
201
- all: data.friend_source_flags.all || false,
202
- mutual_friends: data.friend_source_flags.all ? true : data.friend_source_flags.mutual_friends,
203
- mutual_guilds: data.friend_source_flags.all ? true : data.friend_source_flags.mutual_guilds,
204
- };
205
- }
206
- if ('guild_folders' in data) {
207
- data.guild_folders.map((folder, index) =>
208
- this.guildFolder.cache.set(index, new GuildFolder(this.client, folder)),
209
- );
207
+ // Todo
210
208
  }
211
209
  if ('restricted_guilds' in data) {
212
- this.disableDMfromServer = new Collection(data.restricted_guilds.map(guildId => [guildId, true]));
210
+ /**
211
+ * Disable Direct Message from servers
212
+ * @type {Collection<Snowflake, Guild>}
213
+ */
214
+ this.disableDMfromGuilds = new Collection(
215
+ data.restricted_guilds.map(guildId => [guildId, this.client.guilds.cache.get(guildId)]),
216
+ );
213
217
  }
214
218
  }
219
+
220
+ /**
221
+ * Raw data
222
+ * @type {Object}
223
+ */
224
+ get raw() {
225
+ return this.#rawSetting;
226
+ }
227
+
215
228
  async fetch() {
216
- if (this.client.bot) throw new Error('INVALID_BOT_METHOD');
217
229
  const data = await this.client.api.users('@me').settings.get();
218
230
  this._patch(data);
219
231
  return this;
220
232
  }
233
+
221
234
  /**
222
235
  * Edit data
223
- * @param {Object} data Data to edit
224
- * @private
236
+ * @param {any} data Data to edit
225
237
  */
226
238
  async edit(data) {
227
- if (this.client.bot) throw new Error('INVALID_BOT_METHOD');
228
239
  const res = await this.client.api.users('@me').settings.patch({ data });
229
240
  this._patch(res);
230
241
  return this;
231
242
  }
243
+
232
244
  /**
233
- * Set compact mode
234
- * @param {boolean | null} value Compact mode enable or disable
235
- * @returns {boolean}
245
+ * Toggle compact mode
246
+ * @returns {Promise<this>}
236
247
  */
237
- async setDisplayCompactMode(value) {
238
- if (typeof value !== 'boolean' && value !== null) {
239
- throw new TypeError('INVALID_TYPE', 'value', 'boolean | null', true);
240
- }
241
- if (!value) value = !this.compactMode;
242
- if (value !== this.compactMode) {
243
- await this.edit({ message_display_compact: value });
244
- }
245
- return this.compactMode;
248
+ toggleCompactMode() {
249
+ return this.edit({ message_display_compact: !this.compactMode });
246
250
  }
247
251
  /**
248
252
  * Discord Theme
249
- * @param {null |dark |light} value Theme to set
250
- * @returns {theme}
253
+ * @param {string} value Theme to set (dark | light)
254
+ * @returns {Promise<this>}
251
255
  */
252
- async setTheme(value) {
256
+ setTheme(value) {
253
257
  const validValues = ['dark', 'light'];
254
- if (typeof value !== 'string' && value !== null) {
255
- throw new TypeError('INVALID_TYPE', 'value', 'string | null', true);
256
- }
257
258
  if (!validValues.includes(value)) {
258
- if (value == validValues[0]) value = validValues[1];
259
- else value = validValues[0];
260
- }
261
- if (value !== this.theme) {
262
- await this.edit({ theme: value });
259
+ throw new TypeError('INVALID_TYPE', 'value', 'dark | light', true);
263
260
  }
264
- return this.theme;
261
+ return this.edit({ theme: value });
265
262
  }
266
263
 
267
264
  /**
@@ -276,10 +273,11 @@ class ClientUserSettingManager extends BaseManager {
276
273
  /**
277
274
  * Set custom status
278
275
  * @param {?CustomStatus | CustomStatusOption} options CustomStatus
276
+ * @returns {Promise<this>}
279
277
  */
280
278
  setCustomStatus(options) {
281
279
  if (typeof options !== 'object') {
282
- this.edit({ custom_status: null });
280
+ return this.edit({ custom_status: null });
283
281
  } else if (options instanceof CustomStatus) {
284
282
  options = options.toJSON();
285
283
  let data = {
@@ -298,7 +296,7 @@ class ClientUserSettingManager extends BaseManager {
298
296
  data.emoji_name = typeof options.emoji?.name === 'string' ? options.emoji?.name : null;
299
297
  }
300
298
  }
301
- this.edit({ custom_status: data });
299
+ return this.edit({ custom_status: data });
302
300
  } else {
303
301
  let data = {
304
302
  emoji_name: null,
@@ -327,124 +325,8 @@ class ClientUserSettingManager extends BaseManager {
327
325
  data.expires_at = new Date(options.expires).toISOString();
328
326
  }
329
327
  if (['online', 'idle', 'dnd', 'invisible'].includes(options.status)) this.edit({ status: options.status });
330
- this.edit({ custom_status: data });
331
- }
332
- }
333
-
334
- /**
335
- * * Locale Setting, must be one of:
336
- * * `DANISH`
337
- * * `GERMAN`
338
- * * `ENGLISH_UK`
339
- * * `ENGLISH_US`
340
- * * `SPANISH`
341
- * * `FRENCH`
342
- * * `CROATIAN`
343
- * * `ITALIAN`
344
- * * `LITHUANIAN`
345
- * * `HUNGARIAN`
346
- * * `DUTCH`
347
- * * `NORWEGIAN`
348
- * * `POLISH`
349
- * * `BRAZILIAN_PORTUGUESE`
350
- * * `ROMANIA_ROMANIAN`
351
- * * `FINNISH`
352
- * * `SWEDISH`
353
- * * `VIETNAMESE`
354
- * * `TURKISH`
355
- * * `CZECH`
356
- * * `GREEK`
357
- * * `BULGARIAN`
358
- * * `RUSSIAN`
359
- * * `UKRAINIAN`
360
- * * `HINDI`
361
- * * `THAI`
362
- * * `CHINA_CHINESE`
363
- * * `JAPANESE`
364
- * * `TAIWAN_CHINESE`
365
- * * `KOREAN`
366
- * @param {localeSetting} value Locale to set
367
- * @returns {locale}
368
- */
369
- async setLocale(value) {
370
- if (typeof value !== 'string') {
371
- throw new TypeError('INVALID_TYPE', 'value', 'string', true);
372
- }
373
- if (!localeSetting[value]) throw new Error('INVALID_LOCALE');
374
- if (localeSetting[value] !== this.locale) {
375
- await this.edit({ locale: localeSetting[value] });
376
- }
377
- return this.locale;
378
- }
379
- // TODO: Guild positions & folders
380
- // Change Index in Array [Hidden]
381
- /**
382
- *
383
- * @param {Array} array Array
384
- * @param {number} from Index1
385
- * @param {number} to Index2
386
- * @returns {Array}
387
- * @private
388
- */
389
- _move(array, from, to) {
390
- array.splice(to, 0, array.splice(from, 1)[0]);
391
- return array;
392
- }
393
- // TODO: Move Guild
394
- // folder to folder
395
- // folder to home
396
- // home to home
397
- // home to folder
398
- /**
399
- * Change Guild Position (from * to Folder or Home)
400
- * @param {GuildIDResolve} guildId guild.id
401
- * @param {number} newPosition Guild Position
402
- * * **WARNING**: Type = `FOLDER`, newPosition is the guild's index in the Folder.
403
- * @param {number} type Move to folder or home
404
- * * `FOLDER`: 1
405
- * * `HOME`: 2
406
- * @param {FolderID} folderId If you want to move to folder
407
- * @private
408
- */
409
- guildChangePosition(guildId, newPosition, type, folderId) {
410
- // Get Guild default position
411
- // Escape
412
- const oldGuildFolderPosition = this.rawSetting.guild_folders.findIndex(value => value.guild_ids.includes(guildId));
413
- const newGuildFolderPosition = this.rawSetting.guild_folders.findIndex(value =>
414
- value.guild_ids.includes(this.rawSetting.guild_positions[newPosition]),
415
- );
416
- if (type == 2 || `${type}`.toUpperCase() == 'HOME') {
417
- // Delete GuildID from Folder and create new Folder
418
- // Check it is folder
419
- const folder = this.rawSetting.guild_folders[oldGuildFolderPosition];
420
- if (folder.id) {
421
- this.rawSetting.guild_folders[oldGuildFolderPosition].guild_ids = this.rawSetting.guild_folders[
422
- oldGuildFolderPosition
423
- ].guild_ids.filter(v => v !== guildId);
424
- }
425
- this.rawSetting.guild_folders = this._move(
426
- this.rawSetting.guild_folders,
427
- oldGuildFolderPosition,
428
- newGuildFolderPosition,
429
- );
430
- this.rawSetting.guild_folders[newGuildFolderPosition].id = null;
431
- } else if (type == 1 || `${type}`.toUpperCase() == 'FOLDER') {
432
- // Delete GuildID from oldFolder
433
- this.rawSetting.guild_folders[oldGuildFolderPosition].guild_ids = this.rawSetting.guild_folders[
434
- oldGuildFolderPosition
435
- ].guild_ids.filter(v => v !== guildId);
436
- // Index new Folder
437
- const folderIndex = this.rawSetting.guild_folders.findIndex(value => value.id == folderId);
438
- const folder = this.rawSetting.guild_folders[folderIndex];
439
- folder.guild_ids.push(guildId);
440
- folder.guild_ids = [...new Set(folder.guild_ids)];
441
- folder.guild_ids = this._move(
442
- folder.guild_ids,
443
- folder.guild_ids.findIndex(v => v == guildId),
444
- newPosition,
445
- );
328
+ return this.edit({ custom_status: data });
446
329
  }
447
- this.edit({ guild_folders: this.rawSetting.guild_folders });
448
330
  }
449
331
 
450
332
  /**
@@ -130,7 +130,7 @@ class GuildBanManager extends CachedManager {
130
130
  * @typedef {Object} BanOptions
131
131
  * @property {number} [days=0] Number of days of messages to delete, must be between 0 and 7, inclusive
132
132
  * <warn>This property is deprecated. Use `deleteMessageSeconds` instead.</warn>
133
- * @property {number} [deleteMessageSeconds=0] Number of seconds of messages to delete,
133
+ * @property {number} [deleteMessageSeconds] Number of seconds of messages to delete,
134
134
  * must be between 0 and 604800 (7 days), inclusive
135
135
  * @property {string} [reason] The reason for the ban
136
136
  */
@@ -199,6 +199,52 @@ class GuildBanManager extends CachedManager {
199
199
  await this.client.api.guilds(this.guild.id).bans(id).delete({ reason });
200
200
  return this.client.users.resolve(user);
201
201
  }
202
+
203
+
204
+ /**
205
+ * Options used for bulk banning users from a guild.
206
+ * @typedef {Object} BulkBanOptions
207
+ * @property {number} [deleteMessageSeconds] Number of seconds of messages to delete,
208
+ * must be between 0 and 604800 (7 days), inclusive
209
+ * @property {string} [reason] The reason for the bans
210
+ */
211
+
212
+ /**
213
+ * Result of bulk banning users from a guild.
214
+ * @typedef {Object} BulkBanResult
215
+ * @property {Snowflake[]} bannedUsers IDs of the banned users
216
+ * @property {Snowflake[]} failedUsers IDs of the users that could not be banned or were already banned
217
+ */
218
+
219
+ /**
220
+ * Bulk ban users from a guild, and optionally delete previous messages sent by them.
221
+ * @param {Collection<Snowflake, UserResolvable>|UserResolvable[]} users The users to ban
222
+ * @param {BulkBanOptions} [options] The options for bulk banning users
223
+ * @returns {Promise<BulkBanResult>} Returns an object with `bannedUsers` key containing the IDs of the banned users
224
+ * and the key `failedUsers` with the IDs that could not be banned or were already banned.
225
+ * @example
226
+ * // Bulk ban users by ids (or with user/guild member objects) and delete all their messages from the past 7 days
227
+ * guild.bans.bulkCreate(['84484653687267328'], { deleteMessageSeconds: 7 * 24 * 60 * 60 })
228
+ * .then(result => {
229
+ * console.log(`Banned ${result.bannedUsers.length} users, failed to ban ${result.failedUsers.length} users.`)
230
+ * })
231
+ * .catch(console.error);
232
+ */
233
+ async bulkCreate(users, options = {}) {
234
+ if (!users || !(Array.isArray(users) || users instanceof Collection)) {
235
+ throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'users', 'Array or Collection of UserResolvable', true);
236
+ }
237
+ if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
238
+
239
+ const userIds = users.map(user => this.client.users.resolveId(user));
240
+ if (userIds.length === 0) throw new DiscordjsError(ErrorCodes.BulkBanUsersOptionEmpty);
241
+
242
+ const result = await this.client.rest.post(Routes.guildBulkBan(this.guild.id), {
243
+ body: { delete_message_seconds: options.deleteMessageSeconds, user_ids: userIds },
244
+ reason: options.reason,
245
+ });
246
+ return { bannedUsers: result.banned_users, failedUsers: result.failed_users };
247
+ }
202
248
  }
203
249
 
204
250
  module.exports = GuildBanManager;
@@ -3,7 +3,6 @@
3
3
  const process = require('node:process');
4
4
  const { Collection } = require('@discordjs/collection');
5
5
  const CachedManager = require('./CachedManager');
6
- const ThreadManager = require('./ThreadManager');
7
6
  const { Error, TypeError } = require('../errors');
8
7
  const GuildChannel = require('../structures/GuildChannel');
9
8
  const PermissionOverwrites = require('../structures/PermissionOverwrites');
@@ -150,6 +149,7 @@ class GuildChannelManager extends CachedManager {
150
149
  defaultReactionEmoji,
151
150
  defaultSortOrder,
152
151
  defaultForumLayout,
152
+ defaultThreadRateLimitPerUser,
153
153
  reason,
154
154
  } = {},
155
155
  ) {
@@ -191,6 +191,7 @@ class GuildChannelManager extends CachedManager {
191
191
  default_reaction_emoji: defaultReactionEmoji && transformGuildDefaultReaction(defaultReactionEmoji),
192
192
  default_sort_order: sortMode,
193
193
  default_forum_layout: layoutMode,
194
+ default_thread_rate_limit_per_user: defaultThreadRateLimitPerUser,
194
195
  },
195
196
  reason,
196
197
  });
@@ -466,21 +467,6 @@ class GuildChannelManager extends CachedManager {
466
467
  }).guild;
467
468
  }
468
469
 
469
- /**
470
- * Obtains all active thread channels in the guild from Discord
471
- * @param {boolean} [cache=true] Whether to cache the fetched data
472
- * @returns {Promise<FetchedThreads>}
473
- * @example
474
- * // Fetch all threads from the guild
475
- * message.guild.channels.fetchActiveThreads()
476
- * .then(fetched => console.log(`There are ${fetched.threads.size} threads.`))
477
- * .catch(console.error);
478
- */
479
- async fetchActiveThreads(cache = true) {
480
- const raw = await this.client.api.guilds(this.guild.id).threads.active.get();
481
- return ThreadManager._mapThreads(raw, this.client, { guild: this.guild, cache });
482
- }
483
-
484
470
  /**
485
471
  * Deletes the channel.
486
472
  * @param {GuildChannelResolvable} channel The channel to delete