@open-discord-bots/framework 0.3.7 → 0.3.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/dist/api/main.js CHANGED
@@ -44,7 +44,7 @@ export class ODMain {
44
44
  constructor(managers, project) {
45
45
  this.project = project;
46
46
  this.versions = managers.versions;
47
- this.versions.add(ODVersion.fromString("opendiscord:api", "v0.3.7"));
47
+ this.versions.add(ODVersion.fromString("opendiscord:api", "v0.3.8"));
48
48
  this.versions.add(ODVersion.fromString("opendiscord:livestatus", "v2.0.0"));
49
49
  this.debugfile = managers.debugfile;
50
50
  this.console = managers.console;
@@ -614,6 +614,8 @@ export declare class ODMessageInstance {
614
614
  export declare class ODMessage<Origin extends string, Params, WorkerIds extends string = string> extends ODBuilderImplementation<ODMessageInstance, Origin, Params, ODMessageBuildResult, WorkerIds> {
615
615
  /**Build this message & compile it for discord.js */
616
616
  build(origin: Origin, params: Params): Promise<ODMessageBuildResult>;
617
+ /**Duplicate this message. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
618
+ duplicate(newId?: ODValidId): ODMessage<Origin, Params, WorkerIds>;
617
619
  }
618
620
  /**## ODQuickMessage `class`
619
621
  * This is an Open Discord quick message builder.
@@ -1244,6 +1244,14 @@ export class ODMessage extends ODBuilderImplementation {
1244
1244
  this.didCache = true;
1245
1245
  return result;
1246
1246
  }
1247
+ /**Duplicate this message. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
1248
+ duplicate(newId) {
1249
+ const newMessage = new ODMessage(newId ?? this.id.value);
1250
+ for (const worker of this.workers.getAll()) {
1251
+ newMessage.workers.add(worker.duplicate());
1252
+ }
1253
+ return newMessage;
1254
+ }
1247
1255
  }
1248
1256
  /**## ODQuickMessage `class`
1249
1257
  * This is an Open Discord quick message builder.
@@ -1,7 +1,8 @@
1
1
  import { ODId, ODValidId, ODManagerData, ODNoGeneric, ODManager, ODValidButtonColor, ODInterfaceWithPartialProperty } from "./base.js";
2
2
  import * as discord from "discord.js";
3
- import { ODWorkerManager, ODWorkerCallback } from "./worker.js";
3
+ import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker.js";
4
4
  import { ODDebugger } from "./console.js";
5
+ import { ODMessage, ODMessageInstance } from "./builder.js";
5
6
  /**## ODComponentFactoryInstance `class`
6
7
  * An Open Discord component factory instance.
7
8
  *
@@ -28,6 +29,8 @@ export declare class ODComponentFactory<Component extends ODComponent<object, an
28
29
  constructor(id: ODValidId, callback?: ODWorkerCallback<ODComponentFactoryInstance<Component>, Origin, Params>, priority?: number, callbackId?: ODValidId);
29
30
  /**Run all workers and return the resulting component. */
30
31
  build(origin: Origin, params: Params): Promise<ODComponentInferBuildResult<Component>>;
32
+ /**Duplicate this component factory. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
33
+ duplicate(newId?: ODValidId): ODComponentFactory<Component, Origin, Params, WorkerIds>;
31
34
  }
32
35
  /**## ODComponentManagerIdConstraint `type`
33
36
  * The constraint/layout for id mappings/interfaces of the `ODComponentManager` class.
@@ -54,6 +57,26 @@ export declare class ODBaseComponentManager<IdList extends ODComponentManagerIdC
54
57
  exists(id: keyof ODNoGeneric<IdList>): boolean;
55
58
  exists(id: ODValidId): boolean;
56
59
  }
60
+ /**## ODComponentModifierManagerIdConstraint `type`
61
+ * The constraint/layout for id mappings/interfaces of the `ODComponentModifierManager` class.
62
+ */
63
+ export type ODComponentModifierManagerIdConstraint = Record<string, ODMessageComponentModifier<string, {}>>;
64
+ /**## ODComponentModifierManager `class`
65
+ * An Open Discord component modifier manager.
66
+ *
67
+ * It contains a collection of all `ODMessageComponentModifier`'s. You can:
68
+ * - Patch, modify, expand or update existing messages
69
+ * - It Does not affect the original message (cloned)
70
+ */
71
+ export declare class ODComponentModifierManager<IdList extends ODComponentModifierManagerIdConstraint = ODComponentModifierManagerIdConstraint> extends ODManager<ODMessageComponentModifier<string, {}>> {
72
+ constructor(debug: ODDebugger);
73
+ get<ModifierId extends keyof ODNoGeneric<IdList>>(id: ModifierId): IdList[ModifierId];
74
+ get(id: ODValidId): ODMessageComponentModifier<string, {}> | null;
75
+ remove<ModifierId extends keyof ODNoGeneric<IdList>>(id: ModifierId): IdList[ModifierId];
76
+ remove(id: ODValidId): ODMessageComponentModifier<string, {}> | null;
77
+ exists(id: keyof ODNoGeneric<IdList>): boolean;
78
+ exists(id: ODValidId): boolean;
79
+ }
57
80
  /**## ODSharedComponentManager `class
58
81
  * A special class with types for shared message/modal `ODComponent`'s.
59
82
  * Create button, dropdown or any other layout component template to use them in messages & modals.
@@ -89,31 +112,67 @@ export declare class ODModalComponentManager<IdList extends ODComponentManagerId
89
112
  * - Get to know the origin of the request (e.g. button, dropdown, modal, ...)
90
113
  * - And so much more!
91
114
  */
92
- export declare class ODComponentManager<SharedIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint, MessageIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint, ModalIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint> {
115
+ export declare class ODComponentManager<SharedIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint, MessageIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint, ModalIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint, ModifierIdList extends ODComponentModifierManagerIdConstraint = ODComponentModifierManagerIdConstraint> {
93
116
  /**The manager for all shared components. */
94
117
  shared: ODSharedComponentManager<SharedIdList>;
95
118
  /**The manager for all messages components. */
96
119
  messages: ODMessageComponentManager<MessageIdList>;
97
120
  /**The manager for all modals components. */
98
121
  modals: ODModalComponentManager<ModalIdList>;
122
+ /**The collection of all component modifiers. */
123
+ modifiers: ODComponentModifierManager<ModifierIdList>;
99
124
  constructor(debug: ODDebugger);
100
125
  }
101
126
  /**## ODComponentInferBuildResult `type`
102
127
  * Infer the build result of a certain component.
103
128
  */
104
129
  export type ODComponentInferBuildResult<Component> = Component extends ODComponent<object, infer BuildResult> ? BuildResult : never;
130
+ /**## ODComponentType `type`
131
+ * The type of an `ODComponent`.
132
+ */
133
+ export type ODComponentType = "message" | "simple-message" | "modal" | "action-row" | "container" | "section" | "label" | "separator" | "text" | "file" | "gallery" | "thumbnail" | "simple-content" | "simple-embed" | "simple-poll" | "button" | "short-input" | "paragraph-input" | "dropdown" | "radio-group" | "checkbox-group" | "checkbox" | "file-upload";
134
+ /**## ODComponentType `type`
135
+ * Get the `ODComponent` class for a specific `ODComponentType`.
136
+ */
137
+ export interface ODComponentForType {
138
+ "message": ODMessageComponent;
139
+ "simple-message": ODSimpleMessageComponent;
140
+ "modal": ODModalComponent;
141
+ "action-row": ODActionRowComponent;
142
+ "container": ODContainerComponent;
143
+ "section": ODSectionComponent;
144
+ "label": ODLabelComponent;
145
+ "separator": ODSeparatorComponent;
146
+ "text": ODTextComponent;
147
+ "file": ODFileComponent;
148
+ "gallery": ODGalleryComponent;
149
+ "thumbnail": ODThumbnailComponent;
150
+ "simple-content": ODContentComponent;
151
+ "simple-embed": ODEmbedComponent;
152
+ "simple-poll": ODPollComponent;
153
+ "button": ODButtonComponent;
154
+ "short-input": ODShortInputComponent;
155
+ "paragraph-input": ODParagraphInputComponent;
156
+ "dropdown": ODDropdownComponent;
157
+ "radio-group": ODRadioGroupComponent;
158
+ "checkbox-group": ODCheckboxGroupComponent;
159
+ "checkbox": ODCheckboxComponent;
160
+ "file-upload": ODFileUploadComponent;
161
+ }
105
162
  /**## ODComponent `class`
106
163
  * An Open Discord message/modal component.
107
164
  *
108
165
  * This class itself doesn't do anything, but is a blueprint for other
109
166
  * `ODComponent` classes which represent the new Discord message/modal components.
110
167
  */
111
- export declare abstract class ODComponent<Data extends object, BuildResult> {
168
+ export declare abstract class ODComponent<Data extends object, BuildResult, Type extends ODComponentType = ODComponentType> {
112
169
  /**The id of this message/modal component. */
113
170
  id: ODId;
114
171
  /**The data or configuration of this message/modal component. */
115
172
  readonly data: Data;
116
- constructor(id: ODValidId, data: Data);
173
+ /**The type of this component. */
174
+ readonly type: Type;
175
+ constructor(id: ODValidId, type: Type, data: Data);
117
176
  /**Build this component. Returns `null` when invalid. */
118
177
  abstract build(): Promise<BuildResult | null> | BuildResult | null;
119
178
  }
@@ -125,7 +184,7 @@ export declare abstract class ODComponent<Data extends object, BuildResult> {
125
184
  */
126
185
  export declare abstract class ODGroupComponent<Data extends object, ChildComponent extends ODComponent<object, any>, BuildResult> extends ODComponent<Data, BuildResult> {
127
186
  /**The collection of child components. */
128
- readonly children: ChildComponent[];
187
+ children: ChildComponent[];
129
188
  /**Add a new component to this group. There are multiple modes available:
130
189
  * - `start`: insert at the start of the list.
131
190
  * - `end`: insert at the end of the list.
@@ -136,14 +195,22 @@ export declare abstract class ODGroupComponent<Data extends object, ChildCompone
136
195
  addComponent(c: ChildComponent, mode: "start" | "end"): void;
137
196
  addComponent(c: ChildComponent, mode: "before" | "after", referenceId: ODValidId): void;
138
197
  addComponent(c: ChildComponent, mode: "index", referenceIndex: number): void;
139
- /**Get a component with a certain ID in this group. Returns `null` if non-existent. */
198
+ /**Get a component with a certain ID in this group. Returns `null` if non-existent. Also able to search for components recursively. */
140
199
  getComponent(id: ODValidId): ChildComponent | null;
200
+ getComponent(id: ODValidId, recursive: true, recursiveLimit?: number): ODComponent<any, any, ODComponentType> | null;
201
+ /**Get all components of a certain type in this group. Also able to search for components recursively. */
202
+ getComponentsOfType<Type extends ODComponentType>(type: Type): ODComponentForType[Type][];
203
+ getComponentsOfType<Type extends ODComponentType>(type: Type, recursive: true, recursiveLimit?: number): ODComponentForType[Type][];
141
204
  /**Get the position of a component with a certain ID in this group. Returns `-1` if non-existent. */
142
205
  getComponentPosition(id: ODValidId): number;
206
+ /**List all child components of this group. */
207
+ listComponent(): ChildComponent[];
143
208
  /**Returns if a component with a certain ID exists in this group. */
144
209
  existsComponent(id: ODValidId): boolean;
145
210
  /**Remove a component with a certain ID from this group. Returns the removed component or `null if non-existent. */
146
211
  removeComponent(id: ODValidId): ChildComponent | null;
212
+ /**Remove all child components from this group. Returns the removed components. */
213
+ clearComponents(): ChildComponent[];
147
214
  /**Moves an existing component to a new location in this group. There are multiple modes available:
148
215
  * - `start`: move to the start of the list.
149
216
  * - `end`: move to the end of the list.
@@ -169,6 +236,22 @@ export declare abstract class ODParentComponent<Data extends object, ChildCompon
169
236
  /**Set the child component of this parent. */
170
237
  setComponent(c: ChildComponent | null): void;
171
238
  }
239
+ /**## ODMessageComponentModifier `class`
240
+ * This is an Open Discord message component modifier.
241
+ *
242
+ * It contains a worker which is can be added to a message.
243
+ *
244
+ * The original message is preserved and a duplicate of `ODMessage` or `ODComponentFactory` is returned.
245
+ *
246
+ * Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour!
247
+ */
248
+ export declare class ODMessageComponentModifier<Origin extends string, Params> extends ODManagerData {
249
+ /**The worker which will modify the message. */
250
+ worker: ODWorker<ODMessageInstance | ODComponentFactoryInstance<ODMessageComponent>, Origin, Params>;
251
+ constructor(id: ODValidId, worker: ODWorker<ODMessageInstance | ODComponentFactoryInstance<ODMessageComponent>, Origin, Params>);
252
+ /**Modify an `ODMessage` or `ODComponentFactory` with the worker. A copy will be returned and the original is preserved. */
253
+ modify<Message extends ODMessage<any, any, any> | ODComponentFactory<ODMessageComponent, any, any, any>>(message: Message): Message;
254
+ }
172
255
  /**## ODMessageComponentData `type`
173
256
  * The configurable settings/options for the `ODMessageComponent`.
174
257
  */
@@ -187,7 +270,7 @@ export interface ODMessageComponentData {
187
270
  /**## ODValidMessageComponents `type`
188
271
  * A collection of all valid top-level components that can be sent in a message.
189
272
  */
190
- export type ODValidMessageComponents = ODTextComponent | ODFileComponent | ODGalleryComponent;
273
+ export type ODValidMessageComponents = ODTextComponent | ODFileComponent | ODGalleryComponent | ODActionRowComponent | ODContainerComponent | ODSectionComponent | ODSeparatorComponent;
191
274
  /**## ODMessageComponentBuildResult `type`
192
275
  * The constructed message from an `ODMessageComponent`.
193
276
  */
@@ -46,6 +46,14 @@ export class ODComponentFactory extends ODManagerData {
46
46
  throw new ODSystemError("ODComponentFactory.build() --> Failed to build component! (id: " + this.id.value + ")");
47
47
  return rootComponent.build();
48
48
  }
49
+ /**Duplicate this component factory. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
50
+ duplicate(newId) {
51
+ const newMessage = new ODComponentFactory(newId ?? this.id.value);
52
+ for (const worker of this.workers.getAll()) {
53
+ newMessage.workers.add(worker.duplicate());
54
+ }
55
+ return newMessage;
56
+ }
49
57
  }
50
58
  /**## ODBaseComponentManager `class`
51
59
  * A generic Open Discord component manager.
@@ -67,6 +75,27 @@ export class ODBaseComponentManager extends ODManager {
67
75
  return super.exists(id);
68
76
  }
69
77
  }
78
+ /**## ODComponentModifierManager `class`
79
+ * An Open Discord component modifier manager.
80
+ *
81
+ * It contains a collection of all `ODMessageComponentModifier`'s. You can:
82
+ * - Patch, modify, expand or update existing messages
83
+ * - It Does not affect the original message (cloned)
84
+ */
85
+ export class ODComponentModifierManager extends ODManager {
86
+ constructor(debug) {
87
+ super(debug, "component modifier");
88
+ }
89
+ get(id) {
90
+ return super.get(id);
91
+ }
92
+ remove(id) {
93
+ return super.remove(id);
94
+ }
95
+ exists(id) {
96
+ return super.exists(id);
97
+ }
98
+ }
70
99
  /**## ODSharedComponentManager `class
71
100
  * A special class with types for shared message/modal `ODComponent`'s.
72
101
  * Create button, dropdown or any other layout component template to use them in messages & modals.
@@ -115,10 +144,13 @@ export class ODComponentManager {
115
144
  messages;
116
145
  /**The manager for all modals components. */
117
146
  modals;
147
+ /**The collection of all component modifiers. */
148
+ modifiers;
118
149
  constructor(debug) {
119
150
  this.shared = new ODSharedComponentManager(debug);
120
151
  this.messages = new ODMessageComponentManager(debug);
121
152
  this.modals = new ODModalComponentManager(debug);
153
+ this.modifiers = new ODComponentModifierManager(debug);
122
154
  }
123
155
  }
124
156
  /**## ODComponent `class`
@@ -132,9 +164,12 @@ export class ODComponent {
132
164
  id;
133
165
  /**The data or configuration of this message/modal component. */
134
166
  data;
135
- constructor(id, data) {
167
+ /**The type of this component. */
168
+ type;
169
+ constructor(id, type, data) {
136
170
  this.id = new ODId(id);
137
171
  this.data = data;
172
+ this.type = type;
138
173
  }
139
174
  }
140
175
  /**## ODGroupComponent `class`
@@ -175,15 +210,56 @@ export class ODGroupComponent extends ODComponent {
175
210
  }
176
211
  }
177
212
  }
178
- /**Get a component with a certain ID in this group. Returns `null` if non-existent. */
179
- getComponent(id) {
213
+ getComponent(id, recursive, recursiveLimit = 15) {
180
214
  const component = this.children.find((c) => c.id.value === new ODId(id).value);
181
- return component ?? null;
215
+ if (component)
216
+ return component;
217
+ else if (recursive && (recursiveLimit > 0)) {
218
+ for (const child of this.children) {
219
+ if (child instanceof ODGroupComponent) {
220
+ const finalComponent = child.getComponent(id, recursive, recursiveLimit - 1);
221
+ if (finalComponent)
222
+ return finalComponent;
223
+ }
224
+ else if (child instanceof ODParentComponent) {
225
+ const finalComponent = child.child;
226
+ if (finalComponent.id.value === new ODId(id).value)
227
+ return finalComponent;
228
+ }
229
+ }
230
+ return null;
231
+ }
232
+ else
233
+ return null;
234
+ }
235
+ getComponentsOfType(type, recursive, recursiveLimit = 15) {
236
+ if (recursive && (recursiveLimit > 0)) {
237
+ const finalComponents = [...this.children.filter((c) => c.type === type)];
238
+ for (const child of this.children) {
239
+ if (child instanceof ODGroupComponent) {
240
+ finalComponents.push(...child.getComponentsOfType(type, recursive, recursiveLimit - 1));
241
+ }
242
+ else if (child instanceof ODParentComponent) {
243
+ const finalComponent = child.child;
244
+ if (finalComponent.type === type)
245
+ finalComponents.push(finalComponent);
246
+ }
247
+ }
248
+ return finalComponents;
249
+ }
250
+ else {
251
+ const finalComponents = [...this.children.filter((c) => c.type === type)];
252
+ return finalComponents;
253
+ }
182
254
  }
183
255
  /**Get the position of a component with a certain ID in this group. Returns `-1` if non-existent. */
184
256
  getComponentPosition(id) {
185
257
  return this.children.findIndex((c) => c.id.value === new ODId(id).value);
186
258
  }
259
+ /**List all child components of this group. */
260
+ listComponent() {
261
+ return this.children;
262
+ }
187
263
  /**Returns if a component with a certain ID exists in this group. */
188
264
  existsComponent(id) {
189
265
  const component = this.children.find((c) => c.id.value === new ODId(id).value);
@@ -197,6 +273,12 @@ export class ODGroupComponent extends ODComponent {
197
273
  else
198
274
  return this.children.splice(index, 1)[0];
199
275
  }
276
+ /**Remove all child components from this group. Returns the removed components. */
277
+ clearComponents() {
278
+ const removedChildren = this.children;
279
+ this.children = [];
280
+ return removedChildren;
281
+ }
200
282
  moveComponent(id, mode = "start", reference) {
201
283
  const component = this.removeComponent(id);
202
284
  if (component) {
@@ -228,6 +310,32 @@ export class ODParentComponent extends ODComponent {
228
310
  this.rawChild = c;
229
311
  }
230
312
  }
313
+ /////////////////////////////
314
+ // COMPONENT MODIFIERS //
315
+ /////////////////////////////
316
+ /**## ODMessageComponentModifier `class`
317
+ * This is an Open Discord message component modifier.
318
+ *
319
+ * It contains a worker which is can be added to a message.
320
+ *
321
+ * The original message is preserved and a duplicate of `ODMessage` or `ODComponentFactory` is returned.
322
+ *
323
+ * Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour!
324
+ */
325
+ export class ODMessageComponentModifier extends ODManagerData {
326
+ /**The worker which will modify the message. */
327
+ worker;
328
+ constructor(id, worker) {
329
+ super(id);
330
+ this.worker = worker;
331
+ }
332
+ /**Modify an `ODMessage` or `ODComponentFactory` with the worker. A copy will be returned and the original is preserved. */
333
+ modify(message) {
334
+ const newMsg = message.duplicate(message.id.value + "-VERIFYBAR");
335
+ newMsg.workers.add(this.worker.duplicate());
336
+ return newMsg;
337
+ }
338
+ }
231
339
  /**## ODMessageComponent `class`
232
340
  * A message builder with **components v2** support.
233
341
  * Add items to this message using `addComponent()`.
@@ -237,7 +345,7 @@ export class ODParentComponent extends ODComponent {
237
345
  export class ODMessageComponent extends ODGroupComponent {
238
346
  constructor(id, data) {
239
347
  const initData = { ...data };
240
- super(id, initData);
348
+ super(id, "message", initData);
241
349
  }
242
350
  async build() {
243
351
  if (this.children.length < 1)
@@ -261,6 +369,14 @@ export class ODMessageComponent extends ODGroupComponent {
261
369
  if (res?.attachments)
262
370
  attachments.push(...res.attachments);
263
371
  }
372
+ else if (component instanceof ODContainerComponent) {
373
+ //ODContainerComponent (special)
374
+ const res = await component.build();
375
+ if (res)
376
+ components.push(res.container);
377
+ if (res?.attachments)
378
+ attachments.push(...res.attachments);
379
+ }
264
380
  else {
265
381
  //general ODComponent's
266
382
  const res = await component.build();
@@ -309,7 +425,7 @@ export class ODMessageComponent extends ODGroupComponent {
309
425
  export class ODSimpleMessageComponent extends ODGroupComponent {
310
426
  constructor(id, data) {
311
427
  const initData = { ...data };
312
- super(id, initData);
428
+ super(id, "simple-message", initData);
313
429
  }
314
430
  async build() {
315
431
  if (this.children.length < 1)
@@ -385,7 +501,7 @@ export class ODSimpleMessageComponent extends ODGroupComponent {
385
501
  export class ODModalComponent extends ODGroupComponent {
386
502
  constructor(id, data) {
387
503
  const initData = { title: "<empty>", ...data };
388
- super(id, initData);
504
+ super(id, "modal", initData);
389
505
  }
390
506
  async build() {
391
507
  if (this.children.length < 1)
@@ -429,7 +545,7 @@ export class ODModalComponent extends ODGroupComponent {
429
545
  export class ODActionRowComponent extends ODGroupComponent {
430
546
  constructor(id, data) {
431
547
  const initData = { ...data };
432
- super(id, initData);
548
+ super(id, "action-row", initData);
433
549
  }
434
550
  async build() {
435
551
  if (this.children.length < 1)
@@ -452,7 +568,7 @@ export class ODActionRowComponent extends ODGroupComponent {
452
568
  export class ODContainerComponent extends ODGroupComponent {
453
569
  constructor(id, data) {
454
570
  const initData = { spoiler: false, ...data };
455
- super(id, initData);
571
+ super(id, "container", initData);
456
572
  }
457
573
  async build() {
458
574
  if (this.children.length < 1)
@@ -509,7 +625,7 @@ export class ODContainerComponent extends ODGroupComponent {
509
625
  export class ODSectionComponent extends ODGroupComponent {
510
626
  constructor(id, data) {
511
627
  const initData = { ...data };
512
- super(id, initData);
628
+ super(id, "section", initData);
513
629
  }
514
630
  async build() {
515
631
  if (this.children.length < 1)
@@ -542,7 +658,7 @@ export class ODSectionComponent extends ODGroupComponent {
542
658
  export class ODLabelComponent extends ODParentComponent {
543
659
  constructor(id, data) {
544
660
  const initData = { title: "<empty>", ...data };
545
- super(id, initData);
661
+ super(id, "label", initData);
546
662
  }
547
663
  async build() {
548
664
  let component = undefined;
@@ -572,7 +688,7 @@ export class ODLabelComponent extends ODParentComponent {
572
688
  export class ODSeparatorComponent extends ODComponent {
573
689
  constructor(id, data) {
574
690
  const initData = { divider: true, spacing: "small", ...data };
575
- super(id, initData);
691
+ super(id, "separator", initData);
576
692
  }
577
693
  async build() {
578
694
  return new discord.SeparatorBuilder({
@@ -595,7 +711,7 @@ export class ODSeparatorComponent extends ODComponent {
595
711
  export class ODTextComponent extends ODComponent {
596
712
  constructor(id, data) {
597
713
  const initData = { content: "", ...data };
598
- super(id, initData);
714
+ super(id, "text", initData);
599
715
  }
600
716
  async build() {
601
717
  if (this.data.content.length < 1)
@@ -615,7 +731,7 @@ export class ODTextComponent extends ODComponent {
615
731
  export class ODFileComponent extends ODComponent {
616
732
  constructor(id, data) {
617
733
  const initData = { name: "file.txt", ...data };
618
- super(id, initData);
734
+ super(id, "file", initData);
619
735
  }
620
736
  async build() {
621
737
  if (!this.data.content && !this.data.externalUrl)
@@ -662,7 +778,7 @@ export class ODFileComponent extends ODComponent {
662
778
  export class ODGalleryComponent extends ODGroupComponent {
663
779
  constructor(id, data) {
664
780
  const initData = { ...data };
665
- super(id, initData);
781
+ super(id, "gallery", initData);
666
782
  }
667
783
  async build() {
668
784
  if (this.children.length < 1)
@@ -695,7 +811,7 @@ export class ODGalleryComponent extends ODGroupComponent {
695
811
  export class ODThumbnailComponent extends ODComponent {
696
812
  constructor(id, data) {
697
813
  const initData = { url: "", ...data };
698
- super(id, initData);
814
+ super(id, "thumbnail", initData);
699
815
  }
700
816
  async build() {
701
817
  if (this.data.url.length < 1)
@@ -725,7 +841,7 @@ export class ODThumbnailComponent extends ODComponent {
725
841
  export class ODContentComponent extends ODComponent {
726
842
  constructor(id, data) {
727
843
  const initData = { content: "", ...data };
728
- super(id, initData);
844
+ super(id, "simple-content", initData);
729
845
  }
730
846
  async build() {
731
847
  if (this.data.content.length < 1)
@@ -745,7 +861,7 @@ export class ODContentComponent extends ODComponent {
745
861
  export class ODEmbedComponent extends ODComponent {
746
862
  constructor(id, data) {
747
863
  const initData = { ...data };
748
- super(id, initData);
864
+ super(id, "simple-embed", initData);
749
865
  }
750
866
  async build() {
751
867
  if (this.data.title && this.data.title.length > 256)
@@ -871,7 +987,7 @@ export class ODEmbedComponent extends ODComponent {
871
987
  export class ODPollComponent extends ODComponent {
872
988
  constructor(id, data) {
873
989
  const initData = { question: "<empty>", durationHours: 1, allowMultiSelect: false, answers: [], ...data };
874
- super(id, initData);
990
+ super(id, "simple-poll", initData);
875
991
  }
876
992
  async build() {
877
993
  if (this.data.question.length < 1)
@@ -914,7 +1030,7 @@ export class ODPollComponent extends ODComponent {
914
1030
  export class ODButtonComponent extends ODComponent {
915
1031
  constructor(id, data) {
916
1032
  const initData = { color: "gray", disabled: false, ...data };
917
- super(id, initData);
1033
+ super(id, "button", initData);
918
1034
  }
919
1035
  async build() {
920
1036
  if (!this.data.emoji && !this.data.label)
@@ -981,7 +1097,7 @@ export class ODButtonComponent extends ODComponent {
981
1097
  export class ODShortInputComponent extends ODComponent {
982
1098
  constructor(id, data) {
983
1099
  const initData = { required: false, ...data };
984
- super(id, initData);
1100
+ super(id, "short-input", initData);
985
1101
  }
986
1102
  async build() {
987
1103
  return new discord.TextInputBuilder({
@@ -1032,7 +1148,7 @@ export class ODShortInputComponent extends ODComponent {
1032
1148
  export class ODParagraphInputComponent extends ODComponent {
1033
1149
  constructor(id, data) {
1034
1150
  const initData = { required: false, ...data };
1035
- super(id, initData);
1151
+ super(id, "paragraph-input", initData);
1036
1152
  }
1037
1153
  async build() {
1038
1154
  return new discord.TextInputBuilder({
@@ -1083,7 +1199,7 @@ export class ODParagraphInputComponent extends ODComponent {
1083
1199
  export class ODDropdownComponent extends ODComponent {
1084
1200
  constructor(id, data) {
1085
1201
  const initData = { type: "string", ...data };
1086
- super(id, initData);
1202
+ super(id, "dropdown", initData);
1087
1203
  }
1088
1204
  async build() {
1089
1205
  const genericOpts = {
@@ -1204,7 +1320,7 @@ export class ODDropdownComponent extends ODComponent {
1204
1320
  export class ODRadioGroupComponent extends ODComponent {
1205
1321
  constructor(id, data) {
1206
1322
  const initData = { required: false, options: [], ...data };
1207
- super(id, initData);
1323
+ super(id, "radio-group", initData);
1208
1324
  }
1209
1325
  async build() {
1210
1326
  if (!this.data.options || this.data.options.length < 2)
@@ -1237,7 +1353,7 @@ export class ODRadioGroupComponent extends ODComponent {
1237
1353
  export class ODCheckboxGroupComponent extends ODComponent {
1238
1354
  constructor(id, data) {
1239
1355
  const initData = { required: false, options: [], ...data };
1240
- super(id, initData);
1356
+ super(id, "checkbox-group", initData);
1241
1357
  }
1242
1358
  async build() {
1243
1359
  if (!this.data.options || this.data.options.length < 2)
@@ -1283,7 +1399,7 @@ export class ODCheckboxGroupComponent extends ODComponent {
1283
1399
  export class ODCheckboxComponent extends ODComponent {
1284
1400
  constructor(id, data) {
1285
1401
  const initData = { default: false, ...data };
1286
- super(id, initData);
1402
+ super(id, "checkbox", initData);
1287
1403
  }
1288
1404
  async build() {
1289
1405
  return new discord.CheckboxBuilder({
@@ -1309,7 +1425,7 @@ export class ODCheckboxComponent extends ODComponent {
1309
1425
  export class ODFileUploadComponent extends ODComponent {
1310
1426
  constructor(id, data) {
1311
1427
  const initData = { required: false, ...data };
1312
- super(id, initData);
1428
+ super(id, "file-upload", initData);
1313
1429
  }
1314
1430
  async build() {
1315
1431
  if (typeof this.data.minAmount == "number" && !(this.data.minAmount >= 0 && this.data.minAmount <= 10))
@@ -158,6 +158,8 @@ export interface ODSharedFuseList {
158
158
  messageComponentsLoading: boolean;
159
159
  /**Load the default Open Discord modal components. */
160
160
  modalComponentsLoading: boolean;
161
+ /**Load the default Open Discord component modifiers. */
162
+ componentModifiersLoading: boolean;
161
163
  /**Load the default Open Discord command responders. */
162
164
  commandRespondersLoading: boolean;
163
165
  /**Load the default Open Discord button responders. */
@@ -90,6 +90,7 @@ export class ODSharedFuseManager extends ODFuseManager {
90
90
  sharedComponentsLoading: true,
91
91
  messageComponentsLoading: true,
92
92
  modalComponentsLoading: true,
93
+ componentModifiersLoading: true,
93
94
  commandRespondersLoading: true,
94
95
  buttonRespondersLoading: true,
95
96
  dropdownRespondersLoading: true,
@@ -5,6 +5,7 @@ import { ODButtonResponderInstance } from "./responder.js";
5
5
  import * as discord from "discord.js";
6
6
  import { ODWorkerManager } from "./worker.js";
7
7
  /**## ODVerifyBar `class`
8
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
8
9
  * This is an Open Discord verifybar.
9
10
  *
10
11
  * It is contains 2 sets of workers and a lot of utilities for the (✅ ❌) verifybars in the bot.
@@ -43,6 +44,7 @@ export declare class ODVerifyBar<SuccessWorkerIds extends string = string, Failu
43
44
  activate(responder: ODButtonResponderInstance): Promise<void>;
44
45
  }
45
46
  /**## ODVerifyBarManagerIdConstraint `type`
47
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
46
48
  * The constraint/layout for id mappings/interfaces of the `ODVerifyBarManager` class.
47
49
  */
48
50
  export type ODVerifyBarManagerIdConstraint = Record<string, {
@@ -50,9 +52,9 @@ export type ODVerifyBarManagerIdConstraint = Record<string, {
50
52
  failureWorkerIds: string;
51
53
  }>;
52
54
  /**## ODVerifyBarManager `class`
53
- * This is an Open Discord verifybar manager.
55
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
54
56
  *
55
- * It contains all (✅ ❌) verifybars in the bot.
57
+ * The Open Discord verifybar manager manages all (✅ ❌) verifybars in the bot.
56
58
  * The `ODVerifyBar` classes contain `ODWorkerManager`'s that will be fired when the continue/stop buttons are pressed.
57
59
  *
58
60
  * It doesn't contain the code which activates the verifybars! This should be implemented by your own.
@@ -4,6 +4,7 @@
4
4
  import { ODManager, ODManagerData } from "./base.js";
5
5
  import { ODWorkerManager } from "./worker.js";
6
6
  /**## ODVerifyBar `class`
7
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
7
8
  * This is an Open Discord verifybar.
8
9
  *
9
10
  * It is contains 2 sets of workers and a lot of utilities for the (✅ ❌) verifybars in the bot.
@@ -41,9 +42,9 @@ export class ODVerifyBar extends ODManagerData {
41
42
  }
42
43
  }
43
44
  /**## ODVerifyBarManager `class`
44
- * This is an Open Discord verifybar manager.
45
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
45
46
  *
46
- * It contains all (✅ ❌) verifybars in the bot.
47
+ * The Open Discord verifybar manager manages all (✅ ❌) verifybars in the bot.
47
48
  * The `ODVerifyBar` classes contain `ODWorkerManager`'s that will be fired when the continue/stop buttons are pressed.
48
49
  *
49
50
  * It doesn't contain the code which activates the verifybars! This should be implemented by your own.
@@ -19,6 +19,8 @@ export declare class ODWorker<Instance, Origin extends string, Params> extends O
19
19
  /**The main callback of this worker */
20
20
  callback: ODWorkerCallback<Instance, Origin, Params>;
21
21
  constructor(id: ODValidId, priority: number, callback: ODWorkerCallback<Instance, Origin, Params>);
22
+ /**Duplicate this worker. Warning: If the callback accesses external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
23
+ duplicate(newId?: ODValidId): ODWorker<Instance, Origin, Params>;
22
24
  }
23
25
  /**## ODWorker `class`
24
26
  * This is an Open Discord worker manager.
@@ -22,6 +22,10 @@ export class ODWorker extends ODManagerData {
22
22
  this.priority = priority;
23
23
  this.callback = callback;
24
24
  }
25
+ /**Duplicate this worker. Warning: If the callback accesses external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
26
+ duplicate(newId) {
27
+ return new ODWorker(newId ?? this.id.value, this.priority, this.callback);
28
+ }
25
29
  }
26
30
  /**## ODWorker `class`
27
31
  * This is an Open Discord worker manager.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@open-discord-bots/framework",
3
3
  "author": "DJj123dj",
4
- "version": "0.3.7",
4
+ "version": "0.3.8",
5
5
  "description": "The core framework of the popular open-source discord bots: Open Ticket & Open Moderation.",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
package/src/api/main.ts CHANGED
@@ -154,7 +154,7 @@ export abstract class ODMain implements ODMainManagers {
154
154
  constructor(managers:ODMainManagers,project:ODProjectType){
155
155
  this.project = project
156
156
  this.versions = managers.versions
157
- this.versions.add(ODVersion.fromString("opendiscord:api","v0.3.7"))
157
+ this.versions.add(ODVersion.fromString("opendiscord:api","v0.3.8"))
158
158
  this.versions.add(ODVersion.fromString("opendiscord:livestatus","v2.0.0"))
159
159
 
160
160
  this.debugfile = managers.debugfile
@@ -1469,6 +1469,14 @@ export class ODMessage<Origin extends string,Params,WorkerIds extends string = s
1469
1469
  this.didCache = true
1470
1470
  return result
1471
1471
  }
1472
+ /**Duplicate this message. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
1473
+ duplicate(newId?:ODValidId): ODMessage<Origin,Params,WorkerIds> {
1474
+ const newMessage = new ODMessage<Origin,Params,WorkerIds>(newId ?? this.id.value)
1475
+ for (const worker of this.workers.getAll()){
1476
+ newMessage.workers.add(worker.duplicate())
1477
+ }
1478
+ return newMessage
1479
+ }
1472
1480
  }
1473
1481
 
1474
1482
  /**## ODQuickMessage `class`
@@ -5,6 +5,7 @@ import { ODId, ODValidId, ODSystemError, ODManagerData, ODNoGeneric, ODManager,
5
5
  import * as discord from "discord.js"
6
6
  import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker.js"
7
7
  import { ODDebugger } from "./console.js"
8
+ import { ODMessage, ODMessageInstance } from "./builder.js"
8
9
 
9
10
  /**## ODComponentFactoryInstance `class`
10
11
  * An Open Discord component factory instance.
@@ -49,6 +50,14 @@ export class ODComponentFactory<Component extends ODComponent<object,any>,Origin
49
50
  if (!rootComponent) throw new ODSystemError("ODComponentFactory.build() --> Failed to build component! (id: "+this.id.value+")")
50
51
  return rootComponent.build()
51
52
  }
53
+ /**Duplicate this component factory. Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
54
+ duplicate(newId?:ODValidId): ODComponentFactory<Component,Origin,Params,WorkerIds> {
55
+ const newMessage = new ODComponentFactory<Component,Origin,Params,WorkerIds>(newId ?? this.id.value)
56
+ for (const worker of this.workers.getAll()){
57
+ newMessage.workers.add(worker.duplicate())
58
+ }
59
+ return newMessage
60
+ }
52
61
  }
53
62
 
54
63
  /**## ODComponentManagerIdConstraint `type`
@@ -88,6 +97,46 @@ export class ODBaseComponentManager<IdList extends ODComponentManagerIdConstrain
88
97
  }
89
98
  }
90
99
 
100
+
101
+ /**## ODComponentModifierManagerIdConstraint `type`
102
+ * The constraint/layout for id mappings/interfaces of the `ODComponentModifierManager` class.
103
+ */
104
+ export type ODComponentModifierManagerIdConstraint = Record<string,ODMessageComponentModifier<string,{}>>
105
+
106
+ /**## ODComponentModifierManager `class`
107
+ * An Open Discord component modifier manager.
108
+ *
109
+ * It contains a collection of all `ODMessageComponentModifier`'s. You can:
110
+ * - Patch, modify, expand or update existing messages
111
+ * - It Does not affect the original message (cloned)
112
+ */
113
+ export class ODComponentModifierManager<IdList extends ODComponentModifierManagerIdConstraint = ODComponentModifierManagerIdConstraint> extends ODManager<ODMessageComponentModifier<string,{}>> {
114
+ constructor(debug:ODDebugger){
115
+ super(debug,"component modifier")
116
+ }
117
+
118
+ get<ModifierId extends keyof ODNoGeneric<IdList>>(id:ModifierId): IdList[ModifierId]
119
+ get(id:ODValidId): ODMessageComponentModifier<string,{}>|null
120
+
121
+ get(id:ODValidId): ODMessageComponentModifier<string,{}>|null {
122
+ return super.get(id)
123
+ }
124
+
125
+ remove<ModifierId extends keyof ODNoGeneric<IdList>>(id:ModifierId): IdList[ModifierId]
126
+ remove(id:ODValidId): ODMessageComponentModifier<string,{}>|null
127
+
128
+ remove(id:ODValidId): ODMessageComponentModifier<string,{}>|null {
129
+ return super.remove(id)
130
+ }
131
+
132
+ exists(id:keyof ODNoGeneric<IdList>): boolean
133
+ exists(id:ODValidId): boolean
134
+
135
+ exists(id:ODValidId): boolean {
136
+ return super.exists(id)
137
+ }
138
+ }
139
+
91
140
  /**## ODSharedComponentManager `class
92
141
  * A special class with types for shared message/modal `ODComponent`'s.
93
142
  * Create button, dropdown or any other layout component template to use them in messages & modals.
@@ -135,7 +184,8 @@ export class ODModalComponentManager<IdList extends ODComponentManagerIdConstrai
135
184
  export class ODComponentManager<
136
185
  SharedIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint,
137
186
  MessageIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint,
138
- ModalIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint
187
+ ModalIdList extends ODComponentManagerIdConstraint = ODComponentManagerIdConstraint,
188
+ ModifierIdList extends ODComponentModifierManagerIdConstraint = ODComponentModifierManagerIdConstraint
139
189
  > {
140
190
  /**The manager for all shared components. */
141
191
  shared: ODSharedComponentManager<SharedIdList>
@@ -143,11 +193,14 @@ export class ODComponentManager<
143
193
  messages: ODMessageComponentManager<MessageIdList>
144
194
  /**The manager for all modals components. */
145
195
  modals: ODModalComponentManager<ModalIdList>
196
+ /**The collection of all component modifiers. */
197
+ modifiers: ODComponentModifierManager<ModifierIdList>
146
198
 
147
199
  constructor(debug:ODDebugger){
148
200
  this.shared = new ODSharedComponentManager(debug)
149
201
  this.messages = new ODMessageComponentManager(debug)
150
202
  this.modals = new ODModalComponentManager(debug)
203
+ this.modifiers = new ODComponentModifierManager(debug)
151
204
  }
152
205
  }
153
206
 
@@ -160,21 +213,58 @@ export class ODComponentManager<
160
213
  */
161
214
  export type ODComponentInferBuildResult<Component> = Component extends ODComponent<object,infer BuildResult> ? BuildResult : never
162
215
 
216
+ /**## ODComponentType `type`
217
+ * The type of an `ODComponent`.
218
+ */
219
+ export type ODComponentType = "message"|"simple-message"|"modal"|"action-row"|"container"|"section"|"label"|"separator"|"text"|"file"|"gallery"|"thumbnail"|"simple-content"|"simple-embed"|"simple-poll"|"button"|"short-input"|"paragraph-input"|"dropdown"|"radio-group"|"checkbox-group"|"checkbox"|"file-upload"
220
+
221
+ /**## ODComponentType `type`
222
+ * Get the `ODComponent` class for a specific `ODComponentType`.
223
+ */
224
+ export interface ODComponentForType {
225
+ "message":ODMessageComponent,
226
+ "simple-message":ODSimpleMessageComponent,
227
+ "modal":ODModalComponent,
228
+ "action-row":ODActionRowComponent,
229
+ "container":ODContainerComponent,
230
+ "section":ODSectionComponent,
231
+ "label":ODLabelComponent,
232
+ "separator":ODSeparatorComponent,
233
+ "text":ODTextComponent,
234
+ "file":ODFileComponent,
235
+ "gallery":ODGalleryComponent,
236
+ "thumbnail":ODThumbnailComponent,
237
+ "simple-content":ODContentComponent,
238
+ "simple-embed":ODEmbedComponent,
239
+ "simple-poll":ODPollComponent,
240
+ "button":ODButtonComponent,
241
+ "short-input":ODShortInputComponent,
242
+ "paragraph-input":ODParagraphInputComponent,
243
+ "dropdown":ODDropdownComponent,
244
+ "radio-group":ODRadioGroupComponent,
245
+ "checkbox-group":ODCheckboxGroupComponent,
246
+ "checkbox":ODCheckboxComponent,
247
+ "file-upload":ODFileUploadComponent,
248
+ }
249
+
163
250
  /**## ODComponent `class`
164
251
  * An Open Discord message/modal component.
165
252
  *
166
253
  * This class itself doesn't do anything, but is a blueprint for other
167
254
  * `ODComponent` classes which represent the new Discord message/modal components.
168
255
  */
169
- export abstract class ODComponent<Data extends object,BuildResult> {
256
+ export abstract class ODComponent<Data extends object,BuildResult,Type extends ODComponentType = ODComponentType> {
170
257
  /**The id of this message/modal component. */
171
258
  id: ODId
172
259
  /**The data or configuration of this message/modal component. */
173
260
  readonly data: Data
261
+ /**The type of this component. */
262
+ readonly type: Type
174
263
 
175
- constructor(id:ODValidId,data:Data){
264
+ constructor(id:ODValidId,type:Type,data:Data){
176
265
  this.id = new ODId(id)
177
266
  this.data = data
267
+ this.type = type
178
268
  }
179
269
 
180
270
  /**Build this component. Returns `null` when invalid. */
@@ -189,7 +279,7 @@ export abstract class ODComponent<Data extends object,BuildResult> {
189
279
  */
190
280
  export abstract class ODGroupComponent<Data extends object,ChildComponent extends ODComponent<object,any>,BuildResult> extends ODComponent<Data,BuildResult> {
191
281
  /**The collection of child components. */
192
- readonly children: ChildComponent[] = []
282
+ children: ChildComponent[] = []
193
283
 
194
284
  /**Add a new component to this group. There are multiple modes available:
195
285
  * - `start`: insert at the start of the list.
@@ -223,15 +313,55 @@ export abstract class ODGroupComponent<Data extends object,ChildComponent extend
223
313
  }
224
314
  }
225
315
  }
226
- /**Get a component with a certain ID in this group. Returns `null` if non-existent. */
227
- getComponent(id:ODValidId){
316
+ /**Get a component with a certain ID in this group. Returns `null` if non-existent. Also able to search for components recursively. */
317
+ getComponent(id:ODValidId): ChildComponent|null
318
+ getComponent(id:ODValidId,recursive:true,recursiveLimit?:number): ODComponent<any,any,ODComponentType>|null
319
+ getComponent(id:ODValidId,recursive?:boolean,recursiveLimit:number=15){
228
320
  const component = this.children.find((c) => c.id.value === new ODId(id).value)
229
- return component ?? null
321
+ if (component) return component
322
+ else if (recursive && (recursiveLimit > 0)){
323
+ for (const child of this.children){
324
+ if (child instanceof ODGroupComponent){
325
+ const finalComponent = child.getComponent(id,recursive,recursiveLimit-1) as ODComponent<any,any,ODComponentType>
326
+ if (finalComponent) return finalComponent
327
+ }else if (child instanceof ODParentComponent){
328
+ const finalComponent = child.child as ODComponent<any,any,ODComponentType>
329
+ if (finalComponent.id.value === new ODId(id).value) return finalComponent
330
+ }
331
+ }
332
+ return null
333
+ }else return null
334
+ }
335
+ /**Get all components of a certain type in this group. Also able to search for components recursively. */
336
+ getComponentsOfType<Type extends ODComponentType>(type:Type): ODComponentForType[Type][]
337
+ getComponentsOfType<Type extends ODComponentType>(type:Type,recursive:true,recursiveLimit?:number): ODComponentForType[Type][]
338
+ getComponentsOfType(type:ODComponentType,recursive?:boolean,recursiveLimit:number=15){
339
+ if (recursive && (recursiveLimit > 0)){
340
+ const finalComponents: ODComponent<any,any,ODComponentType>[] = [...this.children.filter((c) => c.type === type)]
341
+
342
+ for (const child of this.children){
343
+ if (child instanceof ODGroupComponent){
344
+ finalComponents.push(...(child.getComponentsOfType(type,recursive,recursiveLimit-1) as ODComponent<any,any,ODComponentType>[]))
345
+
346
+ }else if (child instanceof ODParentComponent){
347
+ const finalComponent = child.child as ODComponent<any,any,ODComponentType>
348
+ if (finalComponent.type === type) finalComponents.push(finalComponent)
349
+ }
350
+ }
351
+ return finalComponents
352
+ }else{
353
+ const finalComponents: ChildComponent[] = [...this.children.filter((c) => c.type === type)]
354
+ return finalComponents
355
+ }
230
356
  }
231
357
  /**Get the position of a component with a certain ID in this group. Returns `-1` if non-existent. */
232
358
  getComponentPosition(id:ODValidId){
233
359
  return this.children.findIndex((c) => c.id.value === new ODId(id).value)
234
360
  }
361
+ /**List all child components of this group. */
362
+ listComponent(){
363
+ return this.children
364
+ }
235
365
  /**Returns if a component with a certain ID exists in this group. */
236
366
  existsComponent(id:ODValidId){
237
367
  const component = this.children.find((c) => c.id.value === new ODId(id).value)
@@ -243,6 +373,12 @@ export abstract class ODGroupComponent<Data extends object,ChildComponent extend
243
373
  if (index < 0) return null
244
374
  else return this.children.splice(index,1)[0]
245
375
  }
376
+ /**Remove all child components from this group. Returns the removed components. */
377
+ clearComponents(){
378
+ const removedChildren = this.children
379
+ this.children = []
380
+ return removedChildren
381
+ }
246
382
  /**Moves an existing component to a new location in this group. There are multiple modes available:
247
383
  * - `start`: move to the start of the list.
248
384
  * - `end`: move to the end of the list.
@@ -284,6 +420,36 @@ export abstract class ODParentComponent<Data extends object,ChildComponent exten
284
420
  }
285
421
  }
286
422
 
423
+ /////////////////////////////
424
+ // COMPONENT MODIFIERS //
425
+ /////////////////////////////
426
+
427
+ /**## ODMessageComponentModifier `class`
428
+ * This is an Open Discord message component modifier.
429
+ *
430
+ * It contains a worker which is can be added to a message.
431
+ *
432
+ * The original message is preserved and a duplicate of `ODMessage` or `ODComponentFactory` is returned.
433
+ *
434
+ * Warning: If workers access external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour!
435
+ */
436
+ export class ODMessageComponentModifier<Origin extends string,Params> extends ODManagerData {
437
+ /**The worker which will modify the message. */
438
+ worker: ODWorker<ODMessageInstance|ODComponentFactoryInstance<ODMessageComponent>,Origin,Params>
439
+
440
+ constructor(id:ODValidId,worker:ODWorker<ODMessageInstance|ODComponentFactoryInstance<ODMessageComponent>,Origin,Params>){
441
+ super(id)
442
+ this.worker = worker
443
+ }
444
+
445
+ /**Modify an `ODMessage` or `ODComponentFactory` with the worker. A copy will be returned and the original is preserved. */
446
+ modify<Message extends ODMessage<any,any,any>|ODComponentFactory<ODMessageComponent,any,any,any>>(message:Message): Message {
447
+ const newMsg = message.duplicate(message.id.value+"-VERIFYBAR") as Message
448
+ newMsg.workers.add(this.worker.duplicate())
449
+ return newMsg
450
+ }
451
+ }
452
+
287
453
  //////////////////////////////////////
288
454
  // GLOBAL COMPONENT DEFINITIONS //
289
455
  //////////////////////////////////////
@@ -307,7 +473,7 @@ export interface ODMessageComponentData {
307
473
  /**## ODValidMessageComponents `type`
308
474
  * A collection of all valid top-level components that can be sent in a message.
309
475
  */
310
- export type ODValidMessageComponents = ODTextComponent|ODFileComponent|ODGalleryComponent
476
+ export type ODValidMessageComponents = ODTextComponent|ODFileComponent|ODGalleryComponent|ODActionRowComponent|ODContainerComponent|ODSectionComponent|ODSeparatorComponent
311
477
 
312
478
  /**## ODMessageComponentBuildResult `type`
313
479
  * The constructed message from an `ODMessageComponent`.
@@ -336,7 +502,7 @@ export interface ODMessageComponentBuildResult {
336
502
  export class ODMessageComponent extends ODGroupComponent<ODMessageComponentData,ODValidMessageComponents,ODMessageComponentBuildResult> {
337
503
  constructor(id:ODValidId,data?:Partial<ODMessageComponentData>){
338
504
  const initData: ODMessageComponentData = {...data}
339
- super(id,initData)
505
+ super(id,"message",initData)
340
506
  }
341
507
 
342
508
  async build(){
@@ -357,6 +523,11 @@ export class ODMessageComponent extends ODGroupComponent<ODMessageComponentData,
357
523
  const res = await component.build()
358
524
  if (res) components.push(res.gallery)
359
525
  if (res?.attachments) attachments.push(...res.attachments)
526
+ }else if (component instanceof ODContainerComponent){
527
+ //ODContainerComponent (special)
528
+ const res = await component.build()
529
+ if (res) components.push(res.container)
530
+ if (res?.attachments) attachments.push(...res.attachments)
360
531
  }else{
361
532
  //general ODComponent's
362
533
  const res = await component.build()
@@ -429,7 +600,7 @@ export type ODValidSimpleMessageComponents = ODContentComponent|ODEmbedComponent
429
600
  export class ODSimpleMessageComponent extends ODGroupComponent<ODSimpleMessageComponentData,ODValidSimpleMessageComponents,ODMessageComponentBuildResult> {
430
601
  constructor(id:ODValidId,data?:Partial<ODMessageComponentData>){
431
602
  const initData: ODMessageComponentData = {...data}
432
- super(id,initData)
603
+ super(id,"simple-message",initData)
433
604
  }
434
605
 
435
606
  async build(){
@@ -521,7 +692,7 @@ export type ODValidModalComponents = ODLabelComponent|ODTextComponent
521
692
  export class ODModalComponent extends ODGroupComponent<ODModalComponentData,ODValidModalComponents,discord.ModalBuilder> {
522
693
  constructor(id:ODValidId,data?:Partial<ODModalComponentData>){
523
694
  const initData: ODModalComponentData = {title:"<empty>",...data}
524
- super(id,initData)
695
+ super(id,"modal",initData)
525
696
  }
526
697
 
527
698
  async build(){
@@ -584,7 +755,7 @@ export type ODValidActionRowComponents = ODButtonComponent|ODDropdownComponent
584
755
  export class ODActionRowComponent extends ODGroupComponent<ODActionRowComponentData,ODValidActionRowComponents,discord.ActionRowBuilder<discord.MessageActionRowComponentBuilder>> {
585
756
  constructor(id:ODValidId,data?:Partial<ODActionRowComponentData>){
586
757
  const initData: ODActionRowComponentData = {...data}
587
- super(id,initData)
758
+ super(id,"action-row",initData)
588
759
  }
589
760
 
590
761
  async build(){
@@ -624,7 +795,7 @@ export type ODValidContainerComponents = ODActionRowComponent|ODTextComponent|OD
624
795
  export class ODContainerComponent extends ODGroupComponent<ODContainerComponentData,ODValidContainerComponents,{container:discord.ContainerBuilder,attachments:discord.AttachmentBuilder[]}> {
625
796
  constructor(id:ODValidId,data?:Partial<ODContainerComponentData>){
626
797
  const initData: ODContainerComponentData = {spoiler:false,...data}
627
- super(id,initData)
798
+ super(id,"container",initData)
628
799
  }
629
800
 
630
801
  async build(){
@@ -689,7 +860,7 @@ export interface ODSectionComponentData {
689
860
  export class ODSectionComponent extends ODGroupComponent<ODSectionComponentData,ODTextComponent,discord.SectionBuilder> {
690
861
  constructor(id:ODValidId,data?:Partial<ODSectionComponentData>){
691
862
  const initData: ODSectionComponentData = {...data}
692
- super(id,initData)
863
+ super(id,"section",initData)
693
864
  }
694
865
 
695
866
  async build(){
@@ -741,7 +912,7 @@ export type ODValidLabelComponents = ODShortInputComponent|ODParagraphInputCompo
741
912
  export class ODLabelComponent extends ODParentComponent<ODLabelComponentData,ODValidLabelComponents,discord.LabelBuilder> {
742
913
  constructor(id:ODValidId,data:Partial<ODLabelComponentData>){
743
914
  const initData: ODLabelComponentData = {title:"<empty>",...data}
744
- super(id,initData)
915
+ super(id,"label",initData)
745
916
  }
746
917
 
747
918
  async build(){
@@ -785,7 +956,7 @@ export interface ODSeparatorComponentData {
785
956
  export class ODSeparatorComponent extends ODComponent<ODSeparatorComponentData,discord.SeparatorBuilder> {
786
957
  constructor(id:ODValidId,data:Partial<ODSeparatorComponentData>){
787
958
  const initData: ODSeparatorComponentData = {divider:true,spacing:"small",...data}
788
- super(id,initData)
959
+ super(id,"separator",initData)
789
960
  }
790
961
 
791
962
  async build(){
@@ -823,7 +994,7 @@ export interface ODTextComponentData {
823
994
  export class ODTextComponent extends ODComponent<ODTextComponentData,discord.TextDisplayBuilder> {
824
995
  constructor(id:ODValidId,data:Partial<ODTextComponentData>){
825
996
  const initData: ODTextComponentData = {content:"",...data}
826
- super(id,initData)
997
+ super(id,"text",initData)
827
998
  }
828
999
 
829
1000
  async build(){
@@ -861,7 +1032,7 @@ export interface ODFileComponentData {
861
1032
  export class ODFileComponent extends ODComponent<ODFileComponentData,{file:discord.FileBuilder,attachment:discord.AttachmentBuilder|null}> {
862
1033
  constructor(id:ODValidId,data:Partial<ODFileComponentData>){
863
1034
  const initData: ODFileComponentData = {name:"file.txt",...data}
864
- super(id,initData)
1035
+ super(id,"file",initData)
865
1036
  }
866
1037
 
867
1038
  async build(){
@@ -919,7 +1090,7 @@ export interface ODGalleryComponentData {
919
1090
  export class ODGalleryComponent extends ODGroupComponent<ODGalleryComponentData,ODFileComponent,{gallery:discord.MediaGalleryBuilder,attachments:discord.AttachmentBuilder[]}> {
920
1091
  constructor(id:ODValidId,data?:Partial<ODGalleryComponentData>){
921
1092
  const initData: ODGalleryComponentData = {...data}
922
- super(id,initData)
1093
+ super(id,"gallery",initData)
923
1094
  }
924
1095
 
925
1096
  async build(){
@@ -966,7 +1137,7 @@ export interface ODThumbnailComponentData {
966
1137
  export class ODThumbnailComponent extends ODComponent<ODThumbnailComponentData,discord.ThumbnailBuilder> {
967
1138
  constructor(id:ODValidId,data:Partial<ODThumbnailComponentData>){
968
1139
  const initData: ODThumbnailComponentData = {url:"",...data}
969
- super(id,initData)
1140
+ super(id,"thumbnail",initData)
970
1141
  }
971
1142
 
972
1143
  async build(){
@@ -1007,7 +1178,7 @@ export interface ODContentComponentData {
1007
1178
  export class ODContentComponent extends ODComponent<ODContentComponentData,{content:string}> {
1008
1179
  constructor(id:ODValidId,data:Partial<ODContentComponentData>){
1009
1180
  const initData: ODContentComponentData = {content:"",...data}
1010
- super(id,initData)
1181
+ super(id,"simple-content",initData)
1011
1182
  }
1012
1183
 
1013
1184
  async build(){
@@ -1062,7 +1233,7 @@ export interface ODEmbedComponentData {
1062
1233
  export class ODEmbedComponent extends ODComponent<ODEmbedComponentData,discord.EmbedBuilder> {
1063
1234
  constructor(id:ODValidId,data:Partial<ODEmbedComponentData>){
1064
1235
  const initData: ODEmbedComponentData = {...data}
1065
- super(id,initData)
1236
+ super(id,"simple-embed",initData)
1066
1237
  }
1067
1238
 
1068
1239
  async build(){
@@ -1195,7 +1366,7 @@ export interface ODPollComponentData {
1195
1366
  export class ODPollComponent extends ODComponent<ODPollComponentData,discord.PollData> {
1196
1367
  constructor(id:ODValidId,data:Partial<ODPollComponentData>){
1197
1368
  const initData: ODPollComponentData = {question:"<empty>",durationHours:1,allowMultiSelect:false,answers:[],...data}
1198
- super(id,initData)
1369
+ super(id,"simple-poll",initData)
1199
1370
  }
1200
1371
 
1201
1372
  async build(){
@@ -1262,7 +1433,7 @@ export interface ODButtonComponentData {
1262
1433
  export class ODButtonComponent extends ODComponent<ODButtonComponentData,discord.ButtonBuilder> {
1263
1434
  constructor(id:ODValidId,data:Partial<ODButtonComponentData>){
1264
1435
  const initData: ODButtonComponentData = {color:"gray",disabled:false,...data}
1265
- super(id,initData)
1436
+ super(id,"button",initData)
1266
1437
  }
1267
1438
 
1268
1439
  async build(){
@@ -1346,7 +1517,7 @@ export interface ODShortInputComponentData {
1346
1517
  export class ODShortInputComponent extends ODComponent<ODShortInputComponentData,discord.TextInputBuilder> {
1347
1518
  constructor(id:ODValidId,data:Partial<ODShortInputComponentData>){
1348
1519
  const initData: ODShortInputComponentData = {required:false,...data}
1349
- super(id,initData)
1520
+ super(id,"short-input",initData)
1350
1521
  }
1351
1522
 
1352
1523
  async build(){
@@ -1418,7 +1589,7 @@ export interface ODParagraphInputComponentData {
1418
1589
  export class ODParagraphInputComponent extends ODComponent<ODParagraphInputComponentData,discord.TextInputBuilder> {
1419
1590
  constructor(id:ODValidId,data:Partial<ODParagraphInputComponentData>){
1420
1591
  const initData: ODParagraphInputComponentData = {required:false,...data}
1421
- super(id,initData)
1592
+ super(id,"paragraph-input",initData)
1422
1593
  }
1423
1594
 
1424
1595
  async build(){
@@ -1504,7 +1675,7 @@ export interface ODDropdownComponentData {
1504
1675
  export class ODDropdownComponent extends ODComponent<ODDropdownComponentData,discord.BaseSelectMenuBuilder<discord.APISelectMenuComponent>> {
1505
1676
  constructor(id:ODValidId,data:Partial<ODDropdownComponentData>){
1506
1677
  const initData: ODDropdownComponentData = {type:"string",...data}
1507
- super(id,initData)
1678
+ super(id,"dropdown",initData)
1508
1679
  }
1509
1680
 
1510
1681
  async build(){
@@ -1631,7 +1802,7 @@ export interface ODRadioGroupComponentData {
1631
1802
  export class ODRadioGroupComponent extends ODComponent<ODRadioGroupComponentData,discord.RadioGroupBuilder> {
1632
1803
  constructor(id:ODValidId,data:Partial<ODRadioGroupComponentData>){
1633
1804
  const initData: ODRadioGroupComponentData = {required:false,options:[],...data}
1634
- super(id,initData)
1805
+ super(id,"radio-group",initData)
1635
1806
  }
1636
1807
 
1637
1808
  async build(){
@@ -1684,7 +1855,7 @@ export interface ODCheckboxGroupComponentData {
1684
1855
  export class ODCheckboxGroupComponent extends ODComponent<ODCheckboxGroupComponentData,discord.CheckboxGroupBuilder> {
1685
1856
  constructor(id:ODValidId,data:Partial<ODCheckboxGroupComponentData>){
1686
1857
  const initData: ODCheckboxGroupComponentData = {required:false,options:[],...data}
1687
- super(id,initData)
1858
+ super(id,"checkbox-group",initData)
1688
1859
  }
1689
1860
 
1690
1861
  async build(){
@@ -1744,7 +1915,7 @@ export interface ODCheckboxComponentData {
1744
1915
  export class ODCheckboxComponent extends ODComponent<ODCheckboxComponentData,discord.CheckboxBuilder> {
1745
1916
  constructor(id:ODValidId,data:Partial<ODCheckboxComponentData>){
1746
1917
  const initData: ODCheckboxComponentData = {default:false,...data}
1747
- super(id,initData)
1918
+ super(id,"checkbox",initData)
1748
1919
  }
1749
1920
 
1750
1921
  async build(){
@@ -1788,7 +1959,7 @@ export interface ODFileUploadComponentData {
1788
1959
  export class ODFileUploadComponent extends ODComponent<ODFileUploadComponentData,discord.FileUploadBuilder> {
1789
1960
  constructor(id:ODValidId,data:Partial<ODFileUploadComponentData>){
1790
1961
  const initData: ODFileUploadComponentData = {required:false,...data}
1791
- super(id,initData)
1962
+ super(id,"file-upload",initData)
1792
1963
  }
1793
1964
 
1794
1965
  async build(){
@@ -185,6 +185,8 @@ export interface ODSharedFuseList {
185
185
  messageComponentsLoading:boolean,
186
186
  /**Load the default Open Discord modal components. */
187
187
  modalComponentsLoading:boolean,
188
+ /**Load the default Open Discord component modifiers. */
189
+ componentModifiersLoading:boolean,
188
190
 
189
191
  /**Load the default Open Discord command responders. */
190
192
  commandRespondersLoading:boolean,
@@ -323,6 +325,7 @@ export class ODSharedFuseManager extends ODFuseManager<ODSharedFuseList> {
323
325
  sharedComponentsLoading:true,
324
326
  messageComponentsLoading:true,
325
327
  modalComponentsLoading:true,
328
+ componentModifiersLoading:true,
326
329
 
327
330
  commandRespondersLoading:true,
328
331
  buttonRespondersLoading:true,
@@ -9,6 +9,7 @@ import * as discord from "discord.js"
9
9
  import { ODWorkerManager } from "./worker.js"
10
10
 
11
11
  /**## ODVerifyBar `class`
12
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
12
13
  * This is an Open Discord verifybar.
13
14
  *
14
15
  * It is contains 2 sets of workers and a lot of utilities for the (✅ ❌) verifybars in the bot.
@@ -47,14 +48,15 @@ export class ODVerifyBar<SuccessWorkerIds extends string = string,FailureWorkerI
47
48
  }
48
49
 
49
50
  /**## ODVerifyBarManagerIdConstraint `type`
51
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
50
52
  * The constraint/layout for id mappings/interfaces of the `ODVerifyBarManager` class.
51
53
  */
52
54
  export type ODVerifyBarManagerIdConstraint = Record<string,{successWorkerIds:string,failureWorkerIds:string}>
53
55
 
54
56
  /**## ODVerifyBarManager `class`
55
- * This is an Open Discord verifybar manager.
57
+ * @deprecated Use `ODMessageComponentModifier`'s instead.
56
58
  *
57
- * It contains all (✅ ❌) verifybars in the bot.
59
+ * The Open Discord verifybar manager manages all (✅ ❌) verifybars in the bot.
58
60
  * The `ODVerifyBar` classes contain `ODWorkerManager`'s that will be fired when the continue/stop buttons are pressed.
59
61
  *
60
62
  * It doesn't contain the code which activates the verifybars! This should be implemented by your own.
@@ -29,6 +29,11 @@ export class ODWorker<Instance, Origin extends string, Params> extends ODManager
29
29
  this.priority = priority
30
30
  this.callback = callback
31
31
  }
32
+
33
+ /**Duplicate this worker. Warning: If the callback accesses external variables (outside parameters), the clone will still use those variables. This might result in unexpected behaviour! */
34
+ duplicate(newId?:ODValidId): ODWorker<Instance,Origin,Params> {
35
+ return new ODWorker<Instance,Origin,Params>(newId ?? this.id.value,this.priority,this.callback)
36
+ }
32
37
  }
33
38
 
34
39
  /**## ODWorker `class`