Open Ticket v4 Beta

This commit is contained in:
DJj123dj
2024-08-21 13:24:56 +02:00
parent 9326d0fae8
commit 0c2aca7039
154 changed files with 33881 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
//MAIN MODULE
export * from "./main"
//BASE MODULES
export * from "./modules/base"
export * from "./modules/event"
export * from "./modules/config"
export * from "./modules/database"
export * from "./modules/language"
export * from "./modules/flag"
export * from "./modules/console"
export * from "./modules/defaults"
export * from "./modules/plugin"
export * from "./modules/checker"
export * from "./modules/client"
export * from "./modules/worker"
export * from "./modules/builder"
export * from "./modules/responder"
export * from "./modules/action"
export * from "./modules/permission"
export * from "./modules/helpmenu"
export * from "./modules/session"
export * from "./modules/stat"
export * from "./modules/code"
export * from "./modules/cooldown"
export * from "./modules/post"
export * from "./modules/verifybar"
export * from "./modules/startscreen"
//OPENTICKET DEFAULT MODULES
export * from "./defaults/base"
export * from "./defaults/event"
export * from "./defaults/config"
export * from "./defaults/database"
export * from "./defaults/checker"
export * from "./defaults/client"
export * from "./defaults/language"
export * from "./defaults/builder"
export * from "./defaults/responder"
export * from "./defaults/action"
export * from "./defaults/flag"
export * from "./defaults/permission"
export * from "./defaults/helpmenu"
export * from "./defaults/session"
export * from "./defaults/stat"
export * from "./defaults/worker"
export * from "./defaults/code"
export * from "./defaults/cooldown"
export * from "./defaults/post"
export * from "./defaults/startscreen"
export * from "./defaults/console"
//OPENTICKET MODULES
export * from "./openticket/question"
export * from "./openticket/option"
export * from "./openticket/panel"
export * from "./openticket/ticket"
export * from "./openticket/blacklist"
export * from "./openticket/transcript"
export * from "./openticket/role"
+154
View File
@@ -0,0 +1,154 @@
///////////////////////////////////////
//DEFAULT ACTION MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODAction, ODActionManager } from "../modules/action"
import { ODWorkerManager_Default } from "./worker"
import * as discord from "discord.js"
import { ODRoleOption, ODTicketOption } from "../openticket/option"
import { ODTicket, ODTicketClearFilter } from "../openticket/ticket"
import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript"
import { ODMessageBuildSentResult } from "../modules/builder"
import { ODRole, OTRoleUpdateMode, OTRoleUpdateResult } from "../openticket/role"
/**## ODActionManagerIds_Default `type`
* This type is an array of ids available in the `ODActionManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODActionManagerIds_Default {
"openticket:create-ticket-permissions":{
source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",
params:{guild:discord.Guild,user:discord.User,option:ODTicketOption},
result:{valid:boolean,reason:"blacklist"|"cooldown"|"global-limit"|"global-user-limit"|"option-limit"|"option-user-limit"|null,cooldownUntil?:Date},
workers:"openticket:check-blacklist"|"openticket:check-cooldown"|"openticket:check-global-limits"|"openticket:check-option-limits"|"openticket:valid"
},
"openticket:create-transcript":{
source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},
result:{compiler:ODTranscriptCompiler<any>, success:boolean, result:ODTranscriptCompilerCompileResult<any>, errorReason:string|null, pendingMessage:ODMessageBuildSentResult<true>|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]},
workers:"openticket:select-compiler"|"openticket:init-transcript"|"openticket:compile-transcript"|"openticket:ready-transcript"|"openticket:logs"
},
"openticket:create-ticket":{
source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",
params:{guild:discord.Guild,user:discord.User,option:ODTicketOption,answers:{id:string,name:string,type:"short"|"paragraph",value:string|null}[]},
result:{channel:discord.GuildTextBasedChannel,ticket:ODTicket},
workers:"openticket:create-ticket"|"openticket:send-ticket-message"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:close-ticket":{
source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:close-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:delete-ticket":{
source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,withoutTranscript:boolean},
result:{},
workers:"openticket:delete-ticket"|"openticket:discord-logs"|"openticket:delete-channel"|"openticket:logs"
},
"openticket:reopen-ticket":{
source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:reopen-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:claim-ticket":{
source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:claim-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:unclaim-ticket":{
source:"slash"|"text"|"ticket-message"|"claim-message"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:unclaim-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:pin-ticket":{
source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:pin-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:unpin-ticket":{
source:"slash"|"text"|"ticket-message"|"pin-message"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean},
result:{},
workers:"openticket:unpin-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:rename-ticket":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:string},
result:{},
workers:"openticket:rename-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:move-ticket":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:ODTicketOption},
result:{},
workers:"openticket:move-ticket"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:add-ticket-user":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User},
result:{},
workers:"openticket:add-ticket-user"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:remove-ticket-user":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User},
result:{},
workers:"openticket:remove-ticket-user"|"openticket:discord-logs"|"openticket:logs"
},
"openticket:reaction-role":{
source:"panel-button"|"other",
params:{guild:discord.Guild,user:discord.User,option:ODRoleOption,overwriteMode:OTRoleUpdateMode|null},
result:{result:OTRoleUpdateResult[],role:ODRole},
workers:"openticket:reaction-role"|"openticket:logs"
},
"openticket:clear-tickets":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:ODTicket[]},
result:{list:string[]},
workers:"openticket:clear-tickets"|"openticket:discord-logs"|"openticket:logs"
}
}
/**## ODActionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODActionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.actions`!
*/
export class ODActionManager_Default extends ODActionManager {
get<ActionId extends keyof ODActionManagerIds_Default>(id:ActionId): ODAction_Default<ODActionManagerIds_Default[ActionId]["source"],ODActionManagerIds_Default[ActionId]["params"],ODActionManagerIds_Default[ActionId]["result"],ODActionManagerIds_Default[ActionId]["workers"]>
get(id:ODValidId): ODAction<string,any,any>|null
get(id:ODValidId): ODAction<string,any,any>|null {
return super.get(id)
}
remove<ActionId extends keyof ODActionManagerIds_Default>(id:ActionId): ODAction_Default<ODActionManagerIds_Default[ActionId]["source"],ODActionManagerIds_Default[ActionId]["params"],ODActionManagerIds_Default[ActionId]["result"],ODActionManagerIds_Default[ActionId]["workers"]>
remove(id:ODValidId): ODAction<string,any,any>|null
remove(id:ODValidId): ODAction<string,any,any>|null {
return super.remove(id)
}
exists(id:keyof ODActionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODAction_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODAction class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODAction`'s!
*/
export class ODAction_Default<Source extends string, Params extends object, Result extends object, WorkerIds extends string> extends ODAction<Source,Params,Result> {
declare workers: ODWorkerManager_Default<Result,Source,Params,WorkerIds>
}
+45
View File
@@ -0,0 +1,45 @@
///////////////////////////////////////
//BASE MODULE
///////////////////////////////////////
import { ODVersion, ODVersionManager, ODValidId } from "../modules/base"
/**## ODVersionManagerIds_Default `type`
* This type is an array of ids available in the `ODVersionManager` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODVersionManagerIds_Default {
"openticket:version":ODVersion,
"openticket:last-version":ODVersion,
"openticket:api":ODVersion,
"openticket:transcripts":ODVersion,
"openticket:livestatus":ODVersion
}
/**## ODFlagManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFlagManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.flags`!
*/
export class ODVersionManager_Default extends ODVersionManager {
get<VersionId extends keyof ODVersionManagerIds_Default>(id:VersionId): ODVersionManagerIds_Default[VersionId]
get(id:ODValidId): ODVersion|null
get(id:ODValidId): ODVersion|null {
return super.get(id)
}
remove<VersionId extends keyof ODVersionManagerIds_Default>(id:VersionId): ODVersionManagerIds_Default[VersionId]
remove(id:ODValidId): ODVersion|null
remove(id:ODValidId): ODVersion|null {
return super.remove(id)
}
exists(id:keyof ODVersionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+532
View File
@@ -0,0 +1,532 @@
///////////////////////////////////////
//DEFAULT BUILDER MODULE
///////////////////////////////////////
import { ODValidButtonColor, ODValidId } from "../modules/base"
import { ODBuilderManager, ODButton, ODButtonInstance, ODButtonManager, ODDropdown, ODDropdownInstance, ODDropdownManager, ODEmbed, ODEmbedInstance, ODEmbedManager, ODFile, ODFileInstance, ODFileManager, ODMessage, ODMessageInstance, ODMessageManager, ODModal, ODModalInstance, ODModalManager } from "../modules/builder"
import { ODWorkerManager_Default } from "./worker"
import { ODTicket, ODTicketClearFilter } from "../openticket/ticket"
import { ODPermissionEmbedType } from "../defaults/permission"
import { ODTextCommandErrorInvalidOption, ODTextCommandErrorMissingOption, ODTextCommandErrorUnknownCommand } from "../modules/client"
import { ODPanel } from "../openticket/panel"
import { ODRoleOption, ODTicketOption, ODWebsiteOption } from "../openticket/option"
import { ODVerifyBar } from "../modules/verifybar"
import * as discord from "discord.js"
import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript"
import { ODRole, OTRoleUpdateResult } from "../openticket/role"
/**## ODBuilderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODBuilderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders`!
*/
export class ODBuilderManager_Default extends ODBuilderManager {
declare buttons: ODButtonManager_Default
declare dropdowns: ODDropdownManager_Default
declare files: ODFileManager_Default
declare embeds: ODEmbedManager_Default
declare messages: ODMessageManager_Default
declare modals: ODModalManager_Default
}
/**## ODButtonManagerIds_Default `type`
* This type is an array of ids available in the `ODButtonManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODButtonManagerIds_Default {
"openticket:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-success"},
"openticket:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-failure"},
"openticket:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"openticket:error-ticket-deprecated-transcript"},
"openticket:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-previous"},
"openticket:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-next"},
"openticket:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-page"}
"openticket:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-switch"},
"openticket:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"openticket:ticket-option"},
"openticket:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"openticket:website-option"},
"openticket:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"openticket:role-option"}
"openticket:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:visit-ticket"},
"openticket:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:close-ticket"},
"openticket:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:delete-ticket"},
"openticket:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:reopen-ticket"},
"openticket:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:claim-ticket"},
"openticket:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unclaim-ticket"},
"openticket:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:pin-ticket"},
"openticket:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unpin-ticket"},
"openticket:transcript-html-visit":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"openticket:transcript-html-visit"},
"openticket:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"openticket:transcript-error-retry"},
"openticket:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"openticket:transcript-error-continue"},
"openticket:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-continue"},
}
/**## ODButtonManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.buttons`!
*/
export class ODButtonManager_Default extends ODButtonManager {
get<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
get(id:ODValidId): ODButton<string,any>|null
get(id:ODValidId): ODButton<string,any>|null {
return super.get(id)
}
remove<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
remove(id:ODValidId): ODButton<string,any>|null
remove(id:ODValidId): ODButton<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODButtonManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
getSafe(id:ODValidId): ODButton<string,any>
getSafe(id:ODValidId): ODButton<string,any> {
return super.getSafe(id)
}
}
/**## ODButton_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButton class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODButton`'s!
*/
export class ODButton_Default<Source extends string, Params, WorkerIds extends string> extends ODButton<Source,Params> {
declare workers: ODWorkerManager_Default<ODButtonInstance,Source,Params,WorkerIds>
}
/**## ODDropdownManagerIds_Default `type`
* This type is an array of ids available in the `ODDropdownManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDropdownManagerIds_Default {
"openticket:panel-dropdown-tickets":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,options:ODTicketOption[]},workers:"openticket:panel-dropdown-tickets"}
}
/**## ODDropdownManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.dropdowns`!
*/
export class ODDropdownManager_Default extends ODDropdownManager {
get<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
get(id:ODValidId): ODDropdown<string,any>|null
get(id:ODValidId): ODDropdown<string,any>|null {
return super.get(id)
}
remove<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
remove(id:ODValidId): ODDropdown<string,any>|null
remove(id:ODValidId): ODDropdown<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODDropdownManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
getSafe(id:ODValidId): ODDropdown<string,any>
getSafe(id:ODValidId): ODDropdown<string,any> {
return super.getSafe(id)
}
}
/**## ODDropdown_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdown class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODDropdown`'s!
*/
export class ODDropdown_Default<Source extends string, Params, WorkerIds extends string> extends ODDropdown<Source,Params> {
declare workers: ODWorkerManager_Default<ODDropdownInstance,Source,Params,WorkerIds>
}
/**## ODFileManagerIds_Default `type`
* This type is an array of ids available in the `ODFileManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFileManagerIds_Default {
"openticket:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,result:ODTranscriptCompilerCompileResult<any>},workers:"openticket:text-transcript"}
}
/**## ODFileManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFileManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.files`!
*/
export class ODFileManager_Default extends ODFileManager {
get<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
get(id:ODValidId): ODFile<string,any>|null
get(id:ODValidId): ODFile<string,any>|null {
return super.get(id)
}
remove<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
remove(id:ODValidId): ODFile<string,any>|null
remove(id:ODValidId): ODFile<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODFileManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
getSafe(id:ODValidId): ODFile<string,any>
getSafe(id:ODValidId): ODFile<string,any> {
return super.getSafe(id)
}
}
/**## ODFile_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFile class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODFile`'s!
*/
export class ODFile_Default<Source extends string, Params, WorkerIds extends string> extends ODFile<Source,Params> {
declare workers: ODWorkerManager_Default<ODFileInstance,Source,Params,WorkerIds>
}
/**## ODEmbedManagerIds_Default `type`
* This type is an array of ids available in the `ODEmbedManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODEmbedManagerIds_Default {
"openticket:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"openticket:error"},
"openticket:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"openticket:error-option-missing"},
"openticket:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"openticket:error-option-invalid"},
"openticket:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"openticket:error-unknown-command"},
"openticket:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"openticket:error-no-permissions"},
"openticket:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"openticket:error-no-permissions-cooldown"},
"openticket:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-no-permissions-blacklisted"},
"openticket:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"openticket:error-no-permissions-limits"},
"openticket:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-responder-timeout"},
"openticket:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-unknown"},
"openticket:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-deprecated"},
"openticket:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-option-unknown"},
"openticket:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-panel-unknown"},
"openticket:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-not-in-guild"},
"openticket:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"openticket:error-channel-rename"},
"openticket:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-busy"},
"openticket:help-menu":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu"},
"openticket:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:stats-global"},
"openticket:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"openticket:stats-ticket"},
"openticket:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"openticket:stats-user"|"openticket:easter-egg"},
"openticket:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"openticket:stats-reset"},
"openticket:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"openticket:stats-ticket-unknown"},
"openticket:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel"},
"openticket:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created"},
"openticket:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-dm"},
"openticket:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-logs"},
"openticket:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-message"},
"openticket:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:close-message"},
"openticket:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:reopen-message"},
"openticket:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:delete-message"},
"openticket:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:claim-message"},
"openticket:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unclaim-message"},
"openticket:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:pin-message"},
"openticket:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unpin-message"},
"openticket:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"openticket:rename-message"},
"openticket:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"openticket:move-message"},
"openticket:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:add-message"},
"openticket:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:remove-message"},
"openticket:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-dm"},
"openticket:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-logs"},
"openticket:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:blacklist-view"},
"openticket:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"openticket:blacklist-get"},
"openticket:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-add"},
"openticket:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-remove"}
"openticket:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"openticket:blacklist-dm"},
"openticket:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"openticket:blacklist-logs"},
"openticket:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string}>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"openticket:transcript-text-ready"},
"openticket:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"openticket:transcript-html-ready"},
"openticket:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,remaining:number},workers:"openticket:transcript-html-progress"},
"openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"openticket:transcript-error"},
"openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"},
"openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"},
"openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"},
"openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"},
"openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"},
"openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"},
"openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"},
"openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"},
"openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"},
"openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"},
}
/**## ODEmbedManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEmbedManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.embeds`!
*/
export class ODEmbedManager_Default extends ODEmbedManager {
get<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
get(id:ODValidId): ODEmbed<string,any>|null
get(id:ODValidId): ODEmbed<string,any>|null {
return super.get(id)
}
remove<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
remove(id:ODValidId): ODEmbed<string,any>|null
remove(id:ODValidId): ODEmbed<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODEmbedManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
getSafe(id:ODValidId): ODEmbed<string,any>
getSafe(id:ODValidId): ODEmbed<string,any> {
return super.getSafe(id)
}
}
/**## ODEmbed_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEmbed class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODEmbed`'s!
*/
export class ODEmbed_Default<Source extends string, Params, WorkerIds extends string> extends ODEmbed<Source,Params> {
declare workers: ODWorkerManager_Default<ODEmbedInstance,Source,Params,WorkerIds>
}
/**## ODMessageManagerIds_Default `type`
* This type is an array of ids available in the `ODMessageManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODMessageManagerIds_Default {
"openticket:verifybar-ticket-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-ticket-message"},
"openticket:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-close-message"},
"openticket:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-reopen-message"},
"openticket:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-claim-message"},
"openticket:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-unclaim-message"},
"openticket:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-pin-message"},
"openticket:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-unpin-message"}
"openticket:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"openticket:verifybar-autoclose-message"}
"openticket:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"openticket:error"},
"openticket:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"openticket:error-option-missing"},
"openticket:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"openticket:error-option-invalid"},
"openticket:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"openticket:error-unknown-command"},
"openticket:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"openticket:error-no-permissions"},
"openticket:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"openticket:error-no-permissions-cooldown"},
"openticket:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-no-permissions-blacklisted"},
"openticket:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"openticket:error-no-permissions-limits"},
"openticket:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-responder-timeout"},
"openticket:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-unknown"},
"openticket:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-deprecated"},
"openticket:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-option-unknown"},
"openticket:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-panel-unknown"},
"openticket:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-not-in-guild"},
"openticket:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"openticket:error-channel-rename"},
"openticket:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-busy"},
"openticket:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu"},
"openticket:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:stats-global"},
"openticket:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"openticket:stats-ticket"},
"openticket:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"openticket:stats-user"|"openticket:easter-egg"},
"openticket:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"openticket:stats-reset"},
"openticket:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"openticket:stats-ticket-unknown"},
"openticket:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-layout"|"openticket:panel-components"},
"openticket:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-ready"},
"openticket:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created"},
"openticket:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-dm"},
"openticket:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-logs"},
"openticket:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-message-layout"|"openticket:ticket-message-components"|"openticket:ticket-message-disable-components"},
"openticket:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:close-message"},
"openticket:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:reopen-message"},
"openticket:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:delete-message"},
"openticket:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:claim-message"},
"openticket:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unclaim-message"},
"openticket:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:pin-message"},
"openticket:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unpin-message"},
"openticket:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"openticket:rename-message"},
"openticket:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"openticket:move-message"},
"openticket:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:add-message"},
"openticket:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:remove-message"},
"openticket:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-dm"},
"openticket:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-logs"},
"openticket:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:blacklist-view"},
"openticket:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"openticket:blacklist-get"},
"openticket:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-add"},
"openticket:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-remove"},
"openticket:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"openticket:blacklist-dm"},
"openticket:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"openticket:blacklist-logs"},
"openticket:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string}>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"openticket:transcript-text-ready"},
"openticket:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"openticket:transcript-html-ready"},
"openticket:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,remaining:number},workers:"openticket:transcript-html-progress"},
"openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"openticket:transcript-error"},
"openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"},
"openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"},
"openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"},
"openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"},
"openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"},
"openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"},
"openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"},
"openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"},
"openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"},
"openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"},
}
/**## ODMessageManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODMessageManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.messages`!
*/
export class ODMessageManager_Default extends ODMessageManager {
get<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
get(id:ODValidId): ODMessage<string,any>|null
get(id:ODValidId): ODMessage<string,any>|null {
return super.get(id)
}
remove<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
remove(id:ODValidId): ODMessage<string,any>|null
remove(id:ODValidId): ODMessage<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODMessageManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
getSafe(id:ODValidId): ODMessage<string,any>
getSafe(id:ODValidId): ODMessage<string,any> {
return super.getSafe(id)
}
}
/**## ODMessage_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODMessage class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODMessage`'s!
*/
export class ODMessage_Default<Source extends string, Params, WorkerIds extends string> extends ODMessage<Source,Params> {
declare workers: ODWorkerManager_Default<ODMessageInstance,Source,Params,WorkerIds>
}
/**## ODModalManagerIds_Default `type`
* This type is an array of ids available in the `ODModalManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODModalManagerIds_Default {
"openticket:ticket-questions":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,option:ODTicketOption},workers:"openticket:ticket-questions"}
"openticket:close-ticket-reason":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:close-ticket-reason"}
"openticket:reopen-ticket-reason":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:reopen-ticket-reason"}
"openticket:delete-ticket-reason":{source:"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:delete-ticket-reason"}
"openticket:claim-ticket-reason":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:claim-ticket-reason"}
"openticket:unclaim-ticket-reason":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unclaim-ticket-reason"}
"openticket:pin-ticket-reason":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:pin-ticket-reason"}
"openticket:unpin-ticket-reason":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unpin-ticket-reason"}
}
/**## ODModalManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.builders.modals`!
*/
export class ODModalManager_Default extends ODModalManager {
get<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
get(id:ODValidId): ODModal<string,any>|null
get(id:ODValidId): ODModal<string,any>|null {
return super.get(id)
}
remove<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
remove(id:ODValidId): ODModal<string,any>|null
remove(id:ODValidId): ODModal<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODModalManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
getSafe(id:ODValidId): ODModal<string,any>
getSafe(id:ODValidId): ODModal<string,any> {
return super.getSafe(id)
}
}
/**## ODModal_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModal class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODModal`'s!
*/
export class ODModal_Default<Source extends string, Params, WorkerIds extends string> extends ODModal<Source,Params> {
declare workers: ODWorkerManager_Default<ODModalInstance,Source,Params,WorkerIds>
}
+378
View File
@@ -0,0 +1,378 @@
///////////////////////////////////////
//DEFAULT CONFIG CHECKER MODULE
///////////////////////////////////////
import { ODLanguageManager_Default } from "../api"
import { ODValidId } from "../modules/base"
import { ODCheckerManager, ODChecker, ODCheckerTranslationRegister, ODCheckerRenderer, ODCheckerFunctionManager, ODCheckerResult, ODCheckerFunction } from "../modules/checker"
import ansis from "ansis"
/**## ODCheckerManagerIds_Default `type`
* This type is an array of ids available in the `ODCheckerManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCheckerManagerIds_Default {
"openticket:general":ODChecker,
"openticket:options":ODChecker,
"openticket:messages":ODChecker,
"openticket:transcripts":ODChecker
}
/**## ODCheckerManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.checkers`!
*/
export class ODCheckerManager_Default extends ODCheckerManager {
declare translation: ODCheckerTranslationRegister_Default
declare renderer: ODCheckerRenderer_Default
declare functions: ODCheckerFunctionManager_Default
get<CheckerId extends keyof ODCheckerManagerIds_Default>(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
get(id:ODValidId): ODChecker|null
get(id:ODValidId): ODChecker|null {
return super.get(id)
}
remove<CheckerId extends keyof ODCheckerManagerIds_Default>(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
remove(id:ODValidId): ODChecker|null
remove(id:ODValidId): ODChecker|null {
return super.remove(id)
}
exists(id:keyof ODCheckerManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODCheckerRenderer_Default `default_class`
* This is a special class that adds type definitions & features to the ODCheckerRenderer class.
* It contains the code that renders the default config checker.
*
* This default class is made for the global variable `openticket.checkers.renderer`!
*/
export class ODCheckerRenderer_Default extends ODCheckerRenderer {
extraHeaderText: string[] = []
extraFooterText: string[] = []
extraTopText: string[] = []
extraBottomText: string[] = []
horizontalFiller: string = "="
verticalFiller: string = "|"
descriptionSeparator: string = " => "
footerTipPrefix: string = "=> "
disableHeader: boolean = false
disableFooter: boolean = false
getComponents(compact:boolean, renderEmpty:boolean, translation:ODCheckerTranslationRegister_Default, data:ODCheckerResult): string[] {
const tm = translation
const t = {
headerOpenticket:tm.get("other","openticket:header-openticket") ?? "OPEN TICKET",
headerConfigchecker:tm.get("other","openticket:header-configchecker") ?? "CONFIG CHECKER",
headerDescription:tm.get("other","openticket:header-description") ?? "check for errors in you config files!",
footerError:tm.get("other","openticket:footer-error") ?? "the bot won't start until all {0}'s are fixed!",
footerWarning:tm.get("other","openticket:footer-warning") ?? "it's recommended to fix all {0}'s before starting!",
footerSupport:tm.get("other","openticket:footer-support") ?? "SUPPORT: {0} - DOCS: {1}",
error:tm.get("other","openticket:type-error") ?? "[ERROR]",
warning:tm.get("other","openticket:type-warning") ?? "[WARNING]",
info:tm.get("other","openticket:type-info") ?? "[INFO]",
compactInfo:tm.get("other","openticket:compact-information") ?? "use {0} for more information!",
dataPath:tm.get("other","openticket:data-path") ?? "path",
dataDocs:tm.get("other","openticket:data-docs") ?? "docs",
dataMessage:tm.get("other","openticket:data-message") ?? "message"
}
const hasErrors = data.messages.filter((m) => m.type == "error").length > 0
const hasWarnings = data.messages.filter((m) => m.type == "warning").length > 0
const hasInfo = data.messages.filter((m) => m.type == "info").length > 0
if (!renderEmpty && !hasErrors && !hasWarnings && (!hasInfo || compact)) return []
const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+" => "+ansis.hex("#f8ba00")(t.headerDescription)
const footerErrorText = (hasErrors) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerError,[ansis.bold.red(t.error)])) : ""
const footerWarningText = (hasWarnings) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerWarning,[ansis.bold.yellow(t.warning)])) : ""
const footerSupportText = tm.insertTranslationParams(t.footerSupport,[ansis.green("https://discord.dj-dj.be"),ansis.green("https://otdocs.dj-dj.be")])
const bottomCompactInfo = (compact) ? ansis.gray(tm.insertTranslationParams(t.compactInfo,[ansis.bold.green("npm start -- --checker")])) : ""
const finalHeader = [headerText,...this.extraHeaderText]
const finalFooter = [footerErrorText,footerWarningText,footerSupportText,...this.extraFooterText]
const finalTop = [...this.extraTopText]
const finalBottom = [bottomCompactInfo,...this.extraBottomText]
const borderLength = this.#getLongestLength([...finalHeader,...finalFooter])
const finalComponents: string[] = []
//header
if (!this.disableHeader){
finalHeader.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.#createBlockFromText(text,borderLength))
})
}
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
//top
finalTop.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.verticalFiller+" "+text)
})
finalComponents.push(this.verticalFiller)
//messages
if (compact){
//use compact messages
data.messages.forEach((msg,index) => {
//compact mode doesn't render info
if (msg.type == "info") return
//check if translation available & use it if possible
const rawTranslation = tm.get("message",msg.messageId.value)
const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
const pathSplitter = msg.path ? ":" : ""
finalComponents.push(this.verticalFiller+ansis.bold(this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
})
}else{
//use full messages
data.messages.forEach((msg,index) => {
//check if translation available & use it if possible
const rawTranslation = tm.get("message",msg.messageId.value)
const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
else if (msg.type == "info") finalComponents.push(this.verticalFiller+" "+ansis.bold.blue(`${t.info} ${translatedMessage}`))
const pathSplitter = msg.path ? ":" : ""
finalComponents.push(this.verticalFiller+" "+ansis.bold((t.dataPath)+this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
if (msg.locationDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataDocs+this.descriptionSeparator)+ansis.italic.gray(msg.locationDocs))
if (msg.messageDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataMessage+this.descriptionSeparator)+ansis.italic.gray(msg.messageDocs))
if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
})
}
//bottom
finalComponents.push(this.verticalFiller)
finalBottom.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.verticalFiller+" "+text)
})
//footer
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
if (!this.disableFooter){
finalFooter.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.#createBlockFromText(text,borderLength))
})
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
}
//return all components
return finalComponents
}
/**Get the length of the longest string in the array. */
#getLongestLength(text:string[]): number {
let finalLength = 0
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. */
#getHorizontalDivider(width:number): string {
if (width > 2) width = width-2
else return this.verticalFiller+this.verticalFiller
let divider = this.verticalFiller + this.horizontalFiller.repeat(width) + this.verticalFiller
return divider
}
/**Create a block of text with a vertical divider on the left & right side. */
#createBlockFromText(text:string,width:number): string {
if (width < 3) return this.verticalFiller+this.verticalFiller
let newWidth = width-ansis.strip(text).length+1
let final = this.verticalFiller+" "+text+" ".repeat(newWidth)+this.verticalFiller
return final
}
}
/**## ODCheckerTranslationRegisterOtherIds_Default `type`
* This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class.
* It's used to generate typescript declarations for this class.
*/
export type ODCheckerTranslationRegisterOtherIds_Default = (
"openticket:header-openticket"|
"openticket:header-configchecker"|
"openticket:header-description"|
"openticket:type-error"|
"openticket:type-warning"|
"openticket:type-info"|
"openticket:data-path"|
"openticket:data-docs"|
"openticket:data-message"|
"openticket:compact-information"|
"openticket:footer-error"|
"openticket:footer-warning"|
"openticket:footer-support"
)
/**## ODCheckerTranslationRegisterMessageIds_Default `type`
* This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class.
* It's used to generate typescript declarations for this class.
*/
export type ODCheckerTranslationRegisterMessageIds_Default = (
"openticket:invalid-type"|
"openticket:property-missing"|
"openticket:property-optional"|
"openticket:object-disabled"|
"openticket:null-invalid"|
"openticket:switch-invalid-type"|
"openticket:object-switch-invalid-type"|
"openticket:string-too-short"|
"openticket:string-too-long"|
"openticket:string-length-invalid"|
"openticket:string-starts-with"|
"openticket:string-ends-with"|
"openticket:string-contains"|
"openticket:string-choices"|
"openticket:string-regex"|
"openticket:number-too-short"|
"openticket:number-too-long"|
"openticket:number-length-invalid"|
"openticket:number-too-small"|
"openticket:number-too-large"|
"openticket:number-not-equal"|
"openticket:number-step"|
"openticket:number-step-offset"|
"openticket:number-starts-with"|
"openticket:number-ends-with"|
"openticket:number-contains"|
"openticket:number-choices"|
"openticket:number-float"|
"openticket:number-negative"|
"openticket:number-positive"|
"openticket:number-zero"|
"openticket:boolean-true"|
"openticket:boolean-false"|
"openticket:array-empty-disabled"|
"openticket:array-empty-required"|
"openticket:array-too-short"|
"openticket:array-too-long"|
"openticket:array-length-invalid"|
"openticket:array-invalid-types"|
"openticket:array-double"|
"openticket:discord-invalid-id"|
"openticket:discord-invalid-id-options"|
"openticket:discord-invalid-token"|
"openticket:color-invalid"|
"openticket:emoji-too-short"|
"openticket:emoji-too-long"|
"openticket:emoji-custom"|
"openticket:emoji-invalid"|
"openticket:url-invalid"|
"openticket:url-invalid-http"|
"openticket:url-invalid-protocol"|
"openticket:url-invalid-hostname"|
"openticket:url-invalid-extension"|
"openticket:url-invalid-path"|
"openticket:id-not-unique"|
"openticket:id-non-existent"|
"openticket:invalid-language"|
"openticket:invalid-button"|
"openticket:unused-option"|
"openticket:unused-question"|
"openticket:dropdown-option"
)
/**## ODCheckerTranslationRegister_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerTranslationRegister class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.checkers.translation`!
*/
export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRegister {
get(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): string
get(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): string
get(type:"message"|"other", id:string): string|null
get(type:"message"|"other", id:string): string|null {
return super.get(type,id)
}
set(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default, translation:string): boolean
set(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default, translation:string): boolean
set(type:"message"|"other", id:string, translation:string): boolean
set(type:"message"|"other", id:string, translation:string): boolean {
return super.set(type,id,translation)
}
delete(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): boolean
delete(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): boolean
delete(type:"message"|"other", id:string): boolean
delete(type:"message"|"other", id:string): boolean {
return super.delete(type,id)
}
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default)
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:string)
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default|string){
super.quickTranslate(manager,translationId,type,id)
}
}
/**## ODCheckerFunctionManagerIds_Default `type`
* This type is an array of ids available in the `ODCheckerFunctionManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCheckerFunctionManagerIds_Default {
"openticket:unused-options":ODCheckerFunction,
"openticket:dropdown-options":ODCheckerFunction
}
/**## ODCheckerFunctionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerFunctionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.checkers.functions`!
*/
export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager {
get<CheckerFunctionId extends keyof ODCheckerManagerIds_Default>(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId]
get(id:ODValidId): ODCheckerFunction|null
get(id:ODValidId): ODCheckerFunction|null {
return super.get(id)
}
remove<CheckerFunctionId extends keyof ODCheckerManagerIds_Default>(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId]
remove(id:ODValidId): ODCheckerFunction|null
remove(id:ODValidId): ODCheckerFunction|null {
return super.remove(id)
}
exists(id:keyof ODCheckerFunctionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+147
View File
@@ -0,0 +1,147 @@
///////////////////////////////////////
//DEFAULT CLIENT MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODClientManager, ODSlashCommand, ODTextCommand, ODSlashCommandManager, ODTextCommandManager, ODSlashCommandInteractionCallback, ODTextCommandInteractionCallback } from "../modules/client"
/**## ODClientManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODClientManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.client`!
*/
export class ODClientManager_Default extends ODClientManager {
declare slashCommands: ODSlashCommandManager_Default
declare textCommands: ODTextCommandManager_Default
}
/**## ODSlashCommandManagerIds_Default `type`
* This type is an array of ids available in the `ODSlashCommandManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODSlashCommandManagerIds_Default {
"openticket:help":ODSlashCommand,
"openticket:panel":ODSlashCommand,
"openticket:ticket":ODSlashCommand,
"openticket:close":ODSlashCommand,
"openticket:delete":ODSlashCommand,
"openticket:reopen":ODSlashCommand,
"openticket:claim":ODSlashCommand,
"openticket:unclaim":ODSlashCommand,
"openticket:pin":ODSlashCommand,
"openticket:unpin":ODSlashCommand,
"openticket:move":ODSlashCommand,
"openticket:rename":ODSlashCommand,
"openticket:add":ODSlashCommand,
"openticket:remove":ODSlashCommand,
"openticket:blacklist":ODSlashCommand,
"openticket:stats":ODSlashCommand,
"openticket:clear":ODSlashCommand,
"openticket:autoclose":ODSlashCommand,
"openticket:autodelete":ODSlashCommand,
}
/**## ODSlashCommandManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODSlashCommandManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.client.slashCommands`!
*/
export class ODSlashCommandManager_Default extends ODSlashCommandManager {
get<SlashCommandId extends keyof ODSlashCommandManagerIds_Default>(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
get(id:ODValidId): ODSlashCommand|null
get(id:ODValidId): ODSlashCommand|null {
return super.get(id)
}
remove<SlashCommandId extends keyof ODSlashCommandManagerIds_Default>(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
remove(id:ODValidId): ODSlashCommand|null
remove(id:ODValidId): ODSlashCommand|null {
return super.remove(id)
}
exists(id:keyof ODSlashCommandManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
onInteraction(commandName:keyof ODSlashCommandManagerIds_Default, callback:ODSlashCommandInteractionCallback): void
onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void
onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void {
return super.onInteraction(commandName,callback)
}
}
/**## ODTextCommandManagerIds_Default `type`
* This type is an array of ids available in the `ODTextCommandManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODTextCommandManagerIds_Default {
"openticket:help":ODTextCommand,
"openticket:panel":ODTextCommand,
"openticket:close":ODTextCommand,
"openticket:delete":ODTextCommand,
"openticket:reopen":ODTextCommand,
"openticket:claim":ODTextCommand,
"openticket:unclaim":ODTextCommand,
"openticket:pin":ODTextCommand,
"openticket:unpin":ODTextCommand,
"openticket:move":ODTextCommand,
"openticket:rename":ODTextCommand,
"openticket:add":ODTextCommand,
"openticket:remove":ODTextCommand,
"openticket:blacklist-view":ODTextCommand,
"openticket:blacklist-add":ODTextCommand,
"openticket:blacklist-remove":ODTextCommand,
"openticket:blacklist-get":ODTextCommand,
"openticket:stats-global":ODTextCommand,
"openticket:stats-reset":ODTextCommand,
"openticket:stats-ticket":ODTextCommand,
"openticket:stats-user":ODTextCommand,
"openticket:clear":ODTextCommand,
"openticket:autoclose-disable":ODTextCommand,
"openticket:autoclose-enable":ODTextCommand,
"openticket:autodelete-disable":ODTextCommand,
"openticket:autodelete-enable":ODTextCommand
}
/**## ODTextCommandManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODTextCommandManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.client.textCommands`!
*/
export class ODTextCommandManager_Default extends ODTextCommandManager {
get<TextCommandId extends keyof ODTextCommandManagerIds_Default>(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
get(id:ODValidId): ODTextCommand|null
get(id:ODValidId): ODTextCommand|null {
return super.get(id)
}
remove<TextCommandId extends keyof ODTextCommandManagerIds_Default>(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
remove(id:ODValidId): ODTextCommand|null
remove(id:ODValidId): ODTextCommand|null {
return super.remove(id)
}
exists(id:keyof ODTextCommandManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
onInteraction(prefix:string, id:keyof ODTextCommandManagerIds_Default, callback:ODTextCommandInteractionCallback): void
onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void
onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void {
return super.onInteraction(commandPrefix,commandName,callback)
}
}
+56
View File
@@ -0,0 +1,56 @@
///////////////////////////////////////
//DEFAULT CODE MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODCode, ODCodeManager } from "../modules/code"
/**## ODCodeManagerIds_Default `type`
* This type is an array of ids available in the `ODCodeManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCodeManagerIds_Default {
"openticket:command-error-handling":ODCode,
"openticket:start-listening-interactions":ODCode,
"openticket:panel-database-cleaner":ODCode,
"openticket:suffix-database-cleaner":ODCode,
"openticket:option-database-cleaner":ODCode,
"openticket:user-database-cleaner":ODCode,
"openticket:ticket-database-cleaner":ODCode,
"openticket:panel-auto-update":ODCode,
"openticket:ticket-saver":ODCode,
"openticket:blacklist-saver":ODCode,
"openticket:auto-role-on-join":ODCode,
"openticket:autoclose-timeout":ODCode,
"openticket:autoclose-leave":ODCode,
"openticket:autodelete-timeout":ODCode,
"openticket:autodelete-leave":ODCode
}
/**## ODCodeManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCodeManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.code`!
*/
export class ODCodeManager_Default extends ODCodeManager {
get<CodeId extends keyof ODCodeManagerIds_Default>(id:CodeId): ODCodeManagerIds_Default[CodeId]
get(id:ODValidId): ODCode|null
get(id:ODValidId): ODCode|null {
return super.get(id)
}
remove<CodeId extends keyof ODCodeManagerIds_Default>(id:CodeId): ODCodeManagerIds_Default[CodeId]
remove(id:ODValidId): ODCode|null
remove(id:ODValidId): ODCode|null {
return super.remove(id)
}
exists(id:keyof ODCodeManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+470
View File
@@ -0,0 +1,470 @@
///////////////////////////////////////
//DEFAULT CONFIG MODULE
///////////////////////////////////////
import { ODValidButtonColor, ODValidId } from "../modules/base"
import * as discord from "discord.js"
import { ODConfigManager, ODConfig, ODJsonConfig } from "../modules/config"
import { ODClientActivityStatus, ODClientActivityType } from "../modules/client"
import { OTRoleUpdateMode } from "../openticket/role"
/**## ODConfigManagerIds_Default `type`
* This type is an array of ids available in the `ODConfigManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODConfigManagerIds_Default {
"openticket:general":ODJsonConfig_DefaultGeneral,
"openticket:options":ODJsonConfig_DefaultOptions,
"openticket:panels":ODJsonConfig_DefaultPanels,
"openticket:questions":ODJsonConfig_DefaultQuestions,
"openticket:transcripts":ODJsonConfig_DefaultTranscripts
}
/**## ODConfigManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODConfigManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.configs`!
*/
export class ODConfigManager_Default extends ODConfigManager {
get<ConfigId extends keyof ODConfigManagerIds_Default>(id:ConfigId): ODConfigManagerIds_Default[ConfigId]
get(id:ODValidId): ODConfig|null
get(id:ODValidId): ODConfig|null {
return super.get(id)
}
remove<ConfigId extends keyof ODConfigManagerIds_Default>(id:ConfigId): ODConfigManagerIds_Default[ConfigId]
remove(id:ODValidId): ODConfig|null
remove(id:ODValidId): ODConfig|null {
return super.remove(id)
}
exists(id:keyof ODConfigManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODJsonConfig_DefaultStatusType `interface`
* This interface is an object which has all properties for the status object in the `general.json` config!
*/
export interface ODJsonConfig_DefaultStatusType {
enabled:boolean,
type:Exclude<ODClientActivityType,false>,
text:string,
status:ODClientActivityStatus
}
/**## ODJsonConfig_DefaultMessageSettingsType `interface`
* This interface is an object which has all properties for the system/messages/... object in the `general.json` config!
*/
export interface ODJsonConfig_DefaultMessageSettingsType {
dm:boolean,
logs:boolean
}
/**## ODJsonConfig_DefaultCmdPermissionSettingsType `type`
* This type is a collection of command permission settings for the system/permissions/... object in the `general.json` config!
*/
export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|"none"|string
/**## ODJsonConfig_DefaultGeneral `default_class`
* This is a special class that adds type definitions & typescript to the ODJsonConfig class.
* It doesn't add any extra features!
*
* This default class is made for the `general.json` config!
*/
export class ODJsonConfig_DefaultGeneral extends ODJsonConfig {
declare data: {
_INFO:{
support:string,
discord:string,
version:string
},
token:string,
tokenFromENV:boolean,
mainColor:discord.ColorResolvable,
language:string,
prefix:string,
serverId:string,
globalAdmins:string[],
slashCommands:boolean,
textCommands:boolean,
status:ODJsonConfig_DefaultStatusType,
system:{
removeParticipantsOnClose:boolean,
replyOnTicketCreation:boolean,
replyOnReactionRole:boolean,
useTranslatedConfigChecker:boolean,
preferSlashOverText:boolean,
sendErrorOnUnknownCommand:boolean,
questionFieldsInCodeBlock:boolean,
disableVerifyBars:boolean,
useRedErrorEmbeds:boolean,
emojiStyle:"before"|"after"|"double"|"disabled",
enableTicketClaimButtons:boolean,
enableTicketCloseButtons:boolean,
enableTicketPinButtons:boolean,
enableTicketDeleteButtons:boolean,
enableTicketActionWithReason:boolean,
enableDeleteWithoutTranscript:boolean,
logs:{
enabled:boolean,
channel:string
},
limits:{
enabled:boolean,
globalMaximum:number,
userMaximum:number
},
permissions:{
help:ODJsonConfig_DefaultCmdPermissionSettingsType,
panel:ODJsonConfig_DefaultCmdPermissionSettingsType,
ticket:ODJsonConfig_DefaultCmdPermissionSettingsType,
close:ODJsonConfig_DefaultCmdPermissionSettingsType,
delete:ODJsonConfig_DefaultCmdPermissionSettingsType,
reopen:ODJsonConfig_DefaultCmdPermissionSettingsType,
claim:ODJsonConfig_DefaultCmdPermissionSettingsType,
unclaim:ODJsonConfig_DefaultCmdPermissionSettingsType,
pin:ODJsonConfig_DefaultCmdPermissionSettingsType,
unpin:ODJsonConfig_DefaultCmdPermissionSettingsType,
move:ODJsonConfig_DefaultCmdPermissionSettingsType,
rename:ODJsonConfig_DefaultCmdPermissionSettingsType,
add:ODJsonConfig_DefaultCmdPermissionSettingsType,
remove:ODJsonConfig_DefaultCmdPermissionSettingsType,
blacklist:ODJsonConfig_DefaultCmdPermissionSettingsType,
stats:ODJsonConfig_DefaultCmdPermissionSettingsType,
clear:ODJsonConfig_DefaultCmdPermissionSettingsType,
autoclose:ODJsonConfig_DefaultCmdPermissionSettingsType,
autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType
},
messages:{
creation:ODJsonConfig_DefaultMessageSettingsType,
closing:ODJsonConfig_DefaultMessageSettingsType,
deleting:ODJsonConfig_DefaultMessageSettingsType,
reopening:ODJsonConfig_DefaultMessageSettingsType,
claiming:ODJsonConfig_DefaultMessageSettingsType,
pinning:ODJsonConfig_DefaultMessageSettingsType,
adding:ODJsonConfig_DefaultMessageSettingsType,
removing:ODJsonConfig_DefaultMessageSettingsType,
renaming:ODJsonConfig_DefaultMessageSettingsType,
moving:ODJsonConfig_DefaultMessageSettingsType,
blacklisting:ODJsonConfig_DefaultMessageSettingsType,
roleAdding:ODJsonConfig_DefaultMessageSettingsType,
roleRemoving:ODJsonConfig_DefaultMessageSettingsType
}
}
}
}
/**## ODJsonConfig_DefaultOptionType `interface`
* This interface is an object which has all basic properties for options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionType {
id:string,
name:string,
description:string,
type:"ticket"|"website"|"role",
button:{
emoji:string,
label:string
}
}
/**## ODJsonConfig_DefaultOptionButtonSettingsType `interface`
* This interface is an object which has all button settings for ticket options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionButtonSettingsType {
emoji:string,
label:string,
color:ODValidButtonColor
}
/**## ODJsonConfig_DefaultOptionEmbedSettingsType `interface`
* This interface is an object which has all message embed settings for ticket options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionEmbedSettingsType {
enabled:boolean,
title:string,
description:string,
customColor:string,
image:string,
thumbnail:string,
fields:{name:string, value:string, inline:boolean}[],
timestamp:boolean
}
/**## ODJsonConfig_DefaultOptionPingSettingsType `interface`
* This interface is an object which has all message ping settings for ticket options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionPingSettingsType {
"@here":boolean,
"@everyone":boolean,
custom:string[]
}
/**## ODJsonConfig_DefaultOptionTicketType `interface`
* This interface is an object which has all ticket properties for options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_DefaultOptionType {
type:"ticket",
button:ODJsonConfig_DefaultOptionButtonSettingsType,
ticketAdmins:string[],
readonlyAdmins:string[],
allowCreationByBlacklistedUsers:boolean,
questions:string[],
channel:{
prefix:string,
suffix:"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed",
category:string,
closedCategory:string,
backupCategory:string,
claimedCategory:{user:string, category:string}[],
description:string
},
dmMessage:{
enabled:boolean,
text:string,
embed:ODJsonConfig_DefaultOptionEmbedSettingsType
},
ticketMessage:{
enabled:boolean,
text:string,
embed:ODJsonConfig_DefaultOptionEmbedSettingsType,
ping:ODJsonConfig_DefaultOptionPingSettingsType
},
autoclose:{
enableInactiveHours:boolean,
inactiveHours:number,
enableUserLeave:boolean,
disableOnClaim:boolean
},
autodelete:{
enableInactiveDays:boolean,
inactiveDays:number,
enableUserLeave:boolean,
disableOnClaim:boolean
},
cooldown:{
enabled:boolean,
cooldownMinutes:number
},
limits:{
enabled:boolean,
globalMaximum:number,
userMaximum:number
}
}
/**## ODJsonConfig_DefaultOptionWebsiteType `interface`
* This interface is an object which has all website properties for options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionWebsiteType extends ODJsonConfig_DefaultOptionType {
type:"website",
url:string
}
/**## ODJsonConfig_DefaultOptionRoleType `interface`
* This interface is an object which has all reaction role properties for options in the `options.json` config!
*/
export interface ODJsonConfig_DefaultOptionRoleType extends ODJsonConfig_DefaultOptionType {
type:"role",
button:ODJsonConfig_DefaultOptionButtonSettingsType,
roles:string[],
mode:OTRoleUpdateMode,
removeRolesOnAdd:string[],
addOnMemberJoin:boolean
}
/**## ODJsonConfig_DefaultOptions `default_class`
* This is a special class that adds type definitions & typescript to the ODJsonConfig class.
* It doesn't add any extra features!
*
* This default class is made for the `options.json` config!
*/
export class ODJsonConfig_DefaultOptions extends ODJsonConfig {
declare data: (
ODJsonConfig_DefaultOptionTicketType|
ODJsonConfig_DefaultOptionWebsiteType|
ODJsonConfig_DefaultOptionRoleType
)[]
}
/**## ODJsonConfig_DefaultPanelEmbedSettingsType `interface`
* This interface is an object which has all message embed settings for panels in the `panels.json` config!
*/
export interface ODJsonConfig_DefaultPanelEmbedSettingsType {
enabled:boolean,
title:string,
description:string,
customColor:string,
url:string,
image:string,
thumbnail:string,
footer:string,
fields:{name:string,value:string,inline:boolean}[],
timestamp:boolean
}
/**## ODJsonConfig_DefaultPanelType `interface`
* This interface is an object which has all properties for panels in the `panels.json` config!
*/
export interface ODJsonConfig_DefaultPanelType {
id:string,
name:string,
dropdown:boolean,
options:string[],
text:string,
embed:ODJsonConfig_DefaultPanelEmbedSettingsType,
settings:{
dropdownPlaceholder:string,
enableMaxTicketsWarningInText:boolean,
enableMaxTicketsWarningInEmbed:boolean,
describeOptionsLayout:"simple"|"normal"|"detailed",
describeOptionsCustomTitle:string,
describeOptionsInText:boolean,
describeOptionsInEmbedFields:boolean,
describeOptionsInEmbedDescription:boolean
}
}
/**## ODJsonConfig_DefaultPanels `default_class`
* This is a special class that adds type definitions & typescript to the ODJsonConfig class.
* It doesn't add any extra features!
*
* This default class is made for the `panels.json` config!
*/
export class ODJsonConfig_DefaultPanels extends ODJsonConfig {
declare data: ODJsonConfig_DefaultPanelType[]
}
/**## ODJsonConfig_DefaultShortQuestionType `interface`
* This interface is an object which has all properties for short questions in the `questions.json` config!
*/
export interface ODJsonConfig_DefaultShortQuestionType {
id:string,
name:string,
type:"short",
required:boolean,
placeholder:string,
length:{
enabled:boolean,
min:number,
max:number
}
}
/**## ODJsonConfig_DefaultParagraphQuestionType `interface`
* This interface is an object which has all properties for paragraph questions in the `questions.json` config!
*/
export interface ODJsonConfig_DefaultParagraphQuestionType {
id:string,
name:string,
type:"paragraph",
required:boolean,
placeholder:string,
length:{
enabled:boolean,
min:number,
max:number
}
}
/**## ODJsonConfig_DefaultQuestions `default_class`
* This is a special class that adds type definitions & typescript to the ODJsonConfig class.
* It doesn't add any extra features!
*
* This default class is made for the `questions.json` config!
*/
export class ODJsonConfig_DefaultQuestions extends ODJsonConfig {
declare data: (
ODJsonConfig_DefaultShortQuestionType|
ODJsonConfig_DefaultParagraphQuestionType
)[]
}
/**## ODJsonConfig_DefaultTranscripts `default_class`
* This is a special class that adds type definitions & typescript to the ODJsonConfig class.
* It doesn't add any extra features!
*
* This default class is made for the `transcripts.json` config!
*/
export class ODJsonConfig_DefaultTranscripts extends ODJsonConfig {
declare data: {
general:{
enabled:boolean,
enableChannel:boolean,
enableCreatorDM:boolean,
enableParticipantDM:boolean,
enableActiveAdminDM:boolean,
enableEveryAdminDM:boolean,
channel:string,
mode:"html"|"text"
},
embedSettings:{
customColor:string,
listAllParticipants:boolean,
includeTicketStats:boolean
},
textTranscriptStyle:{
layout:"simple"|"normal"|"detailed",
includeStats:boolean,
includeIds:boolean,
includeEmbeds:boolean,
includeFiles:boolean,
includeBotMessages:boolean,
fileMode:"custom"|"channel-name"|"channel-id"|"user-name"|"user-id",
customFileName:string
},
htmlTranscriptStyle:{
background:{
enableCustomBackground:boolean,
backgroundColor:string,
backgroundImage:string
},
header:{
enableCustomHeader:boolean,
backgroundColor:string,
decoColor:string,
textColor:string
},
stats:{
enableCustomStats:false,
backgroundColor:string,
keyTextColor:string,
valueTextColor:string,
hideBackgroundColor:string,
hideTextColor:string
},
favicon:{
enableCustomFavicon:boolean,
imageUrl:string
}
}
}
}
+42
View File
@@ -0,0 +1,42 @@
///////////////////////////////////////
//DEFAULT CONSOLE MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from "../modules/console"
/**## ODLiveStatusManagerIds_Default `type`
* This type is an array of ids available in the `ODLiveStatusManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODLiveStatusManagerIds_Default {
"openticket:default-djdj-dev":ODLiveStatusUrlSource
}
/**## ODLiveStatusManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODLiveStatusManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.livestatus`!
*/
export class ODLiveStatusManager_Default extends ODLiveStatusManager {
get<LiveStatusId extends keyof ODLiveStatusManagerIds_Default>(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
get(id:ODValidId): ODLiveStatusSource|null
get(id:ODValidId): ODLiveStatusSource|null {
return super.get(id)
}
remove<LiveStatusId extends keyof ODLiveStatusManagerIds_Default>(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
remove(id:ODValidId): ODLiveStatusSource|null
remove(id:ODValidId): ODLiveStatusSource|null {
return super.remove(id)
}
exists(id:keyof ODLiveStatusManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+42
View File
@@ -0,0 +1,42 @@
///////////////////////////////////////
//DEFAULT COOLDOWN MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODCooldown, ODCooldownManager } from "../modules/cooldown"
/**## ODCooldownManagerIds_Default `type`
* This type is an array of ids available in the `ODCooldownManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCooldownManagerIds_Default {
}
/**## ODCooldownManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCooldownManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.cooldowns`!
*/
export class ODCooldownManager_Default extends ODCooldownManager {
get<CooldownId extends keyof ODCooldownManagerIds_Default>(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
get(id:ODValidId): ODCooldown<object>|null
get(id:ODValidId): ODCooldown<object>|null {
return super.get(id)
}
remove<CooldownId extends keyof ODCooldownManagerIds_Default>(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
remove(id:ODValidId): ODCooldown<object>|null
remove(id:ODValidId): ODCooldown<object>|null {
return super.remove(id)
}
exists(id:keyof ODCooldownManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+256
View File
@@ -0,0 +1,256 @@
///////////////////////////////////////
//DEFAULT DATABASE MODULE
///////////////////////////////////////
import { ODValidId, ODValidJsonType } from "../modules/base"
import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modules/database"
import { ODTicketJson } from "../openticket/ticket"
import { ODOptionJson } from "../openticket/option"
/**## ODDatabaseManagerIds_Default `type`
* This type is an array of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDatabaseManagerIds_Default {
"openticket:global":ODFormattedJsonDatabase_DefaultGlobal,
"openticket:stats":ODFormattedJsonDatabase,
"openticket:tickets":ODFormattedJsonDatabase_DefaultTickets,
"openticket:users":ODFormattedJsonDatabase_DefaultUsers,
"openticket:options":ODFormattedJsonDatabase_DefaultOptions,
}
/**## ODDatabaseManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDatabaseManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.databases`!
*/
export class ODDatabaseManager_Default extends ODDatabaseManager {
get<DatabaseId extends keyof ODDatabaseManagerIds_Default>(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
get(id:ODValidId): ODDatabase|null
get(id:ODValidId): ODDatabase|null {
return super.get(id)
}
remove<DatabaseId extends keyof ODDatabaseManagerIds_Default>(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
remove(id:ODValidId): ODDatabase|null
remove(id:ODValidId): ODDatabase|null {
return super.remove(id)
}
exists(id:keyof ODDatabaseManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultGlobal `type`
* This type is an array of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultGlobal {
"openticket:panel-update":string,
"openticket:option-suffix-counter":number,
"openticket:option-suffix-history":string[],
"openticket:last-version":string
}
/**## ODFormattedJsonDatabase_DefaultGlobal `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `global.json` database!
*/
export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): boolean
set(category:string, key:string, value:ODValidJsonType): boolean
set(category:string, key:string, value:ODValidJsonType): boolean {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]|undefined
get(category:string, key:string): ODValidJsonType|undefined
get(category:string, key:string): ODValidJsonType|undefined {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string): boolean
delete(category:string, key:string): boolean
delete(category:string, key:string): boolean {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): boolean
exists(category:string, key:string): boolean
exists(category:string, key:string): boolean {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultTickets `type`
* This type is an array of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultTickets {
"openticket:ticket":ODTicketJson
}
/**## ODFormattedJsonDatabase_DefaultTickets `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `tickets.json` database!
*/
export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): boolean
set(category:string, key:string, value:ODValidJsonType): boolean
set(category:string, key:string, value:ODValidJsonType): boolean {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]|undefined
get(category:string, key:string): ODValidJsonType|undefined
get(category:string, key:string): ODValidJsonType|undefined {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string): boolean
delete(category:string, key:string): boolean
delete(category:string, key:string): boolean {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): boolean
exists(category:string, key:string): boolean
exists(category:string, key:string): boolean {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultUsers `type`
* This type is an array of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultUsers {
"openticket:blacklist":ODTicketJson
}
/**## ODFormattedJsonDatabase_DefaultUsers `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `users.json` database!
*/
export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): boolean
set(category:string, key:string, value:ODValidJsonType): boolean
set(category:string, key:string, value:ODValidJsonType): boolean {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]|undefined
get(category:string, key:string): ODValidJsonType|undefined
get(category:string, key:string): ODValidJsonType|undefined {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string): boolean
delete(category:string, key:string): boolean
delete(category:string, key:string): boolean {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): boolean
exists(category:string, key:string): boolean
exists(category:string, key:string): boolean {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultOptions `type`
* This type is an array of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultOptions {
"openticket:used-option":ODOptionJson
}
/**## ODFormattedJsonDatabase_DefaultOptions `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `options.json` database!
*/
export class ODFormattedJsonDatabase_DefaultOptions extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): boolean
set(category:string, key:string, value:ODValidJsonType): boolean
set(category:string, key:string, value:ODValidJsonType): boolean {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]|undefined
get(category:string, key:string): ODValidJsonType|undefined
get(category:string, key:string): ODValidJsonType|undefined {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string): boolean
delete(category:string, key:string): boolean
delete(category:string, key:string): boolean {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): boolean
exists(category:string, key:string): boolean
exists(category:string, key:string): boolean {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
return super.getCategory(category)
}
}
+331
View File
@@ -0,0 +1,331 @@
///////////////////////////////////////
//DEFAULT EVENT MODULE
///////////////////////////////////////
//BASE MODULES
import { ODPromiseVoid, ODValidId } from "../modules/base"
import { ODPluginClassManager, ODPluginEventManager, ODPluginManager } from "../modules/plugin"
import { ODConsoleManager, ODError } from "../modules/console"
import { ODCheckerResult, ODCheckerStorage } from "../modules/checker"
import { ODDefaultsManager } from "../modules/defaults"
import { ODLanguage } from "../modules/language"
import { ODClientActivityManager } from "../modules/client"
import { ODEvent, ODEventManager } from "../modules/event"
import * as discord from "discord.js"
//DEFAULT MODULES
import { ODVersionManager_Default } from "./base"
import { ODConfigManager_Default} from "./config"
import { ODDatabaseManager_Default } from "./database"
import { ODFlagManager_Default } from "./flag"
import { ODSessionManager_Default } from "./session"
import { ODLanguageManager_Default } from "./language"
import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./checker"
import { ODClientManager_Default, ODSlashCommandManager_Default, ODTextCommandManager_Default } from "./client"
import { ODBuilderManager_Default, ODButtonManager_Default, ODDropdownManager_Default, ODEmbedManager_Default, ODFileManager_Default, ODMessageManager_Default, ODModalManager_Default } from "./builder"
import { ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder"
import { ODActionManager_Default } from "./action"
import { ODPermissionManager_Default } from "./permission"
import { ODHelpMenuManager_Default } from "./helpmenu"
import { ODStatsManager_Default } from "./stat"
import { ODCodeManager_Default } from "./code"
import { ODCooldownManager_Default } from "./cooldown"
import { ODPostManager_Default } from "./post"
import { ODVerifyBarManager_Default } from "./verifybar"
import { ODStartScreenManager_Default } from "./startscreen"
import { ODLiveStatusManager_Default } from "./console"
//OPEN TICKET MODULES
import { ODOptionManager, ODTicketOption } from "../openticket/option"
import { ODPanel, ODPanelManager } from "../openticket/panel"
import { ODTicket, ODTicketClearFilter, ODTicketManager } from "../openticket/ticket"
import { ODQuestionManager } from "../openticket/question"
import { ODBlacklistManager } from "../openticket/blacklist"
import { ODTranscriptManager_Default } from "../openticket/transcript"
import { ODRole, ODRoleManager } from "../openticket/role"
/**## ODEventIds_Default `type`
* This type is an array of ids available in the `ODEvent_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODEventIds_Default {
//error handling
"onErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin) => ODPromiseVoid>
"afterErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin, message:ODError) => ODPromiseVoid>
//plugins
"afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager) => ODPromiseVoid>
"onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid>
"afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid>
"onPluginEventLoad": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid>
"afterPluginEventsLoaded": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid>
"onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
//configs
"onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
"afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
//databases
"onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
"afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
//languages
"onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"afterLanguagesLoaded": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"onLanguageSelect": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"afterLanguagesSelected": ODEvent_Default<(main:ODLanguage|null, backup:ODLanguage|null, languages:ODLanguageManager_Default) => ODPromiseVoid>
//sessions
"onSessionLoad": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
"afterSessionsLoaded": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
//config checkers
"onCheckerLoad": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersLoaded": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerFunctionLoad": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckerFunctionsLoaded": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerExecute": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersExecuted": ODEvent_Default<(result:ODCheckerResult, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerTranslationLoad": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, enabled:boolean, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckerTranslationsLoaded": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerRender": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersRendered": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerQuit": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
//client configuration
"onClientLoad": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientLoaded": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientInit": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientInitiated": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientActivityLoad": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"afterClientActivityLoaded": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"onClientActivityInit": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"afterClientActivityInitiated": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
//client slash commands
"onSlashCommandLoad": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterSlashCommandsLoaded": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"onSlashCommandRegister": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterSlashCommandsRegistered": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
//client text commands
"onTextCommandLoad": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default,) => ODPromiseVoid>
"afterTextCommandsLoaded": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
//questions
"onQuestionLoad": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
"afterQuestionsLoaded": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
//options
"onOptionLoad": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
"afterOptionsLoaded": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
//panels
"onPanelLoad": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
"afterPanelsLoaded": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
"onPanelSpawn": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
"afterPanelSpawned": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
//tickets
"onTicketLoad": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
"afterTicketsLoaded": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
//ticket creation
"onTicketChannelCreation": ODEvent_Default<(option:ODTicketOption, user:discord.User) => ODPromiseVoid>
"afterTicketChannelCreated": ODEvent_Default<(option:ODTicketOption, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"onTicketChannelDeletion": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketChannelDeleted": ODEvent_Default<(ticket:ODTicket, user:discord.User) => ODPromiseVoid>
"onTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"onTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, message:discord.Message, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
//ticket actions
"onTicketCreate": ODEvent_Default<(creator:discord.User) => ODPromiseVoid>
"afterTicketCreated": ODEvent_Default<(ticket:ODTicket, creator:discord.User, channel:discord.GuildTextBasedChannel) => ODPromiseVoid>
"onTicketClose": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketClosed": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketReopen": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketReopened": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketDelete": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketDeleted": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, reason:string|null) => ODPromiseVoid>
"onTicketMove": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketMoved": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketClaim": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketClaimed": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUnclaim": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUnclaimed": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketPin": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketPinned": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUnpin": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUnpinned": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUserAdd": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUserAdded": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUserRemove": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUserRemoved": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketRename": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketRenamed": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketsClear": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
"afterTicketsCleared": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
//roles
"onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
"afterRolesLoaded": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
"onRoleUpdate": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
"afterRolesUpdated": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
//blacklist
"onBlacklistLoad": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
"afterBlacklistLoaded": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
//transcripts
"onTranscriptCompilerLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"afterTranscriptCompilersLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"onTranscriptHistoryLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"afterTranscriptHistoryLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
//transcript creation
"onTranscriptCreate": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptCreated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptInit": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptInitiated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptCompile": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptCompiled": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
//builders
"onButtonBuilderLoad": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterButtonBuildersLoaded": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onDropdownBuilderLoad": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterDropdownBuildersLoaded": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onFileBuilderLoad": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterFileBuildersLoaded": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onEmbedBuilderLoad": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterEmbedBuildersLoaded": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onMessageBuilderLoad": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterMessageBuildersLoaded": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onModalBuilderLoad": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterModalBuildersLoaded": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
//responders
"onCommandResponderLoad": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterCommandRespondersLoaded": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onButtonResponderLoad": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterButtonRespondersLoaded": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onDropdownResponderLoad": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterDropdownRespondersLoaded": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
//actions
"onActionLoad": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
"afterActionsLoaded": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
//verifybars
"onVerifyBarLoad": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
"afterVerifyBarsLoaded": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
//permissions
"onPermissionLoad": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
"afterPermissionsLoaded": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
//posts
"onPostLoad": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"afterPostsLoaded": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"onPostInit": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"afterPostsInitiated": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
//cooldowns
"onCooldownLoad": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"afterCooldownsLoaded": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"onCooldownInit": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"afterCooldownsInitiated": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
//help menu
"onHelpMenuCategoryLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"afterHelpMenuCategoriesLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"onHelpMenuComponentLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"afterHelpMenuComponentsLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
//stats
"onStatScopeLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatScopesLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"onStatLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatsLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"onStatInit": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatsInitiated": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
//code
"onCodeLoad": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"afterCodeLoaded": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"onCodeExecute": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"afterCodeExecuted": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
//livestatus
"onLiveStatusSourceLoad": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
"afterLiveStatusSourcesLoaded": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
//startscreen
"onStartScreenLoad": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"afterStartScreensLoaded": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"onStartScreenRender": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
}
/**## ODEventManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEvent class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.events`!
*/
export class ODEventManager_Default extends ODEventManager {
get<StartScreenId extends keyof ODEventIds_Default>(id:StartScreenId): ODEventIds_Default[StartScreenId]
get(id:ODValidId): ODEvent|null
get(id:ODValidId): ODEvent|null {
return super.get(id)
}
remove<StartScreenId extends keyof ODEventIds_Default>(id:StartScreenId): ODEventIds_Default[StartScreenId]
remove(id:ODValidId): ODEvent|null
remove(id:ODValidId): ODEvent|null {
return super.remove(id)
}
exists(id:keyof ODEventIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODEventManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEvent class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.events`!
*/
export class ODEvent_Default<Callback extends ((...args:any) => ODPromiseVoid)> extends ODEvent {
listen(callback:Callback): void {
return super.listen(callback)
}
listenOnce(callback:Callback): void {
return super.listenOnce(callback)
}
wait(): Promise<Parameters<Callback>>
wait(): Promise<any[]> {
return super.wait()
}
emit(params:Parameters<Callback>): Promise<void> {
return super.emit(params)
}
}
+53
View File
@@ -0,0 +1,53 @@
///////////////////////////////////////
//DEFAULT PROCESS MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODFlagManager, ODFlag } from "../modules/flag"
/**## ODFlagManagerIds_Default `type`
* This type is an array of ids available in the `ODFlagManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFlagManagerIds_Default {
"openticket:no-migration":ODFlag,
"openticket:dev-config":ODFlag,
"openticket:dev-database":ODFlag,
"openticket:debug":ODFlag,
"openticket:crash":ODFlag,
"openticket:no-transcripts":ODFlag,
"openticket:no-checker":ODFlag,
"openticket:checker":ODFlag,
"openticket:no-easter":ODFlag,
"openticket:no-plugins":ODFlag,
"openticket:soft-plugins":ODFlag,
"openticket:force-slash-update":ODFlag,
}
/**## ODFlagManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFlagManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.flags`!
*/
export class ODFlagManager_Default extends ODFlagManager {
get<FlagId extends keyof ODFlagManagerIds_Default>(id:FlagId): ODFlagManagerIds_Default[FlagId]
get(id:ODValidId): ODFlag|null
get(id:ODValidId): ODFlag|null {
return super.get(id)
}
remove<FlagId extends keyof ODFlagManagerIds_Default>(id:FlagId): ODFlagManagerIds_Default[FlagId]
remove(id:ODValidId): ODFlag|null
remove(id:ODValidId): ODFlag|null {
return super.remove(id)
}
exists(id:keyof ODFlagManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+323
View File
@@ -0,0 +1,323 @@
///////////////////////////////////////
//DEFAULT HELP MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, ODHelpMenuManager } from "../modules/helpmenu"
/**## ODHelpMenuManagerIds_Default `type`
* This type is an array of ids available in the `ODHelpMenuManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerIds_Default {
"openticket:general":ODHelpMenuCategory_DefaultGeneral,
"openticket:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic,
"openticket:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced,
"openticket:ticket-user":ODHelpMenuCategory_DefaultTicketUser,
"openticket:admin":ODHelpMenuCategory_DefaultAdmin,
"openticket:advanced":ODHelpMenuCategory_DefaultAdvanced,
"openticket:extra":ODHelpMenuCategory_DefaultExtra
}
/**## ODHelpMenuManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.helpmenu`!
*/
export class ODHelpMenuManager_Default extends ODHelpMenuManager {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerIds_Default>(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuCategory|null
get(id:ODValidId): ODHelpMenuCategory|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerIds_Default>(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuCategory|null
remove(id:ODValidId): ODHelpMenuCategory|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultGeneral `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultGeneral` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultGeneral {
"openticket:help":ODHelpMenuCommandComponent,
"openticket:ticket":ODHelpMenuCommandComponent|null
}
/**## ODHelpMenuCategory_DefaultGeneral `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:general` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultGeneral>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultGeneral>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultGeneral): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketBasic `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic {
"openticket:close":ODHelpMenuCommandComponent,
"openticket:delete":ODHelpMenuCommandComponent,
"openticket:reopen":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultTicketBasic `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:ticket` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced {
"openticket:pin":ODHelpMenuCommandComponent,
"openticket:unpin":ODHelpMenuCommandComponent,
"openticket:move":ODHelpMenuCommandComponent,
"openticket:rename":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultTicketAdvanced `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:ticket` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketUser `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser {
"openticket:claim":ODHelpMenuCommandComponent,
"openticket:unclaim":ODHelpMenuCommandComponent,
"openticket:add":ODHelpMenuCommandComponent,
"openticket:remove":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultTicketUser `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:ticket` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultAdmin `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdmin` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultAdmin {
"openticket:panel":ODHelpMenuCommandComponent,
"openticket:blacklist-view":ODHelpMenuCommandComponent,
"openticket:blacklist-add":ODHelpMenuCommandComponent,
"openticket:blacklist-remove":ODHelpMenuCommandComponent,
"openticket:blacklist-get":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultAdmin `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:admin` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdmin>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdmin>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdmin): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultAdvanced `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdvanced` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced {
"openticket:stats-global":ODHelpMenuCommandComponent,
"openticket:stats-reset":ODHelpMenuCommandComponent,
"openticket:stats-ticket":ODHelpMenuCommandComponent,
"openticket:stats-user":ODHelpMenuCommandComponent,
"openticket:autoclose-disable":ODHelpMenuCommandComponent,
"openticket:autoclose-enable":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultAdvanced `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:advanced` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultExtra `type`
* This type is an array of ids available in the `ODHelpMenuCategory_DefaultExtra` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultExtra {}
/**## ODHelpMenuCategory_DefaultExtra `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:general` category in `openticket.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultExtra extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultExtra>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultExtra>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultExtra): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+510
View File
@@ -0,0 +1,510 @@
///////////////////////////////////////
//DEFAULT LANGUAGE MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODLanguageManager, ODLanguage } from "../modules/language"
/**## ODLanguageManagerTranslations_Default `type`
* This type is an array of ids available in the `ODLanguageManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export type ODLanguageManagerTranslations_Default = (
"checker.system.headerOpenTicket"|
"checker.system.typeError"|
"checker.system.typeWarning"|
"checker.system.typeInfo"|
"checker.system.headerConfigChecker"|
"checker.system.headerDescription"|
"checker.system.footerError"|
"checker.system.footerWarning"|
"checker.system.footerSupport"|
"checker.system.compactInformation"|
"checker.system.dataPath"|
"checker.system.dataDocs"|
"checker.system.dataMessages"|
"checker.messages.invalidType"|
"checker.messages.propertyMissing"|
"checker.messages.propertyOptional"|
"checker.messages.objectDisabled"|
"checker.messages.nullInvalid"|
"checker.messages.switchInvalidType"|
"checker.messages.objectSwitchInvalid"|
"checker.messages.stringTooShort"|
"checker.messages.stringTooLong"|
"checker.messages.stringLengthInvalid"|
"checker.messages.stringStartsWith"|
"checker.messages.stringEndsWith"|
"checker.messages.stringContains"|
"checker.messages.stringChoices"|
"checker.messages.stringRegex"|
"checker.messages.numberTooShort"|
"checker.messages.numberTooLong"|
"checker.messages.numberLengthInvalid"|
"checker.messages.numberTooSmall"|
"checker.messages.numberTooLarge"|
"checker.messages.numberNotEqual"|
"checker.messages.numberStep"|
"checker.messages.numberStepOffset"|
"checker.messages.numberStartsWith"|
"checker.messages.numberEndsWith"|
"checker.messages.numberContains"|
"checker.messages.numberChoices"|
"checker.messages.numberFloat"|
"checker.messages.numberNegative"|
"checker.messages.numberPositive"|
"checker.messages.numberZero"|
"checker.messages.booleanTrue"|
"checker.messages.booleanFalse"|
"checker.messages.arrayEmptyDisabled"|
"checker.messages.arrayEmptyRequired"|
"checker.messages.arrayTooShort"|
"checker.messages.arrayTooLong"|
"checker.messages.arrayLengthInvalid"|
"checker.messages.arrayInvalidTypes"|
"checker.messages.arrayDouble"|
"checker.messages.discordInvalidId"|
"checker.messages.discordInvalidIdOptions"|
"checker.messages.discordInvalidToken"|
"checker.messages.colorInvalid"|
"checker.messages.emojiTooShort"|
"checker.messages.emojiTooLong"|
"checker.messages.emojiCustom"|
"checker.messages.emojiInvalid"|
"checker.messages.urlInvalid"|
"checker.messages.urlInvalidHttp"|
"checker.messages.urlInvalidProtocol"|
"checker.messages.urlInvalidHostname"|
"checker.messages.urlInvalidExtension"|
"checker.messages.urlInvalidPath"|
"checker.messages.idNotUnique"|
"checker.messages.idNonExistent"|
"checker.messages.invalidLanguage"|
"checker.messages.invalidButton"|
"checker.messages.unusedOption"|
"checker.messages.unusedQuestion"|
"checker.messages.dropdownOption"|
"actions.buttons.create"|
"actions.buttons.close"|
"actions.buttons.delete"|
"actions.buttons.reopen"|
"actions.buttons.claim"|
"actions.buttons.unclaim"|
"actions.buttons.pin"|
"actions.buttons.unpin"|
"actions.buttons.clear"|
"actions.buttons.helpSwitchSlash"|
"actions.buttons.helpSwitchText"|
"actions.buttons.helpPage"|
"actions.buttons.withReason"|
"actions.buttons.withoutTranscript"|
"actions.titles.created"|
"actions.titles.close"|
"actions.titles.delete"|
"actions.titles.reopen"|
"actions.titles.claim"|
"actions.titles.unclaim"|
"actions.titles.pin"|
"actions.titles.unpin"|
"actions.titles.rename"|
"actions.titles.move"|
"actions.titles.add"|
"actions.titles.remove"|
"actions.titles.help"|
"actions.titles.statsReset"|
"actions.titles.blacklistAdd"|
"actions.titles.blacklistRemove"|
"actions.titles.blacklistGet"|
"actions.titles.blacklistView"|
"actions.titles.blacklistAddDm"|
"actions.titles.blacklistRemoveDm"|
"actions.titles.clear"|
"actions.titles.roles"|
"actions.titles.autoclose"|
"actions.titles.autocloseEnabled"|
"actions.titles.autocloseDisabled"|
"actions.titles.autodelete"|
"actions.titles.autodeleteEnabled"|
"actions.titles.autodeleteDisabled"|
"actions.descriptions.create"|
"actions.descriptions.close"|
"actions.descriptions.delete"|
"actions.descriptions.reopen"|
"actions.descriptions.claim"|
"actions.descriptions.unclaim"|
"actions.descriptions.pin"|
"actions.descriptions.unpin"|
"actions.descriptions.rename"|
"actions.descriptions.move"|
"actions.descriptions.add"|
"actions.descriptions.remove"|
"actions.descriptions.helpExplanation"|
"actions.descriptions.statsReset"|
"actions.descriptions.statsError"|
"actions.descriptions.blacklistAdd"|
"actions.descriptions.blacklistRemove"|
"actions.descriptions.blacklistGetSuccess"|
"actions.descriptions.blacklistGetEmpty"|
"actions.descriptions.blacklistViewEmpty"|
"actions.descriptions.blacklistViewTip"|
"actions.descriptions.clearVerify"|
"actions.descriptions.clearReady"|
"actions.descriptions.rolesEmpty"|
"actions.descriptions.autocloseLeave"|
"actions.descriptions.autocloseTimeout"|
"actions.descriptions.autodeleteLeave"|
"actions.descriptions.autodeleteTimeout"|
"actions.descriptions.autocloseEnabled"|
"actions.descriptions.autocloseDisabled"|
"actions.descriptions.autodeleteEnabled"|
"actions.descriptions.autodeleteDisabled"|
"actions.descriptions.ticketMessageLimit"|
"actions.descriptions.ticketMessageAutoclose"|
"actions.descriptions.ticketMessageAutodelete"|
"actions.descriptions.panelReady"|
"actions.modal.closePlaceholder"|
"actions.modal.deletePlaceholder"|
"actions.modal.reopenPlaceholder"|
"actions.modal.claimPlaceholder"|
"actions.modal.unclaimPlaceholder"|
"actions.modal.pinPlaceholder"|
"actions.modal.unpinPlaceholder"|
"actions.logs.createLog"|
"actions.logs.closeLog"|
"actions.logs.closeDm"|
"actions.logs.deleteLog"|
"actions.logs.deleteDm"|
"actions.logs.reopenLog"|
"actions.logs.reopenDm"|
"actions.logs.claimLog"|
"actions.logs.claimDm"|
"actions.logs.unclaimLog"|
"actions.logs.unclaimDm"|
"actions.logs.pinLog"|
"actions.logs.pinDm"|
"actions.logs.unpinLog"|
"actions.logs.unpinDm"|
"actions.logs.renameLog"|
"actions.logs.renameDm"|
"actions.logs.moveLog"|
"actions.logs.moveDm"|
"actions.logs.addLog"|
"actions.logs.addDm"|
"actions.logs.removeLog"|
"actions.logs.removeDm"|
"actions.logs.blacklistAddLog"|
"actions.logs.blacklistRemoveLog"|
"actions.logs.blacklistAddDm"|
"actions.logs.blacklistRemoveDm"|
"actions.logs.clearLog"|
"transcripts.success.visit"|
"transcripts.success.ready"|
"transcripts.success.textFileDescription"|
"transcripts.success.htmlProgress"|
"transcripts.success.createdChannel"|
"transcripts.success.createdCreator"|
"transcripts.success.createdParticipant"|
"transcripts.success.createdActiveAdmin"|
"transcripts.success.createdEveryAdmin"|
"transcripts.success.createdOther"|
"transcripts.errors.retry"|
"transcripts.errors.continue"|
"transcripts.errors.backup"|
"transcripts.errors.error"|
"errors.titles.internalError"|
"errors.titles.optionMissing"|
"errors.titles.optionInvalid"|
"errors.titles.unknownCommand"|
"errors.titles.noPermissions"|
"errors.titles.unknownTicket"|
"errors.titles.deprecatedTicket"|
"errors.titles.unknownOption"|
"errors.titles.unknownPanel"|
"errors.titles.notInGuild"|
"errors.titles.channelRename"|
"errors.titles.busy"|
"errors.descriptions.askForInfo"|
"errors.descriptions.askForInfoResolve"|
"errors.descriptions.internalError"|
"errors.descriptions.optionMissing"|
"errors.descriptions.optionInvalid"|
"errors.descriptions.optionInvalidChoose"|
"errors.descriptions.unknownCommand"|
"errors.descriptions.noPermissions"|
"errors.descriptions.noPermissionsList"|
"errors.descriptions.noPermissionsCooldown"|
"errors.descriptions.noPermissionsBlacklist"|
"errors.descriptions.noPermissionsLimitGlobal"|
"errors.descriptions.noPermissionsLimitGlobalUser"|
"errors.descriptions.noPermissionsLimitOption"|
"errors.descriptions.noPermissionsLimitOptionUser"|
"errors.descriptions.unknownTicket"|
"errors.descriptions.deprecatedTicket"|
"errors.descriptions.notInGuild"|
"errors.descriptions.channelRename"|
"errors.descriptions.channelRenameSource"|
"errors.descriptions.busy"|
"errors.optionInvalidReasons.stringRegex"|
"errors.optionInvalidReasons.stringMinLength"|
"errors.optionInvalidReasons.stringMaxLength"|
"errors.optionInvalidReasons.numberInvalid"|
"errors.optionInvalidReasons.numberMin"|
"errors.optionInvalidReasons.numberMax"|
"errors.optionInvalidReasons.numberDecimal"|
"errors.optionInvalidReasons.numberNegative"|
"errors.optionInvalidReasons.numberPositive"|
"errors.optionInvalidReasons.numberZero"|
"errors.optionInvalidReasons.channelNotFound"|
"errors.optionInvalidReasons.userNotFound"|
"errors.optionInvalidReasons.roleNotFound"|
"errors.optionInvalidReasons.memberNotFound"|
"errors.optionInvalidReasons.mentionableNotFound"|
"errors.optionInvalidReasons.channelType"|
"errors.optionInvalidReasons.notInGuild"|
"errors.permissions.developer"|
"errors.permissions.owner"|
"errors.permissions.admin"|
"errors.permissions.moderator"|
"errors.permissions.support"|
"errors.permissions.member"|
"errors.permissions.discord-administrator"|
"errors.actionInvalid.close"|
"errors.actionInvalid.reopen"|
"errors.actionInvalid.claim"|
"errors.actionInvalid.unclaim"|
"errors.actionInvalid.pin"|
"errors.actionInvalid.unpin"|
"errors.actionInvalid.add"|
"errors.actionInvalid.remove"|
"params.uppercase.ticket"|
"params.uppercase.tickets"|
"params.uppercase.reason"|
"params.uppercase.creator"|
"params.uppercase.remaining"|
"params.uppercase.added"|
"params.uppercase.removed"|
"params.uppercase.filter"|
"params.uppercase.claimedBy"|
"params.uppercase.method"|
"params.uppercase.type"|
"params.uppercase.blacklisted"|
"params.uppercase.panel"|
"params.uppercase.command"|
"params.uppercase.system"|
"params.uppercase.true"|
"params.uppercase.false"|
"params.uppercase.syntax"|
"params.uppercase.originalName"|
"params.uppercase.newName"|
"params.uppercase.until"|
"params.uppercase.validOptions"|
"params.uppercase.validPanels"|
"params.uppercase.autoclose"|
"params.uppercase.autodelete"|
"params.uppercase.startupDate"|
"params.uppercase.version"|
"params.uppercase.name"|
"params.uppercase.role"|
"params.uppercase.status"|
"params.uppercase.claimed"|
"params.uppercase.pinned"|
"params.uppercase.creationDate"|
"params.lowercase.text"|
"params.lowercase.html"|
"params.lowercase.command"|
"params.lowercase.modal"|
"params.lowercase.button"|
"params.lowercase.dropdown"|
"params.lowercase.method"|
"commands.reason"|
"commands.help"|
"commands.panel"|
"commands.panelId"|
"commands.panelAutoUpdate"|
"commands.ticket"|
"commands.ticketId"|
"commands.close"|
"commands.delete"|
"commands.deleteNoTranscript"|
"commands.reopen"|
"commands.claim"|
"commands.claimUser"|
"commands.unclaim"|
"commands.pin"|
"commands.unpin"|
"commands.move"|
"commands.moveId"|
"commands.rename"|
"commands.renameName"|
"commands.add"|
"commands.addUser"|
"commands.remove"|
"commands.removeUser"|
"commands.blacklist"|
"commands.blacklistView"|
"commands.blacklistAdd"|
"commands.blacklistRemove"|
"commands.blacklistGet"|
"commands.blacklistGetUser"|
"commands.stats"|
"commands.statsReset"|
"commands.statsGlobal"|
"commands.statsUser"|
"commands.statsUserUser"|
"commands.statsTicket"|
"commands.statsTicketTicket"|
"commands.clear"|
"commands.clearFilter"|
"commands.clearFilters.all"|
"commands.clearFilters.open"|
"commands.clearFilters.close"|
"commands.clearFilters.claim"|
"commands.clearFilters.unclaim"|
"commands.clearFilters.pin"|
"commands.clearFilters.unpin"|
"commands.clearFilters.autoclose"|
"commands.autoclose"|
"commands.autocloseDisable"|
"commands.autocloseEnable"|
"commands.autocloseEnableTime"|
"commands.autodelete"|
"commands.autodeleteDisable"|
"commands.autodeleteEnable"|
"commands.autodeleteEnableTime"|
"helpMenu.help"|
"helpMenu.ticket"|
"helpMenu.close"|
"helpMenu.delete"|
"helpMenu.reopen"|
"helpMenu.pin"|
"helpMenu.unpin"|
"helpMenu.move"|
"helpMenu.rename"|
"helpMenu.claim"|
"helpMenu.unclaim"|
"helpMenu.add"|
"helpMenu.remove"|
"helpMenu.panel"|
"helpMenu.blacklistView"|
"helpMenu.blacklistAdd"|
"helpMenu.blacklistRemove"|
"helpMenu.blacklistGet"|
"helpMenu.statsGlobal"|
"helpMenu.statsTicket"|
"helpMenu.statsUser"|
"helpMenu.statsReset"|
"helpMenu.autocloseDisable"|
"helpMenu.autocloseEnable"|
"helpMenu.autodeleteDisable"|
"helpMenu.autodeleteEnable"|
"stats.scopes.global"|
"stats.scopes.system"|
"stats.scopes.user"|
"stats.scopes.ticket"|
"stats.scopes.participants"|
"stats.properties.ticketsCreated"|
"stats.properties.ticketsClosed"|
"stats.properties.ticketsDeleted"|
"stats.properties.ticketsReopened"|
"stats.properties.ticketsAutoclosed"|
"stats.properties.ticketsClaimed"|
"stats.properties.ticketsPinned"|
"stats.properties.ticketsMoved"|
"stats.properties.usersBlacklisted"|
"stats.properties.transcriptsCreated"
)
/**## ODLanguageManagerIds_Default `type`
* This type is an array of ids available in the `ODLanguageManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODLanguageManagerIds_Default {
"openticket:custom":ODLanguage,
"openticket:english":ODLanguage,
"openticket:dutch":ODLanguage,
"openticket:portuguese":ODLanguage,
"openticket:czech":ODLanguage,
//ADD NEW LANGUAGES HERE!!!
}
/**## ODLanguageManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODLanguageManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.languages`!
*/
export class ODLanguageManager_Default extends ODLanguageManager {
get<LanguageId extends keyof ODLanguageManagerIds_Default>(id:LanguageId): ODLanguageManagerIds_Default[LanguageId]
get(id:ODValidId): ODLanguage|null
get(id:ODValidId): ODLanguage|null {
return super.get(id)
}
remove<LanguageId extends keyof ODLanguageManagerIds_Default>(id:LanguageId): ODLanguageManagerIds_Default[LanguageId]
remove(id:ODValidId): ODLanguage|null
remove(id:ODValidId): ODLanguage|null {
return super.remove(id)
}
exists(id:keyof ODLanguageManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getTranslation(id:ODLanguageManagerTranslations_Default): string
getTranslation(id:string): string|null
getTranslation(id:string): string|null {
return super.getTranslation(id)
}
setCurrentLanguage(id:keyof ODLanguageManagerIds_Default): void
setCurrentLanguage(id:ODValidId): void
setCurrentLanguage(id:ODValidId): void {
return super.setCurrentLanguage(id)
}
setBackupLanguage(id:keyof ODLanguageManagerIds_Default): void
setBackupLanguage(id:ODValidId): void
setBackupLanguage(id:ODValidId): void {
return super.setBackupLanguage(id)
}
getTranslationWithParams(id:ODLanguageManagerTranslations_Default, params:string[]): string
getTranslationWithParams(id:string, params:string[]): string|null
getTranslationWithParams(id:string, params:string[]): string|null {
return super.getTranslationWithParams(id,params)
}
}
+30
View File
@@ -0,0 +1,30 @@
///////////////////////////////////////
//DEFAULT PERMISSION MODULE
///////////////////////////////////////
import { ODDebugger } from "../modules/console"
import { ODPermissionManager } from "../modules/permission"
/**## ODPermissionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPermissionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.permissions`!
*/
export class ODPermissionManager_Default extends ODPermissionManager {
constructor(debug:ODDebugger){
super(debug,true)
}
}
/**## ODPermissionEmbedType `type`
* This type contains all types available in the `openticket:no-permissions` embed.
*/
export type ODPermissionEmbedType = (
"developer"|
"owner"|
"admin"|
"moderator"|
"support"|
"member"|
"discord-administrator"
)
+44
View File
@@ -0,0 +1,44 @@
///////////////////////////////////////
//DEFAULT POST MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODPost, ODPostManager } from "../modules/post"
import * as discord from "discord.js"
/**## ODPostManagerIds_Default `type`
* This type is an array of ids available in the `ODPostManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODPostManagerIds_Default {
"openticket:logs":ODPost<discord.GuildTextBasedChannel>|null,
"openticket:transcripts":ODPost<discord.GuildTextBasedChannel>|null
}
/**## ODPostManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPostManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.code`!
*/
export class ODPostManager_Default extends ODPostManager {
get<PostId extends keyof ODPostManagerIds_Default>(id:PostId): ODPostManagerIds_Default[PostId]
get(id:ODValidId): ODPost<discord.GuildBasedChannel>|null
get(id:ODValidId): ODPost<discord.GuildBasedChannel>|null {
return super.get(id)
}
remove<PostId extends keyof ODPostManagerIds_Default>(id:PostId): ODPostManagerIds_Default[PostId]
remove(id:ODValidId): ODPost<discord.GuildBasedChannel>|null
remove(id:ODValidId): ODPost<discord.GuildBasedChannel>|null {
return super.remove(id)
}
exists(id:keyof ODPostManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+255
View File
@@ -0,0 +1,255 @@
///////////////////////////////////////
//DEFAULT RESPONDER MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODButtonResponder, ODButtonResponderInstance, ODButtonResponderManager, ODCommandResponder, ODCommandResponderInstance, ODCommandResponderManager, ODDropdownResponder, ODDropdownResponderInstance, ODDropdownResponderManager, ODModalResponder, ODModalResponderInstance, ODModalResponderManager, ODResponderManager } from "../modules/responder"
import { ODWorkerManager_Default } from "./worker"
/**## ODResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.responders`!
*/
export class ODResponderManager_Default extends ODResponderManager {
declare commands: ODCommandResponderManager_Default
declare buttons: ODButtonResponderManager_Default
declare dropdowns: ODDropdownResponderManager_Default
declare modals: ODModalResponderManager_Default
}
/**## ODCommandResponderManagerIds_Default `type`
* This type is an array of ids available in the `ODCommandResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCommandResponderManagerIds_Default {
"openticket:help":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:help"|"openticket:logs"},
"openticket:stats":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:stats"|"openticket:logs"},
"openticket:panel":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:panel"|"openticket:logs"},
"openticket:ticket":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:ticket"|"openticket:logs"},
"openticket:blacklist":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:blacklist"|"openticket:discord-logs"|"openticket:logs"},
"openticket:close":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:close"|"openticket:logs"},
"openticket:reopen":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:reopen"|"openticket:logs"},
"openticket:delete":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:delete"|"openticket:logs"},
"openticket:claim":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:claim"|"openticket:logs"},
"openticket:unclaim":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:unclaim"|"openticket:logs"},
"openticket:pin":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:pin"|"openticket:logs"},
"openticket:unpin":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:unpin"|"openticket:logs"},
"openticket:rename":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:rename"|"openticket:logs"},
"openticket:move":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:move"|"openticket:logs"},
"openticket:add":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:add"|"openticket:logs"},
"openticket:remove":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:remove"|"openticket:logs"},
"openticket:clear":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:clear"|"openticket:logs"},
"openticket:autoclose":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:autoclose"|"openticket:logs"},
"openticket:autodelete":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:autodelete"|"openticket:logs"},
}
/**## ODCommandResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCommandResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.responders.commands`!
*/
export class ODCommandResponderManager_Default extends ODCommandResponderManager {
get<CommandResponderId extends keyof ODCommandResponderManagerIds_Default>(id:CommandResponderId): ODCommandResponder_Default<ODCommandResponderManagerIds_Default[CommandResponderId]["source"],ODCommandResponderManagerIds_Default[CommandResponderId]["params"],ODCommandResponderManagerIds_Default[CommandResponderId]["workers"]>
get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null
get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null {
return super.get(id)
}
remove<CommandResponderId extends keyof ODCommandResponderManagerIds_Default>(id:CommandResponderId): ODCommandResponder_Default<ODCommandResponderManagerIds_Default[CommandResponderId]["source"],ODCommandResponderManagerIds_Default[CommandResponderId]["params"],ODCommandResponderManagerIds_Default[CommandResponderId]["workers"]>
remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null
remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null {
return super.remove(id)
}
exists(id:keyof ODCommandResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODCommandResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCommandResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODCommandResponder`'s!
*/
export class ODCommandResponder_Default<Source extends "slash"|"text", Params, WorkerIds extends string> extends ODCommandResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODCommandResponderInstance,Source,Params,WorkerIds>
}
/**## ODButtonResponderManagerIds_Default `type`
* This type is an array of ids available in the `ODButtonResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODButtonResponderManagerIds_Default {
"openticket:verifybar-success":{source:"button",params:{},workers:"openticket:handle-verifybar"},
"openticket:verifybar-failure":{source:"button",params:{},workers:"openticket:handle-verifybar"},
"openticket:help-menu-switch":{source:"button",params:{},workers:"openticket:update-help-menu"},
"openticket:help-menu-previous":{source:"button",params:{},workers:"openticket:update-help-menu"},
"openticket:help-menu-next":{source:"button",params:{},workers:"openticket:update-help-menu"},
"openticket:ticket-option":{source:"button",params:{},workers:"openticket:ticket-option"},
"openticket:role-option":{source:"button",params:{},workers:"openticket:role-option"},
"openticket:claim-ticket":{source:"button",params:{},workers:"openticket:claim-ticket"},
"openticket:unclaim-ticket":{source:"button",params:{},workers:"openticket:unclaim-ticket"},
"openticket:pin-ticket":{source:"button",params:{},workers:"openticket:pin-ticket"},
"openticket:unpin-ticket":{source:"button",params:{},workers:"openticket:unpin-ticket"},
"openticket:close-ticket":{source:"button",params:{},workers:"openticket:close-ticket"},
"openticket:reopen-ticket":{source:"button",params:{},workers:"openticket:reopen-ticket"},
"openticket:delete-ticket":{source:"button",params:{},workers:"openticket:delete-ticket"},
"openticket:transcript-error-retry":{source:"button",params:{},workers:"openticket:permissions"|"openticket:delete-ticket"|"openticket:logs"},
"openticket:transcript-error-continue":{source:"button",params:{},workers:"openticket:permissions"|"openticket:delete-ticket"|"openticket:logs"},
"openticket:clear-continue":{source:"button",params:{},workers:"openticket:clear-continue"},
}
/**## ODButtonResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.responders.buttons`!
*/
export class ODButtonResponderManager_Default extends ODButtonResponderManager {
get<ButtonResponderId extends keyof ODButtonResponderManagerIds_Default>(id:ButtonResponderId): ODButtonResponder_Default<ODButtonResponderManagerIds_Default[ButtonResponderId]["source"],ODButtonResponderManagerIds_Default[ButtonResponderId]["params"],ODButtonResponderManagerIds_Default[ButtonResponderId]["workers"]>
get(id:ODValidId): ODButtonResponder<"button",any>|null
get(id:ODValidId): ODButtonResponder<"button",any>|null {
return super.get(id)
}
remove<ButtonResponderId extends keyof ODButtonResponderManagerIds_Default>(id:ButtonResponderId): ODButtonResponder_Default<ODButtonResponderManagerIds_Default[ButtonResponderId]["source"],ODButtonResponderManagerIds_Default[ButtonResponderId]["params"],ODButtonResponderManagerIds_Default[ButtonResponderId]["workers"]>
remove(id:ODValidId): ODButtonResponder<"button",any>|null
remove(id:ODValidId): ODButtonResponder<"button",any>|null {
return super.remove(id)
}
exists(id:keyof ODButtonResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODButtonResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODButtonResponder`'s!
*/
export class ODButtonResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODButtonResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODButtonResponderInstance,Source,Params,WorkerIds>
}
/**## ODDropdownResponderManagerIds_Default `type`
* This type is an array of ids available in the `ODDropdownResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDropdownResponderManagerIds_Default {
"openticket:panel-dropdown-tickets":{source:"dropdown",params:{},workers:"openticket:panel-dropdown-tickets"},
}
/**## ODDropdownResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.responders.dropdowns`!
*/
export class ODDropdownResponderManager_Default extends ODDropdownResponderManager {
get<DropdownResponderId extends keyof ODDropdownResponderManagerIds_Default>(id:DropdownResponderId): ODDropdownResponder_Default<ODDropdownResponderManagerIds_Default[DropdownResponderId]["source"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["params"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["workers"]>
get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null
get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null {
return super.get(id)
}
remove<DropdownResponderId extends keyof ODDropdownResponderManagerIds_Default>(id:DropdownResponderId): ODDropdownResponder_Default<ODDropdownResponderManagerIds_Default[DropdownResponderId]["source"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["params"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["workers"]>
remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null
remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null {
return super.remove(id)
}
exists(id:keyof ODDropdownResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODDropdownResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODDropdownResponder`'s!
*/
export class ODDropdownResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODDropdownResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODDropdownResponderInstance,Source,Params,WorkerIds>
}
/**## ODModalResponderManagerIds_Default `type`
* This type is an array of ids available in the `ODModalResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODModalResponderManagerIds_Default {
"openticket:ticket-questions":{source:"modal",params:{},workers:"openticket:ticket-questions"},
"openticket:close-ticket-reason":{source:"modal",params:{},workers:"openticket:close-ticket-reason"},
"openticket:reopen-ticket-reason":{source:"modal",params:{},workers:"openticket:reopen-ticket-reason"},
"openticket:delete-ticket-reason":{source:"modal",params:{},workers:"openticket:delete-ticket-reason"},
"openticket:claim-ticket-reason":{source:"modal",params:{},workers:"openticket:claim-ticket-reason"},
"openticket:unclaim-ticket-reason":{source:"modal",params:{},workers:"openticket:unclaim-ticket-reason"},
"openticket:pin-ticket-reason":{source:"modal",params:{},workers:"openticket:pin-ticket-reason"},
"openticket:unpin-ticket-reason":{source:"modal",params:{},workers:"openticket:unpin-ticket-reason"},
}
/**## ODModalResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.responders.dropdowns`!
*/
export class ODModalResponderManager_Default extends ODModalResponderManager {
get<ModalResponderId extends keyof ODModalResponderManagerIds_Default>(id:ModalResponderId): ODModalResponder_Default<ODModalResponderManagerIds_Default[ModalResponderId]["source"],ODModalResponderManagerIds_Default[ModalResponderId]["params"],ODModalResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODModalResponder<"modal",any>|null
get(id:ODValidId): ODModalResponder<"modal",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODModalResponderManagerIds_Default>(id:ModalResponderId): ODModalResponder_Default<ODModalResponderManagerIds_Default[ModalResponderId]["source"],ODModalResponderManagerIds_Default[ModalResponderId]["params"],ODModalResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODModalResponder<"modal",any>|null
remove(id:ODValidId): ODModalResponder<"modal",any>|null {
return super.remove(id)
}
exists(id:keyof ODModalResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODModalResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODModalResponder`'s!
*/
export class ODModalResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODModalResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODModalResponderInstance,Source,Params,WorkerIds>
}
+42
View File
@@ -0,0 +1,42 @@
///////////////////////////////////////
//DEFAULT SESSION MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODSession, ODSessionManager } from "../modules/session"
/**## ODSessionManagerIds_Default `type`
* This type is an array of ids available in the `ODSessionManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODSessionManagerIds_Default {
"test-session":ODSession
}
/**## ODSessionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODSessionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.sessions`!
*/
export class ODSessionManager_Default extends ODSessionManager {
get<SessionId extends keyof ODSessionManagerIds_Default>(id:SessionId): ODSessionManagerIds_Default[SessionId]
get(id:ODValidId): ODSession|null
get(id:ODValidId): ODSession|null {
return super.get(id)
}
remove<SessionId extends keyof ODSessionManagerIds_Default>(id:SessionId): ODSessionManagerIds_Default[SessionId]
remove(id:ODValidId): ODSession|null
remove(id:ODValidId): ODSession|null {
return super.remove(id)
}
exists(id:keyof ODSessionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+48
View File
@@ -0,0 +1,48 @@
///////////////////////////////////////
//DEFAULT STARTSCREEN MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODStartScreenCategoryComponent, ODStartScreenComponent, ODStartScreenFlagsCategoryComponent, ODStartScreenHeaderComponent, ODStartScreenLiveStatusCategoryComponent, ODStartScreenLogoComponent, ODStartScreenManager, ODStartScreenPluginsCategoryComponent, ODStartScreenPropertiesCategoryComponent } from "../modules/startscreen"
/**## ODStartScreenManagerIds_Default `type`
* This type is an array of ids available in the `ODStartScreenManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStartScreenManagerIds_Default {
"openticket:logo":ODStartScreenLogoComponent,
"openticket:header":ODStartScreenHeaderComponent,
"openticket:flags":ODStartScreenFlagsCategoryComponent,
"openticket:plugins":ODStartScreenPluginsCategoryComponent,
"openticket:stats":ODStartScreenPropertiesCategoryComponent,
"openticket:livestatus":ODStartScreenLiveStatusCategoryComponent,
"openticket:logs":ODStartScreenCategoryComponent
}
/**## ODStartScreenManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODStartScreenManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.startscreen`!
*/
export class ODStartScreenManager_Default extends ODStartScreenManager {
get<StartScreenId extends keyof ODStartScreenManagerIds_Default>(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId]
get(id:ODValidId): ODStartScreenComponent|null
get(id:ODValidId): ODStartScreenComponent|null {
return super.get(id)
}
remove<StartScreenId extends keyof ODStartScreenManagerIds_Default>(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId]
remove(id:ODValidId): ODStartScreenComponent|null
remove(id:ODValidId): ODStartScreenComponent|null {
return super.remove(id)
}
exists(id:keyof ODStartScreenManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+363
View File
@@ -0,0 +1,363 @@
///////////////////////////////////////
//DEFAULT SESSION MODULE
///////////////////////////////////////
import { Guild, TextBasedChannel, User } from "discord.js"
import { ODValidId } from "../modules/base"
import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat"
/**## ODStatsManagerIds_Default `type`
* This type is an array of ids available in the `ODStatsManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatsManagerIds_Default {
"openticket:global":ODStatGlobalScope_DefaultGlobal,
"openticket:system":ODStatGlobalScope_DefaultSystem,
"openticket:user":ODStatScope_DefaultUser,
"openticket:ticket":ODStatScope_DefaultTicket,
"openticket:participants":ODStatScope_DefaultParticipants
}
/**## ODStatsManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.stats`!
*/
export class ODStatsManager_Default extends ODStatsManager {
get<StatsId extends keyof ODStatsManagerIds_Default>(id:StatsId): ODStatsManagerIds_Default[StatsId]
get(id:ODValidId): ODStatScope|null
get(id:ODValidId): ODStatScope|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatsManagerIds_Default>(id:StatsId): ODStatsManagerIds_Default[StatsId]
remove(id:ODValidId): ODStatScope|null
remove(id:ODValidId): ODStatScope|null {
return super.remove(id)
}
exists(id:keyof ODStatsManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODStatGlobalScopeIds_DefaultGlobal `type`
* This type is an array of ids available in the `ODStatGlobalScope_DefaultGlobal` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatGlobalScopeIds_DefaultGlobal {
"openticket:tickets-created":ODBasicStat,
"openticket:tickets-closed":ODBasicStat,
"openticket:tickets-deleted":ODBasicStat,
"openticket:tickets-reopened":ODBasicStat,
"openticket:tickets-autoclosed":ODBasicStat,
"openticket:tickets-autodeleted":ODBasicStat,
"openticket:tickets-claimed":ODBasicStat,
"openticket:tickets-pinned":ODBasicStat,
"openticket:tickets-moved":ODBasicStat,
"openticket:users-blacklisted":ODBasicStat,
"openticket:transcripts-created":ODBasicStat
}
/**## ODStatGlobalScope_DefaultGlobal `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:global` category in `openticket.stats`!
*/
export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope {
get<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatGlobalScopeIds_DefaultGlobal): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): ODValidStatValue|null
getStat(id:ODValidId): ODValidStatValue|null
getStat(id:ODValidId): ODValidStatValue|null {
return super.getStat(id)
}
setStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,value,mode)
}
resetStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:ODValidId): ODValidStatValue|null
resetStat(id:ODValidId): ODValidStatValue|null
resetStat(id:ODValidId): ODValidStatValue|null {
return super.resetStat(id)
}
}
/**## ODStatGlobalScopeIds_DefaultSystem `type`
* This type is an array of ids available in the `ODStatScope_DefaultSystem` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatGlobalScopeIds_DefaultSystem {
"openticket:startup-date":ODDynamicStat,
"openticket:version":ODDynamicStat
}
/**## ODStatGlobalScope_DefaultSystem `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:system` category in `openticket.stats`!
*/
export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope {
get<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatGlobalScopeIds_DefaultSystem): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): ODValidStatValue|null
getStat(id:ODValidId): ODValidStatValue|null
getStat(id:ODValidId): ODValidStatValue|null {
return super.getStat(id)
}
setStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,value,mode)
}
resetStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:ODValidId): ODValidStatValue|null
resetStat(id:ODValidId): ODValidStatValue|null
resetStat(id:ODValidId): ODValidStatValue|null {
return super.resetStat(id)
}
}
/**## ODStatScopeIds_DefaultUser `type`
* This type is an array of ids available in the `ODStatScope_DefaultUser` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultUser {
"openticket:name":ODDynamicStat,
"openticket:role":ODDynamicStat,
"openticket:tickets-created":ODBasicStat,
"openticket:tickets-closed":ODBasicStat,
"openticket:tickets-deleted":ODBasicStat,
"openticket:tickets-reopened":ODBasicStat,
"openticket:tickets-claimed":ODBasicStat,
"openticket:tickets-pinned":ODBasicStat,
"openticket:tickets-moved":ODBasicStat,
"openticket:users-blacklisted":ODBasicStat,
"openticket:transcripts-created":ODBasicStat
}
/**## ODStatScope_DefaultUser `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:user` category in `openticket.stats`!
*/
export class ODStatScope_DefaultUser extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId): ODStatScopeIds_DefaultUser[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId): ODStatScopeIds_DefaultUser[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultUser): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.getStat(id,scopeId)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.resetStat(id,scopeId)
}
}
/**## ODStatScopeIds_DefaultTicket `type`
* This type is an array of ids available in the `ODStatScope_DefaultTicket` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultTicket {
"openticket:name":ODDynamicStat,
"openticket:status":ODDynamicStat,
"openticket:claimed":ODDynamicStat,
"openticket:pinned":ODDynamicStat,
"openticket:creation-date":ODDynamicStat,
"openticket:creator":ODDynamicStat
}
/**## ODStatScope_DefaultTicket `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:ticket` category in `openticket.stats`!
*/
export class ODStatScope_DefaultTicket extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultTicket): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.getStat(id,scopeId)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.resetStat(id,scopeId)
}
}
/**## ODStatScopeIds_DefaultParticipants `type`
* This type is an array of ids available in the `ODStatScope_DefaultParticipants` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultParticipants {
"openticket:participants":ODDynamicStat
}
/**## ODStatScope_DefaultParticipants `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `openticket:participants` category in `openticket.stats`!
*/
export class ODStatScope_DefaultParticipants extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultParticipants): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.getStat(id,scopeId)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
return super.resetStat(id,scopeId)
}
}
+72
View File
@@ -0,0 +1,72 @@
///////////////////////////////////////
//DEFAULT VERIFYBAR MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODButtonResponderInstance } from "../modules/responder"
import { ODWorkerManager_Default } from "../defaults/worker"
import { ODVerifyBarManager, ODVerifyBar } from "../modules/verifybar"
import * as discord from "discord.js"
/**## ODVerifyBarManagerIds_Default `type`
* This type is an array of ids available in the `ODVerifyBarManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODVerifyBarManagerIds_Default {
"openticket:claim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:claim-ticket-unclaim-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-unclaim-message"},
"openticket:unclaim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:unclaim-ticket-claim-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-claim-message"},
"openticket:pin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:pin-ticket-unpin-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-unpin-message"},
"openticket:unpin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:unpin-ticket-pin-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-pin-message"},
"openticket:close-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:close-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-reopen-message"},
"openticket:reopen-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-ticket-message"},
"openticket:reopen-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-close-message"},
"openticket:reopen-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"},
"openticket:delete-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}
"openticket:delete-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-close-message"}
"openticket:delete-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-reopen-message"}
"openticket:delete-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"}
}
/**## ODVerifyBarManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODVerifyBarManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.verifybars`!
*/
export class ODVerifyBarManager_Default extends ODVerifyBarManager {
get<VerifyBarId extends keyof ODVerifyBarManagerIds_Default>(id:VerifyBarId): ODVerifyBar_Default<ODVerifyBarManagerIds_Default[VerifyBarId]["successWorkerIds"],ODVerifyBarManagerIds_Default[VerifyBarId]["failureWorkerIds"]>
get(id:ODValidId): ODVerifyBar|null
get(id:ODValidId): ODVerifyBar|null {
return super.get(id)
}
remove<VerifyBarId extends keyof ODVerifyBarManagerIds_Default>(id:VerifyBarId): ODVerifyBar_Default<ODVerifyBarManagerIds_Default[VerifyBarId]["successWorkerIds"],ODVerifyBarManagerIds_Default[VerifyBarId]["failureWorkerIds"]>
remove(id:ODValidId): ODVerifyBar|null
remove(id:ODValidId): ODVerifyBar|null {
return super.remove(id)
}
exists(id:keyof ODVerifyBarManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODVerifyBar_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODVerifyBar class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODVerifyBar`'s!
*/
export class ODVerifyBar_Default<SuccessWorkerIds extends string,FailureWorkerIds extends string> extends ODVerifyBar {
declare success: ODWorkerManager_Default<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null},SuccessWorkerIds>
declare failure: ODWorkerManager_Default<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null},FailureWorkerIds>
}
+35
View File
@@ -0,0 +1,35 @@
///////////////////////////////////////
//DEFAULT WORKER MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODWorker, ODWorkerManager } from "../modules/worker"
/**## ODWorkerManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODWorkerManager class.
* It doesn't add any extra features!
*
* This default class is made for the worker manager in actions, builders & responders!
*/
export class ODWorkerManager_Default<Instance, Source extends string, Params, WorkerIds extends string> extends ODWorkerManager<Instance,Source,Params> {
get(id:WorkerIds): ODWorker<Instance,Source,Params>
get(id:ODValidId): ODWorker<Instance,Source,Params>|null
get(id:ODValidId): ODWorker<Instance,Source,Params>|null {
return super.get(id)
}
remove(id:WorkerIds): ODWorker<Instance,Source,Params>
remove(id:ODValidId): ODWorker<Instance,Source,Params>|null
remove(id:ODValidId): ODWorker<Instance,Source,Params>|null {
return super.remove(id)
}
exists(id:WorkerIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
+180
View File
@@ -0,0 +1,180 @@
//BASE MODULES
import { ODEnvHelper, ODVersion } from "./modules/base"
import { ODPluginManager } from "./modules/plugin"
import { ODConsoleManager, ODConsoleMessage, ODConsoleMessageParam, ODConsoleMessageTypes, ODDebugFileManager, ODDebugger, ODError } from "./modules/console"
import { ODCheckerStorage } from "./modules/checker"
import { ODDefaultsManager } from "./modules/defaults"
//DEFAULT MODULES
import { ODVersionManager_Default } from "./defaults/base"
import { ODEventManager_Default } from "./defaults/event"
import { ODConfigManager_Default} from "./defaults/config"
import { ODDatabaseManager_Default } from "./defaults/database"
import { ODFlagManager_Default } from "./defaults/flag"
import { ODSessionManager_Default } from "./defaults/session"
import { ODLanguageManager_Default } from "./defaults/language"
import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./defaults/checker"
import { ODClientManager_Default } from "./defaults/client"
import { ODBuilderManager_Default } from "./defaults/builder"
import { ODResponderManager_Default } from "./defaults/responder"
import { ODActionManager_Default } from "./defaults/action"
import { ODPermissionManager_Default } from "./defaults/permission"
import { ODHelpMenuManager_Default } from "./defaults/helpmenu"
import { ODStatsManager_Default } from "./defaults/stat"
import { ODCodeManager_Default } from "./defaults/code"
import { ODCooldownManager_Default } from "./defaults/cooldown"
import { ODPostManager_Default } from "./defaults/post"
import { ODVerifyBarManager_Default } from "./defaults/verifybar"
import { ODStartScreenManager_Default } from "./defaults/startscreen"
import { ODLiveStatusManager_Default } from "./defaults/console"
//OPEN TICKET MODULES
import { ODOptionManager } from "./openticket/option"
import { ODPanelManager } from "./openticket/panel"
import { ODTicketManager } from "./openticket/ticket"
import { ODQuestionManager } from "./openticket/question"
import { ODBlacklistManager } from "./openticket/blacklist"
import { ODTranscriptManager_Default } from "./openticket/transcript"
import { ODRoleManager } from "./openticket/role"
/**## ODMain `class`
* This is the main Open Ticket class.
* It contains all managers from the entire bot & has shortcuts to the event & logging system.
*
* This class can't be overwritten or extended & is available as the global variable `openticket`!
*/
export class ODMain {
/**The manager that handles all versions in the bot. */
versions: ODVersionManager_Default
/**The manager responsible for the debug file. (`otdebug.txt`) */
debugfile: ODDebugFileManager
/**The manager responsible for the console system. (logs, errors, etc) */
console: ODConsoleManager
/**The manager responsible for sending debug logs to the debug file. (`otdebug.txt`) */
debug: ODDebugger
/**The manager containing all Open Ticket events. */
events: ODEventManager_Default
/**The manager that handles & executes all plugins in the bot. */
plugins: ODPluginManager
/**The manager that manages & checks all the console flags of the bot. (like `--debug`) */
flags: ODFlagManager_Default
/**The manager that manages & contains all the config files of the bot. (like `config/general.json`) */
configs: ODConfigManager_Default
/**The manager that manages & contains all the databases of the bot. (like `database/global.json`) */
databases: ODDatabaseManager_Default
/**The manager that manages all the data sessions of the bot. (it's a temporary database) */
sessions: ODSessionManager_Default
/**The manager that manages all languages & translations of the bot. (but not for plugins) */
languages: ODLanguageManager_Default
/**The manager that handles & executes all config checkers in the bot. (the code that checks if you have something wrong in your config) */
checkers: ODCheckerManager_Default
/**The manager that manages all builders in the bot. (e.g. buttons, dropdowns, messages, modals, etc) */
builders: ODBuilderManager_Default
/**The manager that manages all responders in the bot. (e.g. commands, buttons, dropdowns, modals) */
responders: ODResponderManager_Default
/**The manager that manages all actions or procedures in the bot. (e.g. ticket-creation, ticket-deletion, ticket-claiming, etc) */
actions: ODActionManager_Default
/**The manager that manages all verify bars in the bot. (the ✅ ❌ buttons) */
verifybars: ODVerifyBarManager_Default
/**The manager that contains all permissions for commands & actions in the bot. (use it to check if someone has admin perms or not) */
permissions: ODPermissionManager_Default
/**The manager that contains all cooldowns of the bot. (e.g. ticket-cooldowns) */
cooldowns: ODCooldownManager_Default
/**The manager that manages & renders the Open Ticket help menu. (not the embed, but the text) */
helpmenu: ODHelpMenuManager_Default
/**The manager that manages, saves & renders the Open Ticket statistics. (not the embed, but the text & database) */
stats: ODStatsManager_Default
/**This manager is a place where you can put code that executes when the bot almost finishes the setup. (can be used for less important stuff that doesn't require an exact time-order) */
code: ODCodeManager_Default
/**The manager that manages all posts (static discord channels) in the bot. (e.g. (transcript) logs, etc) */
posts: ODPostManager_Default
/**The manager responsible for everything related to the client. (e.g. status, login, slash & text commands, etc) */
client: ODClientManager_Default
/**This manager contains A LOD of booleans. With these switches, you can turn off "default behaviours" from the bot. This is used if you want to replace the default Open Ticket code. */
defaults: ODDefaultsManager
/**This manager manages all the variables in the ENV. It reads from both the `.env` file & the `process.env`. (these 2 will be combined) */
env: ODEnvHelper
/**The manager responsible for the livestatus system. (remote console logs) */
livestatus: ODLiveStatusManager_Default
/**The manager responsible for the livestatus system. (remote console logs) */
startscreen: ODStartScreenManager_Default
//OPEN TICKET
/**The manager that manages all the data of questions in the bot. (these are used in options & tickets) */
questions: ODQuestionManager
/**The manager that manages all the data of options in the bot. (these are used for panels, ticket creation, reaction roles) */
options: ODOptionManager
/**The manager that manages all the data of panels in the bot. (panels contain the options) */
panels: ODPanelManager
/**The manager that manages all tickets in the bot. (here, you can get & edit a lot of data from tickets) */
tickets: ODTicketManager
/**The manager that manages the ticket blacklist. (people who are blacklisted can't create a ticket) */
blacklist: ODBlacklistManager
/**The manager that manages the ticket transcripts. (both the history & compilers) */
transcripts: ODTranscriptManager_Default
/**The manager that manages all reaction roles in the bot. (here, you can add additional data to roles) */
roles: ODRoleManager
constructor(){
this.versions = new ODVersionManager_Default()
this.versions.add(ODVersion.fromString("openticket:version","v4.0.0"))
this.versions.add(ODVersion.fromString("openticket:api","v1.0.0"))
this.versions.add(ODVersion.fromString("openticket:transcripts","v2.0.0"))
this.versions.add(ODVersion.fromString("openticket:livestatus","v2.0.0"))
this.debugfile = new ODDebugFileManager("./","otdebug.txt",5000,this.versions.get("openticket:version"))
this.console = new ODConsoleManager(100,this.debugfile)
this.debug = new ODDebugger(this.console)
this.events = new ODEventManager_Default(this.debug)
this.plugins = new ODPluginManager(this.debug)
this.flags = new ODFlagManager_Default(this.debug)
this.configs = new ODConfigManager_Default(this.debug)
this.databases = new ODDatabaseManager_Default(this.debug)
this.sessions = new ODSessionManager_Default(this.debug)
this.languages = new ODLanguageManager_Default(this.debug,false)
this.checkers = new ODCheckerManager_Default(this.debug,new ODCheckerStorage(),new ODCheckerRenderer_Default(),new ODCheckerTranslationRegister_Default(),new ODCheckerFunctionManager_Default(this.debug))
this.builders = new ODBuilderManager_Default(this.debug)
this.client = new ODClientManager_Default(this.debug)
this.responders = new ODResponderManager_Default(this.debug,this.client)
this.actions = new ODActionManager_Default(this.debug)
this.verifybars = new ODVerifyBarManager_Default(this.debug)
this.permissions = new ODPermissionManager_Default(this.debug)
this.cooldowns = new ODCooldownManager_Default(this.debug)
this.helpmenu = new ODHelpMenuManager_Default(this.debug)
this.stats = new ODStatsManager_Default(this.debug)
this.code = new ODCodeManager_Default(this.debug)
this.posts = new ODPostManager_Default(this.debug)
this.defaults = new ODDefaultsManager()
this.env = new ODEnvHelper()
this.livestatus = new ODLiveStatusManager_Default(this.debug,this)
this.startscreen = new ODStartScreenManager_Default(this.debug,this.livestatus)
//OPEN TICKET
this.questions = new ODQuestionManager(this.debug)
this.options = new ODOptionManager(this.debug)
this.panels = new ODPanelManager(this.debug)
this.tickets = new ODTicketManager(this.debug,this.client)
this.blacklist = new ODBlacklistManager(this.debug)
this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets)
this.roles = new ODRoleManager(this.debug)
}
/**Log a message to the console. But in the Open Ticket style :) */
log(message:ODConsoleMessage): void
log(message:ODError): void
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
if (message instanceof ODConsoleMessage) this.console.log(message)
else if (message instanceof ODError) this.console.log(message)
else if (["string","number","boolean","object"].includes(typeof message)) this.console.log(message,type,params)
}
}
+58
View File
@@ -0,0 +1,58 @@
///////////////////////////////////////
//ACTION MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base"
import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker"
import { ODDebugger } from "./console"
/**## ODActionImplementation `class`
* This is an open ticket action implementation.
*
* It is a basic implementation of the `ODWorkerManager` used by all `ODAction` classes.
*
* This class can't be used stand-alone & needs to be extended from!
*/
export class ODActionImplementation<Source extends string,Params extends object,Result extends object> extends ODManagerData {
/**The manager that has all workers of this implementation */
workers: ODWorkerManager<object,Source,Params>
constructor(id:ODValidId, callback?:ODWorkerCallback<object,Source,Params>, priority?:number, callbackId?:ODValidId){
super(id)
this.workers = new ODWorkerManager("descending")
if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback))
}
/**Execute all workers & return the result. */
async run(source:Source, params:Params): Promise<Partial<Result>> {
throw new ODSystemError("Tried to build an unimplemented ODResponderImplementation")
}
}
/**## ODActionManager `class`
* This is an open ticket action manager.
*
* It contains all Open Ticket actions. You can compare actions with some sort of "procedure".
* It's a complicated task that is divided into multiple functions.
*
* Some examples are `ticket-creation`, `ticket-closing`, `ticket-claiming`, ...
*
* It's recommended to use this system in combination with Open Ticket responders!
*/
export class ODActionManager extends ODManager<ODAction<string,{},{}>> {
constructor(debug:ODDebugger){
super(debug,"action")
}
}
export class ODAction<Source extends string,Params extends object,Result extends object> extends ODActionImplementation<Source,Params,Result> {
/**Run this action */
async run(source:Source, params:Params): Promise<Partial<Result>> {
//create instance
const instance = {}
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
//return data generated by workers
return instance
}
}
+749
View File
@@ -0,0 +1,749 @@
///////////////////////////////////////
//BASE MODULE
///////////////////////////////////////
import * as fs from "fs"
import { ODConsoleWarningMessage, ODDebugger } from "./console"
/**## ODPromiseVoid `type`
* This is a simple type to represent a callback return value that could be a promise or not.
*/
export type ODPromiseVoid = void|Promise<void>
/**## ODValidButtonColor `type`
* This is a collection of all the possible button colors.
*/
export type ODValidButtonColor = "gray"|"red"|"green"|"blue"
/**## ODValidId `type`
* This is a valid open ticket identifier. It can be an `ODId` or `string`!
*
* You will see this type in many functions from open ticket.
*/
export type ODValidId = string|ODId
/**## ODValidJsonType `type`
* This is a collection of all types that can be stored in a JSON file!
*
* list: `string`, `number`, `boolean`, `array`, `object`, `null`
*/
export type ODValidJsonType = string|number|boolean|object|ODValidJsonType[]|null
/**## ODInterfaceWithPartialProperty `type`
* This is a utility type to create an interface where some properties are optional!
*/
export type ODInterfaceWithPartialProperty<Interface,Key extends keyof Interface> = Omit<Interface,Key> & Partial<Pick<Interface,Key>>
/**## ODId `class`
* This is an open ticket identifier.
*
* It can only contain the following characters: `a-z`, `A-Z`, `0-9`, `:`, `-` & `_`
*
* You will use this class to assign a unique id when creating configs, databases, languages & more!
* @example
* const id = new api.ODId("openticket:test-id") //this is valid
* const id = new api.ODId("example%id?") //this is invalid
*/
export class ODId {
/**The full value of this `ODId` as a `string` */
value: string
/**The source of the id (part before `:`). For example `openticket` for all built-in ids! */
source: string
/**The identifier of the id (part after `:`). */
identifier: string
constructor(id:ODValidId){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId")
if (typeof id == "string"){
//id is string
const result: string[] = []
const charregex = /[a-zA-Z0-9éèçàêâôûî\:\-\_]/
id.split("").forEach((char) => {
if (charregex.test(char)){
result.push(char)
}
})
if (result.length > 0) this.value = result.join("")
else throw new ODSystemError("invalid ID at 'new ODID(id: "+id+")'")
const splitted = this.value.split(":")
if (splitted.length > 1){
this.source = splitted[0]
splitted.shift()
this.identifier = splitted.join(":")
}else{
this.identifier = splitted.join(":")
this.source = ""
}
}else{
//id is ODId
this.value = id.value
this.source = id.source
this.identifier = id.identifier
}
}
/**Returns a string representation of this id. (same as `this.value`) */
toString(){
return this.value
}
}
/**## ODManagerChangeHelper `class`
* This is an open ticket manager change helper.
*
* It is used to let the "onChange" event in the `ODManager` class work.
* You will probably use this class when extending your own `ODManager`
*/
export class ODManagerChangeHelper {
#change: (() => void)|null = null
protected _change(){
if (this.#change){
try{
this.#change()
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Failed to execute _change() callback!")
}
}
}
/****(❌ SYSTEM ONLY!!)** Set the callback executed when a value inside this class changes */
changed(callback:(() => void)|null){
this.#change = callback
}
}
/**## ODManagerRedirectHelper `class`
* This is open ticket ticket manager redirect helper.
*
* It is used to redirect a source to another source when the id isn't found.
*
* It will be used in **Open Discord** to allow plugins from all projects to work seamlessly!
* ## **(❌ SYSTEM ONLY!!)**
*/
export class ODManagerRedirectHelper {
#data: {fromSource:string,toSource:string}[] = []
/****(❌ SYSTEM ONLY!!)** Add a redirect to this manager. Returns `true` when overwritten. */
add(fromSource:string, toSource:string){
const index = this.#data.findIndex((data) => data.fromSource === fromSource)
if (index > -1){
//already exists
this.#data[index] = {fromSource,toSource}
return true
}else{
//doesn't exist
this.#data.push({fromSource,toSource})
return false
}
}
/****(❌ SYSTEM ONLY!!)** Remove a redirect from this manager. Returns `true` when it existed. */
remove(fromSource:string, toSource:string){
const index = this.#data.findIndex((data) => data.fromSource === fromSource && data.toSource == toSource)
if (index > -1){
//already exists
this.#data.splice(index,1)
return true
}else return false
}
/**List all redirects from this manager. */
list(){
return [...this.#data]
}
}
/**## ODManagerData `class`
* This is open ticket manager data.
*
* It provides a template for all classes that are used in the `ODManager`.
*
* There is an `id:ODId` property & also some events used in the manager.
*/
export class ODManagerData extends ODManagerChangeHelper {
/**The id of this data */
id: ODId
constructor(id:ODValidId){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId")
super()
this.id = new ODId(id)
}
}
/**## ODManagerCallback `type`
* This is a callback for the `onChange` and `onRemove` events in the `ODManager`
*/
export type ODManagerCallback<DataType extends ODManagerData> = (data:DataType) => void
/**## ODManagerAddCallback `type`
* This is a callback for the `onAdd` event in the `ODManager`
*/
export type ODManagerAddCallback<DataType extends ODManagerData> = (data:DataType, overwritten:boolean) => void
/**## ODManager `class`
* This is an open ticket manager.
*
* It can be used to store & manage different aspects of the bot!
* You will probably to extend this class when creating your own classes & managers.
*
* This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists)
*/
export class ODManager<DataType extends ODManagerData> extends ODManagerChangeHelper {
/**Alias to open ticket debugger. */
#debug?: ODDebugger
/**The message to send when debugging this manager. */
#debugname?: string
/**An array storing all data classes ❌ **(don't edit unless really needed!)***/
#data: DataType[] = []
/**An array storing all listeners when data is added. */
#addListeners: ODManagerAddCallback<DataType>[] = []
/**An array storing all listeners when data has changed. */
#changeListeners: ODManagerCallback<DataType>[] = []
/**An array storing all listeners when data is removed. */
#removeListeners: ODManagerCallback<DataType>[] = []
/**Handle all redirects in this `ODManager` */
redirects: ODManagerRedirectHelper = new ODManagerRedirectHelper()
constructor(debug?:ODDebugger, debugname?:string){
super()
this.#debug = debug
this.#debugname = debugname
}
/**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data!*/
add(data:DataType|DataType[], overwrite?:boolean): boolean {
//repeat same command when data is an array
if (Array.isArray(data)){
data.forEach((arrayData) => {
this.add(arrayData,overwrite)
})
return false
}
//add data
const existIndex = this.#data.findIndex((d) => d.id.value === data.id.value)
if (existIndex < 0){
this.#data.push(data)
if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"false"}])
//change listeners
data.changed(() => {
//notify change in upper-manager (because data in this manager changed)
this._change()
this.#changeListeners.forEach((cb) => {
try{
cb(data)
}catch(err){
throw new ODSystemError("Failed to run manager onChange() listener.\n"+err)
}
})
})
//add listeners
this.#addListeners.forEach((cb) => {
try{
cb(data,false)
}catch(err){
throw new ODSystemError("Failed to run manager onAdd() listener.\n"+err)
}
})
//notify change in upper-manager (because data added)
this._change()
return false
}else{
if (!overwrite) throw new ODSystemError("Id '"+data.id.value+"' already exists in "+this.#debugname+" manager. Use 'overwrite:true' to allow overwriting!")
this.#data[existIndex] = data
if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"true"}])
//change listeners
data.changed(() => {
//notify change in upper-manager (because data in this manager changed)
this._change()
this.#changeListeners.forEach((cb) => {
try{
cb(data)
}catch(err){
throw new ODSystemError("Failed to run manager onChange() listener.\n"+err)
}
})
})
//add listeners
this.#addListeners.forEach((cb) => {
try{
cb(data,true)
}catch(err){
throw new ODSystemError("Failed to run manager onAdd() listener.\n"+err)
}
})
//notify change in upper-manager (because data added)
this._change()
return true
}
}
/**Get data that matches the `ODId`. Returns the found data.*/
get(id:ODValidId): DataType|null {
const newId = new ODId(id)
const d = this.#data.find((a) => a.id.value == newId.value)
if (d) return d
else{
const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source)
if (!redirect) return null
else{
const redirectId = new ODId(redirect.toSource+":"+newId.identifier)
return this.get(redirectId)
}
}
}
/**Remove data that matches the `ODId`. Returns the removed data.*/
remove(id:ODValidId): DataType|null {
const newId = new ODId(id)
const index = this.#data.findIndex((a) => a.id.value == newId.value)
if (index < 0){
const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source)
if (!redirect){
if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"false"}])
return null
}else{
const redirectId = new ODId(redirect.toSource+":"+newId.identifier)
return this.remove(redirectId)
}
}
if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"true"}])
const data = this.#data.splice(index,1)[0]
//change listeners
data.changed(null)
//remove listeners
this.#removeListeners.forEach((cb) => {
try{
cb(data)
}catch(err){
throw new ODSystemError("Failed to run manager onRemove() listener.\n"+err)
}
})
//notify change in upper-manager (because data removed)
this._change()
return data
}
/**Check if data that matches the `ODId` exists. Returns a boolean.*/
exists(id:ODValidId): boolean {
const newId = new ODId(id)
const d = this.#data.find((a) => a.id.value == newId.value)
if (d) return true
else{
const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source)
if (!redirect) return false
else{
const redirectId = new ODId(redirect.toSource+":"+newId.identifier)
return this.exists(redirectId)
}
}
}
/**Get all data inside this manager*/
getAll(): DataType[] {
return [...this.#data]
}
/**Get all data that matches inside the filter function*/
getFiltered(predicate:(value:DataType, index:number, array:DataType[]) => unknown): DataType[] {
return this.#data.filter(predicate)
}
/**Get all data that matches the regex*/
getRegex(regex:RegExp): DataType[] {
return this.#data.filter((data) => regex.test(data.id.value))
}
/**Get the length of the data inside this manager*/
getLength(){
return this.#data.length
}
/**Get a list of all the ids inside this manager*/
getIds(): ODId[] {
return this.#data.map((d) => d.id)
}
/**Use the open ticket debugger in this manager for logs*/
useDebug(debug?:ODDebugger, debugname?:string){
this.#debug = debug
this.#debugname = debugname
}
/**Listen for when data is added to this manager. */
onAdd(callback:ODManagerAddCallback<DataType>){
this.#addListeners.push(callback)
}
/**Listen for when data is changed in this manager. */
onChange(callback:ODManagerCallback<DataType>){
this.#changeListeners.push(callback)
}
/**Listen for when data is removed from this manager. */
onRemove(callback:ODManagerCallback<DataType>){
this.#removeListeners.push(callback)
}
}
/**## ODManagerWithSafety `class`
* This is an open ticket safe manager.
*
* It functions exactly the same as a normal `ODManager`, but it has 1 function extra!
* The `getSafe()` function will always return data, because when it doesn't find an id, it returns pre-configured backup data.
*/
export class ODManagerWithSafety<DataType extends ODManagerData> extends ODManager<DataType> {
/**The function that creates backup data returned in `getSafe()` when an id is missing in this manager. */
#backupCreator: () => DataType
/** Temporary storage for manager debug name. */
#debugname: string
constructor(backupCreator:() => DataType, debug?:ODDebugger, debugname?:string){
super(debug,debugname)
this.#backupCreator = backupCreator
this.#debugname = debugname ?? "unknown"
}
/**Get data that matches the `ODId`. Returns the backup data when not found.
*
* ### ⚠️ This should only be used when the data doesn't need to be written/edited
*/
getSafe(id:ODValidId): DataType {
const data = super.get(id)
if (!data){
process.emit("uncaughtException",new ODSystemError("ODManagerWithSafety:getSafe(\""+id+"\") => Unknown Id => Used backup data ("+this.#debugname+" manager)"))
return this.#backupCreator()
}
else return data
}
}
/**## ODVersionManager `class`
* A open ticket version manager.
*
* It is used to manage different `ODVersion`'s from the bot. You will use it to check which version of the bot is used.
*/
export class ODVersionManager extends ODManager<ODVersion> {
constructor(){
super()
}
}
/**## ODVersion `class`
* This is an open ticket version.
*
* It has many features like comparing versions & checking if they are compatible.
*
* You can use it in your own plugin, but most of the time you will use it to check the open ticket version!
*/
export class ODVersion extends ODManagerData {
/**The first number of the version (example: `v1.2.3` => `1`) */
primary: number
/**The second number of the version (example: `v1.2.3` => `2`) */
secondary: number
/**The third number of the version (example: `v1.2.3` => `3`) */
tertiary: number
constructor(id:ODValidId, primary:number, secondary:number, tertiary:number){
super(id)
if (typeof primary != "number") throw new ODSystemError("Invalid constructor parameter => primary:number")
if (typeof secondary != "number") throw new ODSystemError("Invalid constructor parameter => secondary:number")
if (typeof tertiary != "number") throw new ODSystemError("Invalid constructor parameter => tertiary:number")
this.primary = primary
this.secondary = secondary
this.tertiary = tertiary
}
/**Get the version from a string (also possible with `v` prefix)
* @example const version = api.ODVersion.fromString("id","v1.2.3") //creates version 1.2.3
*/
static fromString(id:ODValidId, version:string){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid function parameter => id:ODValidId")
if (typeof version != "string") throw new ODSystemError("Invalid function parameter => version:string")
const versionCheck = (version.startsWith("v")) ? version.substring(1) : version
const splittedVersion = versionCheck.split(".")
return new this(id,Number(splittedVersion[0]),Number(splittedVersion[1]),Number(splittedVersion[2]))
}
/**Get the version as a string (`noprefix:true` => with `v` prefix)
* @example
* new api.ODVersion(1,0,0).toString(false) //returns "v1.0.0"
* new api.ODVersion(1,0,0).toString(true) //returns "1.0.0"
*/
toString(noprefix?:boolean){
const prefix = noprefix ? "" : "v"
return prefix+[this.primary,this.secondary,this.tertiary].join(".")
}
/**Compare this version with another version and returns the result: `higher`, `lower` or `equal`
* @example
* new api.ODVersion(1,0,0).compare(new api.ODVersion(1,2,0)) //returns "lower"
* new api.ODVersion(1,3,0).compare(new api.ODVersion(1,2,0)) //returns "higher"
* new api.ODVersion(1,2,0).compare(new api.ODVersion(1,2,0)) //returns "equal"
*/
compare(comparator:ODVersion): "higher"|"lower"|"equal" {
if (!(comparator instanceof ODVersion)) throw new ODSystemError("Invalid function parameter => comparator:ODVersion")
if (this.primary < comparator.primary) return "lower"
else if (this.primary > comparator.primary) return "higher"
else {
if (this.secondary < comparator.secondary) return "lower"
else if (this.secondary > comparator.secondary) return "higher"
else {
if (this.tertiary < comparator.tertiary) return "lower"
else if (this.tertiary > comparator.tertiary) return "higher"
else return "equal"
}
}
}
/**Check if this version is included in the list
* @example
* const list = [
* new api.ODVersion(1,0,0),
* new api.ODVersion(1,0,1),
* new api.ODVersion(1,0,2)
* ]
* new api.ODVersion(1,0,0).compatible(list) //returns true
* new api.ODVersion(1,0,1).compatible(list) //returns true
* new api.ODVersion(1,0,3).compatible(list) //returns false
*/
compatible(list:ODVersion[]): boolean {
if (!Array.isArray(list)) throw new ODSystemError("Invalid function parameter => list:ODVersion[]")
if (!list.every((v) => (v instanceof ODVersion))) throw new ODSystemError("Invalid function parameter => list:ODVersion[]")
return list.some((v) => {
return (v.toString() === this.toString())
})
}
}
/**## ODHTTPGetRequest `class`
* This is a class that can help you with creating simple HTTP GET requests.
*
* It works using the native node.js fetch() method. You can configure all options in the constructor!
* @example
* const request = new api.ODHTTPGetRequest("https://www.example.com/abc.txt",false,{})
*
* const result = await request.run()
* result.body //the response body (string)
* result.status //the response code (number)
* result.response //the full response (object)
*/
export class ODHTTPGetRequest {
/**The url used in the request */
url: string
/**The request config for additional options */
config: RequestInit
/**Throw on error OR return http code 500 */
throwOnError: boolean
constructor(url:string,throwOnError:boolean,config?:RequestInit){
if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string")
if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean")
if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit")
this.url = url
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "GET"
this.config = newConfig
}
/**Execute the GET request.*/
run(): Promise<{status:number, body:string, response?:Response}> {
return new Promise(async (resolve,reject) => {
try{
const response = await fetch(this.url,this.config)
resolve({
status:response.status,
body:(await response.text()),
response:response
})
}catch(err){
if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPGetRequest => Unknown fetch() error: "+err)
else return resolve({
status:500,
body:"Open Ticket Error: Unknown fetch() error: "+err,
})
}
})
}
}
/**## ODHTTPPostRequest `class`
* This is a class that can help you with creating simple HTTP POST requests.
*
* It works using the native node.js fetch() method. You can configure all options in the constructor!
* @example
* const request = new api.ODHTTPPostRequest("https://www.example.com/abc.txt",false,{})
*
* const result = await request.run()
* result.body //the response body (string)
* result.status //the response code (number)
* result.response //the full response (object)
*/
export class ODHTTPPostRequest {
/**The url used in the request */
url: string
/**The request config for additional options */
config: RequestInit
/**Throw on error OR return http code 500 */
throwOnError: boolean
constructor(url:string,throwOnError:boolean,config?:RequestInit){
if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string")
if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean")
if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit")
this.url = url
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "POST"
this.config = newConfig
}
/**Execute the POST request.*/
run(): Promise<{status:number, body:string, response?:Response}> {
return new Promise(async (resolve,reject) => {
try{
const response = await fetch(this.url,this.config)
resolve({
status:response.status,
body:(await response.text()),
response:response
})
}catch(err){
if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPPostRequest => Unknown fetch() error: "+err)
else return resolve({
status:500,
body:"Open Ticket Error: Unknown fetch() error!",
})
}
})
}
}
/**## ODEnvHelper `class`
* This is a utility class that helps you with reading the ENV.
*
* It has support for the built-in `process.env` & `.env` file
* @example
* const envHelper = new api.ODEnvHelper()
*
* const variableA = envHelper.getVariable("value-a")
* const variableB = envHelper.getVariable("value-b","dotenv") //only get from .env
* const variableA = envHelper.getVariable("value-c","env") //only get from process.env
*/
export class ODEnvHelper {
/**All variables found in the `.env` file */
dotenv: object
/**All variables found in `process.env` */
env: object
constructor(customEnvPath?:string){
if (typeof customEnvPath != "undefined" && typeof customEnvPath != "string") throw new ODSystemError("Invalid constructor parameter => customEnvPath?:string")
const path = customEnvPath ? customEnvPath : ".env"
this.dotenv = fs.existsSync(path) ? this.#readDotEnv(fs.readFileSync(path)) : {}
this.env = process.env
}
/**Get a variable from the env */
getVariable(name:string,source?:"dotenv"|"env"): any|undefined {
if (typeof name != "string") throw new ODSystemError("Invalid function parameter => name:string")
if ((typeof source != "undefined" && typeof source != "string") || (source && !["env","dotenv"].includes(source))) throw new ODSystemError("Invalid function parameter => source:'dotenv'|'env'")
if (source == "dotenv"){
return this.dotenv[name]
}else if (source == "env"){
return this.env[name]
}else{
//when no source specified => .env has priority over process.env
if (this.dotenv[name]) return this.dotenv[name]
else return this.env[name]
}
}
//THIS CODE IS COPIED FROM THE DODENV-LIB
//Repo: https://github.com/motdotla/dotenv
//Source: https://github.com/motdotla/dotenv/blob/master/lib/main.js#L12
#readDotEnv(src:Buffer){
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
const obj = {}
// Convert buffer to string
let lines = src.toString()
// Convert line breaks to same format
lines = lines.replace(/\r\n?/mg, '\n')
let match
while ((match = LINE.exec(lines)) != null) {
const key = match[1]
// Default undefined or null to empty string
let value = (match[2] || '')
// Remove whitespace
value = value.trim()
// Check if double quoted
const maybeQuote = value[0]
// Remove surrounding quotes
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
// Expand newlines if double quoted
if (maybeQuote === '"') {
value = value.replace(/\\n/g, '\n')
value = value.replace(/\\r/g, '\r')
}
// Add to object
obj[key] = value
}
return obj
}
}
/**## ODSystemError `class`
* A wrapper for the node.js `Error` class that makes the error look better in the console!
*
* This wrapper is made for open ticket system errors! **It can only be used by open ticket itself!**
*/
export class ODSystemError extends Error {
/**This variable gets detected by the error handling system to know how to render it */
_ODErrorType = "system"
/**Create an `ODSystemError` directly from an `Error` class */
static fromError(err:Error){
err["_ODErrorType"] = "system"
return err as ODSystemError
}
}
/**## ODPluginError `class`
* A wrapper for the node.js `Error` class that makes the error look better in the console!
*
* This wrapper is made for open ticket plugin errors! **It can only be used by plugins!**
*/
export class ODPluginError extends Error {
/**This variable gets detected by the error handling system to know how to render it */
_ODErrorType = "plugin"
/**Create an `ODPluginError` directly from an `Error` class */
static fromError(err:Error){
err["_ODErrorType"] = "plugin"
return err as ODPluginError
}
}
/**Oh, what could this be `¯\_(ツ)_/¯` */
export interface ODEasterEggs {
creator:string,
translators:string[]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+55
View File
@@ -0,0 +1,55 @@
///////////////////////////////////////
//CODE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
/**## ODCode `class`
* This is an open ticket code runner.
*
* It is just a function that will run just before the bot has started completely!
* This can be used for code that needs to run at startup, but isn't really time dependent.
*
* - It has an `id` for identification of the function
* - A `priority` to know when to execute this function (related to others)
*/
export class ODCode extends ODManagerData {
/**The priority of this code */
priority: number
/**The main function of this code */
func: () => void|Promise<void>
constructor(id:ODValidId, priority:number, func:() => void|Promise<void>){
super(id)
this.priority = priority
this.func = func
}
}
/**## ODCodeManager `class`
* This is an open ticket code manager.
*
* It manages & executes `ODCode`'s in the correct order.
*
* You will probably register a function/code in this class for something that doesn't really need to be timed.
*/
export class ODCodeManager extends ODManager<ODCode> {
constructor(debug:ODDebugger){
super(debug,"code")
}
/**Execute all functions or code. */
async execute(){
const derefArray = [...this.getAll()]
const workers = derefArray.sort((a,b) => b.priority-a.priority)
for (const worker of workers){
try {
await worker.func()
}catch(err){
process.emit("uncaughtException",err)
}
}
}
}
+96
View File
@@ -0,0 +1,96 @@
///////////////////////////////////////
//CONFIG MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base"
import nodepath from "path"
import { ODDebugger } from "./console"
/**## ODConfigManager `class`
* This is an open ticket config manager.
*
* It manages all config files in the bot and allows plugins to access config files from open ticket & other plugins!
*
* You will use this class to get/add a config file (`ODConfig`) in your plugin!
* @example
* //get ./config/general.json => ODConfig class
* const generalConfig = openticket.configs.get("openticket:general")
*
* //add a new config with id "test" => ./config/test.json
* const testConfig = new api.ODConfig("test","test.json")
* openticket.configs.add(testConfig)
*/
export class ODConfigManager extends ODManager<ODConfig> {
constructor(debug:ODDebugger){
super(debug,"config")
}
/**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data!
* @example
* //add a new config with id "test" => ./config/test.json
* const testConfig = new api.ODConfig("test","test.json")
* openticket.configs.add(testConfig)
*/
add(data:ODConfig, overwrite?:boolean): boolean {
return super.add(data,overwrite)
}
/**Get data that matches the `ODId`. Returns the found data.
* @example
* //get "./config/general.json" (ot-general) => ODConfig class
* const generalConfig = openticket.configs.get("openticket:general")
*/
get(id:ODValidId): ODConfig|null {
return super.get(id)
}
/**Remove data that matches the `ODId`. Returns the removed data.
* @example
* //remove the "test" config
* openticket.configs.remove("test") //returns null if non-existing
*/
remove(id:ODValidId): ODConfig|null {
return super.remove(id)
}
/**Check if data that matches the `ODId` exists. Returns a boolean.
* @example
* //check if "./config/general.json" (ot-general) exists => boolean
* const exists = openticket.configs.exists("openticket:general")
*/
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODConfig `class`
* This is an open ticket config helper.
* This class doesn't do anything at all, it just gives a template & basic methods for a config. Use `ODJsonConfig` instead!
*
* You will only use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)!
*/
export class ODConfig extends ODManagerData {
/**The full path to this config with extension */
file: string = ""
/**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */
data: any = undefined
}
/**## ODJsonConfig `class`
* This is an open ticket config helper.
* You will use this class to get & edit variables from the config files or to create your own config!
* @example
* //create a config from: ./config/test.json with the id "some-config"
* const config = new api.ODJsonConfig("some-config","test.json")
*
* //create a config with custom dir: ./plugins/testplugin/test.json
* const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/")
*/
export class ODJsonConfig extends ODConfig {
constructor(id:ODValidId, file:string, customPath?:string){
super(id)
try {
const filename = (file.endsWith(".json")) ? file : file+".json"
this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./config/",filename)
this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../config",filename))
}catch{
throw new ODSystemError("config \""+nodepath.join("./",customPath ?? "",file)+"\" doesn't exist!")
}
}
}
+663
View File
@@ -0,0 +1,663 @@
///////////////////////////////////////
//CONSOLE MODULE
///////////////////////////////////////
import { ODHTTPGetRequest, ODVersion, ODSystemError, ODPluginError, ODManager, ODManagerData, ODValidId } from "./base"
import { ODMain } from "../main"
import nodepath from "path"
import fs from "fs"
import ansis from "ansis"
/**## ODValidConsoleColor `type`
* This is a collection of all the supported console colors within Open Ticket.
*/
export type ODValidConsoleColor = "white"|"red"|"yellow"|"green"|"blue"|"gray"|"cyan"|"magenta"
/**## ODConsoleMessageParam `type`
* This interface contains all data required for a console log parameter within Open Ticket.
*/
export interface ODConsoleMessageParam {
/**The key of this parameter. */
key:string,
/**The value of this parameter. */
value:string,
/**When enabled, this parameter will only be shown in the debug file. */
hidden?:boolean
}
/**## ODConsoleMessage `class`
* This is an open ticket console message.
*
* It is used to create beautiful & styled logs in the console with a prefix, message & parameters.
* It also has full color support using `ansis` and parameters are parsed for you!
*/
export class ODConsoleMessage {
/**The main message sent in the console */
message: string
/**An array of all the parameters in this message */
params: ODConsoleMessageParam[]
/**The prefix of this message (!uppercase recommended!) */
prefix: string
/**The color of the prefix of this message */
color: ODValidConsoleColor
constructor(message:string, prefix:string, color:ODValidConsoleColor, params?:ODConsoleMessageParam[]){
this.message = message
this.params = params ? params : []
this.prefix = prefix
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
this.color = color
}else{
this.color = "white"
}
}
/**Render this message to the console using `console.log`! Returns `false` when something went wrong. */
render(){
try {
const prefixcolor = ansis[this.color]
const paramsstring = " "+this.createParamsString("gray")
const message = prefixcolor("["+this.prefix+"] ")+this.message
console.log(message+paramsstring)
return true
}catch{
return false
}
}
/**Create a more-detailed, non-colored version of this message to store it in the `otdebug.txt` file! */
toDebugString(){
const pstrings: string[] = []
this.params.forEach((p) => {
pstrings.push(p.key+": "+p.value)
})
const pstring = (pstrings.length > 0) ? " ("+pstrings.join(", ")+")" : ""
const date = new Date()
const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
return `[${dstring} ${this.prefix}] ${this.message}${pstring}`
}
/**Render the parameters of this message in a specific color. */
createParamsString(color:ODValidConsoleColor){
let validcolor: ODValidConsoleColor = "white"
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
validcolor = color
}
const pstrings: string[] = []
this.params.forEach((p) => {
if (!p.hidden) pstrings.push(p.key+": "+p.value)
})
return (pstrings.length > 0) ? ansis[validcolor](" ("+pstrings.join(", ")+")") : ""
}
/**Set the message */
setMessage(message:string){
this.message = message
return this
}
/**Set the params */
setParams(params:ODConsoleMessageParam[]){
this.params = params
return this
}
/**Set the prefix */
setPrefix(prefix:string){
this.prefix = prefix
return this
}
/**Set the prefix color */
setColor(color:ODValidConsoleColor){
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
this.color = color
}else{
this.color = "white"
}
return this
}
}
/**## ODConsoleInfoMessage `class`
* This is an open ticket console info message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "INFO" messages!
*/
export class ODConsoleInfoMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"INFO","blue",params)
}
}
/**## ODConsoleSystemMessage `class`
* This is an open ticket console system message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "SYSTEM" messages!
*/
export class ODConsoleSystemMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"SYSTEM","green",params)
}
}
/**## ODConsolePluginMessage `class`
* This is an open ticket console plugin message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "PLUGIN" messages!
*/
export class ODConsolePluginMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"PLUGIN","magenta",params)
}
}
/**## ODConsoleDebugMessage `class`
* This is an open ticket console debug message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "DEBUG" messages!
*/
export class ODConsoleDebugMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"DEBUG","cyan",params)
}
}
/**## ODConsoleWarningMessage `class`
* This is an open ticket console warning message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "WARNING" messages!
*/
export class ODConsoleWarningMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"WARNING","yellow",params)
}
}
/**## ODConsoleErrorMessage `class`
* This is an open ticket console error message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "ERROR" messages!
*/
export class ODConsoleErrorMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"ERROR","red",params)
}
}
/**## ODError `class`
* This is an open ticket error.
*
* It is used to render and log Node.js errors & crashes in a styled way to the console & `otdebug.txt` file!
*/
export class ODError {
/**The original error that this class wraps around */
error: Error|ODSystemError|ODPluginError
/**The origin of the original error */
origin: NodeJS.UncaughtExceptionOrigin
constructor(error:Error|ODSystemError|ODPluginError, origin:NodeJS.UncaughtExceptionOrigin){
this.error = error
this.origin = origin
}
/**Render this error to the console using `console.log`! Returns `false` when something went wrong. */
render(){
try {
let prefix = (this.error["_ODErrorType"] == "plugin") ? "PLUGIN ERROR" : ((this.error["_ODErrorType"] == "system") ? "OPENTICKET ERROR" : "UNKNOWN ERROR")
//title
console.log(ansis.red("["+prefix+"]: ")+this.error.message+" | origin: "+this.origin)
//stack trace
if (this.error.stack) console.log(ansis.gray(this.error.stack))
//additional message
if (this.error["_ODErrorType"] == "plugin") console.log(ansis.red.bold("\nPlease report this error to the plugin developer and help us create a more stable plugin!"))
else console.log(ansis.red.bold("\nPlease report this error to our discord server and help us create a more stable ticket bot!"))
console.log(ansis.red("Also send the "+ansis.cyan.bold("otdebug.txt")+" file! It would help a lot!\n"))
return true
}catch{
return false
}
}
/**Create a more-detailed, non-colored version of this error to store it in the `otdebug.txt` file! */
toDebugString(){
return "[UNKNOWN OD ERROR]: "+this.error.message+" | origin: "+this.origin+"\n"+this.error.stack
}
}
/**## ODConsoleMessageTypes `type`
* This is a collection of all the default console message types within Open Ticket.
*/
export type ODConsoleMessageTypes = "info"|"system"|"plugin"|"debug"|"warning"|"error"
/**## ODConsoleManager `class`
* This is the open ticket console manager.
*
* It handles the entire console system of Open Ticket. It's also the place where you need to log `ODConsoleMessage`'s.
* This manager keeps a short history of messages sent to the console which is configurable by plugins.
*
* The debug file (`otdebug.txt`) is handled in a sub-manager!
*/
export class ODConsoleManager {
/**The history of `ODConsoleMessage`'s and `ODError`'s since startup */
history: (ODConsoleMessage|ODError)[] = []
/**The max length of the history. The oldest messages will be removed when over the limit */
historylength = 100
/**An alias to the debugfile manager. (`otdebug.txt`) */
debugfile: ODDebugFileManager
constructor(historylength:number, debugfile:ODDebugFileManager){
this.historylength = historylength
this.debugfile = debugfile
}
/**Log a message to the console ... But in the Open Ticket way :) */
log(message:ODConsoleMessage): void
log(message:ODError): void
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
if (message instanceof ODConsoleMessage){
message.render()
if (this.debugfile) this.debugfile.writeConsoleMessage(message)
this.history.push(message)
}else if (message instanceof ODError){
message.render()
if (this.debugfile) this.debugfile.writeErrorMessage(message)
this.history.push(message)
}else if (["string","number","boolean","object"].includes(typeof message)){
let newMessage: ODConsoleMessage
if (type == "info") newMessage = new ODConsoleInfoMessage(message,params)
else if (type == "system") newMessage = new ODConsoleSystemMessage(message,params)
else if (type == "plugin") newMessage = new ODConsolePluginMessage(message,params)
else if (type == "debug") newMessage = new ODConsoleDebugMessage(message,params)
else if (type == "warning") newMessage = new ODConsoleWarningMessage(message,params)
else if (type == "error") newMessage = new ODConsoleErrorMessage(message,params)
else newMessage = new ODConsoleSystemMessage(message,params)
newMessage.render()
if (this.debugfile) this.debugfile.writeConsoleMessage(newMessage)
this.history.push(newMessage)
}
this.#purgeHistory()
}
/**Shorten the history when it exceeds the max history length! */
#purgeHistory(){
if (this.history.length > this.historylength) this.history.shift()
}
}
/**## ODDebugFileManager `class`
* This is the open ticket debug file manager.
*
* It manages the Open Ticket debug file (`otdebug.txt`) which keeps a history of all system logs.
* There are even internal logs that aren't logged to the console which are available in this file!
*
* Using this class, you can change the max length of this file and some other cool things!
*/
export class ODDebugFileManager {
/**The path to the debugfile (`./otdebug.txt` by default) */
path: string
/**The filename of the debugfile (`otdebug.txt` by default) */
filename: string
/**The current version of the bot used in the debug file. */
version: ODVersion
/**The max length of the debug file. */
maxlines: number
constructor(path:string, filename:string, maxlines:number, version:ODVersion){
this.path = nodepath.join(path,filename)
this.filename = filename
this.version = version
this.maxlines = maxlines
this.#writeStartupStats()
}
/**Check if the debug file exists */
#existsDebugFile(){
return fs.existsSync(this.path)
}
/**Read from the debug file */
#readDebugFile(){
if (this.#existsDebugFile()){
try {
return fs.readFileSync(this.path).toString()
}catch{
return false
}
}else{
return false
}
}
/**Write to the debug file and shorten it when needed. */
#writeDebugFile(text:string){
const currenttext = this.#readDebugFile()
if (currenttext){
const splitted = currenttext.split("\n")
if (splitted.length+text.split("\n").length > this.maxlines){
splitted.splice(7,(text.split("\n").length))
}
splitted.push(text)
fs.writeFileSync(this.path,splitted.join("\n"))
}else{
//write new file:
const newtext = this.#createStatsText()+text
fs.writeFileSync(this.path,newtext)
}
}
/**Generate the stats/header of the debug file (containing the version) */
#createStatsText(){
const date = new Date()
const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
return [
"=========================",
"OPEN TICKET DEBUG FILE:",
"version: "+this.version.toString(),
"last startup: "+dstring,
"=========================\n\n"
].join("\n")
}
/**Write the stats/header to the debug file on startup */
#writeStartupStats(){
const currenttext = this.#readDebugFile()
if (currenttext){
//edit previous file:
const splitted = currenttext.split("\n")
splitted.splice(0,7)
if (splitted.length+11 > this.maxlines){
splitted.splice(0,((splitted.length+11) - this.maxlines))
}
splitted.unshift(this.#createStatsText())
splitted.push("\n---------------------------------------------------------------------\n---------------------------------------------------------------------\n")
fs.writeFileSync(this.path,splitted.join("\n"))
}else{
//write new file:
const newtext = this.#createStatsText()
fs.writeFileSync(this.path,newtext)
}
}
/**Write an `ODConsoleMessage` to the debug file */
writeConsoleMessage(message:ODConsoleMessage){
this.#writeDebugFile(message.toDebugString())
}
/**Write an `ODError` to the debug file */
writeErrorMessage(error:ODError){
this.#writeDebugFile(error.toDebugString())
}
/**Write custom text to the debug file */
writeText(text:string){
this.#writeDebugFile(text)
}
/**Write a custom note to the debug file (starting with `[NODE]:`) */
writeNote(text:string){
this.#writeDebugFile("[NODE]: "+text)
}
}
/**## ODDebugger `class`
* This is the open ticket debugger.
*
* It is a simple wrapper around the `ODConsoleManager` to handle debugging (primarily for `ODManagers`).
* Messages created using this debugger are only logged to the debug file unless specified otherwise.
*
* You will probably notice this class being used in the `ODManager` constructor.
*
* Using this system, all additions & removals inside a manager are logged to the debug file. This makes searching for errors a lot easier!
*/
export class ODDebugger {
/**An alias to the open ticket console manager. */
console: ODConsoleManager
/**When enabled, debug logs are also shown in the console. */
visible: boolean = false
constructor(console:ODConsoleManager){
this.console = console
}
/**Create a debug message. This will always be logged to `otdebug.txt` & sometimes to the console (when enabled). Returns `true` when visible */
debug(message:string, params?:{key:string,value:string}[]): boolean {
if (this.visible){
this.console.log(new ODConsoleDebugMessage(message,params))
return true
}else{
this.console.debugfile.writeConsoleMessage(new ODConsoleDebugMessage(message,params))
return false
}
}
}
/**## ODLivestatusColor `type`
* This is a collection of all the colors available within the LiveStatus system.
*/
export type ODLiveStatusColor = "normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"
/**## ODLiveStatusSourceData `interface`
* This is an interface containing all raw data received from the LiveStatus system.
*/
export interface ODLiveStatusSourceData {
/**The message to display */
message:{
/**The title of the message to display */
title:string,
/**The title color of the message to display */
titleColor:ODLiveStatusColor,
/**The description of the message to display */
description:string,
/**The description color of the message to display */
descriptionColor:ODLiveStatusColor
},
/**The message will only be shown when the bot matches all statements */
active:{
/**A list of versions to match */
versions:string[],
/**A list of languages to match */
languages:string[],
/**All languages should match */
allLanguages:boolean,
/**Match when the bot is using plugins */
usingPlugins:boolean,
/**Match when the bot is not using plugins */
notUsingPlugins:boolean,
/**Match when the bot is using slash commands */
usingSlashCommands:boolean,
/**Match when the bot is not using slash commands */
notUsingSlashCommands:boolean,
/**Match when the bot is not using transcripts */
notUsingTranscripts:boolean,
/**Match when the bot is using text transcripts */
usingTextTranscripts:boolean,
/**Match when the bot is using html transcripts */
usingHtmlTranscripts:boolean
}
}
/**## ODLiveStatusSource `class`
* This is the open ticket livestatus source.
*
* It is an empty template for a livestatus source.
* By default, you should use `ODLiveStatusUrlSource` or `ODLiveStatusFileSource`,
* unless you want to create one on your own!
*
* This class doesn't do anything on it's own! It's just a template!
*/
export class ODLiveStatusSource extends ODManagerData {
/**The raw data of this source */
data: ODLiveStatusSourceData[]
constructor(id:ODValidId, data:ODLiveStatusSourceData[]){
super(id)
this.data = data
}
/**Change the current data using this method! */
setData(data:ODLiveStatusSourceData[]){
this.data = data
}
/**Get all messages relevant to the bot based on some parameters. */
async getMessages(main:ODMain): Promise<ODLiveStatusSourceData[]> {
const validMessages: ODLiveStatusSourceData[] = []
//parse data from ODMain
const currentVersion: string = main.versions.get("openticket:version").toString(true)
const usingSlashCommands: boolean = main.configs.get("openticket:general").data.slashCommands
const usingTranscripts: false|"text"|"html" = false as false|"text"|"html" //TODO
const currentLanguage: string = main.languages.getCurrentLanguageId()
const usingPlugins: boolean = (main.plugins.getLength() > 0)
//check data for each message
this.data.forEach((msg) => {
const {active} = msg
const correctVersion = active.versions.includes(currentVersion)
const correctSlashMode = (usingSlashCommands && active.usingSlashCommands) || (!usingSlashCommands && active.notUsingSlashCommands)
const correctTranscriptMode = (usingTranscripts == "text" && active.usingTextTranscripts) || (usingTranscripts == "html" && active.usingHtmlTranscripts) || (!usingTranscripts && active.notUsingTranscripts)
const correctLanguage = active.languages.includes(currentLanguage) || active.allLanguages
const correctPlugins = (usingPlugins && active.usingPlugins) || (!usingPlugins && active.notUsingPlugins)
if (correctVersion && correctLanguage && correctPlugins && correctSlashMode && correctTranscriptMode) validMessages.push(msg)
})
//return the valid messages
return validMessages
}
}
/**## ODLiveStatusFileSource `class`
* This is the open ticket livestatus file source.
*
* It is a LiveStatus source that will read the data from a local file.
*
* This can be used for testing/extending the LiveStatus system!
*/
export class ODLiveStatusFileSource extends ODLiveStatusSource {
/**The path to the source file */
path: string
constructor(id:ODValidId, path:string){
if (fs.existsSync(path)){
super(id,JSON.parse(fs.readFileSync(path).toString()))
}else throw new ODSystemError("LiveStatus source file doesn't exist!")
this.path = path
}
}
/**## ODLiveStatusUrlSource `class`
* This is the open ticket livestatus url source.
*
* It is a LiveStatus source that will read the data from a http URL (json file).
*
* This is the default way of receiving LiveStatus messages!
*/
export class ODLiveStatusUrlSource extends ODLiveStatusSource {
/**The url used in the request */
url: string
/**The `ODHTTPGetRequest` helper to fetch the url! */
request: ODHTTPGetRequest
constructor(id:ODValidId, url:string){
super(id,[])
this.url = url
this.request = new ODHTTPGetRequest(url,false)
}
async getMessages(main:ODMain): Promise<ODLiveStatusSourceData[]> {
//additional setup
this.request.url = this.url
const rawRes = await this.request.run()
if (rawRes.status != 200) throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!")
try{
this.setData(JSON.parse(rawRes.body))
}catch{
throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!")
}
//default
return super.getMessages(main)
}
}
/**## ODLiveStatusManager `class`
* This is the open ticket livestatus manager.
*
* It manages all LiveStatus sources and has the renderer for all LiveStatus messages.
*
* You will probably use this to customise or add stuff to the LiveStatus system.
* Access it in the global `openticket.startscreen.livestatus` variable!
*/
export class ODLiveStatusManager extends ODManager<ODLiveStatusSource> {
/**The class responsible for rendering the livestatus messages. */
renderer: ODLiveStatusRenderer
/**A reference to the ODMain or "openticket" global variable */
#main: ODMain
constructor(debug:ODDebugger, main:ODMain){
super(debug,"livestatus source")
this.renderer = new ODLiveStatusRenderer(main.console)
this.#main = main
}
/**Get the messages from all sources combined! */
async getAllMessages(): Promise<ODLiveStatusSourceData[]> {
const messages: ODLiveStatusSourceData[] = []
for (const source of this.getAll()){
try {
messages.push(...(await source.getMessages(this.#main)))
}catch{}
}
return messages
}
}
/**## ODLiveStatusRenderer `class`
* This is the open ticket livestatus renderer.
*
* It's responsible for rendering all LiveStatus messages to the console.
*/
export class ODLiveStatusRenderer {
/**A reference to the ODConsoleManager or "openticket.console" global variable */
#console: ODConsoleManager
constructor(console:ODConsoleManager){
this.#console = console
}
/**Render all messages */
render(messages:ODLiveStatusSourceData[]): string {
try {
//process data
const final: string[] = []
messages.forEach((msg) => {
const titleColor = msg.message.titleColor
const title = "["+msg.message.title+"] "
const descriptionColor = msg.message.descriptionColor
const description = msg.message.description.split("\n").map((text,row) => {
//first row row doesn't need prefix
if (row < 1) return text
//other rows do need a prefix
let text2 = text
for (const i of title){
text2 = " "+text2
}
return text2
}).join("\n")
if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(titleColor)) var finalTitle = ansis.white(title)
else var finalTitle = ansis[titleColor](title)
if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(descriptionColor)) var finalDescription = ansis.white(description)
else var finalDescription = ansis[descriptionColor](description)
final.push(finalTitle+finalDescription)
})
//return all messages
return final.join("\n")
}catch{
this.#console.log("Failed to render LiveStatus messages!","error")
return ""
}
}
}
+348
View File
@@ -0,0 +1,348 @@
///////////////////////////////////////
//COOLDOWN MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base"
import { ODDebugger } from "./console"
/**## ODCooldownManager `class`
* This is an open ticket cooldown manager.
*
* It is responsible for managing all cooldowns in Open Ticket. An example of this is the ticket creation cooldown.
*
* There are many types of cooldowns available, but you can also create your own!
*/
export class ODCooldownManager extends ODManager<ODCooldown<object>> {
constructor(debug:ODDebugger){
super(debug,"cooldown")
}
/**Initiate all cooldowns in this manager. */
async init(){
for (const cooldown of this.getAll()){
await cooldown.init()
}
}
}
/**## ODCooldownData `class`
* This is open ticket cooldown data.
*
* It contains the instance of an active cooldown (e.g. for a user). It is handled by the cooldown itself.
*/
export class ODCooldownData<Data extends object> extends ODManagerData {
/**Is this cooldown active? */
active: boolean
/**Additional data of this cooldown instance. (different for each cooldown type) */
data: Data
constructor(id:ODValidId,active:boolean,data:Data){
super(id)
this.active = active
this.data = data
}
}
/**## ODCooldown `class`
* This is an open ticket cooldown.
*
* It doesn't do anything on it's own, but it provides the methods that are used to interact with a cooldown.
* This class can be extended from to create a working cooldown.
*
* There are also premade cooldowns available in the bot!
*/
export class ODCooldown<Data extends object> extends ODManagerData {
data: ODManager<ODCooldownData<Data>> = new ODManager()
/**Is this cooldown already initialized? */
ready: boolean = false
constructor(id:ODValidId){
super(id)
}
/**Check this id and start cooldown when it exeeds the limit! Returns `true` when on cooldown! */
use(id:string): boolean {
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Check this id without starting or updating the cooldown. Returns `true` when on cooldown! */
check(id:string): boolean {
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Remove the cooldown for an id when available.*/
delete(id:string){
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Initialize the internal systems of this cooldown. */
async init(){
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
}
/**## ODCounterCooldown `class`
* This is an open ticket counter cooldown.
*
* It is is a cooldown based on a counter. When the number exceeds the limit, the cooldown is activated.
* The number will automatically be decreased with a set amount & interval.
*/
export class ODCounterCooldown extends ODCooldown<{value:number}> {
/**The cooldown will activate when exceeding this limit. */
activeLimit: number
/**The cooldown will deactivate when below this limit. */
cancelLimit: number
/**The amount to increase the counter with everytime the cooldown is triggered/updated. */
increment: number
/**The amount to decrease the counter over time. */
decrement: number
/**The interval between decrements in milliseconds. */
invervalMs: number
constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){
super(id)
this.activeLimit = activeLimit
this.cancelLimit = cancelLimit
this.increment = increment
this.decrement = decrement
this.invervalMs = intervalMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if (cooldown.active){
return true
}else if (cooldown.data.value < this.activeLimit){
cooldown.data.value = cooldown.data.value + this.increment
return false
}else{
cooldown.active = true
return false
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{
value:this.increment
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return cooldown.active
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
async init(){
if (this.ready) return
setInterval(() => {
this.data.getAll().forEach((cooldown) => {
cooldown.data.value = cooldown.data.value - this.decrement
if (cooldown.data.value <= this.cancelLimit){
cooldown.active = false
}
if (cooldown.data.value <= 0){
this.data.remove(cooldown.id)
}
})
},this.invervalMs)
this.ready = true
}
}
/**## ODIncrementalCounterCooldown `class`
* This is an open ticket incremental counter cooldown.
*
* It is is a cooldown based on an incremental counter. It is exactly the same as the normal counter,
* with the only difference being that it still increments when the limit is already exeeded.
*/
export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> {
/**The cooldown will activate when exceeding this limit. */
activeLimit: number
/**The cooldown will deactivate when below this limit. */
cancelLimit: number
/**The amount to increase the counter with everytime the cooldown is triggered/updated. */
increment: number
/**The amount to decrease the counter over time. */
decrement: number
/**The interval between decrements in milliseconds. */
invervalMs: number
constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){
super(id)
this.activeLimit = activeLimit
this.cancelLimit = cancelLimit
this.increment = increment
this.decrement = decrement
this.invervalMs = intervalMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if (cooldown.active){
cooldown.data.value = cooldown.data.value + this.increment
return true
}else if (cooldown.data.value < this.activeLimit){
cooldown.data.value = cooldown.data.value + this.increment
return false
}else{
cooldown.active = true
return false
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{
value:this.increment
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return cooldown.active
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
async init(){
if (this.ready) return
setInterval(() => {
this.data.getAll().forEach((cooldown) => {
cooldown.data.value = cooldown.data.value - this.decrement
if (cooldown.data.value <= this.cancelLimit){
cooldown.active = false
}
if (cooldown.data.value <= 0){
this.data.remove(cooldown.id)
}
})
},this.invervalMs)
this.ready = true
}
}
/**## ODTimeoutCooldown `class`
* This is an open ticket timeout cooldown.
*
* It is a cooldown based on a timer. When triggered/updated, the cooldown is activated for the set amount of time.
* After the timer has timed out, the cooldown will be deleted.
*/
export class ODTimeoutCooldown extends ODCooldown<{date:number}> {
/**The amount of milliseconds before the cooldown times-out */
timeoutMs: number
constructor(id:ODValidId, timeoutMs:number){
super(id)
this.timeoutMs = timeoutMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){
this.data.remove(id)
return false
}else{
return true
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,true,{
date:new Date().getTime()
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return true
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
/**Get the remaining amount of milliseconds before the timeout stops. */
remaining(id:string): number|null {
const cooldown = this.data.get(id)
if (!cooldown) return null
const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date)
return (rawResult > 0) ? rawResult : 0
}
async init(){
if (this.ready) return
this.ready = true
}
}
/**## ODIncrementalTimeoutCooldown `class`
* This is an open ticket incremental timeout cooldown.
*
* It is is a cooldown based on an incremental timer. It is exactly the same as the normal timer,
* with the only difference being that it adds additional time when triggered/updated while the cooldown is already active.
*/
export class ODIncrementalTimeoutCooldown extends ODCooldown<{date:number}> {
/**The amount of milliseconds before the cooldown times-out */
timeoutMs: number
/**The amount of milliseconds to add when triggered/updated while the cooldown is already active. */
incrementMs: number
constructor(id:ODValidId, timeoutMs:number, incrementMs:number){
super(id)
this.timeoutMs = timeoutMs
this.incrementMs = incrementMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){
this.data.remove(id)
return false
}else{
cooldown.data.date = cooldown.data.date + this.incrementMs
return true
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,true,{
date:new Date().getTime()
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return true
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
/**Get the remaining amount of milliseconds before the timeout stops. */
remaining(id:string): number|null {
const cooldown = this.data.get(id)
if (!cooldown) return null
const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date)
return (rawResult > 0) ? rawResult : 0
}
async init(){
if (this.ready) return
this.ready = true
}
}
+316
View File
@@ -0,0 +1,316 @@
///////////////////////////////////////
//DATABASE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base"
import fs from "fs"
import nodepath from "path"
import { ODDebugger } from "./console"
import * as fjs from "formatted-json-stringify"
/**## ODDatabaseManager `class`
* This is an open ticket database manager.
*
* It manages all databases in the bot and allows to permanently store data from the bot!
*
* You will use this class to get/add a database (`ODDatabase`) in your plugin!
* @example
* //get ./database/ot-global.json => ODDatabase class
* const globalDB = openticket.databases.get("openticket:global")
*
* //add a new database with id "test" => ./database/idk-test.json
* const testDatabase = new api.ODDatabase("test","idk-test.json")
* openticket.databases.add(testDatabase)
*/
export class ODDatabaseManager extends ODManager<ODDatabase> {
constructor(debug:ODDebugger){
super(debug,"database")
}
/**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data!
* @example
* //add a new database with id "test" => ./database/idk-test.json
* const testDatabase = new api.ODDatabase("test","idk-test.json")
* openticket.databases.add(testDatabase)
*/
add(data:ODDatabase, overwrite?:boolean): boolean {
return super.add(data,overwrite)
}
/**Get data that matches the `ODId`. Returns the found data.
* @example
* //get ./database/ot-global.json => ODDatabase class
* const globalDB = openticket.databases.get("openticket:global")
*/
get(id:ODValidId): ODDatabase|null {
return super.get(id)
}
/**Remove data that matches the `ODId`. Returns the removed data.
* @example
* //remove the "test" database
* openticket.databases.remove("test") //returns null if non-existing
*/
remove(id:ODValidId): ODDatabase|null {
return super.remove(id)
}
/**Check if data that matches the `ODId` exists. Returns a boolean.
* @example
* //check if "./database/idk-test.json" (test) exists => boolean
* const exists = openticket.databases.exists("test")
*/
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODDatabase `class`
* This is an open ticket database template.
* This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead!
*
* You will only use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)!
* @example
* class SomeDatabase extends ODDatabase {
* //override this method
* setData(category:string, key:string, value:ODValidJsonType): boolean {
* return false
* }
* //override this method
* getData(category:string, key:string): ODValidJsonType|undefined {
* return undefined
* }
* //override this method
* deleteData(category:string, key:string): boolean {
* return false
* }
* }
*/
export class ODDatabase extends ODManagerData {
/**The full path to this database with extension */
file: string = ""
/**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */
set(category:string, key:string, value:ODValidJsonType): boolean {
return false
}
/**Get a specific category & key in the database */
get(category:string, key:string): ODValidJsonType|undefined {
return undefined
}
/**Delete a specific category & key in the database */
delete(category:string, key:string): boolean {
return false
}
/**Check if a specific category & key exists in the database */
exists(category:string, key:string): boolean {
return false
}
/**Get a specific category in the database */
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
return undefined
}
/**Get all values in the database */
getAll(): ODJsonDatabaseStructure {
return []
}
}
/**## ODJsonDatabaseStructure `type`
* This is the structure of how a JSON database file!
*/
export type ODJsonDatabaseStructure = {category:string, key:string, value:ODValidJsonType}[]
/**## ODJsonDatabase `class`
* This is an open ticket JSON database.
* It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy.
* You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`!
*
* You will only use this class if you want to create your own database or use an existing one!
* @example
* //get,set & delete data
* const data = database.getData("category","key") //data will be the value
* const didOverwrite = database.setData("category","key","value") //value can be any of the valid types
* const didExist = database.deleteData("category","key") //delete this value
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
export class ODJsonDatabase extends ODDatabase {
constructor(id:ODValidId, file:string, customPath?:string){
super(id)
const filename = (file.endsWith(".json")) ? file : file+".json"
this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename)
//init file if it doesn't exist yet
this.#system.getData()
}
/**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten!
* @example
* const didOverwrite = database.setData("category","key","value") //value can be any of the valid types
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
set(category:string, key:string, value:ODValidJsonType): boolean {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
//overwrite when already present
if (currentData){
currentList[currentList.indexOf(currentData)].value = value
}else{
currentList.push({category,key,value})
}
this.#system.setData(currentList)
return currentData ? true : false
}
/**Get the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const data = database.getData("category","key") //data will be the value
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
get(category:string, key:string): ODValidJsonType|undefined {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? tempresult.value : undefined
}
/**Remove the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const didExist = database.deleteData("category","key") //delete this value
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
delete(category:string, key:string): boolean {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
if (currentData) currentList.splice(currentList.indexOf(currentData),1)
this.#system.setData(currentList)
return currentData ? true : false
}
/**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */
exists(category:string, key:string): boolean {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? true : false
}
/**Get all values in `category`. Returns `undefined` when non-existent! */
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
const currentList = this.#system.getData()
const tempresult = currentList.filter((d) => (d.category === category))
return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined
}
/**Get all values in `category`. */
getAll(): ODJsonDatabaseStructure {
return this.#system.getData()
}
#system = {
/**Read parsed data from the json file */
getData: (): ODJsonDatabaseStructure => {
if (fs.existsSync(this.file)){
return JSON.parse(fs.readFileSync(this.file).toString())
}else{
fs.writeFileSync(this.file,"[]")
return []
}
},
/**Write parsed data to the json file */
setData: (data:ODJsonDatabaseStructure) => {
fs.writeFileSync(this.file,JSON.stringify(data,null,"\t"))
}
}
}
/**## ODFormattedJsonDatabase `class`
* This is an open ticket Formatted JSON database.
* It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy.
* You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`!
*
* This one is exactly the same as `ODJsonDatabase`, but it has a formatter from the `formatted-json-stringify` package.
* This can help you organise it a little bit better!
*/
export class ODFormattedJsonDatabase extends ODDatabase {
/**The formatter to use on the database array */
formatter: fjs.ArrayFormatter
constructor(id:ODValidId, file:string, formatter:fjs.ArrayFormatter, customPath?:string){
super(id)
const filename = (file.endsWith(".json")) ? file : file+".json"
this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename)
this.formatter = formatter
//init file if it doesn't exist yet
this.#system.getData()
}
/**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten!
* @example
* const didOverwrite = database.setData("category","key","value") //value can be any of the valid types
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
set(category:string, key:string, value:ODValidJsonType): boolean {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
//overwrite when already present
if (currentData){
currentList[currentList.indexOf(currentData)].value = value
}else{
currentList.push({category,key,value})
}
this.#system.setData(currentList)
return currentData ? true : false
}
/**Get the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const data = database.getData("category","key") //data will be the value
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
get(category:string, key:string): ODValidJsonType|undefined {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? tempresult.value : undefined
}
/**Remove the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const didExist = database.deleteData("category","key") //delete this value
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
delete(category:string, key:string): boolean {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
if (currentData) currentList.splice(currentList.indexOf(currentData),1)
this.#system.setData(currentList)
return currentData ? true : false
}
/**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */
exists(category:string, key:string): boolean {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? true : false
}
/**Get all values in `category`. Returns `undefined` when non-existent! */
getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined {
const currentList = this.#system.getData()
const tempresult = currentList.filter((d) => (d.category === category))
return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined
}
/**Get all values in `category`. */
getAll(): ODJsonDatabaseStructure {
return this.#system.getData()
}
#system = {
/**Read parsed data from the json file */
getData: (): ODJsonDatabaseStructure => {
if (fs.existsSync(this.file)){
return JSON.parse(fs.readFileSync(this.file).toString())
}else{
fs.writeFileSync(this.file,"[]")
return []
}
},
/**Write parsed data to the json file */
setData: (data:ODJsonDatabaseStructure) => {
fs.writeFileSync(this.file,this.formatter.stringify(data))
}
}
}
+319
View File
@@ -0,0 +1,319 @@
///////////////////////////////////////
//DEFAULTS MODULE
///////////////////////////////////////
/**## ODDefaults `interface`
* This type is a list of all defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDefaults {
/**Enable the default error handling system. */
errorHandling:boolean,
/**Crash when there is an unknown bot error. */
crashOnError:boolean,
/**Enable the system responsible for the `--debug` flag. */
debugLoading:boolean,
/**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */
pluginLoading:boolean,
/**Don't crash the bot when a plugin crashes! */
softPluginLoading:boolean,
/**Load the default open ticket plugin classes. */
pluginClassLoading:boolean,
/**Load the default open ticket plugin events. */
pluginEventLoading:boolean,
/**Load the default open ticket flags. */
flagLoading:boolean,
/**Enable the default initializer for open ticket flags. */
flagInitiating:boolean,
/**Load the default open ticket configs. */
configLoading:boolean,
/**Load the default open ticket databases. */
databaseLoading:boolean,
/**Load the default open ticket sessions. */
sessionLoading:boolean,
/**Load the default open ticket languages. */
languageLoading:boolean,
/**Enable selecting the current language from `config/general.json`. */
languageSelection:boolean,
/**Set the backup language when the primary language is missing a property. */
backupLanguage:string,
/****[NOD FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */
languageList:string[],
/**Load the default open ticket config checker. */
checkerLoading:boolean,
/**Load the default open ticket config checker functions. */
checkerFunctionLoading:boolean,
/**Enable the default execution of the config checkers. */
checkerExecution:boolean,
/**Load the default open ticket config checker translations. */
checkerTranslationLoading:boolean,
/**Enable the default rendering of the config checkers. */
checkerRendering:boolean,
/**Enable the default quit action when there is an error in the config checker. */
checkerQuit:boolean,
/**Render the checker even when there are no errors & warnings. */
checkerRenderEmpty:boolean,
/**Load the default open ticket client configuration. */
clientLoading:boolean,
/**Load the default open ticket client initialization. */
clientInitiating:boolean,
/**Load the default open ticket client ready actions (status, commands, permissions, ...). */
clientReady:boolean,
/**Create a warning when the bot is present in multiple guilds. */
clientMultiGuildWarning:boolean,
/**Load the default open ticket client activity (from `config/general.json`). */
clientActivityLoading:boolean,
/**Load the default open ticket client activity initialization (& status refresh). */
clientActivityInitiating:boolean,
/**Load the default open ticket slash commands. */
slashCommandLoading:boolean,
/**Load the default open ticket slash command registerer (register slash cmds in discord). */
slashCommandRegistering:boolean,
/**When enabled, the bot is forced to re-register all slash commands in the server. This can be used in case of a auto-update malfunction. */
forceSlashCommandRegistration:boolean,
/**Load the default open ticket text commands. */
textCommandLoading:boolean,
/**Load the default open ticket questions (from `config/questions.json`) */
questionLoading:boolean,
/**Load the default open ticket options (from `config/options.json`) */
optionLoading:boolean,
/**Load the default open ticket panels (from `config/panels.json`) */
panelLoading:boolean,
/**Load the default open ticket tickets (from `database/tickets.json`) */
ticketLoading:boolean,
/**Load the default open ticket reaction roles (from `config/options.json`) */
roleLoading:boolean,
/**Load the default open ticket blacklist (from `database/users.json`) */
blacklistLoading:boolean,
/**Load the default open ticket transcript compilers. */
transcriptCompilerLoading:boolean,
/**Load the default open ticket transcript history (from `database/transcripts.json`) */
transcriptHistoryLoading:boolean,
/**Load the default open ticket button builders. */
buttonBuildersLoading:boolean,
/**Load the default open ticket dropdown builders. */
dropdownBuildersLoading:boolean,
/**Load the default open ticket file builders. */
fileBuildersLoading:boolean,
/**Load the default open ticket embed builders. */
embedBuildersLoading:boolean,
/**Load the default open ticket message builders. */
messageBuildersLoading:boolean,
/**Load the default open ticket modal builders. */
modalBuildersLoading:boolean,
/**Load the default open ticket command responders. */
commandRespondersLoading:boolean,
/**Load the default open ticket button responders. */
buttonRespondersLoading:boolean,
/**Load the default open ticket dropdown responders. */
dropdownRespondersLoading:boolean,
/**Load the default open ticket modal responders. */
modalRespondersLoading:boolean,
/**Set the time (in ms) before open ticket sends an error message when no reply is sent in a responder. */
responderTimeoutMs:number,
/**Load the default open ticket actions. */
actionsLoading:boolean,
/**Load the default open ticket verify bars. */
verifyBarsLoading:boolean,
/**Load the default open ticket permissions. */
permissionsLoading:boolean,
/**Load the default open ticket posts. */
postsLoading:boolean,
/**Initiate the default open ticket posts. */
postsInitiating:boolean,
/**Load the default open ticket cooldowns. */
cooldownsLoading:boolean,
/**Initiate the default open ticket cooldowns. */
cooldownsInitiating:boolean,
/**Load the default open ticket help menu categories. */
helpMenuCategoryLoading:boolean,
/**Load the default open ticket help menu components. */
helpMenuComponentLoading:boolean,
/**Load the default open ticket stat scopes. */
statScopesLoading:boolean,
/**Load the default open ticket stats. */
statLoading:boolean,
/**Initiate the default open ticket stats. */
statInitiating:boolean,
/**Load the default open ticket code/functions. */
codeLoading:boolean,
/**Execute the default open ticket code/functions. */
codeExecution:boolean,
/**Load the default open ticket livestatus. */
liveStatusLoading:boolean,
/**Load the default open ticket startscreen. */
startScreenLoading:boolean,
/**Render the default open ticket startscreen. */
startScreenRendering:boolean,
/**The emoji style to use in embed & message titles using `utilities.emoijTitle()` */
emojiTitleStyle:"disabled"|"before"|"after"|"double",
/**The emoji divider to use in embed & message titles using `utilities.emoijTitle()` */
emojiTitleDivider:string
/**The interval in milliseconds that are between autoclose timeout checkers. */
autocloseCheckInterval:number
/**The interval in milliseconds that are between autodelete timeout checkers. */
autodeleteCheckInterval:number
}
/**## ODDefaultsBooleans `type`
* This type is a list of boolean defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsBooleans = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends boolean ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsStrings `type`
* This type is a list of string defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsStrings = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends string ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsNumbers `type`
* This type is a list of number defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsNumbers = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends number ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsStringArray `type`
* This type is a list of string[] defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsStringArray = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends string[] ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsManager `class`
* This is an open ticket defaults manager.
*
* It manages all settings in open ticket that are not meant to be in the config.
* Here you can disable certain default features to replace them or to specifically enable them!
*
* You are unable to add your own defaults, you can only edit Open Ticket defaults!
*/
export class ODDefaultsManager {
/**A list of all the defaults */
#defaults: ODDefaults
constructor(){
this.#defaults = {
errorHandling:true,
crashOnError:false,
debugLoading:true,
pluginLoading:true,
softPluginLoading:false,
pluginClassLoading:true,
pluginEventLoading:true,
flagLoading:true,
flagInitiating:true,
configLoading:true,
databaseLoading:true,
sessionLoading:true,
languageLoading:true,
languageSelection:true,
backupLanguage:"openticket:english",
languageList:["custom","english","dutch","portuguese","czech"],
checkerLoading:true,
checkerFunctionLoading:true,
checkerExecution:true,
checkerTranslationLoading:true,
checkerRendering:true,
checkerQuit:true,
checkerRenderEmpty:false,
clientLoading:true,
clientInitiating:true,
clientReady:true,
clientMultiGuildWarning:true,
clientActivityLoading:true,
clientActivityInitiating:true,
slashCommandLoading:true,
slashCommandRegistering:true,
forceSlashCommandRegistration:false,
textCommandLoading:true,
questionLoading:true,
optionLoading:true,
panelLoading:true,
ticketLoading:true,
roleLoading:true,
blacklistLoading:true,
transcriptCompilerLoading:true,
transcriptHistoryLoading:true,
buttonBuildersLoading:true,
dropdownBuildersLoading:true,
fileBuildersLoading:true,
embedBuildersLoading:true,
messageBuildersLoading:true,
modalBuildersLoading:true,
commandRespondersLoading:true,
buttonRespondersLoading:true,
dropdownRespondersLoading:true,
modalRespondersLoading:true,
responderTimeoutMs:2500,
actionsLoading:true,
verifyBarsLoading:true,
permissionsLoading:true,
postsLoading:true,
postsInitiating:true,
cooldownsLoading:true,
cooldownsInitiating:true,
helpMenuCategoryLoading:true,
helpMenuComponentLoading:true,
statScopesLoading:true,
statLoading:true,
statInitiating:true,
codeLoading:true,
codeExecution:true,
liveStatusLoading:true,
startScreenLoading:true,
startScreenRendering:true,
emojiTitleStyle:"before",
emojiTitleDivider:" ",
autocloseCheckInterval:300000, //5 minutes
autodeleteCheckInterval:300000 //5 minutes
}
}
/**Set a default to a specific value. Remember! All plugins can edit these values, so your value could be overwritten! */
setDefault<DefaultName extends keyof ODDefaults>(key:DefaultName, value:ODDefaults[DefaultName]): void {
this.#defaults[key] = value
}
/**Get a default. Remember! All plugins can edit these values, so this value could be overwritten! */
getDefault<DefaultName extends keyof ODDefaults>(key:DefaultName): ODDefaults[DefaultName] {
return this.#defaults[key]
}
}
+99
View File
@@ -0,0 +1,99 @@
///////////////////////////////////////
//EVENT MODULE
///////////////////////////////////////
import { ODManagerData, ODManager, ODValidId } from "./base"
import { ODConsoleWarningMessage, ODDebugger } from "./console"
/**## ODEvent `class`
* This is an open ticket event.
*
* This class is made to work with the `ODEventManager` to handle events.
* The function of this specific class is to manage all listeners for a specifc event!
*/
export class ODEvent extends ODManagerData {
/**Alias to open ticket debugger. */
#debug?: ODDebugger
/**The list of permanent listeners. */
listeners: Function[] = []
/**The list of one-time listeners. List is cleared every time the event is emitted. */
oncelisteners: Function[] = []
/**The max listener limit before a possible memory leak will be announced */
listenerLimit: number = 25
/**Use the open ticket debugger in this manager for logs*/
useDebug(debug:ODDebugger|null){
this.#debug = debug ?? undefined
}
/**Get a collection of listeners combined from both types. Also clears the one-time listeners array! */
#getCurrentListeners(){
const final: Function[] = []
this.oncelisteners.forEach((l) => final.push(l))
this.listeners.forEach((l) => final.push(l))
this.oncelisteners = []
return final
}
/**Edit the listener limit */
setListenerLimit(limit:number){
this.listenerLimit = limit
}
/**Add a permanent callback to this event. This will stay as long as the bot is running! */
listen(callback:Function){
this.listeners.push(callback)
if (this.listeners.length > this.listenerLimit){
if (this.#debug) this.#debug.console.log(new ODConsoleWarningMessage("Possible event memory leak detected!",[
{key:"event",value:this.id.value},
{key:"listeners",value:this.listeners.length.toString()}
]))
}
}
/**Add a one-time-only callback to this event. This will only trigger the callback once! */
listenOnce(callback:Function){
this.oncelisteners.push(callback)
}
/**Wait until this event is fired! Be carefull with it, because it could block the entire bot when wrongly used! */
async wait(): Promise<any[]> {
return new Promise((resolve,reject) => {
this.oncelisteners.push((...args:any) => {resolve(args)})
})
}
/**Emit this event to all listeners. You are required to provide all parameters of the event! */
async emit(params:any[]): Promise<void> {
for (const listener of this.#getCurrentListeners()){
try{
await listener(...params)
}catch(err){
process.emit("uncaughtException",err)
}
}
}
}
/**## ODEventManager `class`
* This is an open ticket event manager.
*
* This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter`
*
* You will probably not create this class yourself, but use it globaly instead!
* Check out the `openticket.events` class!
*/
export class ODEventManager extends ODManager<ODEvent> {
/**Reference to the Open Ticket debugger */
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"event")
this.#debug = debug
}
add(data:ODEvent, overwrite?:boolean): boolean {
data.useDebug(this.#debug)
return super.add(data,overwrite)
}
remove(id:ODValidId): ODEvent|null {
const data = super.remove(id)
if (data) data.useDebug(null)
return data
}
}
+73
View File
@@ -0,0 +1,73 @@
///////////////////////////////////////
//FLAG MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODManagerData } from "./base"
import { ODDebugger } from "./console"
/**## ODFlag `class`
* This is an open ticket flag.
*
* A flag is a boolean that can be specified by a parameter in the console.
* It's useful for small settings that are only required once in a while.
*
* Flags can also be enabled manually by plugins!
*/
export class ODFlag extends ODManagerData {
/**The method that has been used to set the value of this flag. (`null` when not set) */
method: "param"|"manual"|null = null
/**The name of this flag. Visible to the user. */
name: string
/**The description of this flag. Visible to the user. */
description: string
/**The name of the parameter in the console. (e.g. `--test`) */
param: string
/**A list of aliases for the parameter in the console. */
aliases: string[]
/**The value of this flag. */
value: boolean = false
constructor(id:ODValidId, name:string, description:string, param:string, aliases?:string[], initialValue?:boolean){
super(id)
this.name = name
this.description = description
this.param = param
this.aliases = aliases ?? []
this.value = initialValue ?? false
}
/**Set the value of this flag. */
setValue(value:boolean,method?:"param"|"manual"){
this.value = value
this.method = method ?? "manual"
}
/**Detect if the process contains the param or aliases & set the value. Use `force` to overwrite a manually set value. */
detectProcessParams(force?:boolean){
if (force){
const params = [this.param,...this.aliases]
this.setValue(params.some((p) => process.argv.includes(p)),"param")
}else if (this.method != "manual"){
const params = [this.param,...this.aliases]
this.setValue(params.some((p) => process.argv.includes(p)),"param")
}
}
}
/**## ODFlagManager `class`
* This is an open ticket flag manager.
*
* This class is responsible for managing & initiating all flags of the bot.
* It also contains a shortcut for initiating all flags.
*/
export class ODFlagManager extends ODManager<ODFlag> {
constructor(debug:ODDebugger){
super(debug,"flag")
}
/**Set all flags to their `process.argv` value. */
init(){
this.getAll().forEach((flag) => {
flag.detectProcessParams(false)
})
}
}
+216
View File
@@ -0,0 +1,216 @@
///////////////////////////////////////
//HELP MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
/**## ODHelpMenuComponentRenderer `type`
* This is the callback of the help menu component renderer. It also contains information about how & where it is rendered.
*/
export type ODHelpMenuComponentRenderer = (page:number, category:number, location:number, mode:"slash"|"text") => string|Promise<string>
/**## ODHelpMenuComponent `class`
* This is an open ticket help menu component.
*
* It can render something on the Open Ticket help menu.
*/
export class ODHelpMenuComponent extends ODManagerData {
/**The priority of this component. The higher, the earlier it will appear in the help menu. */
priority: number
/**The render function for this component. */
render: ODHelpMenuComponentRenderer
constructor(id:ODValidId, priority:number, render:ODHelpMenuComponentRenderer){
super(id)
this.priority = priority
this.render = render
}
}
/**## ODHelpMenuTextComponent `class`
* This is an open ticket help menu text component.
*
* It can render a static piece of text on the Open Ticket help menu.
*/
export class ODHelpMenuTextComponent extends ODHelpMenuComponent {
constructor(id:ODValidId, priority:number, text:string){
super(id,priority,() => {
return text
})
}
}
/**## ODHelpMenuCommandComponentOption `interface`
* This interface contains a command option for the `ODHelpMenuCommandComponent`.
*/
export interface ODHelpMenuCommandComponentOption {
/**The name of this option. */
name:string,
/**Is this option optional? */
optional:boolean
}
/**## ODHelpMenuCommandComponentSettings `interface`
* This interface contains the settings for the `ODHelpMenuCommandComponent`.
*/
export interface ODHelpMenuCommandComponentSettings {
/**The name of this text command. */
textName?:string,
/**The name of this slash command. */
slashName?:string,
/**Options available in the text command. */
textOptions?:ODHelpMenuCommandComponentOption[],
/**Options available in the slash command. */
slashOptions?:ODHelpMenuCommandComponentOption[],
/**The description for the text command. */
textDescription?:string,
/**The description for the slash command. */
slashDescription?:string
}
/**## ODHelpMenuCommandComponent `class`
* This is an open ticket help menu command component.
*
* It contains a useful helper to render a command in the Open Ticket help menu.
*/
export class ODHelpMenuCommandComponent extends ODHelpMenuComponent {
constructor(id:ODValidId, priority:number, settings:ODHelpMenuCommandComponentSettings){
super(id,priority,(page,category,location,mode) => {
if (mode == "slash" && settings.slashName){
return `\`${settings.slashName}${(settings.slashOptions) ? this.#renderOptions(settings.slashOptions) : ""}\` ➜ ${settings.slashDescription ?? ""}`
}else if (mode == "text" && settings.textName){
return `\`${settings.textName}${(settings.textOptions) ? this.#renderOptions(settings.textOptions) : ""}\` ➜ ${settings.textDescription ?? ""}`
}else return ""
})
}
/**Utility function to render all command options. */
#renderOptions(options:ODHelpMenuCommandComponentOption[]){
return " "+options.map((opt) => (opt.optional) ? `[${opt.name}]` : `<${opt.name}>`).join(" ")
}
}
/**## ODHelpMenuCategory `class`
* This is an open ticket help menu category.
*
* Every category in the help menu is an embed field by default.
* Try to limit the amount of components per category.
*/
export class ODHelpMenuCategory extends ODManager<ODHelpMenuComponent> {
/**The id of this category. */
id: ODId
/**The priority of this category. The higher, the earlier it will appear in the menu. */
priority: number
/**The name of this category. (can include emoji's) */
name: string
/**When enabled, it automatically starts this category on a new page. */
newPage: boolean
constructor(id:ODValidId, priority:number, name:string, newPage?:boolean){
super()
this.id = new ODId(id)
this.priority = priority
this.name = name
this.newPage = newPage ?? false
}
/**Render this category and it's components. */
async render(page:number, category:number, mode:"slash"|"text"){
//sort from high priority to low
const derefArray = [...this.getAll()]
derefArray.sort((a,b) => {
return b.priority-a.priority
})
const result: string[] = []
let i = 0
for (const component of derefArray){
try {
result.push(await component.render(page,category,i,mode))
}catch(err){
process.emit("uncaughtException",err)
}
i++
}
//only return the non-empty components
return result.filter((component) => component !== "").join("\n\n")
}
}
/**## ODHelpMenuRenderResult `type`
* This is the array returned when the help menu has been rendered succesfully.
*
* It contains a list of pages, which contain categories by name & value (content).
*/
export type ODHelpMenuRenderResult = {name:string, value:string}[][]
/**## ODHelpMenuManager `class`
* This is an open ticket help menu manager.
*
* It is responsible for rendering the entire help menu content.
* You are also able to configure the amount of categories per page here.
*
* Fewer Categories == More Clean Menu
*/
export class ODHelpMenuManager extends ODManager<ODHelpMenuCategory> {
/**Alias to open ticket debugger. */
#debug: ODDebugger
/**The amount of categories per-page. */
categoriesPerPage: number = 3
constructor(debug:ODDebugger){
super(debug,"help menu category")
this.#debug = debug
}
add(data:ODHelpMenuCategory, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"help menu component")
return super.add(data,overwrite)
}
/**Render this entire help menu & return a `ODHelpMenuRenderResult`. */
async render(mode:"slash"|"text"): Promise<ODHelpMenuRenderResult> {
//sort from high priority to low
const derefArray = [...this.getAll()]
derefArray.sort((a,b) => {
return b.priority-a.priority
})
const result: {name:string, value:string}[][] = []
let currentPage: {name:string, value:string}[] = []
for (const category of derefArray){
try {
const renderedCategory = await category.render(result.length,currentPage.length,mode)
if (renderedCategory !== ""){
//create new page when category wants to
if (currentPage.length > 0 && category.newPage){
result.push(currentPage)
currentPage = []
}
currentPage.push({
name:category.name,
value:renderedCategory
})
//create new page when page is full
if (currentPage.length >= this.categoriesPerPage){
result.push(currentPage)
currentPage = []
}
}
}catch(err){
process.emit("uncaughtException",err)
}
}
//push current page when not-empty
if (currentPage.length > 0) result.push(currentPage)
return result
}
}
+107
View File
@@ -0,0 +1,107 @@
///////////////////////////////////////
//LANGUAGE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base"
import nodepath from "path"
import { ODDebugger } from "./console"
export class ODLanguage extends ODManagerData {
file: string
data: any
metadata: {
otversion:string,
language:string,
translator:string,
lastedited:string
}|null = null
constructor(id:ODValidId, file:string, customPath?:string){
super(id)
this.file = file
try{
const filename = (file.endsWith(".json")) ? file : file+".json"
this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../languages",filename))
}catch{
throw new ODSystemError("[API ERROR] Language \""+file+"\" doesn't exist!")
}
if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"]
}
}
export class ODLanguageManager extends ODManager<ODLanguage> {
current: ODLanguage|null = null
backup: ODLanguage|null = null
constructor(debug:ODDebugger, presets:boolean){
super(debug,"language")
if (presets) this.add(new ODLanguage("english","english.json"))
this.current = presets ? new ODLanguage("english","english.json") : null
this.backup = presets ? new ODLanguage("english","english.json") : null
}
setCurrentLanguage(id:ODValidId){
this.current = this.get(id)
}
getCurrentLanguage(){
return (this.current) ? this.current : null
}
setBackupLanguage(id:ODValidId){
this.backup = this.get(id)
}
getBackupLanguage(){
return (this.backup) ? this.backup : null
}
getLanguageMetadata(frombackup?:boolean){
if (frombackup) return (this.backup) ? this.backup.metadata : null
return (this.current) ? this.current.metadata : null
}
getCurrentLanguageId(){
return (this.current) ? this.current.id.value : ""
}
getTranslation(id:string): string|null {
if (!this.current) return this.#getBackupTranslation(id)
const splitted = id.split(".")
let currentObject = this.current.data
let result: string|false = false
splitted.forEach((id) => {
if (typeof currentObject[id] == "object"){
currentObject = currentObject[id]
}else if (typeof currentObject[id] == "string"){
result = currentObject[id]
}
})
if (typeof result == "string") return result
else return this.#getBackupTranslation(id)
}
#getBackupTranslation(id:string): string|null {
if (!this.backup) return null
const splitted = id.split(".")
let currentObject = this.backup.data
let result: string|false = false
splitted.forEach((id) => {
if (typeof currentObject[id] == "object"){
currentObject = currentObject[id]
}else if (typeof currentObject[id] == "string"){
result = currentObject[id]
}
})
if (typeof result == "string") return result
else return null
}
getTranslationWithParams(id:string, params:string[]): string|null {
let translation = this.getTranslation(id)
if (!translation) return translation
params.forEach((value,index) => {
if (!translation) return
translation = translation.replace(`{${index}}`,value)
})
return translation
}
}
+211
View File
@@ -0,0 +1,211 @@
///////////////////////////////////////
//PERMISSION MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base"
import * as discord from "discord.js"
import { ODDebugger } from "./console"
export type ODPermissionType = "member"|"support"|"moderator"|"admin"|"owner"|"developer"
export type ODPermissionScope = "global-user"|"channel-user"|"global-role"|"channel-role"
export interface ODPermissionResult {
type:ODPermissionType
scope:ODPermissionScope|"default"
level:ODPermissionLevel,
source:ODPermission|null
}
export enum ODPermissionLevel {
member,
support,
moderator,
admin,
owner,
developer
}
export class ODPermission extends ODManagerData {
readonly scope: ODPermissionScope
readonly permission: ODPermissionType
readonly value: discord.Role|discord.User
readonly channel: discord.Channel|null
constructor(id:ODValidId, scope:"global-user", permission:ODPermissionType, value:discord.User)
constructor(id:ODValidId, scope:"global-role", permission:ODPermissionType, value:discord.Role)
constructor(id:ODValidId, scope:"channel-user", permission:ODPermissionType, value:discord.User, channel:discord.Channel)
constructor(id:ODValidId, scope:"channel-role", permission:ODPermissionType, value:discord.Role, channel:discord.Channel)
constructor(id:ODValidId, scope:ODPermissionScope, permission:ODPermissionType, value:discord.Role|discord.User, channel?:discord.Channel){
super(id)
this.scope = scope
this.permission = permission
this.value = value
this.channel = channel ?? null
}
}
export interface ODPermissionSettings {
allowGlobalUserScope?:boolean,
allowGlobalRoleScope?:boolean,
allowChannelUserScope?:boolean,
allowChannelRoleScope?:boolean,
idRegex?:RegExp
}
export type ODPermissionCalculationCallback = (user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null) => Promise<ODPermissionResult>
export class ODPermissionManager extends ODManager<ODPermission> {
#calculation: ODPermissionCalculationCallback|null
defaultResult: ODPermissionResult = {
level:ODPermissionLevel["member"],
scope:"default",
type:"member",
source:null
}
constructor(debug:ODDebugger, useDefaultCalculation?:boolean){
super(debug,"permission")
this.#calculation = useDefaultCalculation ? this.#defaultCalculation : null
}
setCalculation(calculation:ODPermissionCalculationCallback){
this.#calculation = calculation
}
setDefaultResult(result:ODPermissionResult){
this.defaultResult = result
}
getPermissions(user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
try{
if (!this.#calculation) throw new ODSystemError("ODPermissionManager:getPermissions() => missing perms calculation")
return this.#calculation(user,channel,guild,settings)
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("ODPermissionManager:getPermissions() => failed perms calculation")
}
}
hasPermissions(minimum:ODPermissionType, data:ODPermissionResult){
if (minimum == "member") return true
else if (minimum == "support") return (data.level >= ODPermissionLevel["support"])
else if (minimum == "moderator") return (data.level >= ODPermissionLevel["moderator"])
else if (minimum == "admin") return (data.level >= ODPermissionLevel["admin"])
else if (minimum == "owner") return (data.level >= ODPermissionLevel["owner"])
else if (minimum == "developer") return (data.level >= ODPermissionLevel["developer"])
else throw new ODSystemError("Invalid minimum permission type at ODPermissionManager.hasPermissions()")
}
async #defaultCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null
const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true
const allowChannelRoleScope = (settings && typeof settings.allowChannelRoleScope != "undefined") ? settings.allowChannelRoleScope : true
const allowGlobalUserScope = (settings && typeof settings.allowGlobalUserScope != "undefined") ? settings.allowGlobalUserScope : true
const allowGlobalRoleScope = (settings && typeof settings.allowGlobalRoleScope != "undefined") ? settings.allowGlobalRoleScope : true
if (guild && channel && !channel.isDMBased()){
//check for channel user permissions
if (allowChannelUserScope){
const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-user" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.User) && permission.value.id == user.id)
if (users.length > 0){
//sort all permisions from highest to lowest
users.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:users[0].permission,
scope:"channel-user",
level:ODPermissionLevel[users[0].permission],
source:users[0] ?? null
}
}
}
//check for channel role permissions
if (allowChannelRoleScope){
const member = await guild.members.fetch(user.id)
if (member){
const memberRoles = member.roles.cache.map((role) => role.id)
const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-role" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id)
if (roles.length > 0){
//sort all permisions from highest to lowest
roles.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:roles[0].permission,
scope:"channel-role",
level:ODPermissionLevel[roles[0].permission],
source:roles[0] ?? null
}
}
}
}
}
//check for global user permissions
if (allowGlobalUserScope){
const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-user" && (permission.value instanceof discord.User) && permission.value.id == user.id)
if (users.length > 0){
//sort all permisions from highest to lowest
users.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:users[0].permission,
scope:"global-user",
level:ODPermissionLevel[users[0].permission],
source:users[0] ?? null
}
}
}
//check for global role permissions
if (allowGlobalRoleScope){
if (guild){
const member = await guild.members.fetch(user.id)
if (member){
const memberRoles = member.roles.cache.map((role) => role.id)
const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-role" && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id)
if (roles.length > 0){
//sort all permisions from highest to lowest
roles.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:roles[0].permission,
scope:"global-role",
level:ODPermissionLevel[roles[0].permission],
source:roles[0] ?? null
}
}
}
}
}
//spread result to prevent accidental referencing
return {...this.defaultResult}
}
}
+233
View File
@@ -0,0 +1,233 @@
///////////////////////////////////////
//PLUGIN MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODVersion } from "./base"
import nodepath from "path"
import { ODConsolePluginMessage, ODConsoleWarningMessage, ODDebugger } from "./console"
export interface ODUnknownCrashedPlugin {
name:string,
description:string
}
export class ODPluginManager extends ODManager<ODPlugin> {
events: ODPluginEventManager
classes: ODPluginClassManager
unknownCrashedPlugins: ODUnknownCrashedPlugin[] = []
constructor(debug:ODDebugger){
super(debug,"plugin")
this.events = new ODPluginEventManager(debug)
this.classes = new ODPluginClassManager(debug)
}
/**Check if a plugin has loaded successfully.*/
isPluginLoaded(id:ODValidId){
const newId = new ODId(id)
const plugin = this.get(newId)
return (plugin && plugin.executed)
}
}
export interface ODPluginData {
name:string,
id:string,
version:string,
startFile:string,
enabled:boolean,
priority:number,
events:string[]
npmDependencies:string[],
requiredPlugins:string[],
incompatiblePlugins:string[],
details:ODPluginDetails
}
export interface ODPluginDetails {
author:string,
shortDescription:string,
longDescription:string,
imageUrl:string,
projectUrl:string,
tags:string[]
}
export class ODPlugin extends ODManagerData {
dir: string
data: ODPluginData
name: string
priority: number
version: ODVersion
details: ODPluginDetails
enabled: boolean
executed: boolean
crashed: boolean
crashReason: null|"incompatible.plugin"|"missing.plugin"|"missing.dependency"|"executed" = null
constructor(dir:string, jsondata:ODPluginData){
super(jsondata.id)
this.dir = dir
this.data = jsondata
this.name = jsondata.name
this.priority = jsondata.priority
this.version = ODVersion.fromString("plugin",jsondata.version)
this.details = jsondata.details
this.enabled = jsondata.enabled
this.executed = false
this.crashed = false
}
//Get the startfile location relative to the ./plugins/ directory
getStartFile(){
return nodepath.join(this.dir,this.data.startFile)
}
/**Execute this plugin. Returns `false` on crash. */
async execute(debug:ODDebugger,force?:boolean): Promise<boolean> {
if ((this.enabled && !this.crashed) || force){
try{
await require(nodepath.join("../../../../plugins/",this.getStartFile()))
debug.console.log("Plugin \""+this.id.value+"\" loaded successfully!","plugin")
this.executed = true
return true
}catch(error){
this.crashed = true
this.crashReason = "executed"
debug.console.log(error.message+", canceling plugin execution...","plugin",[
{key:"path",value:"./plugins/"+this.dir}
])
debug.console.log("You can see more about this error in the ./otdebug.txt file!","info")
debug.console.debugfile.writeText(error.stack)
return false
}
}else return true
}
#checkDependency(id:string){
try{
require.resolve(id)
return true
}catch{
return false
}
}
dependenciesInstalled(){
const missing: string[] = []
this.data.npmDependencies.forEach((d) => {
if (!this.#checkDependency(d)){
missing.push(d)
}
})
return missing
}
pluginsInstalled(manager:ODPluginManager){
const missing: string[] = []
this.data.requiredPlugins.forEach((p) => {
const plugin = manager.get(p)
if (!plugin || !plugin.enabled){
missing.push(p)
}
})
return missing
}
}
export class ODPluginEvent extends ODManagerData {
listeners: Function[] = []
oncelisteners: Function[] = []
getCurrentListeners(){
const final: Function[] = []
this.oncelisteners.forEach((l) => final.push(l))
this.listeners.forEach((l) => final.push(l))
this.oncelisteners = []
return final
}
}
export class ODPluginEventManager extends ODManager<ODPluginEvent> {
#debug: ODDebugger
listenerLimit: number = 25
constructor(debug:ODDebugger){
super(debug,"plugin event")
this.#debug = debug
}
setListenerLimit(limit:number){
this.listenerLimit = limit
}
on(event:string, callback:Function){
const eventdata = this.get(event)
if (eventdata){
eventdata.listeners.push(callback)
if (eventdata.listeners.length > this.listenerLimit){
this.#debug.console.log(new ODConsoleWarningMessage("Possible plugin event memory leak detected!",[
{key:"event",value:event},
{key:"listeners",value:eventdata.listeners.length.toString()}
]))
}
}else{
throw new ODSystemError("unknown plugin event \""+event+"\"")
}
}
once(event:string, callback:Function){
const eventdata = this.get(event)
if (eventdata){
eventdata.oncelisteners.push(callback)
}else{
throw new ODSystemError("unknown plugin event \""+event+"\"")
}
}
wait(event:string): Promise<any[]> {
return new Promise((resolve,reject) => {
const eventdata = this.get(event)
if (eventdata){
eventdata.oncelisteners.push((...args:any) => {resolve(args)})
}else{
reject("unknown plugin event \""+event+"\"")
}
})
}
emit(event:string, params:any[]): Promise<void> {
return new Promise(async (resolve,reject) => {
const eventdata = this.get(event)
if (eventdata){
const listeners = eventdata.getCurrentListeners()
for (const listener of listeners){
try {
await listener(...params)
}catch(err){
process.emit("uncaughtException",err)
}
}
resolve()
}else{
reject("unknown plugin event \""+event+"\"")
}
})
}
}
export class ODPluginClassManager extends ODManager<ODManagerData> {
constructor(debug:ODDebugger){
super(debug,"plugin class")
}
}
+90
View File
@@ -0,0 +1,90 @@
///////////////////////////////////////
//POST MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder"
import { ODDebugger } from "./console"
import * as discord from "discord.js"
/**## ODPostManager `class`
* This is an open ticket post manager.
*
* It manages `ODPosts`'s for you.
*
* You will probably use this to get the logs channel of the bot (or some other static channel/category).
*/
export class ODPostManager extends ODManager<ODPost<discord.GuildBasedChannel>> {
/**A reference to the main server of the bot */
#guild: discord.Guild|null = null
constructor(debug:ODDebugger){
super(debug,"post")
}
add(data:ODPost<discord.GuildBasedChannel>, overwrite?:boolean): boolean {
if (this.#guild) data.useGuild(this.#guild)
return super.add(data,overwrite)
}
/**Initialize the post manager & all posts. */
async init(guild:discord.Guild){
this.#guild = guild
for (const post of this.getAll()){
post.useGuild(guild)
await post.init()
}
}
}
/**## ODPost `class`
* This is an open ticket post class.
*
* A post is just a shortcut to a static discord channel or category.
* This can be used to get a specific channel over and over again!
*
* This class also contains utilities for sending messages via the Open Ticket builders.
*/
export class ODPost<ChannelType extends discord.GuildBasedChannel> extends ODManagerData {
/**A reference to the main server of the bot */
#guild: discord.Guild|null = null
/**Is this post already initialized? */
ready: boolean = false
/**The discord.js channel */
channel: ChannelType|null = null
/**The discord channel id */
channelId: string
constructor(id:ODValidId, channelId:string){
super(id)
this.channelId = channelId
}
/**Use a specific guild in this class for fetching the channel*/
useGuild(guild:discord.Guild|null){
this.#guild = guild
}
/**Change the channel id to another channel! */
setChannelId(id:string){
this.channelId = id
}
/**Initialize the discord.js channel of this post. */
async init(){
if (this.ready) return
if (!this.#guild) return this.channel = null
try{
this.channel = await this.#guild.channels.fetch(this.channelId) as ChannelType
}catch{
this.channel = null
}
this.ready = true
}
/**Send a message to this channel using the Open Ticket builder system */
async send(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<true>> {
if (!this.channel || !this.channel.isTextBased()) return {success:false,message:null}
try{
const sent = await this.channel.send(msg.message)
return {success:true,message:sent}
}catch{
return {success:false,message:null}
}
}
}
+884
View File
@@ -0,0 +1,884 @@
///////////////////////////////////////
//RESPONDER MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base"
import * as discord from "discord.js"
import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker"
import { ODDebugger } from "./console"
import { ODClientManager, ODSlashCommand, ODTextCommand, ODTextCommandInteractionOption } from "./client"
import { ODDropdownData, ODMessageBuildResult, ODMessageBuildSentResult, ODModalBuildResult } from "./builder"
/**## ODResponderImplementation `class`
* This is an open ticket responder implementation.
*
* It is a basic implementation of the `ODWorkerManager` used by all `ODResponder` classes.
*
* This class can't be used stand-alone & needs to be extended from!
*/
export class ODResponderImplementation<Instance,Source extends string,Params> extends ODManagerData {
/**The manager that has all workers of this implementation */
workers: ODWorkerManager<Instance,Source,Params>
/**The `commandName` or `customId` needs to match this string or regex for this responder to be executed. */
match: string|RegExp
constructor(id:ODValidId, match:string|RegExp, callback?:ODWorkerCallback<Instance,Source,Params>, priority?:number, callbackId?:ODValidId){
super(id)
this.match = match
this.workers = new ODWorkerManager("descending")
if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback))
}
/**Execute all workers & return the result. */
async respond(instance:Instance, source:Source, params:Params): Promise<void> {
throw new ODSystemError("Tried to build an unimplemented ODResponderImplementation")
}
}
export type ODResponderTimeoutErrorCallback<Instance, Source extends "slash"|"text"|"button"|"dropdown"|"modal"|"other"> = (instance:Instance, source:Source) => void|Promise<void>
export class ODResponderManager {
commands: ODCommandResponderManager
buttons: ODButtonResponderManager
dropdowns: ODDropdownResponderManager
modals: ODModalResponderManager
constructor(debug:ODDebugger, client:ODClientManager){
this.commands = new ODCommandResponderManager(debug,"command responder",client)
this.buttons = new ODButtonResponderManager(debug,"button responder",client)
this.dropdowns = new ODDropdownResponderManager(debug,"dropdown responder",client)
this.modals = new ODModalResponderManager(debug,"modal responder",client)
}
}
export class ODCommandResponderManager extends ODManager<ODCommandResponder<"slash"|"text",any>> {
#client: ODClientManager
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODCommandResponderInstance,"slash"|"text">|null = null
#timeoutMs: number|null = null
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODCommandResponderInstance,"slash"|"text">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODCommandResponder<"slash"|"text",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
//add the callback to the slash command manager
this.#client.slashCommands.onInteraction(data.match,(interaction,cmd) => {
const newData = this.get(data.id)
if (!newData) return
newData.respond(new ODCommandResponderInstance(interaction,cmd,this.#timeoutErrorCallback,this.#timeoutMs),"slash",{})
})
//add the callback to the text command manager
this.#client.textCommands.onInteraction(data.prefix,data.match,(interaction,cmd,options) => {
const newData = this.get(data.id)
if (!newData) return
newData.respond(new ODCommandResponderInstance(interaction,cmd,this.#timeoutErrorCallback,this.#timeoutMs,options),"text",{})
})
return res
}
}
export class ODCommandResponderInstanceOptions {
#interaction:discord.ChatInputCommandInteraction|discord.Message
#cmd:ODSlashCommand|ODTextCommand
#options: ODTextCommandInteractionOption[]
constructor(interaction:discord.ChatInputCommandInteraction|discord.Message, cmd:ODSlashCommand|ODTextCommand, options?:ODTextCommandInteractionOption[]){
this.#interaction = interaction
this.#cmd = cmd
this.#options = options ?? []
}
getString(name:string,required:true): string
getString(name:string,required:false): string|null
getString(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getString(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getString() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "string" && opt.name == name)
if (opt && typeof opt.value == "string") return opt.value
else return null
}else return null
}
getBoolean(name:string,required:true): boolean
getBoolean(name:string,required:false): boolean|null
getBoolean(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getBoolean(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getBoolean() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "boolean" && opt.name == name)
if (opt && typeof opt.value == "boolean") return opt.value
else return null
}else return null
}
getNumber(name:string,required:true): number
getNumber(name:string,required:false): number|null
getNumber(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getNumber(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getNumber() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "number" && opt.name == name)
if (opt && typeof opt.value == "number") return opt.value
else return null
}else return null
}
getChannel(name:string,required:true): discord.TextChannel|discord.VoiceChannel|discord.StageChannel|discord.NewsChannel|discord.MediaChannel|discord.ForumChannel|discord.CategoryChannel
getChannel(name:string,required:false): discord.TextChannel|discord.VoiceChannel|discord.StageChannel|discord.NewsChannel|discord.MediaChannel|discord.ForumChannel|discord.CategoryChannel|null
getChannel(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getChannel(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getChannel() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "channel" && opt.name == name)
if (opt && (opt.value instanceof discord.TextChannel || opt.value instanceof discord.VoiceChannel || opt.value instanceof discord.StageChannel || opt.value instanceof discord.NewsChannel || opt.value instanceof discord.MediaChannel || opt.value instanceof discord.ForumChannel || opt.value instanceof discord.CategoryChannel)) return opt.value
else return null
}else return null
}
getRole(name:string,required:true): discord.Role
getRole(name:string,required:false): discord.Role|null
getRole(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getRole(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getRole() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "role" && opt.name == name)
if (opt && opt.value instanceof discord.Role) return opt.value
else return null
}else return null
}
getUser(name:string,required:true): discord.User
getUser(name:string,required:false): discord.User|null
getUser(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getUser(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getUser() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "user" && opt.name == name)
if (opt && opt.value instanceof discord.User) return opt.value
else return null
}else return null
}
getGuildMember(name:string,required:true): discord.GuildMember
getGuildMember(name:string,required:false): discord.GuildMember|null
getGuildMember(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
const member = this.#interaction.options.getMember(name)
if (!member && required) throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!")
return member
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "guildmember" && opt.name == name)
if (opt && opt.value instanceof discord.GuildMember) return opt.value
else return null
}else return null
}
getMentionable(name:string,required:true): discord.User|discord.Role
getMentionable(name:string,required:false): discord.User|discord.Role|null
getMentionable(name:string,required:boolean){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getMentionable(name,required)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message){
const opt = this.#options.find((opt) => opt.type == "mentionable" && opt.name == name)
if (opt && (opt.value instanceof discord.User || opt.value instanceof discord.Role)) return opt.value
else return null
}else return null
}
getSubGroup(): string|null
getSubGroup(){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getSubcommandGroup(true)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getSubGroup() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message && this.#cmd instanceof ODTextCommand){
//0: name, 1:sub/group, 2:sub
const splittedName: string[] = this.#cmd.builder.name.split(" ")
return splittedName[1] ?? null
}else return null
}
getSubCommand(): string|null
getSubCommand(){
if (this.#interaction instanceof discord.ChatInputCommandInteraction){
try {
return this.#interaction.options.getSubcommand(true)
}catch{
throw new ODSystemError("ODCommandResponderInstanceOptions:getSubCommand() slash command option not found!")
}
}else if (this.#interaction instanceof discord.Message && this.#cmd instanceof ODTextCommand){
//0: name, 1:sub/group, 2:sub
const splittedName: string[] = this.#cmd.builder.name.split(" ")
//return the second subcommand when there is a subgroup
if (splittedName.length > 2){
return splittedName[2] ?? null
}else return splittedName[1] ?? null
}else return null
}
}
export class ODCommandResponderInstance {
interaction:discord.ChatInputCommandInteraction|discord.Message
cmd:ODSlashCommand|ODTextCommand
type: "message"|"interaction"
didReply: boolean = false
options: ODCommandResponderInstanceOptions
user: discord.User
member: discord.GuildMember|null
guild: discord.Guild|null
channel: discord.TextBasedChannel
constructor(interaction:discord.ChatInputCommandInteraction|discord.Message, cmd:ODSlashCommand|ODTextCommand, errorCallback:ODResponderTimeoutErrorCallback<ODCommandResponderInstance,"slash"|"text">|null, timeoutMs:number|null, options?:ODTextCommandInteractionOption[]){
if (!interaction.channel) throw new ODSystemError("ODCommandResponderInstance: Unable to find interaction channel!")
this.interaction = interaction
this.cmd = cmd
this.type = (interaction instanceof discord.Message) ? "message" : "interaction"
this.options = new ODCommandResponderInstanceOptions(interaction,cmd,options)
this.user = (interaction instanceof discord.Message) ? interaction.author : interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
setTimeout(async () => {
if (!this.didReply){
try {
if (!errorCallback){
this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{
content:":x: **Something went wrong while replying to this command!**"
}})
}else{
await errorCallback(this,(this.type == "interaction") ? "slash" : "text")
}
}catch(err){
process.emit("uncaughtException",err)
}
}
},timeoutMs ?? 2500)
}
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try {
if (this.type == "interaction" && this.interaction instanceof discord.ChatInputCommandInteraction){
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:sent}
}else{
const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}else if (this.type == "message" && this.interaction instanceof discord.Message){
const sent = await this.interaction.channel.send(msg.message)
this.didReply = true
return {success:true,message:sent}
}else return {success:false,message:null}
}catch{
return {success:false,message:null}
}
}
async defer(ephemeral:boolean){
if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false
if (this.interaction.deferred) return false
await this.interaction.deferReply({ephemeral})
this.didReply = true
return true
}
async modal(modal:ODModalBuildResult){
if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
}
export class ODCommandResponder<Source extends "slash"|"text",Params> extends ODResponderImplementation<ODCommandResponderInstance,Source,Params> {
/**The prefix of the text command needs to match this */
prefix: string
constructor(id:ODValidId, prefix:string, match:string|RegExp, callback?:ODWorkerCallback<ODCommandResponderInstance,Source,Params>, priority?:number, callbackId?:ODValidId){
super(id,match,callback,priority,callbackId)
this.prefix = prefix
}
/**Respond to this command */
async respond(instance:ODCommandResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
export class ODButtonResponderManager extends ODManager<ODButtonResponder<"button",any>> {
#client: ODClientManager
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODButtonResponderInstance,"button">|null = null
#timeoutMs: number|null = null
#listeners: ((interaction:discord.ButtonInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
this.#client.client.on("interactionCreate",(interaction) => {
if (!interaction.isButton()) return
this.#listeners.forEach((cb) => cb(interaction))
})
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODButtonResponderInstance,"button">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODButtonResponder<"button",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
this.#listeners.push((interaction) => {
const newData = this.get(data.id)
if (!newData) return
if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODButtonResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"button",{})
})
return res
}
}
export class ODButtonResponderInstance {
interaction:discord.ButtonInteraction
didReply: boolean = false
user: discord.User
member: discord.GuildMember|null
guild: discord.Guild|null
channel: discord.TextBasedChannel
message: discord.Message
constructor(interaction:discord.ButtonInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODButtonResponderInstance,"button">|null, timeoutMs:number|null){
if (!interaction.channel) throw new ODSystemError("ODButtonResponderInstance: Unable to find interaction channel!")
this.interaction = interaction
this.user = interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
this.message = interaction.message
setTimeout(async () => {
if (!this.didReply){
try {
if (!errorCallback){
this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{
content:":x: **Something went wrong while replying to this button!**"
}})
}else{
await errorCallback(this,"button")
}
}catch(err){
process.emit("uncaughtException",err)
}
}
},timeoutMs ?? 2500)
}
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:sent}
}else{
const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}else{
const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
await this.interaction.deferReply({ephemeral})
}else{
await this.interaction.deferUpdate()
}
this.didReply = true
return true
}
async modal(modal:ODModalBuildResult){
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null
getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null
getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null
getMessageComponent(type:"channel-dropdown",id:string|RegExp): discord.ChannelSelectMenuComponent|null
getMessageComponent(type:"role-dropdown",id:string|RegExp): discord.RoleSelectMenuComponent|null
getMessageComponent(type:"mentionable-dropdown",id:string|RegExp): discord.MentionableSelectMenuComponent|null
getMessageComponent(type:"button"|"string-dropdown"|"user-dropdown"|"channel-dropdown"|"role-dropdown"|"mentionable-dropdown", id:string|RegExp): discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null {
let result: discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null = null
this.message.components.forEach((row) => {
row.components.forEach((component) => {
if (type == "button" && component.type == discord.ComponentType.Button && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "string-dropdown" && component.type == discord.ComponentType.StringSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "user-dropdown" && component.type == discord.ComponentType.UserSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "channel-dropdown" && component.type == discord.ComponentType.ChannelSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "role-dropdown" && component.type == discord.ComponentType.RoleSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "mentionable-dropdown" && component.type == discord.ComponentType.MentionableSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
})
})
return result
}
getMessageEmbed(): discord.Embed|null {
return this.message.embeds[0] ?? null
}
}
export class ODButtonResponder<Source extends string,Params> extends ODResponderImplementation<ODButtonResponderInstance,Source,Params> {
/**Respond to this button */
async respond(instance:ODButtonResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
export class ODDropdownResponderManager extends ODManager<ODDropdownResponder<"dropdown",any>> {
#client: ODClientManager
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODDropdownResponderInstance,"dropdown">|null = null
#timeoutMs: number|null = null
#listeners: ((interaction:discord.AnySelectMenuInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
this.#client.client.on("interactionCreate",(interaction) => {
if (!interaction.isAnySelectMenu()) return
this.#listeners.forEach((cb) => cb(interaction))
})
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODDropdownResponderInstance,"dropdown">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODDropdownResponder<"dropdown",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
this.#listeners.push((interaction) => {
const newData = this.get(data.id)
if (!newData) return
if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODDropdownResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"dropdown",{})
})
return res
}
}
export class ODDropdownResponderInstanceValues {
#interaction:discord.AnySelectMenuInteraction
#type: ODDropdownData["type"]
constructor(interaction:discord.AnySelectMenuInteraction, type:ODDropdownData["type"]){
this.#interaction = interaction
this.#type = type
if (interaction.isChannelSelectMenu()){
interaction.values
}
}
getStringValues(): string[] {
try {
return this.#interaction.values
}catch{
throw new ODSystemError("ODDropdownResponderInstanceValues:getStringValues() invalid values!")
}
}
async getRoleValues(): Promise<discord.Role[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() dropdown type isn't role!")
try {
const result: discord.Role[] = []
for (const id of this.#interaction.values){
if (!this.#interaction.guild) break
const role = await this.#interaction.guild.roles.fetch(id)
if (role) result.push(role)
}
return result
}catch{
throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() invalid values!")
}
}
async getUserValues(): Promise<discord.User[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() dropdown type isn't user!")
try {
const result: discord.User[] = []
for (const id of this.#interaction.values){
const user = await this.#interaction.client.users.fetch(id)
if (user) result.push(user)
}
return result
}catch{
throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() invalid values!")
}
}
async getChannelValues(): Promise<discord.GuildBasedChannel[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() dropdown type isn't channel!")
try {
const result: discord.GuildBasedChannel[] = []
for (const id of this.#interaction.values){
if (!this.#interaction.guild) break
const guild = await this.#interaction.guild.channels.fetch(id)
if (guild) result.push(guild)
}
return result
}catch{
throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() invalid values!")
}
}
}
export class ODDropdownResponderInstance {
interaction:discord.AnySelectMenuInteraction
didReply: boolean = false
type: ODDropdownData["type"]
values: ODDropdownResponderInstanceValues
user: discord.User
member: discord.GuildMember|null
guild: discord.Guild|null
channel: discord.TextBasedChannel
message: discord.Message
constructor(interaction:discord.AnySelectMenuInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODDropdownResponderInstance,"dropdown">|null, timeoutMs:number|null){
if (!interaction.channel) throw new ODSystemError("ODDropdownResponderInstance: Unable to find interaction channel!")
this.interaction = interaction
if (interaction.isStringSelectMenu()){
this.type = "string"
}else if (interaction.isRoleSelectMenu()){
this.type = "role"
}else if (interaction.isUserSelectMenu()){
this.type = "user"
}else if (interaction.isChannelSelectMenu()){
this.type = "channel"
}else if (interaction.isMentionableSelectMenu()){
this.type = "mentionable"
}else throw new ODSystemError("ODDropdownResponderInstance: invalid dropdown type!")
this.values = new ODDropdownResponderInstanceValues(interaction,this.type)
this.user = interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
this.message = interaction.message
setTimeout(async () => {
if (!this.didReply){
try {
if (!errorCallback){
this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{
content:":x: **Something went wrong while replying to this dropdown!**"
}})
}else{
await errorCallback(this,"dropdown")
}
}catch(err){
process.emit("uncaughtException",err)
}
}
},timeoutMs ?? 2500)
}
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try {
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:sent}
}else{
const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}else{
const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
await this.interaction.deferReply({ephemeral})
}else{
await this.interaction.deferUpdate()
}
this.didReply = true
return true
}
async modal(modal:ODModalBuildResult){
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null
getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null
getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null
getMessageComponent(type:"channel-dropdown",id:string|RegExp): discord.ChannelSelectMenuComponent|null
getMessageComponent(type:"role-dropdown",id:string|RegExp): discord.RoleSelectMenuComponent|null
getMessageComponent(type:"mentionable-dropdown",id:string|RegExp): discord.MentionableSelectMenuComponent|null
getMessageComponent(type:"button"|"string-dropdown"|"user-dropdown"|"channel-dropdown"|"role-dropdown"|"mentionable-dropdown", id:string|RegExp): discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null {
let result: discord.ButtonComponent|discord.StringSelectMenuComponent|discord.RoleSelectMenuComponent|discord.ChannelSelectMenuComponent|discord.MentionableSelectMenuComponent|discord.UserSelectMenuComponent|null = null
this.message.components.forEach((row) => {
row.components.forEach((component) => {
if (type == "button" && component.type == discord.ComponentType.Button && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "string-dropdown" && component.type == discord.ComponentType.StringSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "user-dropdown" && component.type == discord.ComponentType.UserSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "channel-dropdown" && component.type == discord.ComponentType.ChannelSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "role-dropdown" && component.type == discord.ComponentType.RoleSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
else if (type == "mentionable-dropdown" && component.type == discord.ComponentType.MentionableSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component
})
})
return result
}
getMessageEmbed(): discord.Embed|null {
return this.message.embeds[0] ?? null
}
}
export class ODDropdownResponder<Source extends string,Params> extends ODResponderImplementation<ODDropdownResponderInstance,Source,Params> {
/**Respond to this dropdown */
async respond(instance:ODDropdownResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
export class ODModalResponderManager extends ODManager<ODModalResponder<"modal",any>> {
#client: ODClientManager
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODModalResponderInstance,"modal">|null = null
#timeoutMs: number|null = null
#listeners: ((interaction:discord.ModalSubmitInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
super(debug,debugname)
this.#client = client
this.#client.client.on("interactionCreate",(interaction) => {
if (!interaction.isModalSubmit()) return
this.#listeners.forEach((cb) => cb(interaction))
})
}
/**Set the message to send when the response times out! */
setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback<ODModalResponderInstance,"modal">|null, ms:number|null){
this.#timeoutErrorCallback = callback
this.#timeoutMs = ms
}
add(data:ODModalResponder<"modal",any>, overwrite?:boolean){
const res = super.add(data,overwrite)
this.#listeners.push((interaction) => {
const newData = this.get(data.id)
if (!newData) return
if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODModalResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"modal",{})
})
return res
}
}
export class ODModalResponderInstanceValues {
#interaction:discord.ModalSubmitInteraction
constructor(interaction:discord.ModalSubmitInteraction){
this.#interaction = interaction
}
getTextField(name:string,required:true): string
getTextField(name:string,required:false): string|null
getTextField(name:string,required:boolean){
try {
const data = this.#interaction.fields.getField(name,discord.ComponentType.TextInput)
if (!data && required) throw new ODSystemError("ODModalResponderInstanceValues:getTextField() field not found!")
return (data) ? data.value : null
}catch{
throw new ODSystemError("ODModalResponderInstanceValues:getTextField() field not found!")
}
}
}
export class ODModalResponderInstance {
interaction:discord.ModalSubmitInteraction
didReply: boolean = false
values: ODModalResponderInstanceValues
user: discord.User
member: discord.GuildMember|null
guild: discord.Guild|null
channel: discord.TextBasedChannel|null
constructor(interaction:discord.ModalSubmitInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODModalResponderInstance,"modal">|null, timeoutMs:number|null){
this.interaction = interaction
this.values = new ODModalResponderInstanceValues(interaction)
this.user = interaction.user
this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null
this.guild = interaction.guild
this.channel = interaction.channel
setTimeout(async () => {
if (!this.didReply){
try {
if (!errorCallback){
this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{
content:":x: **Something went wrong while replying to this modal!**"
}})
}else{
await errorCallback(this,"modal")
}
}catch(err){
process.emit("uncaughtException",err)
}
}
},timeoutMs ?? 2500)
}
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:sent}
}else{
const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}
}catch{
return {success:false,message:null}
}
}
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
if (this.interaction.replied || this.interaction.deferred){
const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral}))
this.didReply = true
return {success:true,message:await sent.fetch()}
}else throw new ODSystemError()
}catch{
return {success:false,message:null}
}
}
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
await this.interaction.deferReply({ephemeral})
}else{
await this.interaction.deferUpdate()
}
this.didReply = true
return true
}
}
export class ODModalResponder<Source extends string,Params> extends ODResponderImplementation<ODModalResponderInstance,Source,Params> {
/**Respond to this modal */
async respond(instance:ODModalResponderInstance, source:Source, params:Params){
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
}
}
+155
View File
@@ -0,0 +1,155 @@
///////////////////////////////////////
//SESSION MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
import * as crypto from "crypto"
/**## ODSessionManager `class`
* This is an open ticket session manager.
*
* It contains all sessions in open ticket. Sessions are a sort of temporary storage which will be cleared when the bot stops.
* Data in sessions have a randomly generated key which will always be unique.
*
* Visit the `ODSession` class for more info
*/
export class ODSessionManager extends ODManager<ODSession> {
constructor(debug:ODDebugger){
super(debug,"session")
}
}
/**## ODSessionInstance `interface`
* This interface represents a single session instance. It contains an id, data & some dates.
*/
export interface ODSessionInstance {
/**The id of this session instance. */
id:string,
/**The creation date of this session instance. */
creation:number,
/**The custom amount of minutes before this session expires. */
timeout:number|null,
/**This is the data from this session instance */
data:any
}
/**## ODSessionTimeoutCallback `type`
* This is the callback used for session timeout listeners.
*/
export type ODSessionTimeoutCallback = (id:string, timeout:"default"|"custom", data:any, creation:Date) => void
/**## ODSession `class`
* This is an open ticket session.
*
* It can be used to create 100% unique id's for usage in the bot. An id can also store additional data which isn't saved to the filesystem.
* You can almost compare it to the PHP session system.
*/
export class ODSession extends ODManagerData {
/**The history of previously generated instance ids. Used to reduce the risk of generating the same id twice. */
#idHistory: string[] = []
/**The max length of the instance id history. */
#maxIdHistoryLength: number = 500
/**An array of all the currently active session instances. */
sessions: ODSessionInstance[] = []
/**The default amount of minutes before a session automatically stops. */
timeoutMinutes: number = 30
/**The id of the auto-timeout session checker interval */
#intervalId: NodeJS.Timeout
/**Listeners for when a session times-out. */
#timeoutListeners: ODSessionTimeoutCallback[] = []
constructor(id:ODValidId, intervalSeconds?:number){
super(id)
//create the auto-timeout session checker
this.#intervalId = setInterval(() => {
const deletableSessions: {instance:ODSessionInstance,reason:"default"|"custom"}[] = []
//collect all deletable sessions
this.sessions.forEach((session) => {
if (session.timeout && (new Date().getTime() - session.creation) > session.timeout*60000){
//stop session => custom timeout
deletableSessions.push({instance:session,reason:"custom"})
}else if (!session.timeout && (new Date().getTime() - session.creation) > this.timeoutMinutes*60000){
//stop session => default timeout
deletableSessions.push({instance:session,reason:"default"})
}
})
//permanently delete sessions
deletableSessions.forEach((session) => {
const index = this.sessions.findIndex((s) => s.id === session.instance.id)
this.sessions.splice(index,1)
//emit timeout listeners
this.#timeoutListeners.forEach((cb) => cb(session.instance.id,session.reason,session.instance.data,new Date(session.instance.creation)))
})
},((intervalSeconds) ? (intervalSeconds * 1000) : 60000))
}
/**Create a unique hex id of 8 characters and add it to the instance id history */
#createUniqueId(): string {
const hex = crypto.randomBytes(4).toString("hex")
if (this.#idHistory.includes(hex)){
return this.#createUniqueId()
}else{
this.#idHistory.push(hex)
if (this.#idHistory.length > this.#maxIdHistoryLength) this.#idHistory.shift()
return hex
}
}
/**Stop the global interval that automatically deletes timed-out sessions. (This action can't be reverted!) */
stopAutoTimeout(){
clearInterval(this.#intervalId)
}
/**Start a session instance with data. Returns the unique id required to access the session. */
start(data?:any): string {
const id = this.#createUniqueId()
this.sessions.push({
id,data,
creation:new Date().getTime(),
timeout:null
})
return id
}
/**Get the data of a session instance. Returns `null` when not found. */
data(id:string): any|null {
const session = this.sessions.find((session) => session.id === id)
if (!session) return null
return session.data
}
/**Stop & delete a session instance. Returns `true` when sucessful. */
stop(id:string): boolean {
const index = this.sessions.findIndex((session) => session.id === id)
if (index < 0) return false
this.sessions.splice(index,1)
return true
}
/**Update the data of a session instance. Returns `true` when sucessful. */
update(id:string, data:any): boolean {
const session = this.sessions.find((session) => session.id === id)
if (!session) return false
session.data = data
return true
}
/**Change the global or session timeout minutes. Returns `true` when sucessful. */
setTimeout(min:number, id?:string): boolean {
if (!id){
//change global timeout minutes
this.timeoutMinutes = min
return true
}else{
//change session instance timeout minutes
const session = this.sessions.find((session) => session.id === id)
if (!session) return false
session.timeout = min
return true
}
}
/**Listen for a session timeout (default or custom) */
onTimeout(callback:ODSessionTimeoutCallback){
this.#timeoutListeners.push(callback)
}
}
+219
View File
@@ -0,0 +1,219 @@
///////////////////////////////////////
//STARTSCREEN MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger, ODError, ODLiveStatusManager } from "./console"
import { ODFlag } from "./flag"
import { ODPlugin, ODUnknownCrashedPlugin } from "./plugin"
import ansis from "ansis"
export type ODStartScreenComponentRenderCallback = (location:number) => string|Promise<string>
export class ODStartScreenManager extends ODManager<ODStartScreenComponent> {
/**Alias to the Open Ticket debugger. */
#debug: ODDebugger
/**Alias to the livestatus manager. */
livestatus: ODLiveStatusManager
constructor(debug:ODDebugger,livestatus:ODLiveStatusManager){
super(debug,"startscreen component")
this.#debug = debug
this.livestatus = livestatus
}
/**Get all components in sorted order. */
getSortedComponents(priority:"ascending"|"descending"){
return this.getAll().sort((a,b) => {
if (priority == "ascending") return a.priority-b.priority
else return b.priority-a.priority
})
}
/**Render all startscreen components in priority order. */
async renderAllComponents(){
const components = this.getSortedComponents("descending")
let location = 0
for (const component of components){
try {
const renderedText = await component.renderAll(location)
console.log(renderedText)
this.#debug.console.debugfile.writeText("[STARTSCREEN] Component: \""+component.id+"\"\n"+ansis.strip(renderedText))
}catch(e){
this.#debug.console.log("Unable to render \""+component.id+"\" startscreen component!","error")
this.#debug.console.debugfile.writeErrorMessage(new ODError(e,"uncaughtException"))
}
location++
}
}
}
export class ODStartScreenComponent extends ODManagerData {
priority: number
renderBefore: ODStartScreenComponentRenderCallback|null = null
render: ODStartScreenComponentRenderCallback
renderAfter: ODStartScreenComponentRenderCallback|null = null
constructor(id:ODValidId, priority:number, render:ODStartScreenComponentRenderCallback){
super(id)
this.priority = priority
this.render = render
}
async renderAll(location:number){
const textBefore = (this.renderBefore) ? await this.renderBefore(location) : ""
const text = await this.render(location)
const textAfter = (this.renderAfter) ? await this.renderAfter(location) : ""
return (textBefore ? textBefore+"\n" : "")+text+(textAfter ? "\n"+textAfter : "")
}
}
export interface ODStartScreenProperty {
key:string,
value:string
}
export class ODStartScreenLogoComponent extends ODStartScreenComponent {
logo: string[]
topPadding: boolean
bottomPadding: boolean
logoHexColor: string
constructor(id:ODValidId, priority:number, logo:string[], topPadding?:boolean, bottomPadding?:boolean, logoHexColor?:string){
super(id,priority,() => {
const renderedTop = (this.topPadding ? "\n" : "")
const renderedLogo = this.logo.join("\n")
const renderedBottom = (this.bottomPadding ? "\n" : "")
return ansis.hex(this.logoHexColor)(renderedTop+renderedLogo+renderedBottom)
})
this.logo = logo
this.topPadding = topPadding ?? false
this.bottomPadding = bottomPadding ?? false
this.logoHexColor = logoHexColor ?? "#f8ba00"
}
}
export interface ODStartScreenHeaderAlignmentSettings {
align:"center"|"left"|"right",
width:number|ODStartScreenComponent
}
export class ODStartScreenHeaderComponent extends ODStartScreenComponent {
properties: ODStartScreenProperty[]
spacer: string
align: ODStartScreenHeaderAlignmentSettings|null
constructor(id:ODValidId, priority:number, properties:ODStartScreenProperty[], spacer?:string, align?:ODStartScreenHeaderAlignmentSettings){
super(id,priority,async () => {
const renderedProperties = ansis.bold(this.properties.map((prop) => prop.key+": "+prop.value).join(this.spacer))
if (!this.align || this.align.align == "left"){
return renderedProperties
}else if (this.align.align == "right"){
const width = (typeof this.align.width == "number") ? this.align.width : (
ansis.strip(await this.align.width.renderAll(0)).split("\n").map((row) => row.length).reduce((prev,curr) => {
if (prev < curr) return curr
else return prev
},0)
)
const offset = width - ansis.strip(renderedProperties).length
if (offset < 0) return renderedProperties
else{
return (" ".repeat(offset) + renderedProperties)
}
}else if (this.align.align == "center"){
const width = (typeof this.align.width == "number") ? this.align.width : (
ansis.strip(await this.align.width.renderAll(0)).split("\n").map((row) => row.length).reduce((prev,curr) => {
if (prev < curr) return curr
else return prev
})
)
const offset = Math.round((width - ansis.strip(renderedProperties).length)/2)
if (offset < 0) return renderedProperties
else{
return (" ".repeat(offset) + renderedProperties)
}
}
return renderedProperties
})
this.properties = properties
this.spacer = spacer ?? " - "
this.align = align ?? null
}
}
export class ODStartScreenCategoryComponent extends ODStartScreenComponent {
name: string
renderIfEmpty: boolean
constructor(id:ODValidId, priority:number, name:string, render:ODStartScreenComponentRenderCallback, renderIfEmpty?:boolean){
super(id,priority,async (location) => {
const contents = await render(location)
if (contents != "" || this.renderIfEmpty){
return ansis.bold.underline("\n"+name.toUpperCase()+(contents != "" ? ":\n" : ":")) + contents
}else return ""
})
this.name = name
this.renderIfEmpty = renderIfEmpty ?? true
}
}
export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCategoryComponent {
properties: ODStartScreenProperty[]
propertyHexColor: string
constructor(id:ODValidId, priority:number, name:string, properties:ODStartScreenProperty[], propertyHexColor?:string, renderIfEmpty?:boolean){
super(id,priority,name,() => {
return this.properties.map((prop) => ansis.hex(this.propertyHexColor)(prop.key+": ")+prop.value).join("\n")
},renderIfEmpty)
this.properties = properties
this.propertyHexColor = propertyHexColor ?? "#f8ba00"
}
}
export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryComponent {
flags: ODFlag[]
constructor(id:ODValidId, priority:number, flags:ODFlag[]){
super(id,priority,"flags",() => {
return this.flags.filter((flag) => (flag.value == true)).map((flag) => ansis.blue("["+flag.name+"] "+flag.description)).join("\n")
},false)
this.flags = flags
}
}
export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategoryComponent {
plugins: ODPlugin[]
unknownCrashedPlugins: ODUnknownCrashedPlugin[]
constructor(id:ODValidId, priority:number, plugins:ODPlugin[], unknownCrashedPlugins:ODUnknownCrashedPlugin[]){
super(id,priority,"plugins",() => {
const renderedPlugins = this.plugins.sort((a,b) => b.priority-a.priority).map((plugin) => {
if (plugin.enabled && plugin.executed) return ansis.green("✅ ["+plugin.name+"] "+plugin.details.shortDescription)
else if (plugin.enabled && plugin.crashed) return ansis.red("❌ ["+plugin.name+"] "+plugin.details.shortDescription)
else return ansis.gray("💤 ["+plugin.name+"] "+plugin.details.shortDescription)
})
const renderedUnknownPlugins = unknownCrashedPlugins.map((plugin) => ansis.red("❌ ["+plugin.name+"] "+plugin.description))
return [...renderedPlugins,...renderedUnknownPlugins].join("\n")
},false)
this.plugins = plugins
this.unknownCrashedPlugins = unknownCrashedPlugins
}
}
export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCategoryComponent {
livestatus: ODLiveStatusManager
constructor(id:ODValidId, priority:number, livestatus:ODLiveStatusManager){
super(id,priority,"livestatus",async () => {
const messages = await this.livestatus.getAllMessages()
return this.livestatus.renderer.render(messages)
},false)
this.livestatus = livestatus
}
}
export class ODStartScreenLogCategoryComponent extends ODStartScreenCategoryComponent {
constructor(id:ODValidId, priority:number){
super(id,priority,"logs",() => "",true)
}
}
+212
View File
@@ -0,0 +1,212 @@
///////////////////////////////////////
//STAT MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base"
import { ODDebugger } from "./console"
import { ODDatabase, ODJsonDatabaseStructure } from "./database"
import * as discord from "discord.js"
export type ODValidStatValue = string|number|boolean
export type ODStatsManagerInitCallback = (database:ODJsonDatabaseStructure, deletables:ODJsonDatabaseStructure) => void|Promise<void>
export type ODStatScopeSetMode = "set"|"increase"|"decrease"
export class ODStatsManager extends ODManager<ODStatScope> {
/**Alias to open ticket debugger. */
#debug: ODDebugger
/**Alias to open ticket stats database. */
database: ODDatabase|null = null
/**All the listeners for the init event. */
#initListeners: ODStatsManagerInitCallback[] = []
constructor(debug:ODDebugger){
super(debug,"stat scope")
this.#debug = debug
}
useDatabase(database:ODDatabase){
this.database = database
}
add(data:ODStatScope, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"stat")
if (this.database) data.useDatabase(this.database)
return super.add(data,overwrite)
}
async init(){
if (!this.database) throw new ODSystemError("Unable to initialize stats scopes due to missing database!")
//get all valid categories
const validCategories: string[] = []
for (const scope of this.getAll()){
validCategories.push(...scope.init())
}
//filter out the deletable stats
const deletableStats: ODJsonDatabaseStructure = []
this.database.getAll().forEach((data) => {
if (!validCategories.includes(data.category)) deletableStats.push(data)
})
//do additional deletion
for (const cb of this.#initListeners){
await cb(this.database.getAll(),deletableStats)
}
//delete all deletable stats
deletableStats.forEach((data) => {
if (!this.database) return
this.database.delete(data.category,data.key)
})
}
reset(){
if (!this.database) return
this.database.getAll().forEach((data) => {
if (!this.database) return
this.database.delete(data.category,data.key)
})
}
onInit(callback:ODStatsManagerInitCallback){
this.#initListeners.push(callback)
}
}
export class ODStatScope extends ODManager<ODStat> {
/**The id of this statistics scope. */
id: ODId
/**Is this stat scope already initialized? */
ready: boolean = false
/**Alias to open ticket stats database. */
database: ODDatabase|null = null
/**The name of this scope (used in embed title) */
name:string
constructor(id:ODValidId, name:string){
super()
this.id = new ODId(id)
this.name = name
}
useDatabase(database:ODDatabase){
this.database = database
}
getStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
if (!this.database) return null
const newId = new ODId(id)
const data = this.database.get(this.id.value+"_"+newId.value,scopeId)
if (typeof data == "undefined"){
//set stats to default value & return
return this.resetStat(id,scopeId)
}else if (typeof data == "string" || typeof data == "boolean" || typeof data == "number"){
//return value received from database
return data
}
//return null on error
return null
}
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
if (!this.database) return false
const stat = this.get(id)
if (!stat) return false
if (mode == "set" || typeof value != "number"){
this.database.set(this.id.value+"_"+stat.id.value,scopeId,value)
}else if (mode == "increase"){
const currentValue = this.getStat(id,scopeId)
if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0)
else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value)
}else if (mode == "decrease"){
const currentValue = this.getStat(id,scopeId)
if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0)
else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value)
}
return true
}
resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null {
if (!this.database) return null
const stat = this.get(id)
if (!stat) return null
if (stat.value != null) this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value)
return stat.value
}
init(): string[] {
//get all valid stats categories
this.ready = true
return this.getAll().map((stat) => this.id.value+"_"+stat.id.value)
}
async render(scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User): Promise<string> {
//sort from high priority to low
const derefArray = [...this.getAll()]
derefArray.sort((a,b) => {
return b.priority-a.priority
})
const result: string[] = []
for (const stat of derefArray){
try {
if (stat instanceof ODDynamicStat){
//dynamic render (without value)
result.push(await stat.render("",scopeId,guild,channel,user))
}else{
//normal render (with value)
const value = this.getStat(stat.id,scopeId)
if (value != null) result.push(await stat.render(value,scopeId,guild,channel,user))
}
}catch(err){
process.emit("uncaughtException",err)
}
}
return result.filter((stat) => stat !== "").join("\n")
}
}
export class ODStatGlobalScope extends ODStatScope {
getStat(id:ODValidId): ODValidStatValue|null {
return super.getStat(id,"GLOBAL")
}
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean {
return super.setStat(id,"GLOBAL",value,mode)
}
resetStat(id:ODValidId): ODValidStatValue|null {
return super.resetStat(id,"GLOBAL")
}
render(scopeId:"GLOBAL", guild:discord.Guild, channel:discord.TextBasedChannel, user: discord.User): Promise<string> {
return super.render("GLOBAL",guild,channel,user)
}
}
export type ODStatRenderer = (value:ODValidStatValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
export class ODStat extends ODManagerData {
priority: number
render: ODStatRenderer
value: ODValidStatValue|null
constructor(id:ODValidId, priority:number, render:ODStatRenderer, value?:ODValidStatValue){
super(id)
this.priority = priority
this.render = render
this.value = value ?? null
}
}
export class ODBasicStat extends ODStat {
name: string
constructor(id:ODValidId, priority:number, name:string, value:ODValidStatValue){
super(id,priority,(value) => {
return ""+name+": `"+value.toString()+"`"
},value)
this.name = name
}
}
export type ODDynamicStatRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
export class ODDynamicStat extends ODStat {
constructor(id:ODValidId, priority:number, render:ODDynamicStatRenderer){
super(id,priority,(value,scopeId,guild,channel,user) => {
return render(scopeId,guild,channel,user)
})
}
}
+43
View File
@@ -0,0 +1,43 @@
///////////////////////////////////////
//VERIFYBAR MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODMessage } from "./builder"
import { ODDebugger } from "./console"
import { ODButtonResponderInstance } from "./responder"
import * as discord from "discord.js"
import { ODWorkerManager } from "./worker"
export type ODVerifyBarCallback = (responder:ODButtonResponderInstance,customData?:string) => void|Promise<void>
export class ODVerifyBar extends ODManagerData {
success: ODWorkerManager<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null}>
failure: ODWorkerManager<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null}>
message: ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>}>
enabled: boolean
constructor(id:ODValidId, message:ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalMessage:discord.Message<boolean>}>, enabled?:boolean){
super(id)
this.success = new ODWorkerManager("descending")
this.failure = new ODWorkerManager("descending")
this.message = message
this.enabled = enabled ?? true
}
async activate(responder:ODButtonResponderInstance){
if (this.enabled){
//show verifybar
const {guild,channel,user,message} = responder
await responder.update(await this.message.build("verifybar",{guild,channel,user,verifybar:this,originalMessage:message}))
}else{
//instant success
if (this.success) await this.success.executeWorkers(responder,"verifybar",{data:null,verifybarMessage:null})
}
}
}
export class ODVerifyBarManager extends ODManager<ODVerifyBar> {
constructor(debug:ODDebugger){
super(debug,"verifybar")
}
}
+93
View File
@@ -0,0 +1,93 @@
///////////////////////////////////////
//WORKER MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
/**## ODWorkerCallback `type`
* This is the callback used in `ODWorker`!
*/
export type ODWorkerCallback<Instance, Source extends string, Params> = (instance:Instance, params:Params, source:Source, cancel:() => void) => void|Promise<void>
/**## ODWorker `class`
* This is an open ticket worker.
*
* You can compare it with a normal javascript callback, but slightly more advanced!
*
* - It has an `id` for identification of the function
* - A `priority` to know when to execute this callback (related to others)
* - It knows who called this callback (`source`)
* - And much more!
*/
export class ODWorker<Instance, Source extends string, Params> extends ODManagerData {
/**The priority of this worker */
priority: number
/**The main callback of this worker */
callback: ODWorkerCallback<Instance,Source,Params>
constructor(id:ODValidId, priority:number, callback:ODWorkerCallback<Instance,Source,Params>){
super(id)
this.priority = priority
this.callback = callback
}
}
/**## ODWorker `class`
* This is an open ticket worker manager.
*
* It manages & executes `ODWorker`'s in the correct order.
*
* You will probably register a custom worker in this class to create a message or button.
*/
export class ODWorkerManager<Instance, Source extends string, Params> extends ODManager<ODWorker<Instance,Source,Params>> {
/**The order of execution for workers inside this manager. */
#priorityOrder: "ascending"|"descending"
/**The backup worker will be executed when one of the workers fails or cancels execution. */
backupWorker: ODWorker<{reason:"error"|"cancel"},Source,Params>|null = null
constructor(priorityOrder:"ascending"|"descending"){
super()
this.#priorityOrder = priorityOrder
}
/**Get all workers in sorted order. */
getSortedWorkers(priority:"ascending"|"descending"){
const derefArray = [...this.getAll()]
return derefArray.sort((a,b) => {
if (priority == "ascending") return a.priority-b.priority
else return b.priority-a.priority
})
}
/**Execute all workers on an instance using the given source & parameters. */
async executeWorkers(instance:Instance, source:Source, params:Params){
const derefParams = {...params}
const workers = this.getSortedWorkers(this.#priorityOrder)
let didCancel = false
let didCrash = false
for (const worker of workers){
if (didCancel) break
try {
await worker.callback(instance,derefParams,source,() => {
didCancel = true
})
}catch(err){
process.emit("uncaughtException",err)
didCrash = true
}
}
if (didCancel && this.backupWorker){
try{
await this.backupWorker.callback({reason:"cancel"},derefParams,source,() => {})
}catch(err){
process.emit("uncaughtException",err)
}
}else if (didCrash && this.backupWorker){
try{
await this.backupWorker.callback({reason:"error"},derefParams,source,() => {})
}catch(err){
process.emit("uncaughtException",err)
}
}
}
}
+28
View File
@@ -0,0 +1,28 @@
///////////////////////////////////////
//OPENTICKET BLACKLIST MODULE
///////////////////////////////////////
import { ODManager, ODManagerData, ODValidId } from "../modules/base"
import { ODDebugger } from "../modules/console"
export class ODBlacklist extends ODManagerData {
#reason: string|null
constructor(id:ODValidId,reason:string|null){
super(id)
this.#reason = reason
}
set reason(reason:string|null) {
this.#reason = reason
this._change()
}
get reason(){
return this.#reason
}
}
export class ODBlacklistManager extends ODManager<ODBlacklist> {
constructor(debug:ODDebugger){
super(debug,"blacklist")
}
}
+421
View File
@@ -0,0 +1,421 @@
///////////////////////////////////////
//OPENTICKET OPTION MODULE
///////////////////////////////////////
import { ODDatabase } from "../modules/database"
import { ODJsonConfig_DefaultOptionEmbedSettingsType, ODJsonConfig_DefaultOptionPingSettingsType } from "../defaults/config"
import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonColor, ODManagerData, ODSystemError } from "../modules/base"
import { ODDebugger } from "../modules/console"
import * as discord from "discord.js"
import * as crypto from "crypto"
import { OTRoleUpdateMode } from "./role"
export class ODOptionManager extends ODManager<ODOption> {
#debug: ODDebugger
suffix: ODOptionSuffixManager
constructor(debug:ODDebugger){
super(debug,"option")
this.#debug = debug
this.suffix = new ODOptionSuffixManager(debug)
}
add(data:ODOption, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"option data")
return super.add(data,overwrite)
}
}
export interface ODOptionDataJson {
id:string,
value:ODValidJsonType
}
export interface ODOptionJson {
id:string,
type:string,
version:string,
data:ODOptionDataJson[]
}
export class ODOption extends ODManager<ODOptionData<ODValidJsonType>> {
id:ODId
type: string
constructor(id:ODValidId, type:string, data:ODOptionData<ODValidJsonType>[]){
super()
this.id = new ODId(id)
this.type = type
data.forEach((data) => {
this.add(data)
})
}
toJson(version:ODVersion): ODOptionJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
type:this.type,
version:version.toString(),
data
}
}
static fromJson(json:ODOptionJson): ODOption {
return new ODOption(json.id,json.type,json.data.map((data) => new ODOptionData(data.id,data.value)))
}
}
export class ODOptionData<DataType extends ODValidJsonType> extends ODManagerData {
#value: DataType
constructor(id:ODValidId, value:DataType){
super(id)
this.#value = value
}
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODOptionData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}
/**## ODTicketOptionIds `type`
* This type is an array of ids available in the `ODTicketOption` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODTicketOptionIds {
"openticket:name":ODOptionData<string>,
"openticket:description":ODOptionData<string>,
"openticket:button-emoji":ODOptionData<string>,
"openticket:button-label":ODOptionData<string>,
"openticket:button-color":ODOptionData<ODValidButtonColor>,
"openticket:admins":ODOptionData<string[]>,
"openticket:admins-readonly":ODOptionData<string[]>,
"openticket:allow-blacklisted-users":ODOptionData<boolean>,
"openticket:questions":ODOptionData<string[]>,
"openticket:channel-prefix":ODOptionData<string>,
"openticket:channel-suffix":ODOptionData<"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">,
"openticket:channel-category":ODOptionData<string>,
"openticket:channel-category-closed":ODOptionData<string>,
"openticket:channel-category-backup":ODOptionData<string>,
"openticket:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>,
"openticket:channel-description":ODOptionData<string>,
"openticket:dm-message-enabled":ODOptionData<boolean>,
"openticket:dm-message-text":ODOptionData<string>,
"openticket:dm-message-embed":ODOptionData<ODJsonConfig_DefaultOptionEmbedSettingsType>,
"openticket:ticket-message-enabled":ODOptionData<boolean>,
"openticket:ticket-message-text":ODOptionData<string>,
"openticket:ticket-message-embed":ODOptionData<ODJsonConfig_DefaultOptionEmbedSettingsType>,
"openticket:ticket-message-ping":ODOptionData<ODJsonConfig_DefaultOptionPingSettingsType>,
"openticket:autoclose-enable-hours":ODOptionData<boolean>,
"openticket:autoclose-enable-leave":ODOptionData<boolean>,
"openticket:autoclose-disable-claim":ODOptionData<boolean>,
"openticket:autoclose-hours":ODOptionData<number>,
"openticket:autodelete-enable-days":ODOptionData<boolean>,
"openticket:autodelete-enable-leave":ODOptionData<boolean>,
"openticket:autodelete-disable-claim":ODOptionData<boolean>,
"openticket:autodelete-days":ODOptionData<number>,
"openticket:cooldown-enabled":ODOptionData<boolean>,
"openticket:cooldown-minutes":ODOptionData<number>,
"openticket:limits-enabled":ODOptionData<boolean>,
"openticket:limits-maximum-global":ODOptionData<number>,
"openticket:limits-maximum-user":ODOptionData<number>
}
export class ODTicketOption extends ODOption {
type: "openticket:ticket" = "openticket:ticket"
constructor(id:ODValidId, data:ODOptionData<ODValidJsonType>[]){
super(id,"openticket:ticket",data)
}
get<OptionId extends keyof ODTicketOptionIds>(id:OptionId): ODTicketOptionIds[OptionId]
get(id:ODValidId): ODOptionData<ODValidJsonType>|null
get(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.get(id)
}
remove<OptionId extends keyof ODTicketOptionIds>(id:OptionId): ODTicketOptionIds[OptionId]
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODTicketOptionIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
static fromJson(json: ODOptionJson): ODTicketOption {
return new ODTicketOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value)))
}
}
/**## ODWebsiteOptionIds `type`
* This type is an array of ids available in the `ODWebsiteOption` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODWebsiteOptionIds {
"openticket:name":ODOptionData<string>,
"openticket:description":ODOptionData<string>,
"openticket:button-emoji":ODOptionData<string>,
"openticket:button-label":ODOptionData<string>,
"openticket:url":ODOptionData<string>,
}
export class ODWebsiteOption extends ODOption {
type: "openticket:website" = "openticket:website"
constructor(id:ODValidId, data:ODOptionData<ODValidJsonType>[]){
super(id,"openticket:website",data)
}
get<OptionId extends keyof ODWebsiteOptionIds>(id:OptionId): ODWebsiteOptionIds[OptionId]
get(id:ODValidId): ODOptionData<ODValidJsonType>|null
get(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.get(id)
}
remove<OptionId extends keyof ODWebsiteOptionIds>(id:OptionId): ODWebsiteOptionIds[OptionId]
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODWebsiteOptionIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
static fromJson(json: ODOptionJson): ODWebsiteOption {
return new ODWebsiteOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value)))
}
}
/**## ODRoleOptionIds `type`
* This type is an array of ids available in the `ODRoleOption` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODRoleOptionIds {
"openticket:name":ODOptionData<string>,
"openticket:description":ODOptionData<string>,
"openticket:button-emoji":ODOptionData<string>,
"openticket:button-label":ODOptionData<string>,
"openticket:button-color":ODOptionData<ODValidButtonColor>,
"openticket:roles":ODOptionData<string[]>,
"openticket:mode":ODOptionData<OTRoleUpdateMode>,
"openticket:remove-roles-on-add":ODOptionData<string[]>,
"openticket:add-on-join":ODOptionData<boolean>
}
export class ODRoleOption extends ODOption {
type: "openticket:role" = "openticket:role"
constructor(id:ODValidId, data:ODOptionData<ODValidJsonType>[]){
super(id,"openticket:role",data)
}
get<OptionId extends keyof ODRoleOptionIds>(id:OptionId): ODRoleOptionIds[OptionId]
get(id:ODValidId): ODOptionData<ODValidJsonType>|null
get(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.get(id)
}
remove<OptionId extends keyof ODRoleOptionIds>(id:OptionId): ODRoleOptionIds[OptionId]
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null
remove(id:ODValidId): ODOptionData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODRoleOptionIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
static fromJson(json:ODOptionJson): ODRoleOption {
return new ODRoleOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value)))
}
}
export class ODOptionSuffixManager extends ODManager<ODOptionSuffix> {
/**Alias to open ticket global database. */
database: ODDatabase|null = null
constructor(debug:ODDebugger){
super(debug,"ticket suffix")
}
useDatabase(database:ODDatabase){
this.database = database
}
/**Instantly get the suffix from an option. */
getSuffixFromOption(option:ODTicketOption,user:discord.User): string|null {
const suffix = this.getAll().find((suffix) => suffix.option.id.value == option.id.value)
if (!suffix) return null
return suffix.getSuffix(user)
}
}
export class ODOptionSuffix extends ODManagerData {
/**The option of this suffix. */
option: ODTicketOption
constructor(id:ODValidId, option:ODTicketOption){
super(id)
this.option = option
}
/**Get the suffix for a new ticket. */
getSuffix(user:discord.User): string {
throw new ODSystemError("Tried to use an unimplemented ODOptionSuffix!")
}
}
export class ODOptionUserNameSuffix extends ODOptionSuffix {
getSuffix(user:discord.User): string {
return user.username
}
}
export class ODOptionUserIdSuffix extends ODOptionSuffix {
getSuffix(user:discord.User): string {
return user.id
}
}
export class ODOptionCounterDynamicSuffix extends ODOptionSuffix {
/**The database where the value of this counter is stored. */
database: ODDatabase
constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){
super(id,option)
this.database = database
if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0)
}
getSuffix(user:discord.User): string {
const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value)
const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue
const newValue = currentValue+1
this.database.set("openticket:option-suffix-counter",this.option.id.value,newValue)
return newValue.toString()
}
}
export class ODOptionCounterFixedSuffix extends ODOptionSuffix {
/**The database where the value of this counter is stored. */
database: ODDatabase
constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){
super(id,option)
this.database = database
if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0)
}
getSuffix(user:discord.User): string {
const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value)
const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue
const newValue = (currentValue >= 9999) ? 0 : currentValue+1
this.database.set("openticket:option-suffix-counter",this.option.id.value,newValue)
if (newValue.toString().length == 1) return "000"+newValue.toString()
else if (newValue.toString().length == 2) return "00"+newValue.toString()
else if (newValue.toString().length == 3) return "0"+newValue.toString()
else return newValue.toString()
}
}
export class ODOptionRandomNumberSuffix extends ODOptionSuffix {
/**The database where previous random numbers are stored. */
database: ODDatabase
constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){
super(id,option)
this.database = database
if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[])
}
#generateUniqueValue(history:string[]): string {
const rawNumber = Math.round(Math.random()*1000).toString()
let number = rawNumber
if (rawNumber.length == 1) number = "000"+rawNumber
else if (rawNumber.length == 2) number = "00"+rawNumber
else if (rawNumber.length == 3) number = "0"+rawNumber
if (history.includes(number)) return this.#generateUniqueValue(history)
else return number
}
getSuffix(user:discord.User): string {
const rawCurrentValues = this.database.get("openticket:option-suffix-history",this.option.id.value)
const currentValues = ((Array.isArray(rawCurrentValues)) ? rawCurrentValues : []) as string[]
const newValue = this.#generateUniqueValue(currentValues)
currentValues.push(newValue)
if (currentValues.length > 50) currentValues.shift()
this.database.set("openticket:option-suffix-history",this.option.id.value,currentValues)
return newValue
}
}
export class ODOptionRandomHexSuffix extends ODOptionSuffix {
/**The database where previous random hexes are stored. */
database: ODDatabase
constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){
super(id,option)
this.database = database
if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[])
}
#generateUniqueValue(history:string[]): string {
const hex = crypto.randomBytes(2).toString("hex")
if (history.includes(hex)) return this.#generateUniqueValue(history)
else return hex
}
getSuffix(user:discord.User): string {
const rawCurrentValues = this.database.get("openticket:option-suffix-history",this.option.id.value)
const currentValues = ((Array.isArray(rawCurrentValues)) ? rawCurrentValues : []) as string[]
const newValue = this.#generateUniqueValue(currentValues)
currentValues.push(newValue)
if (currentValues.length > 50) currentValues.shift()
this.database.set("openticket:option-suffix-history",this.option.id.value,currentValues)
return newValue
}
}
+128
View File
@@ -0,0 +1,128 @@
///////////////////////////////////////
//OPENTICKET PANEL MODULE
///////////////////////////////////////
import { ODJsonConfig_DefaultPanelEmbedSettingsType } from "../defaults/config"
import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonColor, ODManagerData } from "../modules/base"
import { ODDebugger } from "../modules/console"
export class ODPanelManager extends ODManager<ODPanel> {
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"option")
this.#debug = debug
}
add(data:ODPanel, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"option data")
return super.add(data,overwrite)
}
}
export interface ODPanelDataJson {
id:string,
value:ODValidJsonType
}
export interface ODPanelJson {
id:string,
version:string,
data:ODPanelDataJson[]
}
/**## ODPanelIds `type`
* This type is an array of ids available in the `ODPanel` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODPanelIds {
"openticket:name":ODPanelData<string>,
"openticket:options":ODPanelData<string[]>,
"openticket:dropdown":ODPanelData<boolean>,
"openticket:text":ODPanelData<string>,
"openticket:embed":ODPanelData<ODJsonConfig_DefaultPanelEmbedSettingsType>,
"openticket:dropdown-placeholder":ODPanelData<string>,
"openticket:enable-max-tickets-warning-text":ODPanelData<boolean>,
"openticket:enable-max-tickets-warning-embed":ODPanelData<boolean>,
"openticket:describe-options-layout":ODPanelData<"simple"|"normal"|"detailed">,
"openticket:describe-options-custom-title":ODPanelData<string>,
"openticket:describe-options-in-text":ODPanelData<boolean>,
"openticket:describe-options-in-embed-fields":ODPanelData<boolean>,
"openticket:describe-options-in-embed-description":ODPanelData<boolean>
}
export class ODPanel extends ODManager<ODPanelData<ODValidJsonType>> {
id:ODId
constructor(id:ODValidId, data:ODPanelData<ODValidJsonType>[]){
super()
this.id = new ODId(id)
data.forEach((data) => {
this.add(data)
})
}
toJson(version:ODVersion): ODPanelJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
version:version.toString(),
data
}
}
static fromJson(json:ODPanelJson): ODPanel {
return new ODPanel(json.id,json.data.map((data) => new ODPanelData(data.id,data.value)))
}
get<PanelId extends keyof ODPanelIds>(id:PanelId): ODPanelIds[PanelId]
get(id:ODValidId): ODPanelData<ODValidJsonType>|null
get(id:ODValidId): ODPanelData<ODValidJsonType>|null {
return super.get(id)
}
remove<PanelId extends keyof ODPanelIds>(id:PanelId): ODPanelIds[PanelId]
remove(id:ODValidId): ODPanelData<ODValidJsonType>|null
remove(id:ODValidId): ODPanelData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODPanelIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
export class ODPanelData<DataType extends ODValidJsonType> extends ODManagerData {
#value: DataType
constructor(id:ODValidId, value:DataType){
super(id)
this.#value = value
}
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODPanelData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}
+180
View File
@@ -0,0 +1,180 @@
///////////////////////////////////////
//OPENTICKET OPTION MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base"
import { ODDebugger } from "../modules/console"
export class ODQuestionManager extends ODManager<ODQuestion> {
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"question")
this.#debug = debug
}
add(data:ODQuestion, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"question data")
return super.add(data,overwrite)
}
}
export interface ODQuestionDataJson {
id:string,
value:ODValidJsonType
}
export interface ODQuestionJson {
id:string,
type:string,
version:string,
data:ODQuestionDataJson[]
}
export class ODQuestion extends ODManager<ODQuestionData<ODValidJsonType>> {
id:ODId
type: string
constructor(id:ODValidId, type:string, data:ODQuestionData<ODValidJsonType>[]){
super()
this.id = new ODId(id)
this.type = type
data.forEach((data) => {
this.add(data)
})
}
toJson(version:ODVersion): ODQuestionJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
type:this.type,
version:version.toString(),
data
}
}
static fromJson(json:ODQuestionJson): ODQuestion {
return new ODQuestion(json.id,json.type,json.data.map((data) => new ODQuestionData(data.id,data.value)))
}
}
export class ODQuestionData<DataType extends ODValidJsonType> extends ODManagerData {
#value: DataType
constructor(id:ODValidId, value:DataType){
super(id)
this.#value = value
}
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODQuestionData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}
/**## ODShortQuestionIds `type`
* This type is an array of ids available in the `ODShortQuestion` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODShortQuestionIds {
"openticket:name":ODQuestionData<string>,
"openticket:required":ODQuestionData<boolean>,
"openticket:placeholder":ODQuestionData<string>,
"openticket:length-enabled":ODQuestionData<boolean>,
"openticket:length-min":ODQuestionData<number>,
"openticket:length-max":ODQuestionData<number>
}
export class ODShortQuestion extends ODQuestion {
type: "openticket:short" = "openticket:short"
constructor(id:ODValidId, data:ODQuestionData<ODValidJsonType>[]){
super(id,"openticket:short",data)
}
get<QuestionId extends keyof ODShortQuestionIds>(id:QuestionId): ODShortQuestionIds[QuestionId]
get(id:ODValidId): ODQuestionData<ODValidJsonType>|null
get(id:ODValidId): ODQuestionData<ODValidJsonType>|null {
return super.get(id)
}
remove<QuestionId extends keyof ODShortQuestionIds>(id:QuestionId): ODShortQuestionIds[QuestionId]
remove(id:ODValidId): ODQuestionData<ODValidJsonType>|null
remove(id:ODValidId): ODQuestionData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODShortQuestionIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
static fromJson(json: ODQuestionJson): ODShortQuestion {
return new ODShortQuestion(json.id,json.data.map((data) => new ODQuestionData(data.id,data.value)))
}
}
/**## ODParagraphQuestionIds `type`
* This type is an array of ids available in the `ODParagraphQuestion` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODParagraphQuestionIds {
"openticket:name":ODQuestionData<string>,
"openticket:required":ODQuestionData<boolean>,
"openticket:placeholder":ODQuestionData<string>,
"openticket:length-enabled":ODQuestionData<boolean>,
"openticket:length-min":ODQuestionData<number>,
"openticket:length-max":ODQuestionData<number>
}
export class ODParagraphQuestion extends ODQuestion {
type: "openticket:paragraph" = "openticket:paragraph"
constructor(id:ODValidId, data:ODQuestionData<ODValidJsonType>[]){
super(id,"openticket:paragraph",data)
}
get<QuestionId extends keyof ODParagraphQuestionIds>(id:QuestionId): ODParagraphQuestionIds[QuestionId]
get(id:ODValidId): ODQuestionData<ODValidJsonType>|null
get(id:ODValidId): ODQuestionData<ODValidJsonType>|null {
return super.get(id)
}
remove<QuestionId extends keyof ODParagraphQuestionIds>(id:QuestionId): ODParagraphQuestionIds[QuestionId]
remove(id:ODValidId): ODQuestionData<ODValidJsonType>|null
remove(id:ODValidId): ODQuestionData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODParagraphQuestionIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
static fromJson(json: ODQuestionJson): ODParagraphQuestion {
return new ODParagraphQuestion(json.id,json.data.map((data) => new ODQuestionData(data.id,data.value)))
}
}
+122
View File
@@ -0,0 +1,122 @@
///////////////////////////////////////
//OPENTICKET ROLE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base"
import { ODDebugger } from "../modules/console"
import * as discord from "discord.js"
export class ODRoleManager extends ODManager<ODRole> {
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"role")
this.#debug = debug
}
add(data:ODRole, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"role data")
return super.add(data,overwrite)
}
}
export interface ODRoleDataJson {
id:string,
value:ODValidJsonType
}
export interface ODRoleJson {
id:string,
version:string,
data:ODRoleDataJson[]
}
export class ODRoleData<DataType extends ODValidJsonType> extends ODManagerData {
#value: DataType
constructor(id:ODValidId, value:DataType){
super(id)
this.#value = value
}
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODRoleData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}
/**## ODRoleIds `type`
* This type is an array of ids available in the `ODRole` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODRoleIds {
"openticket:roles":ODRoleData<string[]>,
"openticket:mode":ODRoleData<OTRoleUpdateMode>,
"openticket:remove-roles-on-add":ODRoleData<string[]>,
"openticket:add-on-join":ODRoleData<boolean>
}
export class ODRole extends ODManager<ODRoleData<ODValidJsonType>> {
id:ODId
constructor(id:ODValidId, data:ODRoleData<ODValidJsonType>[]){
super()
this.id = new ODId(id)
data.forEach((data) => {
this.add(data)
})
}
toJson(version:ODVersion): ODRoleJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
version:version.toString(),
data
}
}
static fromJson(json:ODRoleJson): ODRole {
return new ODRole(json.id,json.data.map((data) => new ODRoleData(data.id,data.value)))
}
get<OptionId extends keyof ODRoleIds>(id:OptionId): ODRoleIds[OptionId]
get(id:ODValidId): ODRoleData<ODValidJsonType>|null
get(id:ODValidId): ODRoleData<ODValidJsonType>|null {
return super.get(id)
}
remove<OptionId extends keyof ODRoleIds>(id:OptionId): ODRoleIds[OptionId]
remove(id:ODValidId): ODRoleData<ODValidJsonType>|null
remove(id:ODValidId): ODRoleData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODRoleIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
export interface OTRoleUpdateResult {
role:discord.Role,
action:"added"|"removed"|null
}
export type OTRoleUpdateMode = "add&remove"|"add"|"remove"
+251
View File
@@ -0,0 +1,251 @@
///////////////////////////////////////
//OPENTICKET TICKET MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base"
import { ODDebugger } from "../modules/console"
import { ODClientManager_Default } from "../defaults/client"
import { ODOption, ODOptionJson, ODTicketOption } from "./option"
import * as discord from "discord.js"
export class ODTicketManager extends ODManager<ODTicket> {
/**A reference to the main server of the bot */
#guild: discord.Guild|null = null
#client: ODClientManager_Default
#debug: ODDebugger
constructor(debug:ODDebugger, client:ODClientManager_Default){
super(debug,"ticket")
this.#debug = debug
this.#client = client
}
add(data:ODTicket, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"ticket data")
return super.add(data,overwrite)
}
/**Use a specific guild in this class for fetching the channel*/
useGuild(guild:discord.Guild|null){
this.#guild = guild
}
/**Get the discord channel for a specific ticket. */
async getTicketChannel(ticket:ODTicket): Promise<discord.GuildTextBasedChannel|null> {
if (!this.#guild) return null
try {
const channel = await this.#guild.channels.fetch(ticket.id.value)
if (!channel || !channel.isTextBased()) return null
return channel
}catch{
return null
}
}
/**Get the main ticket message of a ticket channel when found. */
async getTicketMessage(ticket:ODTicket): Promise<discord.Message<true>|null> {
const msgId = ticket.get("openticket:ticket-message").value
if (!this.#guild || !msgId) return null
try {
const channel = await this.getTicketChannel(ticket)
if (!channel) return null
return await channel.messages.fetch(msgId)
}catch{
return null
}
}
/**Shortcut for getting a discord.js user within a ticket. */
async getTicketUser(ticket:ODTicket, user:"creator"|"closer"|"claimer"|"pinner"): Promise<discord.User|null> {
if (!this.#guild) return null
try {
if (user == "creator"){
const creatorId = ticket.get("openticket:opened-by").value
if (!creatorId) return null
else return (await this.#guild.client.users.fetch(creatorId))
}else if (user == "closer"){
const closerId = ticket.get("openticket:closed-by").value
if (!closerId) return null
else return (await this.#guild.client.users.fetch(closerId))
}else if (user == "claimer"){
const claimerId = ticket.get("openticket:claimed-by").value
if (!claimerId) return null
else return (await this.#guild.client.users.fetch(claimerId))
}else if (user == "pinner"){
const pinnerId = ticket.get("openticket:pinned-by").value
if (!pinnerId) return null
else return (await this.#guild.client.users.fetch(pinnerId))
}else return null
}catch {return null}
}
/**Shortcut for getting all users that are able to view a ticket. */
async getAllTicketParticipants(ticket:ODTicket): Promise<{user:discord.User,role:"creator"|"participant"|"admin"}[]|null> {
if (!this.#guild) return null
const final: {user:discord.User,role:"creator"|"participant"|"admin"}[] = []
const channel = await this.getTicketChannel(ticket)
if (!channel) return null
//add creator
const creatorId = ticket.get("openticket:opened-by").value
if (creatorId){
const creator = await this.#client.fetchUser(creatorId)
if (creator) final.push({user:creator,role:"creator"})
}
//add participants
const participants = ticket.get("openticket:participants").value.filter((p) => p.type == "user")
for (const p of participants){
if (!final.find((u) => u.user.id == p.id)){
const participant = await this.#client.fetchUser(p.id)
if (participant) final.push({user:participant,role:"participant"})
}
}
//add admin roles
const roles = ticket.get("openticket:participants").value.filter((p) => p.type == "role")
for (const r of roles){
const role = await this.#client.fetchGuildRole(channel.guild,r.id)
if (role){
role.members.forEach((member) => {
if (final.find((u) => u.user.id == member.id)) return
final.push({user:member.user,role:"admin"})
})
}
}
return final
}
}
export interface ODTicketDataJson {
id:string,
value:ODValidJsonType
}
export interface ODTicketJson {
id:string,
option:string,
version:string,
data:ODTicketDataJson[]
}
/**## ODTicketIds `type`
* This type is an array of ids available in the `ODTicket` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODTicketIds {
"openticket:busy":ODTicketData<boolean>,
"openticket:ticket-message":ODTicketData<string|null>,
"openticket:participants":ODTicketData<{type:"role"|"user",id:string}[]>,
"openticket:channel-suffix":ODTicketData<string>,
"openticket:open":ODTicketData<boolean>,
"openticket:opened-by":ODTicketData<string|null>,
"openticket:opened-on":ODTicketData<number|null>,
"openticket:closed":ODTicketData<boolean>,
"openticket:closed-by":ODTicketData<string|null>,
"openticket:closed-on":ODTicketData<number|null>,
"openticket:claimed":ODTicketData<boolean>,
"openticket:claimed-by":ODTicketData<string|null>,
"openticket:claimed-on":ODTicketData<number|null>,
"openticket:pinned":ODTicketData<boolean>,
"openticket:pinned-by":ODTicketData<string|null>,
"openticket:pinned-on":ODTicketData<number|null>,
"openticket:for-deletion":ODTicketData<boolean>,
"openticket:category":ODTicketData<string|null>,
"openticket:category-mode":ODTicketData<null|"normal"|"closed"|"backup"|"claimed">,
"openticket:autoclose-enabled":ODTicketData<boolean>,
"openticket:autoclose-hours":ODTicketData<number>,
"openticket:autoclosed":ODTicketData<boolean>,
"openticket:autodelete-enabled":ODTicketData<boolean>,
"openticket:autodelete-days":ODTicketData<number>,
"openticket:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>,
}
export class ODTicket extends ODManager<ODTicketData<ODValidJsonType>> {
id:ODId
#option: ODTicketOption
constructor(id:ODValidId, option:ODTicketOption, data:ODTicketData<ODValidJsonType>[]){
super()
this.id = new ODId(id)
this.#option = option
data.forEach((data) => {
this.add(data)
})
}
set option(option:ODTicketOption){
this.#option = option
this._change()
}
get option(){
return this.#option
}
toJson(version:ODVersion): ODTicketJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
option:this.option.id.value,
version:version.toString(),
data
}
}
static fromJson(json:ODTicketJson, option:ODTicketOption): ODTicket {
return new ODTicket(json.id,option,json.data.map((data) => new ODTicketData(data.id,data.value)))
}
get<OptionId extends keyof ODTicketIds>(id:OptionId): ODTicketIds[OptionId]
get(id:ODValidId): ODTicketData<ODValidJsonType>|null
get(id:ODValidId): ODTicketData<ODValidJsonType>|null {
return super.get(id)
}
remove<OptionId extends keyof ODTicketIds>(id:OptionId): ODTicketIds[OptionId]
remove(id:ODValidId): ODTicketData<ODValidJsonType>|null
remove(id:ODValidId): ODTicketData<ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODTicketIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
export class ODTicketData<DataType extends ODValidJsonType> extends ODManagerData {
#value: DataType
constructor(id:ODValidId, value:DataType){
super(id)
this.#value = value
}
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODTicketData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}
export type ODTicketClearFilter = "all"|"open"|"closed"|"claimed"|"unclaimed"|"pinned"|"unpinned"|"autoclosed"
+802
View File
@@ -0,0 +1,802 @@
///////////////////////////////////////
//OPENTICKET TRANSCRIPT MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidJsonType, ODValidId, ODManagerData, ODValidButtonColor } from "../modules/base"
import { ODDebugger } from "../modules/console"
import { ODTicket, ODTicketManager } from "./ticket"
import { ODMessageBuildResult } from "../modules/builder"
import * as discord from "discord.js"
export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any>> {
/**The manager responsible for collecting all messages in a channel. */
collector: ODTranscriptCollector
constructor(debug:ODDebugger, tickets:ODTicketManager){
super(debug,"transcript compiler")
this.collector = new ODTranscriptCollector(tickets)
}
}
export type ODTranscriptCompilerInitFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult)|Promise<ODTranscriptCompilerInitResult>
export type ODTranscriptCompilerCompileFunction<Data extends object> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => ODTranscriptCompilerCompileResult<Data>|Promise<ODTranscriptCompilerCompileResult<Data>>
export type ODTranscriptCompilerReadyFunction<Data extends object> = (result:ODTranscriptCompilerCompileResult<Data>) => ODTranscriptCompilerReadyResult|Promise<ODTranscriptCompilerReadyResult>
export interface ODTranscriptCompilerInitResult {
success:boolean,
errorReason:string|null,
pendingMessage:ODMessageBuildResult|null
}
export interface ODTranscriptCompilerCompileResult<Data extends object> {
ticket:ODTicket,
channel:discord.TextChannel,
user:discord.User
success:boolean,
errorReason:string|null,
messages:ODTranscriptMessageData[]|null,
data:Data|null
}
export interface ODTranscriptCompilerReadyResult {
channelMessage?:ODMessageBuildResult,
creatorDmMessage?:ODMessageBuildResult,
participantDmMessage?:ODMessageBuildResult,
activeAdminDmMessage?:ODMessageBuildResult,
everyAdminDmMessage?:ODMessageBuildResult
}
export class ODTranscriptCompiler<Data extends object> extends ODManagerData {
/*Initialise the system every time a transcript is created. Returns optional "pending" message to display while the transcript is being compiled. */
init: ODTranscriptCompilerInitFunction|null
/*Compile or create the transcript. Returns data to give to the ready() function for message creation. */
compile: ODTranscriptCompilerCompileFunction<Data>|null
/*Unload the system & create the final transcript message that will be sent. */
ready: ODTranscriptCompilerReadyFunction<Data>|null
constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction, compile?:ODTranscriptCompilerCompileFunction<Data>, ready?:ODTranscriptCompilerReadyFunction<Data>|null){
super(id)
this.init = init ?? null
this.compile = compile ?? null
this.ready = ready ?? null
}
}
/**## ODTranscriptCompilerIds `type`
* This type is an array of ids available in the `ODTranscriptCompiler` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODTranscriptCompilerIds {
"openticket:html-compiler":ODTranscriptCompiler<{url:string}>,
"openticket:text-compiler":ODTranscriptCompiler<{contents:string}>,
}
/**## ODTranscriptManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODTranscriptManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `openticket.transcripts`!
*/
export class ODTranscriptManager_Default extends ODTranscriptManager {
get<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
get(id:ODValidId): ODTranscriptCompiler<any>|null
get(id:ODValidId): ODTranscriptCompiler<any>|null {
return super.get(id)
}
remove<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
remove(id:ODValidId): ODTranscriptCompiler<any>|null
remove(id:ODValidId): ODTranscriptCompiler<any>|null {
return super.remove(id)
}
exists(id:keyof ODTranscriptCompilerIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
export class ODTranscriptCollector {
/**Alias for the ticket manager. */
#tickets: ODTicketManager
constructor(tickets:ODTicketManager){
this.#tickets = tickets
}
/**Collect all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */
async collectAllMessages(ticket:ODTicket, include?:ODTranscriptCollectorIncludeSettings): Promise<discord.Message<true>[]|null> {
const newInclude: ODTranscriptCollectorIncludeSettings = include ?? {users:true,bots:true,client:true}
const channel = await this.#tickets.getTicketChannel(ticket)
if (!channel) return null
const final: discord.Message<true>[] = []
const limit: number = 2000
let lastId: string = ""
while (true){
const options: discord.FetchMessagesOptions = {limit:100}
if (lastId) options.before = lastId
const messages = await channel.messages.fetch(options)
messages.forEach(msg => {
if (msg.author.id == msg.client.user.id && newInclude.client) final.push(msg)
else if ((msg.author.bot || msg.author.system) && newInclude.bots) final.push(msg)
else if (newInclude.users) final.push(msg)
})
const lastMessage = messages.last()
if (messages.size != 100 || final.length >= limit || !lastMessage) break
else lastId = lastMessage.id
}
return final.reverse()
}
/**Count all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */
async countAllMessages(ticket:ODTicket, include?:ODTranscriptCollectorIncludeSettings){
const messages = await this.collectAllMessages(ticket,include)
if (!messages) return null
return messages.length
}
async convertMessagesToTranscriptData(messages:discord.Message<true>[]): Promise<ODTranscriptMessageData[]> {
const final: ODTranscriptMessageData[] = []
for (const msg of messages){
const {guild,channel,id,createdTimestamp} = msg
//create message author
const author = this.#handleUserData(msg.author,msg.member)
//create message type
let type: ODTranscriptMessageType = "default"
if (msg.mentions.everyone || msg.content.includes("@here")) type = "important"
else if (msg.flags.has("Ephemeral")) type = "ephemeral"
else if (msg.type == discord.MessageType.UserJoin) type = "welcome.message"
else if (msg.type == discord.MessageType.ChannelPinnedMessage) type = "pinned.message"
else if (msg.type == discord.MessageType.GuildBoost || msg.type == discord.MessageType.GuildBoostTier1 || msg.type == discord.MessageType.GuildBoostTier2 || msg.type == discord.MessageType.GuildBoostTier3) type = "boost.message"
else if (msg.type == discord.MessageType.ThreadCreated) type = "thread.message"
//create message embeds
const embeds: ODTranscriptEmbedData[] = []
msg.embeds.forEach((embed) => {
embeds.push({
title:embed.title,
description:embed.description,
authorimg:(embed.author && embed.author.iconURL) ? embed.author.iconURL : null,
authortext:(embed.author) ? embed.author.name : null,
footerimg:(embed.footer && embed.footer.iconURL) ? embed.footer.iconURL : null,
footertext:(embed.footer) ? embed.footer.text : null,
color:(embed.hexColor as discord.HexColorString) ?? "#000000",
image:(embed.image) ? embed.image.url : null,
thumbnail:(embed.thumbnail) ? embed.thumbnail.url : null,
url:embed.url,
fields:embed.fields.map((field) => {return {name:field.name,value:field.value,inline:field.inline ?? false}})
})
})
//create message files
const files: ODTranscriptFileData[] = []
msg.attachments.forEach((attachment) => {
const {size,unit} = this.calculateFileSize(attachment.size)
files.push({
type:attachment.contentType ?? "unknown",
size,
unit,
name:attachment.name,
url:attachment.url,
spoiler:attachment.spoiler,
alt:attachment.description
})
})
//create message components
const rows: ODTranscriptComponentRowData[] = []
msg.components.forEach((row) => {
const components: ODTranscriptComponentRowData["components"] = []
row.components.forEach((component) => {
if (component.type == discord.ComponentType.Button){
components.push({
id:component.customId,
disabled:component.disabled,
type:"button",
label:component.label,
emoji:this.#handleComponentEmoji(msg,component.emoji),
color:this.#handleButtonComponentStyle(component.style),
mode:(component.style == discord.ButtonStyle.Link) ? "url" : "button",
url:component.url
})
}else if (component.type == discord.ComponentType.StringSelect){
components.push({
id:component.customId,
disabled:component.disabled,
type:"dropdown",
placeholder:component.placeholder,
options:component.options.map((option) => {
return {
id:option.value,
label:option.label,
description:option.description ?? null,
emoji:this.#handleComponentEmoji(msg,option.emoji ?? null)
}
})
})
}
})
rows.push({components})
})
//create message reply
let reply: ODTranscriptMessageReplyData|ODTranscriptInteractionReplyData|null = null
if (msg.reference && msg.reference.messageId && msg.reference.guildId){
//normal message reply
try{
const replyChannel = await msg.client.channels.fetch(msg.reference.channelId)
if (replyChannel && !replyChannel.isDMBased() && replyChannel.isTextBased()){
const replyMessage = await replyChannel.messages.fetch(msg.reference.messageId)
if (replyMessage){
const replyUser = this.#handleUserData(replyMessage.author,replyMessage.member)
reply = {
type:"message",
guild:msg.reference.guildId,
channel:msg.reference.channelId,
id:msg.reference.messageId,
user:replyUser,
content:(replyMessage.content != "") ? replyMessage.content : null
}
}
}
}catch{}
}else if (msg.interaction && msg.interaction.type == discord.InteractionType.ApplicationCommand){
//slash command reply
const member = await msg.guild.members.fetch(msg.interaction.user.id)
reply = {
type:"interaction",
name:msg.interaction.commandName,
user:this.#handleUserData(msg.interaction.user,member)
}
}
//create message reactions
const reactions: ODTranscriptReactionData[] = []
msg.reactions.cache.forEach((reaction) => {
const {count,emoji} = reaction
if (emoji instanceof discord.ReactionEmoji && !emoji.id && emoji.name){
//build-in emoji
reactions.push({
id:null,
name:null,
custom:false,
animated:false,
emoji:emoji.name,
amount:count,
super:false //unimplemented in discord.js
})
}else if (emoji instanceof discord.ReactionEmoji && emoji.id){
//custom emoji
reactions.push({
id:emoji.id,
name:emoji.name,
custom:true,
animated:emoji.animated ?? false,
emoji:(emoji.animated ? emoji.imageURL({extension:"gif"}) : emoji.imageURL({extension:"png"})) ?? "❌",
amount:count,
super:false //unimplemented in discord.js
})
}
})
//create message
final.push({
author,
guild:guild.id,
channel:channel.id,
id,
edited:(msg.editedAt) ? true : false,
timestamp:createdTimestamp,
type,
content:(msg.content != "") ? msg.content : null,
embeds,
files,
components:rows,
reply,
reactions
})
}
return final
}
/**Calculate a human-readable file size. Used in transcripts. */
calculateFileSize(bytes:number): {size:number, unit:"B"|"KB"|"MB"|"GB"|"TB"} {
if (bytes >= 1000000000000) return {size:(Math.round((bytes/1000000000000)*100)/100),unit:"TB"}
if (bytes >= 1000000000) return {size:(Math.round((bytes/1000000000)*100)/100),unit:"GB"}
else if (bytes >= 1000000) return {size:(Math.round((bytes/1000000)*100)/100),unit:"MB"}
else if (bytes >= 1000) return {size:(Math.round((bytes/1000)*100)/100),unit:"KB"}
else return {size:bytes,unit:"B"}
}
/**Get the `ODTranscriptEmojiData` from a discord.js component emoji. */
#handleComponentEmoji(message:discord.Message<true>, rawEmoji:discord.APIMessageComponentEmoji|null): ODTranscriptEmojiData|null {
if (!rawEmoji) return null
//return built-in emoji
if (rawEmoji.name) return {
id:null,
name:null,
custom:false,
animated:false,
emoji:rawEmoji.name
}
if (!rawEmoji.id) return null
const emoji = message.client.emojis.resolve(rawEmoji.id)
if (!emoji) return null
//return custom emoji
return {
id:emoji.id,
name:emoji.name,
custom:true,
animated:emoji.animated ?? false,
emoji:(emoji.animated ? emoji.imageURL({extension:"gif"}) : emoji.imageURL({extension:"png"}))
}
}
/**Create the `ODValidButtonColor` from the discord.js button style. */
#handleButtonComponentStyle(style:discord.ButtonStyle): ODValidButtonColor {
if (style == discord.ButtonStyle.Danger) return "red"
else if (style == discord.ButtonStyle.Success) return "green"
else if (style == discord.ButtonStyle.Primary) return "blue"
else return "gray"
}
/**Create the `ODTranscriptUserData` from a discord.js user. */
#handleUserData(user:discord.User, member?:discord.GuildMember|null): ODTranscriptUserData {
const userData: ODTranscriptUserData = {
id:user.id,
username:user.username,
displayname:user.displayName,
pfp:user.displayAvatarURL(),
tag:null,
color:"#ffffff"
}
if (user.flags && user.flags.has("VerifiedBot")) userData.tag = "verified"
else if (user.system) userData.tag = "system"
else if (user.bot) userData.tag = "app"
if (member) userData.color = member.roles.highest.hexColor.replace("#000000","#ffffff") as discord.HexColorString
return userData
}
}
export interface ODTranscriptCollectorIncludeSettings {
/**Collect messages from normal discord users. */
users: boolean,
/**Collect messages from bots & system users. */
bots: boolean,
/**Collect messages from this bot. */
client: boolean
}
export interface ODTranscriptMessageData {
/**The message author. */
author: ODTranscriptUserData,
/**The server this message originated from. */
guild: string,
/**The channel this message originated from. */
channel: string,
/**The id of this message. */
id: string,
/**Is this message edited? */
edited: boolean,
/**The unix timestamp of the creation of this message. */
timestamp: number,
/**The type of message. */
type: ODTranscriptMessageType,
/**The contents of this message. */
content: string|null,
/**The embeds of this message. */
embeds: ODTranscriptEmbedData[],
/**The files of this message. */
files: ODTranscriptFileData[],
/**The components (buttons & dropdowns) of this message. */
components: ODTranscriptComponentRowData[],
/**When this message is a reply to something, the data will be here. */
reply: (ODTranscriptMessageReplyData|ODTranscriptInteractionReplyData|null),
/**All reactions of htis message. */
reactions: ODTranscriptReactionData[]
}
export type ODTranscriptMessageType = "default"|"important"|"ephemeral"|"pinned.message"|"welcome.message"|"boost.message"|"thread.message"
export interface ODTranscriptUserData {
/**The id of this user. */
id: string,
/**The username of this user. */
username: string,
/**The display name of this user. */
displayname: string,
/**The profile picture url of this user. */
pfp: string,
/**The additional tag of this user. */
tag: "app"|"verified"|"system"|null,
/**When in a server, this is the color of the highest role. */
color: discord.HexColorString
}
export interface ODTranscriptEmbedData {
/**The title of this embed. */
title: string|null,
/**The description of this embed. */
description: string|null,
/**The author image of this embed. */
authorimg: string|null,
/**The author text of this embed. */
authortext: string|null,
/**The footer image of this embed. */
footerimg: string|null
/**The footer text of this embed. */
footertext: string|null,
/**The color of this embed (hex color). */
color: discord.HexColorString,
/**The image of this embed. */
image: string|null,
/**The thumbnail of this embed. */
thumbnail: string|null,
/**The url in the title of this embed. */
url: string|null,
/**All fields available in this embed. */
fields: ODTranscriptEmbedFieldData[]
}
export interface ODTranscriptEmbedFieldData {
/**The name of this embed field. */
name: string,
/**The value or contents of this embed field. */
value: string,
/**Is this field rendered inline? */
inline: boolean
}
export interface ODTranscriptFileData {
/**The file type or extension. */
type: string,
/**The size of this file. */
size: number,
/**The unit used for the size of this file. */
unit: "B"|"KB"|"MB"|"GB"|"TB",
/**The name of this file. */
name: string,
/**The url of this file. */
url: string,
/**Is this file a spoiler? */
spoiler: boolean,
/**The alternative text for this file. */
alt: string|null
}
export interface ODTranscriptComponentRowData {
/**All components (buttons & dropdowns) present in this action row. */
components: (ODTranscriptButtonComponentData|ODTranscriptDropdownComponentData)[]
}
export interface ODTranscriptComponentData {
/**The custom id of this component. */
id: string|null,
/**Is this component disabled? */
disabled: boolean
/**The type of this component. */
type: "button"|"dropdown"
}
export interface ODTranscriptButtonComponentData extends ODTranscriptComponentData {
/**The type of this component. */
type: "button"
/**The label of this button. */
label: string|null,
/**The emoji of this button. */
emoji: ODTranscriptEmojiData|null,
/**The color of this button. */
color: ODValidButtonColor,
/**Is this button a url or button? */
mode: "url"|"button",
/**The url of this button. */
url: string|null
}
export interface ODTranscriptDropdownComponentData extends ODTranscriptComponentData {
/**The type of this component. */
type: "dropdown"
/**The placeholder in this dropdown. */
placeholder: string|null,
/**All options available in this dropdown. */
options: ODTranscriptDropdownComponentOptionData[]
}
export interface ODTranscriptDropdownComponentOptionData {
/**The custom id of this dropdown option. */
id: string,
/**The label of this dropdown option. */
label: string|null,
/**The description of this dropdown option. */
description: string|null,
/**The emoji of this dropdown option. */
emoji: ODTranscriptEmojiData|null
}
export interface ODTranscriptReplyData {
/**The type of reply. */
type: "interaction"|"message",
}
export interface ODTranscriptInteractionReplyData extends ODTranscriptReplyData {
/**The type of reply. */
type: "interaction",
/**The bot used for this interaction. */
user: ODTranscriptUserData,
/**The name of the slash command used. */
name: string
}
export interface ODTranscriptMessageReplyData extends ODTranscriptReplyData {
/**The type of reply. */
type: "message",
/**The server this message originated from. */
guild: string,
/**The channel this message originated from. */
channel: string,
/**The id of this message. */
id: string,
/**The author of this message. */
user: ODTranscriptUserData,
/**The content of this message. */
content: string|null
}
export interface ODTranscriptEmojiData {
/**The id of this emoji. */
id: string|null,
/**The name of this emoji. */
name: string|null,
/**Is this emoji animated? */
animated: boolean,
/**Is this a custom emoji (img/gif)? */
custom: boolean,
/**The url or emoji. */
emoji: string,
}
export interface ODTranscriptReactionData extends ODTranscriptEmojiData {
/**The amount of emojis for this reaction. */
amount: number,
/**Is this a super (nitro) reaction? */
super: boolean
}
export interface ODTranscriptHtmlV2Data {
version:"2",
otversion:string,
language:string,
style:{
background:{
enableCustomBackground:boolean,
backgroundModus:"color"|"image",
backgroundData:string
},
header:{
enableCustomHeader:boolean,
decoColor:string,
backgroundColor:string,
textColor:string
},
stats:{
enableCustomStats:boolean,
backgroundColor:string,
keyTextColor:string,
valueTextColor:string,
hideBackgroundColor:string,
hideTextColor:string
},
favicon:{
enableCustomFavicon:boolean,
imageUrl:string
}
},
bot:{
name:string,
id:string,
pfp:string
},
ticket:{
name:string,
id:string,
guildname:string,
guildid:string,
guildinvite:string|false,
creatorname:string,
creatorid:string,
closedbyname:string,
closedbyid:string,
claimedname:string,
claimedid:string,
creatorpfp:string,
closedbypfp:string,
claimedpfp:string,
closedtime:number,
openedtime:number,
components:{
messages:number,
files:number,
embeds:number,
reactions:number,
interactions:{
dropdowns:number,
buttons:number,
total:number
},
attachments:{
invites:number,
images:number,
gifs:number,
stickers:number
}
},
roleColors:{id:string,color:string}[]
},
messages:{
author:{
name:string,
id:string,
color:string,
pfp:string,
bot:boolean,
verifiedBot:boolean,
system:boolean
},
content:string|false,
timestamp:number,
type:"normal",
important:boolean,
edited:boolean,
embeds:{
title:string|false,
description:string|false,
authorimg:string|false,
authortext:string|false,
footerimg:string|false,
footertext:string|false,
color:string,
image:string|false,
thumbnail:string|false,
url:string|false,
fields:{name:string,value:string,inline:boolean}[]
}[],
attachments:(
{
type:"FILE",
name:string,
fileType:string,
size:string,
url:string
}|{
type:"FILE:image",
name:string,
fileType:string,
size:string,
url:string
}|{
type:"URL:invite",
guildId:string,
guildName:string,
guildSize:Number,
guildOnline:Number,
image:string,
url:string
}|{
type:"URL:gif",
url:string
}|{
type:"BUILDIN:sticker",
name:string,
url:string
}
)[],
components:(
{
type:"buttons",
buttons:{
type:"interaction"|"url",
label:string|false,
icon:string|false,
color:"gray"|"green"|"red"|"blue",
id:string|false,
url:string|false,
disabled:boolean
}[]
}|{
type:"dropdown",
placeholder:string|false,
options:{
label:string|false,
icon:string|false,
description:string|false,
id:string|false
}[]
}|{
type:"reactions",
reactions:{
amount:number,
emoji:string,
type:"svg"|"image"|"gif"
}[]
}
)[],
reply:{
type:"reply"|"command"|false,
user?:{
name:string,
id:string,
color:string,
pfp:string,
bot:Boolean,
verifiedBot:Boolean,
system:Boolean
},
replyOptions?:{
content:string,
messageId:string,
channelId:string,
guildId:string
},
commandOptions?:{
interactionName:string,
interactionId:string
}
}
}[],
premium:{
enabled:boolean,
premiumToken:string,
customCredits:{
enable:boolean,
replaceText:string,
replaceURL:string,
enableReportBug:boolean
},
customHeaderUrl:{
enabled:boolean,
url:string,
text:string
},
customTranscriptUrl:{
enabled:boolean,
name:string
},
customFavicon:{
enabled:boolean,
image:string
},
additionalFlags:string[]
}
}
export interface ODTranscriptHtmlV2Response {
status:"success"|"error",
id:string,
time:number,
estimated:{
lastdump: number,
processtime:number,
waittime:number
},
transcriptstatus:{
value:2,
data:{
fetchedmsgs:true,
uploaded:true,
inqueue:true,
processed:false,
waiting:false,
available:false
}
}
}
+205
View File
@@ -0,0 +1,205 @@
import * as fs from "fs"
let tempErrors: string[] = []
const tempError = () => {
if (tempErrors.length > 0){
console.log("\n\n==============================\n[OPEN TICKET ERROR]: "+tempErrors.join("\n[OPEN TICKET ERROR]: ")+"\n==============================\n\n")
process.exit(0)
}
tempErrors = []
}
const nodev = process.versions.node.split(".")
if (Number(nodev[0]) < 18){
tempErrors.push("Invalid node.js version. Open Ticket requires node.js v18 or above!")
}
tempError()
const moduleInstalled = (id:string, throwError:boolean) => {
try{
require.resolve(id)
return true
}catch{
if (throwError) tempErrors.push("npm module \""+id+"\" is not installed! Install it via 'npm install "+id+"'")
return false
}
}
moduleInstalled("discord.js",true)
moduleInstalled("ansis",true)
moduleInstalled("formatted-json-stringify",true)
moduleInstalled("tsx",true)
tempError()
//init API
import * as api from "../api/api" //import for local use
export * as api from "../api/api" //export to other parts of bot
export const openticket = new api.ODMain()
console.log("\n--------------------------- OPEN TICKET STARTUP ---------------------------")
openticket.log("Logging system activated!","system")
openticket.debug.debug("Using Node.js "+process.version+"!")
try{
const packageJson = JSON.parse(fs.readFileSync("./package.json").toString())
openticket.debug.debug("Using discord.js "+packageJson.dependencies["discord.js"]+"!")
openticket.debug.debug("Using ansis "+packageJson.dependencies["ansis"]+"!")
openticket.debug.debug("Using formatted-json-stringify "+packageJson.dependencies["formatted-json-stringify"]+"!")
openticket.debug.debug("Using tsx "+packageJson.dependencies["tsx"]+"!")
}catch{
openticket.debug.debug("Failed to fetch module versions!")
}
const timer = (ms:number): Promise<void> => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
},ms)
})
}
interface ODUtilities {
/**## project `utility variable`
* This is the name of the project you are currently in.
*
* Developers can use this to create a multi-plugin compatible with all bots supporting the `open-discord` framework!
*/
project:"openticket"
/**## isBeta `utility variable`
* Check if you're running a beta version of Open Ticket.
*/
isBeta:boolean
/**## moduleInstalled `utility function`
* Use this function to check if an npm package is installed or not!
* @example utilities.moduleInstalled("discord.js") //check if discord.js is installed
*/
moduleInstalled(id:string): boolean
/**## timer `utility function`
* Use this to wait for a certain amount of milliseconds. This only works when using `await`
* @example await utilities.timer(1000) //wait 1sec
*/
timer(ms:number): Promise<void>
/**## emojiTitle `utility function`
* Use this function to create a title with an emoji before/after the text. The style & divider are set in `openticket.defaults`
* @example utilities.emojiTitle("📎","Links") //create a title with an emoji based on the bot emoji style
*/
emojiTitle(emoji:string, text:string): string
/**## runAsync `utility function`
* Use this function to run a piece of code asyncronous without creating a separate function for it!
*/
runAsync(func:() => Promise<void>): void
/**## timedAwait `utility function`
* Use this function to await a promise but reject after the certain timeout has been reached.
*/
timedAwait<ReturnValue extends Promise<any>>(promise:ReturnValue, timeout:number, onError:(err:Error) => void): ReturnValue
/**## dateString `utility function`
* Use this function to create a short date string in the following format: `DD/MM/YYYY HH:MM:SS`
*/
dateString(date:Date): string
/**## asyncReplace `utility function`
* Same as `string.replace(search, value)` but with async compatibility
*/
asyncReplace(text:string, regex:RegExp, func:(value:string,...args:any[]) => Promise<string>): Promise<string>
/**## easterEggs `utility object`
* Object containing data for Open Ticket easter eggs.
*/
easterEggs: api.ODEasterEggs,
/**## ODVersionMigration `utility class`
* This class is used to manage data migration between Open Ticket versions.
*
* It shouldn't be used by plugins because this is an internal API feature!
*/
ODVersionMigration:new (version:api.ODVersion,func:() => void|Promise<void>) => ODVersionMigration
}
/**## ODVersionMigration `utility class`
* This class is used to manage data migration between Open Ticket versions.
*
* It shouldn't be used by plugins because this is an internal API feature!
*/
class ODVersionMigration {
/**The version to migrate data to */
version: api.ODVersion
/**The migration function */
#func: () => void|Promise<void>
constructor(version:api.ODVersion,func:() => void|Promise<void>){
this.version = version
this.#func = func
}
/**Run this version migration as a plugin. Returns `false` when someting goes wrong. */
async migrate(): Promise<boolean> {
try{
await this.#func()
return true
}catch{
return false
}
}
}
export const utilities: ODUtilities = {
project:"openticket",
isBeta:true,
moduleInstalled:(id:string) => {
return moduleInstalled(id,false)
},
timer,
emojiTitle(emoji:string, text:string){
const style = openticket.defaults.getDefault("emojiTitleStyle")
const divider = openticket.defaults.getDefault("emojiTitleDivider")
if (style == "disabled") return text
else if (style == "before") return emoji+divider+text
else if (style == "after") return text+divider+emoji
else if (style == "double") return emoji+divider+text+divider+emoji
else return text
},
runAsync(func){
func()
},
timedAwait<ReturnValue>(promise:ReturnValue,timeout:number,onError:(err:Error) => void): ReturnValue {
let allowResolve = true
return new Promise(async (resolve,reject) => {
//set timeout & stop if it is before the promise resolved
setTimeout(() => {
allowResolve = false
reject("utilities.timedAwait() => Promise Timeout")
},timeout)
//get promise result & return if not already rejected
try{
const res = await promise
if (allowResolve) resolve(res)
}catch(err){
onError(err)
}
return promise
}) as ReturnValue
},
dateString(date): string {
return `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
},
async asyncReplace(text,regex,func): Promise<string> {
const promises: Promise<string>[] = []
text.replace(regex,(match,...args) => {
promises.push(func(match,...args))
return match
})
const data = await Promise.all(promises)
const result = text.replace(regex,(match) => {
const replaceResult = data.shift()
return replaceResult ?? match
})
return result
},
easterEggs:{
creator:"779742674932072469",
translators:[
"779742674932072469"
]
},
ODVersionMigration
}
+84
View File
@@ -0,0 +1,84 @@
import {openticket, api, utilities} from "../../index"
export const loadVersionMigrationSystem = async () => {
//ENTER MIGRATION CONTEXT
await preloadMigrationContext()
const lastVersion = isMigrationRequired()
openticket.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",openticket.versions.get("openticket:version").toString()))
if (lastVersion && !openticket.flags.get("openticket:no-migration").value){
//MIGRATION IS REQUIRED
openticket.log("Detected old data!","info")
openticket.log("Starting closed API context...","debug")
await utilities.timer(600)
openticket.log("Migrating data to new version...","debug")
await loadAllVersionMigrations(lastVersion)
openticket.log("Stopping closed API context...","debug")
await utilities.timer(400)
openticket.log("All data is now up to date!","info")
await utilities.timer(200)
console.log("---------------------------------------------------------------------")
}
saveAllVersionsToDatabase()
//DEFAULT FLAGS
if (openticket.flags.exists("openticket:no-plugins") && openticket.flags.get("openticket:no-plugins").value) openticket.defaults.setDefault("pluginLoading",false)
if (openticket.flags.exists("openticket:soft-plugins") && openticket.flags.get("openticket:soft-plugins").value) openticket.defaults.setDefault("softPluginLoading",true)
if (openticket.flags.exists("openticket:crash") && openticket.flags.get("openticket:crash").value) openticket.defaults.setDefault("crashOnError",true)
if (openticket.flags.exists("openticket:force-slash-update") && openticket.flags.get("openticket:force-slash-update").value) openticket.defaults.setDefault("forceSlashCommandRegistration",true)
//LEAVE MIGRATION CONTEXT
await unloadMigrationContext()
}
const preloadMigrationContext = async () => {
openticket.debug.debug("-- MIGRATION CONTEXT START --")
await (await import("../../data/framework/flagLoader.ts")).loadAllFlags()
openticket.flags.init()
await (await import("../../data/framework/configLoader.ts")).loadAllConfigs()
await (await import("../../data/framework/databaseLoader.ts")).loadAllDatabases()
openticket.debug.visible = true
}
const unloadMigrationContext = async () => {
openticket.debug.visible = false
openticket.databases.getAll().forEach((database) => openticket.databases.remove(database.id))
openticket.configs.getAll().forEach((config) => openticket.configs.remove(config.id))
openticket.flags.getAll().forEach((flag) => openticket.flags.remove(flag.id))
openticket.debug.debug("-- MIGRATION CONTEXT END --")
}
const isMigrationRequired = (): false|api.ODVersion => {
const rawVersion = openticket.databases.get("openticket:global").get("openticket:last-version","openticket:version")
if (!rawVersion) return false
const version = api.ODVersion.fromString("openticket:last-version",rawVersion)
if (openticket.versions.get("openticket:version").compare(version) == "higher"){
return version
}else return false
}
const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => {
const migrations = (await import("./migration.ts")).migrations
migrations.sort((a,b) => {
const comparison = a.version.compare(b.version)
if (comparison == "equal") return 0
else if (comparison == "higher") return 1
else return -1
})
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrate()
if (success) openticket.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"}
])
}
}
}
const saveAllVersionsToDatabase = async () => {
const globalDatabase = openticket.databases.get("openticket:global")
openticket.versions.getAll().forEach((version) => {
globalDatabase.set("openticket:last-version",version.id.value,version.toString())
})
}
+8
View File
@@ -0,0 +1,8 @@
import {openticket, api, utilities} from "../../index"
export const migrations = [
//MIGRATE TO v4.0.0
new utilities.ODVersionMigration(api.ODVersion.fromString("openticket:version","v4.0.0"),async () => {
//nothing needs to be transferred :)
})
]
+197
View File
@@ -0,0 +1,197 @@
import {openticket, api, utilities} from "../../index"
import fs from "fs"
import { ODPluginError } from "../api/api"
export const loadAllPlugins = async () => {
//start launching plugins
openticket.log("Loading plugins...","system")
let initPluginError: boolean = false
if (!fs.existsSync("./plugins")){
openticket.log("Couldn't find ./plugins directory, canceling all plugin execution!","error")
return
}
const plugins = fs.readdirSync("./plugins")
//check & validate
plugins.forEach(async (p) => {
//prechecks
if (!fs.statSync("./plugins/"+p).isDirectory()) return openticket.log("Plugin is not a directory, canceling plugin execution...","plugin",[
{key:"plugin",value:"./plugins/"+p}
])
if (!fs.existsSync("./plugins/"+p+"/plugin.json")){
initPluginError = true
openticket.log("Plugin doesn't have a plugin.json, canceling plugin execution...","plugin",[
{key:"plugin",value:"./plugins/"+p}
])
return
}
//plugin loading
try {
const rawplugindata: api.ODPluginData = JSON.parse(fs.readFileSync("./plugins/"+p+"/plugin.json").toString())
if (typeof rawplugindata != "object") throw new ODPluginError("Failed to load plugin.json")
if (typeof rawplugindata.id != "string") throw new ODPluginError("Failed to load plugin.json/id")
if (typeof rawplugindata.name != "string") throw new ODPluginError("Failed to load plugin.json/name")
if (typeof rawplugindata.version != "string") throw new ODPluginError("Failed to load plugin.json/version")
if (typeof rawplugindata.startFile != "string") throw new ODPluginError("Failed to load plugin.json/startFile")
if (typeof rawplugindata.enabled != "boolean") throw new ODPluginError("Failed to load plugin.json/enabled")
if (typeof rawplugindata.priority != "number") throw new ODPluginError("Failed to load plugin.json/priority")
if (!Array.isArray(rawplugindata.events)) throw new ODPluginError("Failed to load plugin.json/events")
if (!Array.isArray(rawplugindata.npmDependencies)) throw new ODPluginError("Failed to load plugin.json/npmDependencies")
if (!Array.isArray(rawplugindata.requiredPlugins)) throw new ODPluginError("Failed to load plugin.json/requiredPlugins")
if (!Array.isArray(rawplugindata.incompatiblePlugins)) throw new ODPluginError("Failed to load plugin.json/incompatiblePlugins")
if (typeof rawplugindata.details != "object") throw new ODPluginError("Failed to load plugin.json/details")
if (typeof rawplugindata.details.author != "string") throw new ODPluginError("Failed to load plugin.json/details/author")
if (typeof rawplugindata.details.shortDescription != "string") throw new ODPluginError("Failed to load plugin.json/details/shortDescription")
if (typeof rawplugindata.details.longDescription != "string") throw new ODPluginError("Failed to load plugin.json/details/longDescription")
if (typeof rawplugindata.details.imageUrl != "string") throw new ODPluginError("Failed to load plugin.json/details/imageUrl")
if (typeof rawplugindata.details.projectUrl != "string") throw new ODPluginError("Failed to load plugin.json/details/projectUrl")
if (!Array.isArray(rawplugindata.details.tags)) throw new ODPluginError("Failed to load plugin.json/details/tags")
if (rawplugindata.id != p) throw new ODPluginError("Failed to load plugin, directory name is required to match the id")
if (openticket.plugins.exists(rawplugindata.id)) throw new ODPluginError("Failed to load plugin, this id already exists in another plugin")
//plugin.json is valid => load plugin
const plugin = new api.ODPlugin(p,rawplugindata)
openticket.plugins.add(plugin)
}catch(e){
//when any of the above errors happen, crash the bot when soft mode isn't enabled
initPluginError = true
openticket.log(e.message+", canceling plugin execution...","plugin",[
{key:"path",value:"./plugins/"+p}
])
openticket.log("You can see more about this error in the ./otdebug.txt file!","info")
openticket.debugfile.writeText(e.stack)
//try to get some crashed plugin data
try{
const rawplugindata: api.ODPluginData = JSON.parse(fs.readFileSync("./plugins/"+p+"/plugin.json").toString())
openticket.plugins.unknownCrashedPlugins.push({
name:rawplugindata.name ?? "./plugins/"+p,
description:(rawplugindata.details && rawplugindata.details.shortDescription) ? rawplugindata.details.shortDescription : "This plugin crashed :(",
})
}catch{}
}
})
//sorted plugins (based on priority)
const sortedPlugins = openticket.plugins.getAll().sort((a,b) => {
return (b.priority - a.priority)
})
//check for incompatible & missing plugins/dependencies
const incompatibilities: {from:string,to:string}[] = []
const missingDependencies: {id:string,missing:string}[] = []
const missingPlugins: {id:string,missing:string}[] = []
//go trough all plugins for errors
sortedPlugins.forEach((plugin) => {
const from = plugin.id.value
plugin.data.incompatiblePlugins.forEach((to) => {
//deny incompatibility if it already exists
if (incompatibilities.find((p) => (p.from == from && p.to == to) || (p.to == from && p.from == to))) return
//check for existence of both plugins => add to list
if (openticket.plugins.exists(to)) incompatibilities.push({from,to})
})
plugin.dependenciesInstalled().forEach((missing) => missingDependencies.push({id:from,missing}))
plugin.pluginsInstalled(openticket.plugins).forEach((missing) => missingPlugins.push({id:from,missing}))
})
//handle all incompatibilities
incompatibilities.forEach((match) => {
const fromPlugin = openticket.plugins.get(match.from)
if (fromPlugin && !fromPlugin.crashed){
fromPlugin.crashed = true
fromPlugin.crashReason = "incompatible.plugin"
}
const toPlugin = openticket.plugins.get(match.to)
if (toPlugin && !toPlugin.crashed){
toPlugin.crashed = true
toPlugin.crashReason = "incompatible.plugin"
}
openticket.log(`Incompatible plugins => "${match.from}" & "${match.to}", canceling plugin execution...`,"plugin",[
{key:"path1",value:"./plugins/"+match.from},
{key:"path2",value:"./plugins/"+match.to}
])
initPluginError = true
})
//handle all missing dependencies
missingDependencies.forEach((match) => {
const plugin = openticket.plugins.get(match.id)
if (plugin && !plugin.crashed){
plugin.crashed = true
plugin.crashReason = "missing.dependency"
}
openticket.log(`Missing npm dependency "${match.missing}", canceling plugin execution...`,"plugin",[
{key:"path",value:"./plugins/"+match.id}
])
initPluginError = true
})
//handle all missing plugins
missingPlugins.forEach((match) => {
const plugin = openticket.plugins.get(match.id)
if (plugin && !plugin.crashed){
plugin.crashed = true
plugin.crashReason = "missing.plugin"
}
openticket.log(`Missing required plugin "${match.missing}", canceling plugin execution...`,"plugin",[
{key:"path",value:"./plugins/"+match.id}
])
initPluginError = true
})
//exit on error (when soft mode disabled)
if (!openticket.defaults.getDefault("softPluginLoading") && initPluginError){
console.log("")
openticket.log("Please fix all plugin errors above & try again!","error")
process.exit(1)
}
//preload all events required for every plugin
for (const plugin of sortedPlugins){
if (plugin.enabled) plugin.data.events.forEach((event) => openticket.events.add(new api.ODEvent(event)))
}
//execute all working plugins
for (const plugin of sortedPlugins){
const status = await plugin.execute(openticket.debug,false)
//exit on error (when soft mode disabled)
if (!status && !openticket.defaults.getDefault("softPluginLoading")){
console.log("")
openticket.log("Please fix all plugin errors above & try again!","error")
process.exit(1)
}
}
for (const plugin of sortedPlugins){
if (plugin.enabled){
openticket.debug.debug("Plugin \""+plugin.id.value+"\" loaded",[
{key:"status",value:(plugin.crashed ? "crashed" : "success")},
{key:"crashReason",value:(plugin.crashed ? (plugin.crashReason ?? "/") : "/")},
{key:"author",value:plugin.details.author},
{key:"version",value:plugin.version.toString()},
{key:"priority",value:plugin.priority.toString()}
])
}else{
openticket.debug.debug("Plugin \""+plugin.id.value+"\" disabled",[
{key:"author",value:plugin.details.author},
{key:"version",value:plugin.version.toString()},
{key:"priority",value:plugin.priority.toString()}
])
}
}
}