@minesa-org/mini-interaction 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,45 @@
1
+ import { type APIAutoModerationAction, type APIAutoModerationRuleTriggerMetadata, AutoModerationRuleEventType, AutoModerationRuleTriggerType } from "discord-api-types/v10";
2
+ import type { RESTPostAPIAutoModerationRuleJSONBody } from "discord-api-types/v10";
3
+ import type { JSONEncodable } from "./shared.js";
4
+ /**
5
+ * Shape describing initial data used to seed the auto moderation rule builder.
6
+ */
7
+ export type AutomodRuleBuilderData = Partial<RESTPostAPIAutoModerationRuleJSONBody> & {
8
+ name?: string;
9
+ event_type?: AutoModerationRuleEventType;
10
+ trigger_type?: AutoModerationRuleTriggerType;
11
+ actions?: APIAutoModerationAction[];
12
+ };
13
+ /** Builder that produces Discord auto moderation rule payloads. */
14
+ export declare class AutomodRuleBuilder implements JSONEncodable<RESTPostAPIAutoModerationRuleJSONBody> {
15
+ private data;
16
+ constructor(data?: AutomodRuleBuilderData);
17
+ /** Sets the name of the rule. */
18
+ setName(name: string): this;
19
+ /** Sets the event type that will trigger the rule. */
20
+ setEventType(eventType: AutoModerationRuleEventType): this;
21
+ /** Sets the trigger type for the rule. */
22
+ setTriggerType(triggerType: AutoModerationRuleTriggerType): this;
23
+ /**
24
+ * Assigns trigger metadata describing how the rule should match content.
25
+ */
26
+ setTriggerMetadata(metadata: APIAutoModerationRuleTriggerMetadata | null | undefined): this;
27
+ /**
28
+ * Replaces the actions executed when the rule triggers.
29
+ */
30
+ setActions(actions: Array<APIAutoModerationAction | JSONEncodable<APIAutoModerationAction>>): this;
31
+ /** Adds an action to execute when the rule triggers. */
32
+ addAction(action: APIAutoModerationAction | JSONEncodable<APIAutoModerationAction>): this;
33
+ /** Enables or disables the rule. */
34
+ setEnabled(enabled: boolean): this;
35
+ /** Replaces the list of exempt role ids. */
36
+ setExemptRoles(roleIds: string[]): this;
37
+ /** Adds an exempt role id if not already present. */
38
+ addExemptRole(roleId: string): this;
39
+ /** Replaces the list of exempt channel ids. */
40
+ setExemptChannels(channelIds: string[]): this;
41
+ /** Adds an exempt channel id if not already present. */
42
+ addExemptChannel(channelId: string): this;
43
+ /** Serialises the builder into a REST auto moderation rule payload. */
44
+ toJSON(): RESTPostAPIAutoModerationRuleJSONBody;
45
+ }
@@ -0,0 +1,151 @@
1
+ import { resolveJSONEncodable } from "./shared.js";
2
+ /** Builder that produces Discord auto moderation rule payloads. */
3
+ export class AutomodRuleBuilder {
4
+ data;
5
+ constructor(data = {}) {
6
+ this.data = {
7
+ ...data,
8
+ actions: data.actions?.map(cloneAutoModerationAction) ?? [],
9
+ trigger_metadata: data.trigger_metadata
10
+ ? cloneTriggerMetadata(data.trigger_metadata)
11
+ : undefined,
12
+ exempt_roles: data.exempt_roles ? [...data.exempt_roles] : undefined,
13
+ exempt_channels: data.exempt_channels
14
+ ? [...data.exempt_channels]
15
+ : undefined,
16
+ };
17
+ }
18
+ /** Sets the name of the rule. */
19
+ setName(name) {
20
+ this.data.name = name;
21
+ return this;
22
+ }
23
+ /** Sets the event type that will trigger the rule. */
24
+ setEventType(eventType) {
25
+ this.data.event_type = eventType;
26
+ return this;
27
+ }
28
+ /** Sets the trigger type for the rule. */
29
+ setTriggerType(triggerType) {
30
+ this.data.trigger_type = triggerType;
31
+ return this;
32
+ }
33
+ /**
34
+ * Assigns trigger metadata describing how the rule should match content.
35
+ */
36
+ setTriggerMetadata(metadata) {
37
+ this.data.trigger_metadata = metadata
38
+ ? cloneTriggerMetadata(metadata)
39
+ : undefined;
40
+ return this;
41
+ }
42
+ /**
43
+ * Replaces the actions executed when the rule triggers.
44
+ */
45
+ setActions(actions) {
46
+ this.data.actions = actions.map((action) => cloneAutoModerationAction(resolveJSONEncodable(action)));
47
+ return this;
48
+ }
49
+ /** Adds an action to execute when the rule triggers. */
50
+ addAction(action) {
51
+ if (!this.data.actions) {
52
+ this.data.actions = [];
53
+ }
54
+ this.data.actions.push(cloneAutoModerationAction(resolveJSONEncodable(action)));
55
+ return this;
56
+ }
57
+ /** Enables or disables the rule. */
58
+ setEnabled(enabled) {
59
+ this.data.enabled = enabled;
60
+ return this;
61
+ }
62
+ /** Replaces the list of exempt role ids. */
63
+ setExemptRoles(roleIds) {
64
+ this.data.exempt_roles = [...roleIds];
65
+ return this;
66
+ }
67
+ /** Adds an exempt role id if not already present. */
68
+ addExemptRole(roleId) {
69
+ if (!this.data.exempt_roles) {
70
+ this.data.exempt_roles = [];
71
+ }
72
+ if (!this.data.exempt_roles.includes(roleId)) {
73
+ this.data.exempt_roles.push(roleId);
74
+ }
75
+ return this;
76
+ }
77
+ /** Replaces the list of exempt channel ids. */
78
+ setExemptChannels(channelIds) {
79
+ this.data.exempt_channels = [...channelIds];
80
+ return this;
81
+ }
82
+ /** Adds an exempt channel id if not already present. */
83
+ addExemptChannel(channelId) {
84
+ if (!this.data.exempt_channels) {
85
+ this.data.exempt_channels = [];
86
+ }
87
+ if (!this.data.exempt_channels.includes(channelId)) {
88
+ this.data.exempt_channels.push(channelId);
89
+ }
90
+ return this;
91
+ }
92
+ /** Serialises the builder into a REST auto moderation rule payload. */
93
+ toJSON() {
94
+ const { name, event_type, trigger_type } = this.data;
95
+ const actions = this.data.actions ?? [];
96
+ if (!name) {
97
+ throw new Error("[AutomodRuleBuilder] name is required");
98
+ }
99
+ if (event_type === undefined) {
100
+ throw new Error("[AutomodRuleBuilder] event type is required");
101
+ }
102
+ if (trigger_type === undefined) {
103
+ throw new Error("[AutomodRuleBuilder] trigger type is required");
104
+ }
105
+ if (actions.length === 0) {
106
+ throw new Error("[AutomodRuleBuilder] at least one action is required");
107
+ }
108
+ return {
109
+ name,
110
+ event_type,
111
+ trigger_type,
112
+ trigger_metadata: this.data.trigger_metadata
113
+ ? cloneTriggerMetadata(this.data.trigger_metadata)
114
+ : undefined,
115
+ actions: actions.map(cloneAutoModerationAction),
116
+ enabled: this.data.enabled,
117
+ exempt_roles: this.data.exempt_roles
118
+ ? [...this.data.exempt_roles]
119
+ : undefined,
120
+ exempt_channels: this.data.exempt_channels
121
+ ? [...this.data.exempt_channels]
122
+ : undefined,
123
+ };
124
+ }
125
+ }
126
+ function cloneTriggerMetadata(metadata) {
127
+ return {
128
+ keyword_filter: metadata.keyword_filter
129
+ ? [...metadata.keyword_filter]
130
+ : undefined,
131
+ presets: metadata.presets ? [...metadata.presets] : undefined,
132
+ allow_list: metadata.allow_list ? [...metadata.allow_list] : undefined,
133
+ regex_patterns: metadata.regex_patterns
134
+ ? [...metadata.regex_patterns]
135
+ : undefined,
136
+ mention_total_limit: metadata.mention_total_limit,
137
+ mention_raid_protection_enabled: metadata.mention_raid_protection_enabled,
138
+ };
139
+ }
140
+ function cloneAutoModerationAction(action) {
141
+ return {
142
+ type: action.type,
143
+ metadata: action.metadata
144
+ ? {
145
+ channel_id: action.metadata.channel_id,
146
+ duration_seconds: action.metadata.duration_seconds,
147
+ custom_message: action.metadata.custom_message,
148
+ }
149
+ : undefined,
150
+ };
151
+ }
@@ -0,0 +1,33 @@
1
+ import { type APIEmbed, type APIEmbedAuthor, type APIEmbedField, type APIEmbedFooter, type APIEmbedImage, type APIEmbedThumbnail } from "discord-api-types/v10";
2
+ import type { JSONEncodable } from "./shared.js";
3
+ /** Shape describing data used to seed an embed builder instance. */
4
+ export type EmbedBuilderData = Partial<APIEmbed>;
5
+ /** Builder for Discord embed payloads. */
6
+ export declare class EmbedBuilder implements JSONEncodable<APIEmbed> {
7
+ private data;
8
+ constructor(data?: EmbedBuilderData);
9
+ /** Sets or clears the embed title. */
10
+ setTitle(title: string | null | undefined): this;
11
+ /** Sets or clears the embed description. */
12
+ setDescription(description: string | null | undefined): this;
13
+ /** Sets or clears the embed URL. */
14
+ setURL(url: string | null | undefined): this;
15
+ /** Sets or clears the embed color. */
16
+ setColor(color: number | null | undefined): this;
17
+ /** Sets the timestamp value using either a Date or ISO string. */
18
+ setTimestamp(timestamp: Date | number | string | null | undefined): this;
19
+ /** Sets or clears the footer. */
20
+ setFooter(footer: APIEmbedFooter | null | undefined): this;
21
+ /** Sets or clears the image. */
22
+ setImage(image: APIEmbedImage | null | undefined): this;
23
+ /** Sets or clears the thumbnail. */
24
+ setThumbnail(thumbnail: APIEmbedThumbnail | null | undefined): this;
25
+ /** Sets or clears the author. */
26
+ setAuthor(author: APIEmbedAuthor | null | undefined): this;
27
+ /** Replaces the embed fields with the provided values. */
28
+ setFields(fields: APIEmbedField[]): this;
29
+ /** Appends fields to the embed. */
30
+ addFields(...fields: APIEmbedField[]): this;
31
+ /** Serialises the builder into an API compatible embed payload. */
32
+ toJSON(): APIEmbed;
33
+ }
@@ -0,0 +1,94 @@
1
+ /** Builder for Discord embed payloads. */
2
+ export class EmbedBuilder {
3
+ data;
4
+ constructor(data = {}) {
5
+ this.data = {
6
+ ...data,
7
+ footer: data.footer ? { ...data.footer } : undefined,
8
+ image: data.image ? { ...data.image } : undefined,
9
+ thumbnail: data.thumbnail ? { ...data.thumbnail } : undefined,
10
+ author: data.author ? { ...data.author } : undefined,
11
+ fields: data.fields ? data.fields.map((field) => ({ ...field })) : [],
12
+ };
13
+ }
14
+ /** Sets or clears the embed title. */
15
+ setTitle(title) {
16
+ this.data.title = title ?? undefined;
17
+ return this;
18
+ }
19
+ /** Sets or clears the embed description. */
20
+ setDescription(description) {
21
+ this.data.description = description ?? undefined;
22
+ return this;
23
+ }
24
+ /** Sets or clears the embed URL. */
25
+ setURL(url) {
26
+ this.data.url = url ?? undefined;
27
+ return this;
28
+ }
29
+ /** Sets or clears the embed color. */
30
+ setColor(color) {
31
+ this.data.color = color ?? undefined;
32
+ return this;
33
+ }
34
+ /** Sets the timestamp value using either a Date or ISO string. */
35
+ setTimestamp(timestamp) {
36
+ if (timestamp === null || timestamp === undefined) {
37
+ this.data.timestamp = undefined;
38
+ }
39
+ else if (timestamp instanceof Date) {
40
+ this.data.timestamp = timestamp.toISOString();
41
+ }
42
+ else if (typeof timestamp === "number") {
43
+ this.data.timestamp = new Date(timestamp).toISOString();
44
+ }
45
+ else {
46
+ this.data.timestamp = new Date(timestamp).toISOString();
47
+ }
48
+ return this;
49
+ }
50
+ /** Sets or clears the footer. */
51
+ setFooter(footer) {
52
+ this.data.footer = footer ? { ...footer } : undefined;
53
+ return this;
54
+ }
55
+ /** Sets or clears the image. */
56
+ setImage(image) {
57
+ this.data.image = image ? { ...image } : undefined;
58
+ return this;
59
+ }
60
+ /** Sets or clears the thumbnail. */
61
+ setThumbnail(thumbnail) {
62
+ this.data.thumbnail = thumbnail ? { ...thumbnail } : undefined;
63
+ return this;
64
+ }
65
+ /** Sets or clears the author. */
66
+ setAuthor(author) {
67
+ this.data.author = author ? { ...author } : undefined;
68
+ return this;
69
+ }
70
+ /** Replaces the embed fields with the provided values. */
71
+ setFields(fields) {
72
+ this.data.fields = fields.map((field) => ({ ...field }));
73
+ return this;
74
+ }
75
+ /** Appends fields to the embed. */
76
+ addFields(...fields) {
77
+ if (!this.data.fields) {
78
+ this.data.fields = [];
79
+ }
80
+ this.data.fields.push(...fields.map((field) => ({ ...field })));
81
+ return this;
82
+ }
83
+ /** Serialises the builder into an API compatible embed payload. */
84
+ toJSON() {
85
+ return {
86
+ ...this.data,
87
+ footer: this.data.footer ? { ...this.data.footer } : undefined,
88
+ image: this.data.image ? { ...this.data.image } : undefined,
89
+ thumbnail: this.data.thumbnail ? { ...this.data.thumbnail } : undefined,
90
+ author: this.data.author ? { ...this.data.author } : undefined,
91
+ fields: this.data.fields?.map((field) => ({ ...field })),
92
+ };
93
+ }
94
+ }
@@ -0,0 +1,131 @@
1
+ import type { APIComponentInContainer, APIContainerComponent, APIMediaGalleryComponent, APIMediaGalleryItem, APISectionAccessoryComponent, APISectionComponent, APISeparatorComponent, APITextDisplayComponent, APIThumbnailComponent, APIUnfurledMediaItem } from "discord-api-types/v10";
2
+ import { SeparatorSpacingSize } from "discord-api-types/v10";
3
+ import type { JSONEncodable } from "./shared.js";
4
+ /** Structured message container payload. */
5
+ export type MiniContainerComponent = APIContainerComponent;
6
+ /** Section within a structured message container. */
7
+ export type MiniSectionComponent = APISectionComponent;
8
+ /** Text display structured message component. */
9
+ export type MiniTextDisplayComponent = APITextDisplayComponent;
10
+ /** Separator structured message component. */
11
+ export type MiniSeparatorComponent = APISeparatorComponent;
12
+ /** Thumbnail payload used within sections. */
13
+ export type MiniThumbnailComponent = APIThumbnailComponent;
14
+ /** Gallery item payload. */
15
+ export type MiniGalleryItemComponent = APIMediaGalleryItem;
16
+ /** Gallery structured message component. */
17
+ export type MiniGalleryComponent = APIMediaGalleryComponent;
18
+ /** Union of supported components within a container. */
19
+ export type MiniContentComponent = APIComponentInContainer;
20
+ /** Union of supported section accessory components. */
21
+ export type MiniSectionAccessoryComponent = APISectionAccessoryComponent;
22
+ /** Data accepted by the container builder constructor. */
23
+ export type MiniContainerBuilderData = Partial<Omit<MiniContainerComponent, "components">> & {
24
+ components?: Array<MiniContentComponent | JSONEncodable<MiniContentComponent>>;
25
+ };
26
+ /** Data accepted by the section builder constructor. */
27
+ export type MiniSectionBuilderData = Partial<Omit<MiniSectionComponent, "components" | "accessory">> & {
28
+ components?: Array<MiniTextDisplayComponent | JSONEncodable<MiniTextDisplayComponent>>;
29
+ accessory?: MiniSectionAccessoryComponent | JSONEncodable<MiniSectionAccessoryComponent>;
30
+ };
31
+ /** Data accepted by the text display builder constructor. */
32
+ export type MiniTextDisplayBuilderData = Partial<MiniTextDisplayComponent>;
33
+ /** Data accepted by the separator builder constructor. */
34
+ export type MiniSeparatorBuilderData = Partial<MiniSeparatorComponent>;
35
+ /** Data accepted by the gallery builder constructor. */
36
+ export type MiniGalleryBuilderData = Partial<Omit<MiniGalleryComponent, "items">> & {
37
+ items?: Array<MiniGalleryItemComponent | JSONEncodable<MiniGalleryItemComponent>>;
38
+ };
39
+ /** Data accepted by the gallery item builder constructor. */
40
+ export type MiniGalleryItemBuilderData = Partial<MiniGalleryItemComponent>;
41
+ /** Data accepted by the thumbnail builder constructor. */
42
+ export type MiniThumbnailBuilderData = Partial<MiniThumbnailComponent>;
43
+ /** Builder for structured message container payloads. */
44
+ export declare class MiniContainerBuilder implements JSONEncodable<MiniContainerComponent> {
45
+ private data;
46
+ constructor(data?: MiniContainerBuilderData);
47
+ /** Replaces the components contained in the container. */
48
+ setComponents(components: Array<MiniContentComponent | JSONEncodable<MiniContentComponent>>): this;
49
+ /** Replaces the sections contained in the container. */
50
+ setSections(sections: Array<MiniSectionComponent | JSONEncodable<MiniSectionComponent>>): this;
51
+ /** Adds a component to the container. */
52
+ addComponent(component: MiniContentComponent | JSONEncodable<MiniContentComponent>): this;
53
+ /** Adds a section to the container. */
54
+ addSection(section: MiniSectionComponent | JSONEncodable<MiniSectionComponent>): this;
55
+ /** Sets or clears the accent colour on the container. */
56
+ setAccentColor(color: number | null | undefined): this;
57
+ /** Marks the container as a spoiler. */
58
+ setSpoiler(spoiler: boolean | null | undefined): this;
59
+ /** Serialises the container into a structured message payload. */
60
+ toJSON(): MiniContainerComponent;
61
+ }
62
+ /** Builder for structured message sections. */
63
+ export declare class MiniSectionBuilder implements JSONEncodable<MiniSectionComponent> {
64
+ private data;
65
+ constructor(data?: MiniSectionBuilderData);
66
+ /** Replaces the text components within the section. */
67
+ setComponents(components: Array<MiniTextDisplayComponent | JSONEncodable<MiniTextDisplayComponent>>): this;
68
+ /** Adds a text component to the section. */
69
+ addComponent(component: MiniTextDisplayComponent | JSONEncodable<MiniTextDisplayComponent>): this;
70
+ /** Sets or clears the accessory component. */
71
+ setAccessory(accessory: MiniSectionAccessoryComponent | JSONEncodable<MiniSectionAccessoryComponent> | null | undefined): this;
72
+ /** Serialises the section into a structured message payload. */
73
+ toJSON(): MiniSectionComponent;
74
+ }
75
+ /** Builder for structured message text display components. */
76
+ export declare class MiniTextDisplayBuilder implements JSONEncodable<MiniTextDisplayComponent> {
77
+ private data;
78
+ constructor(data?: MiniTextDisplayBuilderData);
79
+ /** Sets or clears the primary text content. */
80
+ setContent(content: string | null | undefined): this;
81
+ /** Serialises the component into a structured message payload. */
82
+ toJSON(): MiniTextDisplayComponent;
83
+ }
84
+ /** Builder for structured message separator components. */
85
+ export declare class MiniSeparatorBuilder implements JSONEncodable<MiniSeparatorComponent> {
86
+ private data;
87
+ constructor(data?: MiniSeparatorBuilderData);
88
+ /** Sets whether the separator should render a divider. */
89
+ setDivider(divider: boolean | null | undefined): this;
90
+ /** Sets the separator spacing value. */
91
+ setSpacing(spacing: SeparatorSpacingSize | null | undefined): this;
92
+ /** Serialises the separator payload. */
93
+ toJSON(): MiniSeparatorComponent;
94
+ }
95
+ /** Builder for structured message thumbnails. */
96
+ export declare class MiniThumbnailBuilder implements JSONEncodable<MiniThumbnailComponent> {
97
+ private data;
98
+ constructor(data?: MiniThumbnailBuilderData);
99
+ /** Sets the media payload for the thumbnail. */
100
+ setMedia(media: APIUnfurledMediaItem | null | undefined): this;
101
+ /** Sets the thumbnail description. */
102
+ setDescription(description: string | null | undefined): this;
103
+ /** Marks the thumbnail as a spoiler. */
104
+ setSpoiler(spoiler: boolean | null | undefined): this;
105
+ /** Serialises the thumbnail payload. */
106
+ toJSON(): MiniThumbnailComponent;
107
+ }
108
+ /** Builder for structured message gallery items. */
109
+ export declare class MiniGalleryItemBuilder implements JSONEncodable<MiniGalleryItemComponent> {
110
+ private data;
111
+ constructor(data?: MiniGalleryItemBuilderData);
112
+ /** Sets the media item payload. */
113
+ setMedia(media: APIUnfurledMediaItem | null | undefined): this;
114
+ /** Sets the media description. */
115
+ setDescription(description: string | null | undefined): this;
116
+ /** Marks the media item as a spoiler. */
117
+ setSpoiler(spoiler: boolean | null | undefined): this;
118
+ /** Serialises the gallery item payload. */
119
+ toJSON(): MiniGalleryItemComponent;
120
+ }
121
+ /** Builder for structured message gallery components. */
122
+ export declare class MiniGalleryBuilder implements JSONEncodable<MiniGalleryComponent> {
123
+ private data;
124
+ constructor(data?: MiniGalleryBuilderData);
125
+ /** Replaces the gallery items. */
126
+ setItems(items: Array<MiniGalleryItemComponent | JSONEncodable<MiniGalleryItemComponent>>): this;
127
+ /** Adds a gallery item to the payload. */
128
+ addItem(item: MiniGalleryItemComponent | JSONEncodable<MiniGalleryItemComponent>): this;
129
+ /** Serialises the gallery payload. */
130
+ toJSON(): MiniGalleryComponent;
131
+ }
@@ -0,0 +1,345 @@
1
+ import { ComponentType } from "discord-api-types/v10";
2
+ import { resolveJSONEncodable } from "./shared.js";
3
+ function cloneContainerComponent(component) {
4
+ const resolved = resolveJSONEncodable(component);
5
+ return { ...resolved };
6
+ }
7
+ function cloneAccessory(accessory) {
8
+ const resolved = resolveJSONEncodable(accessory);
9
+ return { ...resolved };
10
+ }
11
+ /** Builder for structured message container payloads. */
12
+ export class MiniContainerBuilder {
13
+ data;
14
+ constructor(data = {}) {
15
+ const components = data.components
16
+ ? data.components.map((component) => cloneContainerComponent(component))
17
+ : [];
18
+ this.data = {
19
+ ...data,
20
+ type: ComponentType.Container,
21
+ components,
22
+ };
23
+ }
24
+ /** Replaces the components contained in the container. */
25
+ setComponents(components) {
26
+ this.data.components = components.map((component) => cloneContainerComponent(component));
27
+ return this;
28
+ }
29
+ /** Replaces the sections contained in the container. */
30
+ setSections(sections) {
31
+ return this.setComponents(sections);
32
+ }
33
+ /** Adds a component to the container. */
34
+ addComponent(component) {
35
+ this.data.components ??= [];
36
+ this.data.components.push(cloneContainerComponent(component));
37
+ return this;
38
+ }
39
+ /** Adds a section to the container. */
40
+ addSection(section) {
41
+ return this.addComponent(section);
42
+ }
43
+ /** Sets or clears the accent colour on the container. */
44
+ setAccentColor(color) {
45
+ if (color === undefined) {
46
+ delete this.data.accent_color;
47
+ }
48
+ else {
49
+ this.data.accent_color = color ?? null;
50
+ }
51
+ return this;
52
+ }
53
+ /** Marks the container as a spoiler. */
54
+ setSpoiler(spoiler) {
55
+ if (spoiler === null || spoiler === undefined) {
56
+ delete this.data.spoiler;
57
+ }
58
+ else {
59
+ this.data.spoiler = spoiler;
60
+ }
61
+ return this;
62
+ }
63
+ /** Serialises the container into a structured message payload. */
64
+ toJSON() {
65
+ const components = this.data.components ?? [];
66
+ return {
67
+ ...this.data,
68
+ type: ComponentType.Container,
69
+ components: components.map((component) => ({ ...component })),
70
+ };
71
+ }
72
+ }
73
+ /** Builder for structured message sections. */
74
+ export class MiniSectionBuilder {
75
+ data;
76
+ constructor(data = {}) {
77
+ const components = data.components
78
+ ? data.components.map((component) => cloneTextDisplayComponent(component))
79
+ : [];
80
+ const rawAccessory = data.accessory;
81
+ const accessory = rawAccessory === undefined || rawAccessory === null
82
+ ? undefined
83
+ : cloneAccessory(rawAccessory);
84
+ this.data = {
85
+ ...data,
86
+ type: ComponentType.Section,
87
+ components,
88
+ accessory,
89
+ };
90
+ }
91
+ /** Replaces the text components within the section. */
92
+ setComponents(components) {
93
+ this.data.components = components.map((component) => cloneTextDisplayComponent(component));
94
+ return this;
95
+ }
96
+ /** Adds a text component to the section. */
97
+ addComponent(component) {
98
+ this.data.components ??= [];
99
+ this.data.components.push(cloneTextDisplayComponent(component));
100
+ return this;
101
+ }
102
+ /** Sets or clears the accessory component. */
103
+ setAccessory(accessory) {
104
+ if (accessory === null || accessory === undefined) {
105
+ this.data.accessory = undefined;
106
+ }
107
+ else {
108
+ this.data.accessory = cloneAccessory(accessory);
109
+ }
110
+ return this;
111
+ }
112
+ /** Serialises the section into a structured message payload. */
113
+ toJSON() {
114
+ const components = this.data.components ?? [];
115
+ const accessory = this.data.accessory ? { ...this.data.accessory } : undefined;
116
+ if (!accessory) {
117
+ throw new Error("[MiniSectionBuilder] accessory is required for sections");
118
+ }
119
+ return {
120
+ ...this.data,
121
+ type: ComponentType.Section,
122
+ components: components.map((component) => ({ ...component })),
123
+ accessory,
124
+ };
125
+ }
126
+ }
127
+ function cloneTextDisplayComponent(component) {
128
+ const resolved = resolveJSONEncodable(component);
129
+ return { ...resolved };
130
+ }
131
+ /** Builder for structured message text display components. */
132
+ export class MiniTextDisplayBuilder {
133
+ data;
134
+ constructor(data = {}) {
135
+ this.data = {
136
+ ...data,
137
+ type: ComponentType.TextDisplay,
138
+ };
139
+ }
140
+ /** Sets or clears the primary text content. */
141
+ setContent(content) {
142
+ if (content === null || content === undefined) {
143
+ delete this.data.content;
144
+ }
145
+ else {
146
+ this.data.content = content;
147
+ }
148
+ return this;
149
+ }
150
+ /** Serialises the component into a structured message payload. */
151
+ toJSON() {
152
+ if (!this.data.content) {
153
+ throw new Error("[MiniTextDisplayBuilder] content is required for text displays");
154
+ }
155
+ return {
156
+ ...this.data,
157
+ type: ComponentType.TextDisplay,
158
+ };
159
+ }
160
+ }
161
+ /** Builder for structured message separator components. */
162
+ export class MiniSeparatorBuilder {
163
+ data;
164
+ constructor(data = {}) {
165
+ this.data = {
166
+ ...data,
167
+ type: ComponentType.Separator,
168
+ };
169
+ }
170
+ /** Sets whether the separator should render a divider. */
171
+ setDivider(divider) {
172
+ if (divider === null || divider === undefined) {
173
+ delete this.data.divider;
174
+ }
175
+ else {
176
+ this.data.divider = divider;
177
+ }
178
+ return this;
179
+ }
180
+ /** Sets the separator spacing value. */
181
+ setSpacing(spacing) {
182
+ if (spacing === null || spacing === undefined) {
183
+ delete this.data.spacing;
184
+ }
185
+ else {
186
+ this.data.spacing = spacing;
187
+ }
188
+ return this;
189
+ }
190
+ /** Serialises the separator payload. */
191
+ toJSON() {
192
+ return {
193
+ ...this.data,
194
+ type: ComponentType.Separator,
195
+ };
196
+ }
197
+ }
198
+ /** Builder for structured message thumbnails. */
199
+ export class MiniThumbnailBuilder {
200
+ data;
201
+ constructor(data = {}) {
202
+ this.data = {
203
+ ...data,
204
+ type: ComponentType.Thumbnail,
205
+ media: data.media ? { ...data.media } : undefined,
206
+ };
207
+ }
208
+ /** Sets the media payload for the thumbnail. */
209
+ setMedia(media) {
210
+ if (media === null || media === undefined) {
211
+ delete this.data.media;
212
+ }
213
+ else {
214
+ this.data.media = { ...media };
215
+ }
216
+ return this;
217
+ }
218
+ /** Sets the thumbnail description. */
219
+ setDescription(description) {
220
+ if (description === null || description === undefined) {
221
+ delete this.data.description;
222
+ }
223
+ else {
224
+ this.data.description = description;
225
+ }
226
+ return this;
227
+ }
228
+ /** Marks the thumbnail as a spoiler. */
229
+ setSpoiler(spoiler) {
230
+ if (spoiler === null || spoiler === undefined) {
231
+ delete this.data.spoiler;
232
+ }
233
+ else {
234
+ this.data.spoiler = spoiler;
235
+ }
236
+ return this;
237
+ }
238
+ /** Serialises the thumbnail payload. */
239
+ toJSON() {
240
+ if (!this.data.media) {
241
+ throw new Error("[MiniThumbnailBuilder] media is required for thumbnails");
242
+ }
243
+ return {
244
+ ...this.data,
245
+ type: ComponentType.Thumbnail,
246
+ };
247
+ }
248
+ }
249
+ /** Builder for structured message gallery items. */
250
+ export class MiniGalleryItemBuilder {
251
+ data;
252
+ constructor(data = {}) {
253
+ this.data = {
254
+ ...data,
255
+ media: data.media ? { ...data.media } : undefined,
256
+ };
257
+ }
258
+ /** Sets the media item payload. */
259
+ setMedia(media) {
260
+ if (media === null || media === undefined) {
261
+ delete this.data.media;
262
+ }
263
+ else {
264
+ this.data.media = { ...media };
265
+ }
266
+ return this;
267
+ }
268
+ /** Sets the media description. */
269
+ setDescription(description) {
270
+ if (description === null || description === undefined) {
271
+ delete this.data.description;
272
+ }
273
+ else {
274
+ this.data.description = description;
275
+ }
276
+ return this;
277
+ }
278
+ /** Marks the media item as a spoiler. */
279
+ setSpoiler(spoiler) {
280
+ if (spoiler === null || spoiler === undefined) {
281
+ delete this.data.spoiler;
282
+ }
283
+ else {
284
+ this.data.spoiler = spoiler;
285
+ }
286
+ return this;
287
+ }
288
+ /** Serialises the gallery item payload. */
289
+ toJSON() {
290
+ if (!this.data.media) {
291
+ throw new Error("[MiniGalleryItemBuilder] media is required for gallery items");
292
+ }
293
+ return {
294
+ ...this.data,
295
+ media: { ...this.data.media },
296
+ };
297
+ }
298
+ }
299
+ /** Builder for structured message gallery components. */
300
+ export class MiniGalleryBuilder {
301
+ data;
302
+ constructor(data = {}) {
303
+ const items = data.items
304
+ ? data.items.map((item) => resolveGalleryItem(item))
305
+ : [];
306
+ this.data = {
307
+ ...data,
308
+ type: ComponentType.MediaGallery,
309
+ items,
310
+ };
311
+ }
312
+ /** Replaces the gallery items. */
313
+ setItems(items) {
314
+ this.data.items = items.map((item) => resolveGalleryItem(item));
315
+ return this;
316
+ }
317
+ /** Adds a gallery item to the payload. */
318
+ addItem(item) {
319
+ this.data.items ??= [];
320
+ this.data.items.push(resolveGalleryItem(item));
321
+ return this;
322
+ }
323
+ /** Serialises the gallery payload. */
324
+ toJSON() {
325
+ const items = this.data.items ?? [];
326
+ if (items.length === 0) {
327
+ throw new Error("[MiniGalleryBuilder] at least one gallery item is required");
328
+ }
329
+ return {
330
+ ...this.data,
331
+ type: ComponentType.MediaGallery,
332
+ items: items.map((item) => ({ ...item })),
333
+ };
334
+ }
335
+ }
336
+ function resolveGalleryItem(item) {
337
+ const resolved = resolveJSONEncodable(item);
338
+ if (!resolved.media) {
339
+ throw new Error("[MiniGalleryBuilder] gallery items require media");
340
+ }
341
+ return {
342
+ ...resolved,
343
+ media: { ...resolved.media },
344
+ };
345
+ }
@@ -11,4 +11,10 @@ export { ChannelSelectMenuBuilder } from "./ChannelSelectMenuBuilder.js";
11
11
  export type { ChannelSelectMenuBuilderData } from "./ChannelSelectMenuBuilder.js";
