Merge branch 'dev-v4.1.0' into dev
This commit is contained in:
@@ -19,11 +19,11 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Open Ticket is the most advanced & customisable discord ticket bot that you will ever find! You can customise up to 300+ variables! This includes <code>Html Transcripts</code>, <code>Advanced Plugins</code>, <code>Custom Embeds</code>, <code>Questions/Modals</code>, <code>Stats</code> & more!
|
Open Ticket is the most advanced & customisable discord ticket bot available! You are able to customise up to 300+ settings and aspects! This includes <code>Html Transcripts</code>, <code>Advanced Plugins</code>, <code>Custom Embeds</code>, <code>Questions/Modals</code>, <code>Stats</code> & more!
|
||||||
You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than <code>27 Languages</code>! If you need any help, feel free to join our <a href="https://discord.dj-dj.be">discord server</a>!
|
The bot is translated in more than <code>27 Languages</code> and has been battle tested in large Discord servers! If you need any help, feel free to join our <a href="https://discord.dj-dj.be">discord server</a>!
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center"><b>⭐️ Help us grow by giving a star! ⭐️</b></p>
|
<h3 align="center"><b>⭐️ Help us grow by giving a star! ⭐️</b></h3>
|
||||||
|
|
||||||
### 📌 Features
|
### 📌 Features
|
||||||
- **🦇 pterodactyl support** - Open Ticket works perfect on Pterodactyl based panels! [(Download official eggs)](.eggs/README.md)
|
- **🦇 pterodactyl support** - Open Ticket works perfect on Pterodactyl based panels! [(Download official eggs)](.eggs/README.md)
|
||||||
@@ -68,10 +68,10 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="https://github.com/roppl3r.png" alt="Profile Picture" width="100px"></td>
|
<td><img src="https://github.com/guillee3.png" alt="Profile Picture" width="100px"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/roppl3r"><b>roppl3r</b></a></td>
|
<td align="center"><a href="https://github.com/guillee3"><b>guillee3</b></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -169,12 +169,12 @@
|
|||||||
"rolesEmpty":"Geen enkele rollen zijn bijgewerkt!",
|
"rolesEmpty":"Geen enkele rollen zijn bijgewerkt!",
|
||||||
|
|
||||||
"autocloseLeave":"Dit ticket is automatisch gesloten omdat de maker de server verlaten is!",
|
"autocloseLeave":"Dit ticket is automatisch gesloten omdat de maker de server verlaten is!",
|
||||||
"autocloseTimeout":"Dit ticket is automatisch gesloten omdat het inactief was voor meer dan `{0} uur`!",
|
"autocloseTimeout":"Dit ticket is automatisch gesloten omdat het meer dan `{0} uur` inactief was!",
|
||||||
"autodeleteLeave":"Dit ticket is automatisch verwijderd omdat de maker de server verlaten is!",
|
"autodeleteLeave":"Dit ticket is automatisch verwijderd omdat de maker de server verlaten is!",
|
||||||
"autodeleteTimeout":"Dit ticket is automatisch verwijderd omdat het inactief was voor meer dan `{0} dagen`!",
|
"autodeleteTimeout":"Dit ticket is automatisch verwijderd omdat het meer dan `{0} dagen` inactief was!",
|
||||||
"autocloseEnabled":"Autoclose is ingeschakeld in dit ticket!\nHet wordt gesloten wanneer het inactief is voor meer dan `{0} uur`!",
|
"autocloseEnabled":"Autoclose is ingeschakeld in dit ticket!\nHet wordt gesloten na `{0} uur` inactiviteit!",
|
||||||
"autocloseDisabled":"Autoclose is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch gesloten!",
|
"autocloseDisabled":"Autoclose is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch gesloten!",
|
||||||
"autodeleteEnabled":"Autodelete is ingeschakeld in dit ticket!\nHet wordt verwijderd wanneer het inactief is voor meer dan `{0} dagen`!",
|
"autodeleteEnabled":"Autodelete is ingeschakeld in dit ticket!\nHet wordt verwijderd na `{0} dagen` inactiviteit!",
|
||||||
"autodeleteDisabled":"Autodelete is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch verwijderd!",
|
"autodeleteDisabled":"Autodelete is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch verwijderd!",
|
||||||
|
|
||||||
"ticketMessageLimit":"Je kan maar {0} ticket(s) op het zelfde moment aanmaken!",
|
"ticketMessageLimit":"Je kan maar {0} ticket(s) op het zelfde moment aanmaken!",
|
||||||
|
|||||||
+7
-3
@@ -14,9 +14,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node index.js --compile-only",
|
"build": "node index.js --compile-only",
|
||||||
"start": "node index.js",
|
"start": "node index.js",
|
||||||
|
"setup": "node index.js --cli",
|
||||||
"startnc": "node index.js --no-compile",
|
"startnc": "node index.js --no-compile",
|
||||||
"test": "node index.js --dev-config --dev-database",
|
"test": "node index.js --dev-config --dev-database --soft-plugins",
|
||||||
"testnc": "node index.js --no-compile --dev-config --dev-database",
|
"testsetup": "node index.js --cli --dev-config --dev-database --soft-plugins",
|
||||||
|
"testnc": "node index.js --no-compile --dev-config --dev-database --soft-plugins",
|
||||||
"docs": "npx typedoc --options .docs/typedoc-config.json && node .docs/createDocs.js"
|
"docs": "npx typedoc --options .docs/typedoc-config.json && node .docs/createDocs.js"
|
||||||
},
|
},
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
@@ -24,9 +26,11 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/rest": "^2.4.2",
|
"@discordjs/rest": "^2.4.2",
|
||||||
"@types/node": "^22.5.0",
|
"@types/node": "^22.5.0",
|
||||||
|
"@types/terminal-kit": "^2.5.7",
|
||||||
"ansis": "^2.3.0",
|
"ansis": "^2.3.0",
|
||||||
"discord.js": "^14.19.1",
|
"discord.js": "^14.19.1",
|
||||||
"formatted-json-stringify": "^1.1.0",
|
"formatted-json-stringify": "^1.2.1",
|
||||||
|
"terminal-kit": "^3.1.2",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -183,14 +183,8 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer {
|
|||||||
return finalComponents
|
return finalComponents
|
||||||
}
|
}
|
||||||
/**Get the length of the longest string in the array. */
|
/**Get the length of the longest string in the array. */
|
||||||
#getLongestLength(text:string[]): number {
|
#getLongestLength(texts:string[]): number {
|
||||||
let finalLength = 0
|
return Math.max(...texts.map((t) => ansis.strip(t).length))
|
||||||
text.forEach((t) => {
|
|
||||||
const l = ansis.strip(t).length
|
|
||||||
if (l > finalLength) finalLength = l
|
|
||||||
})
|
|
||||||
|
|
||||||
return finalLength
|
|
||||||
}
|
}
|
||||||
/**Get a horizontal divider used between different parts of the config checker result. */
|
/**Get a horizontal divider used between different parts of the config checker result. */
|
||||||
#getHorizontalDivider(width:number): string {
|
#getHorizontalDivider(width:number): string {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export interface ODFlagManagerIds_Default {
|
|||||||
"opendiscord:force-slash-update":ODFlag,
|
"opendiscord:force-slash-update":ODFlag,
|
||||||
"opendiscord:no-compile":ODFlag,
|
"opendiscord:no-compile":ODFlag,
|
||||||
"opendiscord:compile-only":ODFlag,
|
"opendiscord:compile-only":ODFlag,
|
||||||
|
"opendiscord:silent":ODFlag,
|
||||||
|
"opendiscord:cli":ODFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODFlagManager_Default `default_class`
|
/**## ODFlagManager_Default `default_class`
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
//DEFAULT SESSION MODULE
|
//DEFAULT SESSION MODULE
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
import { Guild, TextBasedChannel, User } from "discord.js"
|
|
||||||
import { ODValidId } from "../modules/base"
|
import { ODValidId } from "../modules/base"
|
||||||
import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat"
|
import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat"
|
||||||
|
|
||||||
|
|||||||
@@ -289,6 +289,16 @@ export class ODCheckerFunctionManager extends ODManager<ODCheckerFunction> {
|
|||||||
*/
|
*/
|
||||||
export type ODCheckerLocationTrace = (string|number)[]
|
export type ODCheckerLocationTrace = (string|number)[]
|
||||||
|
|
||||||
|
/**## ODCheckerOptions `interface`
|
||||||
|
* This interface contains all optional properties to customise in the `ODChecker` class.
|
||||||
|
*/
|
||||||
|
export interface ODCheckerOptions {
|
||||||
|
/**The name of this config in the Interactive Setup CLI. */
|
||||||
|
cliDisplayName?:string
|
||||||
|
/**The description of this config in the Interactive Setup CLI. */
|
||||||
|
cliDisplayDescription?:string
|
||||||
|
}
|
||||||
|
|
||||||
/**## ODChecker `class`
|
/**## ODChecker `class`
|
||||||
* This is an Open Ticket config checker.
|
* This is an Open Ticket config checker.
|
||||||
*
|
*
|
||||||
@@ -310,13 +320,16 @@ export class ODChecker extends ODManagerData {
|
|||||||
messages: ODCheckerMessage[] = []
|
messages: ODCheckerMessage[] = []
|
||||||
/**Temporary storage for the quit status from the check() method (not recommended to use) */
|
/**Temporary storage for the quit status from the check() method (not recommended to use) */
|
||||||
quit: boolean = false
|
quit: boolean = false
|
||||||
|
/**All additional properties of this config checker. */
|
||||||
|
options: ODCheckerOptions
|
||||||
|
|
||||||
constructor(id:ODValidId, storage: ODCheckerStorage, priority:number, config:ODConfig, structure: ODCheckerStructure){
|
constructor(id:ODValidId, storage: ODCheckerStorage, priority:number, config:ODConfig, structure:ODCheckerStructure, options?:ODCheckerOptions){
|
||||||
super(id)
|
super(id)
|
||||||
this.storage = storage
|
this.storage = storage
|
||||||
this.priority = priority
|
this.priority = priority
|
||||||
this.config = config
|
this.config = config
|
||||||
this.structure = structure
|
this.structure = structure
|
||||||
|
this.options = options ?? {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Run this checker. Returns all errors*/
|
/**Run this checker. Returns all errors*/
|
||||||
@@ -391,7 +404,15 @@ export interface ODCheckerStructureOptions {
|
|||||||
/**Add a custom checker function. Returns `true` when valid. */
|
/**Add a custom checker function. Returns `true` when valid. */
|
||||||
custom?:(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace, locationId:ODId, locationDocs:string|null) => boolean,
|
custom?:(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace, locationId:ODId, locationDocs:string|null) => boolean,
|
||||||
/**Set the url to the documentation of this variable. */
|
/**Set the url to the documentation of this variable. */
|
||||||
docs?:string
|
docs?:string,
|
||||||
|
/**The name of this config in the Interactive Setup CLI. */
|
||||||
|
cliDisplayName?:string
|
||||||
|
/**The description of this config in the Interactive Setup CLI. */
|
||||||
|
cliDisplayDescription?:string
|
||||||
|
/**Hide the description of this config in the Interactive Setup CLI parent view/list. */
|
||||||
|
cliHideDescriptionInParent?:boolean
|
||||||
|
/**The default value of this variable when creating it in the Interactive Setup CLI. When not specified, the user will be asked to insert a value. */
|
||||||
|
cliInitDefaultValue?:ODValidJsonType
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerStructure `class`
|
/**## ODCheckerStructure `class`
|
||||||
@@ -426,7 +447,13 @@ export class ODCheckerStructure {
|
|||||||
*/
|
*/
|
||||||
export interface ODCheckerObjectStructureOptions extends ODCheckerStructureOptions {
|
export interface ODCheckerObjectStructureOptions extends ODCheckerStructureOptions {
|
||||||
/**Add a checker for a property in an object (can also be optional) */
|
/**Add a checker for a property in an object (can also be optional) */
|
||||||
children?:{key:string, checker:ODCheckerStructure, priority:number, optional:boolean}[]
|
children:{key:string, priority:number, optional:boolean, cliHideInEditMode?:boolean, checker:ODCheckerStructure}[],
|
||||||
|
/**A list of keys to skip when creating this object with the Interactive Setup CLI. The default value of these properties will be used instead. */
|
||||||
|
cliInitSkipKeys?:string[],
|
||||||
|
/**The key of a (primitive) property in this object to show the value of in the Interactive Setup CLI when listed in an array. */
|
||||||
|
cliDisplayKeyInParentArray?:string,
|
||||||
|
/**A list of additional (primitive) property keys in this object to show the value of in the Interactive Setup CLI when listed in an array. */
|
||||||
|
cliDisplayAdditionalKeysInParentArray?:string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerObjectStructure `class`
|
/**## ODCheckerObjectStructure `class`
|
||||||
@@ -500,7 +527,11 @@ export interface ODCheckerStringStructureOptions extends ODCheckerStructureOptio
|
|||||||
/**You need to choose between ... */
|
/**You need to choose between ... */
|
||||||
choices?:string[],
|
choices?:string[],
|
||||||
/**The string needs to match this regex */
|
/**The string needs to match this regex */
|
||||||
regex?:RegExp
|
regex?:RegExp,
|
||||||
|
/**Provide an optional list for autocomplete when using the Interactive Setup CLI. Defaults to the `choices` option. */
|
||||||
|
cliAutocompleteList?:string[],
|
||||||
|
/**Dynamically provide a list for autocomplete items when using the Interactive Setup CLI. */
|
||||||
|
cliAutocompleteFunc?:() => Promise<string[]|null>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerStringStructure `class`
|
/**## ODCheckerStringStructure `class`
|
||||||
@@ -718,7 +749,9 @@ export interface ODCheckerArrayStructureOptions extends ODCheckerStructureOption
|
|||||||
/**Allow double values (only for `string`, `number` & `boolean`) */
|
/**Allow double values (only for `string`, `number` & `boolean`) */
|
||||||
allowDoubles?:boolean
|
allowDoubles?:boolean
|
||||||
/**Only allow these types in the array (for multi-type propertyCheckers) */
|
/**Only allow these types in the array (for multi-type propertyCheckers) */
|
||||||
allowedTypes?:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[]
|
allowedTypes?:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[],
|
||||||
|
/**The name of the properties inside this array. Used in the GUI of the Interactive Setup CLI. */
|
||||||
|
cliDisplayPropertyName?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerArrayStructure `class`
|
/**## ODCheckerArrayStructure `class`
|
||||||
@@ -863,15 +896,15 @@ export interface ODCheckerTypeSwitchStructureOptions extends ODCheckerStructureO
|
|||||||
/**A checker when the property is a boolean */
|
/**A checker when the property is a boolean */
|
||||||
boolean?:ODCheckerBooleanStructure,
|
boolean?:ODCheckerBooleanStructure,
|
||||||
/**A checker when the property is null */
|
/**A checker when the property is null */
|
||||||
null?:ODCheckerStructure,
|
null?:ODCheckerNullStructure,
|
||||||
/**A checker when the property is an array */
|
/**A checker when the property is an array */
|
||||||
array?:ODCheckerStructure,
|
array?:ODCheckerArrayStructure,
|
||||||
/**A checker when the property is an object */
|
/**A checker when the property is an object */
|
||||||
object?:ODCheckerObjectStructure,
|
object?:ODCheckerObjectStructure,
|
||||||
/**A checker when the property is something else */
|
/**A checker when the property is something else */
|
||||||
other?:ODCheckerStructure,
|
other?:ODCheckerStructure,
|
||||||
/**A list of allowed types */
|
/**A list of allowed types */
|
||||||
allowedTypes?:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[]
|
allowedTypes:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerTypeSwitchStructure `class`
|
/**## ODCheckerTypeSwitchStructure `class`
|
||||||
@@ -925,9 +958,9 @@ export class ODCheckerTypeSwitchStructure extends ODCheckerStructure {
|
|||||||
*/
|
*/
|
||||||
export interface ODCheckerObjectSwitchStructureOptions extends ODCheckerStructureOptions {
|
export interface ODCheckerObjectSwitchStructureOptions extends ODCheckerStructureOptions {
|
||||||
/**An array of object checkers with their name, properties & priority. */
|
/**An array of object checkers with their name, properties & priority. */
|
||||||
objects?:{
|
objects:{
|
||||||
/**The properties to match for this checker to be used. */
|
/**The properties to match for this checker to be used. */
|
||||||
properties:{key:string, value:any}[],
|
properties:{key:string, value:boolean|string|number}[],
|
||||||
/**The name for this object type (used in rendering) */
|
/**The name for this object type (used in rendering) */
|
||||||
name:string,
|
name:string,
|
||||||
/**The higher the priority, the earlier this checker will be tested. */
|
/**The higher the priority, the earlier this checker will be tested. */
|
||||||
@@ -993,11 +1026,11 @@ export class ODCheckerObjectSwitchStructure extends ODCheckerStructure {
|
|||||||
*/
|
*/
|
||||||
export interface ODCheckerEnabledObjectStructureOptions extends ODCheckerStructureOptions {
|
export interface ODCheckerEnabledObjectStructureOptions extends ODCheckerStructureOptions {
|
||||||
/**The name of the property to match the `enabledValue`. */
|
/**The name of the property to match the `enabledValue`. */
|
||||||
property?:string,
|
property:string,
|
||||||
/**The value of the property to be enabled. Defaults to `true` */
|
/**The value of the property to be enabled. (e.g. `true`) */
|
||||||
enabledValue?:any,
|
enabledValue:boolean|string|number,
|
||||||
/**The object checker to use once the property has been matched. */
|
/**The object checker to use once the property has been matched. */
|
||||||
checker?:ODCheckerObjectStructure
|
checker:ODCheckerObjectStructure
|
||||||
}
|
}
|
||||||
|
|
||||||
/**## ODCheckerEnabledObjectStructure `class`
|
/**## ODCheckerEnabledObjectStructure `class`
|
||||||
@@ -1387,35 +1420,29 @@ export class ODCheckerCustomStructure_UniqueIdArray extends ODCheckerArrayStruct
|
|||||||
/**The scope to push unique ids when used in this array! */
|
/**The scope to push unique ids when used in this array! */
|
||||||
readonly usedScope: string|null
|
readonly usedScope: string|null
|
||||||
|
|
||||||
constructor(id:ODValidId, source:string, scope:string, usedScope?:string, options?:ODCheckerArrayStructureOptions){
|
constructor(id:ODValidId, source:string, scope:string, usedScope?:string, options?:ODCheckerArrayStructureOptions, idOptions?:Omit<ODCheckerStringStructureOptions,"minLength"|"custom">){
|
||||||
//add premade custom structure checker
|
//add premade custom structure checker
|
||||||
const newOptions = options ?? {}
|
const newOptions = options ?? {}
|
||||||
newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => {
|
newOptions.propertyChecker = new ODCheckerStringStructure("opendiscord:unique-id",{...(idOptions ?? {}),minLength:1,custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
||||||
const lt = checker.locationTraceDeref(locationTrace)
|
if (typeof value != "string") return false
|
||||||
|
const localLt = checker.locationTraceDeref(locationTrace)
|
||||||
|
localLt.pop()
|
||||||
|
|
||||||
if (!Array.isArray(value)) return false
|
const uniqueArray: string[] = checker.storage.get(source,scope) ?? []
|
||||||
const uniqueArray: string[] = (checker.storage.get(source,scope) === null) ? [] : checker.storage.get(source,scope)
|
if (uniqueArray.includes(value)){
|
||||||
|
//exists
|
||||||
let localQuit = false
|
if (usedScope){
|
||||||
value.forEach((id,index) => {
|
const current: string[] = checker.storage.get(source,usedScope) ?? []
|
||||||
if (typeof id != "string") return
|
current.push(value)
|
||||||
const localLt = checker.locationTraceDeref(lt)
|
checker.storage.set(source,usedScope,current)
|
||||||
localLt.push(index)
|
|
||||||
if (uniqueArray.includes(id)){
|
|
||||||
//exists
|
|
||||||
if (usedScope){
|
|
||||||
const current: string[] = checker.storage.get(source,usedScope) ?? []
|
|
||||||
current.push(id)
|
|
||||||
checker.storage.set(source,usedScope,current)
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
//doesn't exist
|
|
||||||
checker.createMessage("opendiscord:id-non-existent","error",`The id "${id}" doesn't exist!`,localLt,null,[`"${id}"`],this.id,(this.options.docs ?? null))
|
|
||||||
localQuit = true
|
|
||||||
}
|
}
|
||||||
})
|
return true
|
||||||
return !localQuit
|
}else{
|
||||||
}
|
//doesn't exist
|
||||||
|
checker.createMessage("opendiscord:id-non-existent","error",`The id "${value}" doesn't exist!`,localLt,null,[`"${value}"`],locationId,locationDocs)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}})
|
||||||
super(id,newOptions)
|
super(id,newOptions)
|
||||||
this.source = source
|
this.source = source
|
||||||
this.scope = scope
|
this.scope = scope
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export class ODClientManager {
|
|||||||
this.#debug.debug("Created client with permissions: "+this.permissions.join(", "))
|
this.#debug.debug("Created client with permissions: "+this.permissions.join(", "))
|
||||||
}
|
}
|
||||||
/**Get all servers the bot is part of. */
|
/**Get all servers the bot is part of. */
|
||||||
getGuilds(){
|
async getGuilds(): Promise<discord.Guild[]> {
|
||||||
if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!")
|
if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!")
|
||||||
if (!this.ready) throw new ODSystemError("Client isn't ready yet!")
|
if (!this.ready) throw new ODSystemError("Client isn't ready yet!")
|
||||||
|
|
||||||
@@ -135,8 +135,8 @@ export class ODClientManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**Log-in with a discord auth token. */
|
/**Log-in with a discord auth token. Rejects returns `false` using 'softErrors' on failure. */
|
||||||
login(): Promise<boolean> {
|
login(softErrors?:boolean): Promise<boolean> {
|
||||||
return new Promise(async (resolve,reject) => {
|
return new Promise(async (resolve,reject) => {
|
||||||
if (!this.initiated) reject("Client isn't initiated yet!")
|
if (!this.initiated) reject("Client isn't initiated yet!")
|
||||||
if (!this.token) reject("Client doesn't have a token!")
|
if (!this.token) reject("Client doesn't have a token!")
|
||||||
@@ -158,7 +158,8 @@ export class ODClientManager {
|
|||||||
this.#debug.debug("Finished discord.js client.login()")
|
this.#debug.debug("Finished discord.js client.login()")
|
||||||
this.loggedIn = true
|
this.loggedIn = true
|
||||||
}catch(err){
|
}catch(err){
|
||||||
if (err.message.toLowerCase().includes("used disallowed intents")){
|
if (softErrors) return resolve(false)
|
||||||
|
else if (err.message.toLowerCase().includes("used disallowed intents")){
|
||||||
process.emit("uncaughtException",new ODSystemError("Used disallowed intents"))
|
process.emit("uncaughtException",new ODSystemError("Used disallowed intents"))
|
||||||
}else if (err.message.toLowerCase().includes("tokeninvalid") || err.message.toLowerCase().includes("an invalid token was provided")){
|
}else if (err.message.toLowerCase().includes("tokeninvalid") || err.message.toLowerCase().includes("an invalid token was provided")){
|
||||||
process.emit("uncaughtException",new ODSystemError("Invalid discord bot token provided"))
|
process.emit("uncaughtException",new ODSystemError("Invalid discord bot token provided"))
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId
|
|||||||
import nodepath from "path"
|
import nodepath from "path"
|
||||||
import { ODDebugger } from "./console"
|
import { ODDebugger } from "./console"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
|
import * as fjs from "formatted-json-stringify"
|
||||||
|
|
||||||
/**## ODConfigManager `class`
|
/**## ODConfigManager `class`
|
||||||
* This is an Open Ticket config manager.
|
* This is an Open Ticket config manager.
|
||||||
@@ -14,8 +15,17 @@ import fs from "fs"
|
|||||||
* You can use this class to get/change/add a config file (`ODConfig`) in your plugin!
|
* You can use this class to get/change/add a config file (`ODConfig`) in your plugin!
|
||||||
*/
|
*/
|
||||||
export class ODConfigManager extends ODManager<ODConfig> {
|
export class ODConfigManager extends ODManager<ODConfig> {
|
||||||
|
/**Alias to Open Ticket debugger. */
|
||||||
|
#debug: ODDebugger
|
||||||
|
|
||||||
constructor(debug:ODDebugger){
|
constructor(debug:ODDebugger){
|
||||||
super(debug,"config")
|
super(debug,"config")
|
||||||
|
this.#debug = debug
|
||||||
|
}
|
||||||
|
add(data:ODConfig|ODConfig[],overwrite?:boolean): boolean {
|
||||||
|
if (Array.isArray(data)) data.forEach((d) => d.useDebug(this.#debug))
|
||||||
|
else data.useDebug(this.#debug)
|
||||||
|
return super.add(data,overwrite)
|
||||||
}
|
}
|
||||||
/**Init all config files. */
|
/**Init all config files. */
|
||||||
async init(){
|
async init(){
|
||||||
@@ -42,15 +52,45 @@ export class ODConfig extends ODManagerData {
|
|||||||
path: string = ""
|
path: string = ""
|
||||||
/**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */
|
/**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */
|
||||||
data: any
|
data: any
|
||||||
|
/**Is this config already initiated? */
|
||||||
|
initiated: boolean = false
|
||||||
|
/**An array of listeners to run when the config gets reloaded. These are not executed on the initial loading. */
|
||||||
|
protected reloadListeners: Function[] = []
|
||||||
|
/**Alias to Open Ticket debugger. */
|
||||||
|
protected debug: ODDebugger|null = null
|
||||||
|
|
||||||
constructor(id:ODValidId, data:any){
|
constructor(id:ODValidId, data:any){
|
||||||
super(id)
|
super(id)
|
||||||
this.data = data
|
this.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Use the Open Ticket debugger for logs. */
|
||||||
|
useDebug(debug:ODDebugger|null){
|
||||||
|
this.debug = debug
|
||||||
|
}
|
||||||
/**Init the config. */
|
/**Init the config. */
|
||||||
init(): ODPromiseVoid {
|
init(): ODPromiseVoid {
|
||||||
//nothing
|
this.initiated = true
|
||||||
|
if (this.debug) this.debug.debug("Initiated config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
|
||||||
|
//please implement this feature in your own config extension & extend this function.
|
||||||
|
}
|
||||||
|
/**Reload the config. Be aware that this doesn't update the config data everywhere in the bot! */
|
||||||
|
reload(): ODPromiseVoid {
|
||||||
|
if (this.debug) this.debug.debug("Reloaded config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
|
||||||
|
//please implement this feature in your own config extension & extend this function.
|
||||||
|
}
|
||||||
|
/**Save the edited config to the filesystem. This is used by the Interactive Setup CLI. It's not recommended to use this while the bot is running. */
|
||||||
|
save(): ODPromiseVoid {
|
||||||
|
if (this.debug) this.debug.debug("Saved config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
|
||||||
|
//please implement this feature in your own config extension & extend this function.
|
||||||
|
}
|
||||||
|
/**Listen for a reload of this JSON file! */
|
||||||
|
onReload(cb:Function){
|
||||||
|
this.reloadListeners.push(cb)
|
||||||
|
}
|
||||||
|
/**Remove all reload listeners. Not recommended! */
|
||||||
|
removeAllReloadListeners(){
|
||||||
|
this.reloadListeners = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,13 +105,13 @@ export class ODConfig extends ODManagerData {
|
|||||||
* const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/")
|
* const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/")
|
||||||
*/
|
*/
|
||||||
export class ODJsonConfig extends ODConfig {
|
export class ODJsonConfig extends ODConfig {
|
||||||
/**An array of listeners to run when the config gets reloaded. These are not executed on the initial loading. */
|
formatter: fjs.custom.BaseFormatter
|
||||||
#reloadListeners: Function[] = []
|
|
||||||
|
|
||||||
constructor(id:ODValidId, file:string, customPath?:string){
|
constructor(id:ODValidId, file:string, customPath?:string, formatter?:fjs.custom.BaseFormatter){
|
||||||
super(id,{})
|
super(id,{})
|
||||||
this.file = (file.endsWith(".json")) ? file : file+".json"
|
this.file = (file.endsWith(".json")) ? file : file+".json"
|
||||||
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file)
|
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file)
|
||||||
|
this.formatter = formatter ?? new fjs.DefaultFormatter(null,true," ")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Init the config. */
|
/**Init the config. */
|
||||||
@@ -79,17 +119,20 @@ export class ODJsonConfig extends ODConfig {
|
|||||||
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
|
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
|
||||||
try{
|
try{
|
||||||
this.data = JSON.parse(fs.readFileSync(this.path).toString())
|
this.data = JSON.parse(fs.readFileSync(this.path).toString())
|
||||||
|
super.init()
|
||||||
}catch(err){
|
}catch(err){
|
||||||
process.emit("uncaughtException",err)
|
process.emit("uncaughtException",err)
|
||||||
throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!")
|
throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**Reload the JSON file. Be aware that this doesn't update classes that used individual parts of the config data! */
|
/**Reload the config. Be aware that this doesn't update the config data everywhere in the bot! */
|
||||||
reload(){
|
reload(){
|
||||||
|
if (!this.initiated) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file hasn't been initiated yet!")
|
||||||
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
|
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
|
||||||
try{
|
try{
|
||||||
this.data = JSON.parse(fs.readFileSync(this.path).toString())
|
this.data = JSON.parse(fs.readFileSync(this.path).toString())
|
||||||
this.#reloadListeners.forEach((cb) => {
|
super.reload()
|
||||||
|
this.reloadListeners.forEach((cb) => {
|
||||||
try{
|
try{
|
||||||
cb()
|
cb()
|
||||||
}catch(err){
|
}catch(err){
|
||||||
@@ -101,12 +144,16 @@ export class ODJsonConfig extends ODConfig {
|
|||||||
throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\"!")
|
throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\"!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**Listen for a reload of this JSON file! */
|
/**Save the edited config to the filesystem. This is used by the Interactive Setup CLI. It's not recommended to use this while the bot is running. */
|
||||||
onReload(cb:Function){
|
save(): ODPromiseVoid {
|
||||||
this.#reloadListeners.push(cb)
|
if (!this.initiated) throw new ODSystemError("Unable to save config \""+nodepath.join("./",this.path)+"\", the file hasn't been initiated yet!")
|
||||||
}
|
try{
|
||||||
/**Remove all reload listeners. Not recommended! */
|
const contents = this.formatter.stringify(this.data)
|
||||||
removeAllReloadListeners(){
|
fs.writeFileSync(this.path,contents)
|
||||||
this.#reloadListeners = []
|
super.save()
|
||||||
|
}catch(err){
|
||||||
|
process.emit("uncaughtException",err)
|
||||||
|
throw new ODSystemError("Unable to save config \""+nodepath.join("./",this.path)+"\"!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,6 +241,8 @@ export class ODConsoleManager {
|
|||||||
historylength = 100
|
historylength = 100
|
||||||
/**An alias to the debugfile manager. (`otdebug.txt`) */
|
/**An alias to the debugfile manager. (`otdebug.txt`) */
|
||||||
debugfile: ODDebugFileManager
|
debugfile: ODDebugFileManager
|
||||||
|
/**Is silent mode enabled? */
|
||||||
|
silent: boolean = false
|
||||||
|
|
||||||
constructor(historylength:number, debugfile:ODDebugFileManager){
|
constructor(historylength:number, debugfile:ODDebugFileManager){
|
||||||
this.historylength = historylength
|
this.historylength = historylength
|
||||||
@@ -253,12 +255,12 @@ export class ODConsoleManager {
|
|||||||
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
|
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
|
||||||
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
|
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
|
||||||
if (message instanceof ODConsoleMessage){
|
if (message instanceof ODConsoleMessage){
|
||||||
message.render()
|
if (!this.silent) message.render()
|
||||||
if (this.debugfile) this.debugfile.writeConsoleMessage(message)
|
if (this.debugfile) this.debugfile.writeConsoleMessage(message)
|
||||||
this.history.push(message)
|
this.history.push(message)
|
||||||
|
|
||||||
}else if (message instanceof ODError){
|
}else if (message instanceof ODError){
|
||||||
message.render()
|
if (!this.silent) message.render()
|
||||||
if (this.debugfile) this.debugfile.writeErrorMessage(message)
|
if (this.debugfile) this.debugfile.writeErrorMessage(message)
|
||||||
this.history.push(message)
|
this.history.push(message)
|
||||||
|
|
||||||
@@ -272,7 +274,7 @@ export class ODConsoleManager {
|
|||||||
else if (type == "error") newMessage = new ODConsoleErrorMessage(message,params)
|
else if (type == "error") newMessage = new ODConsoleErrorMessage(message,params)
|
||||||
else newMessage = new ODConsoleSystemMessage(message,params)
|
else newMessage = new ODConsoleSystemMessage(message,params)
|
||||||
|
|
||||||
newMessage.render()
|
if (!this.silent) newMessage.render()
|
||||||
if (this.debugfile) this.debugfile.writeConsoleMessage(newMessage)
|
if (this.debugfile) this.debugfile.writeConsoleMessage(newMessage)
|
||||||
this.history.push(newMessage)
|
this.history.push(newMessage)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ export interface ODDefaults {
|
|||||||
crashOnError:boolean,
|
crashOnError:boolean,
|
||||||
/**Enable the system responsible for the `--debug` flag. */
|
/**Enable the system responsible for the `--debug` flag. */
|
||||||
debugLoading:boolean,
|
debugLoading:boolean,
|
||||||
|
/**Enable the system responsible for the `--silent` flag. */
|
||||||
|
silentLoading:boolean,
|
||||||
/**When enabled, you're able to use the "!OPENTICKET:dump" command to send the OT debug file. This is only possible when you're the owner of the bot. */
|
/**When enabled, you're able to use the "!OPENTICKET:dump" command to send the OT debug file. This is only possible when you're the owner of the bot. */
|
||||||
allowDumpCommand:boolean,
|
allowDumpCommand:boolean,
|
||||||
/**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */
|
/**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */
|
||||||
@@ -233,6 +235,7 @@ export class ODDefaultsManager {
|
|||||||
errorHandling:true,
|
errorHandling:true,
|
||||||
crashOnError:false,
|
crashOnError:false,
|
||||||
debugLoading:true,
|
debugLoading:true,
|
||||||
|
silentLoading:true,
|
||||||
allowDumpCommand:true,
|
allowDumpCommand:true,
|
||||||
pluginLoading:true,
|
pluginLoading:true,
|
||||||
softPluginLoading:false,
|
softPluginLoading:false,
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import {opendiscord, api, utilities} from "../../index"
|
||||||
|
import {Terminal, terminal} from "terminal-kit"
|
||||||
|
import ansis from "ansis"
|
||||||
|
|
||||||
|
const logo = [
|
||||||
|
" ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ ",
|
||||||
|
" ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ ",
|
||||||
|
" ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ ",
|
||||||
|
" ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ ",
|
||||||
|
" ╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ ",
|
||||||
|
" ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ "
|
||||||
|
]
|
||||||
|
|
||||||
|
/**A utility function to center text to a certain width. */
|
||||||
|
export function centerText(text:string,width:number){
|
||||||
|
if (width < text.length) return text
|
||||||
|
let newWidth = width-ansis.strip(text).length+1
|
||||||
|
let final = " ".repeat(newWidth/2)+text
|
||||||
|
return final
|
||||||
|
}
|
||||||
|
|
||||||
|
/**A utility function to terminate the interactive CLI. */
|
||||||
|
export async function terminate(){
|
||||||
|
terminal.grabInput(false)
|
||||||
|
terminal.clear()
|
||||||
|
terminal.green("👋 Exited the Open Ticket Interactive Setup CLI.\n")
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
terminal.on("key",(name,matches,data) => {
|
||||||
|
if (name == "CTRL_C") terminate()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**Render the header of the interactive CLI. */
|
||||||
|
export function renderHeader(path:(string|number)[]|string){
|
||||||
|
terminal.grabInput(true)
|
||||||
|
terminal.clear().moveTo(1,1)
|
||||||
|
terminal(ansis.hex("#f8ba00")(logo.join("\n")+"\n"))
|
||||||
|
terminal.bold(centerText("Interactive Setup CLI - Version: "+opendiscord.versions.get("opendiscord:version").toString()+" - Support: https://discord.dj-dj.be\n",88))
|
||||||
|
if (typeof path == "string") terminal.cyan(centerText(path+"\n\n",88))
|
||||||
|
else if (path.length < 1) terminal.cyan(centerText("👋 Hi! Welcome to the Open Ticket Interactive Setup CLI! 👋\n\n",88))
|
||||||
|
else terminal.cyan(centerText("🌐 Current Location: "+path.map((v,i) => {
|
||||||
|
if (i == 0) return v.toString()
|
||||||
|
else if (typeof v == "string") return ".\""+v+"\""
|
||||||
|
else if (typeof v == "number") return "."+v
|
||||||
|
}).join("")+"\n\n",88))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderCliModeSelector(backFn:(() => api.ODPromiseVoid)){
|
||||||
|
renderHeader([])
|
||||||
|
terminal(ansis.bold.green("Please select what CLI module you want to use.\n")+ansis.italic.gray("(use arrow keys to navigate, exit using escape)\n"))
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([
|
||||||
|
"✏️ Edit Config "+ansis.gray("=> Edit the current config, add/remove new tickets/questions/panels & more!"),
|
||||||
|
"⏱️ Quick Setup "+ansis.gray("=> A quick and easy way of setting up the bot in your Discord server."),
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
else if (answer.selectedIndex == 0) await (await import("./editConfig.js")).renderEditConfig(async () => {await renderCliModeSelector(backFn)})
|
||||||
|
else if (answer.selectedIndex == 1) await (await import("./quickSetup.js")).renderQuickSetup(async () => {await renderCliModeSelector(backFn)})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function execute(){
|
||||||
|
if (terminal.width < 100 || terminal.height < 35){
|
||||||
|
terminal(ansis.red.bold("\n\nMake sure your console or cmd window has a "+ansis.cyan("minimum width & height")+" of "+ansis.cyan("100x35")+" characters."))
|
||||||
|
terminal(ansis.red.bold("\nOtherwise the Open Ticket Interactive Setup CLI will be rendered incorrectly."))
|
||||||
|
terminal(ansis.red.bold("\nThe current terminal dimensions are: "+ansis.cyan(terminal.width+"x"+terminal.height)+"."))
|
||||||
|
}else await renderCliModeSelector(terminate)
|
||||||
|
}
|
||||||
@@ -0,0 +1,933 @@
|
|||||||
|
import {opendiscord, api, utilities} from "../../index"
|
||||||
|
import {Terminal, terminal} from "terminal-kit"
|
||||||
|
import ansis from "ansis"
|
||||||
|
import {renderHeader} from "./cli"
|
||||||
|
|
||||||
|
export async function renderEditConfig(backFn:(() => api.ODPromiseVoid)){
|
||||||
|
renderHeader([])
|
||||||
|
terminal(ansis.bold.green("Please select which config you would like to edit.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const checkerList = opendiscord.checkers.getAll()
|
||||||
|
const checkerNameList = checkerList.map((checker) => (checker.options.cliDisplayName ? checker.options.cliDisplayName+" ("+checker.config.file+")" : checker.config.file))
|
||||||
|
const checkerNameLength = utilities.getLongestLength(checkerNameList)
|
||||||
|
const finalCheckerNameList = checkerNameList.map((name,index) => name.padEnd(checkerNameLength+5," ")+ansis.gray(checkerList[index].options.cliDisplayDescription ? "=> "+checkerList[index].options.cliDisplayDescription : ""))
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(finalCheckerNameList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
const checker = checkerList[answer.selectedIndex]
|
||||||
|
const configData = checker.config.data as api.ODValidJsonType
|
||||||
|
await chooseConfigStructure(checker,async () => {await renderEditConfig(backFn)},checker.structure,configData,{},NaN,["("+checker.config.path+")"])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function chooseConfigStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerStructure,data:api.ODValidJsonType,parent:object|any[],parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (structure instanceof api.ODCheckerObjectStructure && typeof data == "object" && !Array.isArray(data) && data) await renderConfigObjectStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerEnabledObjectStructure && typeof data == "object" && !Array.isArray(data) && data) await renderConfigEnabledObjectStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerObjectSwitchStructure && typeof data == "object" && !Array.isArray(data) && data) await renderConfigObjectSwitchStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerArrayStructure && Array.isArray(data)) await renderConfigArrayStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerBooleanStructure && typeof data == "boolean") await renderConfigBooleanStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerNumberStructure && typeof data == "number") await renderConfigNumberStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerStringStructure && typeof data == "string") await renderConfigStringStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerNullStructure && data === null) await renderConfigNullStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else if (structure instanceof api.ODCheckerTypeSwitchStructure) await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
else terminal.red.bold("❌ Unable to detect type of variable! Please try to edit this property in the JSON file itself!")
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigObjectStructureSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerObjectStructure,data:object,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (typeof data != "object" || Array.isArray(data)) throw new api.ODSystemError("OT CLI => Property is not of the type 'object'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select which variable you would like to edit.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
if (!structure.options.children) return await backFn()
|
||||||
|
|
||||||
|
if (structure.options.cliDisplayName){
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName)+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = structure.options.children.filter((child) => !child.cliHideInEditMode)
|
||||||
|
const nameList = list.map((child) => (child.checker.options.cliDisplayName ? child.checker.options.cliDisplayName : child.key))
|
||||||
|
const nameLength = utilities.getLongestLength(nameList)
|
||||||
|
const finalnameList = nameList.map((name,index) => name.padEnd(nameLength+5," ")+ansis.gray((!list[index].checker.options.cliHideDescriptionInParent && list[index].checker.options.cliDisplayDescription) ? "=> "+list[index].checker.options.cliDisplayDescription : ""))
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(finalnameList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold.defaultColor,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
const subStructure = list[answer.selectedIndex]
|
||||||
|
const subData = data[subStructure.key]
|
||||||
|
await chooseConfigStructure(checker,async () => {await renderConfigObjectStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)},subStructure.checker,subData,data,subStructure.key,[...path,subStructure.key])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigEnabledObjectStructureSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerEnabledObjectStructure,data:object,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (typeof data != "object" || Array.isArray(data)) throw new api.ODSystemError("OT CLI => Property is not of the type 'object'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
const enabledProperty = structure.options.property
|
||||||
|
const subStructure = structure.options.checker
|
||||||
|
if (!enabledProperty || !subStructure || !subStructure.options.children) return await backFn()
|
||||||
|
|
||||||
|
if (!subStructure.options.children.find((child) => child.key === structure.options.property)){
|
||||||
|
if (typeof structure.options.enabledValue == "string") subStructure.options.children.unshift({key:enabledProperty,optional:false,priority:1,checker:new api.ODCheckerStringStructure("opendiscord:CLI-checker-enabled-object-structure",{})})
|
||||||
|
else if (typeof structure.options.enabledValue == "number") subStructure.options.children.unshift({key:enabledProperty,optional:false,priority:1,checker:new api.ODCheckerNumberStructure("opendiscord:CLI-checker-enabled-object-structure",{})})
|
||||||
|
else if (typeof structure.options.enabledValue == "boolean") subStructure.options.children.unshift({key:enabledProperty,optional:false,priority:1,checker:new api.ODCheckerBooleanStructure("opendiscord:CLI-checker-enabled-object-structure",{})})
|
||||||
|
}
|
||||||
|
|
||||||
|
await chooseConfigStructure(checker,backFn,subStructure,data,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigObjectSwitchStructureSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerObjectSwitchStructure,data:object,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (typeof data != "object" || Array.isArray(data)) throw new api.ODSystemError("OT CLI => Property is not of the type 'object'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
if (!structure.options.objects) return await backFn()
|
||||||
|
|
||||||
|
let didMatch: boolean = false
|
||||||
|
for (const objectTemplate of structure.options.objects){
|
||||||
|
if (objectTemplate.properties.every((prop) => data[prop.key] === prop.value)){
|
||||||
|
//object template matches data
|
||||||
|
const subStructure = objectTemplate.checker
|
||||||
|
didMatch = true
|
||||||
|
await chooseConfigStructure(checker,backFn,subStructure,data,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!didMatch) throw new api.ODSystemError("OT CLI => Unable to detect type of object in the object switch. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigArrayStructureSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerArrayStructure,data:any[],parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (!Array.isArray(data)) throw new api.ODSystemError("OT CLI => Property is not of the type 'array'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select what you would like to do.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
if (!structure.options.propertyChecker) return await backFn()
|
||||||
|
|
||||||
|
if (structure.options.cliDisplayName || typeof parentIndex == "string" || !isNaN(parentIndex)){
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? parentIndex.toString())+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const propertyName = structure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
const answer = await terminal.singleColumnMenu(data.length < 1 ? ["Add "+propertyName] : [
|
||||||
|
"Add "+propertyName,
|
||||||
|
"Edit "+propertyName,
|
||||||
|
"Move "+propertyName,
|
||||||
|
"Remove "+propertyName,
|
||||||
|
"Duplicate "+propertyName
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
const backFnFunc = async () => {await renderConfigArrayStructureSelector(checker,backFn,structure,data,parent,parentIndex,path)}
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
if (answer.selectedIndex == 0) await chooseAdditionConfigStructure(checker,backFnFunc,async (newData) => {
|
||||||
|
data[data.length] = newData
|
||||||
|
await checker.config.save()
|
||||||
|
await backFnFunc()
|
||||||
|
},structure.options.propertyChecker,data,data.length,path,[])
|
||||||
|
else if (answer.selectedIndex == 1) await renderConfigArrayStructureEditSelector(checker,backFnFunc,structure,structure.options.propertyChecker,data,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 2) await renderconfigArrayStructureMoveSelector(checker,backFnFunc,structure,structure.options.propertyChecker,data,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 3) await renderconfigArrayStructureRemoveSelector(checker,backFnFunc,structure,structure.options.propertyChecker,data,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 4) await renderConfigArrayStructureDuplicateSelector(checker,backFnFunc,structure,structure.options.propertyChecker,data,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigArrayStructureEditSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),arrayStructure:api.ODCheckerArrayStructure,structure:api.ODCheckerStructure,data:any[],parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
const propertyName = arrayStructure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select the "+propertyName+" you would like to edit.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const longestDataListName = Math.max(...data.map((d,i) => getArrayPreviewStructureNameLength(structure,d,data,i)))
|
||||||
|
const dataList = data.map((d,i) => (i+1)+". "+getArrayPreviewFromStructure(structure,d,data,i,longestDataListName))
|
||||||
|
const dataAnswer = await terminal.singleColumnMenu(dataList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (dataAnswer.canceled) return await backFn()
|
||||||
|
const subData = data[dataAnswer.selectedIndex]
|
||||||
|
await chooseConfigStructure(checker,async () => {await renderConfigArrayStructureEditSelector(checker,backFn,arrayStructure,structure,data,parent,parentIndex,path)},structure,subData,data,dataAnswer.selectedIndex,[...path,dataAnswer.selectedIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderconfigArrayStructureMoveSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),arrayStructure:api.ODCheckerArrayStructure,structure:api.ODCheckerStructure,data:any[],parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
const propertyName = arrayStructure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select the "+propertyName+" you would like to move.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const longestDataListName = Math.max(...data.map((d,i) => getArrayPreviewStructureNameLength(structure,d,data,i)))
|
||||||
|
const dataList = data.map((d,i) => (i+1)+". "+getArrayPreviewFromStructure(structure,d,data,i,longestDataListName))
|
||||||
|
const dataAnswer = await terminal.singleColumnMenu(dataList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (dataAnswer.canceled) return await backFn()
|
||||||
|
|
||||||
|
renderHeader([...path,dataAnswer.selectedIndex])
|
||||||
|
terminal(ansis.bold.green("Please select the position you would like to move to.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const moveAnswer = await terminal.singleColumnMenu(data.map((d,i) => "Position "+(i+1)),{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (moveAnswer.canceled) return await renderconfigArrayStructureMoveSelector(checker,backFn,arrayStructure,structure,data,parent,parentIndex,path)
|
||||||
|
|
||||||
|
const subData = data[dataAnswer.selectedIndex]
|
||||||
|
const slicedData = [...data.slice(0,dataAnswer.selectedIndex),...data.slice(dataAnswer.selectedIndex+1)]
|
||||||
|
const insertedData = [...slicedData.slice(0,moveAnswer.selectedIndex),subData,...slicedData.slice(moveAnswer.selectedIndex)]
|
||||||
|
insertedData.forEach((d,i) => data[i] = d)
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Property moved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderconfigArrayStructureRemoveSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),arrayStructure:api.ODCheckerArrayStructure,structure:api.ODCheckerStructure,data:any[],parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
const propertyName = arrayStructure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select the "+propertyName+" you would like to delete.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const longestDataListName = Math.max(...data.map((d,i) => getArrayPreviewStructureNameLength(structure,d,data,i)))
|
||||||
|
const dataList = data.map((d,i) => (i+1)+". "+getArrayPreviewFromStructure(structure,d,data,i,longestDataListName))
|
||||||
|
const dataAnswer = await terminal.singleColumnMenu(dataList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (dataAnswer.canceled) return await backFn()
|
||||||
|
data.splice(dataAnswer.selectedIndex,1)
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Property deleted succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigArrayStructureDuplicateSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),arrayStructure:api.ODCheckerArrayStructure,structure:api.ODCheckerStructure,data:any[],parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
const propertyName = arrayStructure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("Please select the "+propertyName+" you would like to duplicate.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const longestDataListName = Math.max(...data.map((d,i) => getArrayPreviewStructureNameLength(structure,d,data,i)))
|
||||||
|
const dataList = data.map((d,i) => (i+1)+". "+getArrayPreviewFromStructure(structure,d,data,i,longestDataListName))
|
||||||
|
const dataAnswer = await terminal.singleColumnMenu(dataList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (dataAnswer.canceled) return await backFn()
|
||||||
|
data.push(JSON.parse(JSON.stringify(data[dataAnswer.selectedIndex])))
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Property duplicated succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigBooleanStructureEditor(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerBooleanStructure,data:boolean,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (typeof data != "boolean") throw new api.ODSystemError("OT CLI => Property is not of the type 'boolean'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now editing "+(typeof parentIndex == "string" ? "the boolean property "+ansis.blue("\""+parentIndex+"\"") : "boolean property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nCurrent value: "+ansis.bold[data ? "green" : "red"](data.toString())+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(["false (Disabled)","true (Enabled)"],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = (answer.selectedIndex == 0) ? false : true
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
parent[parentIndex] = newValue
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.gray("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderConfigBooleanStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigNumberStructureEditor(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerNumberStructure,data:number,parent:object,parentIndex:string|number,path:(string|number)[],prefillValue?:string){
|
||||||
|
if (typeof data != "number") throw new api.ODSystemError("OT CLI => Property is not of the type 'number'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now editing "+(typeof parentIndex == "string" ? "the number property "+ansis.blue("\""+parentIndex+"\"") : "number property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(insert a new value and press enter, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nCurrent value: "+ansis.bold.blue(data.toString())+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.inputField({
|
||||||
|
default:prefillValue,
|
||||||
|
style:terminal.cyan,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (typeof answer != "string") return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = Number(answer.replaceAll(",","."))
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
parent[parentIndex] = newValue
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderConfigNumberStructureEditor(checker,backFn,structure,data,parent,parentIndex,path,answer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigStringStructureEditor(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerStringStructure,data:string,parent:object,parentIndex:string|number,path:(string|number)[],prefillValue?:string){
|
||||||
|
if (typeof data != "string") throw new api.ODSystemError("OT CLI => Property is not of the type 'string'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now editing "+(typeof parentIndex == "string" ? "the string property "+ansis.blue("\""+parentIndex+"\"") : "string property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(insert a new value and press enter, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nCurrent value:"+(data.includes("\n") ? "\n" : " \"")+ansis.bold.blue(data)+ansis.gray(!data.includes("\n") ? "\"\n" : "\n"))
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const customExtraOptions = (structure instanceof api.ODCheckerCustomStructure_DiscordId) ? structure.extraOptions : undefined
|
||||||
|
const customAutocompleteFunc = structure.options.cliAutocompleteFunc ? await structure.options.cliAutocompleteFunc() : null
|
||||||
|
const autocompleteList = ((customAutocompleteFunc ?? structure.options.cliAutocompleteList) ?? customExtraOptions) ?? structure.options.choices
|
||||||
|
const autoCompleteMenuOpts: Terminal.SingleLineMenuOptions = {
|
||||||
|
style:terminal.white,
|
||||||
|
selectedStyle:terminal.bgBlue.white
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = terminal.inputField({
|
||||||
|
default:prefillValue,
|
||||||
|
style:terminal.cyan,
|
||||||
|
hintStyle:terminal.gray,
|
||||||
|
cancelable:false,
|
||||||
|
autoComplete:autocompleteList,
|
||||||
|
autoCompleteHint:(!!autocompleteList),
|
||||||
|
autoCompleteMenu:(autocompleteList) ? autoCompleteMenuOpts as Terminal.Autocompletion : false
|
||||||
|
})
|
||||||
|
|
||||||
|
terminal.on("key",async (name:string,matches:string[],data:object) => {
|
||||||
|
if (name == "ESCAPE"){
|
||||||
|
terminal.removeListener("key","cli-render-string-structure-edit")
|
||||||
|
input.abort()
|
||||||
|
await backFn()
|
||||||
|
}
|
||||||
|
},({id:"cli-render-string-structure-edit"} as any))
|
||||||
|
|
||||||
|
const answer = await input.promise
|
||||||
|
terminal.removeListener("key","cli-render-string-structure-edit")
|
||||||
|
if (typeof answer != "string") return
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = answer.replaceAll("\\n","\n")
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
parent[parentIndex] = newValue
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderConfigStringStructureEditor(checker,backFn,structure,data,parent,parentIndex,path,answer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigNullStructureEditor(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerNullStructure,data:null,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
if (data !== null) throw new api.ODSystemError("OT CLI => Property is not of the type 'null'. Please check your config for possible errors. (index: "+parentIndex+", path: "+path.join(".")+")")
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now editing "+(typeof parentIndex == "string" ? "the null property "+ansis.blue("\""+parentIndex+"\"") : "null property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nCurrent value: "+ansis.bold.blue("null")+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(["null"],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = null
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
parent[parentIndex] = newValue
|
||||||
|
|
||||||
|
await checker.config.save()
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await backFn()
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderConfigNullStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderConfigTypeSwitchStructureEditor(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),structure:api.ODCheckerTypeSwitchStructure,data:any,parent:object,parentIndex:string|number,path:(string|number)[]){
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now editing "+(typeof parentIndex == "string" ? "the property "+ansis.blue("\""+parentIndex+"\"") : "property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nCurrent value: "+ansis.bold.blue(data.toString())+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const actionsList: string[] = []
|
||||||
|
if (structure.options.boolean) actionsList.push("Edit as boolean")
|
||||||
|
if (structure.options.string) actionsList.push("Edit as string")
|
||||||
|
if (structure.options.number) actionsList.push("Edit as number")
|
||||||
|
if (structure.options.object) actionsList.push("Edit as object")
|
||||||
|
if (structure.options.array) actionsList.push("Edit as array/list")
|
||||||
|
if (structure.options.null) actionsList.push("Edit as null")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(actionsList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run selected structure editor (untested)
|
||||||
|
if (answer.selectedText.startsWith("Edit as boolean") && structure.options.boolean) await renderConfigBooleanStructureEditor(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.boolean,false,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedText.startsWith("Edit as string") && structure.options.string) await renderConfigStringStructureEditor(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.string,data.toString(),parent,parentIndex,path)
|
||||||
|
else if (answer.selectedText.startsWith("Edit as number") && structure.options.number) await renderConfigNumberStructureEditor(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.number,0,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedText.startsWith("Edit as object") && structure.options.object) await renderConfigObjectStructureSelector(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.object,data,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedText.startsWith("Edit as array/list") && structure.options.array) await renderConfigArrayStructureSelector(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.array,data,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedText.startsWith("Edit as null") && structure.options.null) await renderConfigNullStructureEditor(checker,async () => {await renderConfigTypeSwitchStructureEditor(checker,backFn,structure,data,parent,parentIndex,path)},structure.options.null,null,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArrayPreviewStructureNameLength(structure:api.ODCheckerStructure,data:api.ODValidJsonType,parent:object,parentIndex:string|number): number {
|
||||||
|
if (structure instanceof api.ODCheckerBooleanStructure && typeof data == "boolean") return data.toString().length
|
||||||
|
else if (structure instanceof api.ODCheckerNumberStructure && typeof data == "number") return data.toString().length
|
||||||
|
else if (structure instanceof api.ODCheckerStringStructure && typeof data == "string") return data.length
|
||||||
|
else if (structure instanceof api.ODCheckerNullStructure && data === null) return "Null".length
|
||||||
|
else if (structure instanceof api.ODCheckerArrayStructure && Array.isArray(data)) return "Array".length
|
||||||
|
else if (structure instanceof api.ODCheckerObjectStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
if (!structure.options.cliDisplayKeyInParentArray) return "Object".length
|
||||||
|
else return data[structure.options.cliDisplayKeyInParentArray].toString().length
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerEnabledObjectStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
const subStructure = structure.options.checker
|
||||||
|
if (!subStructure) return "<unknown-property>".length
|
||||||
|
return getArrayPreviewStructureNameLength(subStructure,data,parent,parentIndex)
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerObjectSwitchStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
for (const objectTemplate of (structure.options.objects ?? [])){
|
||||||
|
if (objectTemplate.properties.every((prop) => data[prop.key] === prop.value)){
|
||||||
|
//object template matches data
|
||||||
|
const subStructure = objectTemplate.checker
|
||||||
|
return getArrayPreviewStructureNameLength(subStructure,data,parent,parentIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "<unknown-property>".length
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerTypeSwitchStructure){
|
||||||
|
if (typeof data == "boolean" && structure.options.boolean) return getArrayPreviewStructureNameLength(structure.options.boolean,data,parent,parentIndex)
|
||||||
|
else if (typeof data == "number" && structure.options.number) return getArrayPreviewStructureNameLength(structure.options.number,data,parent,parentIndex)
|
||||||
|
else if (typeof data == "string" && structure.options.string) return getArrayPreviewStructureNameLength(structure.options.string,data,parent,parentIndex)
|
||||||
|
else if (typeof data == "object" && !Array.isArray(data) && data && structure.options.object) return getArrayPreviewStructureNameLength(structure.options.object,data,parent,parentIndex)
|
||||||
|
else if (Array.isArray(data) && structure.options.array) return getArrayPreviewStructureNameLength(structure.options.array,data,parent,parentIndex)
|
||||||
|
else if (data === null && structure.options.null) return getArrayPreviewStructureNameLength(structure.options.null,data,parent,parentIndex)
|
||||||
|
else return "<unknown-property>".length
|
||||||
|
}else return "<unknown-property>".length
|
||||||
|
}
|
||||||
|
|
||||||
|
function getArrayPreviewFromStructure(structure:api.ODCheckerStructure,data:api.ODValidJsonType,parent:object,parentIndex:string|number,nameLength:number): string {
|
||||||
|
if (structure instanceof api.ODCheckerBooleanStructure && typeof data == "boolean") return data.toString()
|
||||||
|
else if (structure instanceof api.ODCheckerNumberStructure && typeof data == "number") return data.toString()
|
||||||
|
else if (structure instanceof api.ODCheckerStringStructure && typeof data == "string") return data
|
||||||
|
else if (structure instanceof api.ODCheckerNullStructure && data === null) return "Null"
|
||||||
|
else if (structure instanceof api.ODCheckerArrayStructure && Array.isArray(data)) return "Array"
|
||||||
|
else if (structure instanceof api.ODCheckerObjectStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
const additionalKeys = (structure.options.cliDisplayAdditionalKeysInParentArray ?? []).map((key) => key+": "+data[key].toString()).join(", ")
|
||||||
|
if (!structure.options.cliDisplayKeyInParentArray) return "Object"
|
||||||
|
else return data[structure.options.cliDisplayKeyInParentArray].toString().padEnd(nameLength+5," ")+ansis.gray(additionalKeys.length > 0 ? "("+additionalKeys+")" : "")
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerEnabledObjectStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
const subStructure = structure.options.checker
|
||||||
|
if (!subStructure) return "<unknown-property>"
|
||||||
|
return getArrayPreviewFromStructure(subStructure,data,parent,parentIndex,nameLength)
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerObjectSwitchStructure && typeof data == "object" && !Array.isArray(data) && data){
|
||||||
|
for (const objectTemplate of (structure.options.objects ?? [])){
|
||||||
|
if (objectTemplate.properties.every((prop) => data[prop.key] === prop.value)){
|
||||||
|
//object template matches data
|
||||||
|
const subStructure = objectTemplate.checker
|
||||||
|
return getArrayPreviewFromStructure(subStructure,data,parent,parentIndex,nameLength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "<unknown-property>"
|
||||||
|
|
||||||
|
}else if (structure instanceof api.ODCheckerTypeSwitchStructure){
|
||||||
|
if (typeof data == "boolean" && structure.options.boolean) return getArrayPreviewFromStructure(structure.options.boolean,data,parent,parentIndex,nameLength)
|
||||||
|
else if (typeof data == "number" && structure.options.number) return getArrayPreviewFromStructure(structure.options.number,data,parent,parentIndex,nameLength)
|
||||||
|
else if (typeof data == "string" && structure.options.string) return getArrayPreviewFromStructure(structure.options.string,data,parent,parentIndex,nameLength)
|
||||||
|
else if (typeof data == "object" && !Array.isArray(data) && data && structure.options.object) return getArrayPreviewFromStructure(structure.options.object,data,parent,parentIndex,nameLength)
|
||||||
|
else if (Array.isArray(data) && structure.options.array) return getArrayPreviewFromStructure(structure.options.array,data,parent,parentIndex,nameLength)
|
||||||
|
else if (data === null && structure.options.null) return getArrayPreviewFromStructure(structure.options.null,data,parent,parentIndex,nameLength)
|
||||||
|
else return "<unknown-property>"
|
||||||
|
}else return "<unknown-property>"
|
||||||
|
}
|
||||||
|
|
||||||
|
async function chooseAdditionConfigStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
if (structure instanceof api.ODCheckerObjectStructure) await renderAdditionConfigObjectStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerBooleanStructure) await renderAdditionConfigBooleanStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerNumberStructure) await renderAdditionConfigNumberStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerStringStructure) await renderAdditionConfigStringStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerNullStructure) await renderAdditionConfigNullStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerEnabledObjectStructure) await renderAdditionConfigEnabledObjectStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerObjectSwitchStructure) await renderAdditionConfigObjectSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerArrayStructure) await renderAdditionConfigArrayStructureSelector(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else if (structure instanceof api.ODCheckerTypeSwitchStructure) await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
else await backFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigObjectStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerObjectStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[],localData:object={}){
|
||||||
|
const children = structure.options.children ?? []
|
||||||
|
const skipKeys = (structure.options.cliInitSkipKeys ?? [])
|
||||||
|
//add skipped properties
|
||||||
|
for (const key of skipKeys){
|
||||||
|
const childStructure = children.find((c) => c.key == key)
|
||||||
|
if (childStructure){
|
||||||
|
const defaultValue = childStructure.checker.options.cliInitDefaultValue
|
||||||
|
if (childStructure.checker instanceof api.ODCheckerBooleanStructure) localData[key] = (typeof defaultValue == "boolean" ? defaultValue : false)
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerNumberStructure) localData[key] = (typeof defaultValue == "number" ? defaultValue : 0)
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerStringStructure) localData[key] = (typeof defaultValue == "string" ? defaultValue : "")
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerNullStructure) localData[key] = (defaultValue === null ? defaultValue : null)
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerArrayStructure) localData[key] = (Array.isArray(defaultValue) ? JSON.parse(JSON.stringify(defaultValue)) : [])
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerObjectStructure) localData[key] = ((typeof defaultValue == "object" && !Array.isArray(defaultValue) && defaultValue) ? JSON.parse(JSON.stringify(defaultValue)) : {})
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerObjectSwitchStructure) localData[key] = ((typeof defaultValue == "object" && !Array.isArray(defaultValue) && defaultValue) ? JSON.parse(JSON.stringify(defaultValue)) : {})
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerEnabledObjectStructure) localData[key] = ((typeof defaultValue == "object" && !Array.isArray(defaultValue) && defaultValue) ? JSON.parse(JSON.stringify(defaultValue)) : {})
|
||||||
|
else if (childStructure.checker instanceof api.ODCheckerTypeSwitchStructure && typeof defaultValue != "undefined") localData[key] = JSON.parse(JSON.stringify(defaultValue))
|
||||||
|
else throw new api.ODSystemError("OT CLI => Object skip key has an invalid checker structure! key: "+key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//add properties that need to be configured
|
||||||
|
const configChildren = children.filter((c) => !skipKeys.includes(c.key)).map((c) => {return {key:c.key,checker:c.checker}})
|
||||||
|
await configureAdditionObjectProperties(checker,configChildren,0,localData,[...path,parentIndex],(typeof parentIndex == "number") ? [...localPath] : [...localPath,parentIndex],async () => {
|
||||||
|
//go back to previous screen
|
||||||
|
await backFn()
|
||||||
|
},async () => {
|
||||||
|
//finish setup
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await nextFn(localData)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function configureAdditionObjectProperties(checker:api.ODChecker,children:{key:string,checker:api.ODCheckerStructure}[],currentIndex:number,localData:object,path:(string|number)[],localPath:(string|number)[],backFn:(() => api.ODPromiseVoid),nextFn:(() => api.ODPromiseVoid)){
|
||||||
|
if (children.length < 1) return await nextFn()
|
||||||
|
|
||||||
|
const child = children[currentIndex]
|
||||||
|
await chooseAdditionConfigStructure(checker,async () => {
|
||||||
|
if (children[currentIndex-1]) await configureAdditionObjectProperties(checker,children,currentIndex-1,localData,path,localPath,backFn,nextFn)
|
||||||
|
else await backFn()
|
||||||
|
},async (data) => {
|
||||||
|
localData[child.key] = data
|
||||||
|
if (children[currentIndex+1]) await configureAdditionObjectProperties(checker,children,currentIndex+1,localData,path,localPath,backFn,nextFn)
|
||||||
|
else await nextFn()
|
||||||
|
},child.checker,localData,child.key,path,localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigEnabledObjectStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerEnabledObjectStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
const enabledProperty = structure.options.property
|
||||||
|
const enabledValue = structure.options.enabledValue
|
||||||
|
const subStructure = structure.options.checker
|
||||||
|
if (!enabledProperty || !subStructure || !subStructure.options.children) return await backFn()
|
||||||
|
|
||||||
|
let propertyStructure: api.ODCheckerBooleanStructure|api.ODCheckerNumberStructure|api.ODCheckerStringStructure
|
||||||
|
if (typeof enabledValue == "string") propertyStructure = new api.ODCheckerStringStructure("opendiscord:CLI-checker-enabled-object-structure",{})
|
||||||
|
else if (typeof enabledValue == "number") propertyStructure = new api.ODCheckerNumberStructure("opendiscord:CLI-checker-enabled-object-structure",{})
|
||||||
|
else if (typeof enabledValue == "boolean") propertyStructure = new api.ODCheckerBooleanStructure("opendiscord:CLI-checker-enabled-object-structure",{})
|
||||||
|
else throw new Error("OT CLI => enabled object structure has an invalid type of enabledProperty. It must be a primitive boolean/number/string.")
|
||||||
|
|
||||||
|
const localData = {}
|
||||||
|
await chooseAdditionConfigStructure(checker,backFn,async (data) => {
|
||||||
|
if (data === enabledValue) await renderAdditionConfigObjectStructure(checker,async () => {await renderAdditionConfigEnabledObjectStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,subStructure,parent,parentIndex,path,localPath,localData)
|
||||||
|
else{
|
||||||
|
localData[enabledProperty] = data
|
||||||
|
//copy old object checker to new object checker => all options get de-referenced (this is needed for the new object skip keys are temporary)
|
||||||
|
const newStructure = new api.ODCheckerObjectStructure(subStructure.id,{children:[]})
|
||||||
|
|
||||||
|
//copy all options over to the new checker
|
||||||
|
newStructure.options.children = [...subStructure.options.children]
|
||||||
|
newStructure.options.cliInitSkipKeys = subStructure.options.children.map((child) => child.key)
|
||||||
|
for (const key of Object.keys(subStructure.options)){
|
||||||
|
if (key != "children" && key != "cliInitSkipKeys") newStructure.options[key] = subStructure.options[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
//adds all properties to object as "skipKeys", then continues to next function
|
||||||
|
await renderAdditionConfigObjectStructure(checker,async () => {await renderAdditionConfigEnabledObjectStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,newStructure,parent,parentIndex,path,localPath,localData)
|
||||||
|
await nextFn(localData)
|
||||||
|
}
|
||||||
|
},propertyStructure,localData,enabledProperty,[...path,parentIndex],[...localPath,parentIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigObjectSwitchStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerObjectSwitchStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("What type of object would you like to add?\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(structure.options.objects.map((obj) => obj.name),{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
const objectTemplate = structure.options.objects[answer.selectedIndex]
|
||||||
|
|
||||||
|
//copy old object checker to new object checker => all options get de-referenced (this is needed for the new object switch properties which are temporary)
|
||||||
|
const oldStructure = objectTemplate.checker
|
||||||
|
const newStructure = new api.ODCheckerObjectStructure(oldStructure.id,{children:[]})
|
||||||
|
|
||||||
|
//copy all options over to the new checker
|
||||||
|
newStructure.options.children = [...oldStructure.options.children]
|
||||||
|
newStructure.options.cliInitSkipKeys = [...(oldStructure.options.cliInitSkipKeys ?? [])]
|
||||||
|
for (const key of Object.keys(oldStructure.options)){
|
||||||
|
if (key != "children" && key != "cliInitSkipKeys") newStructure.options[key] = oldStructure.options[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
//add the keys of the object switch properties to the 'cliInitSkipKeys' because they need to be skipped.
|
||||||
|
objectTemplate.properties.map((p) => p.key).forEach((p) => {
|
||||||
|
if (!newStructure.options.cliInitSkipKeys) newStructure.options.cliInitSkipKeys = [p]
|
||||||
|
else if (!newStructure.options.cliInitSkipKeys.includes(p)) newStructure.options.cliInitSkipKeys.push(p)
|
||||||
|
})
|
||||||
|
|
||||||
|
//add structure checkers for all properties
|
||||||
|
for (const prop of objectTemplate.properties){
|
||||||
|
if (!newStructure.options.children.find((child) => child.key === prop.key)){
|
||||||
|
if (typeof prop.value == "string") newStructure.options.children.unshift({key:prop.key,optional:false,priority:1,checker:new api.ODCheckerStringStructure("opendiscord:CLI-checker-object-switch-structure",{cliInitDefaultValue:prop.value})})
|
||||||
|
else if (typeof prop.value == "number") newStructure.options.children.unshift({key:prop.key,optional:false,priority:1,checker:new api.ODCheckerNumberStructure("opendiscord:CLI-checker-object-switch-structure",{cliInitDefaultValue:prop.value})})
|
||||||
|
else if (typeof prop.value == "boolean") newStructure.options.children.unshift({key:prop.key,optional:false,priority:1,checker:new api.ODCheckerBooleanStructure("opendiscord:CLI-checker-object-switch-structure",{cliInitDefaultValue:prop.value})})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await chooseAdditionConfigStructure(checker,backFn,nextFn,newStructure,parent,parentIndex,path,localPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigBooleanStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerBooleanStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("You are now creating "+(typeof parentIndex == "string" ? "the boolean property "+ansis.blue("\""+parentIndex+"\"") : "boolean property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(["false (Disabled)","true (Enabled)"],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = (answer.selectedIndex == 0) ? false : true
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await nextFn(newValue)
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.gray("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderAdditionConfigBooleanStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigNumberStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerNumberStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[],prefillValue?:string){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("You are now creating "+(typeof parentIndex == "string" ? "the number property "+ansis.blue("\""+parentIndex+"\"") : "number property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(insert a new value and press enter, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.inputField({
|
||||||
|
default:prefillValue,
|
||||||
|
style:terminal.cyan,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (typeof answer != "string") return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = Number(answer.replaceAll(",","."))
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await nextFn(newValue)
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderAdditionConfigNumberStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath,answer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigStringStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerStringStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[],prefillValue?:string){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("You are now creating "+(typeof parentIndex == "string" ? "the string property "+ansis.blue("\""+parentIndex+"\"") : "string property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(insert a new value and press enter, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const customExtraOptions = (structure instanceof api.ODCheckerCustomStructure_DiscordId) ? structure.extraOptions : undefined
|
||||||
|
const customAutocompleteFunc = structure.options.cliAutocompleteFunc ? await structure.options.cliAutocompleteFunc() : null
|
||||||
|
const autocompleteList = ((customAutocompleteFunc ?? structure.options.cliAutocompleteList) ?? customExtraOptions) ?? structure.options.choices
|
||||||
|
const autoCompleteMenuOpts: Terminal.SingleLineMenuOptions = {
|
||||||
|
style:terminal.white,
|
||||||
|
selectedStyle:terminal.bgBlue.white
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = terminal.inputField({
|
||||||
|
default:prefillValue,
|
||||||
|
style:terminal.cyan,
|
||||||
|
hintStyle:terminal.gray,
|
||||||
|
cancelable:false,
|
||||||
|
autoComplete:autocompleteList,
|
||||||
|
autoCompleteHint:(!!autocompleteList),
|
||||||
|
autoCompleteMenu:(autocompleteList) ? autoCompleteMenuOpts as Terminal.Autocompletion : false
|
||||||
|
})
|
||||||
|
|
||||||
|
terminal.on("key",async (name:string,matches:string[],data:object) => {
|
||||||
|
if (name == "ESCAPE"){
|
||||||
|
terminal.removeListener("key","cli-render-string-structure-add")
|
||||||
|
input.abort()
|
||||||
|
await backFn()
|
||||||
|
}
|
||||||
|
},({id:"cli-render-string-structure-add"} as any))
|
||||||
|
|
||||||
|
const answer = await input.promise
|
||||||
|
terminal.removeListener("key","cli-render-string-structure-add")
|
||||||
|
if (typeof answer != "string") return
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = answer.replaceAll("\\n","\n")
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await nextFn(newValue)
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderAdditionConfigStringStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath,answer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigNullStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerNullStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("You are now creating "+(typeof parentIndex == "string" ? "the null property "+ansis.blue("\""+parentIndex+"\"") : "null property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(["null"],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run config checker
|
||||||
|
const newValue = null
|
||||||
|
const newPath = [...path]
|
||||||
|
newPath.shift()
|
||||||
|
checker.messages = [] //manually clear previous messages
|
||||||
|
const isDataValid = structure.check(checker,newValue,newPath)
|
||||||
|
|
||||||
|
if (isDataValid){
|
||||||
|
terminal.bold.blue("\n\n✅ Variable saved succesfully!")
|
||||||
|
await utilities.timer(400)
|
||||||
|
await nextFn(newValue)
|
||||||
|
}else{
|
||||||
|
const messages = checker.messages.map((msg) => "=> ["+msg.type.toUpperCase()+"] "+msg.message).join("\n")
|
||||||
|
terminal.bold.blue("\n\n❌ Variable is invalid! Please try again!")
|
||||||
|
terminal.red("\n"+messages)
|
||||||
|
await utilities.timer(1000+(2000*checker.messages.length))
|
||||||
|
await renderAdditionConfigNullStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigArrayStructureSelector(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerArrayStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[],localData:any[]=[]){
|
||||||
|
renderHeader([...path,parentIndex])
|
||||||
|
terminal(ansis.bold.green("Please select what you would like to do with the new array.\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
if (!structure.options.propertyChecker) return await backFn()
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const propertyName = structure.options.cliDisplayPropertyName ?? "index"
|
||||||
|
const answer = await terminal.singleColumnMenu(localData.length < 1 ? [ansis.magenta("-> Continue to next variable"),"Add "+propertyName] : [
|
||||||
|
ansis.magenta("-> Continue to next variable"),
|
||||||
|
"Add "+propertyName,
|
||||||
|
"Edit "+propertyName,
|
||||||
|
"Move "+propertyName,
|
||||||
|
"Remove "+propertyName,
|
||||||
|
"Duplicate "+propertyName,
|
||||||
|
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
const backFnFunc = async () => {await renderAdditionConfigArrayStructureSelector(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath,localData)}
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
if (answer.selectedIndex == 0) await nextFn(localData)
|
||||||
|
else if (answer.selectedIndex == 1) await chooseAdditionConfigStructure(checker,backFnFunc,async (newData) => {
|
||||||
|
localData[localData.length] = newData
|
||||||
|
await backFnFunc()
|
||||||
|
},structure.options.propertyChecker,localData,localData.length,path,[])
|
||||||
|
else if (answer.selectedIndex == 2) await renderConfigArrayStructureEditSelector(checker,backFnFunc,structure,structure.options.propertyChecker,localData,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 3) await renderconfigArrayStructureMoveSelector(checker,backFnFunc,structure,structure.options.propertyChecker,localData,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 4) await renderconfigArrayStructureRemoveSelector(checker,backFnFunc,structure,structure.options.propertyChecker,localData,parent,parentIndex,path)
|
||||||
|
else if (answer.selectedIndex == 5) await renderConfigArrayStructureDuplicateSelector(checker,backFnFunc,structure,structure.options.propertyChecker,localData,parent,parentIndex,path)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderAdditionConfigTypeSwitchStructure(checker:api.ODChecker,backFn:(() => api.ODPromiseVoid),nextFn:((data:any) => api.ODPromiseVoid),structure:api.ODCheckerTypeSwitchStructure,parent:object|any[],parentIndex:string|number,path:(string|number)[],localPath:(string|number)[]){
|
||||||
|
renderHeader(path)
|
||||||
|
terminal(ansis.bold.green("You are now creating "+(typeof parentIndex == "string" ? "the property "+ansis.blue("\""+parentIndex+"\"") : "property "+ansis.blue("#"+(parentIndex+1)))+".\n")+ansis.italic.gray("(use arrow keys to navigate, go back using escape)\n"))
|
||||||
|
|
||||||
|
terminal.gray("\nProperty: "+ansis.bold.blue(structure.options.cliDisplayName ?? [...localPath,parentIndex].join("."))+"\n")
|
||||||
|
terminal.gray("Description: "+ansis.bold(structure.options.cliDisplayDescription ?? "/")+"\n")
|
||||||
|
|
||||||
|
const actionsList: string[] = []
|
||||||
|
if (structure.options.boolean) actionsList.push("Create as boolean")
|
||||||
|
if (structure.options.string) actionsList.push("Create as string")
|
||||||
|
if (structure.options.number) actionsList.push("Create as number")
|
||||||
|
if (structure.options.object) actionsList.push("Create as object")
|
||||||
|
if (structure.options.array) actionsList.push("Create as array/list")
|
||||||
|
if (structure.options.null) actionsList.push("Create as null")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu(actionsList,{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
|
||||||
|
//run selected structure editor (untested)
|
||||||
|
if (answer.selectedText.startsWith("Create as boolean") && structure.options.boolean) await renderAdditionConfigBooleanStructure(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.boolean,parent,parentIndex,path,localPath)
|
||||||
|
else if (answer.selectedText.startsWith("Create as string") && structure.options.string) await renderAdditionConfigStringStructure(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.string,parent,parentIndex,path,localPath)
|
||||||
|
else if (answer.selectedText.startsWith("Create as number") && structure.options.number) await renderAdditionConfigNumberStructure(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.number,parent,parentIndex,path,localPath)
|
||||||
|
else if (answer.selectedText.startsWith("Create as object") && structure.options.object) await renderAdditionConfigObjectStructure(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.object,parent,parentIndex,path,localPath)
|
||||||
|
else if (answer.selectedText.startsWith("Create as array/list") && structure.options.array) await renderAdditionConfigArrayStructureSelector(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.array,parent,parentIndex,path,localPath)
|
||||||
|
else if (answer.selectedText.startsWith("Create as null") && structure.options.null) await renderAdditionConfigNullStructure(checker,async () => {await renderAdditionConfigTypeSwitchStructure(checker,backFn,nextFn,structure,parent,parentIndex,path,localPath)},nextFn,structure.options.null,parent,parentIndex,path,localPath)
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import {opendiscord, api, utilities} from "../../index"
|
||||||
|
import {Terminal, terminal} from "terminal-kit"
|
||||||
|
import ansis from "ansis"
|
||||||
|
import * as discord from "discord.js"
|
||||||
|
import {renderHeader} from "./cli"
|
||||||
|
|
||||||
|
export async function renderQuickSetup(backFn:() => api.ODPromiseVoid){
|
||||||
|
if (quickSetupRequiresReset()) await renderQuickSetupWarning(backFn)
|
||||||
|
else await renderQuickSetupWelcome(backFn)
|
||||||
|
}
|
||||||
|
|
||||||
|
function quickSetupRequiresReset(): boolean {
|
||||||
|
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||||
|
if (generalConfig.data.token != "your bot token here! (or leave empty when using 'tokenFromENV')") return true
|
||||||
|
if (generalConfig.data.mainColor != "#f8ba00") return true
|
||||||
|
if (generalConfig.data.language != "english") return true
|
||||||
|
if (generalConfig.data.prefix != "!ticket ") return true
|
||||||
|
if (generalConfig.data.serverId != "discord server id") return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupWarning(backFn:() => api.ODPromiseVoid) {
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Warning")
|
||||||
|
|
||||||
|
terminal.bold(ansis.yellow("WARNING! ")+ansis.red("By using the 'Quick Setup' feature, your current config will be completely resetted!"))
|
||||||
|
terminal.gray("\n\nAre you sure you want to continue?")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([
|
||||||
|
ansis.green("✅ No, take me back."),
|
||||||
|
ansis.red("🚨 Yes, continue and reset the config.")
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled || answer.selectedIndex == 0) return await backFn()
|
||||||
|
if (answer.selectedIndex == 1) await renderQuickSetupWelcome(async () => {await renderQuickSetupWarning(backFn)})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupWelcome(backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Introduction")
|
||||||
|
|
||||||
|
terminal.bold.underline.blue("Open Ticket: Quick Setup\n")
|
||||||
|
terminal.gray([
|
||||||
|
"Hi there! Thank you for downloading and installing Open Ticket.",
|
||||||
|
"You have chosen to configure the bot using the 'Quick Setup CLI'.",
|
||||||
|
"",
|
||||||
|
"This program will help you with configuring Open Ticket using a step-by-step method.",
|
||||||
|
"If you've ever used Google Forms, then this will probably be very easy for you 😉.",
|
||||||
|
"",
|
||||||
|
ansis.magenta("The configuration should normally only take around 5 minutes."),
|
||||||
|
ansis.magenta("Once you've completed the form, the bot is technically ready for usage!")
|
||||||
|
].join("\n")+"\n\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([
|
||||||
|
ansis.green("Press 'Enter' to start!")
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
else if (answer.selectedIndex == 0) await renderQuickSetupDevPortal(async () => {await renderQuickSetupWelcome(backFn)})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupDevPortal(backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Discord Bot & Developer Portal")
|
||||||
|
|
||||||
|
terminal.bold.blue("(Step 1) Have you already created a Discord bot to use for Open Ticket?\n")
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([
|
||||||
|
"✅ Yes I have, and it has been invited to the server.",
|
||||||
|
"❓ No not yet, I don't know how to create one.",
|
||||||
|
"👶 I've never seen a Discord bot before.",
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.gray,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return await backFn()
|
||||||
|
else if (answer.selectedIndex == 0) await renderQuickSetupBotToken(async () => {await renderQuickSetupDevPortal(backFn)})
|
||||||
|
else if (answer.selectedIndex == 1) await renderQuickSetupDevPortalGuide(0,async () => {await renderQuickSetupDevPortal(backFn)})
|
||||||
|
else if (answer.selectedIndex == 2) await renderQuickSetupDevPortalGuide(1,async () => {await renderQuickSetupDevPortal(backFn)})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupDevPortalGuide(variation:0|1,backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Discord Bot & Developer Portal")
|
||||||
|
|
||||||
|
if (variation == 0){
|
||||||
|
terminal.bold.blue("(Step 1.1) You've mentioned that you don't know how to create a Discord bot.\n\n")
|
||||||
|
terminal.gray("Please visit the following URL for a step-by-step guide on how to create a Discord bot.\nIf it still doesn't work, join our Discord server and we will help you further!\n"+ansis.magenta("=> https://otdocs.dj-dj.be/docs/guides/get-started#bot\n\n"))
|
||||||
|
}else{
|
||||||
|
terminal.bold.blue("(Step 1.2) You've mentioned that you've never seen Discord bot before.\n\n")
|
||||||
|
terminal.gray("How did you even download Open Ticket 🤪? But all jokes aside, we have a step-by-step guide on how to create a Discord bot.\nIf it still doesn't work, join our Discord server and we will help you further!\n"+ansis.magenta("=> https://otdocs.dj-dj.be/docs/guides/get-started#bot\n\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([
|
||||||
|
ansis.green("✅ Alright, I've made the bot. Take me back please!")
|
||||||
|
],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
return await backFn()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function quickSetupLogin(token:string): Promise<api.ODClientManager|null> {
|
||||||
|
const client = new api.ODClientManager(opendiscord.debug)
|
||||||
|
client.token = token
|
||||||
|
client.intents.push("Guilds","GuildMessages","DirectMessages","GuildEmojisAndStickers","GuildMembers","MessageContent","GuildWebhooks","GuildInvites")
|
||||||
|
client.privileges.push("MessageContent","GuildMembers")
|
||||||
|
client.partials.push("Channel","Message")
|
||||||
|
client.permissions.push("AddReactions","AttachFiles","CreatePrivateThreads","CreatePublicThreads","EmbedLinks","ManageChannels","ManageGuild","ManageMessages","ChangeNickname","ManageRoles","ManageThreads","ManageWebhooks","MentionEveryone","ReadMessageHistory","SendMessages","SendMessagesInThreads","UseApplicationCommands","UseExternalEmojis","ViewAuditLog","ViewChannel")
|
||||||
|
client.initClient()
|
||||||
|
|
||||||
|
//client login
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
try{
|
||||||
|
client.readyListener = async () => {
|
||||||
|
client.activity.setStatus("custom","Configuring Open Ticket...","idle",true)
|
||||||
|
resolve(client)
|
||||||
|
}
|
||||||
|
const success = await client.login(true)
|
||||||
|
if (!success) resolve(null)
|
||||||
|
}catch(err){
|
||||||
|
resolve(null)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupBotToken(backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Bot Token")
|
||||||
|
|
||||||
|
terminal.bold.blue("(Step 2) Please insert the token of your discord bot.\n")
|
||||||
|
terminal.gray("It will be safely stored in the 'config/general.json' file.\n\n> ")
|
||||||
|
|
||||||
|
const answer = await terminal.inputField({
|
||||||
|
style:terminal.white,
|
||||||
|
hintStyle:terminal.gray,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (typeof answer != "string") return await backFn()
|
||||||
|
else{
|
||||||
|
const result = await quickSetupLogin(answer)
|
||||||
|
if (!result){
|
||||||
|
//login failure
|
||||||
|
terminal.red.bold("\n\n❌ Something went wrong with logging into the bot.\n")
|
||||||
|
terminal.gray("Please try again and check your token for any mistakes.\nAlso make sure the permissions and priviliged gateaway intents are configured correctly in the developer panel.")
|
||||||
|
await utilities.timer(3000)
|
||||||
|
//retry
|
||||||
|
await renderQuickSetupBotToken(backFn)
|
||||||
|
}else{
|
||||||
|
//login success
|
||||||
|
terminal.green.bold("\n\n✅ Succesfully logged into the bot.\n")
|
||||||
|
terminal.gray("Your bot should be online with the status 'Configuring Open Ticket...'.")
|
||||||
|
await utilities.timer(3000)
|
||||||
|
//continue
|
||||||
|
await renderQuickSetupServer(result,async () => {await renderQuickSetupBotToken(backFn)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupServer(client:api.ODClientManager,backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Discord Server")
|
||||||
|
|
||||||
|
terminal.bold.blue("(Step 3) Please select a Discord Server to use.\n")
|
||||||
|
terminal.gray("The bot will only work in this server.\n\n")
|
||||||
|
|
||||||
|
const guilds = await client.getGuilds()
|
||||||
|
const nameList = guilds.map((g) => g.name)
|
||||||
|
const longestName = utilities.getLongestLength(nameList)
|
||||||
|
const guildList = guilds.map((g) => g.name.padEnd(longestName+5," ")+ansis.gray(" ("+g.id+")"))
|
||||||
|
|
||||||
|
const answer = await terminal.singleColumnMenu([ansis.green("🔄 <Refresh List>"),...guildList],{
|
||||||
|
leftPadding:"> ",
|
||||||
|
style:terminal.cyan,
|
||||||
|
selectedStyle:terminal.bgDefaultColor.bold,
|
||||||
|
submittedStyle:terminal.bgBlue,
|
||||||
|
extraLines:2,
|
||||||
|
cancelable:true
|
||||||
|
}).promise
|
||||||
|
|
||||||
|
if (answer.canceled) return backFn()
|
||||||
|
if (answer.selectedIndex == 0) return await renderQuickSetupServer(client,backFn)
|
||||||
|
const server = guilds[answer.selectedIndex-1]
|
||||||
|
await renderQuickSetupAdminRoles(client,server,[],async () => {await renderQuickSetupServer(client,backFn)})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renderQuickSetupAdminRoles(client:api.ODClientManager,guild:discord.Guild,selectedAdmins:string[],backFn:() => api.ODPromiseVoid){
|
||||||
|
renderHeader("⏱️ Open Ticket Quick Setup: Admin Roles")
|
||||||
|
|
||||||
|
terminal.bold.blue("(Step 4) Please select all 'Global Admins' roles to use.\n")
|
||||||
|
terminal.gray("Users with one of these roles will be able to access & interact with all tickets.\n\n")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,12 +31,13 @@ moduleInstalled("discord.js",true)
|
|||||||
moduleInstalled("ansis",true)
|
moduleInstalled("ansis",true)
|
||||||
moduleInstalled("formatted-json-stringify",true)
|
moduleInstalled("formatted-json-stringify",true)
|
||||||
moduleInstalled("typescript",true)
|
moduleInstalled("typescript",true)
|
||||||
|
moduleInstalled("terminal-kit",true)
|
||||||
tempError()
|
tempError()
|
||||||
|
|
||||||
//init API
|
//init API
|
||||||
import * as api from "../api/api" //import for local use
|
import * as api from "../api/api" //import for local use
|
||||||
export * as api from "../api/api" //export to other parts of bot
|
export * as api from "../api/api" //export to other parts of bot
|
||||||
|
import ansis from "ansis" //import ansis for usage in initialization
|
||||||
|
|
||||||
export const opendiscord = new api.ODMain()
|
export const opendiscord = new api.ODMain()
|
||||||
console.log("\n--------------------------- OPEN TICKET STARTUP ---------------------------")
|
console.log("\n--------------------------- OPEN TICKET STARTUP ---------------------------")
|
||||||
@@ -103,6 +104,10 @@ export interface ODUtilities {
|
|||||||
* Same as `string.replace(search, value)` but with async compatibility
|
* Same as `string.replace(search, value)` but with async compatibility
|
||||||
*/
|
*/
|
||||||
asyncReplace(text:string, regex:RegExp, func:(value:string,...args:any[]) => Promise<string>): Promise<string>
|
asyncReplace(text:string, regex:RegExp, func:(value:string,...args:any[]) => Promise<string>): Promise<string>
|
||||||
|
/**## getLongestLength `utility function`
|
||||||
|
* Get the length of the longest string in the array.
|
||||||
|
*/
|
||||||
|
getLongestLength(text:string[]): number
|
||||||
/**## easterEggs `utility object`
|
/**## easterEggs `utility object`
|
||||||
* Object containing data for Open Ticket easter eggs.
|
* Object containing data for Open Ticket easter eggs.
|
||||||
*/
|
*/
|
||||||
@@ -208,6 +213,9 @@ export const utilities: ODUtilities = {
|
|||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
},
|
},
|
||||||
|
getLongestLength(texts:string[]): number {
|
||||||
|
return Math.max(...texts.map((t) => ansis.strip(t).length))
|
||||||
|
},
|
||||||
easterEggs:{
|
easterEggs:{
|
||||||
/* THANK YOU TO ALL OUR CONTRIBUTORS!!! */
|
/* THANK YOU TO ALL OUR CONTRIBUTORS!!! */
|
||||||
creator:"779742674932072469", //DJj123dj
|
creator:"779742674932072469", //DJj123dj
|
||||||
|
|||||||
@@ -1,5 +1,24 @@
|
|||||||
import {opendiscord, api, utilities} from "../../index"
|
import {opendiscord, api, utilities} from "../../index"
|
||||||
|
|
||||||
|
/**Check if migration is required. Returns the last version used in the database. */
|
||||||
|
async function isMigrationRequired(): Promise<false|api.ODVersion> {
|
||||||
|
const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version")
|
||||||
|
if (!rawVersion) return false
|
||||||
|
const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion)
|
||||||
|
if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){
|
||||||
|
return version
|
||||||
|
}else return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**Save all versions in `opendiscord.versions` to the global database. */
|
||||||
|
async function saveAllVersionsToDatabase(){
|
||||||
|
const globalDatabase = opendiscord.databases.get("opendiscord:global")
|
||||||
|
|
||||||
|
await opendiscord.versions.loopAll(async (version,id) => {
|
||||||
|
await globalDatabase.set("opendiscord:last-version",id.value,version.toString())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const loadVersionMigrationSystem = async () => {
|
export const loadVersionMigrationSystem = async () => {
|
||||||
//ENTER MIGRATION CONTEXT
|
//ENTER MIGRATION CONTEXT
|
||||||
await preloadMigrationContext()
|
await preloadMigrationContext()
|
||||||
@@ -29,6 +48,8 @@ export const loadVersionMigrationSystem = async () => {
|
|||||||
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.defaults.setDefault("softPluginLoading",true)
|
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.defaults.setDefault("softPluginLoading",true)
|
||||||
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.defaults.setDefault("crashOnError",true)
|
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.defaults.setDefault("crashOnError",true)
|
||||||
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value) opendiscord.defaults.setDefault("forceSlashCommandRegistration",true)
|
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value) opendiscord.defaults.setDefault("forceSlashCommandRegistration",true)
|
||||||
|
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
|
||||||
|
|
||||||
|
|
||||||
//LEAVE MIGRATION CONTEXT
|
//LEAVE MIGRATION CONTEXT
|
||||||
await unloadMigrationContext()
|
await unloadMigrationContext()
|
||||||
@@ -36,7 +57,8 @@ export const loadVersionMigrationSystem = async () => {
|
|||||||
return lastVersion
|
return lastVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
const preloadMigrationContext = async () => {
|
/**Initialize the migration context by loading the built-in flags, configs & databases. */
|
||||||
|
async function preloadMigrationContext(){
|
||||||
opendiscord.debug.debug("-- MIGRATION CONTEXT START --")
|
opendiscord.debug.debug("-- MIGRATION CONTEXT START --")
|
||||||
await (await import("../../data/framework/flagLoader.js")).loadAllFlags()
|
await (await import("../../data/framework/flagLoader.js")).loadAllFlags()
|
||||||
await opendiscord.flags.init()
|
await opendiscord.flags.init()
|
||||||
@@ -47,7 +69,8 @@ const preloadMigrationContext = async () => {
|
|||||||
opendiscord.debug.visible = true
|
opendiscord.debug.visible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const unloadMigrationContext = async () => {
|
/**Unload the migration context to start the bot normally. */
|
||||||
|
async function unloadMigrationContext(){
|
||||||
opendiscord.debug.visible = false
|
opendiscord.debug.visible = false
|
||||||
await opendiscord.databases.loopAll((database,id) => {opendiscord.databases.remove(id)})
|
await opendiscord.databases.loopAll((database,id) => {opendiscord.databases.remove(id)})
|
||||||
await opendiscord.configs.loopAll((config,id) => {opendiscord.configs.remove(id)})
|
await opendiscord.configs.loopAll((config,id) => {opendiscord.configs.remove(id)})
|
||||||
@@ -55,16 +78,8 @@ const unloadMigrationContext = async () => {
|
|||||||
opendiscord.debug.debug("-- MIGRATION CONTEXT END --")
|
opendiscord.debug.debug("-- MIGRATION CONTEXT END --")
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMigrationRequired = async (): Promise<false|api.ODVersion> => {
|
/**Execute all version migration functions which are handled in the restricted migration context. */
|
||||||
const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version")
|
async function loadAllVersionMigrations(lastVersion:api.ODVersion){
|
||||||
if (!rawVersion) return false
|
|
||||||
const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion)
|
|
||||||
if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){
|
|
||||||
return version
|
|
||||||
}else return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => {
|
|
||||||
const migrations = (await import("./migration.js")).migrations
|
const migrations = (await import("./migration.js")).migrations
|
||||||
migrations.sort((a,b) => {
|
migrations.sort((a,b) => {
|
||||||
const comparison = a.version.compare(b.version)
|
const comparison = a.version.compare(b.version)
|
||||||
@@ -83,7 +98,8 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loadAllAfterInitVersionMigrations = async (lastVersion:api.ODVersion) => {
|
/**Execute all version migration functions which are handled in the normal startup sequence. */
|
||||||
|
export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersion){
|
||||||
const migrations = (await import("./migration.js")).migrations
|
const migrations = (await import("./migration.js")).migrations
|
||||||
migrations.sort((a,b) => {
|
migrations.sort((a,b) => {
|
||||||
const comparison = a.version.compare(b.version)
|
const comparison = a.version.compare(b.version)
|
||||||
@@ -100,12 +116,4 @@ export const loadAllAfterInitVersionMigrations = async (lastVersion:api.ODVersio
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const saveAllVersionsToDatabase = async () => {
|
|
||||||
const globalDatabase = opendiscord.databases.get("opendiscord:global")
|
|
||||||
|
|
||||||
await opendiscord.versions.loopAll(async (version,id) => {
|
|
||||||
await globalDatabase.set("opendiscord:last-version",id.value,version.toString())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
+277
-250
@@ -3,11 +3,11 @@ import {opendiscord, api, utilities} from "../../index"
|
|||||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||||
|
|
||||||
export const loadAllConfigCheckers = async () => {
|
export const loadAllConfigCheckers = async () => {
|
||||||
opendiscord.checkers.add(new api.ODChecker("opendiscord:general",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:general"),defaultGeneralStructure))
|
opendiscord.checkers.add(new api.ODChecker("opendiscord:general",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:general"),defaultGeneralStructure,{cliDisplayName:"General Config",cliDisplayDescription:"Configure the bot token, status, colors, permissions & more."}))
|
||||||
opendiscord.checkers.add(new api.ODChecker("opendiscord:options",opendiscord.checkers.storage,1,opendiscord.configs.get("opendiscord:options"),defaultOptionsStructure))
|
opendiscord.checkers.add(new api.ODChecker("opendiscord:questions",opendiscord.checkers.storage,2,opendiscord.configs.get("opendiscord:questions"),defaultQuestionsStructure,{cliDisplayName:"Questions Config",cliDisplayDescription:"Create, modify & delete questions which are used in options."}))
|
||||||
opendiscord.checkers.add(new api.ODChecker("opendiscord:panels",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:panels"),defaultPanelsStructure))
|
opendiscord.checkers.add(new api.ODChecker("opendiscord:options",opendiscord.checkers.storage,1,opendiscord.configs.get("opendiscord:options"),defaultOptionsStructure,{cliDisplayName:"Options Config",cliDisplayDescription:"Create, modify & delete options which are used in panels."}))
|
||||||
opendiscord.checkers.add(new api.ODChecker("opendiscord:questions",opendiscord.checkers.storage,2,opendiscord.configs.get("opendiscord:questions"),defaultQuestionsStructure))
|
opendiscord.checkers.add(new api.ODChecker("opendiscord:panels",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:panels"),defaultPanelsStructure,{cliDisplayName:"Panels Config",cliDisplayDescription:"Create, modify & delete panels which can be spawned in discord."}))
|
||||||
opendiscord.checkers.add(new api.ODChecker("opendiscord:transcripts",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:transcripts"),defaultTranscriptsStructure))
|
opendiscord.checkers.add(new api.ODChecker("opendiscord:transcripts",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:transcripts"),defaultTranscriptsStructure,{cliDisplayName:"Transcript Config",cliDisplayDescription:"Configure everything related to transcripts."}))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const loadAllConfigCheckerFunctions = async () => {
|
export const loadAllConfigCheckerFunctions = async () => {
|
||||||
@@ -116,57 +116,59 @@ export const registerDefaultCheckerCustomTranslations = (tm:api.ODCheckerTransla
|
|||||||
tm.quickTranslate(lm,"checker.messages.dropdownOption","message","opendiscord:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type!
|
tm.quickTranslate(lm,"checker.messages.dropdownOption","message","opendiscord:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type!
|
||||||
|
|
||||||
//TODO TRANSLATION!!!
|
//TODO TRANSLATION!!!
|
||||||
//tm.quickTranslate(lm,"checker.messages.TODO","message","opendiscord:invalid-version") // The version specified in your config is invalid! Make sure you have updated it to the latest version!
|
//tm.quickTranslate(lm,"checker.messages.TODO","message","opendiscord:invalid-version") // The version specified in your config does not match! Make sure you have updated the config to the latest version!
|
||||||
}
|
}
|
||||||
|
|
||||||
//UTILITY FUNCTIONS
|
//UTILITY FUNCTIONS
|
||||||
const createMsgStructure = (id:api.ODValidId) => {
|
const createMsgStructure = (id:api.ODValidId,displayName:string) => {
|
||||||
return new api.ODCheckerObjectStructure(id,{children:[
|
return new api.ODCheckerObjectStructure(id,{children:[
|
||||||
{key:"dm",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{})},
|
{key:"dm",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{cliInitDefaultValue:false,cliDisplayName:"DM Enabled",cliDisplayDescription:"Will this action be sent in DM to the creator of the ticket?"})},
|
||||||
{key:"logs",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{})},
|
{key:"logs",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{cliInitDefaultValue:true,cliDisplayName:"Logs Enabled",cliDisplayDescription:"Will this action be sent in the Discord log channel?"})},
|
||||||
]})
|
],cliDisplayName:displayName,cliDisplayDescription:"Configure which places this action gets logged/sent to."})
|
||||||
}
|
}
|
||||||
const createTicketEmbedStructure = (id:api.ODValidId) => {
|
const createTicketEmbedStructure = (id:api.ODValidId) => {
|
||||||
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
|
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
|
||||||
{key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this message."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-description",{maxLength:4096})},
|
{key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
|
||||||
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:ticket-embed-color",true,true)},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-description",{maxLength:4096,cliDisplayName:"Description",cliDisplayDescription:"The description of this embed."})},
|
||||||
|
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:ticket-embed-color",true,true,{cliDisplayName:"Custom Color",cliDisplayDescription:"Set a custom color for this embed. When empty, the default bot color will be used."})},
|
||||||
|
|
||||||
{key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})},
|
{key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]},{cliDisplayName:"Image",cliDisplayDescription:"Add an image to the embed using an image URL."})},
|
||||||
{key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})},
|
{key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]},{cliDisplayName:"Thumbnail",cliDisplayDescription:"Add a thumbnail to the embed using an image URL."})},
|
||||||
{key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-embed-fields",{children:[
|
{key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-embed-fields",{allowedTypes:["object"],cliDisplayPropertyName:"embed field",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-embed-fields",{children:[
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-name",{minLength:1,maxLength:256})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-name",{minLength:1,maxLength:256,cliDisplayName:"Field Name",cliDisplayDescription:"The name/title of this embed field."})},
|
||||||
{key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-value",{minLength:1,maxLength:1024})},
|
{key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-value",{minLength:1,maxLength:1024,cliDisplayName:"Field Value",cliDisplayDescription:"The value/description of this embed field."})},
|
||||||
{key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-field-inline",{})}
|
{key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-field-inline",{cliDisplayName:"Field Inline",cliDisplayDescription:"Should this field be displayed inline with other fields?"})}
|
||||||
]})})},
|
],cliDisplayName:"Field",cliDisplayDescription:"Customise and configure an embed field."}),cliDisplayName:"Fields",cliDisplayDescription:"Customise and configure embed fields."})},
|
||||||
{key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{})}
|
{key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{cliDisplayName:"Timestamp",cliDisplayDescription:"Add a timestamp to the embed."})}
|
||||||
]})})
|
],cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."}),cliInitDefaultValue:{enabled:false,title:"",description:"",customColor:"",image:"",thumbnail:"",fields:[],timestamp:false},cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."})
|
||||||
}
|
}
|
||||||
const createTicketPingStructure = (id:api.ODValidId) => {
|
const createTicketPingStructure = (id:api.ODValidId) => {
|
||||||
return new api.ODCheckerObjectStructure(id,{children:[
|
return new api.ODCheckerObjectStructure(id,{children:[
|
||||||
{key:"@here",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{})},
|
{key:"@here",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{cliDisplayName:"@here Ping",cliDisplayDescription:"Enable/disable an '@here' ping."})},
|
||||||
{key:"@everyone",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{})},
|
{key:"@everyone",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{cliDisplayName:"@everyone Ping",cliDisplayDescription:"Enable/disable an '@everyone' ping."})},
|
||||||
{key:"custom",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false})},
|
{key:"custom",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false,cliDisplayPropertyName:"custom role id",cliDisplayName:"Custom Role Ping",cliDisplayDescription:"Choose your own roles to ping in this message."},{cliDisplayName:"Custom Role",cliDisplayDescription:"The discord role ID of a custom mention/ping."})},
|
||||||
]})
|
],cliInitDefaultValue:{"@here":true,"@everyone":false,custom:[],cliDisplayName:"Message Pings",cliDisplayDescription:"Configure the pings/mentions of this message."}})
|
||||||
}
|
}
|
||||||
const createPanelEmbedStructure = (id:api.ODValidId) => {
|
const createPanelEmbedStructure = (id:api.ODValidId) => {
|
||||||
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
|
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
|
||||||
{key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this panel."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-description",{maxLength:4096})},
|
{key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
|
||||||
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:panel-embed-color",true,true)},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-description",{maxLength:4096,cliDisplayName:"Description",cliDisplayDescription:"The description of this embed."})},
|
||||||
{key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-url",true,{allowHttp:false})},
|
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:panel-embed-color",true,true,{cliDisplayName:"Custom Color",cliDisplayDescription:"Set a custom color for this embed. When empty, the default bot color will be used."})},
|
||||||
|
{key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-url",true,{allowHttp:false},{cliDisplayName:"URL",cliDisplayDescription:"Set a URL which will be displayed in the title of the embed."})},
|
||||||
|
|
||||||
{key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})},
|
{key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]},{cliDisplayName:"Image",cliDisplayDescription:"Add an image to the embed using an image URL."})},
|
||||||
{key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})},
|
{key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]},{cliDisplayName:"Thumbnail",cliDisplayDescription:"Add a thumbnail to the embed using an image URL."})},
|
||||||
|
|
||||||
{key:"footer",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-footer",{maxLength:2048})},
|
{key:"footer",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-footer",{maxLength:2048,cliDisplayName:"Footer",cliDisplayDescription:"The footer of this embed."})},
|
||||||
{key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:panel-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panel-embed-fields",{children:[
|
{key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:panel-embed-fields",{allowedTypes:["object"],cliDisplayPropertyName:"embed field",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panel-embed-fields",{children:[
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-name",{minLength:1,maxLength:256})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-name",{minLength:1,maxLength:256,cliDisplayName:"Field Name",cliDisplayDescription:"The name/title of this embed field."})},
|
||||||
{key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-value",{minLength:1,maxLength:1024})},
|
{key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-value",{minLength:1,maxLength:1024,cliDisplayName:"Field Value",cliDisplayDescription:"The value/description of this embed field."})},
|
||||||
{key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-field-inline",{})}
|
{key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-field-inline",{cliDisplayName:"Field Inline",cliDisplayDescription:"Should this field be displayed inline with other fields?"})}
|
||||||
]})})},
|
],cliDisplayName:"Field",cliDisplayDescription:"Customise and configure an embed field."}),cliDisplayName:"Fields",cliDisplayDescription:"Customise and configure embed fields."})},
|
||||||
{key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-timestamp",{})}
|
{key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-timestamp",{cliDisplayName:"Timestamp",cliDisplayDescription:"Add a timestamp to the embed."})}
|
||||||
]})})
|
],cliDisplayName:"Panel Embed",cliDisplayDescription:"Configure the embed of this panel."}),cliInitDefaultValue:{enabled:false,title:"",description:"",customColor:"",url:"",image:"",thumbnail:"",footer:"",fields:[],timestamp:false},cliDisplayName:"Panel Embed",cliDisplayDescription:"Configure the embed of this panel."})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadFromEnv(){
|
function loadFromEnv(){
|
||||||
@@ -177,8 +179,8 @@ function loadFromEnv(){
|
|||||||
|
|
||||||
//STRUCTURES
|
//STRUCTURES
|
||||||
export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[
|
export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[
|
||||||
//STATUS
|
//INFO
|
||||||
{key:"_INFO",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:info",{children:[
|
{key:"_INFO",optional:false,priority:0,cliHideInEditMode:true,checker:new api.ODCheckerObjectStructure("opendiscord:info",{children:[
|
||||||
{key:"support",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-support",{choices:["https://otdocs.dj-dj.be"]})},
|
{key:"support",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-support",{choices:["https://otdocs.dj-dj.be"]})},
|
||||||
{key:"discord",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-discord",{choices:["https://discord.dj-dj.be"]})},
|
{key:"discord",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-discord",{choices:["https://discord.dj-dj.be"]})},
|
||||||
{key:"version",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
|
{key:"version",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
|
||||||
@@ -186,16 +188,16 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
|
|||||||
|
|
||||||
if (typeof value != "string") return false
|
if (typeof value != "string") return false
|
||||||
else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){
|
else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){
|
||||||
checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config is invalid! Make sure you have updated it to the latest version!",lt,null,[],locationId,locationDocs)
|
checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config does not match! Make sure you have updated the config to the latest version!",lt,null,[],locationId,locationDocs)
|
||||||
return false
|
return false
|
||||||
}else return true
|
}else return true
|
||||||
},})},
|
},})},
|
||||||
]})},
|
]})},
|
||||||
|
|
||||||
//BASIC
|
//BASIC
|
||||||
{key:"token",optional:false,priority:0,checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token")},
|
{key:"token",optional:false,priority:0,checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."})},
|
||||||
{key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{})},
|
{key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{cliDisplayName:"Token From ENV",cliDisplayDescription:"Use the token from the .env file instead of general.json."})},
|
||||||
{key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false)},
|
{key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false,{cliDisplayName:"Main Color",cliDisplayDescription:"The main color of your bot, used in almost all embeds."})},
|
||||||
{key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:language",{
|
{key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:language",{
|
||||||
custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
||||||
const lt = checker.locationTraceDeref(locationTrace)
|
const lt = checker.locationTraceDeref(locationTrace)
|
||||||
@@ -206,109 +208,113 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
|
|||||||
return false
|
return false
|
||||||
}else return true
|
}else return true
|
||||||
},
|
},
|
||||||
|
cliAutocompleteList:opendiscord.defaults.getDefault("languageList"),
|
||||||
|
cliDisplayName:"Language",
|
||||||
|
cliDisplayDescription:"The language of the bot. Visit README.md for a list of available translations."
|
||||||
})},
|
})},
|
||||||
{key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:prefix",{minLength:1})},
|
{key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:prefix",{minLength:1,cliDisplayName:"Prefix",cliDisplayDescription:"The prefix used for the text-commands from the bot."})},
|
||||||
{key:"serverId",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:server-id","server",false,[])},
|
{key:"serverId",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:server-id","server",false,[],{cliDisplayName:"Server Id",cliDisplayDescription:"The ID of the discord server you will be using this bot in."})},
|
||||||
{key:"globalAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:global-admins","role",[],{allowDoubles:false})},
|
{key:"globalAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:global-admins","role",[],{allowDoubles:false,cliDisplayPropertyName:"global admin role",cliDisplayName:"Global Admin Roles",cliDisplayDescription:"A list of role IDs that are able to interact with all commands and tickets."},{cliDisplayName:"Global Admin Role",cliDisplayDescription:"The discord role ID of a global admin."})},
|
||||||
{key:"slashCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:slash-commands",{})},
|
{key:"slashCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:slash-commands",{cliDisplayName:"Enable Slash Commands",cliDisplayDescription:"Enable/disable slash commands in the bot. When disabled, the commands will not be displayed."})},
|
||||||
{key:"textCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:text-commands",{})},
|
{key:"textCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:text-commands",{cliDisplayName:"Enable Text Commands",cliDisplayDescription:"Enable/disable text commands in the bot. (Disabling is recommended in large servers)"})},
|
||||||
|
|
||||||
//STATUS
|
//STATUS
|
||||||
{key:"status",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{
|
{key:"status",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{
|
||||||
property:"enabled",
|
property:"enabled",
|
||||||
enabledValue:true,
|
enabledValue:true,
|
||||||
checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[
|
checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[
|
||||||
{key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"]})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:status-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the status. When disabled, the bot will be online without any status."})},
|
||||||
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-text",{minLength:1,maxLength:128})},
|
{key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"],cliDisplayName:"Type",cliDisplayDescription:"The type of status: Listening, Watching, Playing or Custom."})},
|
||||||
{key:"status",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["online","invisible","idle","dnd"]})},
|
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-text",{minLength:1,maxLength:128,cliDisplayName:"Text",cliDisplayDescription:"The text displayed in the status."})},
|
||||||
]})
|
{key:"status",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-status",{choices:["online","invisible","idle","dnd"],cliDisplayName:"Status",cliDisplayDescription:"The profile status of the bot: Online, Invisible, Idle or Do Not Disturb."})},
|
||||||
|
],cliDisplayName:"Bot Status",cliDisplayDescription:"Manage the status of the bot."}),
|
||||||
|
cliDisplayName:"Bot Status",
|
||||||
|
cliDisplayDescription:"Manage the status of the bot."
|
||||||
})},
|
})},
|
||||||
|
|
||||||
//SYSTEM
|
//SYSTEM
|
||||||
{key:"system",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system",{children:[
|
{key:"system",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system",{children:[
|
||||||
{key:"removeParticipantsOnClose",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:remove-participants-on-close",{})},
|
{key:"removeParticipantsOnClose",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:remove-participants-on-close",{cliDisplayName:"Remove Participants On Close",cliDisplayDescription:"When enabled, all participants except admins will be removed from the ticket."})},
|
||||||
{key:"replyOnTicketCreation",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{})},
|
{key:"replyOnTicketCreation",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{cliDisplayName:"Reply On Ticket Creation",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when creating a ticket."})},
|
||||||
{key:"replyOnReactionRole",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{})},
|
{key:"replyOnReactionRole",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{cliDisplayName:"Reply On Reaction Role",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when using a role button."})},
|
||||||
{key:"useTranslatedConfigChecker",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-translated-config-checker",{})},
|
{key:"useTranslatedConfigChecker",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-translated-config-checker",{cliDisplayName:"Use Translated Config Checker",cliDisplayDescription:"Use a translated config checker to better understand the errors the bot gives."})},
|
||||||
{key:"preferSlashOverText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{})},
|
{key:"preferSlashOverText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{cliDisplayName:"Prefer Slash Over Text",cliDisplayDescription:"Prefer displaying slash commands over text commands in help menus."})},
|
||||||
{key:"sendErrorOnUnknownCommand",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{})},
|
{key:"sendErrorOnUnknownCommand",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{cliDisplayName:"Send Error On Unknown Command",cliDisplayDescription:"Send an error when using the text-command prefix without a valid command."})},
|
||||||
{key:"questionFieldsInCodeBlock",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{})},
|
{key:"questionFieldsInCodeBlock",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{cliDisplayName:"Questions Fields In Code Blocks",cliDisplayDescription:"Display question fields in code blocks instead of plain text."})},
|
||||||
{key:"disableVerifyBars",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:disable-verify-bars",{})},
|
{key:"disableVerifyBars",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:disable-verify-bars",{cliDisplayName:"Disable Verifybars",cliDisplayDescription:"Disable the (✅/❌) verify buttons in all commands. (Not recommended)"})},
|
||||||
{key:"useRedErrorEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{})},
|
{key:"useRedErrorEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{cliDisplayName:"Use Red Error Embeds",cliDisplayDescription:"Display all error messages with a red border instead of the default color of the bot."})},
|
||||||
{key:"emojiStyle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"]})},
|
{key:"emojiStyle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"],cliDisplayName:"Emoji Style",cliDisplayDescription:"Choose how the bot will display emojis in message titles. (Visit docs for more info)"})},
|
||||||
|
|
||||||
{key:"enableTicketClaimButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-claim-buttons",{})},
|
{key:"enableTicketClaimButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-claim-buttons",{cliDisplayName:"Enable Ticket Claim Buttons",cliDisplayDescription:"Enable/disable buttons for claiming a ticket. Be aware that this doesn't disable the command!"})},
|
||||||
{key:"enableTicketCloseButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-close-buttons",{})},
|
{key:"enableTicketCloseButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-close-buttons",{cliDisplayName:"Enable Ticket Close Buttons",cliDisplayDescription:"Enable/disable buttons for closing a ticket. Be aware that this doesn't disable the command!"})},
|
||||||
{key:"enableTicketPinButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-pin-buttons",{})},
|
{key:"enableTicketPinButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-pin-buttons",{cliDisplayName:"Enable Ticket Pin Buttons",cliDisplayDescription:"Enable/disable buttons for pinning a ticket. Be aware that this doesn't disable the command!"})},
|
||||||
{key:"enableTicketDeleteButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{})},
|
{key:"enableTicketDeleteButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{cliDisplayName:"Enable Ticket Delete Buttons",cliDisplayDescription:"Enable/disable buttons for deleting a ticket. Be aware that this doesn't disable the command!"})},
|
||||||
{key:"enableTicketActionWithReason",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{})},
|
{key:"enableTicketActionWithReason",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{cliDisplayName:"Enable Ticket Action With Reason",cliDisplayDescription:"Enable/disable buttons to write an additional reason for all ticket actions."})},
|
||||||
{key:"enableDeleteWithoutTranscript",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{})},
|
{key:"enableDeleteWithoutTranscript",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{cliDisplayName:"Enable Delete Without Transcript",cliDisplayDescription:"Enable/disable the ability to delete tickets without a transcript."})},
|
||||||
|
|
||||||
{key:"logs",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:system-logs",{
|
{key:"logs",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:system-logs",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:system-logs",{children:[
|
||||||
property:"enabled",
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:logs-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable discord logs in a discord channel."})},
|
||||||
enabledValue:true,
|
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:logs-channel","channel",false,[],{cliDisplayName:"Log Channel",cliDisplayDescription:"The ID of the discord channel to log messages to. You can configure the messages somewhere else."})},
|
||||||
checker:new api.ODCheckerObjectStructure("opendiscord:system-logs",{children:[
|
],cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."}),cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."})},
|
||||||
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:log-channel","channel",false,[])},
|
|
||||||
]})
|
|
||||||
})},
|
|
||||||
|
|
||||||
{key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[
|
{key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[
|
||||||
{key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:limits-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable global limits."})},
|
||||||
{key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}
|
{key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,cliDisplayName:"Global Maximum",cliDisplayDescription:"The maximum amount of tickets that are able to exist in the server at the same time."})},
|
||||||
]})})},
|
{key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,cliDisplayName:"User Maximum",cliDisplayDescription:"The maximum amount of tickets from a specific user that are able to exist in the server at the same time."})}
|
||||||
|
],cliDisplayName:"Global Limits",cliDisplayDescription:"Manage global limits for ticket creation to reduce the workload on your support team."}),cliDisplayName:"Global Limits",cliDisplayDescription:"Manage global limits for ticket creation to reduce the workload on your support team."})},
|
||||||
|
|
||||||
{key:"permissions",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
|
{key:"permissions",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
|
||||||
{key:"help",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-help","role",false,["admin","everyone","none"])},
|
{key:"help",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-help","role",false,["admin","everyone","none"],{cliDisplayName:"Help",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"panel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-panel","role",false,["admin","everyone","none"])},
|
{key:"panel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-panel","role",false,["admin","everyone","none"],{cliDisplayName:"Panel",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"ticket",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-ticket","role",false,["admin","everyone","none"])},
|
{key:"ticket",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-ticket","role",false,["admin","everyone","none"],{cliDisplayName:"Ticket",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"close",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-close","role",false,["admin","everyone","none"])},
|
{key:"close",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-close","role",false,["admin","everyone","none"],{cliDisplayName:"Close",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"delete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-delete","role",false,["admin","everyone","none"])},
|
{key:"delete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-delete","role",false,["admin","everyone","none"],{cliDisplayName:"Delete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"reopen",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-reopen","role",false,["admin","everyone","none"])},
|
{key:"reopen",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-reopen","role",false,["admin","everyone","none"],{cliDisplayName:"Reopen",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"claim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-claim","role",false,["admin","everyone","none"])},
|
{key:"claim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-claim","role",false,["admin","everyone","none"],{cliDisplayName:"Claim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"unclaim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unclaim","role",false,["admin","everyone","none"])},
|
{key:"unclaim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unclaim","role",false,["admin","everyone","none"],{cliDisplayName:"Unclaim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"pin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-pin","role",false,["admin","everyone","none"])},
|
{key:"pin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-pin","role",false,["admin","everyone","none"],{cliDisplayName:"Pin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"unpin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unpin","role",false,["admin","everyone","none"])},
|
{key:"unpin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unpin","role",false,["admin","everyone","none"],{cliDisplayName:"Unpin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"move",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-move","role",false,["admin","everyone","none"])},
|
{key:"move",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-move","role",false,["admin","everyone","none"],{cliDisplayName:"Move",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"rename",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-rename","role",false,["admin","everyone","none"])},
|
{key:"rename",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-rename","role",false,["admin","everyone","none"],{cliDisplayName:"Rename",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"add",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-add","role",false,["admin","everyone","none"])},
|
{key:"add",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-add","role",false,["admin","everyone","none"],{cliDisplayName:"Add User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"remove",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-remove","role",false,["admin","everyone","none"])},
|
{key:"remove",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-remove","role",false,["admin","everyone","none"],{cliDisplayName:"Remove User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"blacklist",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-blacklist","role",false,["admin","everyone","none"])},
|
{key:"blacklist",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-blacklist","role",false,["admin","everyone","none"],{cliDisplayName:"Blacklist",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"stats",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-stats","role",false,["admin","everyone","none"])},
|
{key:"stats",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-stats","role",false,["admin","everyone","none"],{cliDisplayName:"Stats",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"clear",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-clear","role",false,["admin","everyone","none"])},
|
{key:"clear",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-clear","role",false,["admin","everyone","none"],{cliDisplayName:"Clear Tickets",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autoclose","role",false,["admin","everyone","none"])},
|
{key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autoclose","role",false,["admin","everyone","none"],{cliDisplayName:"Autoclose",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
|
||||||
{key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autodelete","role",false,["admin","everyone","none"])}
|
{key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autodelete","role",false,["admin","everyone","none"],{cliDisplayName:"Autodelete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})}
|
||||||
]})},
|
],cliDisplayName:"Permissions",cliDisplayDescription:"Manage all button & command permissions in the bot. (Visit docs for more info)"})},
|
||||||
|
|
||||||
{key:"messages",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
|
{key:"messages",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
|
||||||
{key:"creation",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-creation")},
|
{key:"creation",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-creation","Ticket Created")},
|
||||||
{key:"closing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-closing")},
|
{key:"closing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-closing","Ticket Closed")},
|
||||||
{key:"deleting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-deleting")},
|
{key:"deleting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-deleting","Ticket Deleted")},
|
||||||
{key:"reopening",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-reopening")},
|
{key:"reopening",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-reopening","Ticket Reopened")},
|
||||||
{key:"claiming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-claiming")},
|
{key:"claiming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-claiming","Ticket Claimed")},
|
||||||
{key:"pinning",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-pinning")},
|
{key:"pinning",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-pinning","Ticket Pinned")},
|
||||||
{key:"adding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-adding")},
|
{key:"adding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-adding","User Added")},
|
||||||
{key:"removing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-removing")},
|
{key:"removing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-removing","User Removed")},
|
||||||
{key:"renaming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-renaming")},
|
{key:"renaming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-renaming","Ticket Renamed")},
|
||||||
{key:"moving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-moving")},
|
{key:"moving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-moving","Ticket Moved")},
|
||||||
{key:"blacklisting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-blacklisting")},
|
{key:"blacklisting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-blacklisting","User Blacklisted")},
|
||||||
{key:"roleAdding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-adding")},
|
{key:"roleAdding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-adding","Role Added")},
|
||||||
{key:"roleRemoving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-removing")}
|
{key:"roleRemoving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-removing","Role Removed")}
|
||||||
]})},
|
],cliDisplayName:"Messages",cliDisplayDescription:"Manage all messages & DM's for each action of the bot. (Visit docs for more info)"})},
|
||||||
]})}
|
],cliDisplayName:"System",cliDisplayDescription:"Configure everything related to the ticket system."})}
|
||||||
]})
|
],cliDisplayName:"General",cliDisplayDescription:"General settings for the bot."})
|
||||||
|
|
||||||
export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
|
export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],cliDisplayPropertyName:"option",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
|
||||||
//TICKET
|
//TICKET
|
||||||
{name:"ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{children:[
|
{name:"Ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],cliInitSkipKeys:["readonlyAdmins"],children:[
|
||||||
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
|
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this ticket option. Used in panels."})},
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:45})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this ticket option."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256})},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this ticket option."})},
|
||||||
|
|
||||||
//TICKET BUTTON
|
//TICKET BUTTON
|
||||||
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
||||||
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)},
|
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})},
|
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
{key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"]})},
|
{key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
|
||||||
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
||||||
const lt = checker.locationTraceDeref(locationTrace)
|
const lt = checker.locationTraceDeref(locationTrace)
|
||||||
//check if emoji & label exists
|
//check if emoji & label exists
|
||||||
@@ -318,80 +324,89 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
|
|||||||
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
||||||
return false
|
return false
|
||||||
}else return true
|
}else return true
|
||||||
}})},
|
},cliDisplayName:"Button",cliDisplayDescription:"Customise the button/dropdown layout of this ticket option."})},
|
||||||
|
|
||||||
//TICKET ADMINS
|
//TICKET ADMINS
|
||||||
{key:"ticketAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false})},
|
{key:"ticketAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false,cliDisplayPropertyName:"ticket admin role",cliDisplayName:"Ticket Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to interact with this ticket option."},{cliDisplayName:"Ticket Admin Role",cliDisplayDescription:"The discord role ID of a ticket admin."})},
|
||||||
{key:"readonlyAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false})},
|
{key:"readonlyAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false,cliInitDefaultValue:[],cliDisplayPropertyName:"read-only ticket admin role",cliDisplayName:"Readonly Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to read this ticket option."},{cliDisplayName:"Readonly Admin Role",cliDisplayDescription:"The discord role ID of a readonly admin."})},
|
||||||
{key:"allowCreationByBlacklistedUsers",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{})},
|
{key:"allowCreationByBlacklistedUsers",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{cliDisplayName:"Allow Creation By Blacklisted Users",cliDisplayDescription:"When enabled, the blacklist doesn't apply to this ticket option/type and users are still able to create a ticket."})},
|
||||||
{key:"questions",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5})},
|
{key:"questions",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5,cliDisplayPropertyName:"question",cliDisplayName:"Questions",cliDisplayDescription:"A list of valid question IDs to ask before creating this ticket."},{cliDisplayName:"Question ID",cliDisplayDescription:"A valid question ID from the questions.json config.",cliAutocompleteFunc:async () => {
|
||||||
|
const uncheckedRawData = opendiscord.configs.get("opendiscord:questions").data
|
||||||
|
if (!Array.isArray(uncheckedRawData)) return null
|
||||||
|
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
|
||||||
|
return (idList.length > 0) ? idList : null
|
||||||
|
}})},
|
||||||
|
|
||||||
//TICKET CHANNEL
|
//TICKET CHANNEL
|
||||||
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{children:[
|
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{cliInitSkipKeys:["backupCategory","claimedCategory"],children:[
|
||||||
{key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/})},
|
{key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/,cliDisplayName:"Prefix",cliDisplayDescription:"The prefix of the name of the ticket channel. (e.g. 'question-')"})},
|
||||||
{key:"suffix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-id","random-number","random-hex","counter-dynamic","counter-fixed"]})},
|
{key:"suffix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-id","random-number","random-hex","counter-dynamic","counter-fixed"],cliDisplayName:"Suffix",cliDisplayDescription:"The suffix mode to use. The number/text will be appended after the prefix."})},
|
||||||
|
|
||||||
{key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[])},
|
{key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[],{cliDisplayName:"Category",cliDisplayDescription:"The category the ticket will be created in. Leave empty for no category."})},
|
||||||
{key:"closedCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-closed-category","category",true,[])},
|
{key:"closedCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-closed-category","category",true,[],{cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where the ticket will be moved to when closed."})},
|
||||||
{key:"backupCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-backup-category","category",true,[])},
|
{key:"backupCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-backup-category","category",true,[],{cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where the ticket will be created in when the primary category is full (50 channels)."})},
|
||||||
{key:"claimedCategory",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel-claimed-category",{children:[
|
{key:"claimedCategory",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],cliDisplayPropertyName:"claim category",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel-claimed-category",{children:[
|
||||||
{key:"user",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-user","user",false,[])},
|
{key:"user",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-user","user",false,[],{cliDisplayName:"User",cliDisplayDescription:"A discord user ID of the ticket claimer."})},
|
||||||
{key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-category","category",false,[])}
|
{key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-category","category",false,[],{cliDisplayName:"Category",cliDisplayDescription:"A discord category ID to move the ticket to."})}
|
||||||
]})})},
|
],cliDisplayName:"Claimed Category",cliDisplayDescription:"A collection of a user ID and a category ID. The ticket will be moved to the category when this user claims the ticket."}),cliDisplayName:"Claimed Categories",cliDisplayDescription:"Add categories to move the ticket to when a user claims a ticket."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-description",{})},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-description",{cliDisplayName:"Channel Description",cliDisplayDescription:"The description of the ticket channel. Visible in the discord client."})},
|
||||||
]})},
|
],cliDisplayName:"Channel",cliDisplayDescription:"Manage all settings related to the ticket channel and categories."})},
|
||||||
|
|
||||||
//DM MESSAGE
|
//DM MESSAGE
|
||||||
{key:"dmMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-dm-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-dm-message",{children:[
|
{key:"dmMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-dm-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-dm-message",{children:[
|
||||||
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-message-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the DM message on ticket creation."})},
|
||||||
|
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096,cliDisplayName:"Message Text",cliDisplayDescription:"The raw text of the DM message. Leave empty to only use the embed."})},
|
||||||
{key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")}
|
{key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")}
|
||||||
]})})},
|
],cliDisplayName:"DM Message",cliDisplayDescription:"The DM message is the message that will be sent to the creator of the ticket when he/she creates a ticket."}),cliDisplayName:"DM Message",cliDisplayDescription:"The DM message is the message that will be sent to the creator of the ticket when he/she creates a ticket."})},
|
||||||
|
|
||||||
//TICKET MESSAGE
|
//TICKET MESSAGE
|
||||||
{key:"ticketMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-message",{children:[
|
{key:"ticketMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-message",{children:[
|
||||||
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-message-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the ticket message on ticket creation. (Recommended)"})},
|
||||||
|
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096,cliDisplayName:"Message Text",cliDisplayDescription:"The raw text of the ticket message. Leave empty to only use the embed."})},
|
||||||
{key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")},
|
{key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")},
|
||||||
{key:"ping",optional:false,priority:0,checker:createTicketPingStructure("opendiscord:ticket-message-ping")}
|
{key:"ping",optional:false,priority:0,checker:createTicketPingStructure("opendiscord:ticket-message-ping")}
|
||||||
]})})},
|
],cliDisplayName:"Ticket Message",cliDisplayDescription:"The Ticket Message is the message that will be sent in the ticket itself. It contains a few buttons for quick access to actions."}),cliDisplayName:"Ticket Message",cliDisplayDescription:"The Ticket Message is the message that will be sent in the ticket itself. It contains a few buttons for quick access to actions."})},
|
||||||
|
|
||||||
//AUTOCLOSE
|
//AUTOCLOSE
|
||||||
{key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autoclose",{children:[
|
{key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autoclose",{children:[
|
||||||
{key:"enableInactiveHours",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-hours",{})},
|
{key:"enableInactiveHours",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-hours",{cliDisplayName:"Enable Inactive Hours",cliDisplayDescription:"Enable/disable closing the ticket when it has been inactive for the configured amount of time."})},
|
||||||
{key:"inactiveHours",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autoclose-hours",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:8544})},
|
{key:"inactiveHours",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autoclose-hours",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:8544,cliDisplayName:"Inactive Hours",cliDisplayDescription:"The amount of hours the ticket must be inactive."})},
|
||||||
{key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-leave",{})},
|
{key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-leave",{cliDisplayName:"Enable User Leave",cliDisplayDescription:"Instantly close the ticket when the creator of the ticket leaves the server."})},
|
||||||
{key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-disable-claim",{})},
|
{key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-disable-claim",{cliDisplayName:"Disable On Claim",cliDisplayDescription:"Disable the autoclose system when the ticket is claimed by any admin."})},
|
||||||
]})},
|
],cliDisplayName:"Autoclose",cliDisplayDescription:"Manage the autoclose system for this ticket type/option."})},
|
||||||
|
|
||||||
//AUTODELETE
|
//AUTODELETE
|
||||||
{key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autodelete",{children:[
|
{key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autodelete",{children:[
|
||||||
{key:"enableInactiveDays",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-days",{})},
|
{key:"enableInactiveDays",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-days",{cliDisplayName:"Enable Inactive Days",cliDisplayDescription:"Enable/disable deleting the ticket when it has been inactive for the configured amount of time."})},
|
||||||
{key:"inactiveDays",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autodelete-days",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:356})},
|
{key:"inactiveDays",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autodelete-days",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:356,cliDisplayName:"Inactive Days",cliDisplayDescription:"The amount of days the ticket must be inactive."})},
|
||||||
{key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-leave",{})},
|
{key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-leave",{cliDisplayName:"Enable User Leave",cliDisplayDescription:"Instantly delete the ticket when the creator of the ticket leaves the server."})},
|
||||||
{key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-disable-claim",{})},
|
{key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-disable-claim",{cliDisplayName:"Disable On Claim",cliDisplayDescription:"Disable the autodelete system when the ticket is claimed by any admin."})},
|
||||||
]})},
|
],cliDisplayName:"Autodelete",cliDisplayDescription:"Manage the autodelete system for this ticket type/option."})},
|
||||||
|
|
||||||
//COOLDOWN
|
//COOLDOWN
|
||||||
{key:"cooldown",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-cooldown",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-cooldown",{children:[
|
{key:"cooldown",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-cooldown",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-cooldown",{children:[
|
||||||
{key:"cooldownMinutes",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-cooldown-minutes",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,max:512640})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-cooldown-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the cooldown of this ticket option."})},
|
||||||
]})})},
|
{key:"cooldownMinutes",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-cooldown-minutes",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,max:512640,cliDisplayName:"Cooldown Minutes",cliDisplayDescription:"The amount of minutes a user needs to wait before creating another ticket of this type/option."})},
|
||||||
|
],cliDisplayName:"Cooldown",cliDisplayDescription:"Manage cooldowns for this ticket type/option."}),cliDisplayName:"Cooldown",cliDisplayDescription:"Manage cooldowns for this ticket type/option."})},
|
||||||
|
|
||||||
//LIMITS
|
//LIMITS
|
||||||
{key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-limits",{children:[
|
{key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-limits",{children:[
|
||||||
{key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-limits-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the limits of this ticket option. This is not related to the global ticket limits."})},
|
||||||
{key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}
|
{key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,cliInitDefaultValue:10,cliDisplayName:"Global Maximum",cliDisplayDescription:"The maximum amount of tickets of this type/option that are able to exist in the server at the same time."})},
|
||||||
]})})},
|
{key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,cliInitDefaultValue:3,cliDisplayName:"User Maximum",cliDisplayDescription:"The maximum amount of tickets of this type/option from a specific user that are able to exist in the server at the same time."})}
|
||||||
]})},
|
],cliDisplayName:"Option Limits",cliDisplayDescription:"Manage option-based limits for ticket creation to reduce the workload on your support team."}),cliDisplayName:"Limits",cliDisplayDescription:"Manage option-based limits for ticket creation to reduce the workload on your support team."})},
|
||||||
|
],cliDisplayName:"Ticket Option",cliDisplayDescription:"Manage all ticket-specific settings of this option/type."})},
|
||||||
|
|
||||||
//WEBSITE
|
//WEBSITE
|
||||||
{name:"website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:options-website",{children:[
|
{name:"Website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:website",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
|
||||||
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
|
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this website option. Used in panels."})},
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:45})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this website option."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256})},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this website option."})},
|
||||||
|
|
||||||
//WEBSITE BUTTON
|
//WEBSITE BUTTON
|
||||||
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
||||||
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)},
|
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})},
|
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
||||||
const lt = checker.locationTraceDeref(locationTrace)
|
const lt = checker.locationTraceDeref(locationTrace)
|
||||||
//check if emoji & label exists
|
//check if emoji & label exists
|
||||||
@@ -401,23 +416,23 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
|
|||||||
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
||||||
return false
|
return false
|
||||||
}else return true
|
}else return true
|
||||||
}})},
|
},cliDisplayName:"Button",cliDisplayDescription:"Customise the button layout of this website option."})},
|
||||||
|
|
||||||
//WEBSITE URL
|
//WEBSITE URL
|
||||||
{key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:website-url",false,{allowHttp:false})},
|
{key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:website-url",false,{allowHttp:false},{cliDisplayName:"URL",cliDisplayDescription:"The URL this button will link to."})},
|
||||||
]})},
|
],cliDisplayName:"Website Option",cliDisplayDescription:"Manage all settings of this website/url option."})},
|
||||||
|
|
||||||
//REACTION ROLES
|
//REACTION ROLES
|
||||||
{name:"role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:options-role",{children:[
|
{name:"Reaction Role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:role",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
|
||||||
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
|
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this role option. Used in panels."})},
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:45})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this role option."})},
|
||||||
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256})},
|
{key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this role option."})},
|
||||||
|
|
||||||
//ROLE BUTTON
|
//ROLE BUTTON
|
||||||
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
{key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
|
||||||
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)},
|
{key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})},
|
{key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
|
||||||
{key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"]})},
|
{key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
|
||||||
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
|
||||||
const lt = checker.locationTraceDeref(locationTrace)
|
const lt = checker.locationTraceDeref(locationTrace)
|
||||||
//check if emoji & label exists
|
//check if emoji & label exists
|
||||||
@@ -427,117 +442,129 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
|
|||||||
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
|
||||||
return false
|
return false
|
||||||
}else return true
|
}else return true
|
||||||
}})},
|
},cliDisplayName:"Button",cliDisplayDescription:"Customise the button layout of this reaction role option."})},
|
||||||
|
|
||||||
//ROLE SETTINGS
|
//ROLE SETTINGS
|
||||||
{key:"roles",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-roles","role",[],{allowDoubles:false,minLength:1})},
|
{key:"roles",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-roles","role",[],{allowDoubles:false,minLength:1,cliDisplayPropertyName:"role",cliDisplayName:"Roles",cliDisplayDescription:"A list of roles to add/remove when clicking on the button."},{cliDisplayName:"Role",cliDisplayDescription:"The discord role ID you want to add/remove."})},
|
||||||
{key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-mode",{choices:["add","remove","add&remove"]})},
|
{key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-mode",{choices:["add","remove","add&remove"],cliDisplayName:"Mode",cliDisplayDescription:"Decide how the button will work: add-only, remove-only or add & remove."})},
|
||||||
{key:"removeRolesOnAdd",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false})},
|
{key:"removeRolesOnAdd",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false,cliDisplayPropertyName:"role",cliDisplayName:"Remove Roles On Add",cliDisplayDescription:"An additional list of roles to remove when the roles of this option are added. (Can be used to select between roles)"},{cliDisplayName:"Remove Role",cliDisplayDescription:"The discord role ID you want to remove when other roles are added."})},
|
||||||
{key:"addOnMemberJoin",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{})},
|
{key:"addOnMemberJoin",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{cliDisplayName:"Add On Member Join",cliDisplayDescription:"Automatically add these roles to a user when joining the server."})},
|
||||||
]})},
|
],cliDisplayName:"Reaction Role Option",cliDisplayDescription:"Manage all settings of this reaction role option."})},
|
||||||
]})})
|
],cliDisplayName:"Option",cliDisplayDescription:"Manage an option of one of the 3 types: ticket, website, role."}),cliDisplayName:"Options",cliDisplayDescription:"A list of all options in the bot. Here you can add, modify & remove ticket types, website buttons & reaction roles!"})
|
||||||
|
|
||||||
export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{children:[
|
export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],cliDisplayPropertyName:"panel",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","dropdown"],children:[
|
||||||
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
|
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this panel. Used in the /panel command."})},
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50,cliDisplayName:"Name",cliDisplayDescription:"The name of this panel."})},
|
||||||
{key:"dropdown",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{})},
|
{key:"dropdown",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{cliDisplayName:"Dropdown",cliDisplayDescription:"Decide whether to use buttons or a dropdown in the panel. Dropdowns only support options of the 'ticket' type!"})},
|
||||||
{key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,maxLength:25})},
|
{key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,maxLength:25,cliDisplayPropertyName:"option",cliDisplayName:"Options",cliDisplayDescription:"A list of valid option IDs to show in this panel."},{cliDisplayName:"Option ID",cliDisplayDescription:"A valid option ID from the options.json config.",cliAutocompleteFunc:async () => {
|
||||||
|
const uncheckedRawData = opendiscord.configs.get("opendiscord:options").data
|
||||||
|
if (!Array.isArray(uncheckedRawData)) return null
|
||||||
|
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
|
||||||
|
return (idList.length > 0) ? idList : null
|
||||||
|
}})},
|
||||||
|
|
||||||
//EMBED & TEXT
|
//EMBED & TEXT
|
||||||
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-text",{maxLength:4096})},
|
{key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-text",{maxLength:4096,cliDisplayName:"Panel Text",cliDisplayDescription:"The raw text of the panel message. Leave empty to use the embed."})},
|
||||||
{key:"embed",optional:false,priority:0,checker:createPanelEmbedStructure("opendiscord:panel-embed")},
|
{key:"embed",optional:false,priority:0,checker:createPanelEmbedStructure("opendiscord:panel-embed")},
|
||||||
|
|
||||||
//SETTINGS
|
//SETTINGS
|
||||||
{key:"settings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{children:[
|
{key:"settings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{cliInitSkipKeys:["dropdownPlaceholder","describeOptionsCustomTitle"],children:[
|
||||||
{key:"dropdownPlaceholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100})},
|
{key:"dropdownPlaceholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100,cliInitDefaultValue:"Create a ticket!",cliDisplayName:"Dropdown Placeholder",cliDisplayDescription:"Configure the text displayed in the dropdown when nothing is selected."})},
|
||||||
{key:"enableMaxTicketsWarningInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{})},
|
{key:"enableMaxTicketsWarningInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{cliDisplayName:"Enable Max Tickets Warning (Text)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the text contents of the panel."})},
|
||||||
{key:"enableMaxTicketsWarningInEmbed",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{})},
|
{key:"enableMaxTicketsWarningInEmbed",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{cliDisplayName:"Enable Max Tickets Warning (Embed)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the embed of the panel."})},
|
||||||
|
|
||||||
{key:"describeOptionsLayout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-layout",{choices:["simple","normal","detailed"]})},
|
{key:"describeOptionsLayout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-layout",{choices:["simple","normal","detailed"],cliDisplayName:"Describe Options Layout",cliDisplayDescription:"The layout to use in the auto-generated option descriptions (simple, normal, detailed)."})},
|
||||||
{key:"describeOptionsCustomTitle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-title",{maxLength:512})},
|
{key:"describeOptionsCustomTitle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-title",{maxLength:512,cliDisplayName:"Describe Options Title",cliDisplayDescription:"Customise the title to use in the auto-generated option descriptions."})},
|
||||||
{key:"describeOptionsInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-text",{})},
|
{key:"describeOptionsInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-text",{cliDisplayName:"Describe Options In Text",cliDisplayDescription:"Enable/disable showing the auto-generated option descriptions in the raw text contents of the panel."})},
|
||||||
{key:"describeOptionsInEmbedFields",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-fields",{})},
|
{key:"describeOptionsInEmbedFields",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-fields",{cliDisplayName:"Describe Options In Embed Fields",cliDisplayDescription:"Enable/disable showing the auto-generated option descriptions in the embed fields of the panel."})},
|
||||||
{key:"describeOptionsInEmbedDescription",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-embed",{})},
|
{key:"describeOptionsInEmbedDescription",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-embed",{cliDisplayName:"Describe Options In Embed Description",cliDisplayDescription:"Enable/disable showing the auto-generated option descriptions in the embed description of the panel."})},
|
||||||
]})},
|
],cliDisplayName:"Settings",cliDisplayDescription:"Manage additional settings & customisability for this panel."})},
|
||||||
]})})
|
],cliDisplayName:"Panel",cliDisplayDescription:"Manage, customise and configure a panel to your preference."}),cliDisplayName:"Panels",cliDisplayDescription:"A list of all panels in the bot. Here you can add, modify & remove existing panels or customise them to your preference."})
|
||||||
|
|
||||||
export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:questions",{children:[
|
export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],cliDisplayPropertyName:"question",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:questions",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
|
||||||
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})},
|
{key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
|
||||||
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45})},
|
{key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
|
||||||
{key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-type",{choices:["short","paragraph"]})},
|
{key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-type",{choices:["short","paragraph"],cliDisplayName:"Type",cliDisplayDescription:"The type of this question (short/paragraph)."})},
|
||||||
|
|
||||||
{key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{})},
|
{key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
|
||||||
{key:"placeholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100})},
|
{key:"placeholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
|
||||||
|
|
||||||
{key:"length",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
|
{key:"length",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
|
||||||
{key:"min",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
|
||||||
{key:"max",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false})},
|
{key:"min",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
|
||||||
]})})},
|
{key:"max",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
|
||||||
]})})
|
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
|
||||||
|
],cliDisplayName:"Question",cliDisplayDescription:"Manage, customise and configure a question to your preference."}),cliDisplayName:"Questions",cliDisplayDescription:"A list of all questions in the bot. Here you can add, modify & remove existing questions or customise them to your preference."})
|
||||||
|
|
||||||
export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[
|
export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[
|
||||||
//GENERAL
|
//GENERAL
|
||||||
{key:"general",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-general",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-general",{children:[
|
{key:"general",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-general",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-general",{children:[
|
||||||
{key:"enableChannel",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-channel",{})},
|
{key:"enabled",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the transcript system."})},
|
||||||
{key:"enableCreatorDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-creator-dm",{})},
|
|
||||||
{key:"enableParticipantDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-participant-dm",{})},
|
{key:"enableChannel",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-channel",{cliDisplayName:"Enable Channel",cliDisplayDescription:"Send the transcript to a specific channel in your server (configurable in 'channel' property)."})},
|
||||||
{key:"enableActiveAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-active-admin-dm",{})},
|
{key:"enableCreatorDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-creator-dm",{cliDisplayName:"Enable Creator DM",cliDisplayDescription:"Send the transcript in DM to the creator of the ticket."})},
|
||||||
{key:"enableEveryAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-every-admin-dm",{})},
|
{key:"enableParticipantDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-participant-dm",{cliDisplayName:"Enable Participant DM",cliDisplayDescription:"Send the transcript in DM to all non-admin participants of the ticket."})},
|
||||||
|
{key:"enableActiveAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-active-admin-dm",{cliDisplayName:"Enable Active Admin DM",cliDisplayDescription:"Send the transcript in DM to all admins that actively wrote in the ticket."})},
|
||||||
|
{key:"enableEveryAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-every-admin-dm",{cliDisplayName:"Enable Every Admin DM",cliDisplayDescription:"Send the transcript in DM to all admins assigned to the ticket."})},
|
||||||
|
|
||||||
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:transcripts-channel","channel",true,[])},
|
{key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:transcripts-channel","channel",true,[],{cliDisplayName:"Channel",cliDisplayDescription:"The discord channel ID to send the transcript to."})},
|
||||||
{key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-mode",{choices:["html","text"]})},
|
{key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-mode",{choices:["html","text"],cliDisplayName:"Transcript Mode",cliDisplayDescription:"The transcript type to use: 'text' or 'html'."})},
|
||||||
]})})},
|
],cliDisplayName:"General",cliDisplayDescription:"General settings for the transcripts."}),cliDisplayName:"General",cliDisplayDescription:"General settings for the transcripts."})},
|
||||||
|
|
||||||
//EMBED SETTINGS
|
//EMBED SETTINGS
|
||||||
{key:"embedSettings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-embed-settings",{children:[
|
{key:"embedSettings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-embed-settings",{children:[
|
||||||
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-embed-color",false,true)},
|
{key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-embed-color",false,true,{cliDisplayName:"Custom Color",cliDisplayDescription:"Use a custom color in the embed. When empty, the default bot color will be used."})},
|
||||||
{key:"listAllParticipants",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-list-participants",{})},
|
{key:"listAllParticipants",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-list-participants",{cliDisplayName:"List Participants",cliDisplayDescription:"List all participants of the ticket in the embed."})},
|
||||||
{key:"includeTicketStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-include-ticket-stats",{})},
|
{key:"includeTicketStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-include-ticket-stats",{cliDisplayName:"Include Ticket Stats",cliDisplayDescription:"Include some stats from the ticket in the embed."})},
|
||||||
]})},
|
],cliDisplayName:"Embed Settings",cliDisplayDescription:"Settings and customisability related to the embed which contains the transcript."})},
|
||||||
|
|
||||||
//TEXT STYLE
|
//TEXT STYLE
|
||||||
{key:"textTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-text",{children:[
|
{key:"textTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-text",{children:[
|
||||||
{key:"layout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-layout",{choices:["simple","normal","detailed"]})},
|
{key:"layout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-layout",{choices:["simple","normal","detailed"],cliDisplayName:"Layout",cliDisplayDescription:"The layout to use in the text-transcripts (simple, normal, detailed)."})},
|
||||||
{key:"includeStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-stats",{})},
|
{key:"includeStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-stats",{cliDisplayName:"Include Stats",cliDisplayDescription:"Include statistics in the transcript?"})},
|
||||||
{key:"includeIds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-ids",{})},
|
{key:"includeIds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-ids",{cliDisplayName:"Include Ids",cliDisplayDescription:"Include role, channel & user ID's in the transcript?"})},
|
||||||
{key:"includeEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-embeds",{})},
|
{key:"includeEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-embeds",{cliDisplayName:"Include Embeds",cliDisplayDescription:"Include message embeds in the transcript?"})},
|
||||||
{key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-files",{})},
|
{key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-files",{cliDisplayName:"Include Files",cliDisplayDescription:"Include files & attachments in the transcript?"})},
|
||||||
{key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-bots",{})},
|
{key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-bots",{cliDisplayName:"Include Bots",cliDisplayDescription:"Include messages sent by bots/apps?"})},
|
||||||
|
|
||||||
{key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-file-mode",{choices:["custom","channel-name","channel-id","user-name","user-id"]})},
|
{key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-file-mode",{choices:["custom","channel-name","channel-id","user-name","user-id"],cliDisplayName:"File Mode",cliDisplayDescription:"Select the mode the transcript will be named: custom, channel-name, user-name, user-id."})},
|
||||||
{key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/})},
|
{key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/,cliDisplayName:"Custom File Name",cliDisplayDescription:"Use this as transcript name when the mode is set to 'custom'."})},
|
||||||
]})},
|
],cliDisplayName:"Text Transcript Style",cliDisplayDescription:"Configure the 'Text Transcripts' from Open Ticket."})},
|
||||||
|
|
||||||
//HTML STYLE
|
//HTML STYLE
|
||||||
{key:"htmlTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html",{children:[
|
{key:"htmlTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html",{children:[
|
||||||
//HTML BACKGROUND
|
//HTML BACKGROUND
|
||||||
{key:"background",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-background",{property:"enableCustomBackground",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-background",{children:[
|
{key:"background",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-background",{property:"enableCustomBackground",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-background",{children:[
|
||||||
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-background-color",false,true)},
|
{key:"enableCustomBackground",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-html-background-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable background customisation in the HTML Transcripts."})},
|
||||||
{key:"backgroundImage",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-background-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})},
|
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-background-color",false,true,{cliDisplayName:"Background Color",cliDisplayDescription:"The hex-color of the background."})},
|
||||||
]})})},
|
{key:"backgroundImage",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-background-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]},{cliDisplayName:"Background Image",cliDisplayDescription:"A URL to an image to use in the background. This will overwrite the background color."})},
|
||||||
|
],cliDisplayName:"Background Style",cliDisplayDescription:"Customise the background of the HTML Transcripts."}),cliDisplayName:"Background Style",cliDisplayDescription:"Customise the background of the HTML Transcripts."})},
|
||||||
|
|
||||||
//HTML HEADER
|
//HTML HEADER
|
||||||
{key:"header",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-header",{property:"enableCustomHeader",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-header",{children:[
|
{key:"header",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-header",{property:"enableCustomHeader",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-header",{children:[
|
||||||
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-bgcolor",false,false)},
|
{key:"enableCustomHeader",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-html-header-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable header customisation in the HTML Transcripts."})},
|
||||||
{key:"decoColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-decocolor",false,false)},
|
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-bgcolor",false,false,{cliDisplayName:"Background Color",cliDisplayDescription:"The hex-color of the header background."})},
|
||||||
{key:"textColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-textcolor",false,false)},
|
{key:"decoColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-decocolor",false,false,{cliDisplayName:"Decoration Color",cliDisplayDescription:"The hex-color of the header decoration (e.g. horizontal line)."})},
|
||||||
]})})},
|
{key:"textColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-textcolor",false,false,{cliDisplayName:"Text Color",cliDisplayDescription:"The hex-color of the header text."})},
|
||||||
|
],cliDisplayName:"Header Style",cliDisplayDescription:"Customise the header of the HTML Transcripts."}),cliDisplayName:"Header Style",cliDisplayDescription:"Customise the header of the HTML Transcripts."})},
|
||||||
|
|
||||||
//HTML STATS
|
//HTML STATS
|
||||||
{key:"stats",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-stats",{property:"enableCustomStats",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-stats",{children:[
|
{key:"stats",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-stats",{property:"enableCustomStats",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-stats",{children:[
|
||||||
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-bgcolor",false,false)},
|
{key:"enableCustomStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-html-stats-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable stats customisation in the HTML Transcripts."})},
|
||||||
{key:"keyTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-keycolor",false,false)},
|
{key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-bgcolor",false,false,{cliDisplayName:"Background Color",cliDisplayDescription:"The hex-color of the stats background."})},
|
||||||
{key:"valueTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-valuecolor",false,false)},
|
{key:"keyTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-keycolor",false,false,{cliDisplayName:"Key Text Color",cliDisplayDescription:"The hex-color of the stats key text."})},
|
||||||
{key:"hideBackgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidebgcolor",false,false)},
|
{key:"valueTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-valuecolor",false,false,{cliDisplayName:"Value Text Color",cliDisplayDescription:"The hex-color of the stats value text."})},
|
||||||
{key:"hideTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidecolor",false,false)},
|
{key:"hideBackgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidebgcolor",false,false,{cliDisplayName:"Hide Background Color",cliDisplayDescription:"The hex-color of the stats hide button background."})},
|
||||||
]})})},
|
{key:"hideTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidecolor",false,false,{cliDisplayName:"Hide Text Color",cliDisplayDescription:"The hex-color of the stats hide button text."})},
|
||||||
|
],cliDisplayName:"Stats Style",cliDisplayDescription:"Customise the stats of the HTML Transcripts."}),cliDisplayName:"Stats Style",cliDisplayDescription:"Customise the stats of the HTML Transcripts."})},
|
||||||
|
|
||||||
//HTML FAVICON
|
//HTML FAVICON
|
||||||
{key:"favicon",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-favicon",{property:"enableCustomFavicon",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-favicon",{children:[
|
{key:"favicon",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-favicon",{property:"enableCustomFavicon",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-favicon",{children:[
|
||||||
{key:"imageUrl",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-favicon-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp"]})},
|
{key:"enableCustomFavicon",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-html-favicon-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable favicon customisation in the HTML Transcripts."})},
|
||||||
]})})},
|
{key:"imageUrl",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-favicon-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp"]},{cliDisplayName:"LOREMIPSUM",cliDisplayDescription:"IPSUMLOREM"})},
|
||||||
]})},
|
],cliDisplayName:"Favicon Style",cliDisplayDescription:"Customise the favicon of the HTML Transcripts."}),cliDisplayName:"Favicon Style",cliDisplayDescription:"Customise the favicon of the HTML Transcripts."})},
|
||||||
]})
|
],cliDisplayName:"Html Transcript Style",cliDisplayDescription:"Configure the 'Html Transcripts' from Open Ticket."})},
|
||||||
|
],cliDisplayName:"Transcripts",cliDisplayDescription:"All settings related to transcripts."})
|
||||||
|
|
||||||
export const defaultUnusedOptionsFunction = (manager:api.ODCheckerManager, functions:api.ODCheckerFunctionManager): api.ODCheckerResult => {
|
export const defaultUnusedOptionsFunction = (manager:api.ODCheckerManager, functions:api.ODCheckerFunctionManager): api.ODCheckerResult => {
|
||||||
const optionList: string[] = manager.storage.get("openticket","option-ids")
|
const optionList: string[] = manager.storage.get("openticket","option-ids")
|
||||||
|
|||||||
@@ -1,12 +1,374 @@
|
|||||||
import {opendiscord, api, utilities} from "../../index"
|
import {opendiscord, api, utilities} from "../../index"
|
||||||
|
import * as fjs from "formatted-json-stringify"
|
||||||
|
|
||||||
export const loadAllConfigs = async () => {
|
export const loadAllConfigs = async () => {
|
||||||
const devconfigFlag = opendiscord.flags.get("opendiscord:dev-config")
|
const devconfigFlag = opendiscord.flags.get("opendiscord:dev-config")
|
||||||
const isDevconfig = devconfigFlag ? devconfigFlag.value : false
|
const isDevconfig = devconfigFlag ? devconfigFlag.value : false
|
||||||
|
|
||||||
|
/** How to add more config variables?
|
||||||
|
* - Add the variable to the config files in `./config/` & `./devconfig/`.
|
||||||
|
* - Add the variable to the config in ./src/core/api/defaults/config.ts (interfaces + types)
|
||||||
|
* - Add the variable to the config checker in ./src/data/framework/checkerLoader.ts
|
||||||
|
* - Make sure it's compatible with the Interactive Setup CLI.
|
||||||
|
* - Make sure the Migration Manager automatically adds the variable when missing.
|
||||||
|
* - Add the variable to the formatters in this file.
|
||||||
|
* - Update the documentation reference.
|
||||||
|
*/
|
||||||
|
|
||||||
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/"))
|
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultGeneralFormatter))
|
||||||
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/"))
|
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultQuestionsFormatter))
|
||||||
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/"))
|
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultOptionsFormatter))
|
||||||
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/"))
|
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultPanelsFormatter))
|
||||||
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/"))
|
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultTranscriptsFormatter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//FORMATTERS
|
||||||
|
export const defaultGeneralFormatter = new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.ObjectFormatter("_INFO",true,[
|
||||||
|
new fjs.PropertyFormatter("support"),
|
||||||
|
new fjs.PropertyFormatter("discord"),
|
||||||
|
new fjs.PropertyFormatter("version"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("token"),
|
||||||
|
new fjs.PropertyFormatter("tokenFromENV"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("mainColor"),
|
||||||
|
new fjs.PropertyFormatter("language"),
|
||||||
|
new fjs.PropertyFormatter("prefix"),
|
||||||
|
new fjs.PropertyFormatter("serverId"),
|
||||||
|
new fjs.ArrayFormatter("globalAdmins",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("slashCommands"),
|
||||||
|
new fjs.PropertyFormatter("textCommands"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("status",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.PropertyFormatter("text"),
|
||||||
|
new fjs.PropertyFormatter("status"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("system",true,[
|
||||||
|
new fjs.PropertyFormatter("removeParticipantsOnClose"),
|
||||||
|
new fjs.PropertyFormatter("replyOnTicketCreation"),
|
||||||
|
new fjs.PropertyFormatter("replyOnReactionRole"),
|
||||||
|
new fjs.PropertyFormatter("useTranslatedConfigChecker"),
|
||||||
|
new fjs.PropertyFormatter("preferSlashOverText"),
|
||||||
|
new fjs.PropertyFormatter("sendErrorOnUnknownCommand"),
|
||||||
|
new fjs.PropertyFormatter("questionFieldsInCodeBlock"),
|
||||||
|
new fjs.PropertyFormatter("disableVerifyBars"),
|
||||||
|
new fjs.PropertyFormatter("useRedErrorEmbeds"),
|
||||||
|
new fjs.PropertyFormatter("emojiStyle"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("enableTicketClaimButtons"),
|
||||||
|
new fjs.PropertyFormatter("enableTicketCloseButtons"),
|
||||||
|
new fjs.PropertyFormatter("enableTicketPinButtons"),
|
||||||
|
new fjs.PropertyFormatter("enableTicketDeleteButtons"),
|
||||||
|
new fjs.PropertyFormatter("enableTicketActionWithReason"),
|
||||||
|
new fjs.PropertyFormatter("enableDeleteWithoutTranscript"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("logs",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("channel"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("limits",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("globalMaximum"),
|
||||||
|
new fjs.PropertyFormatter("userMaximum"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("permissions",true,[
|
||||||
|
new fjs.PropertyFormatter("help"),
|
||||||
|
new fjs.PropertyFormatter("panel"),
|
||||||
|
new fjs.PropertyFormatter("ticket"),
|
||||||
|
new fjs.PropertyFormatter("close"),
|
||||||
|
new fjs.PropertyFormatter("delete"),
|
||||||
|
new fjs.PropertyFormatter("reopen"),
|
||||||
|
new fjs.PropertyFormatter("claim"),
|
||||||
|
new fjs.PropertyFormatter("unclaim"),
|
||||||
|
new fjs.PropertyFormatter("pin"),
|
||||||
|
new fjs.PropertyFormatter("unpin"),
|
||||||
|
new fjs.PropertyFormatter("move"),
|
||||||
|
new fjs.PropertyFormatter("rename"),
|
||||||
|
new fjs.PropertyFormatter("add"),
|
||||||
|
new fjs.PropertyFormatter("remove"),
|
||||||
|
new fjs.PropertyFormatter("blacklist"),
|
||||||
|
new fjs.PropertyFormatter("stats"),
|
||||||
|
new fjs.PropertyFormatter("clear"),
|
||||||
|
new fjs.PropertyFormatter("autoclose"),
|
||||||
|
new fjs.PropertyFormatter("autodelete"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("messages",true,[
|
||||||
|
new fjs.DefaultFormatter("creation",false),
|
||||||
|
new fjs.DefaultFormatter("closing",false),
|
||||||
|
new fjs.DefaultFormatter("deleting",false),
|
||||||
|
new fjs.DefaultFormatter("reopening",false),
|
||||||
|
new fjs.DefaultFormatter("claiming",false),
|
||||||
|
new fjs.DefaultFormatter("pinning",false),
|
||||||
|
new fjs.DefaultFormatter("adding",false),
|
||||||
|
new fjs.DefaultFormatter("removing",false),
|
||||||
|
new fjs.DefaultFormatter("renaming",false),
|
||||||
|
new fjs.DefaultFormatter("moving",false),
|
||||||
|
new fjs.DefaultFormatter("blacklisting",false),
|
||||||
|
new fjs.DefaultFormatter("roleAdding",false),
|
||||||
|
new fjs.DefaultFormatter("roleRemoving",false),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
|
||||||
|
export const defaultQuestionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
|
||||||
|
{key:"type",value:"short",formatter:new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("required"),
|
||||||
|
new fjs.PropertyFormatter("placeholder"),
|
||||||
|
new fjs.ObjectFormatter("length",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("min"),
|
||||||
|
new fjs.PropertyFormatter("max"),
|
||||||
|
]),
|
||||||
|
])},
|
||||||
|
{key:"type",value:"paragraph",formatter:new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("required"),
|
||||||
|
new fjs.PropertyFormatter("placeholder"),
|
||||||
|
new fjs.ObjectFormatter("length",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("min"),
|
||||||
|
new fjs.PropertyFormatter("max"),
|
||||||
|
]),
|
||||||
|
])}
|
||||||
|
]))
|
||||||
|
|
||||||
|
|
||||||
|
export const defaultOptionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
|
||||||
|
{key:"type",value:"ticket",formatter:new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("button",true,[
|
||||||
|
new fjs.PropertyFormatter("emoji"),
|
||||||
|
new fjs.PropertyFormatter("label"),
|
||||||
|
new fjs.PropertyFormatter("color"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ArrayFormatter("ticketAdmins",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.ArrayFormatter("readonlyAdmins",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.PropertyFormatter("allowCreationByBlacklistedUsers"),
|
||||||
|
new fjs.ArrayFormatter("questions",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("channel",true,[
|
||||||
|
new fjs.PropertyFormatter("prefix"),
|
||||||
|
new fjs.PropertyFormatter("suffix"),
|
||||||
|
new fjs.PropertyFormatter("category"),
|
||||||
|
new fjs.PropertyFormatter("backupCategory"),
|
||||||
|
new fjs.PropertyFormatter("closedCategory"),
|
||||||
|
new fjs.ArrayFormatter("claimedCategory",true,new fjs.ObjectFormatter(null,false,[
|
||||||
|
new fjs.PropertyFormatter("user"),
|
||||||
|
new fjs.PropertyFormatter("category"),
|
||||||
|
])),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("dmMessage",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("text"),
|
||||||
|
new fjs.ObjectFormatter("embed",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("title"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.PropertyFormatter("customColor"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("image"),
|
||||||
|
new fjs.PropertyFormatter("thumbnail"),
|
||||||
|
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("value"),
|
||||||
|
new fjs.PropertyFormatter("inline"),
|
||||||
|
])),
|
||||||
|
new fjs.PropertyFormatter("timestamp"),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("ticketMessage",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("text"),
|
||||||
|
new fjs.ObjectFormatter("embed",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("title"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.PropertyFormatter("customColor"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("image"),
|
||||||
|
new fjs.PropertyFormatter("thumbnail"),
|
||||||
|
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("value"),
|
||||||
|
new fjs.PropertyFormatter("inline"),
|
||||||
|
])),
|
||||||
|
new fjs.PropertyFormatter("timestamp"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("ping",true,[
|
||||||
|
new fjs.PropertyFormatter("@here"),
|
||||||
|
new fjs.PropertyFormatter("@everyone"),
|
||||||
|
new fjs.ArrayFormatter("custom",true,new fjs.PropertyFormatter(null)),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("autoclose",true,[
|
||||||
|
new fjs.PropertyFormatter("enableInactiveHours"),
|
||||||
|
new fjs.PropertyFormatter("inactiveHours"),
|
||||||
|
new fjs.PropertyFormatter("enableUserLeave"),
|
||||||
|
new fjs.PropertyFormatter("disableOnClaim"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("autodelete",true,[
|
||||||
|
new fjs.PropertyFormatter("enableInactiveDays"),
|
||||||
|
new fjs.PropertyFormatter("inactiveDays"),
|
||||||
|
new fjs.PropertyFormatter("enableUserLeave"),
|
||||||
|
new fjs.PropertyFormatter("disableOnClaim"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("cooldown",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("cooldownMinutes"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("limits",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("globalMaximum"),
|
||||||
|
new fjs.PropertyFormatter("userMaximum"),
|
||||||
|
]),
|
||||||
|
])},
|
||||||
|
{key:"type",value:"website",formatter:new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("button",true,[
|
||||||
|
new fjs.PropertyFormatter("emoji"),
|
||||||
|
new fjs.PropertyFormatter("label"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("url"),
|
||||||
|
])},
|
||||||
|
{key:"type",value:"role",formatter:new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.PropertyFormatter("type"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ObjectFormatter("button",true,[
|
||||||
|
new fjs.PropertyFormatter("emoji"),
|
||||||
|
new fjs.PropertyFormatter("label"),
|
||||||
|
new fjs.PropertyFormatter("color"),
|
||||||
|
]),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.ArrayFormatter("roles",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.PropertyFormatter("mode"),
|
||||||
|
new fjs.ArrayFormatter("removeRolesOnAdd",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.PropertyFormatter("addOnMemberJoin"),
|
||||||
|
])}
|
||||||
|
]))
|
||||||
|
|
||||||
|
export const defaultPanelsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.PropertyFormatter("id"),
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("dropdown"),
|
||||||
|
new fjs.ArrayFormatter("options",false,new fjs.PropertyFormatter(null)),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("text"),
|
||||||
|
new fjs.ObjectFormatter("embed",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.PropertyFormatter("title"),
|
||||||
|
new fjs.PropertyFormatter("description"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("customColor"),
|
||||||
|
new fjs.PropertyFormatter("url"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("image"),
|
||||||
|
new fjs.PropertyFormatter("thumbnail"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("footer"),
|
||||||
|
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
|
||||||
|
new fjs.PropertyFormatter("name"),
|
||||||
|
new fjs.PropertyFormatter("value"),
|
||||||
|
new fjs.PropertyFormatter("inline"),
|
||||||
|
])),
|
||||||
|
new fjs.PropertyFormatter("timestamp"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("settings",true,[
|
||||||
|
new fjs.PropertyFormatter("dropdownPlaceholder"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("enableMaxTicketsWarningInText"),
|
||||||
|
new fjs.PropertyFormatter("enableMaxTicketsWarningInEmbed"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("describeOptionsLayout"),
|
||||||
|
new fjs.PropertyFormatter("describeOptionsCustomTitle"),
|
||||||
|
new fjs.PropertyFormatter("describeOptionsInText"),
|
||||||
|
new fjs.PropertyFormatter("describeOptionsInEmbedFields"),
|
||||||
|
new fjs.PropertyFormatter("describeOptionsInEmbedDescription"),
|
||||||
|
]),
|
||||||
|
]))
|
||||||
|
|
||||||
|
export const defaultTranscriptsFormatter = new fjs.ObjectFormatter(null,true,[
|
||||||
|
new fjs.ObjectFormatter("general",true,[
|
||||||
|
new fjs.PropertyFormatter("enabled"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("enableChannel"),
|
||||||
|
new fjs.PropertyFormatter("enableCreatorDM"),
|
||||||
|
new fjs.PropertyFormatter("enableParticipantDM"),
|
||||||
|
new fjs.PropertyFormatter("enableActiveAdminDM"),
|
||||||
|
new fjs.PropertyFormatter("enableEveryAdminDM"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("channel"),
|
||||||
|
new fjs.PropertyFormatter("mode"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("embedSettings",true,[
|
||||||
|
new fjs.PropertyFormatter("customColor"),
|
||||||
|
new fjs.PropertyFormatter("listAllParticipants"),
|
||||||
|
new fjs.PropertyFormatter("includeTicketStats"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("textTranscriptStyle",true,[
|
||||||
|
new fjs.PropertyFormatter("layout"),
|
||||||
|
new fjs.PropertyFormatter("includeStats"),
|
||||||
|
new fjs.PropertyFormatter("includeIds"),
|
||||||
|
new fjs.PropertyFormatter("includeEmbeds"),
|
||||||
|
new fjs.PropertyFormatter("includeFiles"),
|
||||||
|
new fjs.PropertyFormatter("includeBotMessages"),
|
||||||
|
new fjs.TextFormatter(""),
|
||||||
|
new fjs.PropertyFormatter("fileMode"),
|
||||||
|
new fjs.PropertyFormatter("customFileName"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("htmlTranscriptStyle",true,[
|
||||||
|
new fjs.ObjectFormatter("background",true,[
|
||||||
|
new fjs.PropertyFormatter("enableCustomBackground"),
|
||||||
|
new fjs.PropertyFormatter("backgroundColor"),
|
||||||
|
new fjs.PropertyFormatter("backgroundImage"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("header",true,[
|
||||||
|
new fjs.PropertyFormatter("enableCustomHeader"),
|
||||||
|
new fjs.PropertyFormatter("backgroundColor"),
|
||||||
|
new fjs.PropertyFormatter("decoColor"),
|
||||||
|
new fjs.PropertyFormatter("textColor"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("stats",true,[
|
||||||
|
new fjs.PropertyFormatter("enableCustomStats"),
|
||||||
|
new fjs.PropertyFormatter("backgroundColor"),
|
||||||
|
new fjs.PropertyFormatter("keyTextColor"),
|
||||||
|
new fjs.PropertyFormatter("valueTextColor"),
|
||||||
|
new fjs.PropertyFormatter("hideBackgroundColor"),
|
||||||
|
new fjs.PropertyFormatter("hideTextColor"),
|
||||||
|
]),
|
||||||
|
new fjs.ObjectFormatter("favicon",true,[
|
||||||
|
new fjs.PropertyFormatter("enableCustomFavicon"),
|
||||||
|
new fjs.PropertyFormatter("imageUrl"),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
@@ -15,4 +15,6 @@ export const loadAllFlags = async () => {
|
|||||||
opendiscord.flags.add(new api.ODFlag("opendiscord:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"]))
|
opendiscord.flags.add(new api.ODFlag("opendiscord:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"]))
|
||||||
opendiscord.flags.add(new api.ODFlag("opendiscord:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[]))
|
opendiscord.flags.add(new api.ODFlag("opendiscord:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[]))
|
||||||
opendiscord.flags.add(new api.ODFlag("opendiscord:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[]))
|
opendiscord.flags.add(new api.ODFlag("opendiscord:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[]))
|
||||||
|
opendiscord.flags.add(new api.ODFlag("opendiscord:silent","Silent Mode","Run the bot without displaying logs. The startscreen will still be displayed.","--silent",[]))
|
||||||
|
opendiscord.flags.add(new api.ODFlag("opendiscord:cli","Run CLI","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--cli",[]))
|
||||||
}
|
}
|
||||||
+28
-3
@@ -115,6 +115,17 @@ const main = async () => {
|
|||||||
opendiscord.debug.visible = (debugFlag) ? debugFlag.value : false
|
opendiscord.debug.visible = (debugFlag) ? debugFlag.value : false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//load silent mode
|
||||||
|
if (opendiscord.defaults.getDefault("silentLoading")){
|
||||||
|
const silentFlag = opendiscord.flags.get("opendiscord:silent")
|
||||||
|
opendiscord.console.silent = (silentFlag) ? silentFlag.value : false
|
||||||
|
if (opendiscord.console.silent){
|
||||||
|
opendiscord.console.silent = false
|
||||||
|
opendiscord.log("Silent mode is active! Logs won't be shown in the console.","warning")
|
||||||
|
opendiscord.console.silent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//load progress bar renderers
|
//load progress bar renderers
|
||||||
opendiscord.log("Loading progress bars...","system")
|
opendiscord.log("Loading progress bars...","system")
|
||||||
if (opendiscord.defaults.getDefault("progressBarRendererLoading")){
|
if (opendiscord.defaults.getDefault("progressBarRendererLoading")){
|
||||||
@@ -258,9 +269,10 @@ const main = async () => {
|
|||||||
//render config checker
|
//render config checker
|
||||||
const advancedCheckerFlag = opendiscord.flags.get("opendiscord:checker")
|
const advancedCheckerFlag = opendiscord.flags.get("opendiscord:checker")
|
||||||
const disableCheckerFlag = opendiscord.flags.get("opendiscord:no-checker")
|
const disableCheckerFlag = opendiscord.flags.get("opendiscord:no-checker")
|
||||||
|
const useCliFlag = opendiscord.flags.get("opendiscord:cli")
|
||||||
|
|
||||||
await opendiscord.events.get("onCheckerRender").emit([opendiscord.checkers.renderer,opendiscord.checkers])
|
await opendiscord.events.get("onCheckerRender").emit([opendiscord.checkers.renderer,opendiscord.checkers])
|
||||||
if (opendiscord.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false)){
|
if (opendiscord.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false) && !(useCliFlag ? useCliFlag.value : false)){
|
||||||
//check if there is a result (otherwise throw minor error)
|
//check if there is a result (otherwise throw minor error)
|
||||||
const result = opendiscord.checkers.lastResult
|
const result = opendiscord.checkers.lastResult
|
||||||
if (!result) return opendiscord.log("Failed to render Config Checker! (couldn't fetch result)","error")
|
if (!result) return opendiscord.log("Failed to render Config Checker! (couldn't fetch result)","error")
|
||||||
@@ -279,7 +291,7 @@ const main = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//quit config checker (when required)
|
//quit config checker (when required)
|
||||||
if (opendiscord.checkers.lastResult && !opendiscord.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false)){
|
if (opendiscord.checkers.lastResult && !opendiscord.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false) && !(useCliFlag ? useCliFlag.value : false)){
|
||||||
await opendiscord.events.get("onCheckerQuit").emit([opendiscord.checkers])
|
await opendiscord.events.get("onCheckerQuit").emit([opendiscord.checkers])
|
||||||
if (opendiscord.defaults.getDefault("checkerQuit")){
|
if (opendiscord.defaults.getDefault("checkerQuit")){
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
@@ -287,6 +299,14 @@ const main = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//switch to CLI context instead of running the bot
|
||||||
|
if (useCliFlag && useCliFlag.value){
|
||||||
|
await (await (import("./core/cli/cli.js"))).execute()
|
||||||
|
await utilities.timer(1000)
|
||||||
|
console.log("\n\n"+ansis.red("❌ Something went wrong in the Interactive Setup CLI. Please try again or report a bug in our discord server."))
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
//plugin loading before client
|
//plugin loading before client
|
||||||
await opendiscord.events.get("onPluginBeforeClientLoad").emit([])
|
await opendiscord.events.get("onPluginBeforeClientLoad").emit([])
|
||||||
await opendiscord.events.get("afterPluginBeforeClientLoaded").emit([])
|
await opendiscord.events.get("afterPluginBeforeClientLoaded").emit([])
|
||||||
@@ -353,7 +373,7 @@ const main = async () => {
|
|||||||
const client = opendiscord.client
|
const client = opendiscord.client
|
||||||
|
|
||||||
//check if all servers are valid
|
//check if all servers are valid
|
||||||
const botServers = client.getGuilds()
|
const botServers = await client.getGuilds()
|
||||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||||
const serverId = generalConfig.data.serverId ? generalConfig.data.serverId : ""
|
const serverId = generalConfig.data.serverId ? generalConfig.data.serverId : ""
|
||||||
if (!serverId) throw new api.ODSystemError("Server Id Missing!")
|
if (!serverId) throw new api.ODSystemError("Server Id Missing!")
|
||||||
@@ -823,6 +843,11 @@ const main = async () => {
|
|||||||
opendiscord.log("Please help us improve the translation by contributing to our project!","warning")
|
opendiscord.log("Please help us improve the translation by contributing to our project!","warning")
|
||||||
console.log("===================")
|
console.log("===================")
|
||||||
}
|
}
|
||||||
|
if (opendiscord.console.silent){
|
||||||
|
opendiscord.console.silent = false
|
||||||
|
opendiscord.log("Silent mode is active! Logs won't be shown in the console.","warning")
|
||||||
|
opendiscord.console.silent = true
|
||||||
|
}
|
||||||
|
|
||||||
await opendiscord.events.get("afterStartScreensRendered").emit([opendiscord.startscreen])
|
await opendiscord.events.get("afterStartScreensRendered").emit([opendiscord.startscreen])
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@
|
|||||||
"descriptionColor":"normal"
|
"descriptionColor":"normal"
|
||||||
},
|
},
|
||||||
"active":{
|
"active":{
|
||||||
"versions":["4.0.0"],
|
"versions":["4.0.0","4.0.1","4.0.2","4.0.3","4.0.4"],
|
||||||
"languages":[],
|
"languages":[],
|
||||||
"allLanguages":true,
|
"allLanguages":true,
|
||||||
"usingPlugins":true,
|
"usingPlugins":true,
|
||||||
|
|||||||
Reference in New Issue
Block a user