djs-selfbot-v13 3.1.8 → 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 (43) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +18 -8
  3. package/package.json +85 -71
  4. package/src/client/BaseClient.js +1 -1
  5. package/src/client/Client.js +81 -10
  6. package/src/client/actions/GuildMemberRemove.js +0 -1
  7. package/src/client/actions/GuildMemberUpdate.js +0 -1
  8. package/src/client/websocket/WebSocketShard.js +3 -3
  9. package/src/client/websocket/handlers/GUILD_CREATE.js +13 -14
  10. package/src/client/websocket/handlers/GUILD_MEMBER_ADD.js +0 -1
  11. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_ADD.js +22 -0
  12. package/src/client/websocket/handlers/MESSAGE_POLL_VOTE_REMOVE.js +12 -0
  13. package/src/client/websocket/handlers/READY.js +61 -21
  14. package/src/client/websocket/handlers/RELATIONSHIP_REMOVE.js +1 -1
  15. package/src/client/websocket/handlers/RELATIONSHIP_UPDATE.js +1 -1
  16. package/src/client/websocket/handlers/index.js +2 -0
  17. package/src/errors/Messages.js +1 -0
  18. package/src/index.js +4 -3
  19. package/src/managers/ChannelManager.js +1 -1
  20. package/src/managers/ClientUserSettingManager.js +2 -2
  21. package/src/managers/GuildBanManager.js +46 -0
  22. package/src/managers/GuildChannelManager.js +0 -16
  23. package/src/managers/GuildForumThreadManager.js +3 -3
  24. package/src/managers/GuildManager.js +1 -1
  25. package/src/managers/GuildMemberManager.js +11 -7
  26. package/src/managers/RelationshipManager.js +3 -3
  27. package/src/rest/APIRequest.js +13 -7
  28. package/src/structures/ClientPresence.js +9 -12
  29. package/src/structures/ClientUser.js +0 -2
  30. package/src/structures/Message.js +67 -76
  31. package/src/structures/MessagePayload.js +2 -0
  32. package/src/structures/MessagePoll.js +238 -0
  33. package/src/structures/Modal.js +11 -24
  34. package/src/structures/Presence.js +786 -128
  35. package/src/structures/User.js +35 -1
  36. package/src/structures/interfaces/TextBasedChannel.js +21 -23
  37. package/src/util/Constants.js +17 -4
  38. package/src/util/Options.js +1 -7
  39. package/src/util/Permissions.js +10 -0
  40. package/src/util/Util.js +88 -2
  41. package/typings/enums.d.ts +7 -1
  42. package/typings/index.d.ts +112 -70
  43. package/src/structures/RichPresence.js +0 -702
@@ -151,6 +151,30 @@ class User extends Base {
151
151
  this.avatarDecoration ??= null;
152
152
  this.avatarDecorationSKUId ??= null;
153
153
  }
154
+
155
+ if ('clan' in data && data.clan) {
156
+ /**
157
+ * User Clan Structure
158
+ * @see {@link https://docs.discord.sex/resources/user#user-clan-structure}
159
+ * @typedef {Object} UserClan
160
+ * @property {?Snowflake} identityGuildId The ID of the user's primary clan
161
+ * @property {boolean} identityEnabled Whether the user is displaying their clan tag
162
+ * @property {?string} tag The text of the user's clan tag (max 4 characters)
163
+ * @property {?string} badge The clan's badge hash
164
+ */
165
+ /**
166
+ * The primary clan the user is in
167
+ * @type {?UserClan}
168
+ */
169
+ this.clan = {
170
+ identityGuildId: data.clan.identity_guild_id,
171
+ identityEnabled: data.clan.identity_enabled,
172
+ tag: data.clan.tag,
173
+ badge: data.clan.badge,
174
+ };
175
+ } else {
176
+ this.clan ??= null;
177
+ }
154
178
  }
155
179
 