12
12
  export { ModalBuilder } from "./ModalBuilder.js";
13
13
  export type { ModalBuilderData, ModalComponentLike } from "./ModalBuilder.js";
14
+ export { AutomodRuleBuilder } from "./AutomodRuleBuilder.js";
15
+ export type { AutomodRuleBuilderData } from "./AutomodRuleBuilder.js";
16
+ export { EmbedBuilder } from "./EmbedBuilder.js";
17
+ export type { EmbedBuilderData } from "./EmbedBuilder.js";
18
+ export { MiniContainerBuilder, MiniSectionBuilder, MiniTextDisplayBuilder, MiniSeparatorBuilder, MiniGalleryBuilder, MiniGalleryItemBuilder, MiniThumbnailBuilder, } from "./MiniContainerBuilder.js";
19
+ export type { MiniContainerBuilderData, MiniSectionBuilderData, MiniTextDisplayBuilderData, MiniSeparatorBuilderData, MiniGalleryBuilderData, MiniGalleryItemBuilderData, MiniThumbnailBuilderData, MiniContainerComponent, MiniSectionComponent, MiniTextDisplayComponent, MiniSeparatorComponent, MiniGalleryComponent, MiniGalleryItemComponent, MiniThumbnailComponent, MiniContentComponent, MiniSectionAccessoryComponent, } from "./MiniContainerBuilder.js";
14
20
  export type { JSONEncodable } from "./shared.js";
