djs-selfbot-v13 3.7.3 → 3.7.5
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 +50 -0
- package/package.json +2 -1
- package/src/managers/QuestManager.js +5 -22
- package/src/structures/Guild.js +31 -0
- package/src/structures/interfaces/TextBasedChannel.js +54 -7
- package/typings/index.d.ts +19 -0
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,18 @@
|
|
|
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
|
+
|
|
94
|
+
|
|
82
95
|
</details>
|
|
83
96
|
|
|
84
97
|
> [!WARNING]
|
|
@@ -123,6 +136,43 @@ client.on('ready', async () => {
|
|
|
123
136
|
client.login('token');
|
|
124
137
|
```
|
|
125
138
|
|
|
139
|
+
### Advanced Examples
|
|
140
|
+
|
|
141
|
+
#### Message Search
|
|
142
|
+
```js
|
|
143
|
+
// Search for messages with images in a channel
|
|
144
|
+
const results = await channel.search({ has: ['image'] });
|
|
145
|
+
|
|
146
|
+
// Search for messages by a specific author
|
|
147
|
+
const userMessages = await channel.search({
|
|
148
|
+
authorId: '123456789012345678',
|
|
149
|
+
limit: 10
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Search for pinned messages
|
|
153
|
+
const pinnedMessages = await channel.search({ pinned: true });
|
|
154
|
+
|
|
155
|
+
// Search for messages with multiple filters
|
|
156
|
+
const complexSearch = await channel.search({
|
|
157
|
+
has: ['link', 'embed'],
|
|
158
|
+
sortBy: 'timestamp',
|
|
159
|
+
sortOrder: 'desc',
|
|
160
|
+
offset: 20
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### Guild Read State Management
|
|
165
|
+
```js
|
|
166
|
+
// Mark all channels in a guild as read
|
|
167
|
+
await guild.markRead();
|
|
168
|
+
|
|
169
|
+
// Mark specific channels as read
|
|
170
|
+
await guild.markRead([
|
|
171
|
+
{ channel_id: '123456789012345678', message_id: '987654321098765432' },
|
|
172
|
+
{ channel_id: '876543210987654321', message_id: '123456789012345678' }
|
|
173
|
+
]);
|
|
174
|
+
```
|
|
175
|
+
|
|
126
176
|
## Get Token ?
|
|
127
177
|
|
|
128
178
|
- 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.
|
|
3
|
+
"version": "3.7.5",
|
|
4
4
|
"description": "An unofficial discord.js fork for creating selfbots",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./typings/index.d.ts",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"@discordjs/collection": "^2.1.1",
|
|
56
56
|
"@sapphire/async-queue": "^1.5.5",
|
|
57
57
|
"@sapphire/shapeshift": "^4.0.0",
|
|
58
|
+
"debug": "^4.4.3",
|
|
58
59
|
"discord-api-types": "^0.38.15",
|
|
59
60
|
"fetch-cookie": "^3.1.0",
|
|
60
61
|
"find-process": "^2.0.0",
|
|
@@ -76,7 +76,7 @@ class QuestManager extends BaseManager {
|
|
|
76
76
|
* @returns {Promise<Object>} Quest data
|
|
77
77
|
*/
|
|
78
78
|
async get() {
|
|
79
|
-
const data = await this.client.api.
|
|
79
|
+
const data = await this.client.api.quests('@me').get();
|
|
80
80
|
|
|
81
81
|
// Cache quests
|
|
82
82
|
if (data.quests) {
|
|
@@ -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
|
-
|
|
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
|
|
package/src/structures/Guild.js
CHANGED
|
@@ -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>}
|
|
@@ -396,19 +396,66 @@ class TextBasedChannel {
|
|
|
396
396
|
* .then(messages => console.log(`Found ${messages.length} messages`))
|
|
397
397
|
* .catch(console.error);
|
|
398
398
|
*/
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
399
|
+
/**
|
|
400
|
+
* Search for messages in this channel
|
|
401
|
+
* @param {ChannelSearchOptions} [options] Search options
|
|
402
|
+
* @returns {Promise<Object>} The search results
|
|
403
|
+
* @example
|
|
404
|
+
* // Search for messages by author
|
|
405
|
+
* channel.search({ authorId: '123456789012345678' });
|
|
406
|
+
*
|
|
407
|
+
* // Search for messages with images
|
|
408
|
+
* channel.search({ has: ['image'] });
|
|
409
|
+
*
|
|
410
|
+
* // Search for pinned messages
|
|
411
|
+
* channel.search({ pinned: true });
|
|
412
|
+
*/
|
|
413
|
+
async search(options = {}) {
|
|
414
|
+
const {
|
|
415
|
+
authorId,
|
|
416
|
+
mentions,
|
|
417
|
+
has = [],
|
|
418
|
+
pinned,
|
|
419
|
+
sortBy = 'timestamp',
|
|
420
|
+
sortOrder = 'desc',
|
|
421
|
+
offset = 0,
|
|
422
|
+
limit
|
|
423
|
+
} = options;
|
|
424
|
+
|
|
425
|
+
const params = new URLSearchParams({
|
|
426
|
+
channel_id: this.id,
|
|
427
|
+
sort_by: sortBy,
|
|
428
|
+
sort_order: sortOrder,
|
|
429
|
+
offset: offset.toString()
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
if (authorId) params.append('author_id', authorId);
|
|
433
|
+
if (mentions) params.append('mentions', mentions);
|
|
434
|
+
if (pinned) params.append('pinned', 'true');
|
|
402
435
|
|
|
403
|
-
|
|
436
|
+
// Add 'has' parameters
|
|
437
|
+
for (const hasType of has) {
|
|
438
|
+
params.append('has', hasType);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const endpoint = this.guild
|
|
442
|
+
? `guilds/${this.guild.id}/messages/search`
|
|
443
|
+
: `channels/${this.id}/messages/search`;
|
|
444
|
+
|
|
445
|
+
const res = await fetch(`https://ptb.discord.com/api/v9/${endpoint}?${params}`, {
|
|
404
446
|
method: 'GET',
|
|
405
447
|
headers: { authorization: this.client.token }
|
|
406
448
|
});
|
|
407
|
-
|
|
449
|
+
|
|
408
450
|
if (!res.ok) return false;
|
|
409
|
-
|
|
451
|
+
|
|
410
452
|
const data = await res.json();
|
|
411
|
-
|
|
453
|
+
|
|
454
|
+
if (limit && data.messages) {
|
|
455
|
+
data.messages = data.messages.slice(0, limit);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return data;
|
|
412
459
|
}
|
|
413
460
|
|
|
414
461
|
/**
|
package/typings/index.d.ts
CHANGED
|
@@ -945,6 +945,23 @@ 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
|
+
}
|
|
958
|
+
|
|
959
|
+
export interface MarkReadOptions {
|
|
960
|
+
channel_id: Snowflake;
|
|
961
|
+
message_id: Snowflake;
|
|
962
|
+
read_state_type?: number;
|
|
963
|
+
}
|
|
964
|
+
|
|
948
965
|
export type OAuth2AuthorizeOptions = {
|
|
949
966
|
guild_id?: Snowflake;
|
|
950
967
|
permissions?: string;
|
|
@@ -1684,6 +1701,7 @@ export class Guild extends AnonymousGuild {
|
|
|
1684
1701
|
public setVanityCode(code?: string): Promise<this>;
|
|
1685
1702
|
public mute(options?: GuildMuteOptions): Promise<any>;
|
|
1686
1703
|
public unmute(): Promise<any>;
|
|
1704
|
+
public markRead(readStates?: MarkReadOptions[]): Promise<any>;
|
|
1687
1705
|
}
|
|
1688
1706
|
|
|
1689
1707
|
export class GuildAuditLogs<T extends GuildAuditLogsResolvable = 'ALL'> {
|
|
@@ -5225,6 +5243,7 @@ export interface TextBasedChannelFields extends PartialTextBasedChannelFields {
|
|
|
5225
5243
|
fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
|
5226
5244
|
sendTyping(): Promise<{ message_send_cooldown_ms: number; thread_create_cooldown_ms: number } | undefined>;
|
|
5227
5245
|
sendSlash(target: UserResolvable, commandName: string, ...args: any[]): Promise<Message | Modal>;
|
|
5246
|
+
search(options?: ChannelSearchOptions): Promise<any>;
|
|
5228
5247
|
}
|
|
5229
5248
|
|
|
5230
5249
|
export function PartialWebhookMixin<T>(Base?: Constructable<T>): Constructable<T & PartialWebhookFields>;
|