156
180
  /**
@@ -200,6 +224,15 @@ class User extends Base {
200
224
  return this.client.rest.cdn.AvatarDecoration(this.id, this.avatarDecoration, format, size);
201
225
  }
202
226
 
227
+ /**
228
+ * A link to the user's clan badge.
229
+ * @returns {?string}
230
+ */
231
+ clanBadgeURL() {
232
+ if (!this.clan || !this.clan.identityGuildId || !this.clan.badge) return null;
233
+ return this.client.rest.cdn.ClanBadge(this.clan.identityGuildId, this.clan.badge);
234
+ }
235
+
203
236
  /**
204
237
  * A link to the user's default avatar
205
238
  * @type {string}
@@ -369,6 +402,7 @@ class User extends Base {
369
402
  return this.client.api.users(this.id).profile.get({
370
403
  query: {
371
404
  with_mutual_guilds: true,
405
+ with_mutual_friends: true,
372
406
  with_mutual_friends_count: true,
373
407
  guild_id: guildId,
374
408
  },
@@ -467,7 +501,7 @@ class User extends Base {
467
501
 
468
502
  /**
469
503
  * Check relationship status (Client -> User)
470
- * @type {RelationshipTypes}
504
+ * @type {RelationshipType}
471
505
  * @readonly
472
506
  */
