Added new API comments (part 7)

This commit is contained in:
DJj123dj
2025-01-22 15:13:13 +01:00
parent 09d9b2d265
commit 40bd873a33
4 changed files with 329 additions and 14 deletions
+155 -8
View File
@@ -131,7 +131,7 @@ export class ODCommandResponderManager extends ODManager<ODCommandResponder<"sla
*/
export class ODCommandResponderInstanceOptions {
/**The interaction to get data from. */
#interaction:discord.ChatInputCommandInteraction|discord.Message
#interaction: discord.ChatInputCommandInteraction|discord.Message
/**The command which is related to the interaction. */
#cmd:ODSlashCommand|ODTextCommand
/**A list of options which have been parsed by the text command parser. */
@@ -333,11 +333,11 @@ export class ODCommandResponderInstanceOptions {
/**## ODCommandResponderInstance `class`
* This is an open ticket command responder instance.
*
* An instance is an interaction or used text command. You can reply to the command using `reply()` for both slash & text commands.
* An instance is an active slash interaction or used text command. You can reply to the command using `reply()` for both slash & text commands.
*/
export class ODCommandResponderInstance {
/**The interaction which is the source of this instance. */
interaction:discord.ChatInputCommandInteraction|discord.Message
interaction: discord.ChatInputCommandInteraction|discord.Message
/**The command wich is the source of this instance. */
cmd:ODSlashCommand|ODTextCommand
/**The type/source of instance. (from text or slash command) */
@@ -385,6 +385,7 @@ export class ODCommandResponderInstance {
},timeoutMs ?? 2500)
}
/**Reply to this command. */
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try {
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -407,6 +408,7 @@ export class ODCommandResponderInstance {
return {success:false,message:null}
}
}
/**Defer this command. */
async defer(ephemeral:boolean){
if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false
if (this.interaction.deferred) return false
@@ -415,6 +417,7 @@ export class ODCommandResponderInstance {
this.didReply = true
return true
}
/**Show a modal as reply to this command. */
async modal(modal:ODModalBuildResult){
if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false
this.interaction.showModal(modal.modal)
@@ -423,6 +426,11 @@ export class ODCommandResponderInstance {
}
}
/**## ODCommandResponder `class`
* This is an open ticket command responder.
*
* This class manages all workers which are executed when the related command is triggered.
*/
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
@@ -439,10 +447,27 @@ export class ODCommandResponder<Source extends "slash"|"text",Params> extends OD
}
}
/**## ODButtonResponderManager `class`
* This is an open ticket button responder manager.
*
* It contains all Open Ticket button responders. These can respond to button interactions.
*
* Using the Open Ticket responder system has a few advantages compared to vanilla discord.js:
* - plugins can extend/edit replies
* - automatically reply on error
* - independent workers (with priority)
* - fail-safe design using try-catch
* - know where the request came from!
* - And so much more!
*/
export class ODButtonResponderManager extends ODManager<ODButtonResponder<"button",any>> {
/**An alias to the Open Ticket client manager. */
#client: ODClientManager
/**The callback executed when the default workers take too much time to reply. */
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODButtonResponderInstance,"button">|null = null
/**The amount of milliseconds before the timeout error callback is executed. */
#timeoutMs: number|null = null
/**A list of listeners which will listen to the raw interactionCreate event from discord.js */
#listeners: ((interaction:discord.ButtonInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
@@ -474,13 +499,25 @@ export class ODButtonResponderManager extends ODManager<ODButtonResponder<"butto
}
}
/**## ODButtonResponderInstance `class`
* This is an open ticket button responder instance.
*
* An instance is an active button interaction. You can reply to the button using `reply()`.
*/
export class ODButtonResponderInstance {
interaction:discord.ButtonInteraction
/**The interaction which is the source of this instance. */
interaction: discord.ButtonInteraction
/**Did a worker already reply to this instance/interaction? */
didReply: boolean = false
/**The user who triggered this button. */
user: discord.User
/**The guild member who triggered this button. */
member: discord.GuildMember|null
/**The guild where this button was triggered. */
guild: discord.Guild|null
/**The channel where this button was triggered. */
channel: discord.TextBasedChannel
/**The message this button originates from. */
message: discord.Message
constructor(interaction:discord.ButtonInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODButtonResponderInstance,"button">|null, timeoutMs:number|null){
@@ -510,6 +547,7 @@ export class ODButtonResponderInstance {
},timeoutMs ?? 2500)
}
/**Reply to this button. */
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -526,6 +564,7 @@ export class ODButtonResponderInstance {
return {success:false,message:null}
}
}
/**Update the message of this button. */
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -542,6 +581,7 @@ export class ODButtonResponderInstance {
return {success:false,message:null}
}
}
/**Defer this button. */
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
@@ -553,12 +593,14 @@ export class ODButtonResponderInstance {
this.didReply = true
return true
}
/**Show a modal as reply to this button. */
async modal(modal:ODModalBuildResult){
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
/**Get a component from the original message of this button. */
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
@@ -582,11 +624,17 @@ export class ODButtonResponderInstance {
return result
}
/**Get the first embed of the original message if it exists. */
getMessageEmbed(): discord.Embed|null {
return this.message.embeds[0] ?? null
}
}
/**## ODButtonResponder `class`
* This is an open ticket button responder.
*
* This class manages all workers which are executed when the related button is triggered.
*/
export class ODButtonResponder<Source extends string,Params> extends ODResponderImplementation<ODButtonResponderInstance,Source,Params> {
/**Respond to this button */
async respond(instance:ODButtonResponderInstance, source:Source, params:Params){
@@ -595,10 +643,27 @@ export class ODButtonResponder<Source extends string,Params> extends ODResponder
}
}
/**## ODDropdownResponderManager `class`
* This is an open ticket dropdown responder manager.
*
* It contains all Open Ticket dropdown responders. These can respond to dropdown interactions.
*
* Using the Open Ticket responder system has a few advantages compared to vanilla discord.js:
* - plugins can extend/edit replies
* - automatically reply on error
* - independent workers (with priority)
* - fail-safe design using try-catch
* - know where the request came from!
* - And so much more!
*/
export class ODDropdownResponderManager extends ODManager<ODDropdownResponder<"dropdown",any>> {
/**An alias to the Open Ticket client manager. */
#client: ODClientManager
/**The callback executed when the default workers take too much time to reply. */
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODDropdownResponderInstance,"dropdown">|null = null
/**The amount of milliseconds before the timeout error callback is executed. */
#timeoutMs: number|null = null
/**A list of listeners which will listen to the raw interactionCreate event from discord.js */
#listeners: ((interaction:discord.AnySelectMenuInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
@@ -630,8 +695,15 @@ export class ODDropdownResponderManager extends ODManager<ODDropdownResponder<"d
}
}
/**## ODDropdownResponderInstanceValues `class`
* This is an open ticket dropdown responder instance values manager.
*
* This class will manage all values from the dropdowns & select menus.
*/
export class ODDropdownResponderInstanceValues {
#interaction:discord.AnySelectMenuInteraction
/**The interaction to get data from. */
#interaction: discord.AnySelectMenuInteraction
/**The type of this dropdown. */
#type: ODDropdownData["type"]
constructor(interaction:discord.AnySelectMenuInteraction, type:ODDropdownData["type"]){
@@ -642,6 +714,8 @@ export class ODDropdownResponderInstanceValues {
interaction.values
}
}
/**Get the selected values. */
getStringValues(): string[] {
try {
return this.#interaction.values
@@ -649,6 +723,7 @@ export class ODDropdownResponderInstanceValues {
throw new ODSystemError("ODDropdownResponderInstanceValues:getStringValues() invalid values!")
}
}
/**Get the selected roles. */
async getRoleValues(): Promise<discord.Role[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() dropdown type isn't role!")
try {
@@ -663,6 +738,7 @@ export class ODDropdownResponderInstanceValues {
throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() invalid values!")
}
}
/**Get the selected users. */
async getUserValues(): Promise<discord.User[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() dropdown type isn't user!")
try {
@@ -676,6 +752,7 @@ export class ODDropdownResponderInstanceValues {
throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() invalid values!")
}
}
/**Get the selected channels. */
async getChannelValues(): Promise<discord.GuildBasedChannel[]> {
if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() dropdown type isn't channel!")
try {
@@ -692,15 +769,29 @@ export class ODDropdownResponderInstanceValues {
}
}
/**## ODDropdownResponderInstance `class`
* This is an open ticket dropdown responder instance.
*
* An instance is an active dropdown interaction. You can reply to the dropdown using `reply()`.
*/
export class ODDropdownResponderInstance {
interaction:discord.AnySelectMenuInteraction
/**The interaction which is the source of this instance. */
interaction: discord.AnySelectMenuInteraction
/**Did a worker already reply to this instance/interaction? */
didReply: boolean = false
/**The dropdown type. */
type: ODDropdownData["type"]
/**The manager for all values of this dropdown. */
values: ODDropdownResponderInstanceValues
/**The user who triggered this dropdown. */
user: discord.User
/**The guild member who triggered this dropdown. */
member: discord.GuildMember|null
/**The guild where this dropdown was triggered. */
guild: discord.Guild|null
/**The channel where this dropdown was triggered. */
channel: discord.TextBasedChannel
/**The message this dropdown originates from. */
message: discord.Message
constructor(interaction:discord.AnySelectMenuInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODDropdownResponderInstance,"dropdown">|null, timeoutMs:number|null){
@@ -743,6 +834,7 @@ export class ODDropdownResponderInstance {
},timeoutMs ?? 2500)
}
/**Reply to this dropdown. */
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try {
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -759,6 +851,7 @@ export class ODDropdownResponderInstance {
return {success:false,message:null}
}
}
/**Update the message of this dropdown. */
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -775,6 +868,7 @@ export class ODDropdownResponderInstance {
return {success:false,message:null}
}
}
/**Defer this dropdown. */
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
@@ -786,12 +880,14 @@ export class ODDropdownResponderInstance {
this.didReply = true
return true
}
/**Show a modal as reply to this dropdown. */
async modal(modal:ODModalBuildResult){
this.interaction.showModal(modal.modal)
this.didReply = true
return true
}
/**Get a component from the original message of this dropdown. */
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
@@ -815,11 +911,17 @@ export class ODDropdownResponderInstance {
return result
}
/**Get the first embed of the original message if it exists. */
getMessageEmbed(): discord.Embed|null {
return this.message.embeds[0] ?? null
}
}
/**## ODDropdownResponder `class`
* This is an open ticket dropdown responder.
*
* This class manages all workers which are executed when the related dropdown is triggered.
*/
export class ODDropdownResponder<Source extends string,Params> extends ODResponderImplementation<ODDropdownResponderInstance,Source,Params> {
/**Respond to this dropdown */
async respond(instance:ODDropdownResponderInstance, source:Source, params:Params){
@@ -828,10 +930,27 @@ export class ODDropdownResponder<Source extends string,Params> extends ODRespond
}
}
/**## ODModalResponderManager `class`
* This is an open ticket modal responder manager.
*
* It contains all Open Ticket modal responders. These can respond to modal interactions.
*
* Using the Open Ticket responder system has a few advantages compared to vanilla discord.js:
* - plugins can extend/edit replies
* - automatically reply on error
* - independent workers (with priority)
* - fail-safe design using try-catch
* - know where the request came from!
* - And so much more!
*/
export class ODModalResponderManager extends ODManager<ODModalResponder<"modal",any>> {
/**An alias to the Open Ticket client manager. */
#client: ODClientManager
/**The callback executed when the default workers take too much time to reply. */
#timeoutErrorCallback: ODResponderTimeoutErrorCallback<ODModalResponderInstance,"modal">|null = null
/**The amount of milliseconds before the timeout error callback is executed. */
#timeoutMs: number|null = null
/**A list of listeners which will listen to the raw interactionCreate event from discord.js */
#listeners: ((interaction:discord.ModalSubmitInteraction) => void)[] = []
constructor(debug:ODDebugger, debugname:string, client:ODClientManager){
@@ -863,12 +982,20 @@ export class ODModalResponderManager extends ODManager<ODModalResponder<"modal",
}
}
/**## ODModalResponderInstanceValues `class`
* This is an open ticket modal responder instance values manager.
*
* This class will manage all fields from the modals.
*/
export class ODModalResponderInstanceValues {
#interaction:discord.ModalSubmitInteraction
/**The interaction to get data from. */
#interaction: discord.ModalSubmitInteraction
constructor(interaction:discord.ModalSubmitInteraction){
this.#interaction = interaction
}
/**Get the value of a text field. */
getTextField(name:string,required:true): string
getTextField(name:string,required:false): string|null
getTextField(name:string,required:boolean){
@@ -882,13 +1009,25 @@ export class ODModalResponderInstanceValues {
}
}
/**## ODModalResponderInstance `class`
* This is an open ticket modal responder instance.
*
* An instance is an active modal interaction. You can reply to the modal using `reply()`.
*/
export class ODModalResponderInstance {
interaction:discord.ModalSubmitInteraction
/**The interaction which is the source of this instance. */
interaction: discord.ModalSubmitInteraction
/**Did a worker already reply to this instance/interaction? */
didReply: boolean = false
/**The manager for all fields of this modal. */
values: ODModalResponderInstanceValues
/**The user who triggered this modal. */
user: discord.User
/**The guild member who triggered this modal. */
member: discord.GuildMember|null
/**The guild where this modal was triggered. */
guild: discord.Guild|null
/**The channel where this modal was triggered. */
channel: discord.TextBasedChannel|null
constructor(interaction:discord.ModalSubmitInteraction, errorCallback:ODResponderTimeoutErrorCallback<ODModalResponderInstance,"modal">|null, timeoutMs:number|null){
@@ -917,6 +1056,7 @@ export class ODModalResponderInstance {
},timeoutMs ?? 2500)
}
/**Reply to this modal. */
async reply(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -933,6 +1073,7 @@ export class ODModalResponderInstance {
return {success:false,message:null}
}
}
/**Update the message of this modal. */
async update(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<boolean>> {
try{
const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : []
@@ -945,6 +1086,7 @@ export class ODModalResponderInstance {
return {success:false,message:null}
}
}
/**Defer this modal. */
async defer(type:"reply"|"update", ephemeral:boolean){
if (this.interaction.deferred) return false
if (type == "reply"){
@@ -958,6 +1100,11 @@ export class ODModalResponderInstance {
}
}
/**## ODModalResponder `class`
* This is an open ticket modal responder.
*
* This class manages all workers which are executed when the related modal is triggered.
*/
export class ODModalResponder<Source extends string,Params> extends ODResponderImplementation<ODModalResponderInstance,Source,Params> {
/**Respond to this modal */
async respond(instance:ODModalResponderInstance, source:Source, params:Params){
+95
View File
@@ -7,8 +7,17 @@ import { ODFlag } from "./flag"
import { ODPlugin, ODUnknownCrashedPlugin } from "./plugin"
import ansis from "ansis"
/**## ODStartScreenComponentRenderCallback `type`
* This is the render function of a startscreen component. It also sends the location of where the component is rendered.
*/
export type ODStartScreenComponentRenderCallback = (location:number) => string|Promise<string>
/**## ODStartScreenManager `class`
* This is an open ticket startscreen manager.
*
* This class is responsible for managing & rendering the startscreen of the bot.
* The startscreen is the part you see when the bot has started up successfully. (e.g. the Open Ticket logo, logs, livestatus, flags, ...)
*/
export class ODStartScreenManager extends ODManager<ODStartScreenComponent> {
/**Alias to the Open Ticket debugger. */
#debug: ODDebugger
@@ -47,10 +56,22 @@ export class ODStartScreenManager extends ODManager<ODStartScreenComponent> {
}
}
/**## ODStartScreenComponent `class`
* This is an open ticket startscreen component.
*
* This component can be rendered to the start screen of the bot.
* An optional priority can be specified to choose the location of the component.
*
* It's recommended to use pre-built components except if you really need a custom one.
*/
export class ODStartScreenComponent extends ODManagerData {
/**The priority of this component. */
priority: number
/**An optional render function which will be inserted before the default renderer. */
renderBefore: ODStartScreenComponentRenderCallback|null = null
/**The render function which will render the contents of this component. */
render: ODStartScreenComponentRenderCallback
/**An optional render function which will be inserted behind the default renderer. */
renderAfter: ODStartScreenComponentRenderCallback|null = null
constructor(id:ODValidId, priority:number, render:ODStartScreenComponentRenderCallback){
@@ -59,6 +80,7 @@ export class ODStartScreenComponent extends ODManagerData {
this.render = render
}
/**Render this component and combine it with the `renderBefore` & `renderAfter` contents. */
async renderAll(location:number){
const textBefore = (this.renderBefore) ? await this.renderBefore(location) : ""
const text = await this.render(location)
@@ -67,15 +89,30 @@ export class ODStartScreenComponent extends ODManagerData {
}
}
/**## ODStartScreenProperty `type`
* This interface contains properties used in a few default templates of the startscreen component.
*/
export interface ODStartScreenProperty {
/**The key or name of this property. */
key:string,
/**The value or contents of this property. */
value:string
}
/**## ODStartScreenLogoComponent `class`
* This is an open ticket startscreen logo component.
*
* This component will render an ASCII art logo (from an array) to the startscreen. Every property in the array is another row.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenLogoComponent extends ODStartScreenComponent {
/**The ASCII logo contents. */
logo: string[]
/**When enabled, the component will add a new line above the logo. */
topPadding: boolean
/**When enabled, the component will add a new line below the logo. */
bottomPadding: boolean
/**The color of the logo in hex format. */
logoHexColor: string
constructor(id:ODValidId, priority:number, logo:string[], topPadding?:boolean, bottomPadding?:boolean, logoHexColor?:string){
@@ -92,14 +129,28 @@ export class ODStartScreenLogoComponent extends ODStartScreenComponent {
}
}
/**## ODStartScreenHeaderAlignmentSettings `type`
* This interface contains all settings used in the startscreen header component.
*/
export interface ODStartScreenHeaderAlignmentSettings {
/**The alignment settings for this header. */
align:"center"|"left"|"right",
/**The width or component to use when calculating center & right alignment. */
width:number|ODStartScreenComponent
}
/**## ODStartScreenHeaderComponent `class`
* This is an open ticket startscreen header component.
*
* This component will render a header to the startscreen. Properties can be aligned left, right or centered.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenHeaderComponent extends ODStartScreenComponent {
/**All properties of this header component. */
properties: ODStartScreenProperty[]
/**The spacer used between properties. */
spacer: string
/**The alignment settings of this header component. */
align: ODStartScreenHeaderAlignmentSettings|null
constructor(id:ODValidId, priority:number, properties:ODStartScreenProperty[], spacer?:string, align?:ODStartScreenHeaderAlignmentSettings){
@@ -140,8 +191,16 @@ export class ODStartScreenHeaderComponent extends ODStartScreenComponent {
}
}
/**## ODStartScreenCategoryComponent `class`
* This is an open ticket startscreen category component.
*
* This component will render a category to the startscreen. This will only render the category name. You'll need to provide your own renderer for the contents.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenCategoryComponent extends ODStartScreenComponent {
/**The name of this category. */
name: string
/**When enabled, this category will still be rendered when the contents are empty. (enabled by default) */
renderIfEmpty: boolean
constructor(id:ODValidId, priority:number, name:string, render:ODStartScreenComponentRenderCallback, renderIfEmpty?:boolean){
@@ -156,8 +215,16 @@ export class ODStartScreenCategoryComponent extends ODStartScreenComponent {
}
}
/**## ODStartScreenPropertiesCategoryComponent `class`
* This is an open ticket startscreen properties category component.
*
* This component will render a properties category to the startscreen. This will list the properties in the category.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCategoryComponent {
/**The properties of this category component. */
properties: ODStartScreenProperty[]
/**The hex color for the key/name of all the properties. */
propertyHexColor: string
constructor(id:ODValidId, priority:number, name:string, properties:ODStartScreenProperty[], propertyHexColor?:string, renderIfEmpty?:boolean){
@@ -170,7 +237,14 @@ export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCateg
}
}
/**## ODStartScreenFlagsCategoryComponent `class`
* This is an open ticket startscreen flags category component.
*
* This component will render a flags category to the startscreen. This will list the enabled flags in the category.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryComponent {
/**A list of all flags to render. */
flags: ODFlag[]
constructor(id:ODValidId, priority:number, flags:ODFlag[]){
@@ -181,8 +255,16 @@ export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryCo
}
}
/**## ODStartScreenPluginsCategoryComponent `class`
* This is an open ticket startscreen plugins category component.
*
* This component will render a plugins category to the startscreen. This will list the enabled, disabled & crashed plugins in the category.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategoryComponent {
/**A list of all plugins to render. */
plugins: ODPlugin[]
/**A list of all crashed plugins to render. */
unknownCrashedPlugins: ODUnknownCrashedPlugin[]
constructor(id:ODValidId, priority:number, plugins:ODPlugin[], unknownCrashedPlugins:ODUnknownCrashedPlugin[]){
@@ -200,7 +282,14 @@ export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategory
}
}
/**## ODStartScreenLiveStatusCategoryComponent `class`
* This is an open ticket startscreen livestatus category component.
*
* This component will render a livestatus category to the startscreen. This will list the livestatus messages in the category.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCategoryComponent {
/**A reference to the Open Ticket livestatus manager. */
livestatus: ODLiveStatusManager
constructor(id:ODValidId, priority:number, livestatus:ODLiveStatusManager){
@@ -212,6 +301,12 @@ export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCateg
}
}
/**## ODStartScreenLogsCategoryComponent `class`
* This is an open ticket startscreen logs category component.
*
* This component will render a logs category to the startscreen. This will only render the logs category name.
* An optional priority can be specified to choose the location of the component.
*/
export class ODStartScreenLogCategoryComponent extends ODStartScreenCategoryComponent {
constructor(id:ODValidId, priority:number){
super(id,priority,"logs",() => "",true)
+79
View File
@@ -6,10 +6,31 @@ import { ODDebugger } from "./console"
import { ODDatabase, ODJsonDatabaseStructure } from "./database"
import * as discord from "discord.js"
/**## ODValidStatValue `type`
* These are the only allowed types for a stat value to improve compatibility with different database systems.
*/
export type ODValidStatValue = string|number|boolean
/**## ODStatsManagerInitCallback `type`
* This callback can be used to execute something when the stats have been initiated.
*
* By default this is used to clear stats from users that left the server or tickets which don't exist anymore.
*/
export type ODStatsManagerInitCallback = (database:ODJsonDatabaseStructure, deletables:ODJsonDatabaseStructure) => void|Promise<void>
/**## ODStatScopeSetMode `type`
* This type contains all valid methods for changing the value of a stat.
*/
export type ODStatScopeSetMode = "set"|"increase"|"decrease"
/**## ODStatsManager `class`
* This is an open ticket stats manager.
*
* This class is responsible for managing all stats of the bot.
* Stats are categorized in "scopes" which can be accessed in this manager.
*
* Stats can be accessed in the individual scopes.
*/
export class ODStatsManager extends ODManager<ODStatScope> {
/**Alias to open ticket debugger. */
#debug: ODDebugger
@@ -23,6 +44,7 @@ export class ODStatsManager extends ODManager<ODStatScope> {
this.#debug = debug
}
/**Select the database to use to read/write all stats from/to. */
useDatabase(database:ODDatabase){
this.database = database
}
@@ -31,6 +53,7 @@ export class ODStatsManager extends ODManager<ODStatScope> {
if (this.database) data.useDatabase(this.database)
return super.add(data,overwrite)
}
/**Init all stats and run `onInit()` listeners. */
async init(){
if (!this.database) throw new ODSystemError("Unable to initialize stats scopes due to missing database!")
@@ -58,6 +81,7 @@ export class ODStatsManager extends ODManager<ODStatScope> {
await this.database.delete(data.category,data.key)
}
}
/**Reset all stats. (clears the entire database) */
async reset(){
if (!this.database) return
const data = await this.database.getAll()
@@ -66,11 +90,20 @@ export class ODStatsManager extends ODManager<ODStatScope> {
await this.database.delete(d.category,d.key)
}
}
/**Run a function when the stats are initialized. This can be used to clear stats from users that left the server or tickets which don't exist anymore. */
onInit(callback:ODStatsManagerInitCallback){
this.#initListeners.push(callback)
}
}
/**## ODStatScope `class`
* This is an open ticket stat scope.
*
* A scope can contain multiple stats. Every scope is seperated from other scopes.
* Here, you can read & write the values of all stats.
*
* The built-in Open Ticket scopes are: `global`, `user`, `ticket`
*/
export class ODStatScope extends ODManager<ODStat> {
/**The id of this statistics scope. */
id: ODId
@@ -87,9 +120,11 @@ export class ODStatScope extends ODManager<ODStat> {
this.name = name
}
/**Select the database to use to read/write all stats from/to. (Automatically assigned when used in `ODStatsManager`) */
useDatabase(database:ODDatabase){
this.database = database
}
/**Get the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */
async getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
if (!this.database) return null
const newId = new ODId(id)
@@ -105,6 +140,7 @@ export class ODStatScope extends ODManager<ODStat> {
//return null on error
return null
}
/**Set, increase or decrease the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */
async setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
if (!this.database) return false
const stat = this.get(id)
@@ -122,6 +158,7 @@ export class ODStatScope extends ODManager<ODStat> {
}
return true
}
/**Reset the value of a statistic to the initial value. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */
async resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
if (!this.database) return null
const stat = this.get(id)
@@ -129,11 +166,13 @@ export class ODStatScope extends ODManager<ODStat> {
if (stat.value != null) await this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value)
return stat.value
}
/**Initialize this stat scope & return a list of all statistic ids in the following format: `<scopeid>_<statid>` */
init(): string[] {
//get all valid stats categories
this.ready = true
return this.getAll().map((stat) => this.id.value+"_"+stat.id.value)
}
/**Render all stats in this scope for usage in a discord message/embed. */
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()]
@@ -162,6 +201,14 @@ export class ODStatScope extends ODManager<ODStat> {
}
}
/**## ODStatGlobalScope `class`
* This is an open ticket stat global scope.
*
* A scope can contain multiple stats. Every scope is seperated from other scopes.
* Here, you can read & write the values of all stats.
*
* This scope is made specifically for the global stats of Open Ticket.
*/
export class ODStatGlobalScope extends ODStatScope {
getStat(id:ODValidId): Promise<ODValidStatValue|null> {
return super.getStat(id,"GLOBAL")
@@ -177,11 +224,25 @@ export class ODStatGlobalScope extends ODStatScope {
}
}
/**## ODStatRenderer `type`
* This callback will render a single statistic for a discord embed/message.
*/
export type ODStatRenderer = (value:ODValidStatValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
/**## ODStat `class`
* This is an open ticket statistic.
*
* This single statistic doesn't do anything except defining the rules of this statistic.
* Use it in a stats scope to register a new statistic. A statistic can also include a priority to choose the render priority.
*
* It's recommended to use the `ODBasicStat` & `ODDynamicStat` classes instead of this one!
*/
export class ODStat extends ODManagerData {
/**The priority of this statistic. */
priority: number
/**The render function of this statistic. */
render: ODStatRenderer
/**The value of this statistic. */
value: ODValidStatValue|null
constructor(id:ODValidId, priority:number, render:ODStatRenderer, value?:ODValidStatValue){
@@ -192,7 +253,14 @@ export class ODStat extends ODManagerData {
}
}
/**## ODBasicStat `class`
* This is an open ticket basic statistic.
*
* This single statistic will store a number, boolean or string in the database.
* Use it to create a simple statistic for any stats scope.
*/
export class ODBasicStat extends ODStat {
/**The name of this stat. Rendered in discord embeds/messages. */
name: string
constructor(id:ODValidId, priority:number, name:string, value:ODValidStatValue){
@@ -203,8 +271,19 @@ export class ODBasicStat extends ODStat {
}
}
/**## ODDynamicStatRenderer `type`
* This callback will render a single dynamic statistic for a discord embed/message.
*/
export type ODDynamicStatRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise<string>
/**## ODDynamicStat `class`
* This is an open ticket dynamic statistic.
*
* A dynamic statistic does not store anything in the database! Instead, it will execute a function to return a custom result.
* This can be used to show statistics which are not stored in the database.
*
* This is used in Open Ticket for the live ticket status, participants & system status.
*/
export class ODDynamicStat extends ODStat {
constructor(id:ODValidId, priority:number, render:ODDynamicStatRenderer){
super(id,priority,(value,scopeId,guild,channel,user) => {