@open-discord-bots/framework 0.3.14 → 0.3.15

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.
Files changed (41) hide show
  1. package/dist/api/main.js +1 -1
  2. package/dist/api/modules/responder.js +50 -26
  3. package/package.json +1 -1
  4. package/src/api/index.ts +0 -31
  5. package/src/api/main.ts +0 -203
  6. package/src/api/modules/action.ts +0 -89
  7. package/src/api/modules/base.ts +0 -845
  8. package/src/api/modules/builder.ts +0 -1755
  9. package/src/api/modules/checker.ts +0 -1826
  10. package/src/api/modules/client.ts +0 -2345
  11. package/src/api/modules/code.ts +0 -84
  12. package/src/api/modules/component.ts +0 -2000
  13. package/src/api/modules/config.ts +0 -264
  14. package/src/api/modules/console.ts +0 -697
  15. package/src/api/modules/cooldown.ts +0 -369
  16. package/src/api/modules/database.ts +0 -321
  17. package/src/api/modules/event.ts +0 -123
  18. package/src/api/modules/flag.ts +0 -99
  19. package/src/api/modules/fuse.ts +0 -365
  20. package/src/api/modules/helpmenu.ts +0 -273
  21. package/src/api/modules/language.ts +0 -230
  22. package/src/api/modules/permission.ts +0 -363
  23. package/src/api/modules/plugin.ts +0 -294
  24. package/src/api/modules/post.ts +0 -137
  25. package/src/api/modules/progressbar.ts +0 -370
  26. package/src/api/modules/responder.ts +0 -1625
  27. package/src/api/modules/session.ts +0 -181
  28. package/src/api/modules/startscreen.ts +0 -345
  29. package/src/api/modules/state.ts +0 -298
  30. package/src/api/modules/statistic.ts +0 -380
  31. package/src/api/modules/verifybar.ts +0 -68
  32. package/src/api/modules/worker.ts +0 -119
  33. package/src/cli/editConfig.ts +0 -930
  34. package/src/cli/index.ts +0 -152
  35. package/src/index.ts +0 -8
  36. package/src/startup/compilation.ts +0 -204
  37. package/src/startup/dump.ts +0 -46
  38. package/src/startup/errorHandling.ts +0 -42
  39. package/src/startup/pluginLauncher.ts +0 -265
  40. package/src/utilities/index.ts +0 -229
  41. package/tools/cleanup.js +0 -2
