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