@@ -5,3 +5,6 @@ export { StringSelectMenuBuilder } from "./StringSelectMenuBuilder.js";
5
5
  export { RoleSelectMenuBuilder } from "./RoleSelectMenuBuilder.js";
6
6
  export { ChannelSelectMenuBuilder } from "./ChannelSelectMenuBuilder.js";
7
7
  export { ModalBuilder } from "./ModalBuilder.js";
8
+ export { AutomodRuleBuilder } from "./AutomodRuleBuilder.js";
9
+ export { EmbedBuilder } from "./EmbedBuilder.js";
10
+ export { MiniContainerBuilder, MiniSectionBuilder, MiniTextDisplayBuilder, MiniSeparatorBuilder, MiniGalleryBuilder, MiniGalleryItemBuilder, MiniThumbnailBuilder, } from "./MiniContainerBuilder.js";
package/dist/index.d.ts CHANGED
@@ -12,5 +12,6 @@ export { RoleConnectionMetadataTypes } from "./types/RoleConnectionMetadataTypes
12
12
  export { ChannelType } from "./types/ChannelType.js";
13
13
  export { InteractionFollowUpFlags, InteractionReplyFlags, } from "./types/InteractionFlags.js";
14
14
  export { ButtonStyle } from "./types/ButtonStyle.js";
