djs-selfbot-v13 3.7.14 → 3.7.16
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/package.json
CHANGED
package/src/rest/APIRequest.js
CHANGED
|
@@ -16,9 +16,7 @@ class APIRequest {
|
|
|
16
16
|
this.route = options.route;
|
|
17
17
|
this.options = options;
|
|
18
18
|
this.retries = 0;
|
|
19
|
-
|
|
20
19
|
this.fullUserAgent = this.client.options.http.headers['User-Agent'];
|
|
21
|
-
|
|
22
20
|
this.client.options.ws.properties.browser_user_agent = this.fullUserAgent;
|
|
23
21
|
|
|
24
22
|
let queryString = '';
|
|
@@ -223,19 +223,8 @@ class BaseGuildVoiceChannel extends GuildChannel {
|
|
|
223
223
|
return this.edit({ videoQualityMode }, reason);
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
|
227
|
-
/* eslint-disable no-empty-function */
|
|
228
|
-
get lastMessage() {}
|
|
229
|
-
send() {}
|
|
230
|
-
sendTyping() {}
|
|
231
|
-
createMessageCollector() {}
|
|
232
|
-
awaitMessages() {}
|
|
233
|
-
fetchWebhooks() {}
|
|
234
|
-
createWebhook() {}
|
|
235
|
-
setRateLimitPerUser() {}
|
|
236
|
-
setNSFW() {}
|
|
237
226
|
}
|
|
238
227
|
|
|
239
228
|
TextBasedChannel.applyToClass(BaseGuildVoiceChannel, true, ['lastPinAt']);
|
|
240
229
|
|
|
241
|
-
module.exports = BaseGuildVoiceChannel;
|
|
230
|
+
module.exports = BaseGuildVoiceChannel;
|
|
@@ -41,20 +41,44 @@ class ClientPresence extends Presence {
|
|
|
41
41
|
since: typeof since === 'number' && !Number.isNaN(since) ? this.since : 0,
|
|
42
42
|
status: status ?? this.status,
|
|
43
43
|
};
|
|
44
|
+
|
|
45
|
+
// Récupère le custom status actuellement en cache pour ne pas l'écraser
|
|
46
|
+
// lors d'un setActivity / setStatus qui ne touche pas au custom status
|
|
47
|
+
const existingCustom = this.activities?.find(a =>
|
|
48
|
+
CustomStatusActivityTypes.includes(a.type),
|
|
49
|
+
);
|
|
50
|
+
|
|
44
51
|
if (activities?.length) {
|
|
52
|
+
let hasCustom = false;
|
|
45
53
|
for (const [i, activity] of activities.entries()) {
|
|
46
54
|
if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', `activities[${i}].name`, 'string');
|
|
47
55
|
|
|
48
56
|
activity.type ??= ActivityTypes.PLAYING;
|
|
49
57
|
if (typeof activity.type === 'string') activity.type = ActivityTypes[activity.type];
|
|
50
58
|
|
|
51
|
-
if (CustomStatusActivityTypes.includes(activity.type)
|
|
52
|
-
|
|
53
|
-
activity.
|
|
59
|
+
if (CustomStatusActivityTypes.includes(activity.type)) {
|
|
60
|
+
hasCustom = true;
|
|
61
|
+
if (!activity.state) {
|
|
62
|
+
activity.state = activity.name;
|
|
63
|
+
activity.name = 'Custom Status';
|
|
64
|
+
}
|
|
54
65
|
}
|
|
55
66
|
|
|
56
67
|
data.activities.push(activity);
|
|
57
68
|
}
|
|
69
|
+
|
|
70
|
+
// Si le tableau d'activités passé ne contient pas de custom status,
|
|
71
|
+
// réinjecte celui du cache pour ne pas le perdre
|
|
72
|
+
if (!hasCustom && existingCustom) {
|
|
73
|
+
data.activities.unshift({
|
|
74
|
+
type: typeof existingCustom.type === 'string'
|
|
75
|
+
? ActivityTypes[existingCustom.type]
|
|
76
|
+
: existingCustom.type,
|
|
77
|
+
name: existingCustom.name ?? 'Custom Status',
|
|
78
|
+
state: existingCustom.state ?? null,
|
|
79
|
+
emoji: existingCustom.emoji ?? null,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
58
82
|
} else if (!activities && (status || afk || since) && this.activities.length) {
|
|
59
83
|
data.activities.push(
|
|
60
84
|
...this.activities.map(a => {
|
|
@@ -74,4 +98,4 @@ module.exports = ClientPresence;
|
|
|
74
98
|
/**
|
|
75
99
|
* @external APIPresence
|
|
76
100
|
* @see {@link https://discord.com/developers/docs/rich-presence/how-to#updating-presence-update-presence-payload-fields}
|
|
77
|
-
*/
|
|
101
|
+
*/
|
|
@@ -267,6 +267,68 @@ class ClientUser extends User {
|
|
|
267
267
|
return this.setPresence({ afk, shardId });
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Sets the custom status of the client user.
|
|
272
|
+
* Updates both the Gateway (local real-time display) and the REST API (account persistence).
|
|
273
|
+
* @param {CustomStatus|CustomStatusOptions|string|null} options
|
|
274
|
+
* A `CustomStatus` instance, an options object, a plain string for the state, or `null` to clear.
|
|
275
|
+
* @param {string} [options.state] Text displayed as the status
|
|
276
|
+
* @param {EmojiIdentifierResolvable} [options.emoji] Emoji shown next to the text
|
|
277
|
+
* @param {string} [options.expiresAt] ISO8601 date at which Discord auto-clears the status
|
|
278
|
+
* @param {number|number[]} [options.shardId] Shard(s) to broadcast the Gateway update on
|
|
279
|
+
* @returns {Promise<ClientPresence>}
|
|
280
|
+
* @example
|
|
281
|
+
* // With text + unicode emoji
|
|
282
|
+
* await client.user.setCustomStatus({ state: 'Coding...', emoji: '💻' });
|
|
283
|
+
* @example
|
|
284
|
+
* // Plain string shorthand
|
|
285
|
+
* await client.user.setCustomStatus('Taking a break');
|
|
286
|
+
* @example
|
|
287
|
+
* // Clear the custom status
|
|
288
|
+
* await client.user.setCustomStatus(null);
|
|
289
|
+
*/
|
|
290
|
+
async setCustomStatus(options, shardId) {
|
|
291
|
+
const { CustomStatus } = require('../structures/Presence');
|
|
292
|
+
|
|
293
|
+
// ── 1. Normalise l'entrée ─────────────────────────────────────────────
|
|
294
|
+
let activity = null; // null = effacer
|
|
295
|
+
let restPayload = null;
|
|
296
|
+
|
|
297
|
+
if (options !== null && options !== undefined) {
|
|
298
|
+
if (typeof options === 'string') options = { state: options };
|
|
299
|
+
|
|
300
|
+
// Supporte un objet CustomStatus existant (déjà construit par l'utilisateur)
|
|
301
|
+
const cs = options instanceof CustomStatus
|
|
302
|
+
? options
|
|
303
|
+
: new CustomStatus(this.client, {
|
|
304
|
+
state: options.state ?? null,
|
|
305
|
+
emoji: options.emoji ? { name: options.emoji } : undefined,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
activity = cs.toJSON(); // { name, type, state, emoji }
|
|
309
|
+
|
|
310
|
+
restPayload = {
|
|
311
|
+
text: cs.state ?? null,
|
|
312
|
+
emoji_name: cs.emoji?.name ?? null,
|
|
313
|
+
emoji_id: cs.emoji?.id ?? null,
|
|
314
|
+
expires_at: options.expiresAt ?? null,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ── 2. Gateway — visible localement en temps réel ────────────────────
|
|
319
|
+
const presenceActivities = activity ? [activity] : [];
|
|
320
|
+
const presence = this.setPresence({ activities: presenceActivities, shardId });
|
|
321
|
+
|
|
322
|
+
// ── 3. REST — persistance sur le compte Discord ───────────────────────
|
|
323
|
+
await this.client.api.users('@me').settings.patch({ data: { custom_status: restPayload } })
|
|
324
|
+
.catch(err => {
|
|
325
|
+
// Non bloquant : on ne veut pas casser setPresence si l'endpoint échoue
|
|
326
|
+
this.client.emit('warn', `[setCustomStatus] REST patch failed: ${err?.message ?? err}`);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return presence;
|
|
330
|
+
}
|
|
331
|
+
|
|
270
332
|
/**
|
|
271
333
|
* Sets the banner of the logged in client.
|
|
272
334
|
* @param {?(BufferResolvable|Base64Resolvable)} banner The new banner
|
|
@@ -466,10 +528,10 @@ class ClientUser extends User {
|
|
|
466
528
|
|
|
467
529
|
// Get current widgets first
|
|
468
530
|
const currentWidgets = await this.widgetsList();
|
|
469
|
-
|
|
531
|
+
|
|
470
532
|
// Find existing widget of this type or create new one
|
|
471
533
|
let targetWidget = currentWidgets.widgets.find(w => w.data.type === type);
|
|
472
|
-
|
|
534
|
+
|
|
473
535
|
if (!targetWidget) {
|
|
474
536
|
// Create new widget if it doesn't exist
|
|
475
537
|
targetWidget = {
|
|
@@ -488,7 +550,7 @@ class ClientUser extends User {
|
|
|
488
550
|
const gameData = { game_id: gameId };
|
|
489
551
|
if (comment !== null) gameData.comment = comment;
|
|
490
552
|
if (tags.length > 0) gameData.tags = tags;
|
|
491
|
-
|
|
553
|
+
|
|
492
554
|
targetWidget.data.games.push(gameData);
|
|
493
555
|
}
|
|
494
556
|
|
|
@@ -516,7 +578,7 @@ class ClientUser extends User {
|
|
|
516
578
|
|
|
517
579
|
// Get current widgets
|
|
518
580
|
const currentWidgets = await this.widgetsList();
|
|
519
|
-
|
|
581
|
+
|
|
520
582
|
if (gameId) {
|
|
521
583
|
// Remove specific game from widget
|
|
522
584
|
const targetWidget = currentWidgets.widgets.find(w => w.data.type === type);
|
|
@@ -611,7 +673,7 @@ class ClientUser extends User {
|
|
|
611
673
|
|
|
612
674
|
const primaryColor = resolveColor(color1);
|
|
613
675
|
const colors = [primaryColor];
|
|
614
|
-
|
|
676
|
+
|
|
615
677
|
if (color2 !== null) {
|
|
616
678
|
const secondaryColor = resolveColor(color2);
|
|
617
679
|
colors.push(secondaryColor);
|
|
@@ -629,6 +691,44 @@ class ClientUser extends User {
|
|
|
629
691
|
return this;
|
|
630
692
|
}
|
|
631
693
|
|
|
694
|
+
/**
|
|
695
|
+
* Search messages across all DMs/GDMs using the tabs API.
|
|
696
|
+
* Supports pagination via offset.
|
|
697
|
+
* @param {Object} [options] Search options
|
|
698
|
+
* @param {string} [options.sortBy='timestamp'] Sort by ('timestamp' or 'relevance')
|
|
699
|
+
* @param {string} [options.sortOrder='desc'] Sort order ('asc' or 'desc')
|
|
700
|
+
* @param {number} [options.offset=0] Pagination offset
|
|
701
|
+
* @param {number} [options.limit=25] Results per page (max 25)
|
|
702
|
+
* @param {boolean} [options.trackExactTotal=true] Track exact total hits
|
|
703
|
+
* @returns {Promise<{ messages: Message[], total_results: number }>}
|
|
704
|
+
*/
|
|
705
|
+
async searchTab(options = {}) {
|
|
706
|
+
const {
|
|
707
|
+
sortBy = 'timestamp',
|
|
708
|
+
sortOrder = 'desc',
|
|
709
|
+
offset = 0,
|
|
710
|
+
limit = 25,
|
|
711
|
+
trackExactTotal = true,
|
|
712
|
+
} = options;
|
|
713
|
+
|
|
714
|
+
const data = await this.client.api.users['@me'].messages.search.tabs.post({
|
|
715
|
+
data: {
|
|
716
|
+
tabs: {
|
|
717
|
+
messages: {
|
|
718
|
+
sort_by: sortBy,
|
|
719
|
+
sort_order: sortOrder,
|
|
720
|
+
author_id: [this.id],
|
|
721
|
+
offset,
|
|
722
|
+
limit: Math.min(limit, 25),
|
|
723
|
+
},
|
|
724
|
+
},
|
|
725
|
+
track_exact_total_hits: trackExactTotal,
|
|
726
|
+
},
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
return data;
|
|
730
|
+
}
|
|
731
|
+
|
|
632
732
|
/**
|
|
633
733
|
* Set the TAG of a guild.
|
|
634
734
|
* @param {GuildIDResolve} guild The guild with the tag
|
|
@@ -637,7 +737,7 @@ class ClientUser extends User {
|
|
|
637
737
|
setClan(guild) {
|
|
638
738
|
const id = this.client.guilds.resolveId(guild);
|
|
639
739
|
if (!id) throw new TypeError('INVALID_TYPE', 'guild', 'GuildResolvable');
|
|
640
|
-
|
|
740
|
+
|
|
641
741
|
return this.client.api.users['@me'].clan.put({ data: { identity_guild_id: id, identity_enabled: true } });
|
|
642
742
|
}
|
|
643
743
|
|
|
@@ -650,4 +750,4 @@ class ClientUser extends User {
|
|
|
650
750
|
}
|
|
651
751
|
}
|
|
652
752
|
|
|
653
|
-
module.exports = ClientUser;
|
|
753
|
+
module.exports = ClientUser;
|
package/typings/index.d.ts
CHANGED
|
@@ -1034,6 +1034,7 @@ export class ClientUser extends User {
|
|
|
1034
1034
|
public delWidget(type: WidgetType, gameId?: string): Promise<any>;
|
|
1035
1035
|
public widgetsList(): Promise<WidgetsResponse>;
|
|
1036
1036
|
public setNameStyle(fontName: FontName | number, effectName: EffectName | number, color1: number | string, color2?: number | string | null): Promise<this>;
|
|
1037
|
+
public searchTab(options?: UserMessageSearchTabOptions): Promise<{ messages: any[][]; total_results: number }>;
|
|
1037
1038
|
}
|
|
1038
1039
|
|
|
1039
1040
|
export class Options extends null {
|
|
@@ -1723,6 +1724,14 @@ export class Guild extends AnonymousGuild {
|
|
|
1723
1724
|
public search(options?: GuildSearchOptions): Promise<any>;
|
|
1724
1725
|
}
|
|
1725
1726
|
|
|
1727
|
+
export interface UserMessageSearchTabOptions {
|
|
1728
|
+
sortBy?: 'timestamp' | 'relevance';
|
|
1729
|
+
sortOrder?: 'desc' | 'asc';
|
|
1730
|
+
offset?: number;
|
|
1731
|
+
limit?: number;
|
|
1732
|
+
trackExactTotal?: boolean;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1726
1735
|
export class GuildAuditLogs<T extends GuildAuditLogsResolvable = 'ALL'> {
|
|
1727
1736
|
private constructor(guild: Guild, data: RawGuildAuditLogData);
|
|
1728
1737
|
private webhooks: Collection<Snowflake, Webhook>;
|