djs-selfbot-v13 3.7.4 → 3.7.6

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.
package/README.md CHANGED
@@ -29,6 +29,7 @@
29
29
  ### Guild Management
30
30
  - `guild.mute(options?)` - Mute a guild completely (suppress all notifications)
31
31
  - `guild.unmute()` - Unmute a guild (restore all notifications)
32
+ - `guild.markRead(readStates?)` - Mark all channels in a guild as read
32
33
 
33
34
  ### Developer Applications
34
35
  - `client.developers.get(withTeamApplications?)` - Fetch all developer applications owned by the user
@@ -79,6 +80,19 @@
79
80
  - `client.quests.getClaimable()` - Get claimable quests
80
81
  - `client.quests.filterQuestsValid()` - Filter valid quests
81
82
 
83
+ ### Message Search
84
+ - `channel.search(options?)` - Search for messages in a channel with advanced filters
85
+ - `authorId` - Search by specific author
86
+ - `mentions` - Search for messages mentioning a user
87
+ - `has` - Search for messages containing: `image`, `video`, `link`, `embed`, `sound`, `poll`, `sticker`, `snapshot`
88
+ - `pinned` - Search only pinned messages
89
+ - `sortBy` - Sort by `timestamp` or `relevance`
90
+ - `sortOrder` - Sort order `desc` or `asc`
91
+ - `offset` - Pagination offset
92
+ - `limit` - Limit number of results
93
+ - `maxTime` - Search for messages before a specific date/time
94
+
95
+
82
96
  </details>
83
97
 
84
98
  > [!WARNING]