473
507
  get relationship() {
@@ -75,6 +75,7 @@ class TextBasedChannel {
75
75
  * @property {Array<(MessageActionRow|MessageActionRowOptions)>} [components]
76
76
  * Action rows containing interactive components for the message (buttons, select menus)
77
77
  * @property {MessageAttachment[]} [attachments] Attachments to send in the message
78
+ * @property {MessagePoll} [poll] A poll!
78
79
  */
79
80
 
80
81
  /**
@@ -186,7 +187,7 @@ class TextBasedChannel {
186
187
  return this.messages.cache.get(d.id) ?? this.messages._add(d);
187
188
  }
188
189
 
189
- searchInteraction() {
190
+ searchInteractionFromGuildAndPrivateChannel() {
190
191
  // Support Slash / ContextMenu
191
192
  // API https://canary.discord.com/api/v9/guilds/:id/application-command-index // Guild
192
193
  // https://canary.discord.com/api/v9/channels/:id/application-command-index // DM Channel
@@ -196,6 +197,19 @@ class TextBasedChannel {
196
197
  ].get();
197
198
  }
198
199
 
200
+ searchInteractionUserApps() {
201
+ return this.client.api.users['@me']['application-command-index'].get();
202
+ }
203
+
204
+ searchInteraction() {
205
+ return Promise.all([this.searchInteractionFromGuildAndPrivateChannel(), this.searchInteractionUserApps()]).then(
206
+ ([dataA, dataB]) => ({
207
+ applications: [...dataA.applications, ...dataB.applications],
208
+ application_commands: [...dataA.application_commands, ...dataB.application_commands],
209
+ }),
210
+ );
211
+ }
212
+
199
213
  async sendSlash(botOrApplicationId, commandNameString, ...args) {
200
214
  // Parse commandName /role add user
201
215
  const cmd = commandNameString.trim().split(' ');
@@ -225,7 +239,9 @@ class TextBasedChannel {
225
239
  );
226
240
  // Find Command with application
227
241
  const command = filterCommand.find(command => command.application_id == application.id);
228
-
242
+ if (!command) {
243
+ throw new Error('INVALID_APPLICATION_COMMAND', application.id);
244
+ }
229
245
  args = args.flat(2);
230
246
  let optionFormat = [];
231
247
  let attachments = [];
@@ -326,27 +342,7 @@ class TextBasedChannel {
326
342
  data: body,
327
343
  usePayloadJSON: true,
328
344
  });
329
- return new Promise((resolve, reject) => {
330
- const timeoutMs = 5_000;
331
- // Waiting for MsgCreate / ModalCreate
332
- const handler = data => {
333
- if (data.nonce !== nonce) return;
334
- clearTimeout(timeout);
335
- this.client.removeListener(Events.MESSAGE_CREATE, handler);
336
- this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
337
- this.client.decrementMaxListeners();
338
- resolve(data);
339
- };
340
- const timeout = setTimeout(() => {
341
- this.client.removeListener(Events.MESSAGE_CREATE, handler);
342
- this.client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
343
- this.client.decrementMaxListeners();
344
- reject(new Error('INTERACTION_FAILED'));
345
- }, timeoutMs).unref();
346
- this.client.incrementMaxListeners();
347
- this.client.on(Events.MESSAGE_CREATE, handler);
348
- this.client.on(Events.INTERACTION_MODAL_CREATE, handler);
349
- });
345
+ return Util.createPromiseInteraction(this.client, nonce, 5000);
350
346
  }
351
347
 
352
348
  /**
@@ -471,6 +467,8 @@ class TextBasedChannel {
471
467
  props.push(
472
468
  'sendSlash',
473
469
  'searchInteraction',
470
+ 'searchInteractionFromGuildAndPrivateChannel',
471
+ 'searchInteractionUserApps',
474
472
  'lastMessage',
475
473
  'lastPinAt',
476
474
  'sendTyping',
@@ -9,7 +9,7 @@ const { Error, RangeError, TypeError } = require('../errors');
9
9
  exports.MaxBulkDeletableMessageAge = 1_209_600_000;
10
10
 
11
11
  exports.UserAgent =
12
- 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 Electron/22.3.26 Safari/537.36';
12
+ 'Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.5359.215 Safari/537.36';
13
13
 
14
14
  /**
15
15
  * Google Chrome v108 TLS ciphers
@@ -98,6 +98,7 @@ exports.Endpoints = {
98
98
  },
99
99
  AvatarDecoration: (userId, hash, format = 'png', size) =>
100
100
  makeImageUrl(`${root}/avatar-decorations/${userId}/${hash}`, { format, size }),
101
+ ClanBadge: (guildId, hash) => `${root}/clan-badges/${guildId}/${hash}.png`,
101
102
  GuildMemberAvatar: (guildId, memberId, hash, format = 'webp', size, dynamic = false) => {
102
103
  if (dynamic && hash.startsWith('a_')) format = 'gif';
103
104
  return makeImageUrl(`${root}/guilds/${guildId}/users/${memberId}/avatars/${hash}`, { format, size });
@@ -430,6 +431,8 @@ exports.Events = {
430
431
  CALL_CREATE: 'callCreate',
431
432
  CALL_UPDATE: 'callUpdate',
432
433
  CALL_DELETE: 'callDelete',
434
+ MESSAGE_POLL_VOTE_ADD: 'messagePollVoteAdd',
435
+ MESSAGE_POLL_VOTE_REMOVE: 'messagePollVoteRemove',
433
436
  };
434
437
 
435
438
  /**
@@ -755,10 +758,11 @@ exports.SystemMessageTypes = exports.MessageTypes.filter(
755
758
  * * WATCHING
756
759
  * * CUSTOM
757
760
  * * COMPETING
761
+ * * HANG
758
762
  * @typedef {string} ActivityType
759
763
  * @see {@link https://discord.com/developers/docs/game-sdk/activities#data-models-activitytype-enum}
760
764
  */
761
- exports.ActivityTypes = createEnum(['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM', 'COMPETING']);
765
+ exports.ActivityTypes = createEnum(['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM', 'COMPETING', 'HANG']);
762
766
 
763
767
  /**
764
768
  * All available channel types:
@@ -1648,6 +1652,15 @@ exports.SortOrderTypes = createEnum([null, 'LATEST_ACTIVITY', 'CREATION_DATE']);
1648
1652
  */
1649
1653
  exports.ForumLayoutTypes = createEnum(['NOT_SET', 'LIST_VIEW', 'GALLERY_VIEW']);
1650
1654
 
1655
+ /**
1656
+ * Different layouts for {@link MessagePoll} will come in the future. For now though, this value will always be `DEFAULT`.
1657
+ * * DEFAULT
1658
+ * * IMAGE_ONLY_ANSWERS
1659
+ * @typedef {string} MessagePollLayoutType
1660
+ * @see {@link https://docs.discord.sex/resources/message#poll-layout-type}
1661
+ */
1662
+ exports.MessagePollLayoutTypes = createEnum([null, 'DEFAULT', 'IMAGE_ONLY_ANSWERS']);
1663
+
1651
1664
  /**
1652
1665
  * Relationship Enums:
1653
1666
  * * 0: NONE
@@ -1656,7 +1669,7 @@ exports.ForumLayoutTypes = createEnum(['NOT_SET', 'LIST_VIEW', 'GALLERY_VIEW']);
1656
1669
  * * 3: PENDING_INCOMING
1657
1670
  * * 4: PENDING_OUTGOING
1658
1671
  * * 5: IMPLICIT
1659
- * @typedef {string} RelationshipTypes
1672
+ * @typedef {string} RelationshipType
1660
1673
  * @see {@link https://luna.gitlab.io/discord-unofficial-docs/relationships.html}
1661
1674
  */
1662
1675
 
@@ -1727,7 +1740,7 @@ function createEnum(keys) {
1727
1740
  * @property {Object<InteractionResponseType, number>} InteractionResponseTypes The type of an interaction response.
1728
1741
  * @property {Object<InteractionType, number>} InteractionTypes The type of an {@link Interaction} object.
1729
1742
  * @property {InviteScope[]} InviteScopes The scopes of an invite.
1730
- * @property {Object<RelationshipTypes, number>} RelationshipTypes Relationship Enums
1743
+ * @property {Object<RelationshipType, number>} RelationshipTypes Relationship Enums
1731
1744
  * @property {Object<MembershipState, number>} MembershipStates The value set for a team members membership state.
1732
1745
  * @property {Object<MessageButtonStyle, number>} MessageButtonStyles The style of a message button.
1733
1746
  * @property {Object<MessageComponentType, number>} MessageComponentTypes The type of a message component.
@@ -188,18 +188,12 @@ class Options extends null {
188
188
  referrer_current: '',
189
189
  referring_domain_current: '',
190
190
  release_channel: 'stable',
191
- client_build_number: 261141,
191
+ client_build_number: 306208,
192
192
  client_event_source: null,
193
193
  },
194
194
  compress: false,
195
195
  client_state: {
196
196
  guild_versions: {},
197
- highest_last_message_id: '0',
198
- read_state_version: 0,
199
- user_guild_settings_version: -1,
200
- user_settings_version: -1,
201
- private_channels_version: '0',
202
- api_code_version: 0,
203
197
  },
204
198
  version: 9,
205
199
  agent: {},
@@ -110,9 +110,14 @@ class Permissions extends BitField {
110
110
  * * `MODERATE_MEMBERS`
111
111
  * * `VIEW_CREATOR_MONETIZATION_ANALYTICS`
112
112
  * * `USE_SOUNDBOARD`
113
+ * * `CREATE_GUILD_EXPRESSIONS`
114
+ * * `CREATE_EVENTS`
115
+ * * `USE_EXTERNAL_SOUNDS`
113
116
  * * `SEND_VOICE_MESSAGES`
114
117
  * * `USE_CLYDE_AI`
115
118
  * * `SET_VOICE_CHANNEL_STATUS`
119
+ * * `SEND_POLLS`
120
+ * * `USE_EXTERNAL_APPS`
116
121
  * @type {Object<string, bigint>}
117
122
  * @see {@link https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags}
118
123
  */
@@ -163,9 +168,14 @@ Permissions.FLAGS = {
163
168
  MODERATE_MEMBERS: 1n << 40n,
164
169
  VIEW_CREATOR_MONETIZATION_ANALYTICS: 1n << 41n,
165
170
  USE_SOUNDBOARD: 1n << 42n,
171
+ CREATE_GUILD_EXPRESSIONS: 1n << 43n,
172
+ CREATE_EVENTS: 1n << 44n,
173
+ USE_EXTERNAL_SOUNDS: 1n << 45n,
166
174
  SEND_VOICE_MESSAGES: 1n << 46n,
167
175
  USE_CLYDE_AI: 1n << 47n,
168
176
  SET_VOICE_CHANNEL_STATUS: 1n << 48n,
177
+ SEND_POLLS: 1n << 49n,
178
+ USE_EXTERNAL_APPS: 1n << 50n,
169
179
  };
170
180
 
171
181
  /**
package/src/util/Util.js CHANGED
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
+ const { Agent } = require('node:http');
3
4
  const { parse } = require('node:path');
4
5
  const process = require('node:process');
6
+ const { setTimeout } = require('node:timers');
5
7
  const { Collection } = require('@discordjs/collection');
6
8
  const fetch = require('node-fetch');
7
- const { Colors } = require('./Constants');
9
+ const { Colors, Events } = require('./Constants');
8
10
  const { Error: DiscordError, RangeError, TypeError } = require('../errors');
9
11
  const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
10
12
  const isObject = d => typeof d === 'object' && d !== null;
@@ -604,7 +606,7 @@ class Util extends null {
604
606
  return user ? Util._removeMentions(`@${user.username}`) : input;
605
607
  }
606
608
 
607
- const member = channel.guild.members.cache.get(id);
609
+ const member = channel.guild?.members.cache.get(id);
608
610
  if (member) {
609
611
  return Util._removeMentions(`@${member.displayName}`);
610
612
  } else {
@@ -795,6 +797,90 @@ class Util extends null {
795
797
  .catch(reject);
796
798
  });
797
799
  }
800
+
801
+ /**
802
+ * Lazily evaluates a callback function (yea it's v14 :yay:)
803
+ * @param {Function} cb The callback to lazily evaluate
804
+ * @returns {Function}
805
+ * @example
806
+ * const User = lazy(() => require('./User'));
807
+ * const user = new (User())(client, data);
808
+ */
809
+ static lazy(cb) {
810
+ let defaultValue;
811
+ return () => (defaultValue ??= cb());
812
+ }
813
+
814
+ /**
815
+ * Hacking check object instanceof Proxy-agent
816
+ * @param {Object} object any
817
+ * @returns {boolean}
818
+ */
819
+ static verifyProxyAgent(object) {
820
+ return typeof object == 'object' && object.httpAgent instanceof Agent && object.httpsAgent instanceof Agent;
821
+ }
822
+
823
+ static createPromiseInteraction(client, nonce, timeoutMs = 5_000, isHandlerDeferUpdate = false, parent) {
824
+ return new Promise((resolve, reject) => {
825
+ // Waiting for MsgCreate / ModalCreate
826
+ let dataFromInteractionSuccess;
827
+ let dataFromNormal;
828
+ const handler = data => {
829
+ // UnhandledPacket
830
+ if (isHandlerDeferUpdate && data.d?.nonce == nonce && data.t == 'INTERACTION_SUCCESS') {
831
+ // Interaction#deferUpdate
832
+ client.removeListener(Events.MESSAGE_CREATE, handler);
833
+ client.removeListener(Events.UNHANDLED_PACKET, handler);
834
+ client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
835
+ dataFromInteractionSuccess = parent;
836
+ }
837
+ if (data.nonce !== nonce) return;
838
+ clearTimeout(timeout);
839
+ client.removeListener(Events.MESSAGE_CREATE, handler);
840
+ client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
841
+ if (isHandlerDeferUpdate) client.removeListener(Events.UNHANDLED_PACKET, handler);
842
+ client.decrementMaxListeners();
843
+ dataFromNormal = data;
844
+ resolve(data);
845
+ };
846
+ const timeout = setTimeout(() => {
847
+ if (dataFromInteractionSuccess || dataFromNormal) {
848
+ resolve(dataFromNormal || dataFromInteractionSuccess);
849
+ return;
850
+ }
851
+ client.removeListener(Events.MESSAGE_CREATE, handler);
852
+ client.removeListener(Events.INTERACTION_MODAL_CREATE, handler);
853
+ if (isHandlerDeferUpdate) client.removeListener(Events.UNHANDLED_PACKET, handler);
854
+ client.decrementMaxListeners();
855
+ reject(new Error('INTERACTION_FAILED'));
856
+ }, timeoutMs).unref();
857
+ client.incrementMaxListeners();
858
+ client.on(Events.MESSAGE_CREATE, handler);
859
+ client.on(Events.INTERACTION_MODAL_CREATE, handler);
860
+ if (isHandlerDeferUpdate) client.on(Events.UNHANDLED_PACKET, handler);
861
+ });
862
+ }
863
+
864
+ static clearNullOrUndefinedObject(object) {
865
+ const data = {};
866
+ const keys = Object.keys(object);
867
+
868
+ for (const key of keys) {
869
+ const value = object[key];
870
+ if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) {
871
+ continue;
872
+ } else if (!Array.isArray(value) && typeof value === 'object') {
873
+ const cleanedValue = Util.clearNullOrUndefinedObject(value);
874
+ if (cleanedValue !== undefined) {
875
+ data[key] = cleanedValue;
876
+ }
877
+ } else {
878
+ data[key] = value;
879
+ }
880
+ }
881
+
882
+ return Object.keys(data).length > 0 ? data : undefined;
883
+ }
798
884
  }
799
885
 
800
886
  module.exports = Util;
@@ -8,6 +8,7 @@ export const enum ActivityTypes {
8
8
  WATCHING = 3,
9
9
  CUSTOM = 4,
10
10
  COMPETING = 5,
11
+ HANG = 6,
11
12
  }
12
13
 
13
14
  export const enum ApplicationCommandTypes {
@@ -86,6 +87,11 @@ export const enum ForumLayoutType {
86
87
  GALLERY_VIEW = 2,
87
88
  }
88
89
 
90
+ export const enum MessagePollLayoutType {
91
+ DEFAULT = 1,
92
+ IMAGE_ONLY_ANSWERS,
93
+ }
94
+
89
95
  export const enum MessageTypes {
90
96
  DEFAULT,
91
97
  RECIPIENT_ADD,
@@ -281,7 +287,7 @@ export enum ApplicationRoleConnectionMetadataTypes {
281
287
  BOOLEAN_NOT_EQUAL,
282
288
  }
283
289
 
284
- export const enum RelationshipTypes {
290
+ export const enum RelationshipType {
285
291
  NONE = 0,
286
292
  FRIEND = 1,
287
293
  BLOCKED = 2,