@@ -1,1755 +0,0 @@
1
- ///////////////////////////////////////
2
- //BUILDER MODULE
3
- ///////////////////////////////////////
4
- import { ODId, ODValidButtonColor, ODValidId, ODSystemError, ODInterfaceWithPartialProperty, ODManagerWithSafety, ODManagerData, ODNoGeneric } from "./base.js"
5
- import * as discord from "discord.js"
6
- import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker.js"
7
- import { ODDebugger } from "./console.js"
8
-
9
- /**## ODBuilderImplementation `class`
10
- * This is an Open Discord builder implementation.
11
- *
12
- * It is a basic implementation of the `ODWorkerManager` used by all `ODBuilder` classes.
13
- *
14
- * This class can't be used stand-alone & needs to be extended from!
15
- */
16
- export abstract class ODBuilderImplementation<Instance,Origin extends string,Params,BuildType extends {id:ODId},WorkerIds extends string = string> extends ODManagerData {
17
- /**The manager that has all workers of this implementation */
18
- workers: ODWorkerManager<Instance,Origin,Params,WorkerIds>
19
- /**Cache a build or create it every time from scratch when this.build() gets executed. */
20
- allowCache: boolean = false
21
- /**Did the build already got created/cached? */
22
- didCache: boolean = false
23
- /**The cache of this build. */
24
- cache:BuildType|null = null
25
-
26
- constructor(id:ODValidId, callback?:ODWorkerCallback<Instance,Origin,Params>, priority?:number, callbackId?:ODValidId){
27
- super(id)
28
- this.workers = new ODWorkerManager("ascending")
29
- if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback))
30
- }
31
-
32
- /**Set if caching is allowed */
33
- setCacheMode(allowed:boolean){
34
- this.allowCache = allowed
35
- this.resetCache()
36
- return this
37
- }
38
- /**Reset the current cache */
39
- resetCache(){
40
- this.cache = null
41
- this.didCache = false
42
- return this
43
- }
44
- /**Execute all workers & return the result. */
45
- abstract build(origin:Origin, params:Params): Promise<BuildType>
46
- }
47
-
48
- /**## ODBuilderManager `class`
49
- * This is an Open Discord builder manager.
50
- *
51
- * It contains all Open Discord builders. You can find messages, embeds, files & dropdowns, buttons & modals all here!
52
- *
53
- * Using the Open Discord builder system has a few advantages compared to vanilla discord.js:
54
- * - plugins can extend/edit messages
55
- * - automatically reply on error
56
- * - independent workers (with priority)
57
- * - fail-safe design using try-catch
58
- * - cache frequently used objects
59
- * - get to know the origin of the build request for a specific message, button, etc
60
- * - And so much more!
61
- */
62
- export class ODBuilderManager<
63
- ButtonIdList extends ODButtonManagerIdConstraint = ODButtonManagerIdConstraint,
64
- DropdownIdList extends ODDropdownManagerIdConstraint = ODDropdownManagerIdConstraint,
65
- FileIdList extends ODFileManagerIdConstraint = ODFileManagerIdConstraint,
66
- EmbedIdList extends ODEmbedManagerIdConstraint = ODEmbedManagerIdConstraint,
67
- MessageIdList extends ODMessageManagerIdConstraint = ODMessageManagerIdConstraint,
68
- ModalIdList extends ODModalManagerIdConstraint = ODModalManagerIdConstraint
69
- > {
70
- /**The manager for all button builders */
71
- buttons: ODButtonManager<ButtonIdList>
72
- /**The manager for all dropdown builders */
73
- dropdowns: ODDropdownManager<DropdownIdList>
74
- /**The manager for all file/attachment builders */
75
- files: ODFileManager<FileIdList>
76
- /**The manager for all embed builders */
77
- embeds: ODEmbedManager<EmbedIdList>
78
- /**The manager for all message builders */
79
- messages: ODMessageManager<MessageIdList>
80
- /**The manager for all modal builders */
81
- modals: ODModalManager<ModalIdList>
82
-
83
- constructor(debug:ODDebugger){
84
- this.buttons = new ODButtonManager(debug)
85
- this.dropdowns = new ODDropdownManager(debug)
86
- this.files = new ODFileManager(debug)
87
- this.embeds = new ODEmbedManager(debug)
88
- this.messages = new ODMessageManager(debug)
89
- this.modals = new ODModalManager(debug)
90
- }
91
- }
92
-
93
- /**## ODComponentBuildResult `interface`
94
- * This interface contains the result from a built component (button/dropdown). This can be used in the `ODMessage` builder!
95
- */
96
- export interface ODComponentBuildResult {
97
- /**The id of this component (button or dropdown) */
98
- id:ODId,
99
- /**The discord component or `\n` when it is a spacer between action rows */
100
- component:discord.MessageActionRowComponentBuilder|"\n"|null
101
- }
102
-
103
- /**## ODButtonManagerIdConstraint `type`
104
- * The constraint/layout for id mappings/interfaces of the `ODButtonManager` class.
105
- */
106
- export type ODButtonManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
107
-
108
- /**## ODButtonManager `class`
109
- * This is an Open Discord button manager.
110
- *
111
- * It contains all Open Discord button builders. Here, you can add your own buttons or edit existing ones!
112
- *
113
- * It's recommended to use this system in combination with all the other Open Discord builders!
114
- */
115
- export class ODButtonManager<IdList extends ODButtonManagerIdConstraint = ODButtonManagerIdConstraint> extends ODManagerWithSafety<ODButton<string,{},string>> {
116
- constructor(debug:ODDebugger){
117
- super(() => {
118
- return new ODButton("opendiscord:unknown-button",(instance,params,origin,cancel) => {
119
- instance.setCustomId("od:unknown-button")
120
- instance.setMode("button")
121
- instance.setColor("red")
122
- instance.setLabel("<ODError:Unknown Button>")
123
- instance.setEmoji("✖")
124
- instance.setDisabled(true)
125
- cancel()
126
- })
127
- },debug,"button")
128
- }
129
-
130
- /**Get a newline component for buttons & dropdowns! */
131
- getNewLine(id:ODValidId): ODComponentBuildResult {
132
- return {
133
- id:new ODId(id),
134
- component:"\n"
135
- }
136
- }
137
-
138
- get<ButtonId extends keyof ODNoGeneric<IdList>>(id:ButtonId): ODButton<IdList[ButtonId]["origin"],IdList[ButtonId]["params"],IdList[ButtonId]["workers"]>
139
- get(id:ODValidId): ODButton<string,{},string>|null
140
-
141
- get(id:ODValidId): ODButton<string,{},string>|null {
142
- return super.get(id)
143
- }
144
-
145
- remove<ButtonId extends keyof ODNoGeneric<IdList>>(id:ButtonId): ODButton<IdList[ButtonId]["origin"],IdList[ButtonId]["params"],IdList[ButtonId]["workers"]>
146
- remove(id:ODValidId): ODButton<string,{},string>|null
147
-
148
- remove(id:ODValidId): ODButton<string,{},string>|null {
149
- return super.remove(id)
150
- }
151
-
152
- exists(id:keyof ODNoGeneric<IdList>): boolean
153
- exists(id:ODValidId): boolean
154
-
155
- exists(id:ODValidId): boolean {
156
- return super.exists(id)
157
- }
158
-
159
- getSafe<ButtonId extends keyof ODNoGeneric<IdList>>(id:ButtonId): ODButton<IdList[ButtonId]["origin"],IdList[ButtonId]["params"],IdList[ButtonId]["workers"]>
160
- getSafe(id:ODValidId): ODButton<string,{},string>
161
-
162
- getSafe(id:ODValidId): ODButton<string,{},string> {
163
- return super.getSafe(id)
164
- }
165
- }
166
-
167
- /**## ODButtonData `interface`
168
- * This interface contains the data to build a button.
169
- */
170
- export interface ODButtonData {
171
- /**The custom id of this button */
172
- customId:string,
173
- /**The mode of this button */
174
- mode:"button"|"url",
175
- /**The url for when the mode is set to "url" */
176
- url:string|null,
177
- /**The button color */
178
- color:ODValidButtonColor|null,
179
- /**The button label */
180
- label:string|null,
181
- /**The button emoji */
182
- emoji:string|null,
183
- /**Is the button disabled? */
184
- disabled:boolean
185
- }
186
-
187
- /**## ODButtonInstance `class`
188
- * This is an Open Discord button instance.
189
- *
190
- * It contains all properties & functions to build a button!
191
- */
192
- export class ODButtonInstance {
193
- /**The current data of this button */
194
- data: ODButtonData = {
195
- customId:"",
196
- mode:"button",
197
- url:null,
198
- color:null,
199
- label:null,
200
- emoji:null,
201
- disabled:false
202
- }
203
-
204
- /**Set the custom id of this button */
205
- setCustomId(id:ODButtonData["customId"]){
206
- this.data.customId = id
207
- return this
208
- }
209
- /**Set the mode of this button */
210
- setMode(mode:ODButtonData["mode"]){
211
- this.data.mode = mode
212
- return this
213
- }
214
- /**Set the url of this button */
215
- setUrl(url:ODButtonData["url"]){
216
- this.data.url = url
217
- return this
218
- }
219
- /**Set the color of this button */
220
- setColor(color:ODButtonData["color"]){
221
- this.data.color = color
222
- return this
223
- }
224
- /**Set the label of this button */
225
- setLabel(label:ODButtonData["label"]){
226
- this.data.label = label
227
- return this
228
- }
229
- /**Set the emoji of this button */
230
- setEmoji(emoji:ODButtonData["emoji"]){
231
- this.data.emoji = emoji
232
- return this
233
- }
234
- /**Disable this button */
235
- setDisabled(disabled:ODButtonData["disabled"]){
236
- this.data.disabled = disabled
237
- return this
238
- }
239
- }
240
-
241
- /**## ODButton `class`
242
- * This is an Open Discord button builder.
243
- *
244
- * With this class, you can create a button to use in a message.
245
- * The only difference with normal buttons is that this one can be edited by Open Discord plugins!
246
- *
247
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
248
- */
249
- export class ODButton<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODButtonInstance,Origin,Params,ODComponentBuildResult,WorkerIds> {
250
- /**Build this button & compile it for discord.js */
251
- async build(origin:Origin, params:Params): Promise<ODComponentBuildResult> {
252
- if (this.didCache && this.cache && this.allowCache) return this.cache
253
-
254
- try {
255
- //create instance
256
- const instance = new ODButtonInstance()
257
-
258
- //wait for workers to finish
259
- await this.workers.executeWorkers(instance,origin,params)
260
-
261
- //create the discord.js button
262
- const button = new discord.ButtonBuilder()
263
- if (instance.data.mode == "button") button.setCustomId(instance.data.customId)
264
- if (instance.data.mode == "url") button.setStyle(discord.ButtonStyle.Link)
265
- else if (instance.data.color == "gray") button.setStyle(discord.ButtonStyle.Secondary)
266
- else if (instance.data.color == "blue") button.setStyle(discord.ButtonStyle.Primary)
267
- else if (instance.data.color == "green") button.setStyle(discord.ButtonStyle.Success)
268
- else if (instance.data.color == "red") button.setStyle(discord.ButtonStyle.Danger)
269
- if (instance.data.url) button.setURL(instance.data.url)
270
- if (instance.data.label) button.setLabel(instance.data.label)
271
- if (instance.data.emoji) button.setEmoji(instance.data.emoji)
272
- if (instance.data.disabled) button.setDisabled(instance.data.disabled)
273
- if (!instance.data.emoji && !instance.data.label) button.setLabel(instance.data.customId)
274
-
275
- this.cache = {id:this.id,component:button}
276
- this.didCache = true
277
- return {id:this.id,component:button}
278
- }catch(err){
279
- process.emit("uncaughtException",new ODSystemError("ODButton:build(\""+this.id.value+"\") => Major Error (see next error)"))
280
- process.emit("uncaughtException",err)
281
- return {id:this.id,component:null}
282
- }
283
- }
284
- }
285
-
286
- /**## ODQuickButton `class`
287
- * This is an Open Discord quick button builder.
288
- *
289
- * With this class, you can quickly create a button to use in a message.
290
- * This quick button can be used by Open Discord plugins instead of the normal builders to speed up the process!
291
- *
292
- * Because of the quick functionality, these buttons are less customisable by other plugins.
293
- */
294
- export class ODQuickButton {
295
- /**The id of this button. */
296
- id: ODId
297
- /**The current data of this button */
298
- data: Partial<ODButtonData>
299
-
300
- constructor(id:ODValidId,data:Partial<ODButtonData>){
301
- this.id = new ODId(id)
302
- this.data = data
303
- }
304
-
305
- /**Build this button & compile it for discord.js */
306
- async build(): Promise<ODComponentBuildResult> {
307
- try {
308
- //create the discord.js button
309
- const button = new discord.ButtonBuilder()
310
- if (this.data.mode == "button" || (!this.data.mode && this.data.customId)) button.setCustomId(this.data.customId ?? "od:unknown-button")
311
- if (this.data.mode == "url") button.setStyle(discord.ButtonStyle.Link)
312
- else if (this.data.color == "gray") button.setStyle(discord.ButtonStyle.Secondary)
313
- else if (this.data.color == "blue") button.setStyle(discord.ButtonStyle.Primary)
314
- else if (this.data.color == "green") button.setStyle(discord.ButtonStyle.Success)
315
- else if (this.data.color == "red") button.setStyle(discord.ButtonStyle.Danger)
316
- else button.setStyle(discord.ButtonStyle.Secondary)
317
- if (this.data.url) button.setURL(this.data.url)
318
- if (this.data.label) button.setLabel(this.data.label)
319
- if (this.data.emoji) button.setEmoji(this.data.emoji)
320
- if (this.data.disabled) button.setDisabled(this.data.disabled)
321
- if (!this.data.emoji && !this.data.label) button.setLabel(this.data.customId ?? "od:unknown-button")
322
-
323
- return {id:this.id,component:button}
324
- }catch(err){
325
- process.emit("uncaughtException",new ODSystemError("ODQuickButton:build(\""+this.id.value+"\") => Major Error (see next error)"))
326
- process.emit("uncaughtException",err)
327
- return {id:this.id,component:null}
328
- }
329
- }
330
- }
331
-
332
- /**## ODDropdownManagerIdConstraint `type`
333
- * The constraint/layout for id mappings/interfaces of the `ODDropdownManager` class.
334
- */
335
- export type ODDropdownManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
336
-
337
- /**## ODDropdownManager `class`
338
- * This is an Open Discord dropdown manager.
339
- *
340
- * It contains all Open Discord dropdown builders. Here, you can add your own dropdowns or edit existing ones!
341
- *
342
- * It's recommended to use this system in combination with all the other Open Discord builders!
343
- */
344
- export class ODDropdownManager<IdList extends ODDropdownManagerIdConstraint = ODDropdownManagerIdConstraint> extends ODManagerWithSafety<ODDropdown<string,{},string>> {
345
- constructor(debug:ODDebugger){
346
- super(() => {
347
- return new ODDropdown("opendiscord:unknown-dropdown",(instance,params,origin,cancel) => {
348
- instance.setCustomId("od:unknown-dropdown")
349
- instance.setType("string")
350
- instance.setPlaceholder("❌ <ODError:Unknown Dropdown>")
351
- instance.setDisabled(true)
352
- instance.setOptions([
353
- {emoji:"❌",label:"<ODError:Unknown Dropdown>",value:"error"}
354
- ])
355
- cancel()
356
- })
357
- },debug,"dropdown")
358
- }
359
-
360
- /**Get a newline component for buttons & dropdowns! */
361
- getNewLine(id:ODValidId): ODComponentBuildResult {
362
- return {
363
- id:new ODId(id),
364
- component:"\n"
365
- }
366
- }
367
-
368
- get<DropdownId extends keyof ODNoGeneric<IdList>>(id:DropdownId): ODDropdown<IdList[DropdownId]["origin"],IdList[DropdownId]["params"],IdList[DropdownId]["workers"]>
369
- get(id:ODValidId): ODDropdown<string,{},string>|null
370
-
371
- get(id:ODValidId): ODDropdown<string,{},string>|null {
372
- return super.get(id)
373
- }
374
-
375
- remove<DropdownId extends keyof ODNoGeneric<IdList>>(id:DropdownId): ODDropdown<IdList[DropdownId]["origin"],IdList[DropdownId]["params"],IdList[DropdownId]["workers"]>
376
- remove(id:ODValidId): ODDropdown<string,{},string>|null
377
-
378
- remove(id:ODValidId): ODDropdown<string,{},string>|null {
379
- return super.remove(id)
380
- }
381
-
382
- exists(id:keyof ODNoGeneric<IdList>): boolean
383
- exists(id:ODValidId): boolean
384
-
385
- exists(id:ODValidId): boolean {
386
- return super.exists(id)
387
- }
388
-
389
- getSafe<DropdownId extends keyof ODNoGeneric<IdList>>(id:DropdownId): ODDropdown<IdList[DropdownId]["origin"],IdList[DropdownId]["params"],IdList[DropdownId]["workers"]>
390
- getSafe(id:ODValidId): ODDropdown<string,{},string>
391
-
392
- getSafe(id:ODValidId): ODDropdown<string,{},string> {
393
- return super.getSafe(id)
394
- }
395
- }
396
-
397
- /**## ODDropdownData `interface`
398
- * This interface contains the data to build a dropdown.
399
- */
400
- export interface ODDropdownData {
401
- /**The custom id of this dropdown */
402
- customId:string,
403
- /**The type of this dropdown */
404
- type:"string"|"role"|"channel"|"user"|"mentionable",
405
- /**The placeholder of this dropdown */
406
- placeholder:string|null,
407
- /**The minimum amount of items to be selected in this dropdown */
408
- minValues:number|null,
409
- /**The maximum amount of items to be selected in this dropdown */
410
- maxValues:number|null,
411
- /**Is this dropdown disabled? */
412
- disabled:boolean,
413
- /**Allowed channel types when the type is "channel" */
414
- channelTypes:discord.ChannelType[]
415
-
416
- /**The options when the type is "string" */
417
- options:discord.SelectMenuComponentOptionData[],
418
- /**The options when the type is "user" */
419
- users:discord.User[],
420
- /**The options when the type is "role" */
421
- roles:discord.Role[],
422
- /**The options when the type is "channel" */
423
- channels:discord.Channel[],
424
- /**The options when the type is "mentionable" */
425
- mentionables:(discord.User|discord.Role)[],
426
- }
427
-
428
- /**## ODDropdownInstance `class`
429
- * This is an Open Discord dropdown instance.
430
- *
431
- * It contains all properties & functions to build a dropdown!
432
- */
433
- export class ODDropdownInstance {
434
- /**The current data of this dropdown */
435
- data: ODDropdownData = {
436
- customId:"",
437
- type:"string",
438
- placeholder:null,
439
- minValues:null,
440
- maxValues:null,
441
- disabled:false,
442
- channelTypes:[],
443
-
444
- options:[],
445
- users:[],
446
- roles:[],
447
- channels:[],
448
- mentionables:[]
449
- }
450
-
451
- /**Set the custom id of this dropdown */
452
- setCustomId(id:ODDropdownData["customId"]){
453
- this.data.customId = id
454
- return this
455
- }
456
- /**Set the type of this dropdown */
457
- setType(type:ODDropdownData["type"]){
458
- this.data.type = type
459
- return this
460
- }
461
- /**Set the placeholder of this dropdown */
462
- setPlaceholder(placeholder:ODDropdownData["placeholder"]){
463
- this.data.placeholder = placeholder
464
- return this
465
- }
466
- /**Set the minimum amount of values in this dropdown */
467
- setMinValues(minValues:ODDropdownData["minValues"]){
468
- this.data.minValues = minValues
469
- return this
470
- }
471
- /**Set the maximum amount of values ax this dropdown */
472
- setMaxValues(maxValues:ODDropdownData["maxValues"]){
473
- this.data.maxValues = maxValues
474
- return this
475
- }
476
- /**Set the disabled of this dropdown */
477
- setDisabled(disabled:ODDropdownData["disabled"]){
478
- this.data.disabled = disabled
479
- return this
480
- }
481
- /**Set the channel types of this dropdown */
482
- setChannelTypes(channelTypes:ODDropdownData["channelTypes"]){
483
- this.data.channelTypes = channelTypes
484
- return this
485
- }
486
- /**Set the options of this dropdown (when `type == "string"`) */
487
- setOptions(options:ODDropdownData["options"]){
488
- this.data.options = options
489
- return this
490
- }
491
- /**Set the users of this dropdown (when `type == "user"`) */
492
- setUsers(users:ODDropdownData["users"]){
493
- this.data.users = users
494
- return this
495
- }
496
- /**Set the roles of this dropdown (when `type == "role"`) */
497
- setRoles(roles:ODDropdownData["roles"]){
498
- this.data.roles = roles
499
- return this
500
- }
501
- /**Set the channels of this dropdown (when `type == "channel"`) */
502
- setChannels(channels:ODDropdownData["channels"]){
503
- this.data.channels = channels
504
- return this
505
- }
506
- /**Set the mentionables of this dropdown (when `type == "mentionable"`) */
507
- setMentionables(mentionables:ODDropdownData["mentionables"]){
508
- this.data.mentionables = mentionables
509
- return this
510
- }
511
- }
512
-
513
- /**## ODDropdown `class`
514
- * This is an Open Discord dropdown builder.
515
- *
516
- * With this class, you can create a dropdown to use in a message.
517
- * The only difference with normal dropdowns is that this one can be edited by Open Discord plugins!
518
- *
519
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
520
- */
521
- export class ODDropdown<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODDropdownInstance,Origin,Params,ODComponentBuildResult,WorkerIds> {
522
- /**Build this dropdown & compile it for discord.js */
523
- async build(origin:Origin, params:Params): Promise<ODComponentBuildResult> {
524
- if (this.didCache && this.cache && this.allowCache) return this.cache
525
-
526
- try{
527
- //create instance
528
- const instance = new ODDropdownInstance()
529
-
530
- //wait for workers to finish
531
- await this.workers.executeWorkers(instance,origin,params)
532
-
533
- //create the discord.js dropdown
534
- if (instance.data.type == "string"){
535
- const dropdown = new discord.StringSelectMenuBuilder()
536
- dropdown.setCustomId(instance.data.customId)
537
- dropdown.setOptions(...instance.data.options)
538
- if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder)
539
- if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues)
540
- if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues)
541
- if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled)
542
-
543
- this.cache = {id:this.id,component:dropdown}
544
- this.didCache = true
545
- return {id:this.id,component:dropdown}
546
-
547
- }else if (instance.data.type == "user"){
548
- const dropdown = new discord.UserSelectMenuBuilder()
549
- dropdown.setCustomId(instance.data.customId)
550
- if (instance.data.users.length > 0) dropdown.setDefaultUsers(...instance.data.users.map((u) => u.id))
551
- if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder)
552
- if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues)
553
- if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues)
554
- if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled)
555
-
556
- this.cache = {id:this.id,component:dropdown}
557
- this.didCache = true
558
- return {id:this.id,component:dropdown}
559
-
560
- }else if (instance.data.type == "role"){
561
- const dropdown = new discord.RoleSelectMenuBuilder()
562
- dropdown.setCustomId(instance.data.customId)
563
- if (instance.data.roles.length > 0) dropdown.setDefaultRoles(...instance.data.roles.map((r) => r.id))
564
- if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder)
565
- if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues)
566
- if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues)
567
- if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled)
568
-
569
- this.cache = {id:this.id,component:dropdown}
570
- this.didCache = true
571
- return {id:this.id,component:dropdown}
572
-
573
- }else if (instance.data.type == "channel"){
574
- const dropdown = new discord.ChannelSelectMenuBuilder()
575
- dropdown.setCustomId(instance.data.customId)
576
- if (instance.data.channels.length > 0) dropdown.setDefaultChannels(...instance.data.channels.map((c) => c.id))
577
- if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder)
578
- if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues)
579
- if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues)
580
- if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled)
581
-
582
- this.cache = {id:this.id,component:dropdown}
583
- this.didCache = true
584
- return {id:this.id,component:dropdown}
585
-
586
- }else if (instance.data.type == "mentionable"){
587
- const dropdown = new discord.MentionableSelectMenuBuilder()
588
-
589
- const values: ({type:discord.SelectMenuDefaultValueType.User,id:string}|{type:discord.SelectMenuDefaultValueType.Role,id:string})[] = []
590
- instance.data.mentionables.forEach((m) => {
591
- if (m instanceof discord.User){
592
- values.push({type:discord.SelectMenuDefaultValueType.User,id:m.id})
593
- }else{
594
- values.push({type:discord.SelectMenuDefaultValueType.Role,id:m.id})
595
- }
596
- })
597
-
598
- dropdown.setCustomId(instance.data.customId)
599
- if (instance.data.mentionables.length > 0) dropdown.setDefaultValues(...values)
600
- if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder)
601
- if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues)
602
- if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues)
603
- if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled)
604
-
605
- this.cache = {id:this.id,component:dropdown}
606
- this.didCache = true
607
- return {id:this.id,component:dropdown}
608
- }else{
609
- throw new Error("Tried to build an ODDropdown with unknown type!")
610
- }
611
- }catch(err){
612
- process.emit("uncaughtException",new ODSystemError("ODDropdown:build(\""+this.id.value+"\") => Major Error (see next error)"))
613
- process.emit("uncaughtException",err)
614
- return {id:this.id,component:null}
615
- }
616
- }
617
- }
618
-
619
- /**## ODQuickDropdown `class`
620
- * This is an Open Discord quick dropdown builder.
621
- *
622
- * With this class, you can quickly create a dropdown to use in a message.
623
- * This quick dropdown can be used by Open Discord plugins instead of the normal builders to speed up the process!
624
- *
625
- * Because of the quick functionality, these dropdowns are less customisable by other plugins.
626
- */
627
- export class ODQuickDropdown {
628
- /**The id of this dropdown. */
629
- id: ODId
630
- /**The current data of this dropdown */
631
- data: Partial<ODDropdownData>
632
-
633
- constructor(id:ODValidId,data:Partial<ODDropdownData>){
634
- this.id = new ODId(id)
635
- this.data = data
636
- }
637
-
638
- /**Build this dropdown & compile it for discord.js */
639
- async build(): Promise<ODComponentBuildResult> {
640
- try{
641
- //create the discord.js dropdown
642
- if (this.data.type == "string"){
643
- if (!this.data.options) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 option to be present.")
644
- const dropdown = new discord.StringSelectMenuBuilder()
645
- dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
646
- dropdown.setOptions(...this.data.options)
647
- if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
648
- if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
649
- if (this.data.maxValues) dropdown.setMaxValues(this.data.maxValues)
650
- if (this.data.disabled) dropdown.setDisabled(this.data.disabled)
651
-
652
- return {id:this.id,component:dropdown}
653
-
654
- }else if (this.data.type == "user"){
655
- if (!this.data.users) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 user option to be present.")
656
- const dropdown = new discord.UserSelectMenuBuilder()
657
- dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
658
- if (this.data.users.length > 0) dropdown.setDefaultUsers(...this.data.users.map((u) => u.id))
659
- if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
660
- if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
661
- if (this.data.maxValues) dropdown.setMaxValues(this.data.maxValues)
662
- if (this.data.disabled) dropdown.setDisabled(this.data.disabled)
663
-
664
- return {id:this.id,component:dropdown}
665
-
666
- }else if (this.data.type == "role"){
667
- if (!this.data.roles) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 role option to be present.")
668
- const dropdown = new discord.RoleSelectMenuBuilder()
669
- dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
670
- if (this.data.roles.length > 0) dropdown.setDefaultRoles(...this.data.roles.map((r) => r.id))
671
- if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
672
- if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
673
- if (this.data.maxValues) dropdown.setMaxValues(this.data.maxValues)
674
- if (this.data.disabled) dropdown.setDisabled(this.data.disabled)
675
-
676
- return {id:this.id,component:dropdown}
677
-
678
- }else if (this.data.type == "channel"){
679
- if (!this.data.channels) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 channel option to be present.")
680
- const dropdown = new discord.ChannelSelectMenuBuilder()
681
- dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
682
- if (this.data.channels.length > 0) dropdown.setDefaultChannels(...this.data.channels.map((c) => c.id))
683
- if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
684
- if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
685
- if (this.data.maxValues) dropdown.setMaxValues(this.data.maxValues)
686
- if (this.data.disabled) dropdown.setDisabled(this.data.disabled)
687
-
688
- return {id:this.id,component:dropdown}
689
-
690
- }else if (this.data.type == "mentionable"){
691
- if (!this.data.mentionables) throw new ODSystemError("ODQuickDropdown:build(): "+this.id.value+" => Dropdown requires at least 1 mentionable option to be present.")
692
- const dropdown = new discord.MentionableSelectMenuBuilder()
693
-
694
- const values: ({type:discord.SelectMenuDefaultValueType.User,id:string}|{type:discord.SelectMenuDefaultValueType.Role,id:string})[] = []
695
- this.data.mentionables.forEach((m) => {
696
- if (m instanceof discord.User){
697
- values.push({type:discord.SelectMenuDefaultValueType.User,id:m.id})
698
- }else{
699
- values.push({type:discord.SelectMenuDefaultValueType.Role,id:m.id})
700
- }
701
- })
702
-
703
- dropdown.setCustomId(this.data.customId ?? "od:unknown-dropdown")
704
- if (this.data.mentionables.length > 0) dropdown.setDefaultValues(...values)
705
- if (this.data.placeholder) dropdown.setPlaceholder(this.data.placeholder)
706
- if (this.data.minValues) dropdown.setMinValues(this.data.minValues)
707
- if (this.data.maxValues) dropdown.setMaxValues(this.data.maxValues)
708
- if (this.data.disabled) dropdown.setDisabled(this.data.disabled)
709
-
710
- return {id:this.id,component:dropdown}
711
- }else{
712
- throw new Error("Tried to build an ODQuickDropdown with unknown type!")
713
- }
714
- }catch(err){
715
- process.emit("uncaughtException",new ODSystemError("ODQuickDropdown:build(\""+this.id.value+"\") => Major Error (see next error)"))
716
- process.emit("uncaughtException",err)
717
- return {id:this.id,component:null}
718
- }
719
- }
720
- }
721
-
722
- /**## ODFileManagerIdConstraint `type`
723
- * The constraint/layout for id mappings/interfaces of the `ODFileManager` class.
724
- */
725
- export type ODFileManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
726
-
727
- /**## ODFileManager `class`
728
- * This is an Open Discord file manager.
729
- *
730
- * It contains all Open Discord file builders. Here, you can add your own files or edit existing ones!
731
- *
732
- * It's recommended to use this system in combination with all the other Open Discord builders!
733
- */
734
- export class ODFileManager<IdList extends ODFileManagerIdConstraint = ODFileManagerIdConstraint> extends ODManagerWithSafety<ODFile<string,{},string>> {
735
- constructor(debug:ODDebugger){
736
- super(() => {
737
- return new ODFile("opendiscord:unknown-file",(instance,params,origin,cancel) => {
738
- instance.setName("opendiscord_unknown-file.txt")
739
- instance.setDescription("❌ <ODError:Unknown File>")
740
- instance.setContents("Couldn't find file in registery `opendiscord.builders.files`")
741
- cancel()
742
- })
743
- },debug,"file")
744
- }
745
-
746
- get<FileId extends keyof ODNoGeneric<IdList>>(id:FileId): ODFile<IdList[FileId]["origin"],IdList[FileId]["params"],IdList[FileId]["workers"]>
747
- get(id:ODValidId): ODFile<string,{},string>|null
748
-
749
- get(id:ODValidId): ODFile<string,{},string>|null {
750
- return super.get(id)
751
- }
752
-
753
- remove<FileId extends keyof ODNoGeneric<IdList>>(id:FileId): ODFile<IdList[FileId]["origin"],IdList[FileId]["params"],IdList[FileId]["workers"]>
754
- remove(id:ODValidId): ODFile<string,{},string>|null
755
-
756
- remove(id:ODValidId): ODFile<string,{},string>|null {
757
- return super.remove(id)
758
- }
759
-
760
- exists(id:keyof ODNoGeneric<IdList>): boolean
761
- exists(id:ODValidId): boolean
762
-
763
- exists(id:ODValidId): boolean {
764
- return super.exists(id)
765
- }
766
-
767
- getSafe<FileId extends keyof ODNoGeneric<IdList>>(id:FileId): ODFile<IdList[FileId]["origin"],IdList[FileId]["params"],IdList[FileId]["workers"]>
768
- getSafe(id:ODValidId): ODFile<string,{},string>
769
-
770
- getSafe(id:ODValidId): ODFile<string,{},string> {
771
- return super.getSafe(id)
772
- }
773
- }
774
-
775
- /**## ODFileData `interface`
776
- * This interface contains the data to build a file.
777
- */
778
- export interface ODFileData {
779
- /**The file buffer, string or raw data */
780
- file:discord.BufferResolvable
781
- /**The name of the file */
782
- name:string,
783
- /**The description of the file */
784
- description:string|null,
785
- /**Set the file to be a spoiler */
786
- spoiler:boolean
787
- }
788
-
789
- /**## ODFileBuildResult `interface`
790
- * This interface contains the result from a built file (attachment). This can be used in the `ODMessage` builder!
791
- */
792
- export interface ODFileBuildResult {
793
- /**The id of this file */
794
- id:ODId,
795
- /**The discord file */
796
- file:discord.AttachmentBuilder|null
797
- }
798
-
799
- /**## ODFileInstance `class`
800
- * This is an Open Discord file instance.
801
- *
802
- * It contains all properties & functions to build a file!
803
- */
804
- export class ODFileInstance {
805
- /**The current data of this file */
806
- data: ODFileData = {
807
- file:"",
808
- name:"file.txt",
809
- description:null,
810
- spoiler:false
811
- }
812
-
813
- /**Set the file path of this attachment */
814
- setFile(file:string){
815
- this.data.file = file
816
- return this
817
- }
818
- /**Set the file contents of this attachment */
819
- setContents(contents:string|Buffer){
820
- this.data.file = (typeof contents == "string") ? Buffer.from(contents) : contents
821
- return this
822
- }
823
- /**Set the name of this attachment */
824
- setName(name:ODFileData["name"]){
825
- this.data.name = name
826
- return this
827
- }
828
- /**Set the description of this attachment */
829
- setDescription(description:ODFileData["description"]){
830
- this.data.description = description
831
- return this
832
- }
833
- /**Set this attachment to show as a spoiler */
834
- setSpoiler(spoiler:ODFileData["spoiler"]){
835
- this.data.spoiler = spoiler
836
- return this
837
- }
838
- }
839
-
840
- /**## ODFile `class`
841
- * This is an Open Discord file builder.
842
- *
843
- * With this class, you can create a file to use in a message.
844
- * The only difference with normal files is that this one can be edited by Open Discord plugins!
845
- *
846
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
847
- */
848
- export class ODFile<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODFileInstance,Origin,Params,ODFileBuildResult,WorkerIds> {
849
- /**Build this attachment & compile it for discord.js */
850
- async build(origin:Origin, params:Params): Promise<ODFileBuildResult> {
851
- if (this.didCache && this.cache && this.allowCache) return this.cache
852
-
853
- try{
854
- //create instance
855
- const instance = new ODFileInstance()
856
-
857
- //wait for workers to finish
858
- await this.workers.executeWorkers(instance,origin,params)
859
-
860
- //create the discord.js attachment
861
- const file = new discord.AttachmentBuilder(instance.data.file)
862
- file.setName(instance.data.name ? instance.data.name : "file.txt")
863
- if (instance.data.description) file.setDescription(instance.data.description)
864
- if (instance.data.spoiler) file.setSpoiler(instance.data.spoiler)
865
-
866
-
867
- this.cache = {id:this.id,file}
868
- this.didCache = true
869
- return {id:this.id,file}
870
- }catch(err){
871
- process.emit("uncaughtException",new ODSystemError("ODFile:build(\""+this.id.value+"\") => Major Error (see next error)"))
872
- process.emit("uncaughtException",err)
873
- return {id:this.id,file:null}
874
- }
875
- }
876
- }
877
-
878
- /**## ODQuickFile `class`
879
- * This is an Open Discord quick file builder.
880
- *
881
- * With this class, you can quickly create a file to use in a message.
882
- * This quick file can be used by Open Discord plugins instead of the normal builders to speed up the process!
883
- *
884
- * Because of the quick functionality, these files are less customisable by other plugins.
885
- */
886
- export class ODQuickFile {
887
- /**The id of this file. */
888
- id: ODId
889
- /**The current data of this file */
890
- data: Partial<ODFileData>
891
-
892
- constructor(id:ODValidId,data:Partial<ODFileData>){
893
- this.id = new ODId(id)
894
- this.data = data
895
- }
896
-
897
- /**Build this attachment & compile it for discord.js */
898
- async build(): Promise<ODFileBuildResult> {
899
- try{
900
- //create the discord.js attachment
901
- const file = new discord.AttachmentBuilder(this.data.file ?? "<empty-file>")
902
- file.setName(this.data.name ? this.data.name : "file.txt")
903
- if (this.data.description) file.setDescription(this.data.description)
904
- if (this.data.spoiler) file.setSpoiler(this.data.spoiler)
905
-
906
- return {id:this.id,file}
907
- }catch(err){
908
- process.emit("uncaughtException",new ODSystemError("ODQuickFile:build(\""+this.id.value+"\") => Major Error (see next error)"))
909
- process.emit("uncaughtException",err)
910
- return {id:this.id,file:null}
911
- }
912
- }
913
- }
914
-
915
- /**## ODEmbedManagerIdConstraint `type`
916
- * The constraint/layout for id mappings/interfaces of the `ODEmbedManager` class.
917
- */
918
- export type ODEmbedManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
919
-
920
- /**## ODEmbedManager `class`
921
- * This is an Open Discord embed manager.
922
- *
923
- * It contains all Open Discord embed builders. Here, you can add your own embeds or edit existing ones!
924
- *
925
- * It's recommended to use this system in combination with all the other Open Discord builders!
926
- */
927
- export class ODEmbedManager<IdList extends ODEmbedManagerIdConstraint = ODEmbedManagerIdConstraint> extends ODManagerWithSafety<ODEmbed<string,{},string>> {
928
- constructor(debug:ODDebugger){
929
- super(() => {
930
- return new ODEmbed("opendiscord:unknown-embed",(instance,params,origin,cancel) => {
931
- instance.setFooter("opendiscord:unknown-embed")
932
- instance.setColor("#ff0000")
933
- instance.setTitle("❌ <ODError:Unknown Embed>")
934
- instance.setDescription("Couldn't find embed in registery `opendiscord.builders.embeds`")
935
- cancel()
936
- })
937
- },debug,"embed")
938
- }
939
-
940
- get<EmbedId extends keyof ODNoGeneric<IdList>>(id:EmbedId): ODEmbed<IdList[EmbedId]["origin"],IdList[EmbedId]["params"],IdList[EmbedId]["workers"]>
941
- get(id:ODValidId): ODEmbed<string,{},string>|null
942
-
943
- get(id:ODValidId): ODEmbed<string,{},string>|null {
944
- return super.get(id)
945
- }
946
-
947
- remove<EmbedId extends keyof ODNoGeneric<IdList>>(id:EmbedId): ODEmbed<IdList[EmbedId]["origin"],IdList[EmbedId]["params"],IdList[EmbedId]["workers"]>
948
- remove(id:ODValidId): ODEmbed<string,{},string>|null
949
-
950
- remove(id:ODValidId): ODEmbed<string,{},string>|null {
951
- return super.remove(id)
952
- }
953
-
954
- exists(id:keyof ODNoGeneric<IdList>): boolean
955
- exists(id:ODValidId): boolean
956
-
957
- exists(id:ODValidId): boolean {
958
- return super.exists(id)
959
- }
960
-
961
- getSafe<EmbedId extends keyof ODNoGeneric<IdList>>(id:EmbedId): ODEmbed<IdList[EmbedId]["origin"],IdList[EmbedId]["params"],IdList[EmbedId]["workers"]>
962
- getSafe(id:ODValidId): ODEmbed<string,{},string>
963
-
964
- getSafe(id:ODValidId): ODEmbed<string,{},string> {
965
- return super.getSafe(id)
966
- }
967
- }
968
-
969
- /**## ODEmbedData `interface`
970
- * This interface contains the data to build an embed.
971
- */
972
- export interface ODEmbedData {
973
- /**The title of the embed */
974
- title:string|null,
975
- /**The color of the embed */
976
- color:discord.ColorResolvable|string|null,
977
- /**The url of the embed */
978
- url:string|null,
979
- /**The description of the embed */
980
- description:string|null,
981
- /**The author text of the embed */
982
- authorText:string|null,
983
- /**The author image of the embed */
984
- authorImage:string|null,
985
- /**The author url of the embed */
986
- authorUrl:string|null,
987
- /**The footer text of the embed */
988
- footerText:string|null,
989
- /**The footer image of the embed */
990
- footerImage:string|null,
991
- /**The image of the embed */
992
- image:string|null,
993
- /**The thumbnail of the embed */
994
- thumbnail:string|null,
995
- /**The fields of the embed */
996
- fields:ODInterfaceWithPartialProperty<discord.EmbedField,"inline">[],
997
- /**The timestamp of the embed */
998
- timestamp:number|Date|null
999
- }
1000
-
1001
- /**## ODEmbedBuildResult `interface`
1002
- * This interface contains the result from a built embed. This can be used in the `ODMessage` builder!
1003
- */
1004
- export interface ODEmbedBuildResult {
1005
- /**The id of this embed */
1006
- id:ODId,
1007
- /**The discord embed */
1008
- embed:discord.EmbedBuilder|null
1009
- }
1010
-
1011
- /**## ODEmbedInstance `class`
1012
- * This is an Open Discord embed instance.
1013
- *
1014
- * It contains all properties & functions to build an embed!
1015
- */
1016
- export class ODEmbedInstance {
1017
- /**The current data of this embed */
1018
- data: ODEmbedData = {
1019
- title:null,
1020
- color:null,
1021
- url:null,
1022
- description:null,
1023
- authorText:null,
1024
- authorImage:null,
1025
- authorUrl:null,
1026
- footerText:null,
1027
- footerImage:null,
1028
- image:null,
1029
- thumbnail:null,
1030
- fields:[],
1031
- timestamp:null
1032
- }
1033
-
1034
- /**Set the title of this embed */
1035
- setTitle(title:ODEmbedData["title"]){
1036
- this.data.title = title
1037
- return this
1038
- }
1039
- /**Set the color of this embed */
1040
- setColor(color:ODEmbedData["color"]){
1041
- this.data.color = color
1042
- return this
1043
- }
1044
- /**Set the url of this embed */
1045
- setUrl(url:ODEmbedData["url"]){
1046
- this.data.url = url
1047
- return this
1048
- }
1049
- /**Set the description of this embed */
1050
- setDescription(description:ODEmbedData["description"]){
1051
- this.data.description = description
1052
- return this
1053
- }
1054
- /**Set the author of this embed */
1055
- setAuthor(text:ODEmbedData["authorText"], image?:ODEmbedData["authorImage"], url?:ODEmbedData["authorUrl"]){
1056
- this.data.authorText = text
1057
- this.data.authorImage = image ?? null
1058
- this.data.authorUrl = url ?? null
1059
- return this
1060
- }
1061
- /**Set the footer of this embed */
1062
- setFooter(text:ODEmbedData["footerText"], image?:ODEmbedData["footerImage"]){
1063
- this.data.footerText = text
1064
- this.data.footerImage = image ?? null
1065
- return this
1066
- }
1067
- /**Set the image of this embed */
1068
- setImage(image:ODEmbedData["image"]){
1069
- this.data.image = image
1070
- return this
1071
- }
1072
- /**Set the thumbnail of this embed */
1073
- setThumbnail(thumbnail:ODEmbedData["thumbnail"]){
1074
- this.data.thumbnail = thumbnail
1075
- return this
1076
- }
1077
- /**Set the fields of this embed */
1078
- setFields(fields:ODEmbedData["fields"]){
1079
- //TEMP CHECKS
1080
- fields.forEach((field,index) => {
1081
- if (field.value.length >= 1024) throw new ODSystemError("ODEmbed:setFields() => field "+index+" reached 1024 character limit!")
1082
- if (field.name.length >= 256) throw new ODSystemError("ODEmbed:setFields() => field "+index+" reached 256 name character limit!")
1083
- })
1084
-
1085
- this.data.fields = fields
1086
- return this
1087
- }
1088
- /**Add fields to this embed */
1089
- addFields(...fields:ODEmbedData["fields"]){
1090
- //TEMP CHECKS
1091
- fields.forEach((field,index) => {
1092
- if (field.value.length >= 1024) throw new ODSystemError("ODEmbed:addFields() => field "+index+" reached 1024 character limit!")
1093
- if (field.name.length >= 256) throw new ODSystemError("ODEmbed:addFields() => field "+index+" reached 256 name character limit!")
1094
- })
1095
-
1096
- this.data.fields.push(...fields)
1097
- return this
1098
- }
1099
- /**Clear all fields from this embed */
1100
- clearFields(){
1101
- this.data.fields = []
1102
- return this
1103
- }
1104
- /**Set the timestamp of this embed */
1105
- setTimestamp(timestamp:ODEmbedData["timestamp"]){
1106
- this.data.timestamp = timestamp
1107
- return this
1108
- }
1109
- }
1110
-
1111
- /**## ODEmbed `class`
1112
- * This is an Open Discord embed builder.
1113
- *
1114
- * With this class, you can create a embed to use in a message.
1115
- * The only difference with normal embeds is that this one can be edited by Open Discord plugins!
1116
- *
1117
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
1118
- */
1119
- export class ODEmbed<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODEmbedInstance,Origin,Params,ODEmbedBuildResult,WorkerIds> {
1120
- /**Build this embed & compile it for discord.js */
1121
- async build(origin:Origin, params:Params): Promise<ODEmbedBuildResult> {
1122
- if (this.didCache && this.cache && this.allowCache) return this.cache
1123
-
1124
- try{
1125
- //create instance
1126
- const instance = new ODEmbedInstance()
1127
-
1128
- //wait for workers to finish
1129
- await this.workers.executeWorkers(instance,origin,params)
1130
-
1131
- //create the discord.js embed
1132
- const embed = new discord.EmbedBuilder()
1133
- if (instance.data.title) embed.setTitle(instance.data.title)
1134
- if (instance.data.color) embed.setColor(instance.data.color as discord.ColorResolvable)
1135
- if (instance.data.url) embed.setURL(instance.data.url)
1136
- if (instance.data.description) embed.setDescription(instance.data.description)
1137
- if (instance.data.authorText) embed.setAuthor({
1138
- name:instance.data.authorText,
1139
- iconURL:instance.data.authorImage ?? undefined,
1140
- url:instance.data.authorUrl ?? undefined
1141
- })
1142
- if (instance.data.footerText) embed.setFooter({
1143
- text:instance.data.footerText,
1144
- iconURL:instance.data.footerImage ?? undefined,
1145
- })
1146
- if (instance.data.image) embed.setImage(instance.data.image)
1147
- if (instance.data.thumbnail) embed.setThumbnail(instance.data.thumbnail)
1148
- if (instance.data.timestamp) embed.setTimestamp(instance.data.timestamp)
1149
- if (instance.data.fields.length > 0) embed.setFields(instance.data.fields)
1150
-
1151
- this.cache = {id:this.id,embed}
1152
- this.didCache = true
1153
- return {id:this.id,embed}
1154
- }catch(err){
1155
- process.emit("uncaughtException",new ODSystemError("ODEmbed:build(\""+this.id.value+"\") => Major Error (see next error)"))
1156
- process.emit("uncaughtException",err)
1157
- return {id:this.id,embed:null}
1158
- }
1159
- }
1160
- }
1161
-
1162
- /**## ODQuickEmbed `class`
1163
- * This is an Open Discord quick embed builder.
1164
- *
1165
- * With this class, you can quickly create a embed to use in a message.
1166
- * This quick embed can be used by Open Discord plugins instead of the normal builders to speed up the process!
1167
- *
1168
- * Because of the quick functionality, these embeds are less customisable by other plugins.
1169
- */
1170
- export class ODQuickEmbed {
1171
- /**The id of this embed. */
1172
- id: ODId
1173
- /**The current data of this embed */
1174
- data: Partial<ODEmbedData>
1175
-
1176
- constructor(id:ODValidId,data:Partial<ODEmbedData>){
1177
- this.id = new ODId(id)
1178
- this.data = data
1179
- }
1180
-
1181
- /**Build this embed & compile it for discord.js */
1182
- async build(): Promise<ODEmbedBuildResult> {
1183
- try{
1184
- //create the discord.js embed
1185
- const embed = new discord.EmbedBuilder()
1186
- if (this.data.title) embed.setTitle(this.data.title)
1187
- if (this.data.color) embed.setColor(this.data.color as discord.ColorResolvable)
1188
- if (this.data.url) embed.setURL(this.data.url)
1189
- if (this.data.description) embed.setDescription(this.data.description)
1190
- if (this.data.authorText) embed.setAuthor({
1191
- name:this.data.authorText,
1192
- iconURL:this.data.authorImage ?? undefined,
1193
- url:this.data.authorUrl ?? undefined
1194
- })
1195
- if (this.data.footerText) embed.setFooter({
1196
- text:this.data.footerText,
1197
- iconURL:this.data.footerImage ?? undefined,
1198
- })
1199
- if (this.data.image) embed.setImage(this.data.image)
1200
- if (this.data.thumbnail) embed.setThumbnail(this.data.thumbnail)
1201
- if (this.data.timestamp) embed.setTimestamp(this.data.timestamp)
1202
- if (this.data.fields && this.data.fields.length > 0) embed.setFields(this.data.fields)
1203
-
1204
- return {id:this.id,embed}
1205
- }catch(err){
1206
- process.emit("uncaughtException",new ODSystemError("ODQuickEmbed:build(\""+this.id.value+"\") => Major Error (see next error)"))
1207
- process.emit("uncaughtException",err)
1208
- return {id:this.id,embed:null}
1209
- }
1210
- }
1211
- }
1212
-
1213
- /**## ODMessageManagerIdConstraint `type`
1214
- * The constraint/layout for id mappings/interfaces of the `ODMessageManager` class.
1215
- */
1216
- export type ODMessageManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
1217
-
1218
- /**## ODMessageManager `class`
1219
- * This is an Open Discord message manager.
1220
- *
1221
- * It contains all Open Discord message builders. Here, you can add your own messages or edit existing ones!
1222
- *
1223
- * It's recommended to use this system in combination with all the other Open Discord builders!
1224
- */
1225
- export class ODMessageManager<IdList extends ODMessageManagerIdConstraint = ODMessageManagerIdConstraint> extends ODManagerWithSafety<ODMessage<string,{},string>> {
1226
- constructor(debug:ODDebugger){
1227
- super(() => {
1228
- return new ODMessage("opendiscord:unknown-message",(instance,params,origin,cancel) => {
1229
- instance.setContent("**❌ <ODError:Unknown Message>**\nCouldn't find message in registery `opendiscord.builders.messages`")
1230
- cancel()
1231
- })
1232
- },debug,"message")
1233
- }
1234
-
1235
- get<MessageId extends keyof ODNoGeneric<IdList>>(id:MessageId): ODMessage<IdList[MessageId]["origin"],IdList[MessageId]["params"],IdList[MessageId]["workers"]>
1236
- get(id:ODValidId): ODMessage<string,{},string>|null
1237
-
1238
- get(id:ODValidId): ODMessage<string,{},string>|null {
1239
- return super.get(id)
1240
- }
1241
-
1242
- remove<MessageId extends keyof ODNoGeneric<IdList>>(id:MessageId): ODMessage<IdList[MessageId]["origin"],IdList[MessageId]["params"],IdList[MessageId]["workers"]>
1243
- remove(id:ODValidId): ODMessage<string,{},string>|null
1244
-
1245
- remove(id:ODValidId): ODMessage<string,{},string>|null {
1246
- return super.remove(id)
1247
- }
1248
-
1249
- exists(id:keyof ODNoGeneric<IdList>): boolean
1250
- exists(id:ODValidId): boolean
1251
-
1252
- exists(id:ODValidId): boolean {
1253
- return super.exists(id)
1254
- }
1255
-
1256
- getSafe<MessageId extends keyof ODNoGeneric<IdList>>(id:MessageId): ODMessage<IdList[MessageId]["origin"],IdList[MessageId]["params"],IdList[MessageId]["workers"]>
1257
- getSafe(id:ODValidId): ODMessage<string,{},string>
1258
-
1259
- getSafe(id:ODValidId): ODMessage<string,{},string> {
1260
- return super.getSafe(id)
1261
- }
1262
- }
1263
-
1264
- /**## ODMessageData `interface`
1265
- * This interface contains the data to build a message.
1266
- */
1267
- export interface ODMessageData {
1268
- /**The content of this message. `null` when no content */
1269
- content:string|null,
1270
- /**Poll data for this message */
1271
- poll:discord.PollData|null,
1272
- /**Try to make this message ephemeral when available */
1273
- ephemeral:boolean,
1274
-
1275
- /**Embeds from this message */
1276
- embeds:ODEmbedBuildResult[],
1277
- /**Components from this message */
1278
- components:ODComponentBuildResult[],
1279
- /**Files from this message */
1280
- files:ODFileBuildResult[],
1281
-
1282
- /**Additional options that aren't covered by the Open Discord api!*/
1283
- additionalOptions:Omit<discord.MessageCreateOptions,"poll"|"content"|"embeds"|"components"|"files"|"flags">
1284
- }
1285
-
1286
- /**## ODMessageBuildResult `interface`
1287
- * This interface contains the result from a built message. This can be sent in a discord channel!
1288
- */
1289
- export interface ODMessageBuildResult {
1290
- /**The id of this message */
1291
- id:ODId,
1292
- /**The discord message */
1293
- message:Omit<discord.MessageCreateOptions,"flags">,
1294
- /**When enabled, the bot will try to send this as an ephemeral message */
1295
- ephemeral:boolean
1296
- }
1297
-
1298
- /**## ODMessageInstance `class`
1299
- * This is an Open Discord message instance.
1300
- *
1301
- * It contains all properties & functions to build a message!
1302
- */
1303
- export class ODMessageInstance {
1304
- /**The current data of this message */
1305
- data: ODMessageData = {
1306
- content:null,
1307
- poll:null,
1308
- ephemeral:false,
1309
- embeds:[],
1310
- components:[],
1311
- files:[],
1312
- additionalOptions:{}
1313
- }
1314
-
1315
- /**Set the content of this message */
1316
- setContent(content:ODMessageData["content"]){
1317
- this.data.content = content
1318
- return this
1319
- }
1320
- /**Set the poll of this message */
1321
- setPoll(poll:ODMessageData["poll"]){
1322
- this.data.poll = poll
1323
- return this
1324
- }
1325
- /**Make this message ephemeral when possible */
1326
- setEphemeral(ephemeral:ODMessageData["ephemeral"]){
1327
- this.data.ephemeral = ephemeral
1328
- return this
1329
- }
1330
- /**Set the embeds of this message */
1331
- setEmbeds(...embeds:ODEmbedBuildResult[]){
1332
- this.data.embeds = embeds
1333
- return this
1334
- }
1335
- /**Add an embed to this message! */
1336
- addEmbed(embed:ODEmbedBuildResult){
1337
- this.data.embeds.push(embed)
1338
- return this
1339
- }
1340
- /**Remove an embed from this message */
1341
- removeEmbed(id:ODValidId){
1342
- const index = this.data.embeds.findIndex((embed) => embed.id.value === new ODId(id).value)
1343
- if (index > -1) this.data.embeds.splice(index,1)
1344
- return this
1345
- }
1346
- /**Get an embed from this message */
1347
- getEmbed(id:ODValidId){
1348
- const embed = this.data.embeds.find((embed) => embed.id.value === new ODId(id).value)
1349
- if (embed) return embed.embed
1350
- else return null
1351
- }
1352
- /**Set the components of this message */
1353
- setComponents(...components:ODComponentBuildResult[]){
1354
- this.data.components = components
1355
- return this
1356
- }
1357
- /**Add a component to this message! */
1358
- addComponent(component:ODComponentBuildResult){
1359
- this.data.components.push(component)
1360
- return this
1361
- }
1362
- /**Remove a component from this message */
1363
- removeComponent(id:ODValidId){
1364
- const index = this.data.components.findIndex((component) => component.id.value === new ODId(id).value)
1365
- if (index > -1) this.data.components.splice(index,1)
1366
- return this
1367
- }
1368
- /**Get a component from this message */
1369
- getComponent(id:ODValidId){
1370
- const component = this.data.components.find((component) => component.id.value === new ODId(id).value)
1371
- if (component) return component.component
1372
- else return null
1373
- }
1374
- /**Set the files of this message */
1375
- setFiles(...files:ODFileBuildResult[]){
1376
- this.data.files = files
1377
- return this
1378
- }
1379
- /**Add a file to this message! */
1380
- addFile(file:ODFileBuildResult){
1381
- this.data.files.push(file)
1382
- return this
1383
- }
1384
- /**Remove a file from this message */
1385
- removeFile(id:ODValidId){
1386
- const index = this.data.files.findIndex((file) => file.id.value === new ODId(id).value)
1387
- if (index > -1) this.data.files.splice(index,1)
1388
- return this
1389
- }
1390
- /**Get a file from this message */
1391
- getFile(id:ODValidId){
1392
- const file = this.data.files.find((file) => file.id.value === new ODId(id).value)
1393
- if (file) return file.file
1394
- else return null
1395
- }
1396
- }
1397
-
1398
- /**## ODMessage `class`
1399
- * This is an Open Discord message builder.
1400
- *
1401
- * With this class, you can create a message to send in a discord channel.
1402
- * The only difference with normal messages is that this one can be edited by Open Discord plugins!
1403
- *
1404
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
1405
- */
1406
- export class ODMessage<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODMessageInstance,Origin,Params,ODMessageBuildResult,WorkerIds> {
1407
- /**Build this message & compile it for discord.js */
1408
- async build(origin:Origin, params:Params){
1409
- if (this.didCache && this.cache && this.allowCache) return this.cache
1410
-
1411
- //create instance
1412
- const instance = new ODMessageInstance()
1413
-
1414
- //wait for workers to finish
1415
- await this.workers.executeWorkers(instance,origin,params)
1416
-
1417
- //create the discord.js message
1418
- const componentArray: discord.ActionRowBuilder<discord.MessageActionRowComponentBuilder>[] = []
1419
- let currentRow: discord.ActionRowBuilder<discord.MessageActionRowComponentBuilder> = new discord.ActionRowBuilder()
1420
- instance.data.components.forEach((c) => {
1421
- //return when component crashed
1422
- if (c.component == null) return
1423
- else if (c.component == "\n"){
1424
- //create new current row when required
1425
- if (currentRow.components.length > 0){
1426
- componentArray.push(currentRow)
1427
- currentRow = new discord.ActionRowBuilder()
1428
- }
1429
- }else if (c.component instanceof discord.BaseSelectMenuBuilder){
1430
- //push current row when not empty
1431
- if (currentRow.components.length > 0){
1432
- componentArray.push(currentRow)
1433
- currentRow = new discord.ActionRowBuilder()
1434
- }
1435
- currentRow.addComponents(c.component)
1436
- //create new current row after dropdown
1437
- componentArray.push(currentRow)
1438
- currentRow = new discord.ActionRowBuilder()
1439
- }else{
1440
- //push button to current row
1441
- currentRow.addComponents(c.component)
1442
- }
1443
-
1444
- //create new row when 5 rows in length
1445
- if (currentRow.components.length == 5){
1446
- componentArray.push(currentRow)
1447
- currentRow = new discord.ActionRowBuilder()
1448
- }
1449
- })
1450
- //push final row to array
1451
- if (currentRow.components.length > 0) componentArray.push(currentRow)
1452
-
1453
- const filteredEmbeds = instance.data.embeds.map((e) => e.embed).filter((e) => e instanceof discord.EmbedBuilder) as discord.EmbedBuilder[]
1454
- const filteredFiles = instance.data.files.map((f) => f.file).filter((f) => f instanceof discord.AttachmentBuilder) as discord.AttachmentBuilder[]
1455
-
1456
- const message : discord.MessageCreateOptions = {
1457
- content:instance.data.content ?? "",
1458
- poll:instance.data.poll ?? undefined,
1459
- embeds:filteredEmbeds,
1460
- components:componentArray,
1461
- files:filteredFiles
1462
- }
1463
-
1464
- let result = {id:this.id,message,ephemeral:instance.data.ephemeral}
1465
-
1466
- Object.assign(result.message,instance.data.additionalOptions)
1467
-
1468
- this.cache = result
1469
- this.didCache = true
1470
- return result
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
- }
1480
- }
1481
-
1482
- /**## ODQuickMessage `class`
1483
- * This is an Open Discord quick message builder.
1484
- *
1485
- * With this class, you can quickly create a message to send in a discord channel.
1486
- * This quick message can be used by Open Discord plugins instead of the normal builders to speed up the process!
1487
- *
1488
- * Because of the quick functionality, these messages are less customisable by other plugins.
1489
- */
1490
- export class ODQuickMessage {
1491
- /**The id of this message. */
1492
- id: ODId
1493
- /**The current data of this message. */
1494
- data: Partial<ODMessageData>
1495
-
1496
- constructor(id:ODValidId,data:Partial<ODMessageData>){
1497
- this.id = new ODId(id)
1498
- this.data = data
1499
- }
1500
-
1501
- /**Build this message & compile it for discord.js */
1502
- async build(): Promise<ODMessageBuildResult> {
1503
- //create the discord.js message
1504
- const componentArray: discord.ActionRowBuilder<discord.MessageActionRowComponentBuilder>[] = []
1505
- let currentRow: discord.ActionRowBuilder<discord.MessageActionRowComponentBuilder> = new discord.ActionRowBuilder()
1506
- this.data.components?.forEach((c) => {
1507
- //return when component crashed
1508
- if (c.component == null) return
1509
- else if (c.component == "\n"){
1510
- //create new current row when required
1511
- if (currentRow.components.length > 0){
1512
- componentArray.push(currentRow)
1513
- currentRow = new discord.ActionRowBuilder()
1514
- }
1515
- }else if (c.component instanceof discord.BaseSelectMenuBuilder){
1516
- //push current row when not empty
1517
- if (currentRow.components.length > 0){
1518
- componentArray.push(currentRow)
1519
- currentRow = new discord.ActionRowBuilder()
1520
- }
1521
- currentRow.addComponents(c.component)
1522
- //create new current row after dropdown
1523
- componentArray.push(currentRow)
1524
- currentRow = new discord.ActionRowBuilder()
1525
- }else{
1526
- //push button to current row
1527
- currentRow.addComponents(c.component)
1528
- }
1529
-
1530
- //create new row when 5 rows in length
1531
- if (currentRow.components.length == 5){
1532
- componentArray.push(currentRow)
1533
- currentRow = new discord.ActionRowBuilder()
1534
- }
1535
- })
1536
- //push final row to array
1537
- if (currentRow.components.length > 0) componentArray.push(currentRow)
1538
-
1539
- const filteredEmbeds = (this.data.embeds?.map((e) => e.embed).filter((e) => e instanceof discord.EmbedBuilder) as discord.EmbedBuilder[]) ?? []
1540
- const filteredFiles = (this.data.files?.map((f) => f.file).filter((f) => f instanceof discord.AttachmentBuilder) as discord.AttachmentBuilder[]) ?? []
1541
-
1542
- const message : discord.MessageCreateOptions = {
1543
- content:this.data.content ?? "",
1544
- poll:this.data.poll ?? undefined,
1545
- embeds:filteredEmbeds,
1546
- components:componentArray,
1547
- files:filteredFiles
1548
- }
1549
-
1550
- let result = {id:this.id,message,ephemeral:this.data.ephemeral ?? false}
1551
-
1552
- Object.assign(result.message,this.data.additionalOptions)
1553
- return result
1554
- }
1555
- }
1556
-
1557
- /**## ODModalManagerIdConstraint `type`
1558
- * The constraint/layout for id mappings/interfaces of the `ODModalManager` class.
1559
- */
1560
- export type ODModalManagerIdConstraint = Record<string,{origin:string,params:object,workers:string}>
1561
-
1562
- /**## ODModalManager `class`
1563
- * This is an Open Discord modal manager.
1564
- *
1565
- * It contains all Open Discord modal builders. Here, you can add your own modals or edit existing ones!
1566
- *
1567
- * It's recommended to use this system in combination with all the other Open Discord builders!
1568
- */
1569
- export class ODModalManager<IdList extends ODModalManagerIdConstraint = ODModalManagerIdConstraint> extends ODManagerWithSafety<ODModal<string,{},string>> {
1570
- constructor(debug:ODDebugger){
1571
- super(() => {
1572
- return new ODModal("opendiscord:unknown-modal",(instance,params,origin,cancel) => {
1573
- instance.setCustomId("od:unknown-modal")
1574
- instance.setTitle("❌ <ODError:Unknown Modal>")
1575
- instance.setQuestions(
1576
- {
1577
- style:"short",
1578
- customId:"error",
1579
- label:"error",
1580
- placeholder:"Contact the bot creator for more info!"
1581
- }
1582
- )
1583
- cancel()
1584
- })
1585
- },debug,"modal")
1586
- }
1587
-
1588
- get<ModalId extends keyof ODNoGeneric<IdList>>(id:ModalId): ODModal<IdList[ModalId]["origin"],IdList[ModalId]["params"],IdList[ModalId]["workers"]>
1589
- get(id:ODValidId): ODModal<string,{},string>|null
1590
-
1591
- get(id:ODValidId): ODModal<string,{},string>|null {
1592
- return super.get(id)
1593
- }
1594
-
1595
- remove<ModalId extends keyof ODNoGeneric<IdList>>(id:ModalId): ODModal<IdList[ModalId]["origin"],IdList[ModalId]["params"],IdList[ModalId]["workers"]>
1596
- remove(id:ODValidId): ODModal<string,{},string>|null
1597
-
1598
- remove(id:ODValidId): ODModal<string,{},string>|null {
1599
- return super.remove(id)
1600
- }
1601
-
1602
- exists(id:keyof ODNoGeneric<IdList>): boolean
1603
- exists(id:ODValidId): boolean
1604
-
1605
- exists(id:ODValidId): boolean {
1606
- return super.exists(id)
1607
- }
1608
-
1609
- getSafe<ModalId extends keyof ODNoGeneric<IdList>>(id:ModalId): ODModal<IdList[ModalId]["origin"],IdList[ModalId]["params"],IdList[ModalId]["workers"]>
1610
- getSafe(id:ODValidId): ODModal<string,{},string>
1611
-
1612
- getSafe(id:ODValidId): ODModal<string,{},string> {
1613
- return super.getSafe(id)
1614
- }
1615
- }
1616
-
1617
- /**## ODModalDataQuestion `interface`
1618
- * This interface contains the data to build a modal question.
1619
- */
1620
- export interface ODModalDataQuestion {
1621
- /**The style of this modal question */
1622
- style:"short"|"paragraph",
1623
- /**The custom id of this modal question */
1624
- customId:string
1625
- /**The label of this modal question */
1626
- label?:string,
1627
- /**The min length of this modal question */
1628
- minLength?:number,
1629
- /**The max length of this modal question */
1630
- maxLength?:number,
1631
- /**Is this modal question required? */
1632
- required?:boolean,
1633
- /**The placeholder of this modal question */
1634
- placeholder?:string,
1635
- /**The initial value of this modal question */
1636
- value?:string
1637
- }
1638
-
1639
- /**## ODModalData `interface`
1640
- * This interface contains the data to build a modal.
1641
- */
1642
- export interface ODModalData {
1643
- /**The custom id of this modal */
1644
- customId:string,
1645
- /**The title of this modal */
1646
- title:string|null,
1647
- /**The collection of questions in this modal */
1648
- questions:ODModalDataQuestion[],
1649
- }
1650
-
1651
- /**## ODModalBuildResult `interface`
1652
- * This interface contains the result from a built modal (form). This can be used in the `ODMessage` builder!
1653
- */
1654
- export interface ODModalBuildResult {
1655
- /**The id of this modal */
1656
- id:ODId,
1657
- /**The discord modal */
1658
- modal:discord.ModalBuilder
1659
- }
1660
-
1661
- /**## ODModalInstance `class`
1662
- * This is an Open Discord modal instance.
1663
- *
1664
- * It contains all properties & functions to build a modal!
1665
- */
1666
- export class ODModalInstance {
1667
- /**The current data of this modal */
1668
- data: ODModalData = {
1669
- customId:"",
1670
- title:null,
1671
- questions:[]
1672
- }
1673
-
1674
- /**Set the custom id of this modal */
1675
- setCustomId(customId:ODModalData["customId"]){
1676
- this.data.customId = customId
1677
- return this
1678
- }
1679
- /**Set the title of this modal */
1680
- setTitle(title:ODModalData["title"]){
1681
- this.data.title = title
1682
- return this
1683
- }
1684
- /**Set the questions of this modal */
1685
- setQuestions(...questions:ODModalData["questions"]){
1686
- this.data.questions = questions
1687
- return this
1688
- }
1689
- /**Add a question to this modal! */
1690
- addQuestion(question:ODModalDataQuestion){
1691
- this.data.questions.push(question)
1692
- return this
1693
- }
1694
- /**Remove a question from this modal */
1695
- removeQuestion(customId:string){
1696
- const index = this.data.questions.findIndex((question) => question.customId === customId)
1697
- if (index > -1) this.data.questions.splice(index,1)
1698
- return this
1699
- }
1700
- /**Get a question from this modal */
1701
- getQuestion(customId:string){
1702
- const question = this.data.questions.find((question) => question.customId === customId)
1703
- if (question) return question
1704
- else return null
1705
- }
1706
- }
1707
-
1708
- /**## ODModal `class`
1709
- * This is an Open Discord modal builder.
1710
- *
1711
- * With this class, you can create a modal to use as response in interactions.
1712
- * The only difference with normal modals is that this one can be edited by Open Discord plugins!
1713
- *
1714
- * This is possible by using "workers" or multiple functions that will be executed in priority order!
1715
- */
1716
- export class ODModal<Origin extends string,Params,WorkerIds extends string = string> extends ODBuilderImplementation<ODModalInstance,Origin,Params,ODModalBuildResult,WorkerIds> {
1717
- /**Build this modal & compile it for discord.js */
1718
- async build(origin:Origin, params:Params){
1719
- if (this.didCache && this.cache && this.allowCache) return this.cache
1720
-
1721
- //create instance
1722
- const instance = new ODModalInstance()
1723
-
1724
- //wait for workers to finish
1725
- await this.workers.executeWorkers(instance,origin,params)
1726
-
1727
- //create the discord.js modal
1728
- const modal = new discord.ModalBuilder()
1729
- modal.setCustomId(instance.data.customId)
1730
- if (instance.data.title) modal.setTitle(instance.data.title)
1731
- else modal.setTitle(instance.data.customId)
1732
-
1733
- instance.data.questions.forEach((question) => {
1734
- const input = new discord.TextInputBuilder()
1735
- .setStyle(question.style == "paragraph" ? discord.TextInputStyle.Paragraph : discord.TextInputStyle.Short)
1736
- .setCustomId(question.customId)
1737
- .setLabel(question.label ? question.label : question.customId)
1738
- .setRequired(question.required ? true : false)
1739
-
1740
- if (question.minLength) input.setMinLength(question.minLength)
1741
- if (question.maxLength) input.setMaxLength(question.maxLength)
1742
- if (question.value) input.setValue(question.value)
1743
- if (question.placeholder) input.setPlaceholder(question.placeholder)
1744
-
1745
- modal.addComponents(
1746
- new discord.ActionRowBuilder<discord.ModalActionRowComponentBuilder>()
1747
- .addComponents(input)
1748
- )
1749
- })
1750
-
1751
- this.cache = {id:this.id,modal}
1752
- this.didCache = true
1753
- return {id:this.id,modal}
1754
- }
1755
- }