@@ -123,6 +137,50 @@ client.on('ready', async () => {
123
137
  client.login('token');
124
138
  ```
125
139
 
140
+ ### Advanced Examples
141
+
142
+ #### Message Search
143
+ ```js
144
+ // Search for messages with images in a channel
145
+ const results = await channel.search({ has: ['image'] });
146
+
147
+ // Search for messages by a specific author
148
+ const userMessages = await channel.search({
149
+ authorId: '123456789012345678',
150
+ limit: 10
151
+ });
152
+
153
+ // Search for pinned messages
154
+ const pinnedMessages = await channel.search({ pinned: true });
155
+
156
+ // Search for messages before a specific date
157
+ const oldMessages = await channel.search({
158
+ maxTime: '2023-12-01',
159
+ limit: 50
160
+ });
161
+
162
+ // Search for messages with multiple filters
163
+ const complexSearch = await channel.search({
164
+ has: ['link', 'embed'],
165
+ sortBy: 'timestamp',
166
+ sortOrder: 'desc',
167
+ offset: 20,
168
+ maxTime: new Date('2023-12-31')
169
+ });
170
+ ```
171
+
172
+ #### Guild Read State Management
173
+ ```js
174
+ // Mark all channels in a guild as read
175
+ await guild.markRead();
176
+
177
+ // Mark specific channels as read
178
+ await guild.markRead([
179
+ { channel_id: '123456789012345678', message_id: '987654321098765432' },
180
+ { channel_id: '876543210987654321', message_id: '123456789012345678' }
181
+ ]);
182
+ ```
183
+
126
184
  ## Get Token ?
127
185
 
128
186
  - Based: [findByProps](https://discord.com/channels/603970300668805120/1085682686607249478/1085682686607249478)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "djs-selfbot-v13",
3
- "version": "3.7.4",
3
+ "version": "3.7.6",
4
4
  "description": "An unofficial discord.js fork for creating selfbots",
5
5
  "main": "./src/index.js",
6
6
  "types": "./typings/index.d.ts",
@@ -250,12 +250,9 @@ class QuestManager extends BaseManager {
250
250
  async doingQuest(quest) {
251
251
  const questName = quest.config.messages?.quest_name || 'Unknown Quest';
252
252
 
253
- if (!quest.isEnrolledQuest()) {
254
- console.log(`Enrolling in quest "${questName}"...`);
253
+ if (!quest.isEnrolledQuest())
255
254
  await this.acceptQuest(quest.id);
256
- }
257
255
 
258
- const applicationName = quest.config.application?.name || 'Unknown App';
259
256
  const taskConfig = quest.config.task_config;
260
257
 
261
258
  const taskName = [
@@ -266,10 +263,9 @@ class QuestManager extends BaseManager {
266
263
  'WATCH_VIDEO_ON_MOBILE'
267
264
  ].find(x => taskConfig.tasks?.[x] != null);
268
265
 
269
- if (!taskName) {
270
- console.log(`Unknown task type for quest "${questName}"`);
271
- return;
272
- }
266
+ if (!taskName)
267
+ return console.log(`Unknown task type for quest "${questName}"`);
268
+
273
269
 
274
270
  const secondsNeeded = taskConfig.tasks[taskName].target;
275
271
  let secondsDone = quest.userStatus?.progress?.[taskName]?.value ?? 0;
@@ -281,8 +277,6 @@ class QuestManager extends BaseManager {
281
277
  const enrolledAt = new Date(quest.userStatus?.enrolled_at).getTime();
282
278
  let completed = false;
283
279
 
284
- console.log(`Spoofing video for ${questName}.`);
285
-
286
280
  while (true) {
287
281
  const maxAllowed = Math.floor((Date.now() - enrolledAt) / 1000) + maxFuture;
288
282
  const diff = maxAllowed - secondsDone;
@@ -305,8 +299,6 @@ class QuestManager extends BaseManager {
305
299
  await this.videoProgress(quest.id, secondsNeeded);
306
300
  }
307
301
 
308
- console.log(`Quest "${questName}" completed!`);
309
-
310
302
  } else if (taskName === 'PLAY_ON_DESKTOP') {
311
303
  const interval = 60;
312
304
 
@@ -315,20 +307,11 @@ class QuestManager extends BaseManager {
315
307
  const res = await this.heartbeat(quest.id, quest.config.application.id, false);
316
308
  quest.updateUserStatus(res);
317
309
 
318
- console.log(`Spoofed your game to ${applicationName}. Wait for ${Math.ceil((secondsNeeded - secondsDone) / 60)} more minutes.`);
319
310
  await this.timeout(interval * 1000);
320
311
  }
321
312
 
322
313
  const res = await this.heartbeat(quest.id, quest.config.application.id, true);
323
314
  quest.updateUserStatus(res);
324
- console.log(`Quest "${questName}" completed!`);
325
-
326
- } else if (taskName === 'STREAM_ON_DESKTOP') {
327
- console.log('This no longer works in node for non-video quests. Use the discord desktop app to complete the', questName, 'quest!');
328
- } else if (taskName === 'PLAY_ACTIVITY') {
329
- console.log('This quest not supported. Use the discord desktop app to complete the', questName, 'quest!');
330
- } else {
331
- console.log('Unknown quest type. Use the discord desktop app to complete the', questName, 'quest!');
332
315
  }
333
316
  }
334
317
 
@@ -1659,6 +1659,37 @@ class Guild extends AnonymousGuild {
1659
1659
  return data;
1660
1660
  }
1661
1661
 
1662
+ /**
1663
+ * Mark all channels in this guild as read
1664
+ * @param {MarkReadOptions[]} [readStates] Array of read states to mark as read
1665
+ * @returns {Promise<Object>} The response from Discord
1666
+ * @example
1667
+ * // Mark all channels as read
1668
+ * guild.markRead();
1669
+ *
1670
+ * // Mark specific channels as read
1671
+ * guild.markRead([
1672
+ * { channel_id: '123456789012345678', message_id: '987654321098765432' }
1673
+ * ]);
1674
+ */
1675
+ async markRead(readStates = []) {
1676
+ // If no readStates provided, get all channels in guild
1677
+ if (readStates.length === 0) {
1678
+ const channels = this.channels.cache.filter(c => c.isTextBased());
1679
+ readStates = channels.map(channel => ({
1680
+ channel_id: channel.id,
1681
+ message_id: channel.lastMessageId || '0',
1682
+ read_state_type: 0
1683
+ }));
1684
+ }
1685
+
1686
+ const data = await this.client.api['read-states']['ack-bulk'].post({
1687
+ data: readStates
1688
+ });
1689
+
1690
+ return data;
1691
+ }
1692
+
1662
1693
  /**
1663
1694
  * Creates a collection of this guild's roles, sorted by their position and ids.
1664
1695
  * @returns {Collection<Snowflake, Role>}
@@ -385,30 +385,67 @@ class TextBasedChannel {
385
385
  return Util.createPromiseInteraction(this.client, nonce, 5000);
386
386
  }
387
387
 
388
+
388
389
  /**
389
- * Search messages in this channel by user
390
- * @param {number} limit Number of messages to return
391
- * @param {UserResolvable} user User whose messages to search for
392
- * @returns {Promise<Object[]|false>} Array of messages or false if failed
390
+ * Search for messages in this channel
391
+ * @param {ChannelSearchOptions} [options] Search options
392
+ * @returns {Promise<Object>} The search results
393
393
  * @example
394
- * // Search for messages from a user
395
- * channel.search(10, user)
396
- * .then(messages => console.log(`Found ${messages.length} messages`))
397
- * .catch(console.error);
394
+ * // Search for messages by author
395
+ * channel.search({ authorId: '123456789012345678' });
396
+ *
397
+ * // Search for messages with images
398
+ * channel.search({ has: ['image'] });
399
+ *
400
+ * // Search for pinned messages
401
+ * channel.search({ pinned: true });
398
402
  */
399
- async search(limit, user) {
400
- const userId = this.client.users.resolveId(user);
401
- if (!userId) throw new Error('INVALID_TYPE', 'user', 'UserResolvable');
403
+ async search(options = {}) {
404
+ const {
405
+ authorId,
406
+ mentions,
407
+ has = [],
408
+ pinned,
409
+ sortBy = 'timestamp',
410
+ sortOrder = 'desc',
411
+ offset = 0,
412
+ limit,
413
+ maxTime
414
+ } = options;
415
+
416
+ const query = {
417
+ sort_by: sortBy,
418
+ sort_order: sortOrder,
419
+ offset: offset
420
+ };
421
+
422
+ if (maxTime) {
423
+ const time = new Date(maxTime).getTime();
424
+ const maxId = (BigInt(time) - 1420070400000n) << 22n;
425
+ query.max_id = maxId.toString();
426
+ }
427
+
428
+ if (authorId) query.author_id = authorId;
429
+ if (mentions) query.mentions = mentions;
430
+ if (pinned) query.pinned = true;
402
431
 
403
- const res = await fetch(`https://ptb.discord.com/api/v9/${this.guild ? `guilds/${this.guild.id}` : `channels/${this.id}`}/messages/search?author_id=${userId}&channel_id=${this.id}&sort_by=timestamp&sort_order=desc&offset=0`, {
404
- method: 'GET',
405
- headers: { authorization: this.client.token }
406
- });
432
+ for (const hasType of has) {
433
+ if (!query.has) query.has = [];
434
+ query.has.push(hasType);
435
+ }
436
+
437
+ if (this.guild) query.channel_id = this.id;
438
+
439
+ const endpoint = this.guild
440
+ ? this.client.api.guilds(this.guild.id).messages.search
441
+ : this.client.api.channels(this.id).messages.search;
442
+
443
+ const data = await endpoint.get({ query });
407
444
 
