@ovencord/builders 1.12.7 → 1.12.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -3
- package/src/components/ActionRow.ts +14 -13
- package/src/components/Assertions.ts +38 -27
- package/src/components/Component.ts +3 -3
- package/src/components/Components.ts +35 -27
- package/src/components/button/Button.ts +1 -1
- package/src/components/button/ButtonBuilder.ts +7 -6
- package/src/components/button/CustomIdButton.ts +4 -2
- package/src/components/button/LinkButton.ts +3 -2
- package/src/components/button/mixins/EmojiOrLabelButtonMixin.ts +3 -5
- package/src/components/label/Label.ts +4 -1
- package/src/components/selectMenu/ChannelSelectMenu.ts +2 -2
- package/src/components/selectMenu/MentionableSelectMenu.ts +2 -2
- package/src/components/selectMenu/RoleSelectMenu.ts +2 -2
- package/src/components/selectMenu/StringSelectMenu.ts +1 -1
- package/src/components/selectMenu/UserSelectMenu.ts +2 -2
- package/src/components/textInput/TextInput.ts +1 -1
- package/src/components/v2/Assertions.ts +11 -6
- package/src/components/v2/Container.ts +12 -7
- package/src/components/v2/File.ts +1 -1
- package/src/components/v2/MediaGallery.ts +1 -1
- package/src/components/v2/Section.ts +7 -20
- package/src/components/v2/Separator.ts +1 -1
- package/src/components/v2/TextDisplay.ts +2 -2
- package/src/components/v2/Thumbnail.ts +8 -8
- package/src/index.ts +29 -42
- package/src/interactions/commands/Command.ts +11 -7
- package/src/interactions/commands/SharedName.ts +2 -3
- package/src/interactions/commands/SharedNameAndDescription.ts +2 -1
- package/src/interactions/commands/chatInput/Assertions.ts +17 -5
- package/src/interactions/commands/chatInput/ChatInputCommandSubcommands.ts +5 -4
- package/src/interactions/commands/chatInput/mixins/ApplicationCommandNumericOptionMinMaxValueMixin.ts +3 -5
- package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionChannelTypesMixin.ts +4 -6
- package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionWithAutocompleteMixin.ts +1 -1
- package/src/interactions/commands/chatInput/mixins/ApplicationCommandOptionWithChoicesMixin.ts +1 -1
- package/src/interactions/commands/chatInput/mixins/SharedChatInputCommandOptions.ts +34 -11
- package/src/interactions/commands/chatInput/mixins/SharedSubcommands.ts +2 -2
- package/src/interactions/commands/chatInput/options/ApplicationCommandOptionBase.ts +1 -1
- package/src/interactions/commands/chatInput/options/string.ts +3 -3
- package/src/interactions/modals/Modal.ts +3 -9
- package/src/messages/Assertions.ts +6 -3
- package/src/messages/Attachment.ts +1 -1
- package/src/messages/Message.ts +30 -21
- package/src/messages/embed/Assertions.ts +16 -3
- package/src/messages/embed/Embed.ts +4 -2
- package/src/messages/poll/Poll.ts +1 -1
- package/src/util/componentUtil.ts +4 -4
- package/src/util/resolveBuilder.ts +5 -2
- package/src/util/validation.ts +4 -2
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@ovencord/builders",
|
|
4
|
-
"version": "1.12.
|
|
4
|
+
"version": "1.12.9",
|
|
5
5
|
"description": "A set of builders that you can use when creating your bot",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "bun test",
|
|
8
8
|
"typecheck": "tsc --noEmit",
|
|
9
|
-
"lint": "
|
|
9
|
+
"lint": "biome check .",
|
|
10
|
+
"format": "biome format --write .",
|
|
11
|
+
"check": "biome check --write ."
|
|
10
12
|
},
|
|
11
13
|
"exports": "./src/index.ts",
|
|
12
14
|
"main": "./src/index.ts",
|
|
@@ -43,7 +45,7 @@
|
|
|
43
45
|
"ts-mixer": "^6.0.4",
|
|
44
46
|
|
|
45
47
|
"zod": "^4.3.6",
|
|
46
|
-
"@ovencord/util": "^1.1.
|
|
48
|
+
"@ovencord/util": "^1.1.8"
|
|
47
49
|
},
|
|
48
50
|
"devDependencies": {},
|
|
49
51
|
"engines": {
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
APITextInputComponent,
|
|
3
2
|
APIActionRowComponent,
|
|
4
|
-
|
|
3
|
+
APIButtonComponentWithCustomId,
|
|
4
|
+
APIButtonComponentWithSKUId,
|
|
5
|
+
APIButtonComponentWithURL,
|
|
5
6
|
APIChannelSelectComponent,
|
|
7
|
+
APIComponentInActionRow,
|
|
6
8
|
APIMentionableSelectComponent,
|
|
7
9
|
APIRoleSelectComponent,
|
|
8
10
|
APIStringSelectComponent,
|
|
11
|
+
APITextInputComponent,
|
|
9
12
|
APIUserSelectComponent,
|
|
10
|
-
APIButtonComponentWithCustomId,
|
|
11
|
-
APIButtonComponentWithSKUId,
|
|
12
|
-
APIButtonComponentWithURL,
|
|
13
13
|
} from 'discord-api-types/v10';
|
|
14
14
|
import { ComponentType } from 'discord-api-types/v10';
|
|
15
15
|
import { normalizeArray, type RestOrArray } from '../util/normalizeArray.js';
|
|
16
16
|
import { resolveBuilder } from '../util/resolveBuilder.js';
|
|
17
17
|
import { validate } from '../util/validation.js';
|
|
18
18
|
import { actionRowPredicate } from './Assertions.js';
|
|
19
|
-
import { ComponentBuilder } from './Component.js';
|
|
20
|
-
import type { AnyActionRowComponentBuilder } from './Components.js';
|
|
21
|
-
import { createComponentBuilder } from './Components.js';
|
|
22
19
|
import {
|
|
23
20
|
DangerButtonBuilder,
|
|
24
21
|
PrimaryButtonBuilder,
|
|
@@ -27,6 +24,9 @@ import {
|
|
|
27
24
|
} from './button/CustomIdButton.js';
|
|
28
25
|
import { LinkButtonBuilder } from './button/LinkButton.js';
|
|
29
26
|
import { PremiumButtonBuilder } from './button/PremiumButton.js';
|
|
27
|
+
import { ComponentBuilder } from './Component.js';
|
|
28
|
+
import type { AnyActionRowComponentBuilder, MessageComponentBuilder } from './Components.js';
|
|
29
|
+
import { createComponentBuilder } from './Components.js';
|
|
30
30
|
import { ChannelSelectMenuBuilder } from './selectMenu/ChannelSelectMenu.js';
|
|
31
31
|
import { MentionableSelectMenuBuilder } from './selectMenu/MentionableSelectMenu.js';
|
|
32
32
|
import { RoleSelectMenuBuilder } from './selectMenu/RoleSelectMenu.js';
|
|
@@ -34,16 +34,17 @@ import { StringSelectMenuBuilder } from './selectMenu/StringSelectMenu.js';
|
|
|
34
34
|
import { UserSelectMenuBuilder } from './selectMenu/UserSelectMenu.js';
|
|
35
35
|
import { TextInputBuilder } from './textInput/TextInput.js';
|
|
36
36
|
|
|
37
|
-
export interface ActionRowBuilderData<T extends AnyActionRowComponentBuilder = AnyActionRowComponentBuilder>
|
|
38
|
-
Omit<APIActionRowComponent<APIComponentInActionRow>, 'components'
|
|
39
|
-
> {
|
|
37
|
+
export interface ActionRowBuilderData<T extends AnyActionRowComponentBuilder = AnyActionRowComponentBuilder>
|
|
38
|
+
extends Partial<Omit<APIActionRowComponent<APIComponentInActionRow>, 'components'>> {
|
|
40
39
|
components: T[];
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
43
|
* A builder that creates API-compatible JSON data for action rows.
|
|
45
44
|
*/
|
|
46
|
-
export class ActionRowBuilder<
|
|
45
|
+
export class ActionRowBuilder<
|
|
46
|
+
T extends AnyActionRowComponentBuilder = AnyActionRowComponentBuilder,
|
|
47
|
+
> extends ComponentBuilder<APIActionRowComponent<APIComponentInActionRow>> {
|
|
47
48
|
/**
|
|
48
49
|
* @internal
|
|
49
50
|
*/
|
|
@@ -348,7 +349,7 @@ export class ActionRowBuilder<T extends AnyActionRowComponentBuilder = AnyAction
|
|
|
348
349
|
|
|
349
350
|
const data = {
|
|
350
351
|
...structuredClone(rest),
|
|
351
|
-
components: components.map((component) => (component as
|
|
352
|
+
components: components.map((component) => (component as MessageComponentBuilder).toJSON(validationOverride)),
|
|
352
353
|
};
|
|
353
354
|
|
|
354
355
|
validate(actionRowPredicate, data, validationOverride);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ButtonStyle, ChannelType, ComponentType, SelectMenuDefaultValueType } from 'discord-api-types/v10';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import {
|
|
3
|
+
import { customIdPredicate, idPredicate, snowflakePredicate } from '../Assertions.js';
|
|
4
4
|
|
|
5
5
|
export const emojiPredicate = z
|
|
6
6
|
.strictObject({
|
|
@@ -19,37 +19,52 @@ const buttonPredicateBase = z.strictObject({
|
|
|
19
19
|
|
|
20
20
|
const buttonLabelPredicate = z.string().min(1).max(80);
|
|
21
21
|
|
|
22
|
-
const buttonCustomIdPredicateBase = buttonPredicateBase
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
const buttonCustomIdPredicateBase = buttonPredicateBase.extend({
|
|
23
|
+
custom_id: customIdPredicate,
|
|
24
|
+
emoji: emojiPredicate.optional(),
|
|
25
|
+
label: buttonLabelPredicate.optional(),
|
|
26
|
+
});
|
|
30
27
|
|
|
31
28
|
const buttonPrimaryPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Primary) });
|
|
32
29
|
const buttonSecondaryPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Secondary) });
|
|
33
30
|
const buttonSuccessPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Success) });
|
|
34
31
|
const buttonDangerPredicate = buttonCustomIdPredicateBase.extend({ style: z.literal(ButtonStyle.Danger) });
|
|
35
32
|
|
|
36
|
-
const buttonPrimaryRefinedPredicate = buttonPrimaryPredicate.refine(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
const buttonPrimaryRefinedPredicate = buttonPrimaryPredicate.refine(
|
|
34
|
+
(data) => data.emoji !== undefined || data.label !== undefined,
|
|
35
|
+
{
|
|
36
|
+
message: 'Buttons with a custom id must have either an emoji or a label.',
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
const buttonSecondaryRefinedPredicate = buttonSecondaryPredicate.refine(
|
|
40
|
+
(data) => data.emoji !== undefined || data.label !== undefined,
|
|
41
|
+
{
|
|
42
|
+
message: 'Buttons with a custom id must have either an emoji or a label.',
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
const buttonSuccessRefinedPredicate = buttonSuccessPredicate.refine(
|
|
46
|
+
(data) => data.emoji !== undefined || data.label !== undefined,
|
|
47
|
+
{
|
|
48
|
+
message: 'Buttons with a custom id must have either an emoji or a label.',
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
const buttonDangerRefinedPredicate = buttonDangerPredicate.refine(
|
|
52
|
+
(data) => data.emoji !== undefined || data.label !== undefined,
|
|
53
|
+
{
|
|
54
|
+
message: 'Buttons with a custom id must have either an emoji or a label.',
|
|
55
|
+
},
|
|
56
|
+
);
|
|
48
57
|
|
|
49
58
|
const buttonLinkPredicate = buttonPredicateBase
|
|
50
59
|
.extend({
|
|
51
60
|
style: z.literal(ButtonStyle.Link),
|
|
52
|
-
url: z
|
|
61
|
+
url: z
|
|
62
|
+
.string()
|
|
63
|
+
.url()
|
|
64
|
+
.max(512)
|
|
65
|
+
.refine((url) => url.startsWith('http:') || url.startsWith('https:') || url.startsWith('discord:'), {
|
|
66
|
+
message: 'URL must use http, https, or discord protocol',
|
|
67
|
+
}),
|
|
53
68
|
emoji: emojiPredicate.optional(),
|
|
54
69
|
label: buttonLabelPredicate.optional(),
|
|
55
70
|
})
|
|
@@ -140,11 +155,7 @@ export const selectMenuStringPredicate = selectMenuBasePredicate
|
|
|
140
155
|
addIssue('min_values', value.min_values);
|
|
141
156
|
}
|
|
142
157
|
|
|
143
|
-
if (
|
|
144
|
-
value.min_values !== undefined &&
|
|
145
|
-
value.max_values !== undefined &&
|
|
146
|
-
value.min_values > value.max_values
|
|
147
|
-
) {
|
|
158
|
+
if (value.min_values !== undefined && value.max_values !== undefined && value.min_values > value.max_values) {
|
|
148
159
|
ctx.addIssue({
|
|
149
160
|
code: z.ZodIssueCode.too_big,
|
|
150
161
|
message: `The maximum amount of options must be greater than or equal to the minimum amount of options`,
|
|
@@ -10,9 +10,9 @@ export interface ComponentBuilderBaseData {
|
|
|
10
10
|
*
|
|
11
11
|
* @typeParam Component - The type of API data that is stored within the builder
|
|
12
12
|
*/
|
|
13
|
-
export abstract class ComponentBuilder<
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
export abstract class ComponentBuilder<Component extends APIBaseComponent<ComponentType>>
|
|
14
|
+
implements JSONEncodable<Component>
|
|
15
|
+
{
|
|
16
16
|
/**
|
|
17
17
|
* @internal
|
|
18
18
|
*/
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
APIActionRowComponent,
|
|
2
3
|
APIBaseComponent,
|
|
3
4
|
APIButtonComponent,
|
|
5
|
+
APIChannelSelectComponent,
|
|
6
|
+
APIComponentInActionRow,
|
|
7
|
+
APIMentionableSelectComponent,
|
|
4
8
|
APIMessageComponent,
|
|
5
9
|
APIModalComponent,
|
|
10
|
+
APIRoleSelectComponent,
|
|
6
11
|
APISectionAccessoryComponent,
|
|
12
|
+
APIStringSelectComponent,
|
|
13
|
+
APITextInputComponent,
|
|
14
|
+
APIUserSelectComponent,
|
|
7
15
|
} from 'discord-api-types/v10';
|
|
8
16
|
import { ButtonStyle, ComponentType } from 'discord-api-types/v10';
|
|
9
17
|
import { ActionRowBuilder } from './ActionRow.js';
|
|
10
|
-
import {
|
|
18
|
+
import { ButtonBuilder } from './button/ButtonBuilder.js';
|
|
11
19
|
import {
|
|
12
20
|
DangerButtonBuilder,
|
|
13
21
|
PrimaryButtonBuilder,
|
|
14
22
|
SecondaryButtonBuilder,
|
|
15
23
|
SuccessButtonBuilder,
|
|
16
24
|
} from './button/CustomIdButton.js';
|
|
17
|
-
import {
|
|
25
|
+
import { ComponentBuilder } from './Component.js';
|
|
18
26
|
export { ButtonBuilder };
|
|
27
|
+
|
|
19
28
|
import { LinkButtonBuilder } from './button/LinkButton.js';
|
|
20
29
|
import { PremiumButtonBuilder } from './button/PremiumButton.js';
|
|
21
30
|
import { FileUploadBuilder } from './fileUpload/FileUpload.js';
|
|
@@ -178,7 +187,6 @@ export interface MappedComponentTypes {
|
|
|
178
187
|
* @param data - The API data to transform to a component class
|
|
179
188
|
*/
|
|
180
189
|
export function createComponentBuilder<ComponentType extends keyof MappedComponentTypes>(
|
|
181
|
-
|
|
182
190
|
data: (APIModalComponent | APIMessageComponent) & { type: ComponentType },
|
|
183
191
|
): MappedComponentTypes[ComponentType];
|
|
184
192
|
|
|
@@ -196,45 +204,45 @@ export function createComponentBuilder(
|
|
|
196
204
|
data: APIMessageComponent | APIModalComponent | MessageComponentBuilder,
|
|
197
205
|
): ComponentBuilder<APIBaseComponent<ComponentType>> {
|
|
198
206
|
if (data instanceof ComponentBuilder || (typeof data === 'object' && data !== null && 'toJSON' in data)) {
|
|
199
|
-
return data as
|
|
207
|
+
return data as unknown as ComponentBuilder<APIBaseComponent<ComponentType>>;
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
const rawData = data as APIMessageComponent | APIModalComponent;
|
|
203
211
|
switch (rawData.type) {
|
|
204
212
|
case ComponentType.ActionRow:
|
|
205
|
-
return new ActionRowBuilder(rawData as
|
|
213
|
+
return new ActionRowBuilder(rawData as APIActionRowComponent<APIComponentInActionRow>);
|
|
206
214
|
case ComponentType.Button:
|
|
207
|
-
return createButtonBuilder(rawData as
|
|
215
|
+
return createButtonBuilder(rawData as APIButtonComponent) as unknown as MessageComponentBuilder;
|
|
208
216
|
case ComponentType.StringSelect:
|
|
209
|
-
return new StringSelectMenuBuilder(rawData as
|
|
217
|
+
return new StringSelectMenuBuilder(rawData as APIStringSelectComponent);
|
|
210
218
|
case ComponentType.TextInput:
|
|
211
|
-
return new TextInputBuilder(rawData as
|
|
219
|
+
return new TextInputBuilder(rawData as APITextInputComponent);
|
|
212
220
|
case ComponentType.UserSelect:
|
|
213
|
-
return new UserSelectMenuBuilder(rawData as
|
|
221
|
+
return new UserSelectMenuBuilder(rawData as APIUserSelectComponent);
|
|
214
222
|
case ComponentType.RoleSelect:
|
|
215
|
-
return new RoleSelectMenuBuilder(rawData as
|
|
223
|
+
return new RoleSelectMenuBuilder(rawData as APIRoleSelectComponent);
|
|
216
224
|
case ComponentType.MentionableSelect:
|
|
217
|
-
return new MentionableSelectMenuBuilder(rawData as
|
|
225
|
+
return new MentionableSelectMenuBuilder(rawData as APIMentionableSelectComponent);
|
|
218
226
|
case ComponentType.ChannelSelect:
|
|
219
|
-
return new ChannelSelectMenuBuilder(rawData as
|
|
227
|
+
return new ChannelSelectMenuBuilder(rawData as APIChannelSelectComponent);
|
|
220
228
|
case ComponentType.Thumbnail:
|
|
221
|
-
return new ThumbnailBuilder(rawData as
|
|
229
|
+
return new ThumbnailBuilder(rawData as unknown);
|
|
222
230
|
case ComponentType.File:
|
|
223
|
-
return new FileBuilder(rawData as
|
|
231
|
+
return new FileBuilder(rawData as unknown);
|
|
224
232
|
case ComponentType.Separator:
|
|
225
|
-
return new SeparatorBuilder(rawData as
|
|
233
|
+
return new SeparatorBuilder(rawData as unknown);
|
|
226
234
|
case ComponentType.TextDisplay:
|
|
227
|
-
return new TextDisplayBuilder(rawData as
|
|
235
|
+
return new TextDisplayBuilder(rawData as unknown);
|
|
228
236
|
case ComponentType.MediaGallery:
|
|
229
|
-
return new MediaGalleryBuilder(rawData as
|
|
237
|
+
return new MediaGalleryBuilder(rawData as unknown);
|
|
230
238
|
case ComponentType.Section:
|
|
231
|
-
return new SectionBuilder(rawData as
|
|
239
|
+
return new SectionBuilder(rawData as unknown);
|
|
232
240
|
case ComponentType.Container:
|
|
233
|
-
return new ContainerBuilder(rawData as
|
|
241
|
+
return new ContainerBuilder(rawData as unknown);
|
|
234
242
|
case ComponentType.Label:
|
|
235
|
-
return new LabelBuilder(rawData as
|
|
243
|
+
return new LabelBuilder(rawData as unknown);
|
|
236
244
|
case ComponentType.FileUpload:
|
|
237
|
-
return new FileUploadBuilder(rawData as
|
|
245
|
+
return new FileUploadBuilder(rawData as unknown);
|
|
238
246
|
default:
|
|
239
247
|
// This case can still occur if we get a newer unsupported component type
|
|
240
248
|
throw new Error(`Cannot properly serialize component type: ${rawData.type}`);
|
|
@@ -244,17 +252,17 @@ export function createComponentBuilder(
|
|
|
244
252
|
function createButtonBuilder(data: APIButtonComponent): ButtonBuilder {
|
|
245
253
|
switch (data.style) {
|
|
246
254
|
case ButtonStyle.Primary:
|
|
247
|
-
return new PrimaryButtonBuilder(data) as
|
|
255
|
+
return new PrimaryButtonBuilder(data) as unknown as ButtonBuilder;
|
|
248
256
|
case ButtonStyle.Secondary:
|
|
249
|
-
return new SecondaryButtonBuilder(data) as
|
|
257
|
+
return new SecondaryButtonBuilder(data) as unknown as ButtonBuilder;
|
|
250
258
|
case ButtonStyle.Success:
|
|
251
|
-
return new SuccessButtonBuilder(data) as
|
|
259
|
+
return new SuccessButtonBuilder(data) as unknown as ButtonBuilder;
|
|
252
260
|
case ButtonStyle.Danger:
|
|
253
|
-
return new DangerButtonBuilder(data) as
|
|
261
|
+
return new DangerButtonBuilder(data) as unknown as ButtonBuilder;
|
|
254
262
|
case ButtonStyle.Link:
|
|
255
|
-
return new LinkButtonBuilder(data) as
|
|
263
|
+
return new LinkButtonBuilder(data) as unknown as ButtonBuilder;
|
|
256
264
|
case ButtonStyle.Premium:
|
|
257
|
-
return new PremiumButtonBuilder(data) as
|
|
265
|
+
return new PremiumButtonBuilder(data) as unknown as ButtonBuilder;
|
|
258
266
|
default:
|
|
259
267
|
// @ts-expect-error This case can still occur if we get a newer unsupported button style
|
|
260
268
|
throw new Error(`Cannot properly serialize button with style: ${data.style}`);
|
|
@@ -10,7 +10,7 @@ export abstract class BaseButtonBuilder<ButtonData extends APIButtonComponent> e
|
|
|
10
10
|
/**
|
|
11
11
|
* @internal
|
|
12
12
|
*/
|
|
13
|
-
declare
|
|
13
|
+
protected declare readonly data: Partial<ButtonData>;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Sets whether this button is disabled.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type APIButtonComponent, type ButtonStyle, ComponentType } from 'discord-api-types/v10';
|
|
2
2
|
import { Mixin } from 'ts-mixer';
|
|
3
3
|
import { BaseButtonBuilder } from './Button.js';
|
|
4
4
|
import { EmojiOrLabelButtonMixin } from './mixins/EmojiOrLabelButtonMixin.js';
|
|
@@ -9,9 +9,10 @@ import { EmojiOrLabelButtonMixin } from './mixins/EmojiOrLabelButtonMixin.js';
|
|
|
9
9
|
* @mixes {@link BaseButtonBuilder}\<{@link discord-api-types/v10#(APIButtonComponent:interface)}\>
|
|
10
10
|
* @mixes {@link EmojiOrLabelButtonMixin}
|
|
11
11
|
*/
|
|
12
|
-
// @ts-
|
|
12
|
+
// @ts-expect-error - Structural mismatch from ts-mixer
|
|
13
13
|
export interface ButtonBuilder extends BaseButtonBuilder<APIButtonComponent>, EmojiOrLabelButtonMixin {}
|
|
14
14
|
|
|
15
|
+
// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: Standard event typing pattern
|
|
15
16
|
export class ButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponent>, EmojiOrLabelButtonMixin) {
|
|
16
17
|
/**
|
|
17
18
|
* @internal
|
|
@@ -34,7 +35,7 @@ export class ButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponent>,
|
|
|
34
35
|
* @param customId - The custom id to use
|
|
35
36
|
*/
|
|
36
37
|
public setCustomId(customId: string) {
|
|
37
|
-
(this.data as
|
|
38
|
+
(this.data as Record<string, unknown>).custom_id = customId;
|
|
38
39
|
return this;
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -44,7 +45,7 @@ export class ButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponent>,
|
|
|
44
45
|
* @param style - The style to use
|
|
45
46
|
*/
|
|
46
47
|
public setStyle(style: ButtonStyle) {
|
|
47
|
-
(this.data as
|
|
48
|
+
(this.data as Record<string, unknown>).style = style;
|
|
48
49
|
return this;
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -54,7 +55,7 @@ export class ButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponent>,
|
|
|
54
55
|
* @param url - The URL to use
|
|
55
56
|
*/
|
|
56
57
|
public setURL(url: string) {
|
|
57
|
-
(this.data as
|
|
58
|
+
(this.data as Record<string, unknown>).url = url;
|
|
58
59
|
return this;
|
|
59
60
|
}
|
|
60
61
|
|
|
@@ -64,7 +65,7 @@ export class ButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponent>,
|
|
|
64
65
|
* @param skuId - The SKU id to use
|
|
65
66
|
*/
|
|
66
67
|
public setSKUId(skuId: string) {
|
|
67
|
-
(this.data as
|
|
68
|
+
(this.data as Record<string, unknown>).sku_id = skuId;
|
|
68
69
|
return this;
|
|
69
70
|
}
|
|
70
71
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ButtonStyle, ComponentType
|
|
1
|
+
import { type APIButtonComponentWithCustomId, ButtonStyle, ComponentType } from 'discord-api-types/v10';
|
|
2
2
|
import { Mixin } from 'ts-mixer';
|
|
3
3
|
import { BaseButtonBuilder } from './Button.js';
|
|
4
4
|
import { EmojiOrLabelButtonMixin } from './mixins/EmojiOrLabelButtonMixin.js';
|
|
@@ -11,7 +11,9 @@ export type CustomIdButtonStyle = APIButtonComponentWithCustomId['style'];
|
|
|
11
11
|
* @mixes {@link BaseButtonBuilder}\<{@link discord-api-types/v10#(APIButtonComponentWithCustomId:interface)}\>
|
|
12
12
|
* @mixes {@link EmojiOrLabelButtonMixin}
|
|
13
13
|
*/
|
|
14
|
-
export interface CustomIdButtonBuilder
|
|
14
|
+
export interface CustomIdButtonBuilder
|
|
15
|
+
extends BaseButtonBuilder<APIButtonComponentWithCustomId>,
|
|
16
|
+
EmojiOrLabelButtonMixin {}
|
|
15
17
|
|
|
16
18
|
export abstract class CustomIdButtonBuilder extends Mixin(
|
|
17
19
|
BaseButtonBuilder<APIButtonComponentWithCustomId>,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ButtonStyle,
|
|
3
|
-
ComponentType,
|
|
4
2
|
type APIButtonComponent,
|
|
5
3
|
type APIButtonComponentWithURL,
|
|
4
|
+
ButtonStyle,
|
|
5
|
+
ComponentType,
|
|
6
6
|
} from 'discord-api-types/v10';
|
|
7
7
|
import { Mixin } from 'ts-mixer';
|
|
8
8
|
import { BaseButtonBuilder } from './Button.js';
|
|
@@ -16,6 +16,7 @@ import { EmojiOrLabelButtonMixin } from './mixins/EmojiOrLabelButtonMixin.js';
|
|
|
16
16
|
*/
|
|
17
17
|
export interface LinkButtonBuilder extends BaseButtonBuilder<APIButtonComponentWithURL>, EmojiOrLabelButtonMixin {}
|
|
18
18
|
|
|
19
|
+
// biome-ignore lint/suspicious/noUnsafeDeclarationMerging: Standard event typing pattern
|
|
19
20
|
export class LinkButtonBuilder extends Mixin(BaseButtonBuilder<APIButtonComponentWithURL>, EmojiOrLabelButtonMixin) {
|
|
20
21
|
protected override readonly data: Partial<APIButtonComponentWithURL>;
|
|
21
22
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { APIButtonComponent, APIButtonComponentWithSKUId, APIMessageComponentEmoji } from 'discord-api-types/v10';
|
|
2
2
|
import { parseEmoji } from '../../../util/componentUtil.js';
|
|
3
3
|
|
|
4
|
-
export interface EmojiOrLabelButtonData
|
|
5
|
-
Exclude<APIButtonComponent, APIButtonComponentWithSKUId>,
|
|
6
|
-
'emoji' | 'label'
|
|
7
|
-
> {}
|
|
4
|
+
export interface EmojiOrLabelButtonData
|
|
5
|
+
extends Pick<Exclude<APIButtonComponent, APIButtonComponentWithSKUId>, 'emoji' | 'label'> {}
|
|
8
6
|
|
|
9
7
|
/**
|
|
10
8
|
* A mixin that adds emoji and label symbols to a button builder.
|
|
@@ -13,7 +11,7 @@ export class EmojiOrLabelButtonMixin {
|
|
|
13
11
|
/**
|
|
14
12
|
* @internal
|
|
15
13
|
*/
|
|
16
|
-
declare
|
|
14
|
+
protected declare readonly data: EmojiOrLabelButtonData;
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* Sets the emoji to display on this button.
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
APIFileUploadComponent,
|
|
4
4
|
APILabelComponent,
|
|
5
5
|
APIMentionableSelectComponent,
|
|
6
|
+
APIMessageComponent,
|
|
6
7
|
APIRoleSelectComponent,
|
|
7
8
|
APIStringSelectComponent,
|
|
8
9
|
APITextInputComponent,
|
|
@@ -70,7 +71,9 @@ export class LabelBuilder extends ComponentBuilder<APILabelComponent> {
|
|
|
70
71
|
|
|
71
72
|
this.data = {
|
|
72
73
|
...structuredClone(rest),
|
|
73
|
-
component: component
|
|
74
|
+
component: component
|
|
75
|
+
? (createComponentBuilder(component as APIMessageComponent) as LabelBuilderData['component'])
|
|
76
|
+
: undefined,
|
|
74
77
|
type: ComponentType.Label,
|
|
75
78
|
};
|
|
76
79
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type APIChannelSelectComponent,
|
|
3
3
|
type ChannelType,
|
|
4
|
-
type Snowflake,
|
|
5
4
|
ComponentType,
|
|
6
5
|
SelectMenuDefaultValueType,
|
|
6
|
+
type Snowflake,
|
|
7
7
|
} from 'discord-api-types/v10';
|
|
8
|
-
import { type RestOrArray
|
|
8
|
+
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
9
9
|
import { validate } from '../../util/validation.js';
|
|
10
10
|
import { selectMenuChannelPredicate } from '../Assertions.js';
|
|
11
11
|
import { BaseSelectMenuBuilder } from './BaseSelectMenu.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type APIMentionableSelectComponent,
|
|
3
3
|
type APISelectMenuDefaultValue,
|
|
4
|
-
type Snowflake,
|
|
5
4
|
ComponentType,
|
|
6
5
|
SelectMenuDefaultValueType,
|
|
6
|
+
type Snowflake,
|
|
7
7
|
} from 'discord-api-types/v10';
|
|
8
|
-
import { type RestOrArray
|
|
8
|
+
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
9
9
|
import { validate } from '../../util/validation.js';
|
|
10
10
|
import { selectMenuMentionablePredicate } from '../Assertions.js';
|
|
11
11
|
import { BaseSelectMenuBuilder } from './BaseSelectMenu.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type APIRoleSelectComponent,
|
|
3
|
-
type Snowflake,
|
|
4
3
|
ComponentType,
|
|
5
4
|
SelectMenuDefaultValueType,
|
|
5
|
+
type Snowflake,
|
|
6
6
|
} from 'discord-api-types/v10';
|
|
7
|
-
import { type RestOrArray
|
|
7
|
+
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
8
8
|
import { validate } from '../../util/validation.js';
|
|
9
9
|
import { selectMenuRolePredicate } from '../Assertions.js';
|
|
10
10
|
import { BaseSelectMenuBuilder } from './BaseSelectMenu.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { APISelectMenuOption, APIStringSelectComponent } from 'discord-api-types/v10';
|
|
1
2
|
import { ComponentType } from 'discord-api-types/v10';
|
|
2
|
-
import type { APIStringSelectComponent, APISelectMenuOption } from 'discord-api-types/v10';
|
|
3
3
|
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
4
4
|
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
|
5
5
|
import { validate } from '../../util/validation.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type APIUserSelectComponent,
|
|
3
|
-
type Snowflake,
|
|
4
3
|
ComponentType,
|
|
5
4
|
SelectMenuDefaultValueType,
|
|
5
|
+
type Snowflake,
|
|
6
6
|
} from 'discord-api-types/v10';
|
|
7
|
-
import { type RestOrArray
|
|
7
|
+
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
8
8
|
import { validate } from '../../util/validation.js';
|
|
9
9
|
import { selectMenuUserPredicate } from '../Assertions.js';
|
|
10
10
|
import { BaseSelectMenuBuilder } from './BaseSelectMenu.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, type TextInputStyle
|
|
1
|
+
import { type APITextInputComponent, ComponentType, type TextInputStyle } from 'discord-api-types/v10';
|
|
2
2
|
import { validate } from '../../util/validation.js';
|
|
3
3
|
import { ComponentBuilder } from '../Component.js';
|
|
4
4
|
import { textInputPredicate } from './Assertions.js';
|
|
@@ -4,7 +4,12 @@ import { idPredicate } from '../../Assertions.js';
|
|
|
4
4
|
import { actionRowPredicate, buttonPredicate } from '../Assertions.js';
|
|
5
5
|
|
|
6
6
|
const unfurledMediaItemPredicate = z.object({
|
|
7
|
-
url: z
|
|
7
|
+
url: z
|
|
8
|
+
.string()
|
|
9
|
+
.url()
|
|
10
|
+
.refine((url) => url.startsWith('http:') || url.startsWith('https:') || url.startsWith('attachment:'), {
|
|
11
|
+
message: 'URL must use http, https, or attachment protocol',
|
|
12
|
+
}),
|
|
8
13
|
});
|
|
9
14
|
|
|
10
15
|
export const thumbnailPredicate = z.object({
|
|
@@ -16,7 +21,10 @@ export const thumbnailPredicate = z.object({
|
|
|
16
21
|
});
|
|
17
22
|
|
|
18
23
|
const unfurledMediaItemAttachmentOnlyPredicate = z.object({
|
|
19
|
-
url: z
|
|
24
|
+
url: z
|
|
25
|
+
.string()
|
|
26
|
+
.url()
|
|
27
|
+
.refine((url) => url.startsWith('attachment:'), { message: 'URL must use attachment protocol' }),
|
|
20
28
|
});
|
|
21
29
|
|
|
22
30
|
export const filePredicate = z.object({
|
|
@@ -56,10 +64,7 @@ export const sectionPredicate = z.object({
|
|
|
56
64
|
type: z.literal(ComponentType.Section),
|
|
57
65
|
id: idPredicate,
|
|
58
66
|
components: z.array(textDisplayPredicate).min(1).max(3),
|
|
59
|
-
accessory: z.union([
|
|
60
|
-
buttonPredicate,
|
|
61
|
-
thumbnailPredicate,
|
|
62
|
-
]),
|
|
67
|
+
accessory: z.union([buttonPredicate, thumbnailPredicate]),
|
|
63
68
|
});
|
|
64
69
|
|
|
65
70
|
export const containerPredicate = z.object({
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type APIComponentInMessageActionRow,
|
|
3
|
-
type APISeparatorComponent,
|
|
4
2
|
type APIActionRowComponent,
|
|
5
|
-
type
|
|
6
|
-
type APITextDisplayComponent,
|
|
7
|
-
type APIContainerComponent,
|
|
3
|
+
type APIComponentInActionRow,
|
|
8
4
|
type APIComponentInContainer,
|
|
5
|
+
type APIComponentInMessageActionRow,
|
|
6
|
+
type APIContainerComponent,
|
|
7
|
+
type APIFileComponent,
|
|
9
8
|
type APIMediaGalleryComponent,
|
|
10
9
|
type APISectionComponent,
|
|
11
|
-
type
|
|
10
|
+
type APISeparatorComponent,
|
|
11
|
+
type APITextDisplayComponent,
|
|
12
12
|
ComponentType,
|
|
13
13
|
} from 'discord-api-types/v10';
|
|
14
14
|
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray';
|
|
@@ -110,7 +110,12 @@ export class ContainerBuilder extends ComponentBuilder<APIContainerComponent> {
|
|
|
110
110
|
>
|
|
111
111
|
): this {
|
|
112
112
|
const normalized = normalizeArray(input);
|
|
113
|
-
const resolved = normalized.map((component) =>
|
|
113
|
+
const resolved = normalized.map((component) =>
|
|
114
|
+
resolveBuilder<ActionRowBuilder, Partial<APIActionRowComponent<APIComponentInActionRow>>>(
|
|
115
|
+
component,
|
|
116
|
+
ActionRowBuilder,
|
|
117
|
+
),
|
|
118
|
+
);
|
|
114
119
|
|
|
115
120
|
this.data.components.push(...resolved);
|
|
116
121
|
return this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type APIFileComponent, ComponentType } from 'discord-api-types/v10';
|
|
2
2
|
import { validate } from '../../util/validation.js';
|
|
3
3
|
import { ComponentBuilder } from '../Component.js';
|
|
4
4
|
import { filePredicate } from './Assertions.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type APIMediaGalleryComponent, type APIMediaGalleryItem, ComponentType } from 'discord-api-types/v10';
|
|
2
2
|
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray.js';
|
|
3
3
|
import { resolveBuilder } from '../../util/resolveBuilder.js';
|
|
4
4
|
import { validate } from '../../util/validation.js';
|