@minesa-org/mini-interaction 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders/AutomodRuleBuilder.d.ts +45 -0
- package/dist/builders/AutomodRuleBuilder.js +151 -0
- package/dist/builders/EmbedBuilder.d.ts +33 -0
- package/dist/builders/EmbedBuilder.js +94 -0
- package/dist/builders/MiniContainerBuilder.d.ts +131 -0
- package/dist/builders/MiniContainerBuilder.js +347 -0
- package/dist/builders/TextInputBuilder.d.ts +57 -0
- package/dist/builders/TextInputBuilder.js +98 -0
- package/dist/builders/index.d.ts +8 -0
- package/dist/builders/index.js +4 -0
- package/dist/clients/MiniInteraction.d.ts +25 -0
- package/dist/clients/MiniInteraction.js +114 -4
- package/dist/index.d.ts +6 -1
- package/dist/index.js +3 -0
- package/dist/types/Commands.d.ts +11 -0
- package/dist/types/PermissionFlags.d.ts +55 -0
- package/dist/types/PermissionFlags.js +5 -0
- package/dist/types/SeparatorSpacingSize.d.ts +2 -0
- package/dist/types/SeparatorSpacingSize.js +2 -0
- package/dist/utils/CommandInteractionOptions.d.ts +3 -1
- package/dist/utils/CommandInteractionOptions.js +6 -1
- package/dist/utils/MessageComponentInteraction.d.ts +13 -1
- package/dist/utils/MessageComponentInteraction.js +15 -0
- package/dist/utils/ModalSubmitInteraction.d.ts +28 -0
- package/dist/utils/ModalSubmitInteraction.js +74 -0
- package/dist/utils/interactionMessageHelpers.d.ts +5 -5
- package/dist/utils/interactionMessageHelpers.js +79 -9
- package/package.json +2 -1
|
@@ -7,6 +7,7 @@ import { verifyKey } from "discord-interactions";
|
|
|
7
7
|
import { DISCORD_BASE_URL } from "../utils/constants.js";
|
|
8
8
|
import { createCommandInteraction } from "../utils/CommandInteractionOptions.js";
|
|
9
9
|
import { createMessageComponentInteraction, } from "../utils/MessageComponentInteraction.js";
|
|
10
|
+
import { createModalSubmitInteraction, } from "../utils/ModalSubmitInteraction.js";
|
|
10
11
|
/** File extensions that are treated as loadable modules when auto-loading. */
|
|
11
12
|
const SUPPORTED_MODULE_EXTENSIONS = new Set([
|
|
12
13
|
".js",
|
|
@@ -29,6 +30,7 @@ export class MiniInteraction {
|
|
|
29
30
|
componentsDirectory;
|
|
30
31
|
commands = new Map();
|
|
31
32
|
componentHandlers = new Map();
|
|
33
|
+
modalHandlers = new Map();
|
|
32
34
|
commandsLoaded = false;
|
|
33
35
|
loadCommandsPromise = null;
|
|
34
36
|
componentsLoaded = false;
|
|
@@ -75,6 +77,18 @@ export class MiniInteraction {
|
|
|
75
77
|
console.warn(`[MiniInteraction] Command "${commandName}" already exists and will be overwritten.`);
|
|
76
78
|
}
|
|
77
79
|
this.commands.set(commandName, command);
|
|
80
|
+
// Register components exported with the command
|
|
81
|
+
if (command.components && Array.isArray(command.components)) {
|
|
82
|
+
for (const component of command.components) {
|
|
83
|
+
this.useComponent(component);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Register modals exported with the command
|
|
87
|
+
if (command.modals && Array.isArray(command.modals)) {
|
|
88
|
+
for (const modal of command.modals) {
|
|
89
|
+
this.useModal(modal);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
78
92
|
return this;
|
|
79
93
|
}
|
|
80
94
|
/**
|
|
@@ -118,6 +132,36 @@ export class MiniInteraction {
|
|
|
118
132
|
}
|
|
119
133
|
return this;
|
|
120
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Registers a single modal handler mapped to a custom identifier.
|
|
137
|
+
*
|
|
138
|
+
* @param modal - The modal definition to register.
|
|
139
|
+
*/
|
|
140
|
+
useModal(modal) {
|
|
141
|
+
const customId = modal?.customId;
|
|
142
|
+
if (!customId) {
|
|
143
|
+
throw new Error("[MiniInteraction] modal.customId is required");
|
|
144
|
+
}
|
|
145
|
+
if (typeof modal.handler !== "function") {
|
|
146
|
+
throw new Error("[MiniInteraction] modal.handler must be a function");
|
|
147
|
+
}
|
|
148
|
+
if (this.modalHandlers.has(customId)) {
|
|
149
|
+
console.warn(`[MiniInteraction] Modal "${customId}" already exists and will be overwritten.`);
|
|
150
|
+
}
|
|
151
|
+
this.modalHandlers.set(customId, modal.handler);
|
|
152
|
+
return this;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Registers multiple modal handlers in a single call.
|
|
156
|
+
*
|
|
157
|
+
* @param modals - The modal definitions to register.
|
|
158
|
+
*/
|
|
159
|
+
useModals(modals) {
|
|
160
|
+
for (const modal of modals) {
|
|
161
|
+
this.useModal(modal);
|
|
162
|
+
}
|
|
163
|
+
return this;
|
|
164
|
+
}
|
|
121
165
|
/**
|
|
122
166
|
* Recursively loads components from the configured components directory.
|
|
123
167
|
*
|
|
@@ -184,6 +228,18 @@ export class MiniInteraction {
|
|
|
184
228
|
continue;
|
|
185
229
|
}
|
|
186
230
|
this.commands.set(command.data.name, command);
|
|
231
|
+
// Register components exported from the command file
|
|
232
|
+
if (command.components && Array.isArray(command.components)) {
|
|
233
|
+
for (const component of command.components) {
|
|
234
|
+
this.useComponent(component);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Register modals exported from the command file
|
|
238
|
+
if (command.modals && Array.isArray(command.modals)) {
|
|
239
|
+
for (const modal of command.modals) {
|
|
240
|
+
this.useModal(modal);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
187
243
|
}
|
|
188
244
|
this.commandsLoaded = true;
|
|
189
245
|
return this;
|
|
@@ -302,6 +358,9 @@ export class MiniInteraction {
|
|
|
302
358
|
if (interaction.type === InteractionType.MessageComponent) {
|
|
303
359
|
return this.handleMessageComponent(interaction);
|
|
304
360
|
}
|
|
361
|
+
if (interaction.type === InteractionType.ModalSubmit) {
|
|
362
|
+
return this.handleModalSubmit(interaction);
|
|
363
|
+
}
|
|
305
364
|
return {
|
|
306
365
|
status: 400,
|
|
307
366
|
body: {
|
|
@@ -542,9 +601,10 @@ export class MiniInteraction {
|
|
|
542
601
|
return;
|
|
543
602
|
}
|
|
544
603
|
if (!this.loadComponentsPromise) {
|
|
545
|
-
this.loadComponentsPromise =
|
|
546
|
-
this.
|
|
547
|
-
|
|
604
|
+
this.loadComponentsPromise =
|
|
605
|
+
this.loadComponentsFromDirectory().then(() => {
|
|
606
|
+
this.loadComponentsPromise = null;
|
|
607
|
+
});
|
|
548
608
|
}
|
|
549
609
|
await this.loadComponentsPromise;
|
|
550
610
|
}
|
|
@@ -583,7 +643,8 @@ export class MiniInteraction {
|
|
|
583
643
|
const candidates = [];
|
|
584
644
|
const isWithin = (parent, child) => {
|
|
585
645
|
const relative = path.relative(parent, child);
|
|
586
|
-
return relative === "" ||
|
|
646
|
+
return (relative === "" ||
|
|
647
|
+
(!relative.startsWith("..") && !path.isAbsolute(relative)));
|
|
587
648
|
};
|
|
588
649
|
const pushCandidate = (candidate) => {
|
|
589
650
|
if (!candidates.includes(candidate)) {
|
|
@@ -681,6 +742,55 @@ export class MiniInteraction {
|
|
|
681
742
|
};
|
|
682
743
|
}
|
|
683
744
|
}
|
|
745
|
+
/**
|
|
746
|
+
* Handles execution of a modal submit interaction.
|
|
747
|
+
*/
|
|
748
|
+
async handleModalSubmit(interaction) {
|
|
749
|
+
const customId = interaction?.data?.custom_id;
|
|
750
|
+
if (!customId) {
|
|
751
|
+
return {
|
|
752
|
+
status: 400,
|
|
753
|
+
body: {
|
|
754
|
+
error: "[MiniInteraction] Modal submit interaction is missing a custom_id",
|
|
755
|
+
},
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
const handler = this.modalHandlers.get(customId);
|
|
759
|
+
if (!handler) {
|
|
760
|
+
return {
|
|
761
|
+
status: 404,
|
|
762
|
+
body: {
|
|
763
|
+
error: `[MiniInteraction] No handler registered for modal "${customId}"`,
|
|
764
|
+
},
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
try {
|
|
768
|
+
const interactionWithHelpers = createModalSubmitInteraction(interaction);
|
|
769
|
+
const response = await handler(interactionWithHelpers);
|
|
770
|
+
const resolvedResponse = response ?? interactionWithHelpers.getResponse();
|
|
771
|
+
if (!resolvedResponse) {
|
|
772
|
+
return {
|
|
773
|
+
status: 500,
|
|
774
|
+
body: {
|
|
775
|
+
error: `[MiniInteraction] Modal "${customId}" did not return a response. ` +
|
|
776
|
+
"Return an APIInteractionResponse to acknowledge the interaction.",
|
|
777
|
+
},
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
return {
|
|
781
|
+
status: 200,
|
|
782
|
+
body: resolvedResponse,
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
catch (error) {
|
|
786
|
+
return {
|
|
787
|
+
status: 500,
|
|
788
|
+
body: {
|
|
789
|
+
error: `[MiniInteraction] Modal "${customId}" failed: ${String(error)}`,
|
|
790
|
+
},
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
}
|
|
684
794
|
/**
|
|
685
795
|
* Handles execution of an application command interaction.
|
|
686
796
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -7,10 +7,15 @@ export { CommandInteractionOptionResolver, createCommandInteraction, } from "./u
|
|
|
7
7
|
export type { CommandInteraction, MentionableOption, ResolvedUserOption, } from "./utils/CommandInteractionOptions.js";
|
|
8
8
|
export type { MiniInteractionFetchHandler, MiniInteractionNodeHandler, MiniInteractionHandlerResult, MiniInteractionRequest, MiniInteractionOptions, } from "./clients/MiniInteraction.js";
|
|
9
9
|
export type { MiniInteractionCommand, SlashCommandHandler, } from "./types/Commands.js";
|
|
10
|
-
export type { MiniInteractionComponent, MiniInteractionComponentHandler, } from "./clients/MiniInteraction.js";
|
|
10
|
+
export type { MiniInteractionComponent, MiniInteractionComponentHandler, MiniInteractionModal, MiniInteractionModalHandler, } from "./clients/MiniInteraction.js";
|
|
11
|
+
export type { MessageComponentInteraction } from "./utils/MessageComponentInteraction.js";
|
|
12
|
+
export type { ModalSubmitInteraction } from "./utils/ModalSubmitInteraction.js";
|
|
11
13
|
export { RoleConnectionMetadataTypes } from "./types/RoleConnectionMetadataTypes.js";
|
|
12
14
|
export { ChannelType } from "./types/ChannelType.js";
|
|
13
15
|
export { InteractionFollowUpFlags, InteractionReplyFlags, } from "./types/InteractionFlags.js";
|
|
14
16
|
export { ButtonStyle } from "./types/ButtonStyle.js";
|
|
17
|
+
export { SeparatorSpacingSize } from "./types/SeparatorSpacingSize.js";
|
|
18
|
+
export { TextInputStyle } from "discord-api-types/v10";
|
|
19
|
+
export { MiniPermFlags } from "./types/PermissionFlags.js";
|
|
15
20
|
export type { MiniComponentActionRow, MiniComponentMessageActionRow, } from "./types/ComponentTypes.js";
|
|
16
21
|
export * from "./builders/index.js";
|
package/dist/index.js
CHANGED
|
@@ -6,4 +6,7 @@ export { RoleConnectionMetadataTypes } from "./types/RoleConnectionMetadataTypes
|
|
|
6
6
|
export { ChannelType } from "./types/ChannelType.js";
|
|
7
7
|
export { InteractionFollowUpFlags, InteractionReplyFlags, } from "./types/InteractionFlags.js";
|
|
8
8
|
export { ButtonStyle } from "./types/ButtonStyle.js";
|
|
9
|
+
export { SeparatorSpacingSize } from "./types/SeparatorSpacingSize.js";
|
|
10
|
+
export { TextInputStyle } from "discord-api-types/v10";
|
|
11
|
+
export { MiniPermFlags } from "./types/PermissionFlags.js";
|
|
9
12
|
export * from "./builders/index.js";
|
package/dist/types/Commands.d.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import type { APIInteractionResponse, RESTPostAPIChatInputApplicationCommandsJSONBody } from "discord-api-types/v10";
|
|
2
2
|
import type { CommandInteraction } from "../utils/CommandInteractionOptions.js";
|
|
3
|
+
import type { MiniInteractionComponent, MiniInteractionModal } from "../clients/MiniInteraction.js";
|
|
3
4
|
/** Handler signature for slash command executions within MiniInteraction. */
|
|
4
5
|
export type SlashCommandHandler = (interaction: CommandInteraction) => Promise<APIInteractionResponse | void> | APIInteractionResponse | void;
|
|
5
6
|
/** Structure representing a slash command definition and its runtime handler. */
|
|
6
7
|
export type MiniInteractionCommand = {
|
|
7
8
|
data: RESTPostAPIChatInputApplicationCommandsJSONBody;
|
|
8
9
|
handler: SlashCommandHandler;
|
|
10
|
+
/**
|
|
11
|
+
* Optional array of component handlers related to this command.
|
|
12
|
+
* These will be automatically registered when the command is loaded.
|
|
13
|
+
*/
|
|
14
|
+
components?: MiniInteractionComponent[];
|
|
15
|
+
/**
|
|
16
|
+
* Optional array of modal handlers related to this command.
|
|
17
|
+
* These will be automatically registered when the command is loaded.
|
|
18
|
+
*/
|
|
19
|
+
modals?: MiniInteractionModal[];
|
|
9
20
|
};
|
|
10
21
|
/** Map of command names to their registered MiniInteraction command definitions. */
|
|
11
22
|
export type MiniInteractionCommandsMap = Map<string, MiniInteractionCommand>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Convenience mapping of Discord permission bit flags for MiniInteraction usage. */
|
|
2
|
+
export declare const MiniPermFlags: {
|
|
3
|
+
readonly CreateInstantInvite: bigint;
|
|
4
|
+
readonly KickMembers: bigint;
|
|
5
|
+
readonly BanMembers: bigint;
|
|
6
|
+
readonly Administrator: bigint;
|
|
7
|
+
readonly ManageChannels: bigint;
|
|
8
|
+
readonly ManageGuild: bigint;
|
|
9
|
+
readonly AddReactions: bigint;
|
|
10
|
+
readonly ViewAuditLog: bigint;
|
|
11
|
+
readonly PrioritySpeaker: bigint;
|
|
12
|
+
readonly Stream: bigint;
|
|
13
|
+
readonly ViewChannel: bigint;
|
|
14
|
+
readonly SendMessages: bigint;
|
|
15
|
+
readonly SendTTSMessages: bigint;
|
|
16
|
+
readonly ManageMessages: bigint;
|
|
17
|
+
readonly EmbedLinks: bigint;
|
|
18
|
+
readonly AttachFiles: bigint;
|
|
19
|
+
readonly ReadMessageHistory: bigint;
|
|
20
|
+
readonly MentionEveryone: bigint;
|
|
21
|
+
readonly UseExternalEmojis: bigint;
|
|
22
|
+
readonly ViewGuildInsights: bigint;
|
|
23
|
+
readonly Connect: bigint;
|
|
24
|
+
readonly Speak: bigint;
|
|
25
|
+
readonly MuteMembers: bigint;
|
|
26
|
+
readonly DeafenMembers: bigint;
|
|
27
|
+
readonly MoveMembers: bigint;
|
|
28
|
+
readonly UseVAD: bigint;
|
|
29
|
+
readonly ChangeNickname: bigint;
|
|
30
|
+
readonly ManageNicknames: bigint;
|
|
31
|
+
readonly ManageRoles: bigint;
|
|
32
|
+
readonly ManageWebhooks: bigint;
|
|
33
|
+
readonly ManageEmojisAndStickers: bigint;
|
|
34
|
+
readonly ManageGuildExpressions: bigint;
|
|
35
|
+
readonly UseApplicationCommands: bigint;
|
|
36
|
+
readonly RequestToSpeak: bigint;
|
|
37
|
+
readonly ManageEvents: bigint;
|
|
38
|
+
readonly ManageThreads: bigint;
|
|
39
|
+
readonly CreatePublicThreads: bigint;
|
|
40
|
+
readonly CreatePrivateThreads: bigint;
|
|
41
|
+
readonly UseExternalStickers: bigint;
|
|
42
|
+
readonly SendMessagesInThreads: bigint;
|
|
43
|
+
readonly UseEmbeddedActivities: bigint;
|
|
44
|
+
readonly ModerateMembers: bigint;
|
|
45
|
+
readonly ViewCreatorMonetizationAnalytics: bigint;
|
|
46
|
+
readonly UseSoundboard: bigint;
|
|
47
|
+
readonly CreateGuildExpressions: bigint;
|
|
48
|
+
readonly CreateEvents: bigint;
|
|
49
|
+
readonly UseExternalSounds: bigint;
|
|
50
|
+
readonly SendVoiceMessages: bigint;
|
|
51
|
+
readonly SendPolls: bigint;
|
|
52
|
+
readonly UseExternalApps: bigint;
|
|
53
|
+
readonly PinMessages: bigint;
|
|
54
|
+
};
|
|
55
|
+
export type MiniPermFlag = (typeof MiniPermFlags)[keyof typeof MiniPermFlags];
|
|
@@ -132,7 +132,9 @@ export interface CommandInteraction extends Omit<APIChatInputApplicationCommandI
|
|
|
132
132
|
followUp(data: InteractionMessageData): APIInteractionResponseChannelMessageWithSource;
|
|
133
133
|
edit(data?: InteractionMessageData): APIInteractionResponseUpdateMessage;
|
|
134
134
|
deferReply(options?: DeferReplyOptions): APIInteractionResponseDeferredChannelMessageWithSource;
|
|
135
|
-
showModal(data: APIModalInteractionResponseCallbackData
|
|
135
|
+
showModal(data: APIModalInteractionResponseCallbackData | {
|
|
136
|
+
toJSON(): APIModalInteractionResponseCallbackData;
|
|
137
|
+
}): APIModalInteractionResponse;
|
|
136
138
|
}
|
|
137
139
|
/**
|
|
138
140
|
* Wraps a raw application command interaction with helper methods and option resolvers.
|
|
@@ -366,9 +366,14 @@ export function createCommandInteraction(interaction) {
|
|
|
366
366
|
: undefined);
|
|
367
367
|
},
|
|
368
368
|
showModal(data) {
|
|
369
|
+
const resolvedData = typeof data === "object" &&
|
|
370
|
+
"toJSON" in data &&
|
|
371
|
+
typeof data.toJSON === "function"
|
|
372
|
+
? data.toJSON()
|
|
373
|
+
: data;
|
|
369
374
|
return captureResponse({
|
|
370
375
|
type: InteractionResponseType.Modal,
|
|
371
|
-
data,
|
|
376
|
+
data: resolvedData,
|
|
372
377
|
});
|
|
373
378
|
},
|
|
374
379
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { type APIInteractionResponse, type APIInteractionResponseChannelMessageWithSource, type APIInteractionResponseDeferredChannelMessageWithSource, type APIInteractionResponseDeferredMessageUpdate, type APIInteractionResponseUpdateMessage, type APIMessageComponentInteraction } from "discord-api-types/v10";
|
|
1
|
+
import { type APIInteractionResponse, type APIInteractionResponseChannelMessageWithSource, type APIInteractionResponseDeferredChannelMessageWithSource, type APIInteractionResponseDeferredMessageUpdate, type APIInteractionResponseUpdateMessage, type APIMessageComponentInteraction, type APIModalInteractionResponse, type APIModalInteractionResponseCallbackData } from "discord-api-types/v10";
|
|
2
2
|
import { DeferReplyOptions, InteractionMessageData } from "./interactionMessageHelpers.js";
|
|
3
3
|
/**
|
|
4
4
|
* Represents a component interaction augmented with helper response methods.
|
|
5
|
+
*
|
|
6
|
+
* Note: The `values` property is available on select menu interactions (data.values).
|
|
7
|
+
* For button interactions, this property will be undefined.
|
|
5
8
|
*/
|
|
6
9
|
export type MessageComponentInteraction = APIMessageComponentInteraction & {
|
|
7
10
|
getResponse: () => APIInteractionResponse | null;
|
|
@@ -9,6 +12,15 @@ export type MessageComponentInteraction = APIMessageComponentInteraction & {
|
|
|
9
12
|
deferReply: (options?: DeferReplyOptions) => APIInteractionResponseDeferredChannelMessageWithSource;
|
|
10
13
|
update: (data?: InteractionMessageData) => APIInteractionResponseUpdateMessage;
|
|
11
14
|
deferUpdate: () => APIInteractionResponseDeferredMessageUpdate;
|
|
15
|
+
showModal: (data: APIModalInteractionResponseCallbackData | {
|
|
16
|
+
toJSON(): APIModalInteractionResponseCallbackData;
|
|
17
|
+
}) => APIModalInteractionResponse;
|
|
18
|
+
/**
|
|
19
|
+
* The selected values from a select menu interaction.
|
|
20
|
+
* This property is only present for select menu interactions.
|
|
21
|
+
* For button interactions, this will be undefined.
|
|
22
|
+
*/
|
|
23
|
+
values?: string[];
|
|
12
24
|
};
|
|
13
25
|
/**
|
|
14
26
|
* Wraps a raw component interaction with helper methods mirroring Discord's expected responses.
|
|
@@ -49,12 +49,27 @@ export function createMessageComponentInteraction(interaction) {
|
|
|
49
49
|
const deferUpdate = () => captureResponse({
|
|
50
50
|
type: InteractionResponseType.DeferredMessageUpdate,
|
|
51
51
|
});
|
|
52
|
+
const showModal = (data) => {
|
|
53
|
+
const resolvedData = typeof data === "object" &&
|
|
54
|
+
"toJSON" in data &&
|
|
55
|
+
typeof data.toJSON === "function"
|
|
56
|
+
? data.toJSON()
|
|
57
|
+
: data;
|
|
58
|
+
return captureResponse({
|
|
59
|
+
type: InteractionResponseType.Modal,
|
|
60
|
+
data: resolvedData,
|
|
61
|
+
});
|
|
62
|
+
};
|
|
52
63
|
const getResponse = () => capturedResponse;
|
|
64
|
+
// Extract values from select menu interactions
|
|
65
|
+
const values = "values" in interaction.data ? interaction.data.values : undefined;
|
|
53
66
|
return Object.assign(interaction, {
|
|
54
67
|
reply,
|
|
55
68
|
deferReply,
|
|
56
69
|
update,
|
|
57
70
|
deferUpdate,
|
|
71
|
+
showModal,
|
|
58
72
|
getResponse,
|
|
73
|
+
values,
|
|
59
74
|
});
|
|
60
75
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type APIInteractionResponse, type APIInteractionResponseChannelMessageWithSource, type APIInteractionResponseDeferredChannelMessageWithSource, type APIModalSubmitInteraction } from "discord-api-types/v10";
|
|
2
|
+
import { DeferReplyOptions, InteractionMessageData } from "./interactionMessageHelpers.js";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a modal submit interaction augmented with helper response methods.
|
|
5
|
+
*/
|
|
6
|
+
export type ModalSubmitInteraction = APIModalSubmitInteraction & {
|
|
7
|
+
getResponse: () => APIInteractionResponse | null;
|
|
8
|
+
reply: (data: InteractionMessageData) => APIInteractionResponseChannelMessageWithSource;
|
|
9
|
+
deferReply: (options?: DeferReplyOptions) => APIInteractionResponseDeferredChannelMessageWithSource;
|
|
10
|
+
/**
|
|
11
|
+
* Helper method to get the value of a text input component by custom_id.
|
|
12
|
+
* @param customId - The custom_id of the text input component
|
|
13
|
+
* @returns The value of the text input, or undefined if not found
|
|
14
|
+
*/
|
|
15
|
+
getTextInputValue: (customId: string) => string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Helper method to get all text input values as a map.
|
|
18
|
+
* @returns A map of custom_id to value for all text inputs
|
|
19
|
+
*/
|
|
20
|
+
getTextInputValues: () => Map<string, string>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Wraps a raw modal submit interaction with helper methods.
|
|
24
|
+
*
|
|
25
|
+
* @param interaction - The raw interaction payload from Discord.
|
|
26
|
+
* @returns A helper-augmented interaction object.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createModalSubmitInteraction(interaction: APIModalSubmitInteraction): ModalSubmitInteraction;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { InteractionResponseType, } from "discord-api-types/v10";
|
|
2
|
+
import { normaliseInteractionMessageData, normaliseMessageFlags, } from "./interactionMessageHelpers.js";
|
|
3
|
+
/**
|
|
4
|
+
* Wraps a raw modal submit interaction with helper methods.
|
|
5
|
+
*
|
|
6
|
+
* @param interaction - The raw interaction payload from Discord.
|
|
7
|
+
* @returns A helper-augmented interaction object.
|
|
8
|
+
*/
|
|
9
|
+
export function createModalSubmitInteraction(interaction) {
|
|
10
|
+
let capturedResponse = null;
|
|
11
|
+
const captureResponse = (response) => {
|
|
12
|
+
capturedResponse = response;
|
|
13
|
+
return response;
|
|
14
|
+
};
|
|
15
|
+
const reply = (data) => {
|
|
16
|
+
const normalisedData = normaliseInteractionMessageData(data);
|
|
17
|
+
if (!normalisedData) {
|
|
18
|
+
throw new Error("[MiniInteraction] Modal submit replies require response data to be provided.");
|
|
19
|
+
}
|
|
20
|
+
return captureResponse({
|
|
21
|
+
type: InteractionResponseType.ChannelMessageWithSource,
|
|
22
|
+
data: normalisedData,
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
const deferReply = (options) => {
|
|
26
|
+
const flags = normaliseMessageFlags(options?.flags);
|
|
27
|
+
const response = flags !== undefined
|
|
28
|
+
? {
|
|
29
|
+
type: InteractionResponseType.DeferredChannelMessageWithSource,
|
|
30
|
+
data: { flags },
|
|
31
|
+
}
|
|
32
|
+
: {
|
|
33
|
+
type: InteractionResponseType.DeferredChannelMessageWithSource,
|
|
34
|
+
};
|
|
35
|
+
return captureResponse(response);
|
|
36
|
+
};
|
|
37
|
+
const getResponse = () => capturedResponse;
|
|
38
|
+
// Helper to extract text input values from modal components
|
|
39
|
+
const extractTextInputs = () => {
|
|
40
|
+
const textInputs = new Map();
|
|
41
|
+
for (const component of interaction.data.components) {
|
|
42
|
+
// Handle action rows
|
|
43
|
+
if ("components" in component && Array.isArray(component.components)) {
|
|
44
|
+
for (const child of component.components) {
|
|
45
|
+
if ("value" in child && "custom_id" in child) {
|
|
46
|
+
textInputs.set(child.custom_id, child.value);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Handle labeled components
|
|
51
|
+
else if ("component" in component) {
|
|
52
|
+
const labeledComponent = component.component;
|
|
53
|
+
if ("value" in labeledComponent && "custom_id" in labeledComponent) {
|
|
54
|
+
textInputs.set(labeledComponent.custom_id, labeledComponent.value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return textInputs;
|
|
59
|
+
};
|
|
60
|
+
const textInputValues = extractTextInputs();
|
|
61
|
+
const getTextInputValue = (customId) => {
|
|
62
|
+
return textInputValues.get(customId);
|
|
63
|
+
};
|
|
64
|
+
const getTextInputValues = () => {
|
|
65
|
+
return new Map(textInputValues);
|
|
66
|
+
};
|
|
67
|
+
return Object.assign(interaction, {
|
|
68
|
+
reply,
|
|
69
|
+
deferReply,
|
|
70
|
+
getResponse,
|
|
71
|
+
getTextInputValue,
|
|
72
|
+
getTextInputValues,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -4,23 +4,23 @@ import type { InteractionFollowUpFlags, InteractionReplyFlags } from "../types/I
|
|
|
4
4
|
export type MessageFlagLike = MessageFlags | InteractionReplyFlags | InteractionFollowUpFlags;
|
|
5
5
|
/** Message payload accepted by helper reply/edit functions. */
|
|
6
6
|
export type InteractionMessageData = Omit<APIInteractionResponseCallbackData, "flags"> & {
|
|
7
|
-
flags?: MessageFlagLike;
|
|
7
|
+
flags?: MessageFlagLike | MessageFlagLike[];
|
|
8
8
|
};
|
|
9
9
|
/** Deferred response payload recognised by helper methods. */
|
|
10
10
|
export type DeferredResponseData = {
|
|
11
|
-
flags: MessageFlagLike;
|
|
11
|
+
flags: MessageFlagLike | MessageFlagLike[];
|
|
12
12
|
};
|
|
13
13
|
/** Options accepted when deferring a reply. */
|
|
14
14
|
export type DeferReplyOptions = {
|
|
15
|
-
flags?: MessageFlagLike;
|
|
15
|
+
flags?: MessageFlagLike | MessageFlagLike[];
|
|
16
16
|
};
|
|
17
17
|
/**
|
|
18
18
|
* Normalises helper flag enums into the raw Discord `MessageFlags` bitfield.
|
|
19
19
|
*
|
|
20
|
-
* @param flags - A flag from helper enums or raw Discord flags.
|
|
20
|
+
* @param flags - A flag or array of flags from helper enums or raw Discord flags.
|
|
21
21
|
* @returns The value coerced to a `MessageFlags` compatible bitfield.
|
|
22
22
|
*/
|
|
23
|
-
export declare function normaliseMessageFlags(flags: MessageFlagLike | undefined): MessageFlags | undefined;
|
|
23
|
+
export declare function normaliseMessageFlags(flags: MessageFlagLike | MessageFlagLike[] | undefined): MessageFlags | undefined;
|
|
24
24
|
/**
|
|
25
25
|
* Ensures helper message payloads include correctly normalised message flags.
|
|
26
26
|
*
|
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
import { ComponentType, MessageFlags as RawMessageFlags, } from "discord-api-types/v10";
|
|
2
|
+
const COMPONENTS_V2_TYPES = new Set([
|
|
3
|
+
ComponentType.Container,
|
|
4
|
+
ComponentType.Section,
|
|
5
|
+
ComponentType.TextDisplay,
|
|
6
|
+
ComponentType.MediaGallery,
|
|
7
|
+
ComponentType.File,
|
|
8
|
+
ComponentType.Separator,
|
|
9
|
+
ComponentType.Thumbnail,
|
|
10
|
+
]);
|
|
1
11
|
/**
|
|
2
12
|
* Normalises helper flag enums into the raw Discord `MessageFlags` bitfield.
|
|
3
13
|
*
|
|
4
|
-
* @param flags - A flag from helper enums or raw Discord flags.
|
|
14
|
+
* @param flags - A flag or array of flags from helper enums or raw Discord flags.
|
|
5
15
|
* @returns The value coerced to a `MessageFlags` compatible bitfield.
|
|
6
16
|
*/
|
|
7
17
|
export function normaliseMessageFlags(flags) {
|
|
8
|
-
|
|
18
|
+
if (flags === undefined) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(flags)) {
|
|
22
|
+
if (flags.length === 0) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
// Combine multiple flags using bitwise OR
|
|
26
|
+
return flags.reduce((acc, flag) => (acc | flag), 0);
|
|
27
|
+
}
|
|
28
|
+
return flags;
|
|
9
29
|
}
|
|
10
30
|
/**
|
|
11
31
|
* Ensures helper message payloads include correctly normalised message flags.
|
|
@@ -17,16 +37,66 @@ export function normaliseInteractionMessageData(data) {
|
|
|
17
37
|
if (!data) {
|
|
18
38
|
return undefined;
|
|
19
39
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
40
|
+
// Auto-convert builders to JSON
|
|
41
|
+
const normalisedComponents = data.components
|
|
42
|
+
? data.components.map((component) => resolveComponentLike(component))
|
|
43
|
+
: undefined;
|
|
44
|
+
const normalisedEmbeds = data.embeds
|
|
45
|
+
? data.embeds.map((embed) => resolveComponentLike(embed))
|
|
46
|
+
: undefined;
|
|
47
|
+
const usesComponentsV2 = Array.isArray(normalisedComponents)
|
|
48
|
+
? containsComponentsV2(normalisedComponents)
|
|
49
|
+
: false;
|
|
50
|
+
const normalisedFlags = normaliseMessageFlags(data.flags);
|
|
51
|
+
const finalFlags = usesComponentsV2
|
|
52
|
+
? ((normalisedFlags ?? 0) |
|
|
53
|
+
RawMessageFlags.IsComponentsV2)
|
|
54
|
+
: normalisedFlags;
|
|
55
|
+
const needsNormalisation = finalFlags !== data.flags ||
|
|
56
|
+
normalisedComponents !== data.components ||
|
|
57
|
+
normalisedEmbeds !== data.embeds;
|
|
58
|
+
if (!needsNormalisation) {
|
|
26
59
|
return data;
|
|
27
60
|
}
|
|
61
|
+
const { flags: _flags, components: _components, embeds: _embeds, ...rest } = data;
|
|
28
62
|
return {
|
|
29
63
|
...rest,
|
|
30
|
-
|
|
64
|
+
...(normalisedComponents !== undefined
|
|
65
|
+
? { components: normalisedComponents }
|
|
66
|
+
: {}),
|
|
67
|
+
...(normalisedEmbeds !== undefined ? { embeds: normalisedEmbeds } : {}),
|
|
68
|
+
...(finalFlags !== undefined ? { flags: finalFlags } : {}),
|
|
31
69
|
};
|
|
32
70
|
}
|
|
71
|
+
function containsComponentsV2(components) {
|
|
72
|
+
return components.some((component) => componentUsesComponentsV2(component));
|
|
73
|
+
}
|
|
74
|
+
function componentUsesComponentsV2(component) {
|
|
75
|
+
const resolved = resolveComponentLike(component);
|
|
76
|
+
if (!resolved || typeof resolved !== "object") {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const type = resolved.type;
|
|
80
|
+
if (typeof type !== "number") {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
if (COMPONENTS_V2_TYPES.has(type)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
if (type === ComponentType.ActionRow) {
|
|
87
|
+
const rowComponents = resolved.components;
|
|
88
|
+
if (Array.isArray(rowComponents)) {
|
|
89
|
+
return containsComponentsV2(rowComponents);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
function resolveComponentLike(component) {
|
|
95
|
+
if (component && typeof component === "object" && "toJSON" in component) {
|
|
96
|
+
const encoder = component;
|
|
97
|
+
if (typeof encoder.toJSON === "function") {
|
|
98
|
+
return encoder.toJSON();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return component;
|
|
102
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@minesa-org/mini-interaction",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Mini interaction, connecting your app with Discord via HTTP-interaction (Vercel support).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"build": "tsc --project tsconfig.json",
|
|
15
15
|
"typecheck": "tsc --noEmit",
|
|
16
16
|
"prepare": "npm run build",
|
|
17
|
+
"patch": "npm version patch",
|
|
17
18
|
"publish:npm": "npm publish",
|
|
18
19
|
"publish:gh": "npm publish --registry=https://npm.pkg.github.com"
|
|
19
20
|
},
|