@ovencord/builders 1.11.7 → 1.11.8
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 +1 -1
- package/src/components/v2/Assertions.ts +3 -3
- package/src/components/v2/Container.ts +3 -2
- package/src/components/v2/Section.ts +18 -7
- package/src/components/v2/TextDisplay.ts +9 -2
- package/src/components/v2/Thumbnail.ts +12 -2
- package/src/messages/Message.ts +2 -1
- package/src/util/resolveBuilder.ts +5 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ComponentType, SeparatorSpacingSize } from 'discord-api-types/v10';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { idPredicate } from '../../Assertions.js';
|
|
4
|
-
import { actionRowPredicate } from '../Assertions.js';
|
|
4
|
+
import { actionRowPredicate, buttonPredicate } from '../Assertions.js';
|
|
5
5
|
|
|
6
6
|
const unfurledMediaItemPredicate = z.object({
|
|
7
7
|
url: z.string().url().refine((url) => url.startsWith('http:') || url.startsWith('https:') || url.startsWith('attachment:'), { message: 'URL must use http, https, or attachment protocol' }),
|
|
@@ -57,8 +57,8 @@ export const sectionPredicate = z.object({
|
|
|
57
57
|
id: idPredicate,
|
|
58
58
|
components: z.array(textDisplayPredicate).min(1).max(3),
|
|
59
59
|
accessory: z.union([
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
buttonPredicate,
|
|
61
|
+
thumbnailPredicate,
|
|
62
62
|
]),
|
|
63
63
|
});
|
|
64
64
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type APIComponentInContainer,
|
|
9
9
|
type APIMediaGalleryComponent,
|
|
10
10
|
type APISectionComponent,
|
|
11
|
+
type APIComponentInActionRow,
|
|
11
12
|
ComponentType,
|
|
12
13
|
} from 'discord-api-types/v10';
|
|
13
14
|
import { normalizeArray, type RestOrArray } from '../../util/normalizeArray';
|
|
@@ -19,7 +20,7 @@ import { createComponentBuilder } from '../Components';
|
|
|
19
20
|
import { containerPredicate } from './Assertions';
|
|
20
21
|
import { FileBuilder } from './File.js';
|
|
21
22
|
import { MediaGalleryBuilder } from './MediaGallery';
|
|
22
|
-
import { SectionBuilder } from './Section';
|
|
23
|
+
import { SectionBuilder } from './Section.js';
|
|
23
24
|
import { SeparatorBuilder } from './Separator.js';
|
|
24
25
|
import { TextDisplayBuilder } from './TextDisplay';
|
|
25
26
|
|
|
@@ -109,7 +110,7 @@ export class ContainerBuilder extends ComponentBuilder<APIContainerComponent> {
|
|
|
109
110
|
>
|
|
110
111
|
): this {
|
|
111
112
|
const normalized = normalizeArray(input);
|
|
112
|
-
const resolved = normalized.map((component) => resolveBuilder(component, ActionRowBuilder));
|
|
113
|
+
const resolved = normalized.map((component) => resolveBuilder<ActionRowBuilder, Partial<APIActionRowComponent<APIComponentInActionRow>>>(component, ActionRowBuilder));
|
|
113
114
|
|
|
114
115
|
this.data.components.push(...resolved);
|
|
115
116
|
return this;
|
|
@@ -94,6 +94,7 @@ export class SectionBuilder extends ComponentBuilder<APISectionComponent> {
|
|
|
94
94
|
public constructor(data: Partial<APISectionComponent> = {}) {
|
|
95
95
|
super();
|
|
96
96
|
|
|
97
|
+
|
|
97
98
|
const { components = [], accessory, ...rest } = data;
|
|
98
99
|
|
|
99
100
|
this.data = {
|
|
@@ -255,23 +256,33 @@ export class SectionBuilder extends ComponentBuilder<APISectionComponent> {
|
|
|
255
256
|
return this;
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
/**
|
|
260
|
+
* {@inheritDoc ComponentBuilder.toJSON}
|
|
261
|
+
*/
|
|
258
262
|
/**
|
|
259
263
|
* {@inheritDoc ComponentBuilder.toJSON}
|
|
260
264
|
*/
|
|
261
265
|
public override toJSON(validationOverride?: boolean): APISectionComponent {
|
|
262
266
|
const { components, accessory, ...rest } = this.data;
|
|
263
267
|
|
|
268
|
+
// Resolve accessory if it exists
|
|
269
|
+
const accessoryData = accessory
|
|
270
|
+
? (accessory as any).toJSON
|
|
271
|
+
? (accessory as any).toJSON(validationOverride)
|
|
272
|
+
: accessory
|
|
273
|
+
: undefined;
|
|
274
|
+
|
|
264
275
|
const data = {
|
|
265
276
|
...structuredClone(rest),
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
277
|
+
type: ComponentType.Section,
|
|
278
|
+
components: components.map((component) => component.toJSON(validationOverride)),
|
|
279
|
+
accessory: accessoryData,
|
|
280
|
+
} as APISectionComponent;
|
|
281
|
+
|
|
282
|
+
|
|
269
283
|
|
|
270
284
|
validate(sectionPredicate, data, validationOverride);
|
|
271
|
-
|
|
272
|
-
// DEBUG LOGGING
|
|
273
|
-
console.log('[SectionBuilder] toJSON Payload:', JSON.stringify(data, null, 2));
|
|
274
285
|
|
|
275
|
-
return data
|
|
286
|
+
return data;
|
|
276
287
|
}
|
|
277
288
|
}
|
|
@@ -56,8 +56,15 @@ export class TextDisplayBuilder extends ComponentBuilder<APITextDisplayComponent
|
|
|
56
56
|
*/
|
|
57
57
|
public override toJSON(validationOverride?: boolean): APITextDisplayComponent {
|
|
58
58
|
const clone = structuredClone(this.data);
|
|
59
|
-
|
|
59
|
+
|
|
60
|
+
// Enforce only type and content are present
|
|
61
|
+
const data: APITextDisplayComponent = {
|
|
62
|
+
type: ComponentType.TextDisplay,
|
|
63
|
+
content: clone.content!,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
validate(textDisplayPredicate, data, validationOverride);
|
|
60
67
|
|
|
61
|
-
return
|
|
68
|
+
return data;
|
|
62
69
|
}
|
|
63
70
|
}
|
|
@@ -93,8 +93,18 @@ export class ThumbnailBuilder extends ComponentBuilder<APIThumbnailComponent> {
|
|
|
93
93
|
*/
|
|
94
94
|
public override toJSON(validationOverride?: boolean): APIThumbnailComponent {
|
|
95
95
|
const clone = structuredClone(this.data);
|
|
96
|
-
validate(thumbnailPredicate, clone, validationOverride);
|
|
97
96
|
|
|
98
|
-
|
|
97
|
+
// Enforce Type 11 structure: { type: 11, media: { url: ... } }
|
|
98
|
+
// We ignore description and spoiler for now as per V2 accessory specs
|
|
99
|
+
const data: APIThumbnailComponent = {
|
|
100
|
+
type: ComponentType.Thumbnail,
|
|
101
|
+
media: {
|
|
102
|
+
url: clone.media!.url,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
validate(thumbnailPredicate, data, validationOverride);
|
|
107
|
+
|
|
108
|
+
return data;
|
|
99
109
|
}
|
|
100
110
|
}
|
package/src/messages/Message.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
APISeparatorComponent,
|
|
18
18
|
APITextDisplayComponent,
|
|
19
19
|
APIMessageTopLevelComponent,
|
|
20
|
+
APIComponentInActionRow,
|
|
20
21
|
} from 'discord-api-types/v10';
|
|
21
22
|
import { ActionRowBuilder } from '../components/ActionRow.js';
|
|
22
23
|
import { ComponentBuilder } from '../components/Component.js';
|
|
@@ -310,7 +311,7 @@ export class MessageBuilder
|
|
|
310
311
|
): this {
|
|
311
312
|
this.data.components ??= [];
|
|
312
313
|
|
|
313
|
-
const resolved = normalizeArray(components).map((component) => resolveBuilder(component, ActionRowBuilder));
|
|
314
|
+
const resolved = normalizeArray(components).map((component) => resolveBuilder<ActionRowBuilder, Partial<APIActionRowComponent<APIComponentInActionRow>>>(component, ActionRowBuilder));
|
|
314
315
|
this.data.components.push(...resolved);
|
|
315
316
|
|
|
316
317
|
return this;
|
|
@@ -36,5 +36,9 @@ export function resolveBuilder<Builder extends JSONEncodable<any>, BuilderData e
|
|
|
36
36
|
return builder(new Constructor());
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
if (typeof builder === 'object' && builder !== null && 'toJSON' in builder) {
|
|
40
|
+
return new Constructor((builder as unknown as JSONEncodable<BuilderData>).toJSON());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return new Constructor(builder as BuilderData);
|
|
40
44
|
}
|