15
+ export { MiniPermFlags } from "./types/PermissionFlags.js";
15
16
  export type { MiniComponentActionRow, MiniComponentMessageActionRow, } from "./types/ComponentTypes.js";
16
17
  export * from "./builders/index.js";
package/dist/index.js CHANGED
@@ -6,4 +6,5 @@ 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 { MiniPermFlags } from "./types/PermissionFlags.js";
9
10
  export * from "./builders/index.js";
@@ -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];
@@ -0,0 +1,5 @@
1
+ import { PermissionFlagsBits } from "discord-api-types/v10";
2
+ /** Convenience mapping of Discord permission bit flags for MiniInteraction usage. */
3
+ export const MiniPermFlags = {
4
+ ...PermissionFlagsBits,
5
+ };
@@ -1,3 +1,13 @@
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
  *
@@ -17,16 +27,51 @@ export function normaliseInteractionMessageData(data) {
17
27
  if (!data) {
18
28
  return undefined;
19
29
  }
20
- if (data.flags === undefined) {
21
- return data;
22
- }
23
- const { flags, ...rest } = data;
24
- const normalisedFlags = normaliseMessageFlags(flags);
25
- if (normalisedFlags === flags) {
30
+ const usesComponentsV2 = Array.isArray(data.components)
31
+ ? containsComponentsV2(data.components)
32
+ : false;
33
+ const normalisedFlags = normaliseMessageFlags(data.flags);
34
+ const finalFlags = usesComponentsV2
35
+ ? ((normalisedFlags ?? 0) | RawMessageFlags.IsComponentsV2)
36
+ : normalisedFlags;
37
+ if (finalFlags === data.flags) {
26
38
  return data;
27
39
  }
40
+ const { flags: _flags, ...rest } = data;
28
41
  return {
29
42
  ...rest,
30
- flags: normalisedFlags,
43
+ ...(finalFlags !== undefined ? { flags: finalFlags } : {}),
31
44
  };
32
45
  }
46
+ function containsComponentsV2(components) {
47
+ return components.some((component) => componentUsesComponentsV2(component));
48
+ }
49
+ function componentUsesComponentsV2(component) {
50
+ const resolved = resolveComponentLike(component);
51
+ if (!resolved || typeof resolved !== "object") {
52
+ return false;
53
+ }
54
+ const type = resolved.type;
55
+ if (typeof type !== "number") {
56
+ return false;
57
+ }
58
+ if (COMPONENTS_V2_TYPES.has(type)) {
59
+ return true;
60
+ }
61
+ if (type === ComponentType.ActionRow) {
62
+ const rowComponents = resolved.components;
63
+ if (Array.isArray(rowComponents)) {
64
+ return containsComponentsV2(rowComponents);
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ function resolveComponentLike(component) {
70
+ if (component && typeof component === "object" && "toJSON" in component) {
71
+ const encoder = component;
72
+ if (typeof encoder.toJSON === "function") {
73
+ return encoder.toJSON();
74
+ }
75
+ }
76
+ return component;
77
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minesa-org/mini-interaction",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
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",