lunibee 0.1.8 → 0.2.1
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 +2 -0
- package/dist/builders/components.d.ts +30 -2
- package/dist/builders/embed.d.ts +7 -7
- package/dist/builders/index.d.ts +1 -1
- package/dist/builders/index.js +110 -18
- package/dist/builders/index.js.map +6 -6
- package/dist/collection/index.d.ts +68 -1
- package/dist/collection/index.js +334 -1
- package/dist/collection/index.js.map +3 -3
- package/dist/core/collector.d.ts +13 -0
- package/dist/core/events.d.ts +29 -3
- package/dist/core/index.d.ts +25 -9
- package/dist/core/index.js +1745 -134
- package/dist/core/index.js.map +30 -26
- package/dist/core/permissions.d.ts +48 -0
- package/dist/index.js +2102 -362
- package/dist/index.js.map +36 -34
- package/dist/managers/advanced.d.ts +116 -0
- package/dist/managers/base.d.ts +13 -2
- package/dist/managers/emoji.d.ts +1 -1
- package/dist/managers/guild-resources.d.ts +22 -2
- package/dist/managers/guild.d.ts +31 -3
- package/dist/managers/index.d.ts +38 -6
- package/dist/managers/index.js +996 -160
- package/dist/managers/index.js.map +20 -18
- package/dist/managers/member.d.ts +13 -12
- package/dist/managers/message.d.ts +21 -4
- package/dist/rest/errors.d.ts +33 -0
- package/dist/rest/index.d.ts +1 -1
- package/dist/rest/index.js +52 -6
- package/dist/rest/index.js.map +5 -5
- package/dist/rest/routes.d.ts +20 -0
- package/dist/sharding/index.d.ts +29 -0
- package/dist/sharding/index.js +99 -15
- package/dist/sharding/index.js.map +8 -8
- package/dist/structures/base.d.ts +38 -0
- package/dist/structures/index.d.ts +29 -0
- package/dist/structures/index.js +208 -46
- package/dist/structures/index.js.map +13 -12
- package/dist/structures/interactions.d.ts +51 -1
- package/dist/structures/options.d.ts +2 -0
- package/dist/structures/resources.d.ts +29 -3
- package/dist/types/gateway.d.ts +16 -0
- package/dist/types/index.d.ts +67 -1
- package/dist/types/index.js.map +3 -3
- package/dist/utils/args.d.ts +79 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +190 -2
- package/dist/utils/index.js.map +5 -4
- package/dist/voice/index.d.ts +3 -0
- package/dist/voice/index.js +15 -1
- package/dist/voice/index.js.map +3 -3
- package/dist/ws/index.js +13 -5
- package/dist/ws/index.js.map +6 -6
- package/package.json +14 -14
|
@@ -24,7 +24,32 @@ export interface ResourceContext {
|
|
|
24
24
|
removeAllReactions?(channelId: string, messageId: string): Promise<void>;
|
|
25
25
|
pinMessage?(channelId: string, messageId: string): Promise<void>;
|
|
26
26
|
unpinMessage?(channelId: string, messageId: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* A member's permissions from cached state: guild-level, or channel-level
|
|
29
|
+
* (with overwrites) when a channel ID is given. Null when the guild (or
|
|
30
|
+
* channel) is not cached.
|
|
31
|
+
*/
|
|
32
|
+
memberPermissions?(guildId: string, memberId: string, roleIds: readonly string[], channelId?: string): import("@lunibee/core").PermissionSet | null;
|
|
33
|
+
kickMember?(guildId: string, userId: string, reason?: string): Promise<void>;
|
|
34
|
+
banMember?(guildId: string, userId: string, options?: {
|
|
35
|
+
reason?: string;
|
|
36
|
+
deleteMessageSeconds?: number;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
editMember?(guildId: string, userId: string, options: Record<string, unknown>, reason?: string): Promise<import("./resources.js").GuildMember>;
|
|
39
|
+
addMemberRole?(guildId: string, userId: string, roleId: string, reason?: string): Promise<void>;
|
|
40
|
+
removeMemberRole?(guildId: string, userId: string, roleId: string, reason?: string): Promise<void>;
|
|
41
|
+
/** Collects the client's interactions (a `Collector` over `interactionCreate`). Used by message and interaction collectors. */
|
|
42
|
+
collectInteractions?(options: import("@lunibee/core").CollectorOptions<import("./interactions.js").Interaction>): import("@lunibee/core").Collector<string, import("./interactions.js").Interaction>;
|
|
43
|
+
editPermissionOverwrite?(channelId: string, targetId: string, changes: PermissionOverwriteChanges, options?: {
|
|
44
|
+
type?: 0 | 1;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}): Promise<void>;
|
|
27
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Permissions to change on one overwrite: `true` allows, `false` denies,
|
|
50
|
+
* `null` goes back to inheriting. Permissions not named keep their state.
|
|
51
|
+
*/
|
|
52
|
+
export type PermissionOverwriteChanges = Partial<Record<import("@lunibee/core").PermissionName, boolean | null>>;
|
|
28
53
|
export declare const CDN_BASE = "https://cdn.discordapp.com";
|
|
29
54
|
/** Options for CDN image URLs. */
|
|
30
55
|
export interface ImageURLOptions {
|
|
@@ -67,6 +92,8 @@ export declare class Channel extends BaseStructure {
|
|
|
67
92
|
nsfw?: boolean;
|
|
68
93
|
rateLimitPerUser?: number;
|
|
69
94
|
position?: number;
|
|
95
|
+
/** Role and member permission overwrites (empty for DMs and when not provided). */
|
|
96
|
+
permissionOverwrites: import("@lunibee/types").APIOverwrite[];
|
|
70
97
|
/** Creates a channel structure from Discord channel data. */
|
|
71
98
|
constructor(data: import("@lunibee/types").APIChannel, context?: ResourceContext);
|
|
72
99
|
/** Sends a message to this channel. @param options Message payload. @returns The created message. @throws {Error} If the channel is not attached to a client. */
|
|
@@ -84,6 +111,17 @@ export declare class Channel extends BaseStructure {
|
|
|
84
111
|
/** Changes only this channel's topic. @param topic New topic, or null to clear it. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
|
|
85
112
|
editTopic(topic: string | null): Promise<Channel>;
|
|
86
113
|
/** Moves this channel to another parent category. @param parentId Parent category ID, or null to remove the parent. @returns The updated channel. @throws {Error} If the channel is not attached to a client. */
|
|
114
|
+
/**
|
|
115
|
+
* Changes some permissions of one overwrite and keeps the rest: `true`
|
|
116
|
+
* allows, `false` denies, `null` resets to inherited.
|
|
117
|
+
* @param targetId Role or member ID. @param changes Permissions to change.
|
|
118
|
+
* @param options `type` (0 role, 1 member) when the overwrite does not exist yet; audit-log `reason`.
|
|
119
|
+
* @example channel.editPermissionOverwrite(userId, { ViewChannel: true, SendMessages: false }, { type: 1 })
|
|
120
|
+
*/
|
|
121
|
+
editPermissionOverwrite(targetId: string, changes: PermissionOverwriteChanges, options?: {
|
|
122
|
+
type?: 0 | 1;
|
|
123
|
+
reason?: string;
|
|
124
|
+
}): Promise<void>;
|
|
87
125
|
editParent(parentId: string | null): Promise<Channel>;
|
|
88
126
|
/** Deletes this channel. @returns A promise fulfilled when Discord confirms deletion. @throws {Error} If the channel is not attached to a client. */
|
|
89
127
|
delete(): Promise<void>;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** Resource structures for Discord messages and related entities. */
|
|
2
2
|
import { BaseStructure, Channel, User } from "./base.js";
|
|
3
|
+
import { GuildMember } from "./resources.js";
|
|
4
|
+
import type { ComponentInteraction } from "./interactions.js";
|
|
5
|
+
import type { Collector, CollectorOptions } from "@lunibee/core";
|
|
6
|
+
/** Options for {@link Message.createComponentCollector}. */
|
|
7
|
+
export interface ComponentCollectorOptions extends CollectorOptions<ComponentInteraction> {
|
|
8
|
+
/** Only this component type (2 button, 3 string select...). */
|
|
9
|
+
componentType?: number;
|
|
10
|
+
}
|
|
3
11
|
import type { ResourceContext } from "./base.js";
|
|
4
12
|
export { BaseStructure, Channel, Guild, User } from "./base.js";
|
|
5
13
|
export type { ResourceContext } from "./base.js";
|
|
@@ -23,6 +31,12 @@ export declare class Message extends BaseStructure {
|
|
|
23
31
|
readonly reference?: import("@lunibee/types").APIMessageReference;
|
|
24
32
|
readonly components: import("@lunibee/types").APIMessageComponent[];
|
|
25
33
|
readonly referencedMessage?: Message | null;
|
|
34
|
+
/**
|
|
35
|
+
* The author as a guild member, on guild messages from the Gateway. Its
|
|
36
|
+
* `permissions` are computed from the cached roles; `member.kick()` and the
|
|
37
|
+
* other member actions work when the message came from a client.
|
|
38
|
+
*/
|
|
39
|
+
member: GuildMember | null;
|
|
26
40
|
/** Creates a message structure from Discord message data. */
|
|
27
41
|
constructor(data: import("@lunibee/types").APIMessage, context?: ResourceContext);
|
|
28
42
|
/** Whether embeds are suppressed on this message. */
|
|
@@ -49,6 +63,21 @@ export declare class Message extends BaseStructure {
|
|
|
49
63
|
})): Promise<Message>;
|
|
50
64
|
/** Crossposts this message. @returns The resulting message. @throws {Error} If the message is not attached to a client. */
|
|
51
65
|
crosspost(): Promise<Message>;
|
|
66
|
+
/**
|
|
67
|
+
* Collects clicks and picks on this message's components. It always ends:
|
|
68
|
+
* after `time`, or 15 minutes (an interaction token's life) when neither
|
|
69
|
+
* `time` nor `idle` is set.
|
|
70
|
+
* @example
|
|
71
|
+
* const collector = message.createComponentCollector({ filter: (i) => i.user?.id === authorId, time: 60_000 });
|
|
72
|
+
* collector.on("collect", (i) => i.update({ content: `Picked ${i.customId}` }));
|
|
73
|
+
*/
|
|
74
|
+
createComponentCollector(options?: ComponentCollectorOptions): Collector<string, ComponentInteraction>;
|
|
75
|
+
/**
|
|
76
|
+
* Waits for the next click or pick on this message's components.
|
|
77
|
+
* @param options `time` (default 15 minutes), `filter`, `componentType`.
|
|
78
|
+
* @returns The interaction. @throws {Error} When time runs out first.
|
|
79
|
+
*/
|
|
80
|
+
awaitComponent(options?: Omit<ComponentCollectorOptions, "max">): Promise<ComponentInteraction>;
|
|
52
81
|
/** Adds a reaction to this message. @param emoji Emoji identifier. @returns A promise fulfilled when the reaction is added. @throws {Error} If reactions are unavailable. */
|
|
53
82
|
react(emoji: string): Promise<void>;
|
|
54
83
|
/** Removes a reaction from this message. @param emoji Emoji identifier. @param userId User whose reaction should be removed; omit to remove the current user's reaction. @returns A promise fulfilled when the reaction is removed. @throws {Error} If reaction operations are unavailable. */
|
package/dist/structures/index.js
CHANGED
|
@@ -71,6 +71,7 @@ class Channel extends BaseStructure {
|
|
|
71
71
|
nsfw;
|
|
72
72
|
rateLimitPerUser;
|
|
73
73
|
position;
|
|
74
|
+
permissionOverwrites;
|
|
74
75
|
#context;
|
|
75
76
|
constructor(data, context) {
|
|
76
77
|
super(data.id);
|
|
@@ -84,6 +85,7 @@ class Channel extends BaseStructure {
|
|
|
84
85
|
this.nsfw = data.nsfw;
|
|
85
86
|
this.rateLimitPerUser = data.rate_limit_per_user;
|
|
86
87
|
this.position = data.position;
|
|
88
|
+
this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
|
|
87
89
|
this.#context = context;
|
|
88
90
|
}
|
|
89
91
|
sendMessage(options) {
|
|
@@ -107,6 +109,11 @@ class Channel extends BaseStructure {
|
|
|
107
109
|
editTopic(topic) {
|
|
108
110
|
return this.edit({ topic });
|
|
109
111
|
}
|
|
112
|
+
editPermissionOverwrite(targetId, changes, options) {
|
|
113
|
+
if (!this.#context?.editPermissionOverwrite)
|
|
114
|
+
throw new Error("This channel is not attached to a client.");
|
|
115
|
+
return this.#context.editPermissionOverwrite(this.id, targetId, changes, options);
|
|
116
|
+
}
|
|
110
117
|
editParent(parentId) {
|
|
111
118
|
return this.edit({ parent_id: parentId });
|
|
112
119
|
}
|
|
@@ -241,6 +248,7 @@ class Guild extends BaseStructure {
|
|
|
241
248
|
return this.name;
|
|
242
249
|
}
|
|
243
250
|
}
|
|
251
|
+
|
|
244
252
|
// packages/core/src/permissions.ts
|
|
245
253
|
var Permission = {
|
|
246
254
|
createInstantInvite: 1n << 0n,
|
|
@@ -290,8 +298,11 @@ var Permission = {
|
|
|
290
298
|
createEvents: 1n << 44n,
|
|
291
299
|
useExternalSounds: 1n << 45n,
|
|
292
300
|
sendVoiceMessages: 1n << 46n,
|
|
301
|
+
setVoiceChannelStatus: 1n << 48n,
|
|
293
302
|
sendPolls: 1n << 49n,
|
|
294
|
-
useExternalApps: 1n << 50n
|
|
303
|
+
useExternalApps: 1n << 50n,
|
|
304
|
+
pinMessages: 1n << 51n,
|
|
305
|
+
bypassSlowmode: 1n << 52n
|
|
295
306
|
};
|
|
296
307
|
var Permissions = {
|
|
297
308
|
CreateInstantInvite: 1n << 0n,
|
|
@@ -341,8 +352,11 @@ var Permissions = {
|
|
|
341
352
|
CreateEvents: 1n << 44n,
|
|
342
353
|
UseExternalSounds: 1n << 45n,
|
|
343
354
|
SendVoiceMessages: 1n << 46n,
|
|
355
|
+
SetVoiceChannelStatus: 1n << 48n,
|
|
344
356
|
SendPolls: 1n << 49n,
|
|
345
|
-
UseExternalApps: 1n << 50n
|
|
357
|
+
UseExternalApps: 1n << 50n,
|
|
358
|
+
PinMessages: 1n << 51n,
|
|
359
|
+
BypassSlowmode: 1n << 52n
|
|
346
360
|
};
|
|
347
361
|
var PermissionFlagsBits = {
|
|
348
362
|
CreateInstantInvite: 1n << 0n,
|
|
@@ -392,8 +406,11 @@ var PermissionFlagsBits = {
|
|
|
392
406
|
CreateEvents: 1n << 44n,
|
|
393
407
|
UseExternalSounds: 1n << 45n,
|
|
394
408
|
SendVoiceMessages: 1n << 46n,
|
|
409
|
+
SetVoiceChannelStatus: 1n << 48n,
|
|
395
410
|
SendPolls: 1n << 49n,
|
|
396
|
-
UseExternalApps: 1n << 50n
|
|
411
|
+
UseExternalApps: 1n << 50n,
|
|
412
|
+
PinMessages: 1n << 51n,
|
|
413
|
+
BypassSlowmode: 1n << 52n
|
|
397
414
|
};
|
|
398
415
|
|
|
399
416
|
class PermissionSet {
|
|
@@ -595,6 +612,10 @@ class PermissionSet {
|
|
|
595
612
|
}
|
|
596
613
|
return false;
|
|
597
614
|
}
|
|
615
|
+
missing(...permissions) {
|
|
616
|
+
const wanted = new PermissionSet(permissions);
|
|
617
|
+
return wanted.toArray().filter((name) => !this.has(name));
|
|
618
|
+
}
|
|
598
619
|
add(...permissions) {
|
|
599
620
|
let bitfield = this.bitfield;
|
|
600
621
|
for (let i = 0;i < permissions.length; i++) {
|
|
@@ -620,6 +641,11 @@ class PermissionSet {
|
|
|
620
641
|
toArray() {
|
|
621
642
|
return Object.keys(Permission).filter((permission) => this.has(permission));
|
|
622
643
|
}
|
|
644
|
+
static #renamed = {
|
|
645
|
+
ManageEmojisAndStickers: "ManageGuildExpressions",
|
|
646
|
+
ManageEmojis: "ManageGuildExpressions",
|
|
647
|
+
UseSlashCommands: "UseApplicationCommands"
|
|
648
|
+
};
|
|
623
649
|
#resolve(permission) {
|
|
624
650
|
if (typeof permission === "bigint")
|
|
625
651
|
return permission;
|
|
@@ -634,6 +660,9 @@ class PermissionSet {
|
|
|
634
660
|
return bit;
|
|
635
661
|
}
|
|
636
662
|
if (typeof permission === "string") {
|
|
663
|
+
const renamed = PermissionSet.#renamed[permission];
|
|
664
|
+
if (renamed)
|
|
665
|
+
return this.#resolve(renamed);
|
|
637
666
|
if (permission in Permission)
|
|
638
667
|
return Permission[permission];
|
|
639
668
|
if (permission in Permissions)
|
|
@@ -656,6 +685,7 @@ class PermissionsBitField extends PermissionSet {
|
|
|
656
685
|
super(value);
|
|
657
686
|
}
|
|
658
687
|
}
|
|
688
|
+
var ALL_PERMISSIONS = Object.values(Permission).reduce((bits, bit) => bits | bit, 0n);
|
|
659
689
|
// packages/types/src/gateway.ts
|
|
660
690
|
var GatewayIntentBits = {
|
|
661
691
|
Guilds: 1 << 0,
|
|
@@ -721,7 +751,7 @@ var InteractionResponseType = {
|
|
|
721
751
|
// packages/rest/package.json
|
|
722
752
|
var package_default = {
|
|
723
753
|
name: "@lunibee/rest",
|
|
724
|
-
version: "0.1
|
|
754
|
+
version: "0.2.1",
|
|
725
755
|
type: "module",
|
|
726
756
|
module: "./src/index.ts",
|
|
727
757
|
types: "./src/index.ts",
|
|
@@ -743,6 +773,9 @@ var REQUEST_DATA_KEYS = new Set([
|
|
|
743
773
|
"auth",
|
|
744
774
|
"signal"
|
|
745
775
|
]);
|
|
776
|
+
// packages/managers/src/index.ts
|
|
777
|
+
var BULK_DELETE_MAX_AGE_MS = 14 * 24 * 60 * 60000;
|
|
778
|
+
|
|
746
779
|
// packages/ws/src/close-codes.ts
|
|
747
780
|
var GatewayCloseCodes = {
|
|
748
781
|
UnknownError: 4000,
|
|
@@ -789,13 +822,15 @@ class GuildMember {
|
|
|
789
822
|
roleIds;
|
|
790
823
|
pending;
|
|
791
824
|
joinedAt;
|
|
792
|
-
permissions;
|
|
793
825
|
avatarHash;
|
|
794
826
|
premiumSince;
|
|
795
827
|
timedOutUntil;
|
|
796
828
|
flags;
|
|
797
|
-
|
|
829
|
+
#suppliedPermissions;
|
|
830
|
+
#context;
|
|
831
|
+
constructor(data, context) {
|
|
798
832
|
this.user = new User(data.user);
|
|
833
|
+
this.#context = context;
|
|
799
834
|
if (!/^\d{1,20}$/.test(data.guild_id))
|
|
800
835
|
throw new TypeError("Member guild_id must be a valid snowflake.");
|
|
801
836
|
this.guildId = data.guild_id;
|
|
@@ -805,12 +840,53 @@ class GuildMember {
|
|
|
805
840
|
this.joinedAt = data.joined_at ? new Date(data.joined_at) : undefined;
|
|
806
841
|
if (this.joinedAt?.toString() === "Invalid Date")
|
|
807
842
|
throw new RangeError("Member joined_at must be a valid date.");
|
|
808
|
-
|
|
843
|
+
if (data.permissions !== undefined)
|
|
844
|
+
this.#suppliedPermissions = new PermissionsBitField(data.permissions);
|
|
809
845
|
this.avatarHash = data.avatar ?? null;
|
|
810
846
|
this.premiumSince = toDateOrNull(data.premium_since);
|
|
811
847
|
this.timedOutUntil = toDateOrNull(data.communication_disabled_until);
|
|
812
848
|
this.flags = data.flags ?? 0;
|
|
813
849
|
}
|
|
850
|
+
get permissions() {
|
|
851
|
+
if (this.#suppliedPermissions)
|
|
852
|
+
return this.#suppliedPermissions;
|
|
853
|
+
return new PermissionsBitField(this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds) ?? 0n);
|
|
854
|
+
}
|
|
855
|
+
permissionsIn(channelId) {
|
|
856
|
+
const computed = this.#context?.memberPermissions?.(this.guildId, this.user.id, this.roleIds, channelId);
|
|
857
|
+
return computed ? new PermissionsBitField(computed) : null;
|
|
858
|
+
}
|
|
859
|
+
#action(name) {
|
|
860
|
+
const action = this.#context?.[name];
|
|
861
|
+
if (!action)
|
|
862
|
+
throw new Error("This member is not attached to a client.");
|
|
863
|
+
return action;
|
|
864
|
+
}
|
|
865
|
+
kick(reason) {
|
|
866
|
+
return this.#action("kickMember")(this.guildId, this.user.id, reason);
|
|
867
|
+
}
|
|
868
|
+
ban(options = {}) {
|
|
869
|
+
return this.#action("banMember")(this.guildId, this.user.id, options);
|
|
870
|
+
}
|
|
871
|
+
edit(options, reason) {
|
|
872
|
+
return this.#action("editMember")(this.guildId, this.user.id, options, reason);
|
|
873
|
+
}
|
|
874
|
+
timeout(milliseconds, reason) {
|
|
875
|
+
if (milliseconds !== null && !(milliseconds > 0))
|
|
876
|
+
throw new RangeError("Timeout length must be a positive number of milliseconds.");
|
|
877
|
+
return this.edit({
|
|
878
|
+
communication_disabled_until: milliseconds === null ? null : new Date(Date.now() + milliseconds).toISOString()
|
|
879
|
+
}, reason);
|
|
880
|
+
}
|
|
881
|
+
setNickname(nickname, reason) {
|
|
882
|
+
return this.edit({ nick: nickname }, reason);
|
|
883
|
+
}
|
|
884
|
+
addRole(roleId, reason) {
|
|
885
|
+
return this.#action("addMemberRole")(this.guildId, this.user.id, roleId, reason);
|
|
886
|
+
}
|
|
887
|
+
removeRole(roleId, reason) {
|
|
888
|
+
return this.#action("removeMemberRole")(this.guildId, this.user.id, roleId, reason);
|
|
889
|
+
}
|
|
814
890
|
get displayName() {
|
|
815
891
|
return this.nickname ?? this.user.displayName;
|
|
816
892
|
}
|
|
@@ -1344,6 +1420,17 @@ class CommandOptions {
|
|
|
1344
1420
|
throw new TypeError(`Resolved mentionable for option "${name}" is missing.`);
|
|
1345
1421
|
return resolved;
|
|
1346
1422
|
}
|
|
1423
|
+
getMentionableType(name) {
|
|
1424
|
+
const opt = this.#get(name);
|
|
1425
|
+
if (!opt || opt.type !== OptionType.Mentionable)
|
|
1426
|
+
return null;
|
|
1427
|
+
const id = String(opt.value);
|
|
1428
|
+
if (this.#resolved?.users?.[id])
|
|
1429
|
+
return "user";
|
|
1430
|
+
if (this.#resolved?.roles?.[id])
|
|
1431
|
+
return "role";
|
|
1432
|
+
return null;
|
|
1433
|
+
}
|
|
1347
1434
|
getAttachment(name, required = false) {
|
|
1348
1435
|
const opt = this.#get(name);
|
|
1349
1436
|
if (!opt || opt.type !== OptionType.Attachment) {
|
|
@@ -1369,6 +1456,17 @@ var InteractionType = {
|
|
|
1369
1456
|
ApplicationCommandAutocomplete: 4,
|
|
1370
1457
|
ModalSubmit: 5
|
|
1371
1458
|
};
|
|
1459
|
+
var EPHEMERAL = 64;
|
|
1460
|
+
var TOKEN_LIFETIME_MS = 15 * 60000;
|
|
1461
|
+
var DISCORD_EPOCH = 1420070400000n;
|
|
1462
|
+
function toMessageData(options) {
|
|
1463
|
+
if (typeof options === "string")
|
|
1464
|
+
return { content: options };
|
|
1465
|
+
const { ephemeral, ...data } = options;
|
|
1466
|
+
if (ephemeral)
|
|
1467
|
+
data.flags = (typeof data.flags === "number" ? data.flags : 0) | EPHEMERAL;
|
|
1468
|
+
return data;
|
|
1469
|
+
}
|
|
1372
1470
|
|
|
1373
1471
|
class InteractionResponse {
|
|
1374
1472
|
type;
|
|
@@ -1383,14 +1481,10 @@ class InteractionResponse {
|
|
|
1383
1481
|
return this.data === undefined ? { type: this.type } : { type: this.type, data: this.data };
|
|
1384
1482
|
}
|
|
1385
1483
|
static message(options) {
|
|
1386
|
-
|
|
1387
|
-
if (options.ephemeral) {
|
|
1388
|
-
data.flags = (typeof options.flags === "number" ? options.flags : 0) | 64;
|
|
1389
|
-
}
|
|
1390
|
-
return new InteractionResponse(InteractionResponseType.ChannelMessage, data);
|
|
1484
|
+
return new InteractionResponse(InteractionResponseType.ChannelMessage, toMessageData(options));
|
|
1391
1485
|
}
|
|
1392
1486
|
static defer(ephemeral = false) {
|
|
1393
|
-
return new InteractionResponse(InteractionResponseType.DeferredChannelMessage, ephemeral ? { flags:
|
|
1487
|
+
return new InteractionResponse(InteractionResponseType.DeferredChannelMessage, ephemeral ? { flags: EPHEMERAL } : undefined);
|
|
1394
1488
|
}
|
|
1395
1489
|
static pong() {
|
|
1396
1490
|
return new InteractionResponse(InteractionResponseType.Pong);
|
|
@@ -1408,6 +1502,7 @@ class Interaction {
|
|
|
1408
1502
|
replied = false;
|
|
1409
1503
|
deferred = false;
|
|
1410
1504
|
#client;
|
|
1505
|
+
#acknowledging = false;
|
|
1411
1506
|
constructor(client, data) {
|
|
1412
1507
|
if (!data.id || !data.token)
|
|
1413
1508
|
throw new TypeError("Interaction ID and token are required.");
|
|
@@ -1423,6 +1518,20 @@ class Interaction {
|
|
|
1423
1518
|
isChatInputCommand() {
|
|
1424
1519
|
return this.type === InteractionType.ApplicationCommand;
|
|
1425
1520
|
}
|
|
1521
|
+
awaitModalSubmit(options) {
|
|
1522
|
+
const collect = this.#client.resourceContext?.collectInteractions;
|
|
1523
|
+
if (!collect)
|
|
1524
|
+
return Promise.reject(new Error("This interaction is not attached to a client."));
|
|
1525
|
+
if (!(options.time > 0))
|
|
1526
|
+
return Promise.reject(new RangeError("awaitModalSubmit needs a positive time."));
|
|
1527
|
+
const userId = this.user?.id;
|
|
1528
|
+
const collector = collect({
|
|
1529
|
+
time: options.time,
|
|
1530
|
+
max: 1,
|
|
1531
|
+
filter: async (interaction) => interaction.isModalSubmit() && interaction.user?.id === userId && (options.customId === undefined || interaction.customId === options.customId) && (options.filter ? await options.filter(interaction) : true)
|
|
1532
|
+
});
|
|
1533
|
+
return collector.next();
|
|
1534
|
+
}
|
|
1426
1535
|
isMessageComponent() {
|
|
1427
1536
|
return this.type === InteractionType.MessageComponent;
|
|
1428
1537
|
}
|
|
@@ -1457,9 +1566,57 @@ class Interaction {
|
|
|
1457
1566
|
return [3, 5, 6, 7, 8].includes(this.#componentType());
|
|
1458
1567
|
}
|
|
1459
1568
|
assertUnacknowledged() {
|
|
1460
|
-
if (this.replied || this.deferred)
|
|
1569
|
+
if (this.replied || this.deferred || this.#acknowledging)
|
|
1461
1570
|
throw new Error("Interaction has already been acknowledged.");
|
|
1462
1571
|
}
|
|
1572
|
+
async acknowledge(response, state) {
|
|
1573
|
+
this.assertUnacknowledged();
|
|
1574
|
+
this.#acknowledging = true;
|
|
1575
|
+
try {
|
|
1576
|
+
const result = await this.postResponse(response);
|
|
1577
|
+
this[state] = true;
|
|
1578
|
+
return result;
|
|
1579
|
+
} finally {
|
|
1580
|
+
this.#acknowledging = false;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
get user() {
|
|
1584
|
+
const raw = this.data.member?.user ?? this.data.user;
|
|
1585
|
+
return raw ? new User(raw) : null;
|
|
1586
|
+
}
|
|
1587
|
+
get member() {
|
|
1588
|
+
const raw = this.data.member;
|
|
1589
|
+
if (!raw || !this.guildId)
|
|
1590
|
+
return null;
|
|
1591
|
+
return new GuildMember({
|
|
1592
|
+
...raw,
|
|
1593
|
+
guild_id: this.guildId
|
|
1594
|
+
}, this.#client.resourceContext);
|
|
1595
|
+
}
|
|
1596
|
+
get createdTimestamp() {
|
|
1597
|
+
return Number((BigInt(this.id) >> 22n) + DISCORD_EPOCH);
|
|
1598
|
+
}
|
|
1599
|
+
get expiresAt() {
|
|
1600
|
+
return new Date(this.createdTimestamp + TOKEN_LIFETIME_MS);
|
|
1601
|
+
}
|
|
1602
|
+
get isExpired() {
|
|
1603
|
+
return Date.now() >= this.createdTimestamp + TOKEN_LIFETIME_MS;
|
|
1604
|
+
}
|
|
1605
|
+
#webhookMessage(method, messageId, data) {
|
|
1606
|
+
if (!this.#client.interactionWebhookMessage)
|
|
1607
|
+
return Promise.reject(new Error("This interaction client does not support webhook message access."));
|
|
1608
|
+
return this.#client.interactionWebhookMessage(method, this.applicationId, this.token, messageId, data);
|
|
1609
|
+
}
|
|
1610
|
+
fetchReply() {
|
|
1611
|
+
this.assertAcknowledged();
|
|
1612
|
+
return this.#webhookMessage("GET", "@original");
|
|
1613
|
+
}
|
|
1614
|
+
editFollowUp(messageId, options) {
|
|
1615
|
+
return this.#webhookMessage("PATCH", messageId, toMessageData(options));
|
|
1616
|
+
}
|
|
1617
|
+
async deleteFollowUp(messageId) {
|
|
1618
|
+
await this.#webhookMessage("DELETE", messageId);
|
|
1619
|
+
}
|
|
1463
1620
|
assertAcknowledged() {
|
|
1464
1621
|
if (!this.replied && !this.deferred)
|
|
1465
1622
|
throw new Error("Interaction has not been acknowledged.");
|
|
@@ -1468,41 +1625,29 @@ class Interaction {
|
|
|
1468
1625
|
return this.#client.postInteractionResponse(this.id, this.token, response);
|
|
1469
1626
|
}
|
|
1470
1627
|
async reply(options) {
|
|
1471
|
-
this.
|
|
1472
|
-
const payload = typeof options === "string" ? { content: options } : options;
|
|
1473
|
-
const result = await this.#client.postInteractionResponse(this.id, this.token, InteractionResponse.message(payload));
|
|
1474
|
-
this.replied = true;
|
|
1475
|
-
return result;
|
|
1628
|
+
return this.acknowledge(InteractionResponse.message(toMessageData(options)), "replied");
|
|
1476
1629
|
}
|
|
1477
|
-
async deferReply(
|
|
1478
|
-
|
|
1479
|
-
await this
|
|
1480
|
-
this.deferred = true;
|
|
1630
|
+
async deferReply(options = false) {
|
|
1631
|
+
const ephemeral = typeof options === "boolean" ? options : options.ephemeral === true;
|
|
1632
|
+
await this.acknowledge(InteractionResponse.defer(ephemeral), "deferred");
|
|
1481
1633
|
}
|
|
1482
1634
|
editReply(options) {
|
|
1483
1635
|
this.assertAcknowledged();
|
|
1484
|
-
return this.#client.editInteractionReply(this.token, options);
|
|
1636
|
+
return this.#client.editInteractionReply(this.token, toMessageData(options));
|
|
1485
1637
|
}
|
|
1486
1638
|
deleteReply() {
|
|
1487
1639
|
this.assertAcknowledged();
|
|
1488
1640
|
return this.#client.deleteInteractionReply(this.token);
|
|
1489
1641
|
}
|
|
1490
1642
|
followUp(options) {
|
|
1491
|
-
|
|
1492
|
-
return this.#client.followUpInteraction(this.token, payload);
|
|
1643
|
+
return this.#client.followUpInteraction(this.token, toMessageData(options));
|
|
1493
1644
|
}
|
|
1494
1645
|
async update(options) {
|
|
1495
|
-
this.
|
|
1496
|
-
const payload = typeof options === "string" ? { content: options } : options;
|
|
1497
|
-
const result = await this.#client.postInteractionResponse(this.id, this.token, new InteractionResponse(InteractionResponseType.MessageUpdate, payload));
|
|
1498
|
-
this.replied = true;
|
|
1499
|
-
return result;
|
|
1646
|
+
return this.acknowledge(new InteractionResponse(InteractionResponseType.MessageUpdate, toMessageData(options)), "replied");
|
|
1500
1647
|
}
|
|
1501
1648
|
async showModal(modal) {
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
this.replied = true;
|
|
1505
|
-
return result;
|
|
1649
|
+
const data = "toJSON" in modal && typeof modal.toJSON === "function" ? modal.toJSON() : modal;
|
|
1650
|
+
return this.acknowledge(new InteractionResponse(InteractionResponseType.Modal, data), "replied");
|
|
1506
1651
|
}
|
|
1507
1652
|
}
|
|
1508
1653
|
|
|
@@ -1523,6 +1668,9 @@ class ComponentInteraction extends Interaction {
|
|
|
1523
1668
|
get customId() {
|
|
1524
1669
|
return this.data?.data?.custom_id ?? "";
|
|
1525
1670
|
}
|
|
1671
|
+
get messageId() {
|
|
1672
|
+
return this.data?.message?.id;
|
|
1673
|
+
}
|
|
1526
1674
|
get componentType() {
|
|
1527
1675
|
return this.data?.data?.component_type ?? 0;
|
|
1528
1676
|
}
|
|
@@ -1530,16 +1678,10 @@ class ComponentInteraction extends Interaction {
|
|
|
1530
1678
|
return this.data?.data?.values ?? [];
|
|
1531
1679
|
}
|
|
1532
1680
|
async deferUpdate() {
|
|
1533
|
-
this.
|
|
1534
|
-
await this.postResponse(new InteractionResponse(InteractionResponseType.DeferredMessageUpdate));
|
|
1535
|
-
this.deferred = true;
|
|
1681
|
+
await this.acknowledge(new InteractionResponse(InteractionResponseType.DeferredMessageUpdate), "deferred");
|
|
1536
1682
|
}
|
|
1537
1683
|
async update(options) {
|
|
1538
|
-
this.
|
|
1539
|
-
const payload = typeof options === "string" ? { content: options } : options;
|
|
1540
|
-
const result = await this.postResponse(new InteractionResponse(InteractionResponseType.MessageUpdate, payload));
|
|
1541
|
-
this.replied = true;
|
|
1542
|
-
return result;
|
|
1684
|
+
return this.acknowledge(new InteractionResponse(InteractionResponseType.MessageUpdate, toMessageData(options)), "replied");
|
|
1543
1685
|
}
|
|
1544
1686
|
}
|
|
1545
1687
|
|
|
@@ -1582,8 +1724,7 @@ class AutocompleteInteraction extends Interaction {
|
|
|
1582
1724
|
if (!Array.isArray(choices))
|
|
1583
1725
|
throw new TypeError("Autocomplete choices must be an array.");
|
|
1584
1726
|
const response = new InteractionResponse(InteractionResponseType.Autocomplete, { choices });
|
|
1585
|
-
await this.
|
|
1586
|
-
this.replied = true;
|
|
1727
|
+
await this.acknowledge(response, "replied");
|
|
1587
1728
|
}
|
|
1588
1729
|
}
|
|
1589
1730
|
function findFocused(options) {
|
|
@@ -1780,6 +1921,7 @@ class AuditLog {
|
|
|
1780
1921
|
}
|
|
1781
1922
|
|
|
1782
1923
|
// packages/structures/src/index.ts
|
|
1924
|
+
var COMPONENT_COLLECTOR_DEFAULT_TIME = 15 * 60000;
|
|
1783
1925
|
var NON_SYSTEM_MESSAGE_TYPES = new Set([0, 19, 20, 23]);
|
|
1784
1926
|
|
|
1785
1927
|
class Message extends BaseStructure {
|
|
@@ -1800,6 +1942,7 @@ class Message extends BaseStructure {
|
|
|
1800
1942
|
reference;
|
|
1801
1943
|
components;
|
|
1802
1944
|
referencedMessage;
|
|
1945
|
+
member;
|
|
1803
1946
|
#context;
|
|
1804
1947
|
constructor(data, context) {
|
|
1805
1948
|
super(data.id);
|
|
@@ -1822,6 +1965,11 @@ class Message extends BaseStructure {
|
|
|
1822
1965
|
this.reference = data.message_reference;
|
|
1823
1966
|
this.referencedMessage = data.referenced_message ? new Message(data.referenced_message, context) : data.referenced_message === null ? null : undefined;
|
|
1824
1967
|
this.#context = context;
|
|
1968
|
+
this.member = data.member && data.guild_id ? new GuildMember({
|
|
1969
|
+
...data.member,
|
|
1970
|
+
user: data.member.user ?? data.author,
|
|
1971
|
+
guild_id: data.guild_id
|
|
1972
|
+
}, context) : null;
|
|
1825
1973
|
this.channel = new Channel({ id: data.channel_id, type: 0, guild_id: data.guild_id }, context);
|
|
1826
1974
|
}
|
|
1827
1975
|
get embedsSuppressed() {
|
|
@@ -1862,6 +2010,20 @@ class Message extends BaseStructure {
|
|
|
1862
2010
|
throw new Error("This message is not attached to a client.");
|
|
1863
2011
|
return this.#context.crosspostMessage(this.channelId, this.id);
|
|
1864
2012
|
}
|
|
2013
|
+
createComponentCollector(options = {}) {
|
|
2014
|
+
const collect = this.#context?.collectInteractions;
|
|
2015
|
+
if (!collect)
|
|
2016
|
+
throw new Error("This message is not attached to a client.");
|
|
2017
|
+
const { componentType, filter, ...rest } = options;
|
|
2018
|
+
return collect({
|
|
2019
|
+
...rest,
|
|
2020
|
+
time: rest.time ?? (rest.idle ? undefined : COMPONENT_COLLECTOR_DEFAULT_TIME),
|
|
2021
|
+
filter: async (interaction) => interaction.isMessageComponent() && interaction.messageId === this.id && (componentType === undefined || interaction.componentType === componentType) && (filter ? await filter(interaction) : true)
|
|
2022
|
+
});
|
|
2023
|
+
}
|
|
2024
|
+
awaitComponent(options = {}) {
|
|
2025
|
+
return this.createComponentCollector({ ...options, max: 1 }).next();
|
|
2026
|
+
}
|
|
1865
2027
|
react(emoji) {
|
|
1866
2028
|
if (!this.#context?.addReaction)
|
|
1867
2029
|
throw new Error("This message is not attached to a client.");
|
|
@@ -1977,4 +2139,4 @@ export {
|
|
|
1977
2139
|
createInteraction
|
|
1978
2140
|
};
|
|
1979
2141
|
|
|
1980
|
-
//# debugId=
|
|
2142
|
+
//# debugId=56391DD25556C30C64756E2164756E21
|