408
- if (!res.ok) return false;
445
+ if (limit && data.messages)
446
+ data.messages = data.messages.flat().slice(0, limit);
409
447
 
410
- const data = await res.json();
411
- return data.messages.splice(0, limit);
448
+ return data;
412
449
  }
413
450
 
414
451
  /**
@@ -945,6 +945,24 @@ export interface AcceptInviteOptions {
945
945
  bypassVerify: boolean;
946
946
  }
947
947
 
948
+ export interface ChannelSearchOptions {
949
+ authorId?: Snowflake;
950
+ mentions?: Snowflake;
951
+ has?: ('image' | 'video' | 'link' | 'embed' | 'sound' | 'poll' | 'sticker' | 'snapshot')[];
952
+ pinned?: boolean;
953
+ sortBy?: 'timestamp' | 'relevance';
954
+ sortOrder?: 'desc' | 'asc';
955
+ offset?: number;
956
+ limit?: number;
957
+ maxTime?: string | Date;
958
+ }
959
+
960
+ export interface MarkReadOptions {
961
+ channel_id: Snowflake;
962
+ message_id: Snowflake;
963
+ read_state_type?: number;
964
+ }
965
+
948
966
  export type OAuth2AuthorizeOptions = {
949
967
  guild_id?: Snowflake;
950
968
  permissions?: string;
@@ -1684,6 +1702,7 @@ export class Guild extends AnonymousGuild {
1684
1702
  public setVanityCode(code?: string): Promise<this>;
1685
1703
  public mute(options?: GuildMuteOptions): Promise<any>;
1686
1704
  public unmute(): Promise<any>;
1705
+ public markRead(readStates?: MarkReadOptions[]): Promise<any>;
1687
1706
  }
1688
1707
 
1689
1708
  export class GuildAuditLogs<T extends GuildAuditLogsResolvable = 'ALL'> {
@@ -5225,6 +5244,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
5225
5244
  fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
5226
5245
  sendTyping(): Promise<{ message_send_cooldown_ms: number; thread_create_cooldown_ms: number } | undefined>;
5227
5246
  sendSlash(target: UserResolvable, commandName: string, ...args: any[]): Promise<Message | Modal>;
5247
+ search(options?: ChannelSearchOptions): Promise<any>;
5228
5248
  }
5229
5249
 
5230
5250
  export function PartialWebhookMixin<T>(Base?: Constructable<T>): Constructable<T & PartialWebhookFields>;