lunibee 0.1.5 → 0.1.7
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 +13 -24
- package/dist/builders/commands.d.ts +37 -0
- package/dist/builders/components.d.ts +127 -12
- package/dist/builders/embed.d.ts +3 -1
- package/dist/builders/index.d.ts +2 -2
- package/dist/builders/index.js +319 -16
- package/dist/builders/index.js.map +8 -7
- package/dist/collection/index.d.ts +36 -0
- package/dist/collection/index.js +110 -6
- package/dist/collection/index.js.map +4 -4
- package/dist/core/events.d.ts +69 -3
- package/dist/core/index.d.ts +158 -90
- package/dist/core/index.js +1543 -1169
- package/dist/core/index.js.map +24 -23
- package/dist/core/permissions.d.ts +112 -53
- package/dist/formatters/index.d.ts +43 -3
- package/dist/formatters/index.js +64 -1
- package/dist/formatters/index.js.map +3 -3
- package/dist/handlers/index.js.map +2 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3882 -1588
- package/dist/index.js.map +43 -35
- package/dist/managers/emoji.d.ts +38 -0
- package/dist/managers/guild.d.ts +141 -0
- package/dist/managers/index.d.ts +86 -75
- package/dist/managers/index.js +1084 -67
- package/dist/managers/index.js.map +21 -16
- package/dist/managers/message.d.ts +7 -12
- package/dist/managers/user.d.ts +20 -0
- package/dist/rest/index.d.ts +173 -1
- package/dist/rest/index.js +343 -47
- package/dist/rest/index.js.map +8 -6
- package/dist/rest/redis.d.ts +37 -0
- package/dist/rest/routes.d.ts +26 -1
- package/dist/rest/store.d.ts +38 -0
- package/dist/rest/webhook.d.ts +2 -2
- package/dist/sharding/cluster.d.ts +61 -0
- package/dist/sharding/index.d.ts +8 -0
- package/dist/sharding/index.js +289 -18
- package/dist/sharding/index.js.map +8 -7
- package/dist/structures/audit-log.d.ts +26 -0
- package/dist/structures/base.d.ts +131 -48
- package/dist/structures/embed.d.ts +65 -0
- package/dist/structures/index.d.ts +74 -26
- package/dist/structures/index.js +1528 -59
- package/dist/structures/index.js.map +14 -8
- package/dist/structures/interactions.d.ts +72 -17
- package/dist/structures/resources.d.ts +199 -7
- package/dist/types/index.d.ts +605 -84
- package/dist/types/index.js +71 -1
- package/dist/types/index.js.map +3 -3
- package/dist/utils/index.js.map +2 -2
- package/dist/voice/index.d.ts +88 -0
- package/dist/voice/index.js +204 -5
- package/dist/voice/index.js.map +3 -3
- package/dist/ws/index.d.ts +40 -1
- package/dist/ws/index.js +105 -18
- package/dist/ws/index.js.map +4 -4
- package/package.json +16 -16
- package/dist/structures/permissions.d.ts +0 -73
package/dist/core/index.js
CHANGED
|
@@ -107,58 +107,57 @@ var Permissions = {
|
|
|
107
107
|
SendPolls: 1n << 49n,
|
|
108
108
|
UseExternalApps: 1n << 50n
|
|
109
109
|
};
|
|
110
|
-
var PermissionFlagsBits
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
})(PermissionFlagsBits ||= {});
|
|
110
|
+
var PermissionFlagsBits = {
|
|
111
|
+
CreateInstantInvite: 1n << 0n,
|
|
112
|
+
KickMembers: 1n << 1n,
|
|
113
|
+
BanMembers: 1n << 2n,
|
|
114
|
+
Administrator: 1n << 3n,
|
|
115
|
+
ManageChannels: 1n << 4n,
|
|
116
|
+
ManageGuild: 1n << 5n,
|
|
117
|
+
AddReactions: 1n << 6n,
|
|
118
|
+
ViewAuditLog: 1n << 7n,
|
|
119
|
+
PrioritySpeaker: 1n << 8n,
|
|
120
|
+
Stream: 1n << 9n,
|
|
121
|
+
ViewChannel: 1n << 10n,
|
|
122
|
+
SendMessages: 1n << 11n,
|
|
123
|
+
SendTTSMessages: 1n << 12n,
|
|
124
|
+
ManageMessages: 1n << 13n,
|
|
125
|
+
EmbedLinks: 1n << 14n,
|
|
126
|
+
AttachFiles: 1n << 15n,
|
|
127
|
+
ReadMessageHistory: 1n << 16n,
|
|
128
|
+
MentionEveryone: 1n << 17n,
|
|
129
|
+
UseExternalEmojis: 1n << 18n,
|
|
130
|
+
ViewGuildInsights: 1n << 19n,
|
|
131
|
+
Connect: 1n << 20n,
|
|
132
|
+
Speak: 1n << 21n,
|
|
133
|
+
MuteMembers: 1n << 22n,
|
|
134
|
+
DeafenMembers: 1n << 23n,
|
|
135
|
+
MoveMembers: 1n << 24n,
|
|
136
|
+
UseVAD: 1n << 25n,
|
|
137
|
+
ChangeNickname: 1n << 26n,
|
|
138
|
+
ManageNicknames: 1n << 27n,
|
|
139
|
+
ManageRoles: 1n << 28n,
|
|
140
|
+
ManageWebhooks: 1n << 29n,
|
|
141
|
+
ManageGuildExpressions: 1n << 30n,
|
|
142
|
+
UseApplicationCommands: 1n << 31n,
|
|
143
|
+
RequestToSpeak: 1n << 32n,
|
|
144
|
+
ManageEvents: 1n << 33n,
|
|
145
|
+
ManageThreads: 1n << 34n,
|
|
146
|
+
CreatePublicThreads: 1n << 35n,
|
|
147
|
+
CreatePrivateThreads: 1n << 36n,
|
|
148
|
+
UseExternalStickers: 1n << 37n,
|
|
149
|
+
SendMessagesInThreads: 1n << 38n,
|
|
150
|
+
UseEmbeddedActivities: 1n << 39n,
|
|
151
|
+
ModerateMembers: 1n << 40n,
|
|
152
|
+
ViewCreatorMonetizationAnalytics: 1n << 41n,
|
|
153
|
+
UseSoundboard: 1n << 42n,
|
|
154
|
+
CreateGuildExpressions: 1n << 43n,
|
|
155
|
+
CreateEvents: 1n << 44n,
|
|
156
|
+
UseExternalSounds: 1n << 45n,
|
|
157
|
+
SendVoiceMessages: 1n << 46n,
|
|
158
|
+
SendPolls: 1n << 49n,
|
|
159
|
+
UseExternalApps: 1n << 50n
|
|
160
|
+
};
|
|
162
161
|
|
|
163
162
|
class PermissionSet {
|
|
164
163
|
bitfield;
|
|
@@ -403,7 +402,7 @@ class PermissionSet {
|
|
|
403
402
|
if (permission in Permissions)
|
|
404
403
|
return Permissions[permission];
|
|
405
404
|
if (permission in PermissionFlagsBits)
|
|
406
|
-
return
|
|
405
|
+
return PermissionFlagsBits[permission];
|
|
407
406
|
const lower = permission.charAt(0).toLowerCase() + permission.slice(1);
|
|
408
407
|
if (lower in Permission)
|
|
409
408
|
return Permission[lower];
|
|
@@ -420,6 +419,228 @@ class PermissionsBitField extends PermissionSet {
|
|
|
420
419
|
super(value);
|
|
421
420
|
}
|
|
422
421
|
}
|
|
422
|
+
// packages/core/src/events.ts
|
|
423
|
+
var ClientEvent;
|
|
424
|
+
((ClientEvent2) => {
|
|
425
|
+
ClientEvent2["Ready"] = "ready";
|
|
426
|
+
ClientEvent2["Resumed"] = "resumed";
|
|
427
|
+
ClientEvent2["InvalidSession"] = "invalidSession";
|
|
428
|
+
ClientEvent2["Raw"] = "raw";
|
|
429
|
+
ClientEvent2["Error"] = "error";
|
|
430
|
+
ClientEvent2["Open"] = "open";
|
|
431
|
+
ClientEvent2["Close"] = "close";
|
|
432
|
+
ClientEvent2["MessageCreate"] = "messageCreate";
|
|
433
|
+
ClientEvent2["MessageUpdate"] = "messageUpdate";
|
|
434
|
+
ClientEvent2["MessageDelete"] = "messageDelete";
|
|
435
|
+
ClientEvent2["MessageDeleteBulk"] = "messageDeleteBulk";
|
|
436
|
+
ClientEvent2["MessageReactionAdd"] = "messageReactionAdd";
|
|
437
|
+
ClientEvent2["MessageReactionRemove"] = "messageReactionRemove";
|
|
438
|
+
ClientEvent2["MessageReactionRemoveAll"] = "messageReactionRemoveAll";
|
|
439
|
+
ClientEvent2["MessageReactionRemoveEmoji"] = "messageReactionRemoveEmoji";
|
|
440
|
+
ClientEvent2["MessagePollVoteAdd"] = "messagePollVoteAdd";
|
|
441
|
+
ClientEvent2["MessagePollVoteRemove"] = "messagePollVoteRemove";
|
|
442
|
+
ClientEvent2["GuildCreate"] = "guildCreate";
|
|
443
|
+
ClientEvent2["GuildUpdate"] = "guildUpdate";
|
|
444
|
+
ClientEvent2["GuildDelete"] = "guildDelete";
|
|
445
|
+
ClientEvent2["GuildAvailable"] = "guildAvailable";
|
|
446
|
+
ClientEvent2["GuildUnavailable"] = "guildUnavailable";
|
|
447
|
+
ClientEvent2["GuildMemberAdd"] = "guildMemberAdd";
|
|
448
|
+
ClientEvent2["GuildMemberUpdate"] = "guildMemberUpdate";
|
|
449
|
+
ClientEvent2["GuildMemberRemove"] = "guildMemberRemove";
|
|
450
|
+
ClientEvent2["GuildMembersChunk"] = "guildMembersChunk";
|
|
451
|
+
ClientEvent2["GuildBanAdd"] = "guildBanAdd";
|
|
452
|
+
ClientEvent2["GuildBanRemove"] = "guildBanRemove";
|
|
453
|
+
ClientEvent2["GuildRoleCreate"] = "guildRoleCreate";
|
|
454
|
+
ClientEvent2["GuildRoleUpdate"] = "guildRoleUpdate";
|
|
455
|
+
ClientEvent2["GuildRoleDelete"] = "guildRoleDelete";
|
|
456
|
+
ClientEvent2["GuildEmojisUpdate"] = "guildEmojisUpdate";
|
|
457
|
+
ClientEvent2["GuildStickersUpdate"] = "guildStickersUpdate";
|
|
458
|
+
ClientEvent2["GuildIntegrationsUpdate"] = "guildIntegrationsUpdate";
|
|
459
|
+
ClientEvent2["GuildScheduledEventCreate"] = "guildScheduledEventCreate";
|
|
460
|
+
ClientEvent2["GuildScheduledEventUpdate"] = "guildScheduledEventUpdate";
|
|
461
|
+
ClientEvent2["GuildScheduledEventDelete"] = "guildScheduledEventDelete";
|
|
462
|
+
ClientEvent2["GuildScheduledEventUserAdd"] = "guildScheduledEventUserAdd";
|
|
463
|
+
ClientEvent2["GuildScheduledEventUserRemove"] = "guildScheduledEventUserRemove";
|
|
464
|
+
ClientEvent2["AutoModerationRuleCreate"] = "autoModerationRuleCreate";
|
|
465
|
+
ClientEvent2["AutoModerationRuleUpdate"] = "autoModerationRuleUpdate";
|
|
466
|
+
ClientEvent2["AutoModerationRuleDelete"] = "autoModerationRuleDelete";
|
|
467
|
+
ClientEvent2["AutoModerationActionExecution"] = "autoModerationActionExecution";
|
|
468
|
+
ClientEvent2["ChannelCreate"] = "channelCreate";
|
|
469
|
+
ClientEvent2["ChannelUpdate"] = "channelUpdate";
|
|
470
|
+
ClientEvent2["ChannelDelete"] = "channelDelete";
|
|
471
|
+
ClientEvent2["ChannelPinsUpdate"] = "channelPinsUpdate";
|
|
472
|
+
ClientEvent2["ThreadCreate"] = "threadCreate";
|
|
473
|
+
ClientEvent2["ThreadUpdate"] = "threadUpdate";
|
|
474
|
+
ClientEvent2["ThreadDelete"] = "threadDelete";
|
|
475
|
+
ClientEvent2["ThreadListSync"] = "threadListSync";
|
|
476
|
+
ClientEvent2["ThreadMembersUpdate"] = "threadMembersUpdate";
|
|
477
|
+
ClientEvent2["ThreadMemberUpdate"] = "threadMemberUpdate";
|
|
478
|
+
ClientEvent2["StageInstanceCreate"] = "stageInstanceCreate";
|
|
479
|
+
ClientEvent2["StageInstanceUpdate"] = "stageInstanceUpdate";
|
|
480
|
+
ClientEvent2["StageInstanceDelete"] = "stageInstanceDelete";
|
|
481
|
+
ClientEvent2["InviteCreate"] = "inviteCreate";
|
|
482
|
+
ClientEvent2["InviteDelete"] = "inviteDelete";
|
|
483
|
+
ClientEvent2["WebhooksUpdate"] = "webhooksUpdate";
|
|
484
|
+
ClientEvent2["VoiceStateUpdate"] = "voiceStateUpdate";
|
|
485
|
+
ClientEvent2["VoiceServerUpdate"] = "voiceServerUpdate";
|
|
486
|
+
ClientEvent2["PresenceUpdate"] = "presenceUpdate";
|
|
487
|
+
ClientEvent2["TypingStart"] = "typingStart";
|
|
488
|
+
ClientEvent2["InteractionCreate"] = "interactionCreate";
|
|
489
|
+
})(ClientEvent ||= {});
|
|
490
|
+
// packages/core/src/collector.ts
|
|
491
|
+
import { EventEmitter } from "events";
|
|
492
|
+
|
|
493
|
+
class Collector extends EventEmitter {
|
|
494
|
+
collected = new Map;
|
|
495
|
+
options;
|
|
496
|
+
ended = false;
|
|
497
|
+
endReason;
|
|
498
|
+
totalProcessed = 0;
|
|
499
|
+
#timeoutTimer;
|
|
500
|
+
constructor(options = {}) {
|
|
501
|
+
super();
|
|
502
|
+
this.options = options;
|
|
503
|
+
if (options.time && options.time > 0) {
|
|
504
|
+
this.#timeoutTimer = setTimeout(() => {
|
|
505
|
+
this.stop("time");
|
|
506
|
+
}, options.time);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
async handle(key, item) {
|
|
510
|
+
if (this.ended)
|
|
511
|
+
return false;
|
|
512
|
+
this.totalProcessed++;
|
|
513
|
+
const reachedProcessed = !!this.options.maxProcessed && this.totalProcessed >= this.options.maxProcessed;
|
|
514
|
+
let passed = true;
|
|
515
|
+
if (this.options.filter)
|
|
516
|
+
passed = !!await this.options.filter(item);
|
|
517
|
+
if (this.ended)
|
|
518
|
+
return false;
|
|
519
|
+
if (!passed) {
|
|
520
|
+
if (reachedProcessed)
|
|
521
|
+
this.stop("processedLimit");
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
this.collected.set(key, item);
|
|
525
|
+
this.emit("collect", item);
|
|
526
|
+
if (this.options.max && this.collected.size >= this.options.max) {
|
|
527
|
+
this.stop("limit");
|
|
528
|
+
return true;
|
|
529
|
+
}
|
|
530
|
+
if (reachedProcessed) {
|
|
531
|
+
this.stop("processedLimit");
|
|
532
|
+
return true;
|
|
533
|
+
}
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
stop(reason = "user") {
|
|
537
|
+
if (this.ended)
|
|
538
|
+
return;
|
|
539
|
+
this.ended = true;
|
|
540
|
+
this.endReason = reason;
|
|
541
|
+
if (this.#timeoutTimer)
|
|
542
|
+
clearTimeout(this.#timeoutTimer);
|
|
543
|
+
this.emit("end", this.collected, reason);
|
|
544
|
+
this.removeAllListeners();
|
|
545
|
+
}
|
|
546
|
+
next() {
|
|
547
|
+
return new Promise((resolve, reject) => {
|
|
548
|
+
if (this.ended) {
|
|
549
|
+
return reject(new Error(`Collector already ended: ${this.endReason ?? "unknown"}`));
|
|
550
|
+
}
|
|
551
|
+
this.once("collect", (item) => {
|
|
552
|
+
resolve(item);
|
|
553
|
+
});
|
|
554
|
+
this.once("end", (_collected, reason) => {
|
|
555
|
+
reject(new Error(`Collector ended before item was collected: ${reason}`));
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// packages/types/src/index.ts
|
|
561
|
+
var GatewayIntentBits = {
|
|
562
|
+
Guilds: 1 << 0,
|
|
563
|
+
GuildMembers: 1 << 1,
|
|
564
|
+
GuildModeration: 1 << 2,
|
|
565
|
+
GuildExpressions: 1 << 3,
|
|
566
|
+
GuildIntegrations: 1 << 4,
|
|
567
|
+
GuildWebhooks: 1 << 5,
|
|
568
|
+
GuildInvites: 1 << 6,
|
|
569
|
+
GuildVoiceStates: 1 << 7,
|
|
570
|
+
GuildPresences: 1 << 8,
|
|
571
|
+
GuildMessages: 1 << 9,
|
|
572
|
+
GuildMessageReactions: 1 << 10,
|
|
573
|
+
GuildMessageTyping: 1 << 11,
|
|
574
|
+
DirectMessages: 1 << 12,
|
|
575
|
+
DirectMessageReactions: 1 << 13,
|
|
576
|
+
DirectMessageTyping: 1 << 14,
|
|
577
|
+
MessageContent: 1 << 15,
|
|
578
|
+
GuildScheduledEvents: 1 << 16,
|
|
579
|
+
AutoModerationConfiguration: 1 << 20,
|
|
580
|
+
AutoModerationExecution: 1 << 21,
|
|
581
|
+
GuildMessagePolls: 1 << 24,
|
|
582
|
+
DirectMessagePolls: 1 << 25
|
|
583
|
+
};
|
|
584
|
+
var IntentBits = {
|
|
585
|
+
guild: 1 << 0,
|
|
586
|
+
guilds: 1 << 0,
|
|
587
|
+
guildMembers: 1 << 1,
|
|
588
|
+
guildModeration: 1 << 2,
|
|
589
|
+
guildBans: 1 << 2,
|
|
590
|
+
guildExpressions: 1 << 3,
|
|
591
|
+
guildEmojis: 1 << 3,
|
|
592
|
+
guildEmojisAndStickers: 1 << 3,
|
|
593
|
+
guildIntegrations: 1 << 4,
|
|
594
|
+
guildWebhooks: 1 << 5,
|
|
595
|
+
guildInvites: 1 << 6,
|
|
596
|
+
guildVoiceStates: 1 << 7,
|
|
597
|
+
guildPresences: 1 << 8,
|
|
598
|
+
guildMessages: 1 << 9,
|
|
599
|
+
guildMessage: 1 << 9,
|
|
600
|
+
guildMessageReactions: 1 << 10,
|
|
601
|
+
guildMessageTyping: 1 << 11,
|
|
602
|
+
directMessages: 1 << 12,
|
|
603
|
+
directMessageReactions: 1 << 13,
|
|
604
|
+
directMessageTyping: 1 << 14,
|
|
605
|
+
messageContent: 1 << 15,
|
|
606
|
+
guildScheduledEvents: 1 << 16,
|
|
607
|
+
autoModerationConfiguration: 1 << 20,
|
|
608
|
+
autoModerationExecution: 1 << 21,
|
|
609
|
+
guildMessagePolls: 1 << 24,
|
|
610
|
+
directMessagePolls: 1 << 25
|
|
611
|
+
};
|
|
612
|
+
var Intents = IntentBits;
|
|
613
|
+
function resolveGatewayIntents(intents) {
|
|
614
|
+
if (typeof intents === "number")
|
|
615
|
+
return intents;
|
|
616
|
+
if (Array.isArray(intents)) {
|
|
617
|
+
return intents.reduce((acc, intent) => {
|
|
618
|
+
return acc | resolveGatewayIntents(intent);
|
|
619
|
+
}, 0);
|
|
620
|
+
}
|
|
621
|
+
if (typeof intents === "string") {
|
|
622
|
+
if (intents in GatewayIntentBits)
|
|
623
|
+
return GatewayIntentBits[intents];
|
|
624
|
+
if (intents in IntentBits)
|
|
625
|
+
return IntentBits[intents];
|
|
626
|
+
const lower = intents.charAt(0).toLowerCase() + intents.slice(1);
|
|
627
|
+
if (lower in IntentBits)
|
|
628
|
+
return IntentBits[lower];
|
|
629
|
+
const num = Number(intents);
|
|
630
|
+
if (!Number.isNaN(num))
|
|
631
|
+
return num;
|
|
632
|
+
}
|
|
633
|
+
return 0;
|
|
634
|
+
}
|
|
635
|
+
var InteractionResponseType = {
|
|
636
|
+
Pong: 1,
|
|
637
|
+
ChannelMessage: 4,
|
|
638
|
+
DeferredChannelMessage: 5,
|
|
639
|
+
DeferredMessageUpdate: 6,
|
|
640
|
+
MessageUpdate: 7,
|
|
641
|
+
Autocomplete: 8,
|
|
642
|
+
Modal: 9
|
|
643
|
+
};
|
|
423
644
|
// packages/collection/src/index.ts
|
|
424
645
|
class Collection extends Map {
|
|
425
646
|
first() {
|
|
@@ -544,6 +765,97 @@ class Collection extends Map {
|
|
|
544
765
|
entry = [item[0], item[1]];
|
|
545
766
|
return entry;
|
|
546
767
|
}
|
|
768
|
+
union(other) {
|
|
769
|
+
const result = this.clone();
|
|
770
|
+
for (const [key, value] of other)
|
|
771
|
+
result.set(key, value);
|
|
772
|
+
return result;
|
|
773
|
+
}
|
|
774
|
+
intersection(other) {
|
|
775
|
+
const result = new Collection;
|
|
776
|
+
for (const [key, value] of this) {
|
|
777
|
+
if (other.has(key))
|
|
778
|
+
result.set(key, value);
|
|
779
|
+
}
|
|
780
|
+
return result;
|
|
781
|
+
}
|
|
782
|
+
difference(other) {
|
|
783
|
+
const result = new Collection;
|
|
784
|
+
for (const [key, value] of this) {
|
|
785
|
+
if (!other.has(key))
|
|
786
|
+
result.set(key, value);
|
|
787
|
+
}
|
|
788
|
+
return result;
|
|
789
|
+
}
|
|
790
|
+
partition(predicate) {
|
|
791
|
+
const pass = new Collection;
|
|
792
|
+
const fail = new Collection;
|
|
793
|
+
for (const [key, value] of this) {
|
|
794
|
+
if (predicate(value, key, this))
|
|
795
|
+
pass.set(key, value);
|
|
796
|
+
else
|
|
797
|
+
fail.set(key, value);
|
|
798
|
+
}
|
|
799
|
+
return [pass, fail];
|
|
800
|
+
}
|
|
801
|
+
tap(fn) {
|
|
802
|
+
fn(this);
|
|
803
|
+
return this;
|
|
804
|
+
}
|
|
805
|
+
flatMap(transform) {
|
|
806
|
+
const result = [];
|
|
807
|
+
for (const [key, value] of this) {
|
|
808
|
+
for (const item of transform(value, key, this))
|
|
809
|
+
result.push(item);
|
|
810
|
+
}
|
|
811
|
+
return result;
|
|
812
|
+
}
|
|
813
|
+
reduce(fn, initialValue) {
|
|
814
|
+
let acc = initialValue;
|
|
815
|
+
for (const [key, value] of this)
|
|
816
|
+
acc = fn(acc, value, key, this);
|
|
817
|
+
return acc;
|
|
818
|
+
}
|
|
819
|
+
sorted(comparator) {
|
|
820
|
+
const decorated = [...this.entries()].map((entry, index) => ({
|
|
821
|
+
entry,
|
|
822
|
+
index
|
|
823
|
+
}));
|
|
824
|
+
if (comparator)
|
|
825
|
+
decorated.sort((x, y) => {
|
|
826
|
+
const comparison = comparator(x.entry[1], y.entry[1], x.entry[0], y.entry[0]);
|
|
827
|
+
return comparison !== 0 ? comparison : x.index - y.index;
|
|
828
|
+
});
|
|
829
|
+
const result = new Collection;
|
|
830
|
+
for (const { entry } of decorated)
|
|
831
|
+
result.set(entry[0], entry[1]);
|
|
832
|
+
return result;
|
|
833
|
+
}
|
|
834
|
+
random() {
|
|
835
|
+
const arr = [...this.values()];
|
|
836
|
+
if (!arr.length)
|
|
837
|
+
return;
|
|
838
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
839
|
+
}
|
|
840
|
+
randomKey() {
|
|
841
|
+
const arr = [...this.keys()];
|
|
842
|
+
if (!arr.length)
|
|
843
|
+
return;
|
|
844
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
845
|
+
}
|
|
846
|
+
at(index) {
|
|
847
|
+
const arr = [...this.values()];
|
|
848
|
+
const i = index < 0 ? arr.length + index : index;
|
|
849
|
+
return arr[i];
|
|
850
|
+
}
|
|
851
|
+
keyAt(index) {
|
|
852
|
+
const arr = [...this.keys()];
|
|
853
|
+
const i = index < 0 ? arr.length + index : index;
|
|
854
|
+
return arr[i];
|
|
855
|
+
}
|
|
856
|
+
toJSON() {
|
|
857
|
+
return [...this.entries()];
|
|
858
|
+
}
|
|
547
859
|
}
|
|
548
860
|
|
|
549
861
|
// packages/managers/src/base.ts
|
|
@@ -612,11 +924,66 @@ class ResourceManager extends Manager {
|
|
|
612
924
|
return this.upsert(resource);
|
|
613
925
|
}
|
|
614
926
|
}
|
|
927
|
+
// packages/rest/package.json
|
|
928
|
+
var package_default = {
|
|
929
|
+
name: "@lunibee/rest",
|
|
930
|
+
version: "0.1.7",
|
|
931
|
+
type: "module",
|
|
932
|
+
module: "./src/index.ts",
|
|
933
|
+
types: "./src/index.ts",
|
|
934
|
+
exports: {
|
|
935
|
+
".": "./src/index.ts"
|
|
936
|
+
}
|
|
937
|
+
};
|
|
938
|
+
|
|
939
|
+
// packages/rest/src/store.ts
|
|
940
|
+
class MemoryRateLimitStore {
|
|
941
|
+
#buckets = new Map;
|
|
942
|
+
#routeBuckets = new Map;
|
|
943
|
+
#globalResetAt = 0;
|
|
944
|
+
static #PRUNE_INTERVAL = 60000;
|
|
945
|
+
#lastPruneAt = 0;
|
|
946
|
+
getBucketHash(route) {
|
|
947
|
+
return this.#routeBuckets.get(route);
|
|
948
|
+
}
|
|
949
|
+
setBucketHash(route, hash) {
|
|
950
|
+
this.#routeBuckets.set(route, hash);
|
|
951
|
+
}
|
|
952
|
+
getBucket(key) {
|
|
953
|
+
return this.#buckets.get(key);
|
|
954
|
+
}
|
|
955
|
+
updateBucket(key, state) {
|
|
956
|
+
this.#buckets.set(key, state);
|
|
957
|
+
const now = Date.now();
|
|
958
|
+
if (now - this.#lastPruneAt >= MemoryRateLimitStore.#PRUNE_INTERVAL) {
|
|
959
|
+
this.#lastPruneAt = now;
|
|
960
|
+
this.prune();
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
prune(maxAge = 0) {
|
|
964
|
+
const cutoff = Date.now() - Math.max(0, maxAge);
|
|
965
|
+
for (const [key, state] of this.#buckets) {
|
|
966
|
+
if (state.resetAt <= cutoff)
|
|
967
|
+
this.#buckets.delete(key);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
getGlobalReset() {
|
|
971
|
+
return this.#globalResetAt;
|
|
972
|
+
}
|
|
973
|
+
setGlobalReset(resetAt) {
|
|
974
|
+
this.#globalResetAt = resetAt;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
615
978
|
// packages/rest/src/routes.ts
|
|
616
979
|
var Routes = {
|
|
617
980
|
user: () => "/users/@me",
|
|
618
981
|
userById: (userId) => `/users/${snowflake(userId, "User ID")}`,
|
|
619
982
|
guild: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}`,
|
|
983
|
+
guildPreview: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/preview`,
|
|
984
|
+
guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
|
|
985
|
+
guildWebhooks: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/webhooks`,
|
|
986
|
+
guildInvites: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/invites`,
|
|
620
987
|
guildChannels: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/channels`,
|
|
621
988
|
guildMember: (guildId, userId) => `/guilds/${snowflake(guildId, "Guild ID")}/members/${snowflake(userId, "User ID")}`,
|
|
622
989
|
guildRoles: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/roles`,
|
|
@@ -644,7 +1011,6 @@ var Routes = {
|
|
|
644
1011
|
guildApplicationCommand: (applicationId, guildId, commandId) => `/applications/${snowflake(applicationId, "Application ID")}/guilds/${snowflake(guildId, "Guild ID")}/commands/${snowflake(commandId, "Command ID")}`,
|
|
645
1012
|
interactionCallback: (interactionId, token) => `/interactions/${snowflake(interactionId, "Interaction ID")}/${encodeURIComponent(token)}/callback`,
|
|
646
1013
|
interactionOriginalResponse: (applicationId, token) => `/webhooks/${snowflake(applicationId, "Application ID")}/${encodeURIComponent(token)}/messages/@original`,
|
|
647
|
-
guildActiveThreads: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/threads/active`,
|
|
648
1014
|
channelPublicArchivedThreads: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/threads/archived/public`,
|
|
649
1015
|
channelPrivateArchivedThreads: (channelId) => `/channels/${snowflake(channelId, "Channel ID")}/threads/archived/private`,
|
|
650
1016
|
threadMembers: (threadId) => `/channels/${snowflake(threadId, "Thread ID")}/thread-members`,
|
|
@@ -654,7 +1020,18 @@ var Routes = {
|
|
|
654
1020
|
guildAutoModerationRule: (guildId, ruleId) => `/guilds/${snowflake(guildId, "Guild ID")}/auto-moderation/rules/${snowflake(ruleId, "Rule ID")}`,
|
|
655
1021
|
voiceRegions: () => "/voice/regions",
|
|
656
1022
|
gateway: () => "/gateway",
|
|
657
|
-
gatewayBot: () => "/gateway/bot"
|
|
1023
|
+
gatewayBot: () => "/gateway/bot",
|
|
1024
|
+
guildAuditLog: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/audit-logs`,
|
|
1025
|
+
guildMembers: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/members`,
|
|
1026
|
+
guildWelcomeScreen: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/welcome-screen`,
|
|
1027
|
+
guildOnboarding: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/onboarding`,
|
|
1028
|
+
guildPrune: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/prune`,
|
|
1029
|
+
stageInstances: () => "/stage-instances",
|
|
1030
|
+
stageInstanceByChannel: (channelId) => `/stage-instances/${snowflake(channelId, "Channel ID")}`,
|
|
1031
|
+
invite: (code) => `/invites/${encodeURIComponent(code)}`,
|
|
1032
|
+
guildVanity: (guildId) => `/guilds/${snowflake(guildId, "Guild ID")}/vanity-url`,
|
|
1033
|
+
guildEmoji: (guildId, emojiId) => emojiId ? `/guilds/${snowflake(guildId, "Guild ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/guilds/${snowflake(guildId, "Guild ID")}/emojis`,
|
|
1034
|
+
applicationEmoji: (applicationId, emojiId) => emojiId ? `/applications/${snowflake(applicationId, "Application ID")}/emojis/${snowflake(emojiId, "Emoji ID")}` : `/applications/${snowflake(applicationId, "Application ID")}/emojis`
|
|
658
1035
|
};
|
|
659
1036
|
function snowflake(value, field) {
|
|
660
1037
|
if (!/^\d{1,20}$/.test(value))
|
|
@@ -679,7 +1056,53 @@ class RESTError extends Error {
|
|
|
679
1056
|
this.path = options.path;
|
|
680
1057
|
}
|
|
681
1058
|
}
|
|
682
|
-
|
|
1059
|
+
var LIBRARY_VERSION = package_default.version;
|
|
1060
|
+
var LIBRARY_URL = "https://github.com/Ekretos/lunibee";
|
|
1061
|
+
var USER_AGENT = `DiscordBot (${LIBRARY_URL}, ${package_default.version})`;
|
|
1062
|
+
var REQUEST_DATA_KEYS = new Set([
|
|
1063
|
+
"body",
|
|
1064
|
+
"files",
|
|
1065
|
+
"query",
|
|
1066
|
+
"headers",
|
|
1067
|
+
"reason",
|
|
1068
|
+
"auth",
|
|
1069
|
+
"signal"
|
|
1070
|
+
]);
|
|
1071
|
+
function isRequestData(value) {
|
|
1072
|
+
if (value === null || typeof value !== "object")
|
|
1073
|
+
return false;
|
|
1074
|
+
if (Array.isArray(value))
|
|
1075
|
+
return false;
|
|
1076
|
+
if (typeof FormData !== "undefined" && value instanceof FormData)
|
|
1077
|
+
return false;
|
|
1078
|
+
if (value instanceof Blob || value instanceof Uint8Array || value instanceof ArrayBuffer)
|
|
1079
|
+
return false;
|
|
1080
|
+
const keys = Object.keys(value);
|
|
1081
|
+
if (keys.length === 0)
|
|
1082
|
+
return false;
|
|
1083
|
+
return keys.every((key) => REQUEST_DATA_KEYS.has(key));
|
|
1084
|
+
}
|
|
1085
|
+
function serializeQuery(query) {
|
|
1086
|
+
if (query === undefined)
|
|
1087
|
+
return "";
|
|
1088
|
+
if (typeof query === "string")
|
|
1089
|
+
return query.length === 0 || query.startsWith("?") ? query : `?${query}`;
|
|
1090
|
+
const params = query instanceof URLSearchParams ? query : new URLSearchParams(Object.entries(query).flatMap(([key, value]) => value === undefined || value === null ? [] : [[key, String(value)]]));
|
|
1091
|
+
const serialized = params.toString();
|
|
1092
|
+
return serialized.length === 0 ? "" : `?${serialized}`;
|
|
1093
|
+
}
|
|
1094
|
+
function majorParameter(path) {
|
|
1095
|
+
const match = /^\/(channels|guilds|webhooks)\/(\d+)(?:\/([^/?]+))?/.exec(path);
|
|
1096
|
+
if (!match)
|
|
1097
|
+
return "@none";
|
|
1098
|
+
if (match[1] === "webhooks" && match[3] !== undefined)
|
|
1099
|
+
return `${match[2]}:${match[3]}`;
|
|
1100
|
+
return match[2];
|
|
1101
|
+
}
|
|
1102
|
+
function scopeBucket(hashOrRoute, major) {
|
|
1103
|
+
return `${hashOrRoute}|${major}`;
|
|
1104
|
+
}
|
|
1105
|
+
function createRetryPolicy(maxRetries = 2) {
|
|
683
1106
|
if (!Number.isFinite(maxRetries) || maxRetries < 0)
|
|
684
1107
|
throw new TypeError("maxRetries must be a non-negative finite number.");
|
|
685
1108
|
return {
|
|
@@ -701,14 +1124,21 @@ class REST {
|
|
|
701
1124
|
#timeout;
|
|
702
1125
|
#retryPolicy;
|
|
703
1126
|
#token;
|
|
704
|
-
#
|
|
705
|
-
#
|
|
706
|
-
#
|
|
1127
|
+
#store;
|
|
1128
|
+
#localQueues = new Map;
|
|
1129
|
+
#hooks = {};
|
|
707
1130
|
constructor(options = {}) {
|
|
708
1131
|
this.#token = options.token;
|
|
709
1132
|
this.#timeout = Math.max(1, options.timeout ?? 15000);
|
|
710
1133
|
this.#retryPolicy = options.retryPolicy ?? createRetryPolicy(options.retries ?? 2);
|
|
711
1134
|
this.#baseURL = (options.baseURL ?? "https://discord.com/api/v10").replace(/\/$/, "");
|
|
1135
|
+
this.#store = options.store ?? new MemoryRateLimitStore;
|
|
1136
|
+
if (options.hooks)
|
|
1137
|
+
this.#hooks = options.hooks;
|
|
1138
|
+
}
|
|
1139
|
+
setHooks(hooks) {
|
|
1140
|
+
this.#hooks = hooks;
|
|
1141
|
+
return this;
|
|
712
1142
|
}
|
|
713
1143
|
setToken(token) {
|
|
714
1144
|
if (!token.trim())
|
|
@@ -721,52 +1151,91 @@ class REST {
|
|
|
721
1151
|
throw new TypeError("REST method is required.");
|
|
722
1152
|
if (!path.startsWith("/"))
|
|
723
1153
|
throw new TypeError("REST paths must start with '/'.");
|
|
1154
|
+
const files = options.files;
|
|
1155
|
+
if (files && files.length > 0 && !(body instanceof FormData))
|
|
1156
|
+
body = this.#fileForm(body, files);
|
|
1157
|
+
const query = serializeQuery(options.query);
|
|
1158
|
+
const finalPath = query ? `${path}${query}` : path;
|
|
724
1159
|
const route = `${normalizedMethod}:${this.#normalizeRoute(path)}`;
|
|
725
|
-
|
|
726
|
-
let
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
queue: Promise.resolve()
|
|
730
|
-
};
|
|
731
|
-
this.#buckets.set(bucketKey, bucket);
|
|
732
|
-
const previous = bucket.queue;
|
|
1160
|
+
const major = majorParameter(path);
|
|
1161
|
+
let bucketKey = scopeBucket(await this.#store.getBucketHash(route) ?? route, major);
|
|
1162
|
+
const queueKey = bucketKey;
|
|
1163
|
+
const previous = this.#localQueues.get(queueKey) ?? Promise.resolve();
|
|
733
1164
|
let release;
|
|
734
|
-
|
|
1165
|
+
const gate = new Promise((resolve) => {
|
|
735
1166
|
release = resolve;
|
|
736
1167
|
});
|
|
1168
|
+
this.#localQueues.set(queueKey, gate);
|
|
737
1169
|
await this.#abortable(previous, options.signal, path);
|
|
738
1170
|
try {
|
|
739
1171
|
for (let attempt = 0;attempt <= this.#retryPolicy.maxRetries; attempt++) {
|
|
740
|
-
await this.#wait(
|
|
1172
|
+
await this.#wait(bucketKey, options.signal, path);
|
|
741
1173
|
await this.#waitGlobal(options.signal, path);
|
|
742
1174
|
const controller = new AbortController;
|
|
743
1175
|
const onAbort = () => controller.abort(options.signal?.reason);
|
|
744
1176
|
if (options.signal?.aborted)
|
|
745
1177
|
throw this.#abortError(path, options.signal.reason);
|
|
746
|
-
options.signal?.addEventListener("abort", onAbort, {
|
|
1178
|
+
options.signal?.addEventListener("abort", onAbort, {
|
|
1179
|
+
once: true
|
|
1180
|
+
});
|
|
747
1181
|
const timer = setTimeout(() => controller.abort(new DOMException("REST request timeout", "TimeoutError")), this.#timeout);
|
|
1182
|
+
const isFormData = typeof FormData !== "undefined" && body instanceof FormData;
|
|
1183
|
+
const headers = { ...options.headers };
|
|
1184
|
+
if (options.auth !== false && this.#token)
|
|
1185
|
+
headers["Authorization"] = `Bot ${this.#token}`;
|
|
1186
|
+
headers["User-Agent"] = USER_AGENT;
|
|
1187
|
+
if (options.reason !== undefined)
|
|
1188
|
+
headers["X-Audit-Log-Reason"] = encodeURIComponent(options.reason);
|
|
1189
|
+
if (!isFormData)
|
|
1190
|
+
headers["Content-Type"] = "application/json";
|
|
1191
|
+
const fetchBody = isFormData ? body : body === undefined ? undefined : JSON.stringify(body);
|
|
748
1192
|
try {
|
|
749
|
-
|
|
1193
|
+
this.#emit(this.#hooks.onRequest, {
|
|
1194
|
+
method: normalizedMethod,
|
|
1195
|
+
path,
|
|
1196
|
+
attempt
|
|
1197
|
+
});
|
|
1198
|
+
const requestStart = Date.now();
|
|
1199
|
+
const response = await fetch(`${this.#baseURL}${finalPath}`, {
|
|
750
1200
|
method: normalizedMethod,
|
|
751
|
-
headers
|
|
752
|
-
|
|
753
|
-
"Content-Type": "application/json",
|
|
754
|
-
"User-Agent": "Lunibee/0.1.0"
|
|
755
|
-
},
|
|
756
|
-
body: body === undefined ? undefined : JSON.stringify(body),
|
|
1201
|
+
headers,
|
|
1202
|
+
body: fetchBody,
|
|
757
1203
|
signal: controller.signal
|
|
758
1204
|
});
|
|
759
|
-
|
|
760
|
-
|
|
1205
|
+
this.#emit(this.#hooks.onResponse, {
|
|
1206
|
+
method: normalizedMethod,
|
|
1207
|
+
path,
|
|
1208
|
+
status: response.status,
|
|
1209
|
+
durationMs: Date.now() - requestStart
|
|
1210
|
+
});
|
|
1211
|
+
bucketKey = await this.#update(response, bucketKey, route, major);
|
|
761
1212
|
const payload = await this.#readPayload(response);
|
|
762
1213
|
if (response.ok)
|
|
763
1214
|
return response.status === 204 ? undefined : payload;
|
|
764
1215
|
const data = this.#errorData(payload);
|
|
765
1216
|
const retryAfter = response.status === 429 ? this.#retryAfter(response, data) : undefined;
|
|
766
|
-
if (data.global && retryAfter !== undefined)
|
|
767
|
-
|
|
1217
|
+
if (data.global && retryAfter !== undefined) {
|
|
1218
|
+
const currentGlobal = await this.#store.getGlobalReset();
|
|
1219
|
+
await this.#store.setGlobalReset(Math.max(currentGlobal, Date.now() + retryAfter * 1000));
|
|
1220
|
+
}
|
|
1221
|
+
if (response.status === 429)
|
|
1222
|
+
this.#emit(this.#hooks.onRateLimit, {
|
|
1223
|
+
method: normalizedMethod,
|
|
1224
|
+
path,
|
|
1225
|
+
retryAfterMs: (retryAfter ?? 1) * 1000,
|
|
1226
|
+
global: data.global ?? false,
|
|
1227
|
+
bucket: await this.#store.getBucketHash(route)
|
|
1228
|
+
});
|
|
768
1229
|
if (attempt < this.#retryPolicy.maxRetries && this.#retryPolicy.shouldRetry(normalizedMethod, response.status)) {
|
|
769
|
-
|
|
1230
|
+
const delay = this.#retryPolicy.getDelay(attempt, retryAfter);
|
|
1231
|
+
this.#emit(this.#hooks.onRetry, {
|
|
1232
|
+
method: normalizedMethod,
|
|
1233
|
+
path,
|
|
1234
|
+
attempt,
|
|
1235
|
+
status: response.status,
|
|
1236
|
+
delayMs: delay
|
|
1237
|
+
});
|
|
1238
|
+
await this.#sleep(delay, options.signal, path);
|
|
770
1239
|
continue;
|
|
771
1240
|
}
|
|
772
1241
|
throw new RESTError(data.message ?? response.statusText ?? `Discord REST request failed with status ${response.status}`, response.status, data.code, payload, { method: normalizedMethod, path });
|
|
@@ -789,30 +1258,64 @@ class REST {
|
|
|
789
1258
|
throw new RESTError("Discord REST request exhausted its retry attempts", 0, undefined, undefined, { method: normalizedMethod, path });
|
|
790
1259
|
} finally {
|
|
791
1260
|
release();
|
|
1261
|
+
if (this.#localQueues.get(queueKey) === gate)
|
|
1262
|
+
this.#localQueues.delete(queueKey);
|
|
792
1263
|
}
|
|
793
1264
|
}
|
|
1265
|
+
#dispatch(method, path, bodyOrOptions, options) {
|
|
1266
|
+
if (options === undefined && isRequestData(bodyOrOptions))
|
|
1267
|
+
return this.request(method, path, bodyOrOptions.body, bodyOrOptions);
|
|
1268
|
+
return this.request(method, path, bodyOrOptions, options);
|
|
1269
|
+
}
|
|
794
1270
|
get(path, options) {
|
|
795
|
-
return this.request("GET", path,
|
|
1271
|
+
return this.request("GET", path, options?.body, options);
|
|
796
1272
|
}
|
|
797
1273
|
post(path, body, options) {
|
|
798
|
-
return this
|
|
1274
|
+
return this.#dispatch("POST", path, body, options);
|
|
799
1275
|
}
|
|
800
1276
|
patch(path, body, options) {
|
|
801
|
-
return this
|
|
1277
|
+
return this.#dispatch("PATCH", path, body, options);
|
|
802
1278
|
}
|
|
803
1279
|
put(path, body, options) {
|
|
804
|
-
return this
|
|
1280
|
+
return this.#dispatch("PUT", path, body, options);
|
|
805
1281
|
}
|
|
806
1282
|
delete(path, options) {
|
|
807
|
-
return this.request("DELETE", path,
|
|
1283
|
+
return this.request("DELETE", path, options?.body, options);
|
|
1284
|
+
}
|
|
1285
|
+
#fileForm(payload, files) {
|
|
1286
|
+
const form = new FormData;
|
|
1287
|
+
form.append("payload_json", JSON.stringify(payload));
|
|
1288
|
+
for (let i = 0;i < files.length; i++) {
|
|
1289
|
+
const file = files[i];
|
|
1290
|
+
const blob = file.data instanceof Blob ? file.data : new Blob([file.data], {
|
|
1291
|
+
type: file.contentType ?? "application/octet-stream"
|
|
1292
|
+
});
|
|
1293
|
+
form.append(`files[${i}]`, blob, file.name);
|
|
1294
|
+
}
|
|
1295
|
+
return form;
|
|
1296
|
+
}
|
|
1297
|
+
postWithFiles(path, payload, files, options) {
|
|
1298
|
+
return this.request("POST", path, this.#fileForm(payload, files), options);
|
|
1299
|
+
}
|
|
1300
|
+
patchWithFiles(path, payload, files, options) {
|
|
1301
|
+
return this.request("PATCH", path, this.#fileForm(payload, files), options);
|
|
1302
|
+
}
|
|
1303
|
+
#emit(hook, ctx) {
|
|
1304
|
+
if (!hook)
|
|
1305
|
+
return;
|
|
1306
|
+
Promise.resolve().then(() => hook(ctx)).catch(() => {});
|
|
808
1307
|
}
|
|
809
|
-
async#wait(
|
|
1308
|
+
async#wait(bucketKey, signal, path) {
|
|
1309
|
+
const bucket = await this.#store.getBucket(bucketKey);
|
|
1310
|
+
if (!bucket)
|
|
1311
|
+
return;
|
|
810
1312
|
const delay = bucket.resetAt - Date.now();
|
|
811
1313
|
if (bucket.remaining <= 0 && delay > 0)
|
|
812
1314
|
await this.#sleep(delay, signal, path);
|
|
813
1315
|
}
|
|
814
1316
|
async#waitGlobal(signal, path) {
|
|
815
|
-
const
|
|
1317
|
+
const globalResetAt = await this.#store.getGlobalReset();
|
|
1318
|
+
const delay = globalResetAt - Date.now();
|
|
816
1319
|
if (delay > 0)
|
|
817
1320
|
await this.#sleep(delay, signal, path);
|
|
818
1321
|
}
|
|
@@ -876,16 +1379,17 @@ class REST {
|
|
|
876
1379
|
const routePath = queryIndex === -1 ? path : path.slice(0, queryIndex);
|
|
877
1380
|
return routePath.replace(/\/\d+(?=\/|$)/g, "/:id");
|
|
878
1381
|
}
|
|
879
|
-
#update(response,
|
|
1382
|
+
async#update(response, bucketKey, route, major) {
|
|
1383
|
+
let currentKey = bucketKey;
|
|
880
1384
|
const serverBucket = response.headers.get("X-RateLimit-Bucket");
|
|
881
1385
|
if (serverBucket) {
|
|
882
|
-
this.#
|
|
883
|
-
|
|
884
|
-
const shared = this.#buckets.get(serverBucket) ?? bucket;
|
|
885
|
-
this.#buckets.set(serverBucket, shared);
|
|
886
|
-
bucket = shared;
|
|
887
|
-
}
|
|
1386
|
+
await this.#store.setBucketHash(route, serverBucket);
|
|
1387
|
+
currentKey = scopeBucket(serverBucket, major);
|
|
888
1388
|
}
|
|
1389
|
+
let bucket = await this.#store.getBucket(currentKey) ?? {
|
|
1390
|
+
remaining: 1,
|
|
1391
|
+
resetAt: 0
|
|
1392
|
+
};
|
|
889
1393
|
const remaining = Number(response.headers.get("X-RateLimit-Remaining"));
|
|
890
1394
|
const resetAfter = Number(response.headers.get("X-RateLimit-Reset-After"));
|
|
891
1395
|
const reset = Number(response.headers.get("X-RateLimit-Reset"));
|
|
@@ -900,12 +1404,15 @@ class REST {
|
|
|
900
1404
|
if (Number.isFinite(retryAfter))
|
|
901
1405
|
bucket.resetAt = Math.max(bucket.resetAt, Date.now() + retryAfter * 1000);
|
|
902
1406
|
}
|
|
1407
|
+
await this.#store.updateBucket(currentKey, bucket);
|
|
903
1408
|
if (response.headers.get("X-RateLimit-Global") === "true") {
|
|
904
1409
|
const retryAfter = Number(response.headers.get("Retry-After"));
|
|
905
|
-
if (Number.isFinite(retryAfter))
|
|
906
|
-
|
|
1410
|
+
if (Number.isFinite(retryAfter)) {
|
|
1411
|
+
const currentGlobal = await this.#store.getGlobalReset();
|
|
1412
|
+
await this.#store.setGlobalReset(Math.max(currentGlobal, Date.now() + retryAfter * 1000));
|
|
1413
|
+
}
|
|
907
1414
|
}
|
|
908
|
-
return
|
|
1415
|
+
return currentKey;
|
|
909
1416
|
}
|
|
910
1417
|
}
|
|
911
1418
|
|
|
@@ -920,6 +1427,16 @@ class BaseStructure {
|
|
|
920
1427
|
toString() {
|
|
921
1428
|
return this.id;
|
|
922
1429
|
}
|
|
1430
|
+
get createdAt() {
|
|
1431
|
+
return new Date(Number((BigInt(this.id) >> 22n) + 1420070400000n));
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
var CDN_BASE = "https://cdn.discordapp.com";
|
|
1435
|
+
function cdnURL(path, hash, options = {}) {
|
|
1436
|
+
const isAnimated = hash.startsWith("a_") && !options.forceStatic;
|
|
1437
|
+
const ext = options.extension ?? (isAnimated ? "gif" : "png");
|
|
1438
|
+
const size = options.size ? `?size=${options.size}` : "";
|
|
1439
|
+
return `${CDN_BASE}${path}/${hash}.${ext}${size}`;
|
|
923
1440
|
}
|
|
924
1441
|
|
|
925
1442
|
class User extends BaseStructure {
|
|
@@ -929,6 +1446,7 @@ class User extends BaseStructure {
|
|
|
929
1446
|
bot;
|
|
930
1447
|
system;
|
|
931
1448
|
flags;
|
|
1449
|
+
discriminator;
|
|
932
1450
|
constructor(data) {
|
|
933
1451
|
super(data.id);
|
|
934
1452
|
if (!data.username)
|
|
@@ -939,6 +1457,7 @@ class User extends BaseStructure {
|
|
|
939
1457
|
this.bot = data.bot ?? false;
|
|
940
1458
|
this.system = data.system ?? false;
|
|
941
1459
|
this.flags = data.public_flags ?? 0;
|
|
1460
|
+
this.discriminator = data.discriminator && data.discriminator !== "0" ? data.discriminator : null;
|
|
942
1461
|
}
|
|
943
1462
|
get displayName() {
|
|
944
1463
|
return this.globalName ?? this.username;
|
|
@@ -946,21 +1465,29 @@ class User extends BaseStructure {
|
|
|
946
1465
|
avatarURL(options = {}) {
|
|
947
1466
|
if (!this.avatar)
|
|
948
1467
|
return null;
|
|
949
|
-
|
|
950
|
-
return `https://cdn.discordapp.com/avatars/${this.id}/${this.avatar}.${extension}${options.size ? `?size=${options.size}` : ""}`;
|
|
1468
|
+
return cdnURL(`/avatars/${this.id}`, this.avatar, options);
|
|
951
1469
|
}
|
|
952
1470
|
defaultAvatarURL() {
|
|
953
|
-
|
|
1471
|
+
const index = this.discriminator ? Number(this.discriminator) % 5 : Number((BigInt(this.id) >> 22n) % 6n);
|
|
1472
|
+
return `${CDN_BASE}/embed/avatars/${index}.png`;
|
|
954
1473
|
}
|
|
955
1474
|
displayAvatarURL(options = {}) {
|
|
956
1475
|
return this.avatarURL(options) ?? this.defaultAvatarURL();
|
|
957
1476
|
}
|
|
1477
|
+
toString() {
|
|
1478
|
+
return `<@${this.id}>`;
|
|
1479
|
+
}
|
|
958
1480
|
}
|
|
959
1481
|
|
|
960
1482
|
class Channel extends BaseStructure {
|
|
961
1483
|
type;
|
|
962
1484
|
name;
|
|
963
1485
|
guildId;
|
|
1486
|
+
topic;
|
|
1487
|
+
parentId;
|
|
1488
|
+
nsfw;
|
|
1489
|
+
rateLimitPerUser;
|
|
1490
|
+
position;
|
|
964
1491
|
#context;
|
|
965
1492
|
constructor(data, context) {
|
|
966
1493
|
super(data.id);
|
|
@@ -969,6 +1496,11 @@ class Channel extends BaseStructure {
|
|
|
969
1496
|
this.type = data.type;
|
|
970
1497
|
this.name = data.name;
|
|
971
1498
|
this.guildId = data.guild_id;
|
|
1499
|
+
this.topic = data.topic;
|
|
1500
|
+
this.parentId = data.parent_id;
|
|
1501
|
+
this.nsfw = data.nsfw;
|
|
1502
|
+
this.rateLimitPerUser = data.rate_limit_per_user;
|
|
1503
|
+
this.position = data.position;
|
|
972
1504
|
this.#context = context;
|
|
973
1505
|
}
|
|
974
1506
|
sendMessage(options) {
|
|
@@ -976,73 +1508,187 @@ class Channel extends BaseStructure {
|
|
|
976
1508
|
throw new Error("This channel is not attached to a client.");
|
|
977
1509
|
return this.#context.sendMessage(this.id, options);
|
|
978
1510
|
}
|
|
1511
|
+
send(options) {
|
|
1512
|
+
return this.sendMessage(options);
|
|
1513
|
+
}
|
|
1514
|
+
edit(options) {
|
|
1515
|
+
if (!this.#context?.editChannel)
|
|
1516
|
+
throw new Error("This channel is not attached to a client.");
|
|
1517
|
+
return this.#context.editChannel(this.id, options);
|
|
1518
|
+
}
|
|
1519
|
+
editName(name) {
|
|
1520
|
+
if (!name.trim())
|
|
1521
|
+
throw new TypeError("Channel name cannot be empty.");
|
|
1522
|
+
return this.edit({ name });
|
|
1523
|
+
}
|
|
1524
|
+
editTopic(topic) {
|
|
1525
|
+
return this.edit({ topic });
|
|
1526
|
+
}
|
|
1527
|
+
editParent(parentId) {
|
|
1528
|
+
return this.edit({ parent_id: parentId });
|
|
1529
|
+
}
|
|
1530
|
+
delete() {
|
|
1531
|
+
if (!this.#context?.deleteChannel)
|
|
1532
|
+
throw new Error("This channel is not attached to a client.");
|
|
1533
|
+
return this.#context.deleteChannel(this.id);
|
|
1534
|
+
}
|
|
1535
|
+
update(options) {
|
|
1536
|
+
return this.edit(options);
|
|
1537
|
+
}
|
|
1538
|
+
toString() {
|
|
1539
|
+
return `<#${this.id}>`;
|
|
1540
|
+
}
|
|
979
1541
|
}
|
|
980
1542
|
|
|
981
1543
|
class Guild extends BaseStructure {
|
|
982
1544
|
name;
|
|
1545
|
+
icon;
|
|
1546
|
+
splash;
|
|
1547
|
+
banner;
|
|
1548
|
+
description;
|
|
983
1549
|
preferredLocale;
|
|
984
1550
|
ownerId;
|
|
1551
|
+
features;
|
|
1552
|
+
verificationLevel;
|
|
1553
|
+
premiumTier;
|
|
1554
|
+
premiumSubscriptionCount;
|
|
1555
|
+
memberCount;
|
|
1556
|
+
approximateMemberCount;
|
|
1557
|
+
approximatePresenceCount;
|
|
1558
|
+
vanityUrlCode;
|
|
1559
|
+
nsfwLevel;
|
|
1560
|
+
discoverySplash;
|
|
1561
|
+
rulesChannelId;
|
|
1562
|
+
systemChannelId;
|
|
1563
|
+
systemChannelFlags;
|
|
1564
|
+
maxMembers;
|
|
1565
|
+
mfaLevel;
|
|
1566
|
+
explicitContentFilter;
|
|
1567
|
+
defaultMessageNotifications;
|
|
985
1568
|
constructor(data) {
|
|
986
1569
|
super(data.id);
|
|
987
1570
|
if (!data.name)
|
|
988
1571
|
throw new TypeError("A Discord guild requires a name.");
|
|
989
1572
|
this.name = data.name;
|
|
990
|
-
this.
|
|
1573
|
+
this.icon = data.icon ?? null;
|
|
1574
|
+
this.splash = data.splash ?? null;
|
|
1575
|
+
this.banner = data.banner ?? null;
|
|
1576
|
+
this.description = data.description ?? null;
|
|
1577
|
+
this.preferredLocale = data.preferred_locale ?? "en-US";
|
|
991
1578
|
this.ownerId = data.owner_id;
|
|
1579
|
+
this.features = data.features ?? [];
|
|
1580
|
+
this.verificationLevel = data.verification_level ?? 0;
|
|
1581
|
+
this.premiumTier = data.premium_tier ?? 0;
|
|
1582
|
+
this.premiumSubscriptionCount = data.premium_subscription_count ?? 0;
|
|
1583
|
+
this.memberCount = data.member_count ?? data.approximate_member_count;
|
|
1584
|
+
this.approximateMemberCount = data.approximate_member_count;
|
|
1585
|
+
this.approximatePresenceCount = data.approximate_presence_count;
|
|
1586
|
+
this.vanityUrlCode = data.vanity_url_code ?? null;
|
|
1587
|
+
this.nsfwLevel = data.nsfw_level ?? 0;
|
|
1588
|
+
this.discoverySplash = data.discovery_splash ?? null;
|
|
1589
|
+
const d = data;
|
|
1590
|
+
this.rulesChannelId = d.rules_channel_id ?? null;
|
|
1591
|
+
this.systemChannelId = d.system_channel_id ?? null;
|
|
1592
|
+
this.systemChannelFlags = d.system_channel_flags ?? 0;
|
|
1593
|
+
this.maxMembers = d.max_members ?? 0;
|
|
1594
|
+
this.mfaLevel = d.mfa_level ?? 0;
|
|
1595
|
+
this.explicitContentFilter = d.explicit_content_filter ?? 0;
|
|
1596
|
+
this.defaultMessageNotifications = d.default_message_notifications ?? 0;
|
|
1597
|
+
}
|
|
1598
|
+
iconURL(options = {}) {
|
|
1599
|
+
if (!this.icon)
|
|
1600
|
+
return null;
|
|
1601
|
+
return cdnURL(`/icons/${this.id}`, this.icon, options);
|
|
1602
|
+
}
|
|
1603
|
+
splashURL(options = {}) {
|
|
1604
|
+
if (!this.splash)
|
|
1605
|
+
return null;
|
|
1606
|
+
return cdnURL(`/splashes/${this.id}`, this.splash, options);
|
|
1607
|
+
}
|
|
1608
|
+
bannerURL(options = {}) {
|
|
1609
|
+
if (!this.banner)
|
|
1610
|
+
return null;
|
|
1611
|
+
return cdnURL(`/banners/${this.id}`, this.banner, options);
|
|
1612
|
+
}
|
|
1613
|
+
discoverySplashURL(options = {}) {
|
|
1614
|
+
if (!this.discoverySplash)
|
|
1615
|
+
return null;
|
|
1616
|
+
return cdnURL(`/discovery-splashes/${this.id}`, this.discoverySplash, options);
|
|
1617
|
+
}
|
|
1618
|
+
widgetImageURL(style = "shield") {
|
|
1619
|
+
return `https://discord.com/api/guilds/${this.id}/widget.png?style=${style}`;
|
|
1620
|
+
}
|
|
1621
|
+
hasFeature(feature) {
|
|
1622
|
+
return this.features.includes(feature);
|
|
1623
|
+
}
|
|
1624
|
+
get isCommunity() {
|
|
1625
|
+
return this.hasFeature("COMMUNITY");
|
|
1626
|
+
}
|
|
1627
|
+
get isPartnered() {
|
|
1628
|
+
return this.hasFeature("PARTNERED");
|
|
1629
|
+
}
|
|
1630
|
+
get isVerified() {
|
|
1631
|
+
return this.hasFeature("VERIFIED");
|
|
1632
|
+
}
|
|
1633
|
+
get isBoosted() {
|
|
1634
|
+
return this.premiumSubscriptionCount > 0;
|
|
1635
|
+
}
|
|
1636
|
+
get boostLevel() {
|
|
1637
|
+
return this.premiumTier;
|
|
1638
|
+
}
|
|
1639
|
+
get hasVanityUrl() {
|
|
1640
|
+
return this.vanityUrlCode !== null;
|
|
1641
|
+
}
|
|
1642
|
+
get vanityURL() {
|
|
1643
|
+
return this.vanityUrlCode ? `https://discord.gg/${this.vanityUrlCode}` : null;
|
|
1644
|
+
}
|
|
1645
|
+
toString() {
|
|
1646
|
+
return this.name;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
// packages/structures/src/resources.ts
|
|
1650
|
+
class AutoModerationRule extends BaseStructure {
|
|
1651
|
+
guildId;
|
|
1652
|
+
name;
|
|
1653
|
+
creatorId;
|
|
1654
|
+
eventType;
|
|
1655
|
+
triggerType;
|
|
1656
|
+
triggerMetadata;
|
|
1657
|
+
actions;
|
|
1658
|
+
enabled;
|
|
1659
|
+
exemptRoles;
|
|
1660
|
+
exemptChannels;
|
|
1661
|
+
constructor(data) {
|
|
1662
|
+
super(data.id);
|
|
1663
|
+
if (!/^\d{1,20}$/.test(data.guild_id))
|
|
1664
|
+
throw new TypeError("AutoModerationRule guild_id must be a valid snowflake.");
|
|
1665
|
+
this.guildId = data.guild_id;
|
|
1666
|
+
this.name = data.name;
|
|
1667
|
+
this.creatorId = data.creator_id;
|
|
1668
|
+
this.eventType = data.event_type;
|
|
1669
|
+
this.triggerType = data.trigger_type;
|
|
1670
|
+
this.triggerMetadata = data.trigger_metadata;
|
|
1671
|
+
this.actions = data.actions;
|
|
1672
|
+
this.enabled = data.enabled;
|
|
1673
|
+
this.exemptRoles = data.exempt_roles;
|
|
1674
|
+
this.exemptChannels = data.exempt_channels;
|
|
1675
|
+
}
|
|
1676
|
+
toJSON() {
|
|
1677
|
+
return {
|
|
1678
|
+
id: this.id,
|
|
1679
|
+
guildId: this.guildId,
|
|
1680
|
+
name: this.name,
|
|
1681
|
+
creatorId: this.creatorId,
|
|
1682
|
+
eventType: this.eventType,
|
|
1683
|
+
triggerType: this.triggerType,
|
|
1684
|
+
triggerMetadata: this.triggerMetadata,
|
|
1685
|
+
actions: this.actions,
|
|
1686
|
+
enabled: this.enabled,
|
|
1687
|
+
exemptRoles: this.exemptRoles,
|
|
1688
|
+
exemptChannels: this.exemptChannels
|
|
1689
|
+
};
|
|
992
1690
|
}
|
|
993
1691
|
}
|
|
994
|
-
// packages/structures/src/permissions.ts
|
|
995
|
-
var Permissions2 = {
|
|
996
|
-
CreateInstantInvite: 1n << 0n,
|
|
997
|
-
KickMembers: 1n << 1n,
|
|
998
|
-
BanMembers: 1n << 2n,
|
|
999
|
-
Administrator: 1n << 3n,
|
|
1000
|
-
ManageChannels: 1n << 4n,
|
|
1001
|
-
ManageGuild: 1n << 5n,
|
|
1002
|
-
AddReactions: 1n << 6n,
|
|
1003
|
-
ViewAuditLog: 1n << 7n,
|
|
1004
|
-
PrioritySpeaker: 1n << 8n,
|
|
1005
|
-
Stream: 1n << 9n,
|
|
1006
|
-
ViewChannel: 1n << 10n,
|
|
1007
|
-
SendMessages: 1n << 11n,
|
|
1008
|
-
SendTTSMessages: 1n << 12n,
|
|
1009
|
-
ManageMessages: 1n << 13n,
|
|
1010
|
-
EmbedLinks: 1n << 14n,
|
|
1011
|
-
AttachFiles: 1n << 15n,
|
|
1012
|
-
ReadMessageHistory: 1n << 16n,
|
|
1013
|
-
MentionEveryone: 1n << 17n,
|
|
1014
|
-
UseExternalEmojis: 1n << 18n,
|
|
1015
|
-
ViewGuildInsights: 1n << 19n,
|
|
1016
|
-
Connect: 1n << 20n,
|
|
1017
|
-
Speak: 1n << 21n,
|
|
1018
|
-
MuteMembers: 1n << 22n,
|
|
1019
|
-
DeafenMembers: 1n << 23n,
|
|
1020
|
-
MoveMembers: 1n << 24n,
|
|
1021
|
-
UseVAD: 1n << 25n,
|
|
1022
|
-
ChangeNickname: 1n << 26n,
|
|
1023
|
-
ManageNicknames: 1n << 27n,
|
|
1024
|
-
ManageRoles: 1n << 28n,
|
|
1025
|
-
ManageWebhooks: 1n << 29n,
|
|
1026
|
-
ManageGuildExpressions: 1n << 30n,
|
|
1027
|
-
UseApplicationCommands: 1n << 31n,
|
|
1028
|
-
RequestToSpeak: 1n << 32n,
|
|
1029
|
-
ManageEvents: 1n << 33n,
|
|
1030
|
-
ManageThreads: 1n << 34n,
|
|
1031
|
-
CreatePublicThreads: 1n << 35n,
|
|
1032
|
-
CreatePrivateThreads: 1n << 36n,
|
|
1033
|
-
UseExternalStickers: 1n << 37n,
|
|
1034
|
-
SendMessagesInThreads: 1n << 38n,
|
|
1035
|
-
UseEmbeddedActivities: 1n << 39n,
|
|
1036
|
-
ModerateMembers: 1n << 40n,
|
|
1037
|
-
ViewCreatorMonetizationAnalytics: 1n << 41n,
|
|
1038
|
-
UseSoundboard: 1n << 42n,
|
|
1039
|
-
CreateGuildExpressions: 1n << 43n,
|
|
1040
|
-
CreateEvents: 1n << 44n,
|
|
1041
|
-
UseExternalSounds: 1n << 45n,
|
|
1042
|
-
SendVoiceMessages: 1n << 46n,
|
|
1043
|
-
SendPolls: 1n << 49n,
|
|
1044
|
-
UseExternalApps: 1n << 50n
|
|
1045
|
-
};
|
|
1046
1692
|
// packages/structures/src/interactions.ts
|
|
1047
1693
|
var InteractionType = {
|
|
1048
1694
|
Ping: 1,
|
|
@@ -1051,16 +1697,167 @@ var InteractionType = {
|
|
|
1051
1697
|
ApplicationCommandAutocomplete: 4,
|
|
1052
1698
|
ModalSubmit: 5
|
|
1053
1699
|
};
|
|
1054
|
-
var
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1700
|
+
var OptionType = {
|
|
1701
|
+
SubCommand: 1,
|
|
1702
|
+
SubCommandGroup: 2,
|
|
1703
|
+
String: 3,
|
|
1704
|
+
Integer: 4,
|
|
1705
|
+
Boolean: 5,
|
|
1706
|
+
User: 6,
|
|
1707
|
+
Channel: 7,
|
|
1708
|
+
Role: 8,
|
|
1709
|
+
Mentionable: 9,
|
|
1710
|
+
Number: 10,
|
|
1711
|
+
Attachment: 11
|
|
1062
1712
|
};
|
|
1063
1713
|
|
|
1714
|
+
class CommandOptions {
|
|
1715
|
+
#options;
|
|
1716
|
+
#resolved;
|
|
1717
|
+
constructor(options, resolved = {}) {
|
|
1718
|
+
let currentOptions = options;
|
|
1719
|
+
let group = null;
|
|
1720
|
+
let sub = null;
|
|
1721
|
+
while (currentOptions.length === 1) {
|
|
1722
|
+
const opt = currentOptions[0];
|
|
1723
|
+
if (opt.type === OptionType.SubCommandGroup) {
|
|
1724
|
+
group = opt.name;
|
|
1725
|
+
currentOptions = opt.options ?? [];
|
|
1726
|
+
} else if (opt.type === OptionType.SubCommand) {
|
|
1727
|
+
sub = opt.name;
|
|
1728
|
+
currentOptions = opt.options ?? [];
|
|
1729
|
+
} else {
|
|
1730
|
+
break;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
this.#options = currentOptions;
|
|
1734
|
+
this.#resolved = resolved;
|
|
1735
|
+
this.#subcommandGroup = group;
|
|
1736
|
+
this.#subcommand = sub;
|
|
1737
|
+
}
|
|
1738
|
+
#subcommandGroup;
|
|
1739
|
+
#subcommand;
|
|
1740
|
+
#get(name) {
|
|
1741
|
+
return this.#options.find((o) => o.name.toLowerCase() === name.toLowerCase());
|
|
1742
|
+
}
|
|
1743
|
+
getSubcommand(required = false) {
|
|
1744
|
+
if (!this.#subcommand && required) {
|
|
1745
|
+
throw new TypeError("No subcommand was provided.");
|
|
1746
|
+
}
|
|
1747
|
+
return this.#subcommand;
|
|
1748
|
+
}
|
|
1749
|
+
getSubcommandGroup(required = false) {
|
|
1750
|
+
if (!this.#subcommandGroup && required) {
|
|
1751
|
+
throw new TypeError("No subcommand group was provided.");
|
|
1752
|
+
}
|
|
1753
|
+
return this.#subcommandGroup;
|
|
1754
|
+
}
|
|
1755
|
+
getString(name, required = false) {
|
|
1756
|
+
const opt = this.#get(name);
|
|
1757
|
+
if (!opt || opt.type !== OptionType.String) {
|
|
1758
|
+
if (required)
|
|
1759
|
+
throw new TypeError(`Required option "${name}" (string) is missing.`);
|
|
1760
|
+
return null;
|
|
1761
|
+
}
|
|
1762
|
+
return typeof opt.value === "string" ? opt.value : null;
|
|
1763
|
+
}
|
|
1764
|
+
getInteger(name, required = false) {
|
|
1765
|
+
const opt = this.#get(name);
|
|
1766
|
+
if (!opt || opt.type !== OptionType.Integer) {
|
|
1767
|
+
if (required)
|
|
1768
|
+
throw new TypeError(`Required option "${name}" (integer) is missing.`);
|
|
1769
|
+
return null;
|
|
1770
|
+
}
|
|
1771
|
+
return typeof opt.value === "number" ? Math.trunc(opt.value) : null;
|
|
1772
|
+
}
|
|
1773
|
+
getNumber(name, required = false) {
|
|
1774
|
+
const opt = this.#get(name);
|
|
1775
|
+
if (!opt || opt.type !== OptionType.Number) {
|
|
1776
|
+
if (required)
|
|
1777
|
+
throw new TypeError(`Required option "${name}" (number) is missing.`);
|
|
1778
|
+
return null;
|
|
1779
|
+
}
|
|
1780
|
+
return typeof opt.value === "number" ? opt.value : null;
|
|
1781
|
+
}
|
|
1782
|
+
getBoolean(name, required = false) {
|
|
1783
|
+
const opt = this.#get(name);
|
|
1784
|
+
if (!opt || opt.type !== OptionType.Boolean) {
|
|
1785
|
+
if (required)
|
|
1786
|
+
throw new TypeError(`Required option "${name}" (boolean) is missing.`);
|
|
1787
|
+
return null;
|
|
1788
|
+
}
|
|
1789
|
+
return typeof opt.value === "boolean" ? opt.value : null;
|
|
1790
|
+
}
|
|
1791
|
+
getUser(name, required = false) {
|
|
1792
|
+
const opt = this.#get(name);
|
|
1793
|
+
if (!opt || opt.type !== OptionType.User) {
|
|
1794
|
+
if (required)
|
|
1795
|
+
throw new TypeError(`Required option "${name}" (user) is missing.`);
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
const userId = String(opt.value);
|
|
1799
|
+
const resolved = this.#resolved?.users?.[userId] ?? null;
|
|
1800
|
+
if (!resolved && required)
|
|
1801
|
+
throw new TypeError(`Resolved user for option "${name}" is missing.`);
|
|
1802
|
+
return resolved;
|
|
1803
|
+
}
|
|
1804
|
+
getChannel(name, required = false) {
|
|
1805
|
+
const opt = this.#get(name);
|
|
1806
|
+
if (!opt || opt.type !== OptionType.Channel) {
|
|
1807
|
+
if (required)
|
|
1808
|
+
throw new TypeError(`Required option "${name}" (channel) is missing.`);
|
|
1809
|
+
return null;
|
|
1810
|
+
}
|
|
1811
|
+
const channelId = String(opt.value);
|
|
1812
|
+
const resolved = this.#resolved?.channels?.[channelId] ?? null;
|
|
1813
|
+
if (!resolved && required)
|
|
1814
|
+
throw new TypeError(`Resolved channel for option "${name}" is missing.`);
|
|
1815
|
+
return resolved;
|
|
1816
|
+
}
|
|
1817
|
+
getRole(name, required = false) {
|
|
1818
|
+
const opt = this.#get(name);
|
|
1819
|
+
if (!opt || opt.type !== OptionType.Role) {
|
|
1820
|
+
if (required)
|
|
1821
|
+
throw new TypeError(`Required option "${name}" (role) is missing.`);
|
|
1822
|
+
return null;
|
|
1823
|
+
}
|
|
1824
|
+
const roleId = String(opt.value);
|
|
1825
|
+
const resolved = this.#resolved?.roles?.[roleId] ?? null;
|
|
1826
|
+
if (!resolved && required)
|
|
1827
|
+
throw new TypeError(`Resolved role for option "${name}" is missing.`);
|
|
1828
|
+
return resolved;
|
|
1829
|
+
}
|
|
1830
|
+
getMentionable(name, required = false) {
|
|
1831
|
+
const opt = this.#get(name);
|
|
1832
|
+
if (!opt || opt.type !== OptionType.Mentionable) {
|
|
1833
|
+
if (required)
|
|
1834
|
+
throw new TypeError(`Required option "${name}" (mentionable) is missing.`);
|
|
1835
|
+
return null;
|
|
1836
|
+
}
|
|
1837
|
+
const id = String(opt.value);
|
|
1838
|
+
const resolved = this.#resolved?.users?.[id] ?? this.#resolved?.roles?.[id] ?? null;
|
|
1839
|
+
if (!resolved && required)
|
|
1840
|
+
throw new TypeError(`Resolved mentionable for option "${name}" is missing.`);
|
|
1841
|
+
return resolved;
|
|
1842
|
+
}
|
|
1843
|
+
getAttachment(name, required = false) {
|
|
1844
|
+
const opt = this.#get(name);
|
|
1845
|
+
if (!opt || opt.type !== OptionType.Attachment) {
|
|
1846
|
+
if (required)
|
|
1847
|
+
throw new TypeError(`Required option "${name}" (attachment) is missing.`);
|
|
1848
|
+
return null;
|
|
1849
|
+
}
|
|
1850
|
+
const attachmentId = String(opt.value);
|
|
1851
|
+
const resolved = this.#resolved?.attachments?.[attachmentId] ?? null;
|
|
1852
|
+
if (!resolved && required)
|
|
1853
|
+
throw new TypeError(`Resolved attachment for option "${name}" is missing.`);
|
|
1854
|
+
return resolved;
|
|
1855
|
+
}
|
|
1856
|
+
get raw() {
|
|
1857
|
+
return this.#options;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1064
1861
|
class InteractionResponse {
|
|
1065
1862
|
type;
|
|
1066
1863
|
data;
|
|
@@ -1174,9 +1971,16 @@ class Interaction {
|
|
|
1174
1971
|
}
|
|
1175
1972
|
|
|
1176
1973
|
class CommandInteraction extends Interaction {
|
|
1974
|
+
options;
|
|
1177
1975
|
get commandName() {
|
|
1178
1976
|
return typeof this.data.data?.name === "string" ? this.data.data.name : "";
|
|
1179
1977
|
}
|
|
1978
|
+
constructor(client, data) {
|
|
1979
|
+
super(client, data);
|
|
1980
|
+
const rawOptions = data.data?.options ?? [];
|
|
1981
|
+
const resolved = data.data?.resolved ?? {};
|
|
1982
|
+
this.options = new CommandOptions(rawOptions, resolved);
|
|
1983
|
+
}
|
|
1180
1984
|
}
|
|
1181
1985
|
|
|
1182
1986
|
class ComponentInteraction extends Interaction {
|
|
@@ -1202,20 +2006,75 @@ class ComponentInteraction extends Interaction {
|
|
|
1202
2006
|
return result;
|
|
1203
2007
|
}
|
|
1204
2008
|
}
|
|
2009
|
+
|
|
2010
|
+
class ModalSubmitInteraction extends Interaction {
|
|
2011
|
+
get customId() {
|
|
2012
|
+
return this.data?.data?.custom_id ?? "";
|
|
2013
|
+
}
|
|
2014
|
+
getInputValue(customId) {
|
|
2015
|
+
const rows = this.data?.data?.components ?? [];
|
|
2016
|
+
for (const row of rows) {
|
|
2017
|
+
for (const comp of row.components ?? []) {
|
|
2018
|
+
if (comp.custom_id === customId)
|
|
2019
|
+
return comp.value;
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
return;
|
|
2023
|
+
}
|
|
2024
|
+
getRequiredInputValue(customId) {
|
|
2025
|
+
const value = this.getInputValue(customId);
|
|
2026
|
+
if (value === undefined)
|
|
2027
|
+
throw new TypeError(`Modal input "${customId}" was not found in the submission.`);
|
|
2028
|
+
return value;
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
class AutocompleteInteraction extends Interaction {
|
|
2033
|
+
get commandName() {
|
|
2034
|
+
return this.data?.data?.name ?? "";
|
|
2035
|
+
}
|
|
2036
|
+
get focusedOption() {
|
|
2037
|
+
const options = this.data?.data?.options ?? [];
|
|
2038
|
+
return findFocused(options);
|
|
2039
|
+
}
|
|
2040
|
+
async respond(choices) {
|
|
2041
|
+
if (!Array.isArray(choices))
|
|
2042
|
+
throw new TypeError("Autocomplete choices must be an array.");
|
|
2043
|
+
const response = new InteractionResponse(InteractionResponseType.Autocomplete, { choices });
|
|
2044
|
+
await this.postResponse(response);
|
|
2045
|
+
this.replied = true;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
function findFocused(options) {
|
|
2049
|
+
for (const opt of options) {
|
|
2050
|
+
if (opt.focused)
|
|
2051
|
+
return { name: opt.name, value: opt.value, type: opt.type };
|
|
2052
|
+
if (Array.isArray(opt.options)) {
|
|
2053
|
+
const found = findFocused(opt.options);
|
|
2054
|
+
if (found)
|
|
2055
|
+
return found;
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
2058
|
+
return;
|
|
2059
|
+
}
|
|
1205
2060
|
function createInteraction(client, data) {
|
|
1206
2061
|
switch (data.type) {
|
|
1207
2062
|
case InteractionType.ApplicationCommand:
|
|
1208
|
-
case InteractionType.ApplicationCommandAutocomplete:
|
|
1209
2063
|
return new CommandInteraction(client, data);
|
|
2064
|
+
case InteractionType.ApplicationCommandAutocomplete:
|
|
2065
|
+
return new AutocompleteInteraction(client, data);
|
|
1210
2066
|
case InteractionType.MessageComponent:
|
|
1211
|
-
case InteractionType.ModalSubmit:
|
|
1212
2067
|
return new ComponentInteraction(client, data);
|
|
2068
|
+
case InteractionType.ModalSubmit:
|
|
2069
|
+
return new ModalSubmitInteraction(client, data);
|
|
1213
2070
|
default:
|
|
1214
2071
|
return new Interaction(client, data);
|
|
1215
2072
|
}
|
|
1216
2073
|
}
|
|
1217
2074
|
|
|
1218
2075
|
// packages/structures/src/index.ts
|
|
2076
|
+
var NON_SYSTEM_MESSAGE_TYPES = new Set([0, 19, 20, 23]);
|
|
2077
|
+
|
|
1219
2078
|
class Message extends BaseStructure {
|
|
1220
2079
|
content;
|
|
1221
2080
|
author;
|
|
@@ -1223,7 +2082,7 @@ class Message extends BaseStructure {
|
|
|
1223
2082
|
channel;
|
|
1224
2083
|
guildId;
|
|
1225
2084
|
flags;
|
|
1226
|
-
|
|
2085
|
+
timestamp;
|
|
1227
2086
|
attachments;
|
|
1228
2087
|
embeds;
|
|
1229
2088
|
mentions;
|
|
@@ -1232,6 +2091,7 @@ class Message extends BaseStructure {
|
|
|
1232
2091
|
mentionEveryone;
|
|
1233
2092
|
type;
|
|
1234
2093
|
reference;
|
|
2094
|
+
components;
|
|
1235
2095
|
referencedMessage;
|
|
1236
2096
|
#context;
|
|
1237
2097
|
constructor(data, context) {
|
|
@@ -1243,9 +2103,10 @@ class Message extends BaseStructure {
|
|
|
1243
2103
|
this.channelId = data.channel_id;
|
|
1244
2104
|
this.guildId = data.guild_id;
|
|
1245
2105
|
this.flags = data.flags ?? 0;
|
|
1246
|
-
this.
|
|
2106
|
+
this.timestamp = new Date(data.timestamp ?? Number((BigInt(this.id) >> 22n) + 1420070400000n));
|
|
1247
2107
|
this.attachments = data.attachments ?? [];
|
|
1248
2108
|
this.embeds = data.embeds ?? [];
|
|
2109
|
+
this.components = data.components ?? [];
|
|
1249
2110
|
this.mentions = (data.mentions ?? []).map((user) => new User(user));
|
|
1250
2111
|
this.mentionRoles = data.mention_roles ?? [];
|
|
1251
2112
|
this.pinned = data.pinned ?? false;
|
|
@@ -1259,21 +2120,25 @@ class Message extends BaseStructure {
|
|
|
1259
2120
|
get embedsSuppressed() {
|
|
1260
2121
|
return (this.flags & 4) !== 0;
|
|
1261
2122
|
}
|
|
2123
|
+
get createdTimestamp() {
|
|
2124
|
+
return this.timestamp.getTime();
|
|
2125
|
+
}
|
|
2126
|
+
get createdAt() {
|
|
2127
|
+
return this.timestamp;
|
|
2128
|
+
}
|
|
1262
2129
|
edit(options) {
|
|
1263
2130
|
if (!this.#context)
|
|
1264
2131
|
throw new Error("This message is not attached to a client.");
|
|
1265
2132
|
return this.#context.editMessage(this.channelId, this.id, options);
|
|
1266
2133
|
}
|
|
2134
|
+
update(options) {
|
|
2135
|
+
return this.edit(options);
|
|
2136
|
+
}
|
|
1267
2137
|
delete() {
|
|
1268
2138
|
if (!this.#context)
|
|
1269
2139
|
throw new Error("This message is not attached to a client.");
|
|
1270
2140
|
return this.#context.deleteMessage(this.channelId, this.id);
|
|
1271
2141
|
}
|
|
1272
|
-
crosspost() {
|
|
1273
|
-
if (!this.#context)
|
|
1274
|
-
throw new Error("This message is not attached to a client.");
|
|
1275
|
-
return this.#context.crosspostMessage(this.channelId, this.id);
|
|
1276
|
-
}
|
|
1277
2142
|
reply(options) {
|
|
1278
2143
|
if (!this.#context)
|
|
1279
2144
|
throw new Error("This message is not attached to a client.");
|
|
@@ -1285,6 +2150,81 @@ class Message extends BaseStructure {
|
|
|
1285
2150
|
};
|
|
1286
2151
|
return this.#context.sendMessage(this.channelId, payload);
|
|
1287
2152
|
}
|
|
2153
|
+
crosspost() {
|
|
2154
|
+
if (!this.#context)
|
|
2155
|
+
throw new Error("This message is not attached to a client.");
|
|
2156
|
+
return this.#context.crosspostMessage(this.channelId, this.id);
|
|
2157
|
+
}
|
|
2158
|
+
react(emoji) {
|
|
2159
|
+
if (!this.#context?.addReaction)
|
|
2160
|
+
throw new Error("This message is not attached to a client.");
|
|
2161
|
+
return this.#context.addReaction(this.channelId, this.id, emoji);
|
|
2162
|
+
}
|
|
2163
|
+
removeReaction(emoji, userId) {
|
|
2164
|
+
if (!this.#context)
|
|
2165
|
+
throw new Error("This message is not attached to a client.");
|
|
2166
|
+
return userId ? this.#context.removeReaction?.(this.channelId, this.id, emoji, userId) ?? Promise.reject(new Error("Reaction operations are unavailable.")) : this.#context.removeOwnReaction?.(this.channelId, this.id, emoji) ?? Promise.reject(new Error("Reaction operations are unavailable."));
|
|
2167
|
+
}
|
|
2168
|
+
removeAllReactions() {
|
|
2169
|
+
if (!this.#context?.removeAllReactions)
|
|
2170
|
+
throw new Error("This message is not attached to a client.");
|
|
2171
|
+
return this.#context.removeAllReactions(this.channelId, this.id);
|
|
2172
|
+
}
|
|
2173
|
+
pin() {
|
|
2174
|
+
if (!this.#context?.pinMessage)
|
|
2175
|
+
throw new Error("This message is not attached to a client.");
|
|
2176
|
+
return this.#context.pinMessage(this.channelId, this.id);
|
|
2177
|
+
}
|
|
2178
|
+
unpin() {
|
|
2179
|
+
if (!this.#context?.unpinMessage)
|
|
2180
|
+
throw new Error("This message is not attached to a client.");
|
|
2181
|
+
return this.#context.unpinMessage(this.channelId, this.id);
|
|
2182
|
+
}
|
|
2183
|
+
get isEphemeral() {
|
|
2184
|
+
return (this.flags & 64) !== 0;
|
|
2185
|
+
}
|
|
2186
|
+
get isPinned() {
|
|
2187
|
+
return this.pinned;
|
|
2188
|
+
}
|
|
2189
|
+
get isSystemMessage() {
|
|
2190
|
+
return !NON_SYSTEM_MESSAGE_TYPES.has(this.type);
|
|
2191
|
+
}
|
|
2192
|
+
get isCrosspost() {
|
|
2193
|
+
return (this.flags & 2) !== 0;
|
|
2194
|
+
}
|
|
2195
|
+
get hasAttachments() {
|
|
2196
|
+
return this.attachments.length > 0;
|
|
2197
|
+
}
|
|
2198
|
+
get hasEmbeds() {
|
|
2199
|
+
return this.embeds.length > 0;
|
|
2200
|
+
}
|
|
2201
|
+
get hasComponents() {
|
|
2202
|
+
return this.components.length > 0;
|
|
2203
|
+
}
|
|
2204
|
+
suppressEmbeds() {
|
|
2205
|
+
return this.edit({ flags: this.flags | 4 });
|
|
2206
|
+
}
|
|
2207
|
+
toJSON() {
|
|
2208
|
+
return {
|
|
2209
|
+
id: this.id,
|
|
2210
|
+
content: this.content,
|
|
2211
|
+
channelId: this.channelId,
|
|
2212
|
+
guildId: this.guildId,
|
|
2213
|
+
flags: this.flags,
|
|
2214
|
+
pinned: this.pinned,
|
|
2215
|
+
mentionEveryone: this.mentionEveryone,
|
|
2216
|
+
type: this.type,
|
|
2217
|
+
timestamp: this.timestamp.toISOString(),
|
|
2218
|
+
author: { id: this.author.id, username: this.author.username },
|
|
2219
|
+
attachments: [...this.attachments],
|
|
2220
|
+
embeds: [...this.embeds],
|
|
2221
|
+
components: [...this.components],
|
|
2222
|
+
mentions: this.mentions.map((u) => u.id),
|
|
2223
|
+
mentionRoles: [...this.mentionRoles],
|
|
2224
|
+
reference: this.reference,
|
|
2225
|
+
referencedMessage: this.referencedMessage ? this.referencedMessage.id : this.referencedMessage
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
1288
2228
|
}
|
|
1289
2229
|
|
|
1290
2230
|
// packages/managers/src/message.ts
|
|
@@ -1309,10 +2249,7 @@ class MessageManager {
|
|
|
1309
2249
|
}
|
|
1310
2250
|
async fetch(messageId) {
|
|
1311
2251
|
const data = await this.#rest.get(Routes.message(this.#channelId, messageId));
|
|
1312
|
-
|
|
1313
|
-
if (!message)
|
|
1314
|
-
throw new Error("Discord returned no message payload.");
|
|
1315
|
-
return this.upsert(message);
|
|
2252
|
+
return this.upsert(data);
|
|
1316
2253
|
}
|
|
1317
2254
|
fetchMany(messageIds) {
|
|
1318
2255
|
return Promise.all(Array.from(messageIds, (messageId) => this.fetch(messageId)));
|
|
@@ -1353,8 +2290,110 @@ class ThreadManager {
|
|
|
1353
2290
|
return new Channel(data, this.#context);
|
|
1354
2291
|
}
|
|
1355
2292
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
2293
|
+
|
|
2294
|
+
// packages/managers/src/user.ts
|
|
2295
|
+
class UserManager extends ResourceManager {
|
|
2296
|
+
#rest;
|
|
2297
|
+
constructor(rest) {
|
|
2298
|
+
super(async (id) => new User(await rest.get(Routes.userById(id))), (user) => user.id);
|
|
2299
|
+
this.#rest = rest;
|
|
2300
|
+
}
|
|
2301
|
+
async fetchMe() {
|
|
2302
|
+
const data = await this.#rest.get("/users/@me");
|
|
2303
|
+
return this.upsert(new User(data));
|
|
2304
|
+
}
|
|
2305
|
+
async editMe(options) {
|
|
2306
|
+
const data = await this.#rest.patch("/users/@me", options);
|
|
2307
|
+
return this.upsert(new User(data));
|
|
2308
|
+
}
|
|
2309
|
+
async leaveGuild(guildId) {
|
|
2310
|
+
await this.#rest.delete(`/users/@me/guilds/${guildId}`);
|
|
2311
|
+
}
|
|
2312
|
+
async createDM(userId) {
|
|
2313
|
+
return this.#rest.post("/users/@me/channels", {
|
|
2314
|
+
recipient_id: userId
|
|
2315
|
+
});
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
// packages/managers/src/guild.ts
|
|
2319
|
+
function withQuery(path, params) {
|
|
2320
|
+
const suffix = params.toString();
|
|
2321
|
+
return suffix ? `${path}?${suffix}` : path;
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
class GuildManager extends ResourceManager {
|
|
2325
|
+
#rest;
|
|
2326
|
+
constructor(rest) {
|
|
2327
|
+
super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
|
|
2328
|
+
this.#rest = rest;
|
|
2329
|
+
}
|
|
2330
|
+
async create(options) {
|
|
2331
|
+
const data = await this.#rest.post("/guilds", options);
|
|
2332
|
+
return this.upsert(new Guild(data));
|
|
2333
|
+
}
|
|
2334
|
+
async edit(id, options) {
|
|
2335
|
+
const data = await this.#rest.patch(Routes.guild(id), options);
|
|
2336
|
+
return this.upsert(new Guild(data));
|
|
2337
|
+
}
|
|
2338
|
+
async deleteGuild(id) {
|
|
2339
|
+
await this.#rest.delete(Routes.guild(id));
|
|
2340
|
+
}
|
|
2341
|
+
async fetchPreview(id) {
|
|
2342
|
+
return this.#rest.get(Routes.guildPreview(id));
|
|
2343
|
+
}
|
|
2344
|
+
async fetchActiveThreads(id) {
|
|
2345
|
+
return this.#rest.get(Routes.guildActiveThreads(id));
|
|
2346
|
+
}
|
|
2347
|
+
async fetchWebhooks(id) {
|
|
2348
|
+
return this.#rest.get(Routes.guildWebhooks(id));
|
|
2349
|
+
}
|
|
2350
|
+
async fetchInvites(id) {
|
|
2351
|
+
return this.#rest.get(Routes.guildInvites(id));
|
|
2352
|
+
}
|
|
2353
|
+
async fetchAuditLog(guildId, options = {}) {
|
|
2354
|
+
const params = new URLSearchParams;
|
|
2355
|
+
if (options.userId)
|
|
2356
|
+
params.set("user_id", options.userId);
|
|
2357
|
+
if (options.actionType !== undefined)
|
|
2358
|
+
params.set("action_type", String(options.actionType));
|
|
2359
|
+
if (options.before)
|
|
2360
|
+
params.set("before", options.before);
|
|
2361
|
+
if (options.after)
|
|
2362
|
+
params.set("after", options.after);
|
|
2363
|
+
if (options.limit !== undefined)
|
|
2364
|
+
params.set("limit", String(Math.min(100, Math.max(1, options.limit))));
|
|
2365
|
+
return this.#rest.get(withQuery(Routes.guildAuditLog(guildId), params));
|
|
2366
|
+
}
|
|
2367
|
+
async fetchMembers(guildId, options = {}) {
|
|
2368
|
+
const params = new URLSearchParams;
|
|
2369
|
+
if (options.limit !== undefined)
|
|
2370
|
+
params.set("limit", String(Math.min(1000, Math.max(1, options.limit))));
|
|
2371
|
+
if (options.after)
|
|
2372
|
+
params.set("after", options.after);
|
|
2373
|
+
return this.#rest.get(withQuery(Routes.guildMembers(guildId), params));
|
|
2374
|
+
}
|
|
2375
|
+
async fetchAutoModerationRules(guildId) {
|
|
2376
|
+
const rules = await this.#rest.get(Routes.guildAutoModerationRules(guildId));
|
|
2377
|
+
return rules.map((r) => new AutoModerationRule(r));
|
|
2378
|
+
}
|
|
2379
|
+
async fetchAutoModerationRule(guildId, ruleId) {
|
|
2380
|
+
const rule = await this.#rest.get(Routes.guildAutoModerationRule(guildId, ruleId));
|
|
2381
|
+
return new AutoModerationRule(rule);
|
|
2382
|
+
}
|
|
2383
|
+
async createAutoModerationRule(guildId, options) {
|
|
2384
|
+
const rule = await this.#rest.post(Routes.guildAutoModerationRules(guildId), options);
|
|
2385
|
+
return new AutoModerationRule(rule);
|
|
2386
|
+
}
|
|
2387
|
+
async editAutoModerationRule(guildId, ruleId, options) {
|
|
2388
|
+
const rule = await this.#rest.patch(Routes.guildAutoModerationRule(guildId, ruleId), options);
|
|
2389
|
+
return new AutoModerationRule(rule);
|
|
2390
|
+
}
|
|
2391
|
+
async deleteAutoModerationRule(guildId, ruleId) {
|
|
2392
|
+
await this.#rest.delete(Routes.guildAutoModerationRule(guildId, ruleId));
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
// packages/managers/src/application.ts
|
|
2396
|
+
class ApplicationCommandManager {
|
|
1358
2397
|
#rest;
|
|
1359
2398
|
#applicationId;
|
|
1360
2399
|
constructor(rest, applicationId) {
|
|
@@ -1394,23 +2433,6 @@ class ApplicationCommandManager {
|
|
|
1394
2433
|
}
|
|
1395
2434
|
|
|
1396
2435
|
// packages/managers/src/index.ts
|
|
1397
|
-
class UserManager extends ResourceManager {
|
|
1398
|
-
constructor(rest) {
|
|
1399
|
-
super(async (id) => new User(await rest.get(Routes.userById(id))), (user) => user.id);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
class GuildManager extends ResourceManager {
|
|
1404
|
-
constructor(rest) {
|
|
1405
|
-
super(async (id) => new Guild(await rest.get(Routes.guild(id))), (guild) => guild.id);
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
var MessageCreateOptions = undefined;
|
|
1409
|
-
var MessageEditOptions = undefined;
|
|
1410
|
-
var MessageFetchOptions = undefined;
|
|
1411
|
-
var MessageThreadOptions = undefined;
|
|
1412
|
-
var ReactionFetchOptions = undefined;
|
|
1413
|
-
|
|
1414
2436
|
class ChannelManager extends Manager {
|
|
1415
2437
|
#rest;
|
|
1416
2438
|
#context;
|
|
@@ -1422,7 +2444,15 @@ class ChannelManager extends Manager {
|
|
|
1422
2444
|
sendMessage: (channelId, options) => this.send(channelId, options),
|
|
1423
2445
|
editMessage: (channelId, messageId, options) => this.editMessage(channelId, messageId, options),
|
|
1424
2446
|
deleteMessage: (channelId, messageId) => this.deleteMessage(channelId, messageId),
|
|
1425
|
-
crosspostMessage: (channelId, messageId) => this.crosspostMessage(channelId, messageId)
|
|
2447
|
+
crosspostMessage: (channelId, messageId) => this.crosspostMessage(channelId, messageId),
|
|
2448
|
+
editChannel: (channelId, options) => this.edit(channelId, options),
|
|
2449
|
+
deleteChannel: (channelId) => this.deleteChannel(channelId),
|
|
2450
|
+
addReaction: (channelId, messageId, emoji) => this.addReaction(channelId, messageId, emoji),
|
|
2451
|
+
removeOwnReaction: (channelId, messageId, emoji) => this.removeOwnReaction(channelId, messageId, emoji),
|
|
2452
|
+
removeReaction: (channelId, messageId, emoji, userId) => this.removeReaction(channelId, messageId, emoji, userId),
|
|
2453
|
+
removeAllReactions: (channelId, messageId) => this.removeAllReactions(channelId, messageId),
|
|
2454
|
+
pinMessage: (channelId, messageId) => this.pinMessage(channelId, messageId),
|
|
2455
|
+
unpinMessage: (channelId, messageId) => this.unpinMessage(channelId, messageId)
|
|
1426
2456
|
};
|
|
1427
2457
|
}
|
|
1428
2458
|
messages(channelId) {
|
|
@@ -1437,8 +2467,7 @@ class ChannelManager extends Manager {
|
|
|
1437
2467
|
return new ThreadManager(this.#rest, this.#context, channelId);
|
|
1438
2468
|
}
|
|
1439
2469
|
async fetch(channelId) {
|
|
1440
|
-
|
|
1441
|
-
return this.upsert(data);
|
|
2470
|
+
return this.upsert(await this.#rest.get(Routes.channel(channelId)));
|
|
1442
2471
|
}
|
|
1443
2472
|
async resolve(channelId) {
|
|
1444
2473
|
return this.get(channelId) ?? this.fetch(channelId);
|
|
@@ -1456,6 +2485,20 @@ class ChannelManager extends Manager {
|
|
|
1456
2485
|
update(channel) {
|
|
1457
2486
|
return this.set(channel.id, channel);
|
|
1458
2487
|
}
|
|
2488
|
+
async create(guildId, options) {
|
|
2489
|
+
return this.upsert(await this.#rest.post(Routes.guildChannels(guildId), options));
|
|
2490
|
+
}
|
|
2491
|
+
async edit(channelId, options) {
|
|
2492
|
+
return this.upsert(await this.#rest.patch(Routes.channel(channelId), options));
|
|
2493
|
+
}
|
|
2494
|
+
async deleteChannel(channelId) {
|
|
2495
|
+
await this.#rest.delete(Routes.channel(channelId));
|
|
2496
|
+
this.delete(channelId);
|
|
2497
|
+
}
|
|
2498
|
+
delete(channelId) {
|
|
2499
|
+
this.#messageManagers.delete(channelId);
|
|
2500
|
+
return super.delete(channelId);
|
|
2501
|
+
}
|
|
1459
2502
|
send(channelId, options) {
|
|
1460
2503
|
return this.messages(channelId).send(options);
|
|
1461
2504
|
}
|
|
@@ -1485,8 +2528,7 @@ class ChannelManager extends Manager {
|
|
|
1485
2528
|
return this.messages(data.channel_id).upsert(data);
|
|
1486
2529
|
}
|
|
1487
2530
|
async editMessage(channelId, messageId, options) {
|
|
1488
|
-
|
|
1489
|
-
return this.messages(channelId).upsert(data);
|
|
2531
|
+
return this.messages(channelId).upsert(await this.#rest.patch(Routes.message(channelId, messageId), options));
|
|
1490
2532
|
}
|
|
1491
2533
|
async deleteMessage(channelId, messageId) {
|
|
1492
2534
|
await this.#rest.delete(Routes.message(channelId, messageId));
|
|
@@ -1496,11 +2538,12 @@ class ChannelManager extends Manager {
|
|
|
1496
2538
|
return this.messages(channelId).delete(messageId);
|
|
1497
2539
|
}
|
|
1498
2540
|
async crosspostMessage(channelId, messageId) {
|
|
1499
|
-
|
|
1500
|
-
return this.messages(channelId).upsert(data);
|
|
2541
|
+
return this.messages(channelId).upsert(await this.#rest.post(Routes.crosspostMessage(channelId, messageId)));
|
|
1501
2542
|
}
|
|
1502
2543
|
async bulkDeleteMessages(channelId, messageIds) {
|
|
1503
2544
|
const ids = [...messageIds];
|
|
2545
|
+
if (ids.length < 2 || ids.length > 100)
|
|
2546
|
+
throw new RangeError("bulkDelete requires between 2 and 100 message IDs.");
|
|
1504
2547
|
await this.#rest.post(Routes.channelBulkDelete(channelId), {
|
|
1505
2548
|
messages: ids
|
|
1506
2549
|
});
|
|
@@ -1508,7 +2551,7 @@ class ChannelManager extends Manager {
|
|
|
1508
2551
|
this.messages(channelId).delete(id);
|
|
1509
2552
|
}
|
|
1510
2553
|
async addReaction(channelId, messageId, emoji) {
|
|
1511
|
-
await this.#rest.put(Routes.messageReactions(channelId, messageId, emoji));
|
|
2554
|
+
await this.#rest.put(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
|
|
1512
2555
|
}
|
|
1513
2556
|
async fetchReactions(channelId, messageId, emoji, options = {}) {
|
|
1514
2557
|
const params = new URLSearchParams;
|
|
@@ -1521,7 +2564,7 @@ class ChannelManager extends Manager {
|
|
|
1521
2564
|
return data.map((user) => new User(user));
|
|
1522
2565
|
}
|
|
1523
2566
|
async removeOwnReaction(channelId, messageId, emoji) {
|
|
1524
|
-
await this.#rest.delete(Routes.messageReactions(channelId, messageId, emoji)
|
|
2567
|
+
await this.#rest.delete(`${Routes.messageReactions(channelId, messageId, emoji)}/@me`);
|
|
1525
2568
|
}
|
|
1526
2569
|
async removeReaction(channelId, messageId, emoji, userId) {
|
|
1527
2570
|
await this.#rest.delete(`${Routes.messageReactions(channelId, messageId, emoji)}/${userId}`);
|
|
@@ -1542,9 +2585,21 @@ class ChannelManager extends Manager {
|
|
|
1542
2585
|
createThreadFromMessage(channelId, messageId, options) {
|
|
1543
2586
|
return this.threads(channelId).createFromMessage(messageId, options);
|
|
1544
2587
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
2588
|
+
async fetchPage(channelId, options = {}) {
|
|
2589
|
+
const limit = Math.min(100, Math.max(1, options.limit ?? 50));
|
|
2590
|
+
const messages = await this.fetchMessages(channelId, {
|
|
2591
|
+
...options,
|
|
2592
|
+
limit
|
|
2593
|
+
});
|
|
2594
|
+
return {
|
|
2595
|
+
messages,
|
|
2596
|
+
before: messages[0]?.id,
|
|
2597
|
+
after: messages[messages.length - 1]?.id,
|
|
2598
|
+
hasMore: messages.length === limit
|
|
2599
|
+
};
|
|
2600
|
+
}
|
|
2601
|
+
async bulkDelete(channelId, messageIds) {
|
|
2602
|
+
return this.bulkDeleteMessages(channelId, messageIds);
|
|
1548
2603
|
}
|
|
1549
2604
|
clear() {
|
|
1550
2605
|
this.#messageManagers.clear();
|
|
@@ -1555,126 +2610,6 @@ function isMessageQuery(value) {
|
|
|
1555
2610
|
return typeof value === "object" && value !== null && !(Symbol.iterator in value);
|
|
1556
2611
|
}
|
|
1557
2612
|
|
|
1558
|
-
// packages/types/src/index.ts
|
|
1559
|
-
var GatewayIntentBits = {
|
|
1560
|
-
Guilds: 1 << 0,
|
|
1561
|
-
GuildMembers: 1 << 1,
|
|
1562
|
-
GuildModeration: 1 << 2,
|
|
1563
|
-
GuildExpressions: 1 << 3,
|
|
1564
|
-
GuildIntegrations: 1 << 4,
|
|
1565
|
-
GuildWebhooks: 1 << 5,
|
|
1566
|
-
GuildInvites: 1 << 6,
|
|
1567
|
-
GuildVoiceStates: 1 << 7,
|
|
1568
|
-
GuildPresences: 1 << 8,
|
|
1569
|
-
GuildMessages: 1 << 9,
|
|
1570
|
-
GuildMessageReactions: 1 << 10,
|
|
1571
|
-
GuildMessageTyping: 1 << 11,
|
|
1572
|
-
DirectMessages: 1 << 12,
|
|
1573
|
-
DirectMessageReactions: 1 << 13,
|
|
1574
|
-
DirectMessageTyping: 1 << 14,
|
|
1575
|
-
MessageContent: 1 << 15,
|
|
1576
|
-
GuildScheduledEvents: 1 << 16,
|
|
1577
|
-
AutoModerationConfiguration: 1 << 20,
|
|
1578
|
-
AutoModerationExecution: 1 << 21,
|
|
1579
|
-
GuildMessagePolls: 1 << 24,
|
|
1580
|
-
DirectMessagePolls: 1 << 25
|
|
1581
|
-
};
|
|
1582
|
-
var IntentBits = {
|
|
1583
|
-
guild: 1 << 0,
|
|
1584
|
-
guilds: 1 << 0,
|
|
1585
|
-
guildMembers: 1 << 1,
|
|
1586
|
-
guildModeration: 1 << 2,
|
|
1587
|
-
guildBans: 1 << 2,
|
|
1588
|
-
guildExpressions: 1 << 3,
|
|
1589
|
-
guildEmojis: 1 << 3,
|
|
1590
|
-
guildEmojisAndStickers: 1 << 3,
|
|
1591
|
-
guildIntegrations: 1 << 4,
|
|
1592
|
-
guildWebhooks: 1 << 5,
|
|
1593
|
-
guildInvites: 1 << 6,
|
|
1594
|
-
guildVoiceStates: 1 << 7,
|
|
1595
|
-
guildPresences: 1 << 8,
|
|
1596
|
-
guildMessages: 1 << 9,
|
|
1597
|
-
guildMessage: 1 << 9,
|
|
1598
|
-
guildMessageReactions: 1 << 10,
|
|
1599
|
-
guildMessageTyping: 1 << 11,
|
|
1600
|
-
directMessages: 1 << 12,
|
|
1601
|
-
directMessageReactions: 1 << 13,
|
|
1602
|
-
directMessageTyping: 1 << 14,
|
|
1603
|
-
messageContent: 1 << 15,
|
|
1604
|
-
guildScheduledEvents: 1 << 16,
|
|
1605
|
-
autoModerationConfiguration: 1 << 20,
|
|
1606
|
-
autoModerationExecution: 1 << 21,
|
|
1607
|
-
guildMessagePolls: 1 << 24,
|
|
1608
|
-
directMessagePolls: 1 << 25
|
|
1609
|
-
};
|
|
1610
|
-
var Intents = IntentBits;
|
|
1611
|
-
function resolveGatewayIntents(intents) {
|
|
1612
|
-
if (typeof intents === "number")
|
|
1613
|
-
return intents;
|
|
1614
|
-
if (Array.isArray(intents)) {
|
|
1615
|
-
return intents.reduce((acc, intent) => {
|
|
1616
|
-
return acc | resolveGatewayIntents(intent);
|
|
1617
|
-
}, 0);
|
|
1618
|
-
}
|
|
1619
|
-
if (typeof intents === "string") {
|
|
1620
|
-
if (intents in GatewayIntentBits)
|
|
1621
|
-
return GatewayIntentBits[intents];
|
|
1622
|
-
if (intents in IntentBits)
|
|
1623
|
-
return IntentBits[intents];
|
|
1624
|
-
const lower = intents.charAt(0).toLowerCase() + intents.slice(1);
|
|
1625
|
-
if (lower in IntentBits)
|
|
1626
|
-
return IntentBits[lower];
|
|
1627
|
-
const num = Number(intents);
|
|
1628
|
-
if (!Number.isNaN(num))
|
|
1629
|
-
return num;
|
|
1630
|
-
}
|
|
1631
|
-
return 0;
|
|
1632
|
-
}
|
|
1633
|
-
var MessageFlags = {
|
|
1634
|
-
Crossposted: 1,
|
|
1635
|
-
IsCrosspost: 2,
|
|
1636
|
-
SuppressEmbeds: 4,
|
|
1637
|
-
SourceMessageDeleted: 8,
|
|
1638
|
-
Urgent: 16,
|
|
1639
|
-
HasThread: 32,
|
|
1640
|
-
Ephemeral: 64,
|
|
1641
|
-
Loading: 128,
|
|
1642
|
-
IsComponentsV2: 32768
|
|
1643
|
-
};
|
|
1644
|
-
var ChannelType = {
|
|
1645
|
-
GuildText: 0,
|
|
1646
|
-
DM: 1,
|
|
1647
|
-
GuildVoice: 2,
|
|
1648
|
-
GroupDM: 3,
|
|
1649
|
-
GuildCategory: 4,
|
|
1650
|
-
GuildAnnouncement: 5,
|
|
1651
|
-
AnnouncementThread: 10,
|
|
1652
|
-
PublicThread: 11,
|
|
1653
|
-
PrivateThread: 12,
|
|
1654
|
-
GuildStageVoice: 13,
|
|
1655
|
-
GuildDirectory: 14,
|
|
1656
|
-
GuildForum: 15,
|
|
1657
|
-
GuildMedia: 16
|
|
1658
|
-
};
|
|
1659
|
-
var ApplicationCommandOptionType = {
|
|
1660
|
-
SubCommand: 1,
|
|
1661
|
-
SubCommandGroup: 2,
|
|
1662
|
-
String: 3,
|
|
1663
|
-
Integer: 4,
|
|
1664
|
-
Boolean: 5,
|
|
1665
|
-
User: 6,
|
|
1666
|
-
Channel: 7,
|
|
1667
|
-
Role: 8,
|
|
1668
|
-
Mentionable: 9,
|
|
1669
|
-
Number: 10,
|
|
1670
|
-
Attachment: 11
|
|
1671
|
-
};
|
|
1672
|
-
var ApplicationCommandType = {
|
|
1673
|
-
ChatInput: 1,
|
|
1674
|
-
User: 2,
|
|
1675
|
-
Message: 3
|
|
1676
|
-
};
|
|
1677
|
-
|
|
1678
2613
|
// packages/ws/src/index.ts
|
|
1679
2614
|
var GatewayOpcodes = {
|
|
1680
2615
|
Dispatch: 0,
|
|
@@ -1689,6 +2624,22 @@ var GatewayOpcodes = {
|
|
|
1689
2624
|
Hello: 10,
|
|
1690
2625
|
HeartbeatAck: 11
|
|
1691
2626
|
};
|
|
2627
|
+
var GatewayCloseCodes = {
|
|
2628
|
+
UnknownError: 4000,
|
|
2629
|
+
UnknownOpcode: 4001,
|
|
2630
|
+
DecodeError: 4002,
|
|
2631
|
+
NotAuthenticated: 4003,
|
|
2632
|
+
AuthenticationFailed: 4004,
|
|
2633
|
+
AlreadyAuthenticated: 4005,
|
|
2634
|
+
InvalidSeq: 4007,
|
|
2635
|
+
RateLimited: 4008,
|
|
2636
|
+
SessionTimedOut: 4009,
|
|
2637
|
+
InvalidShard: 4010,
|
|
2638
|
+
ShardingRequired: 4011,
|
|
2639
|
+
InvalidAPIVersion: 4012,
|
|
2640
|
+
InvalidIntents: 4013,
|
|
2641
|
+
DisallowedIntents: 4014
|
|
2642
|
+
};
|
|
1692
2643
|
class GatewayError extends Error {
|
|
1693
2644
|
code;
|
|
1694
2645
|
constructor(message, code, options) {
|
|
@@ -1722,6 +2673,8 @@ class Gateway {
|
|
|
1722
2673
|
#rejectConnect;
|
|
1723
2674
|
#listeners = new Map;
|
|
1724
2675
|
#sendTimestamps = [];
|
|
2676
|
+
ping = -1;
|
|
2677
|
+
#decompressor;
|
|
1725
2678
|
constructor(options) {
|
|
1726
2679
|
if (!options.token?.trim())
|
|
1727
2680
|
throw new TypeError("A Gateway token is required.");
|
|
@@ -1742,7 +2695,12 @@ class Gateway {
|
|
|
1742
2695
|
browser: "Discord Android",
|
|
1743
2696
|
device: "Discord Android"
|
|
1744
2697
|
},
|
|
1745
|
-
presence: {
|
|
2698
|
+
presence: {
|
|
2699
|
+
status: "online",
|
|
2700
|
+
activities: [],
|
|
2701
|
+
afk: false,
|
|
2702
|
+
since: null
|
|
2703
|
+
},
|
|
1746
2704
|
...options
|
|
1747
2705
|
};
|
|
1748
2706
|
if (this.#options.shardId < 0 || this.#options.shardId >= this.#options.shardCount)
|
|
@@ -1757,10 +2715,13 @@ class Gateway {
|
|
|
1757
2715
|
return this.#connectPromise;
|
|
1758
2716
|
this.#closed = false;
|
|
1759
2717
|
this.#setState("CONNECT" /* Connect */);
|
|
2718
|
+
const connectURL = this.#options.compress ? url.includes("compress=") ? url : `${url}&compress=zlib-stream` : url;
|
|
2719
|
+
if (this.#options.compress)
|
|
2720
|
+
this.#initDecompressor();
|
|
1760
2721
|
this.#connectPromise = new Promise((resolve, reject) => {
|
|
1761
2722
|
this.#resolveConnect = resolve;
|
|
1762
2723
|
this.#rejectConnect = reject;
|
|
1763
|
-
this.#open(
|
|
2724
|
+
this.#open(connectURL);
|
|
1764
2725
|
});
|
|
1765
2726
|
return this.#connectPromise;
|
|
1766
2727
|
}
|
|
@@ -1796,12 +2757,15 @@ class Gateway {
|
|
|
1796
2757
|
send(payload) {
|
|
1797
2758
|
if (!payload || !Number.isInteger(payload.op))
|
|
1798
2759
|
throw new TypeError("Gateway payload must contain an integer opcode.");
|
|
2760
|
+
return this.#dispatch(payload, false);
|
|
2761
|
+
}
|
|
2762
|
+
#dispatch(payload, privileged) {
|
|
1799
2763
|
if (this.#ws?.readyState !== WebSocket.OPEN)
|
|
1800
2764
|
return false;
|
|
1801
2765
|
const now = Date.now();
|
|
1802
2766
|
while (this.#sendTimestamps.length && now - this.#sendTimestamps[0] >= 60000)
|
|
1803
2767
|
this.#sendTimestamps.shift();
|
|
1804
|
-
if (this.#sendTimestamps.length >= 115) {
|
|
2768
|
+
if (!privileged && this.#sendTimestamps.length >= 115) {
|
|
1805
2769
|
this.#emitError(new GatewayError("Gateway send rate budget exhausted."));
|
|
1806
2770
|
return false;
|
|
1807
2771
|
}
|
|
@@ -1872,7 +2836,11 @@ class Gateway {
|
|
|
1872
2836
|
ws.addEventListener("message", (event) => {
|
|
1873
2837
|
this.#lastMessageAt = Date.now();
|
|
1874
2838
|
this.#zombieReported = false;
|
|
1875
|
-
this.#
|
|
2839
|
+
if (this.#options.compress && event.data instanceof ArrayBuffer) {
|
|
2840
|
+
this.#decompress(new Uint8Array(event.data)).then((text) => this.#message(ws, text)).catch((err) => this.#emitError(err));
|
|
2841
|
+
} else {
|
|
2842
|
+
this.#message(ws, String(event.data));
|
|
2843
|
+
}
|
|
1876
2844
|
});
|
|
1877
2845
|
ws.addEventListener("close", (event) => this.#close(ws, event.code));
|
|
1878
2846
|
ws.addEventListener("error", () => this.#emitError(new GatewayError("Gateway WebSocket error")));
|
|
@@ -1880,7 +2848,7 @@ class Gateway {
|
|
|
1880
2848
|
#startZombieDetection() {
|
|
1881
2849
|
if (this.#zombieTimer)
|
|
1882
2850
|
clearInterval(this.#zombieTimer);
|
|
1883
|
-
const interval = Math.max(1, Math.min(
|
|
2851
|
+
const interval = Math.max(1, Math.min(1000, this.#options.heartbeatAckTimeout, this.#options.zombieTimeout / 2));
|
|
1884
2852
|
this.#zombieTimer = setInterval(() => {
|
|
1885
2853
|
if (this.#closed || this.#ws?.readyState !== WebSocket.OPEN || this.#lastMessageAt === 0)
|
|
1886
2854
|
return;
|
|
@@ -1931,18 +2899,24 @@ class Gateway {
|
|
|
1931
2899
|
break;
|
|
1932
2900
|
case GatewayOpcodes.HeartbeatAck:
|
|
1933
2901
|
this.#heartbeatACK = true;
|
|
2902
|
+
this.ping = Date.now() - this.#heartbeatSentAt;
|
|
1934
2903
|
this.#clearHeartbeatAckTimer();
|
|
1935
2904
|
this.#emit("heartbeatAck", payload.d);
|
|
1936
2905
|
break;
|
|
1937
2906
|
case GatewayOpcodes.Reconnect:
|
|
1938
2907
|
ws.close(1001, "Server requested reconnect");
|
|
1939
2908
|
break;
|
|
1940
|
-
case GatewayOpcodes.InvalidSession:
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
2909
|
+
case GatewayOpcodes.InvalidSession: {
|
|
2910
|
+
const resumable = payload.d === true;
|
|
2911
|
+
if (!resumable) {
|
|
2912
|
+
this.#sessionId = undefined;
|
|
2913
|
+
this.#sequence = null;
|
|
2914
|
+
this.#resumeURL = undefined;
|
|
2915
|
+
}
|
|
2916
|
+
this.#emit("invalidSession", resumable);
|
|
2917
|
+
ws.close(resumable ? GatewayCloseCodes.UnknownError : 1000, resumable ? "Invalid session (resumable)" : "Invalid session");
|
|
1945
2918
|
break;
|
|
2919
|
+
}
|
|
1946
2920
|
}
|
|
1947
2921
|
}
|
|
1948
2922
|
#handleDispatch(event, data) {
|
|
@@ -1957,7 +2931,14 @@ class Gateway {
|
|
|
1957
2931
|
this.#attempt = 0;
|
|
1958
2932
|
this.#setState("READY" /* Ready */);
|
|
1959
2933
|
this.#emit("ready", data);
|
|
2934
|
+
} else if (event === "RESUMED") {
|
|
2935
|
+
this.#attempt = 0;
|
|
2936
|
+
this.#setState("READY" /* Ready */);
|
|
2937
|
+
this.#emit("resumed", data);
|
|
1960
2938
|
}
|
|
2939
|
+
this.#emit("RAW", { event: event ?? "UNKNOWN", data });
|
|
2940
|
+
if (this.#closed)
|
|
2941
|
+
return;
|
|
1961
2942
|
this.#emit(event ?? "dispatch", data);
|
|
1962
2943
|
}
|
|
1963
2944
|
#handleHello(data) {
|
|
@@ -2031,12 +3012,12 @@ class Gateway {
|
|
|
2031
3012
|
#sendHeartbeat() {
|
|
2032
3013
|
this.#heartbeatACK = false;
|
|
2033
3014
|
this.#heartbeatSentAt = Date.now();
|
|
2034
|
-
if (!this
|
|
3015
|
+
if (!this.#dispatch({
|
|
2035
3016
|
op: GatewayOpcodes.Heartbeat,
|
|
2036
3017
|
d: this.#sequence,
|
|
2037
3018
|
s: null,
|
|
2038
3019
|
t: null
|
|
2039
|
-
})) {
|
|
3020
|
+
}, true)) {
|
|
2040
3021
|
this.#emitError(new GatewayError("Unable to send Gateway heartbeat because the WebSocket is not open."));
|
|
2041
3022
|
return;
|
|
2042
3023
|
}
|
|
@@ -2069,14 +3050,23 @@ class Gateway {
|
|
|
2069
3050
|
if (action === "identify") {
|
|
2070
3051
|
this.#sequence = null;
|
|
2071
3052
|
this.#sessionId = undefined;
|
|
3053
|
+
this.#resumeURL = undefined;
|
|
2072
3054
|
}
|
|
2073
3055
|
this.#setState("RECONNECT" /* Reconnect */);
|
|
2074
3056
|
this.#scheduleReconnect();
|
|
2075
3057
|
}
|
|
2076
3058
|
#closeAction(code) {
|
|
2077
|
-
|
|
3059
|
+
const fatal = [
|
|
3060
|
+
GatewayCloseCodes.AuthenticationFailed,
|
|
3061
|
+
GatewayCloseCodes.InvalidShard,
|
|
3062
|
+
GatewayCloseCodes.ShardingRequired,
|
|
3063
|
+
GatewayCloseCodes.InvalidAPIVersion,
|
|
3064
|
+
GatewayCloseCodes.InvalidIntents,
|
|
3065
|
+
GatewayCloseCodes.DisallowedIntents
|
|
3066
|
+
];
|
|
3067
|
+
if (fatal.includes(code))
|
|
2078
3068
|
return "stop";
|
|
2079
|
-
if (
|
|
3069
|
+
if (code === GatewayCloseCodes.InvalidSeq || code === GatewayCloseCodes.SessionTimedOut)
|
|
2080
3070
|
return "identify";
|
|
2081
3071
|
return this.#sessionId && this.#sequence !== null ? "resume" : "identify";
|
|
2082
3072
|
}
|
|
@@ -2089,7 +3079,7 @@ class Gateway {
|
|
|
2089
3079
|
return;
|
|
2090
3080
|
}
|
|
2091
3081
|
const delay = Math.min(this.#options.reconnectMaxDelay, this.#options.reconnectBaseDelay * 2 ** this.#attempt++);
|
|
2092
|
-
const jitter = Math.random() * Math.
|
|
3082
|
+
const jitter = Math.random() * Math.max(1, delay * 0.25);
|
|
2093
3083
|
this.#reconnectTimer = setTimeout(() => {
|
|
2094
3084
|
this.#reconnectTimer = undefined;
|
|
2095
3085
|
this.#open(this.#resumeURL ?? "wss://gateway.discord.gg/?v=10&encoding=json");
|
|
@@ -2159,690 +3149,36 @@ class Gateway {
|
|
|
2159
3149
|
this.state = next;
|
|
2160
3150
|
this.#emit("stateChange", { previous, next });
|
|
2161
3151
|
}
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
this.#data.title = validate(value, 256, "Embed title");
|
|
2168
|
-
return this;
|
|
2169
|
-
}
|
|
2170
|
-
setDescription(value) {
|
|
2171
|
-
this.#data.description = validate(value, 4096, "Embed description");
|
|
2172
|
-
return this;
|
|
2173
|
-
}
|
|
2174
|
-
setURL(value) {
|
|
2175
|
-
this.#data.url = url(value, "Embed URL");
|
|
2176
|
-
return this;
|
|
2177
|
-
}
|
|
2178
|
-
setColor(value) {
|
|
2179
|
-
if (!Number.isInteger(value) || value < 0 || value > 16777215)
|
|
2180
|
-
throw new RangeError("Embed color must be an integer between 0 and 16777215.");
|
|
2181
|
-
this.#data.color = value;
|
|
2182
|
-
return this;
|
|
2183
|
-
}
|
|
2184
|
-
setTimestamp(value = new Date) {
|
|
2185
|
-
const date = value instanceof Date ? value : new Date(value);
|
|
2186
|
-
if (Number.isNaN(date.getTime()))
|
|
2187
|
-
throw new RangeError("Embed timestamp must be a valid date.");
|
|
2188
|
-
this.#data.timestamp = date.toISOString();
|
|
2189
|
-
return this;
|
|
2190
|
-
}
|
|
2191
|
-
setFooter(value) {
|
|
2192
|
-
this.#data.footer = {
|
|
2193
|
-
text: validate(value.text, 2048, "Footer text"),
|
|
2194
|
-
...value.icon_url ? { icon_url: url(value.icon_url, "Footer icon URL") } : {}
|
|
2195
|
-
};
|
|
2196
|
-
return this;
|
|
2197
|
-
}
|
|
2198
|
-
setAuthor(value) {
|
|
2199
|
-
this.#data.author = {
|
|
2200
|
-
name: validate(value.name, 256, "Author name"),
|
|
2201
|
-
...value.url ? { url: url(value.url, "Author URL") } : {},
|
|
2202
|
-
...value.icon_url ? { icon_url: url(value.icon_url, "Author icon URL") } : {}
|
|
3152
|
+
#initDecompressor() {
|
|
3153
|
+
const ds = new DecompressionStream("deflate-raw");
|
|
3154
|
+
this.#decompressor = {
|
|
3155
|
+
writer: ds.writable.getWriter(),
|
|
3156
|
+
reader: ds.readable.getReader()
|
|
2203
3157
|
};
|
|
2204
|
-
return this;
|
|
2205
|
-
}
|
|
2206
|
-
setThumbnail(value) {
|
|
2207
|
-
const valueURL = typeof value === "string" ? value : value.url;
|
|
2208
|
-
this.#data.thumbnail = { url: url(valueURL, "Thumbnail URL") };
|
|
2209
|
-
return this;
|
|
2210
|
-
}
|
|
2211
|
-
setImage(value) {
|
|
2212
|
-
const valueURL = typeof value === "string" ? value : value.url;
|
|
2213
|
-
this.#data.image = { url: url(valueURL, "Image URL") };
|
|
2214
|
-
return this;
|
|
2215
|
-
}
|
|
2216
|
-
addFields(...fields) {
|
|
2217
|
-
if (!fields.length)
|
|
2218
|
-
throw new TypeError("At least one embed field is required.");
|
|
2219
|
-
const current = this.#data.fields ?? [];
|
|
2220
|
-
if (current.length + fields.length > 25)
|
|
2221
|
-
throw new RangeError("An embed cannot contain more than 25 fields.");
|
|
2222
|
-
for (const field of fields) {
|
|
2223
|
-
validate(field.name, 256, "Embed field name");
|
|
2224
|
-
validate(field.value, 1024, "Embed field value");
|
|
2225
|
-
}
|
|
2226
|
-
this.#data.fields = [...current, ...fields.map((field) => ({ ...field }))];
|
|
2227
|
-
return this;
|
|
2228
|
-
}
|
|
2229
|
-
setFields(fields) {
|
|
2230
|
-
this.#data.fields = [];
|
|
2231
|
-
return this.addFields(...fields);
|
|
2232
|
-
}
|
|
2233
|
-
spliceFields(index, deleteCount, ...fields) {
|
|
2234
|
-
const current = [...this.#data.fields ?? []];
|
|
2235
|
-
if (!Number.isInteger(index) || !Number.isInteger(deleteCount) || index < 0 || deleteCount < 0)
|
|
2236
|
-
throw new RangeError("Field index and delete count must be non-negative integers.");
|
|
2237
|
-
current.splice(index, deleteCount, ...fields);
|
|
2238
|
-
if (current.length > 25)
|
|
2239
|
-
throw new RangeError("An embed cannot contain more than 25 fields.");
|
|
2240
|
-
this.#data.fields = current;
|
|
2241
|
-
return this;
|
|
2242
|
-
}
|
|
2243
|
-
clearFields() {
|
|
2244
|
-
delete this.#data.fields;
|
|
2245
|
-
return this;
|
|
2246
|
-
}
|
|
2247
|
-
clearTitle() {
|
|
2248
|
-
delete this.#data.title;
|
|
2249
|
-
return this;
|
|
2250
|
-
}
|
|
2251
|
-
clearDescription() {
|
|
2252
|
-
delete this.#data.description;
|
|
2253
|
-
return this;
|
|
2254
|
-
}
|
|
2255
|
-
get data() {
|
|
2256
|
-
return this.toJSON();
|
|
2257
|
-
}
|
|
2258
|
-
toJSON() {
|
|
2259
|
-
return structuredClone(this.#data);
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
function validate(value, max, field) {
|
|
2263
|
-
if (typeof value !== "string" || value.length === 0 || value.length > max)
|
|
2264
|
-
throw new RangeError(`${field} must contain 1-${max} characters.`);
|
|
2265
|
-
return value;
|
|
2266
|
-
}
|
|
2267
|
-
function url(value, field) {
|
|
2268
|
-
try {
|
|
2269
|
-
return new URL(value).toString();
|
|
2270
|
-
} catch (error) {
|
|
2271
|
-
throw new TypeError(`${field} must be a valid URL.`, { cause: error });
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
// packages/builders/src/components.ts
|
|
2275
|
-
var ComponentType = {
|
|
2276
|
-
ActionRow: 1,
|
|
2277
|
-
Button: 2,
|
|
2278
|
-
StringSelect: 3,
|
|
2279
|
-
TextInput: 4,
|
|
2280
|
-
UserSelect: 5,
|
|
2281
|
-
RoleSelect: 6,
|
|
2282
|
-
MentionableSelect: 7,
|
|
2283
|
-
ChannelSelect: 8
|
|
2284
|
-
};
|
|
2285
|
-
var ButtonStyle = {
|
|
2286
|
-
Primary: 1,
|
|
2287
|
-
Secondary: 2,
|
|
2288
|
-
Success: 3,
|
|
2289
|
-
Danger: 4,
|
|
2290
|
-
Link: 5
|
|
2291
|
-
};
|
|
2292
|
-
class ActionRowBuilder {
|
|
2293
|
-
#components = [];
|
|
2294
|
-
addComponents(...components) {
|
|
2295
|
-
if (!components.length)
|
|
2296
|
-
throw new TypeError("At least one component is required.");
|
|
2297
|
-
if (this.#components.length + components.length > 5)
|
|
2298
|
-
throw new RangeError("An action row cannot contain more than 5 components.");
|
|
2299
|
-
this.#components.push(...components);
|
|
2300
|
-
return this;
|
|
2301
|
-
}
|
|
2302
|
-
clearComponents() {
|
|
2303
|
-
this.#components.length = 0;
|
|
2304
|
-
return this;
|
|
2305
|
-
}
|
|
2306
|
-
toJSON() {
|
|
2307
|
-
return {
|
|
2308
|
-
type: ComponentType.ActionRow,
|
|
2309
|
-
components: this.#components.map((component) => component.toJSON())
|
|
2310
|
-
};
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
class StringSelectBuilder {
|
|
2315
|
-
#data = {
|
|
2316
|
-
type: ComponentType.StringSelect
|
|
2317
|
-
};
|
|
2318
|
-
setCustomId(value) {
|
|
2319
|
-
validateText(value, 100, "Component custom ID");
|
|
2320
|
-
this.#data.custom_id = value;
|
|
2321
|
-
return this;
|
|
2322
|
-
}
|
|
2323
|
-
setPlaceholder(value) {
|
|
2324
|
-
validateText(value, 150, "Component placeholder");
|
|
2325
|
-
this.#data.placeholder = value;
|
|
2326
|
-
return this;
|
|
2327
|
-
}
|
|
2328
|
-
setMinValues(value) {
|
|
2329
|
-
validateCount(value, "min_values", 0);
|
|
2330
|
-
this.#data.min_values = value;
|
|
2331
|
-
return this;
|
|
2332
|
-
}
|
|
2333
|
-
setMaxValues(value) {
|
|
2334
|
-
validateCount(value, "max_values", 1);
|
|
2335
|
-
this.#data.max_values = value;
|
|
2336
|
-
return this;
|
|
2337
|
-
}
|
|
2338
|
-
setRequired(value = true) {
|
|
2339
|
-
this.#data.required = value;
|
|
2340
|
-
return this;
|
|
2341
|
-
}
|
|
2342
|
-
setDisabled(value = true) {
|
|
2343
|
-
this.#data.disabled = value;
|
|
2344
|
-
return this;
|
|
2345
|
-
}
|
|
2346
|
-
addOptions(...options) {
|
|
2347
|
-
if (!options.length)
|
|
2348
|
-
throw new TypeError("At least one select option is required.");
|
|
2349
|
-
const current = this.#data.options ?? [];
|
|
2350
|
-
if (current.length + options.length > 25)
|
|
2351
|
-
throw new RangeError("A string select cannot contain more than 25 options.");
|
|
2352
|
-
for (const option of options) {
|
|
2353
|
-
validateText(option.label, 100, "Select option label");
|
|
2354
|
-
validateText(option.value, 100, "Select option value");
|
|
2355
|
-
if (option.description)
|
|
2356
|
-
validateText(option.description, 100, "Select option description");
|
|
2357
|
-
}
|
|
2358
|
-
this.#data.options = [
|
|
2359
|
-
...current,
|
|
2360
|
-
...options.map((option) => ({ ...option }))
|
|
2361
|
-
];
|
|
2362
|
-
return this;
|
|
2363
|
-
}
|
|
2364
|
-
toJSON() {
|
|
2365
|
-
return structuredClone(this.#data);
|
|
2366
|
-
}
|
|
2367
|
-
}
|
|
2368
|
-
|
|
2369
|
-
class ButtonBuilder {
|
|
2370
|
-
#data = {
|
|
2371
|
-
type: ComponentType.Button,
|
|
2372
|
-
style: ButtonStyle.Secondary
|
|
2373
|
-
};
|
|
2374
|
-
setStyle(style) {
|
|
2375
|
-
this.#data.style = style;
|
|
2376
|
-
if (style === ButtonStyle.Link)
|
|
2377
|
-
delete this.#data.custom_id;
|
|
2378
|
-
return this;
|
|
2379
|
-
}
|
|
2380
|
-
setCustomId(value) {
|
|
2381
|
-
validateText(value, 100, "Button custom ID");
|
|
2382
|
-
if (this.#data.style === ButtonStyle.Link)
|
|
2383
|
-
throw new TypeError("Link buttons cannot use custom IDs.");
|
|
2384
|
-
this.#data.custom_id = value;
|
|
2385
|
-
return this;
|
|
2386
|
-
}
|
|
2387
|
-
setLabel(value) {
|
|
2388
|
-
validateText(value, 80, "Button label");
|
|
2389
|
-
this.#data.label = value;
|
|
2390
|
-
return this;
|
|
2391
|
-
}
|
|
2392
|
-
setURL(value) {
|
|
2393
|
-
validateText(value, 512, "Button URL");
|
|
2394
|
-
let url2;
|
|
2395
|
-
try {
|
|
2396
|
-
url2 = new URL(value);
|
|
2397
|
-
} catch (error) {
|
|
2398
|
-
throw new TypeError("Button URL must be a valid URL.", { cause: error });
|
|
2399
|
-
}
|
|
2400
|
-
this.#data.style = ButtonStyle.Link;
|
|
2401
|
-
delete this.#data.custom_id;
|
|
2402
|
-
this.#data.url = url2.toString();
|
|
2403
|
-
return this;
|
|
2404
|
-
}
|
|
2405
|
-
setEmoji(emoji) {
|
|
2406
|
-
this.#data.emoji = typeof emoji === "string" ? { name: emoji } : { ...emoji };
|
|
2407
|
-
return this;
|
|
2408
|
-
}
|
|
2409
|
-
setDisabled(value = true) {
|
|
2410
|
-
this.#data.disabled = value;
|
|
2411
|
-
return this;
|
|
2412
|
-
}
|
|
2413
|
-
toJSON() {
|
|
2414
|
-
return structuredClone(this.#data);
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
function validateText(value, max, field) {
|
|
2418
|
-
if (typeof value !== "string")
|
|
2419
|
-
throw new TypeError(`${field} must be a string.`);
|
|
2420
|
-
if (!value.trim())
|
|
2421
|
-
throw new RangeError(`${field} must be a non-empty string.`);
|
|
2422
|
-
if (value.length > max)
|
|
2423
|
-
throw new RangeError(`${field} cannot exceed ${max} characters.`);
|
|
2424
|
-
}
|
|
2425
|
-
function validateCount(value, field, min, max = 25) {
|
|
2426
|
-
if (!Number.isInteger(value) || value < min || value > max)
|
|
2427
|
-
throw new RangeError(`${field} must be an integer between ${min} and ${max}.`);
|
|
2428
|
-
}
|
|
2429
|
-
// packages/builders/src/commands.ts
|
|
2430
|
-
var ApplicationCommandOptionType2 = {
|
|
2431
|
-
Subcommand: 1,
|
|
2432
|
-
SubcommandGroup: 2,
|
|
2433
|
-
String: 3,
|
|
2434
|
-
Integer: 4,
|
|
2435
|
-
Boolean: 5,
|
|
2436
|
-
User: 6,
|
|
2437
|
-
Channel: 7,
|
|
2438
|
-
Role: 8,
|
|
2439
|
-
Mentionable: 9,
|
|
2440
|
-
Number: 10,
|
|
2441
|
-
Attachment: 11
|
|
2442
|
-
};
|
|
2443
|
-
|
|
2444
|
-
class SlashCommandBuilder {
|
|
2445
|
-
#data = { type: 1 };
|
|
2446
|
-
setName(name) {
|
|
2447
|
-
validateName(name, "Command name");
|
|
2448
|
-
this.#data.name = name;
|
|
2449
|
-
return this;
|
|
2450
|
-
}
|
|
2451
|
-
setDescription(description) {
|
|
2452
|
-
validateText2(description, "Command description", 100);
|
|
2453
|
-
this.#data.description = description;
|
|
2454
|
-
return this;
|
|
2455
|
-
}
|
|
2456
|
-
setDMPermission(enabled) {
|
|
2457
|
-
this.#data.dm_permission = enabled;
|
|
2458
|
-
return this;
|
|
2459
|
-
}
|
|
2460
|
-
setNSFW(nsfw = true) {
|
|
2461
|
-
this.#data.nsfw = nsfw;
|
|
2462
|
-
return this;
|
|
2463
|
-
}
|
|
2464
|
-
setNsfw(nsfw = true) {
|
|
2465
|
-
return this.setNSFW(nsfw);
|
|
2466
|
-
}
|
|
2467
|
-
setDefaultMemberPermissions(permissions) {
|
|
2468
|
-
this.#data.default_member_permissions = permissions === null ? null : BigInt(permissions).toString();
|
|
2469
|
-
return this;
|
|
2470
|
-
}
|
|
2471
|
-
setIntegrationTypes(...types) {
|
|
2472
|
-
this.#data.integration_types = [...types];
|
|
2473
|
-
return this;
|
|
2474
|
-
}
|
|
2475
|
-
addStringOption(configure) {
|
|
2476
|
-
return this.addOption(configure(new StringOptionBuilder));
|
|
2477
|
-
}
|
|
2478
|
-
addIntegerOption(configure) {
|
|
2479
|
-
return this.addOption(configure(new IntegerOptionBuilder));
|
|
2480
|
-
}
|
|
2481
|
-
addNumberOption(configure) {
|
|
2482
|
-
return this.addOption(configure(new NumberOptionBuilder));
|
|
2483
|
-
}
|
|
2484
|
-
addBooleanOption(configure) {
|
|
2485
|
-
return this.addOption(configure(new BooleanOptionBuilder));
|
|
2486
3158
|
}
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
}
|
|
2502
|
-
addSubcommand(configure) {
|
|
2503
|
-
return this.addOption(configure(new SubcommandBuilder));
|
|
2504
|
-
}
|
|
2505
|
-
addSubcommandGroup(configure) {
|
|
2506
|
-
return this.addOption(configure(new SubcommandGroupBuilder));
|
|
2507
|
-
}
|
|
2508
|
-
toJSON() {
|
|
2509
|
-
return structuredClone(this.#data);
|
|
2510
|
-
}
|
|
2511
|
-
addOption(option) {
|
|
2512
|
-
const options = this.#data.options ?? [];
|
|
2513
|
-
if (options.length >= 25)
|
|
2514
|
-
throw new RangeError("An application command cannot contain more than 25 options.");
|
|
2515
|
-
const payload = option.toJSON();
|
|
2516
|
-
if (options.some((existing) => existing.name === payload.name))
|
|
2517
|
-
throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
|
|
2518
|
-
if (payload.required === true && options.some((existing) => existing.required !== true))
|
|
2519
|
-
throw new RangeError("Required application command options must be placed before optional options.");
|
|
2520
|
-
options.push(payload);
|
|
2521
|
-
this.#data.options = options;
|
|
2522
|
-
return this;
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
|
-
class CommandOptionBuilder {
|
|
2527
|
-
data;
|
|
2528
|
-
constructor(type) {
|
|
2529
|
-
this.data = { type };
|
|
2530
|
-
}
|
|
2531
|
-
setName(name) {
|
|
2532
|
-
validateName(name, "Option name");
|
|
2533
|
-
this.data.name = name;
|
|
2534
|
-
return this;
|
|
2535
|
-
}
|
|
2536
|
-
setDescription(description) {
|
|
2537
|
-
validateText2(description, "Option description", 100);
|
|
2538
|
-
this.data.description = description;
|
|
2539
|
-
return this;
|
|
2540
|
-
}
|
|
2541
|
-
setRequired(required = true) {
|
|
2542
|
-
this.data.required = required;
|
|
2543
|
-
return this;
|
|
2544
|
-
}
|
|
2545
|
-
setAutocomplete(enabled = true) {
|
|
2546
|
-
this.data.autocomplete = enabled;
|
|
2547
|
-
return this;
|
|
2548
|
-
}
|
|
2549
|
-
toJSON() {
|
|
2550
|
-
return structuredClone(this.data);
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
class StringOptionBuilder extends CommandOptionBuilder {
|
|
2555
|
-
constructor() {
|
|
2556
|
-
super(ApplicationCommandOptionType2.String);
|
|
2557
|
-
}
|
|
2558
|
-
addChoices(...choices) {
|
|
2559
|
-
const current = this.data.choices ?? [];
|
|
2560
|
-
if (!choices.length)
|
|
2561
|
-
throw new TypeError("At least one choice is required.");
|
|
2562
|
-
if (this.data.autocomplete === true)
|
|
2563
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
2564
|
-
if (current.length + choices.length > 25)
|
|
2565
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
2566
|
-
for (const choice of choices) {
|
|
2567
|
-
validateText2(choice.name, "Choice name", 100);
|
|
2568
|
-
validateText2(choice.value, "Choice value", 100);
|
|
2569
|
-
}
|
|
2570
|
-
this.data.choices = [
|
|
2571
|
-
...current,
|
|
2572
|
-
...choices.map((choice) => ({ ...choice }))
|
|
2573
|
-
];
|
|
2574
|
-
return this;
|
|
2575
|
-
}
|
|
2576
|
-
setMinLength(value) {
|
|
2577
|
-
validateIntegerRange(value, 0, 6000, "min_length");
|
|
2578
|
-
this.data.min_length = value;
|
|
2579
|
-
return this;
|
|
2580
|
-
}
|
|
2581
|
-
setMaxLength(value) {
|
|
2582
|
-
validateIntegerRange(value, 1, 6000, "max_length");
|
|
2583
|
-
if (this.data.min_length !== undefined && this.data.min_length > value)
|
|
2584
|
-
throw new RangeError("min_length cannot exceed max_length.");
|
|
2585
|
-
this.data.max_length = value;
|
|
2586
|
-
return this;
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
|
|
2590
|
-
class IntegerOptionBuilder extends CommandOptionBuilder {
|
|
2591
|
-
constructor() {
|
|
2592
|
-
super(ApplicationCommandOptionType2.Integer);
|
|
2593
|
-
}
|
|
2594
|
-
setMinValue(value) {
|
|
2595
|
-
validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", true);
|
|
2596
|
-
this.data.min_value = value;
|
|
2597
|
-
return this;
|
|
2598
|
-
}
|
|
2599
|
-
setMaxValue(value) {
|
|
2600
|
-
validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", true);
|
|
2601
|
-
if (this.data.min_value !== undefined && this.data.min_value > value)
|
|
2602
|
-
throw new RangeError("min_value cannot exceed max_value.");
|
|
2603
|
-
this.data.max_value = value;
|
|
2604
|
-
return this;
|
|
2605
|
-
}
|
|
2606
|
-
setAutocomplete(enabled = true) {
|
|
2607
|
-
if (enabled && Array.isArray(this.data.choices) && this.data.choices.length)
|
|
2608
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
2609
|
-
this.data.autocomplete = enabled;
|
|
2610
|
-
return this;
|
|
2611
|
-
}
|
|
2612
|
-
addChoices(...choices) {
|
|
2613
|
-
const current = this.data.choices ?? [];
|
|
2614
|
-
if (!choices.length)
|
|
2615
|
-
throw new TypeError("At least one choice is required.");
|
|
2616
|
-
if (this.data.autocomplete === true)
|
|
2617
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
2618
|
-
if (current.length + choices.length > 25)
|
|
2619
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
2620
|
-
this.data.choices = [...current, ...choices];
|
|
2621
|
-
return this;
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
class NumberOptionBuilder extends CommandOptionBuilder {
|
|
2626
|
-
constructor() {
|
|
2627
|
-
super(ApplicationCommandOptionType2.Number);
|
|
2628
|
-
}
|
|
2629
|
-
setMinValue(value) {
|
|
2630
|
-
validateNumberRange(value, -9007199254740991, 9007199254740991, "min_value", false);
|
|
2631
|
-
this.data.min_value = value;
|
|
2632
|
-
return this;
|
|
2633
|
-
}
|
|
2634
|
-
setMaxValue(value) {
|
|
2635
|
-
validateNumberRange(value, -9007199254740991, 9007199254740991, "max_value", false);
|
|
2636
|
-
if (this.data.min_value !== undefined && this.data.min_value > value)
|
|
2637
|
-
throw new RangeError("min_value cannot exceed max_value.");
|
|
2638
|
-
this.data.max_value = value;
|
|
2639
|
-
return this;
|
|
2640
|
-
}
|
|
2641
|
-
setAutocomplete(enabled = true) {
|
|
2642
|
-
if (enabled && Array.isArray(this.data.choices) && this.data.choices.length)
|
|
2643
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
2644
|
-
this.data.autocomplete = enabled;
|
|
2645
|
-
return this;
|
|
2646
|
-
}
|
|
2647
|
-
addChoices(...choices) {
|
|
2648
|
-
const current = this.data.choices ?? [];
|
|
2649
|
-
if (!choices.length)
|
|
2650
|
-
throw new TypeError("At least one choice is required.");
|
|
2651
|
-
if (this.data.autocomplete === true)
|
|
2652
|
-
throw new RangeError("Autocomplete options cannot define choices.");
|
|
2653
|
-
if (current.length + choices.length > 25)
|
|
2654
|
-
throw new RangeError("An option cannot contain more than 25 choices.");
|
|
2655
|
-
this.data.choices = [...current, ...choices];
|
|
2656
|
-
return this;
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
|
|
2660
|
-
class BooleanOptionBuilder extends CommandOptionBuilder {
|
|
2661
|
-
constructor() {
|
|
2662
|
-
super(ApplicationCommandOptionType2.Boolean);
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
|
|
2666
|
-
class UserOptionBuilder extends CommandOptionBuilder {
|
|
2667
|
-
constructor() {
|
|
2668
|
-
super(ApplicationCommandOptionType2.User);
|
|
2669
|
-
}
|
|
2670
|
-
}
|
|
2671
|
-
|
|
2672
|
-
class RoleOptionBuilder extends CommandOptionBuilder {
|
|
2673
|
-
constructor() {
|
|
2674
|
-
super(ApplicationCommandOptionType2.Role);
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
|
-
|
|
2678
|
-
class MentionableOptionBuilder extends CommandOptionBuilder {
|
|
2679
|
-
constructor() {
|
|
2680
|
-
super(ApplicationCommandOptionType2.Mentionable);
|
|
2681
|
-
}
|
|
2682
|
-
}
|
|
2683
|
-
|
|
2684
|
-
class AttachmentOptionBuilder extends CommandOptionBuilder {
|
|
2685
|
-
constructor() {
|
|
2686
|
-
super(ApplicationCommandOptionType2.Attachment);
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
|
|
2690
|
-
class ChannelOptionBuilder extends CommandOptionBuilder {
|
|
2691
|
-
constructor() {
|
|
2692
|
-
super(ApplicationCommandOptionType2.Channel);
|
|
2693
|
-
}
|
|
2694
|
-
addChannelTypes(...types) {
|
|
2695
|
-
if (types.some((type) => !Number.isInteger(type) || type < 0))
|
|
2696
|
-
throw new RangeError("Channel types must be non-negative integers.");
|
|
2697
|
-
this.data.channel_types = [...new Set(types)];
|
|
2698
|
-
return this;
|
|
2699
|
-
}
|
|
2700
|
-
}
|
|
2701
|
-
|
|
2702
|
-
class SubcommandBuilder extends CommandOptionBuilder {
|
|
2703
|
-
constructor() {
|
|
2704
|
-
super(ApplicationCommandOptionType2.Subcommand);
|
|
2705
|
-
}
|
|
2706
|
-
addStringOption(configure) {
|
|
2707
|
-
return this.addChildOption(configure(new StringOptionBuilder));
|
|
2708
|
-
}
|
|
2709
|
-
addIntegerOption(configure) {
|
|
2710
|
-
return this.addChildOption(configure(new IntegerOptionBuilder));
|
|
2711
|
-
}
|
|
2712
|
-
addNumberOption(configure) {
|
|
2713
|
-
return this.addChildOption(configure(new NumberOptionBuilder));
|
|
2714
|
-
}
|
|
2715
|
-
addBooleanOption(configure) {
|
|
2716
|
-
return this.addChildOption(configure(new BooleanOptionBuilder));
|
|
2717
|
-
}
|
|
2718
|
-
addUserOption(configure) {
|
|
2719
|
-
return this.addChildOption(configure(new UserOptionBuilder));
|
|
2720
|
-
}
|
|
2721
|
-
addChannelOption(configure) {
|
|
2722
|
-
return this.addChildOption(configure(new ChannelOptionBuilder));
|
|
2723
|
-
}
|
|
2724
|
-
addRoleOption(configure) {
|
|
2725
|
-
return this.addChildOption(configure(new RoleOptionBuilder));
|
|
2726
|
-
}
|
|
2727
|
-
addMentionableOption(configure) {
|
|
2728
|
-
return this.addChildOption(configure(new MentionableOptionBuilder));
|
|
2729
|
-
}
|
|
2730
|
-
addAttachmentOption(configure) {
|
|
2731
|
-
return this.addChildOption(configure(new AttachmentOptionBuilder));
|
|
2732
|
-
}
|
|
2733
|
-
addChildOption(option) {
|
|
2734
|
-
const options = this.data.options ?? [];
|
|
2735
|
-
if (options.length >= 25)
|
|
2736
|
-
throw new RangeError("A subcommand cannot contain more than 25 options.");
|
|
2737
|
-
const payload = option.toJSON();
|
|
2738
|
-
if (options.some((existing) => existing.name === payload.name))
|
|
2739
|
-
throw new RangeError(`Duplicate option name: ${String(payload.name)}.`);
|
|
2740
|
-
if (payload.required === true && options.some((existing) => existing.required !== true))
|
|
2741
|
-
throw new RangeError("Required subcommand options must be placed before optional options.");
|
|
2742
|
-
if (options.some((existing) => existing.type === ApplicationCommandOptionType2.Subcommand))
|
|
2743
|
-
throw new RangeError("Subcommands cannot contain nested subcommands.");
|
|
2744
|
-
options.push(payload);
|
|
2745
|
-
this.data.options = options;
|
|
2746
|
-
return this;
|
|
2747
|
-
}
|
|
2748
|
-
}
|
|
2749
|
-
|
|
2750
|
-
class SubcommandGroupBuilder extends CommandOptionBuilder {
|
|
2751
|
-
constructor() {
|
|
2752
|
-
super(ApplicationCommandOptionType2.SubcommandGroup);
|
|
2753
|
-
}
|
|
2754
|
-
addSubcommand(configure) {
|
|
2755
|
-
const options = this.data.options ?? [];
|
|
2756
|
-
if (options.length >= 25)
|
|
2757
|
-
throw new RangeError("A subcommand group cannot contain more than 25 subcommands.");
|
|
2758
|
-
const payload = configure(new SubcommandBuilder).toJSON();
|
|
2759
|
-
if (options.some((existing) => existing.name === payload.name))
|
|
2760
|
-
throw new RangeError(`Duplicate subcommand name: ${String(payload.name)}.`);
|
|
2761
|
-
if (payload.type !== ApplicationCommandOptionType2.Subcommand)
|
|
2762
|
-
throw new TypeError("Subcommand group children must be subcommands.");
|
|
2763
|
-
options.push(payload);
|
|
2764
|
-
this.data.options = options;
|
|
2765
|
-
return this;
|
|
2766
|
-
}
|
|
2767
|
-
}
|
|
2768
|
-
function validateName(value, field) {
|
|
2769
|
-
if (!/^[\p{L}\p{N}_-]{1,32}$/u.test(value) || value !== value.toLowerCase())
|
|
2770
|
-
throw new RangeError(`${field} must contain 1-32 lowercase letters, numbers, underscores, or hyphens.`);
|
|
2771
|
-
}
|
|
2772
|
-
function validateText2(value, field, max) {
|
|
2773
|
-
if (typeof value !== "string" || !value.trim() || value.length > max)
|
|
2774
|
-
throw new RangeError(`${field} must contain 1-${max} characters.`);
|
|
2775
|
-
}
|
|
2776
|
-
function validateIntegerRange(value, minimum, maximum, field) {
|
|
2777
|
-
if (!Number.isInteger(value) || value < minimum || value > maximum)
|
|
2778
|
-
throw new RangeError(`${field} must be an integer between ${minimum} and ${maximum}.`);
|
|
2779
|
-
}
|
|
2780
|
-
function validateNumberRange(value, minimum, maximum, field, integerOnly = true) {
|
|
2781
|
-
if (!Number.isFinite(value) || integerOnly && !Number.isInteger(value) || value < minimum || value > maximum)
|
|
2782
|
-
throw new RangeError(`${field} must be ${integerOnly ? "an integer" : "a number"} between ${minimum} and ${maximum}.`);
|
|
2783
|
-
}
|
|
2784
|
-
// packages/core/src/collector.ts
|
|
2785
|
-
import { EventEmitter } from "events";
|
|
2786
|
-
|
|
2787
|
-
class Collector extends EventEmitter {
|
|
2788
|
-
collected = new Map;
|
|
2789
|
-
options;
|
|
2790
|
-
ended = false;
|
|
2791
|
-
endReason;
|
|
2792
|
-
totalProcessed = 0;
|
|
2793
|
-
#timeoutTimer;
|
|
2794
|
-
constructor(options = {}) {
|
|
2795
|
-
super();
|
|
2796
|
-
this.options = options;
|
|
2797
|
-
if (options.time && options.time > 0) {
|
|
2798
|
-
this.#timeoutTimer = setTimeout(() => {
|
|
2799
|
-
this.stop("time");
|
|
2800
|
-
}, options.time);
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
async handle(key, item) {
|
|
2804
|
-
if (this.ended)
|
|
2805
|
-
return false;
|
|
2806
|
-
this.totalProcessed++;
|
|
2807
|
-
if (this.options.filter) {
|
|
2808
|
-
const passed = await this.options.filter(item);
|
|
2809
|
-
if (!passed)
|
|
2810
|
-
return false;
|
|
2811
|
-
}
|
|
2812
|
-
this.collected.set(key, item);
|
|
2813
|
-
this.emit("collect", item);
|
|
2814
|
-
if (this.options.max && this.collected.size >= this.options.max) {
|
|
2815
|
-
this.stop("limit");
|
|
2816
|
-
return true;
|
|
3159
|
+
async#decompress(chunk) {
|
|
3160
|
+
if (!this.#decompressor)
|
|
3161
|
+
this.#initDecompressor();
|
|
3162
|
+
const { writer, reader } = this.#decompressor;
|
|
3163
|
+
await writer.write(chunk);
|
|
3164
|
+
const parts = [];
|
|
3165
|
+
while (true) {
|
|
3166
|
+
const { done, value } = await Promise.race([
|
|
3167
|
+
reader.read(),
|
|
3168
|
+
new Promise((resolve) => setTimeout(() => resolve({ done: true, value: undefined }), 50))
|
|
3169
|
+
]);
|
|
3170
|
+
if (done || !value)
|
|
3171
|
+
break;
|
|
3172
|
+
parts.push(value);
|
|
2817
3173
|
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
3174
|
+
const total = parts.reduce((n, p) => n + p.length, 0);
|
|
3175
|
+
const merged = new Uint8Array(total);
|
|
3176
|
+
let offset = 0;
|
|
3177
|
+
for (const p of parts) {
|
|
3178
|
+
merged.set(p, offset);
|
|
3179
|
+
offset += p.length;
|
|
2821
3180
|
}
|
|
2822
|
-
return
|
|
2823
|
-
}
|
|
2824
|
-
stop(reason = "user") {
|
|
2825
|
-
if (this.ended)
|
|
2826
|
-
return;
|
|
2827
|
-
this.ended = true;
|
|
2828
|
-
this.endReason = reason;
|
|
2829
|
-
if (this.#timeoutTimer)
|
|
2830
|
-
clearTimeout(this.#timeoutTimer);
|
|
2831
|
-
this.emit("end", this.collected, reason);
|
|
2832
|
-
this.removeAllListeners();
|
|
2833
|
-
}
|
|
2834
|
-
next() {
|
|
2835
|
-
return new Promise((resolve, reject) => {
|
|
2836
|
-
if (this.ended) {
|
|
2837
|
-
return reject(new Error(`Collector already ended: ${this.endReason ?? "unknown"}`));
|
|
2838
|
-
}
|
|
2839
|
-
this.once("collect", (item) => {
|
|
2840
|
-
resolve(item);
|
|
2841
|
-
});
|
|
2842
|
-
this.once("end", (_collected, reason) => {
|
|
2843
|
-
reject(new Error(`Collector ended before item was collected: ${reason}`));
|
|
2844
|
-
});
|
|
2845
|
-
});
|
|
3181
|
+
return new TextDecoder().decode(merged);
|
|
2846
3182
|
}
|
|
2847
3183
|
}
|
|
2848
3184
|
|
|
@@ -2869,6 +3205,9 @@ class EventEmitter2 {
|
|
|
2869
3205
|
this.#listeners.get(event)?.delete(listener);
|
|
2870
3206
|
return this;
|
|
2871
3207
|
}
|
|
3208
|
+
removeListener(event, listener) {
|
|
3209
|
+
return this.off(event, listener);
|
|
3210
|
+
}
|
|
2872
3211
|
removeAllListeners(event) {
|
|
2873
3212
|
if (event === undefined)
|
|
2874
3213
|
this.#listeners.clear();
|
|
@@ -2892,11 +3231,11 @@ class EventEmitter2 {
|
|
|
2892
3231
|
return true;
|
|
2893
3232
|
}
|
|
2894
3233
|
#handleError(event, error) {
|
|
2895
|
-
if (event === "error")
|
|
3234
|
+
if (event === "error" /* Error */)
|
|
2896
3235
|
return;
|
|
2897
3236
|
const normalized = error instanceof Error ? error : new Error(String(error), { cause: error });
|
|
2898
3237
|
for (const listener of [
|
|
2899
|
-
...this.#listeners.get("error") ?? []
|
|
3238
|
+
...this.#listeners.get("error" /* Error */) ?? []
|
|
2900
3239
|
]) {
|
|
2901
3240
|
try {
|
|
2902
3241
|
listener(normalized);
|
|
@@ -2921,9 +3260,27 @@ class Client extends EventEmitter2 {
|
|
|
2921
3260
|
user;
|
|
2922
3261
|
readyAt;
|
|
2923
3262
|
state = "idle";
|
|
3263
|
+
get token() {
|
|
3264
|
+
return this.state === "destroyed" ? null : this.options.token ?? null;
|
|
3265
|
+
}
|
|
2924
3266
|
get uptime() {
|
|
2925
3267
|
return this.readyAt ? Date.now() - this.readyAt.getTime() : null;
|
|
2926
3268
|
}
|
|
3269
|
+
get ping() {
|
|
3270
|
+
return this.#gateway.ping;
|
|
3271
|
+
}
|
|
3272
|
+
isReady() {
|
|
3273
|
+
return this.state === "ready";
|
|
3274
|
+
}
|
|
3275
|
+
setPresence(data) {
|
|
3276
|
+
return this.#gateway.setPresence(data);
|
|
3277
|
+
}
|
|
3278
|
+
setVoiceState(data) {
|
|
3279
|
+
return this.#gateway.setVoiceState(data);
|
|
3280
|
+
}
|
|
3281
|
+
requestGuildMembers(data) {
|
|
3282
|
+
return this.#gateway.requestGuildMembers(data);
|
|
3283
|
+
}
|
|
2927
3284
|
#gateway;
|
|
2928
3285
|
#resourceContext;
|
|
2929
3286
|
constructor(options) {
|
|
@@ -2941,7 +3298,15 @@ class Client extends EventEmitter2 {
|
|
|
2941
3298
|
sendMessage: (channelId, options2) => this.channels.send(channelId, options2),
|
|
2942
3299
|
editMessage: (channelId, messageId, options2) => this.channels.editMessage(channelId, messageId, options2),
|
|
2943
3300
|
deleteMessage: (channelId, messageId) => this.channels.deleteMessage(channelId, messageId),
|
|
2944
|
-
crosspostMessage: (channelId, messageId) => this.channels.crosspostMessage(channelId, messageId)
|
|
3301
|
+
crosspostMessage: (channelId, messageId) => this.channels.crosspostMessage(channelId, messageId),
|
|
3302
|
+
editChannel: (channelId, options2) => this.channels.edit(channelId, options2),
|
|
3303
|
+
deleteChannel: (channelId) => this.channels.deleteChannel(channelId),
|
|
3304
|
+
addReaction: (channelId, messageId, emoji) => this.channels.addReaction(channelId, messageId, emoji),
|
|
3305
|
+
removeOwnReaction: (channelId, messageId, emoji) => this.channels.removeOwnReaction(channelId, messageId, emoji),
|
|
3306
|
+
removeReaction: (channelId, messageId, emoji, userId) => this.channels.removeReaction(channelId, messageId, emoji, userId),
|
|
3307
|
+
removeAllReactions: (channelId, messageId) => this.channels.removeAllReactions(channelId, messageId),
|
|
3308
|
+
pinMessage: (channelId, messageId) => this.channels.pinMessage(channelId, messageId),
|
|
3309
|
+
unpinMessage: (channelId, messageId) => this.channels.unpinMessage(channelId, messageId)
|
|
2945
3310
|
};
|
|
2946
3311
|
this.#gateway = new Gateway({
|
|
2947
3312
|
token: options.token,
|
|
@@ -2956,233 +3321,242 @@ class Client extends EventEmitter2 {
|
|
|
2956
3321
|
this.state = "ready";
|
|
2957
3322
|
const appId = ready.application?.id ?? this.user.id;
|
|
2958
3323
|
this.application.commands = new ApplicationCommandManager(this.rest, appId);
|
|
2959
|
-
this.emit("ready"
|
|
3324
|
+
this.emit("ready" /* Ready */, this.user);
|
|
3325
|
+
});
|
|
3326
|
+
this.#gateway.on("RESUMED", () => {
|
|
3327
|
+
this.state = "ready";
|
|
3328
|
+
this.emit("resumed" /* Resumed */);
|
|
2960
3329
|
});
|
|
2961
|
-
this.#gateway.on("
|
|
3330
|
+
this.#gateway.on("invalidSession", (isRecoverable) => {
|
|
3331
|
+
this.emit("invalidSession" /* InvalidSession */, isRecoverable);
|
|
3332
|
+
});
|
|
3333
|
+
this.#gateway.on("open", () => this.emit("open" /* Open */));
|
|
2962
3334
|
this.#gateway.on("close", (data) => {
|
|
2963
3335
|
if (this.state !== "destroyed")
|
|
2964
3336
|
this.state = "idle";
|
|
2965
|
-
this.emit("close"
|
|
3337
|
+
this.emit("close" /* Close */, data);
|
|
2966
3338
|
});
|
|
2967
3339
|
this.#gateway.on("MESSAGE_CREATE", (data) => {
|
|
2968
3340
|
const message = new Message(data, this.#resourceContext);
|
|
2969
3341
|
this.channels.set(message.channelId, message.channel);
|
|
2970
3342
|
this.users.set(message.author.id, message.author);
|
|
2971
|
-
this.emit("messageCreate"
|
|
3343
|
+
this.emit("messageCreate" /* MessageCreate */, message);
|
|
2972
3344
|
});
|
|
2973
3345
|
this.#gateway.on("MESSAGE_UPDATE", (data) => {
|
|
2974
3346
|
const message = new Message(data, this.#resourceContext);
|
|
2975
3347
|
this.channels.set(message.channelId, message.channel);
|
|
2976
3348
|
this.users.set(message.author.id, message.author);
|
|
2977
|
-
this.emit("messageUpdate"
|
|
3349
|
+
this.emit("messageUpdate" /* MessageUpdate */, message);
|
|
2978
3350
|
});
|
|
2979
|
-
this.#gateway.on("MESSAGE_DELETE", (data) => this.emit("messageDelete"
|
|
2980
|
-
this.#gateway.on("MESSAGE_DELETE_BULK", (data) => this.emit("messageDeleteBulk"
|
|
3351
|
+
this.#gateway.on("MESSAGE_DELETE", (data) => this.emit("messageDelete" /* MessageDelete */, data));
|
|
3352
|
+
this.#gateway.on("MESSAGE_DELETE_BULK", (data) => this.emit("messageDeleteBulk" /* MessageDeleteBulk */, data));
|
|
3353
|
+
this.#gateway.on("MESSAGE_REACTION_ADD", (data) => this.emit("messageReactionAdd" /* MessageReactionAdd */, data));
|
|
3354
|
+
this.#gateway.on("MESSAGE_REACTION_REMOVE", (data) => this.emit("messageReactionRemove" /* MessageReactionRemove */, data));
|
|
3355
|
+
this.#gateway.on("MESSAGE_REACTION_REMOVE_ALL", (data) => this.emit("messageReactionRemoveAll" /* MessageReactionRemoveAll */, data));
|
|
3356
|
+
this.#gateway.on("MESSAGE_REACTION_REMOVE_EMOJI", (data) => this.emit("messageReactionRemoveEmoji" /* MessageReactionRemoveEmoji */, data));
|
|
3357
|
+
this.#gateway.on("MESSAGE_POLL_VOTE_ADD", (data) => this.emit("messagePollVoteAdd" /* MessagePollVoteAdd */, data));
|
|
3358
|
+
this.#gateway.on("MESSAGE_POLL_VOTE_REMOVE", (data) => this.emit("messagePollVoteRemove" /* MessagePollVoteRemove */, data));
|
|
2981
3359
|
this.#gateway.on("GUILD_CREATE", (data) => {
|
|
2982
|
-
const guild = new Guild(data);
|
|
2983
|
-
this.guilds.set(guild.id, guild);
|
|
2984
3360
|
const payload = data;
|
|
3361
|
+
if (payload.unavailable) {
|
|
3362
|
+
this.emit("guildUnavailable" /* GuildUnavailable */, payload);
|
|
3363
|
+
return;
|
|
3364
|
+
}
|
|
3365
|
+
const wasCached = this.guilds.has(payload.id);
|
|
3366
|
+
const guild = new Guild(payload);
|
|
3367
|
+
this.guilds.set(guild.id, guild);
|
|
2985
3368
|
for (const member of payload.members ?? [])
|
|
2986
3369
|
this.users.set(member.user.id, new User(member.user));
|
|
2987
3370
|
for (const channelData of [
|
|
2988
3371
|
...payload.channels ?? [],
|
|
2989
3372
|
...payload.threads ?? []
|
|
2990
|
-
])
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
}
|
|
2994
|
-
this.emit("guildCreate", data);
|
|
3373
|
+
])
|
|
3374
|
+
this.channels.set(channelData.id, new Channel(channelData, this.#resourceContext));
|
|
3375
|
+
this.emit(wasCached ? "guildAvailable" /* GuildAvailable */ : "guildCreate" /* GuildCreate */, payload);
|
|
2995
3376
|
});
|
|
2996
3377
|
this.#gateway.on("GUILD_UPDATE", (data) => {
|
|
2997
3378
|
const guild = new Guild(data);
|
|
2998
3379
|
this.guilds.update(guild);
|
|
2999
|
-
this.emit("guildUpdate"
|
|
3380
|
+
this.emit("guildUpdate" /* GuildUpdate */, data);
|
|
3000
3381
|
});
|
|
3001
3382
|
this.#gateway.on("GUILD_DELETE", (data) => {
|
|
3002
3383
|
const payload = data;
|
|
3003
|
-
if (
|
|
3004
|
-
this.
|
|
3005
|
-
|
|
3384
|
+
if (payload.unavailable) {
|
|
3385
|
+
this.emit("guildUnavailable" /* GuildUnavailable */, payload);
|
|
3386
|
+
return;
|
|
3387
|
+
}
|
|
3388
|
+
this.guilds.delete(payload.id);
|
|
3389
|
+
this.emit("guildDelete" /* GuildDelete */, payload);
|
|
3006
3390
|
});
|
|
3391
|
+
this.#gateway.on("GUILD_MEMBER_ADD", (data) => {
|
|
3392
|
+
const member = data;
|
|
3393
|
+
this.users.set(member.user.id, new User(member.user));
|
|
3394
|
+
this.emit("guildMemberAdd" /* GuildMemberAdd */, member);
|
|
3395
|
+
});
|
|
3396
|
+
this.#gateway.on("GUILD_MEMBER_UPDATE", (data) => {
|
|
3397
|
+
const member = data;
|
|
3398
|
+
this.users.set(member.user.id, new User(member.user));
|
|
3399
|
+
this.emit("guildMemberUpdate" /* GuildMemberUpdate */, member);
|
|
3400
|
+
});
|
|
3401
|
+
this.#gateway.on("GUILD_MEMBER_REMOVE", (data) => this.emit("guildMemberRemove" /* GuildMemberRemove */, data));
|
|
3402
|
+
this.#gateway.on("GUILD_MEMBERS_CHUNK", (data) => this.emit("guildMembersChunk" /* GuildMembersChunk */, data));
|
|
3403
|
+
this.#gateway.on("GUILD_BAN_ADD", (data) => this.emit("guildBanAdd" /* GuildBanAdd */, data));
|
|
3404
|
+
this.#gateway.on("GUILD_BAN_REMOVE", (data) => this.emit("guildBanRemove" /* GuildBanRemove */, data));
|
|
3405
|
+
this.#gateway.on("GUILD_ROLE_CREATE", (data) => this.emit("guildRoleCreate" /* GuildRoleCreate */, data));
|
|
3406
|
+
this.#gateway.on("GUILD_ROLE_UPDATE", (data) => this.emit("guildRoleUpdate" /* GuildRoleUpdate */, data));
|
|
3407
|
+
this.#gateway.on("GUILD_ROLE_DELETE", (data) => this.emit("guildRoleDelete" /* GuildRoleDelete */, data));
|
|
3408
|
+
this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => this.emit("guildEmojisUpdate" /* GuildEmojisUpdate */, data));
|
|
3409
|
+
this.#gateway.on("GUILD_STICKERS_UPDATE", (data) => this.emit("guildStickersUpdate" /* GuildStickersUpdate */, data));
|
|
3410
|
+
this.#gateway.on("GUILD_INTEGRATIONS_UPDATE", (data) => this.emit("guildIntegrationsUpdate" /* GuildIntegrationsUpdate */, data));
|
|
3411
|
+
this.#gateway.on("GUILD_SCHEDULED_EVENT_CREATE", (data) => this.emit("guildScheduledEventCreate" /* GuildScheduledEventCreate */, data));
|
|
3412
|
+
this.#gateway.on("GUILD_SCHEDULED_EVENT_UPDATE", (data) => this.emit("guildScheduledEventUpdate" /* GuildScheduledEventUpdate */, data));
|
|
3413
|
+
this.#gateway.on("GUILD_SCHEDULED_EVENT_DELETE", (data) => this.emit("guildScheduledEventDelete" /* GuildScheduledEventDelete */, data));
|
|
3414
|
+
this.#gateway.on("GUILD_SCHEDULED_EVENT_USER_ADD", (data) => this.emit("guildScheduledEventUserAdd" /* GuildScheduledEventUserAdd */, data));
|
|
3415
|
+
this.#gateway.on("GUILD_SCHEDULED_EVENT_USER_REMOVE", (data) => this.emit("guildScheduledEventUserRemove" /* GuildScheduledEventUserRemove */, data));
|
|
3416
|
+
this.#gateway.on("AUTO_MODERATION_RULE_CREATE", (data) => this.emit("autoModerationRuleCreate" /* AutoModerationRuleCreate */, data));
|
|
3417
|
+
this.#gateway.on("AUTO_MODERATION_RULE_UPDATE", (data) => this.emit("autoModerationRuleUpdate" /* AutoModerationRuleUpdate */, data));
|
|
3418
|
+
this.#gateway.on("AUTO_MODERATION_RULE_DELETE", (data) => this.emit("autoModerationRuleDelete" /* AutoModerationRuleDelete */, data));
|
|
3419
|
+
this.#gateway.on("AUTO_MODERATION_ACTION_EXECUTION", (data) => this.emit("autoModerationActionExecution" /* AutoModerationActionExecution */, data));
|
|
3007
3420
|
this.#gateway.on("CHANNEL_CREATE", (data) => {
|
|
3008
3421
|
const channel = new Channel(data, this.#resourceContext);
|
|
3009
3422
|
this.channels.update(channel);
|
|
3010
|
-
this.emit("channelCreate"
|
|
3423
|
+
this.emit("channelCreate" /* ChannelCreate */, channel);
|
|
3011
3424
|
});
|
|
3012
3425
|
this.#gateway.on("CHANNEL_UPDATE", (data) => {
|
|
3013
3426
|
const channel = new Channel(data, this.#resourceContext);
|
|
3014
3427
|
this.channels.update(channel);
|
|
3015
|
-
this.emit("channelUpdate"
|
|
3428
|
+
this.emit("channelUpdate" /* ChannelUpdate */, channel);
|
|
3016
3429
|
});
|
|
3017
3430
|
this.#gateway.on("CHANNEL_DELETE", (data) => {
|
|
3018
3431
|
const payload = data;
|
|
3019
3432
|
this.channels.delete(payload.id);
|
|
3020
|
-
this.emit("channelDelete"
|
|
3433
|
+
this.emit("channelDelete" /* ChannelDelete */, payload);
|
|
3021
3434
|
});
|
|
3435
|
+
this.#gateway.on("CHANNEL_PINS_UPDATE", (data) => this.emit("channelPinsUpdate" /* ChannelPinsUpdate */, data));
|
|
3022
3436
|
this.#gateway.on("THREAD_CREATE", (data) => {
|
|
3023
3437
|
const channel = new Channel(data, this.#resourceContext);
|
|
3024
3438
|
this.channels.update(channel);
|
|
3025
|
-
this.emit("threadCreate"
|
|
3439
|
+
this.emit("threadCreate" /* ThreadCreate */, channel);
|
|
3026
3440
|
});
|
|
3027
3441
|
this.#gateway.on("THREAD_UPDATE", (data) => {
|
|
3028
3442
|
const channel = new Channel(data, this.#resourceContext);
|
|
3029
3443
|
this.channels.update(channel);
|
|
3030
|
-
this.emit("threadUpdate"
|
|
3444
|
+
this.emit("threadUpdate" /* ThreadUpdate */, channel);
|
|
3031
3445
|
});
|
|
3032
3446
|
this.#gateway.on("THREAD_DELETE", (data) => {
|
|
3033
3447
|
const payload = data;
|
|
3034
3448
|
this.channels.delete(payload.id);
|
|
3035
|
-
this.emit("threadDelete"
|
|
3449
|
+
this.emit("threadDelete" /* ThreadDelete */, payload);
|
|
3036
3450
|
});
|
|
3037
|
-
this.#gateway.on("
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
this.#gateway.on("
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
this.#gateway.on("
|
|
3048
|
-
this.#gateway.on("
|
|
3049
|
-
this.#gateway.on("
|
|
3050
|
-
this.#gateway.on("
|
|
3051
|
-
this.#gateway.on("
|
|
3052
|
-
this.#gateway.on("
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
this.#gateway.on("GUILD_BAN_ADD", (data) => this.emit("guildBanAdd", data));
|
|
3056
|
-
this.#gateway.on("GUILD_BAN_REMOVE", (data) => this.emit("guildBanRemove", data));
|
|
3057
|
-
this.#gateway.on("GUILD_EMOJIS_UPDATE", (data) => this.emit("guildEmojisUpdate", data));
|
|
3058
|
-
for (const event of [
|
|
3059
|
-
"READY",
|
|
3060
|
-
"MESSAGE_CREATE",
|
|
3061
|
-
"MESSAGE_UPDATE",
|
|
3062
|
-
"MESSAGE_DELETE",
|
|
3063
|
-
"MESSAGE_DELETE_BULK",
|
|
3064
|
-
"GUILD_CREATE",
|
|
3065
|
-
"GUILD_UPDATE",
|
|
3066
|
-
"GUILD_DELETE",
|
|
3067
|
-
"CHANNEL_CREATE",
|
|
3068
|
-
"CHANNEL_UPDATE",
|
|
3069
|
-
"CHANNEL_DELETE",
|
|
3070
|
-
"THREAD_CREATE",
|
|
3071
|
-
"THREAD_UPDATE",
|
|
3072
|
-
"THREAD_DELETE",
|
|
3073
|
-
"GUILD_MEMBER_ADD",
|
|
3074
|
-
"GUILD_MEMBER_UPDATE",
|
|
3075
|
-
"GUILD_MEMBER_REMOVE",
|
|
3076
|
-
"MESSAGE_REACTION_ADD",
|
|
3077
|
-
"MESSAGE_REACTION_REMOVE",
|
|
3078
|
-
"MESSAGE_REACTION_REMOVE_ALL",
|
|
3079
|
-
"INTERACTION_CREATE",
|
|
3080
|
-
"GUILD_ROLE_CREATE",
|
|
3081
|
-
"GUILD_ROLE_UPDATE",
|
|
3082
|
-
"GUILD_ROLE_DELETE",
|
|
3083
|
-
"GUILD_BAN_ADD",
|
|
3084
|
-
"GUILD_BAN_REMOVE",
|
|
3085
|
-
"GUILD_EMOJIS_UPDATE"
|
|
3086
|
-
])
|
|
3087
|
-
this.#gateway.on(event, (data) => this.emit("raw", { event, data }));
|
|
3088
|
-
this.#gateway.on("error", (data) => this.emit("error", data));
|
|
3089
|
-
}
|
|
3090
|
-
isReady() {
|
|
3091
|
-
return this.state === "ready" && this.user !== undefined && this.readyAt !== undefined;
|
|
3092
|
-
}
|
|
3093
|
-
async login() {
|
|
3451
|
+
this.#gateway.on("THREAD_LIST_SYNC", (data) => this.emit("threadListSync" /* ThreadListSync */, data));
|
|
3452
|
+
this.#gateway.on("THREAD_MEMBERS_UPDATE", (data) => this.emit("threadMembersUpdate" /* ThreadMembersUpdate */, data));
|
|
3453
|
+
this.#gateway.on("THREAD_MEMBER_UPDATE", (data) => this.emit("threadMemberUpdate" /* ThreadMemberUpdate */, data));
|
|
3454
|
+
this.#gateway.on("STAGE_INSTANCE_CREATE", (data) => this.emit("stageInstanceCreate" /* StageInstanceCreate */, data));
|
|
3455
|
+
this.#gateway.on("STAGE_INSTANCE_UPDATE", (data) => this.emit("stageInstanceUpdate" /* StageInstanceUpdate */, data));
|
|
3456
|
+
this.#gateway.on("STAGE_INSTANCE_DELETE", (data) => this.emit("stageInstanceDelete" /* StageInstanceDelete */, data));
|
|
3457
|
+
this.#gateway.on("INVITE_CREATE", (data) => this.emit("inviteCreate" /* InviteCreate */, data));
|
|
3458
|
+
this.#gateway.on("INVITE_DELETE", (data) => this.emit("inviteDelete" /* InviteDelete */, data));
|
|
3459
|
+
this.#gateway.on("WEBHOOKS_UPDATE", (data) => this.emit("webhooksUpdate" /* WebhooksUpdate */, data));
|
|
3460
|
+
this.#gateway.on("VOICE_STATE_UPDATE", (data) => this.emit("voiceStateUpdate" /* VoiceStateUpdate */, data));
|
|
3461
|
+
this.#gateway.on("VOICE_SERVER_UPDATE", (data) => this.emit("voiceServerUpdate" /* VoiceServerUpdate */, data));
|
|
3462
|
+
this.#gateway.on("PRESENCE_UPDATE", (data) => this.emit("presenceUpdate" /* PresenceUpdate */, data));
|
|
3463
|
+
this.#gateway.on("TYPING_START", (data) => this.emit("typingStart" /* TypingStart */, data));
|
|
3464
|
+
this.#gateway.on("INTERACTION_CREATE", (data) => this.emit("interactionCreate" /* InteractionCreate */, createInteraction(this, data)));
|
|
3465
|
+
this.#gateway.on("RAW", (data) => this.emit("raw" /* Raw */, data));
|
|
3466
|
+
this.#gateway.on("error", (error) => this.emit("error" /* Error */, error));
|
|
3467
|
+
}
|
|
3468
|
+
async login(token) {
|
|
3094
3469
|
if (this.state === "destroyed")
|
|
3095
3470
|
throw new Error("Cannot login a destroyed client.");
|
|
3096
|
-
if (
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
try {
|
|
3100
|
-
this.user = await this.rest.get(Routes.user());
|
|
3101
|
-
this.users.set(this.user.id, new User(this.user));
|
|
3102
|
-
await this.#gateway.connect();
|
|
3103
|
-
} catch (error) {
|
|
3104
|
-
this.state = "idle";
|
|
3105
|
-
throw error;
|
|
3471
|
+
if (token?.trim()) {
|
|
3472
|
+
this.rest.setToken(token);
|
|
3473
|
+
this.options.token = token;
|
|
3106
3474
|
}
|
|
3475
|
+
const usedToken = this.options.token;
|
|
3476
|
+
if (!usedToken?.trim())
|
|
3477
|
+
throw new TypeError("A bot token is required to log in.");
|
|
3478
|
+
this.state = "connecting";
|
|
3479
|
+
await this.#gateway.connect();
|
|
3480
|
+
return usedToken;
|
|
3107
3481
|
}
|
|
3108
3482
|
destroy() {
|
|
3109
|
-
if (this.state === "destroyed")
|
|
3110
|
-
return;
|
|
3111
|
-
this.#gateway.close();
|
|
3112
|
-
this.users.clear();
|
|
3113
|
-
this.guilds.clear();
|
|
3114
|
-
this.channels.clear();
|
|
3115
3483
|
this.state = "destroyed";
|
|
3116
|
-
this.
|
|
3117
|
-
this.user = undefined;
|
|
3484
|
+
this.#gateway.close();
|
|
3118
3485
|
}
|
|
3119
3486
|
postInteractionResponse(id, token, response) {
|
|
3120
3487
|
return this.rest.post(Routes.interactionCallback(id, token), response.toJSON());
|
|
3121
3488
|
}
|
|
3122
3489
|
editInteractionReply(token, data) {
|
|
3123
|
-
if (!this.user
|
|
3124
|
-
|
|
3490
|
+
if (!this.user)
|
|
3491
|
+
return Promise.reject(new Error("Client is unauthenticated."));
|
|
3125
3492
|
return this.rest.patch(Routes.interactionOriginalResponse(this.user.id, token), data);
|
|
3126
3493
|
}
|
|
3127
|
-
|
|
3128
|
-
if (!this.user
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
}
|
|
3132
|
-
setPresence(presence) {
|
|
3133
|
-
return this.#gateway.setPresence(presence);
|
|
3494
|
+
deleteInteractionReply(token) {
|
|
3495
|
+
if (!this.user)
|
|
3496
|
+
return Promise.reject(new Error("Client is unauthenticated."));
|
|
3497
|
+
return this.rest.delete(Routes.interactionOriginalResponse(this.user.id, token));
|
|
3134
3498
|
}
|
|
3135
3499
|
followUpInteraction(token, data) {
|
|
3136
|
-
if (!this.user
|
|
3137
|
-
|
|
3138
|
-
return this.rest.post(
|
|
3500
|
+
if (!this.user)
|
|
3501
|
+
return Promise.reject(new Error("Client is unauthenticated."));
|
|
3502
|
+
return this.rest.post(`/webhooks/${this.user.id}/${token}`, data);
|
|
3503
|
+
}
|
|
3504
|
+
fetchWebhook(id, token) {
|
|
3505
|
+
return this.rest.get(token ? `/webhooks/${id}/${token}` : `/webhooks/${id}`);
|
|
3506
|
+
}
|
|
3507
|
+
fetchGuildPreview(guildId) {
|
|
3508
|
+
return this.rest.get(`/guilds/${guildId}/preview`);
|
|
3509
|
+
}
|
|
3510
|
+
fetchVoiceRegions() {
|
|
3511
|
+
return this.rest.get("/voice/regions");
|
|
3512
|
+
}
|
|
3513
|
+
fetchInvite(code, options) {
|
|
3514
|
+
const query = new URLSearchParams;
|
|
3515
|
+
if (options?.withCounts)
|
|
3516
|
+
query.set("with_counts", "true");
|
|
3517
|
+
if (options?.withExpiration)
|
|
3518
|
+
query.set("with_expiration", "true");
|
|
3519
|
+
if (options?.guildScheduledEventId)
|
|
3520
|
+
query.set("guild_scheduled_event_id", options.guildScheduledEventId);
|
|
3521
|
+
const qs = query.toString();
|
|
3522
|
+
return this.rest.get(`/invites/${code}${qs ? `?${qs}` : ""}`);
|
|
3523
|
+
}
|
|
3524
|
+
fetchSticker(id) {
|
|
3525
|
+
return this.rest.get(`/stickers/${id}`);
|
|
3526
|
+
}
|
|
3527
|
+
fetchPremiumStickerPacks() {
|
|
3528
|
+
return this.rest.get(`/sticker-packs`);
|
|
3529
|
+
}
|
|
3530
|
+
fetchGuildTemplate(code) {
|
|
3531
|
+
return this.rest.get(`/guilds/templates/${code}`);
|
|
3532
|
+
}
|
|
3533
|
+
generateInvite(options) {
|
|
3534
|
+
if (!this.user)
|
|
3535
|
+
throw new Error("Client must be ready to generate invite.");
|
|
3536
|
+
const params = new URLSearchParams({
|
|
3537
|
+
client_id: this.user.id,
|
|
3538
|
+
scopes: (options?.scopes ?? ["bot"]).join(" ")
|
|
3539
|
+
});
|
|
3540
|
+
if (options?.permissions) {
|
|
3541
|
+
params.set("permissions", String(options.permissions));
|
|
3542
|
+
}
|
|
3543
|
+
return `https://discord.com/api/oauth2/authorize?${params.toString()}`;
|
|
3139
3544
|
}
|
|
3140
3545
|
}
|
|
3141
3546
|
export {
|
|
3142
|
-
ActionRowBuilder,
|
|
3143
|
-
ApplicationCommandManager,
|
|
3144
|
-
ApplicationCommandOptionType,
|
|
3145
|
-
ApplicationCommandType,
|
|
3146
|
-
ButtonBuilder,
|
|
3147
|
-
Channel,
|
|
3148
|
-
ChannelManager,
|
|
3149
|
-
ChannelType,
|
|
3150
3547
|
Client,
|
|
3151
|
-
|
|
3548
|
+
ClientEvent,
|
|
3152
3549
|
Collector,
|
|
3153
|
-
EmbedBuilder,
|
|
3154
|
-
Gateway,
|
|
3155
|
-
GatewayError,
|
|
3156
3550
|
GatewayIntentBits,
|
|
3157
|
-
GatewayOpcodes,
|
|
3158
|
-
Guild,
|
|
3159
|
-
GuildManager,
|
|
3160
3551
|
IntentBits,
|
|
3161
3552
|
Intents,
|
|
3162
|
-
Manager,
|
|
3163
|
-
Message,
|
|
3164
|
-
MessageCreateOptions,
|
|
3165
|
-
MessageEditOptions,
|
|
3166
|
-
MessageFetchOptions,
|
|
3167
|
-
MessageFlags,
|
|
3168
|
-
MessageThreadOptions,
|
|
3169
3553
|
Permission,
|
|
3170
3554
|
PermissionFlagsBits,
|
|
3171
3555
|
PermissionOverwriteType,
|
|
3172
3556
|
PermissionSet,
|
|
3173
3557
|
Permissions,
|
|
3174
3558
|
PermissionsBitField,
|
|
3175
|
-
REST,
|
|
3176
|
-
RESTError,
|
|
3177
|
-
ReactionFetchOptions,
|
|
3178
|
-
ResourceManager,
|
|
3179
|
-
Routes,
|
|
3180
|
-
SlashCommandBuilder,
|
|
3181
|
-
StringOptionBuilder,
|
|
3182
|
-
StringSelectBuilder,
|
|
3183
|
-
User,
|
|
3184
|
-
UserManager,
|
|
3185
3559
|
resolveGatewayIntents
|
|
3186
3560
|
};
|
|
3187
3561
|
|
|
3188
|
-
//# debugId=
|
|
3562
|
+
//# debugId=5F8825194034E27864756E2164756E21
|