From 3e928ed06ed80b244eafd86a982bf9b95459c874 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:24:48 +0100 Subject: [PATCH] Bug fixes for new database system --- src/commands/panel.ts | 2 +- src/core/api/defaults/event.ts | 4 + src/core/api/modules/config.ts | 71 ++++++---------- src/core/api/modules/database.ts | 121 +++++++++------------------- src/core/api/modules/defaults.ts | 6 ++ src/core/api/openticket/option.ts | 23 ++++-- src/core/startup/manageMigration.ts | 4 +- src/data/framework/codeLoader.ts | 78 +++++++++--------- src/data/framework/eventLoader.ts | 4 + src/data/openticket/ticketLoader.ts | 14 ++-- src/index.ts | 14 ++++ 11 files changed, 161 insertions(+), 180 deletions(-) diff --git a/src/commands/panel.ts b/src/commands/panel.ts index 0a7a184..0eb103e 100644 --- a/src/commands/panel.ts +++ b/src/commands/panel.ts @@ -67,7 +67,7 @@ export const registerCommandResponders = async () => { //add panel to database on auto-update if (instance.options.getBoolean("auto-update",false)){ const globalDatabase = openticket.databases.get("openticket:global") - globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) + await globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index 200af2d..7c6ec37 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -64,10 +64,14 @@ export interface ODEventIds_Default { //configs "onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> "afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + "onConfigInit": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + "afterConfigsInitiated": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> //databases "onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> "afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + "onDatabaseInit": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + "afterDatabasesInitiated": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> //languages "onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index acc2f2a..8e635ed 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //CONFIG MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId } from "./base" import nodepath from "path" import { ODDebugger } from "./console" import fs from "fs" @@ -12,51 +12,20 @@ import fs from "fs" * 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 { 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) + /**Init all config files. */ + async init(){ + for (const config of this.getAll()){ + try{ + await config.init() + }catch(err){ + process.emit("uncaughtException",new ODSystemError(err)) + } + } } } @@ -72,7 +41,17 @@ export class ODConfig extends ODManagerData { /**The path to the file relative to the main directory. */ path: string = "" /**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */ - data: any = undefined + data: any + + constructor(id:ODValidId, data:any){ + super(id) + this.data = data + } + + /**Init the config. */ + init(): ODPromiseVoid { + //nothing + } } /**## ODJsonConfig `class` @@ -90,10 +69,13 @@ export class ODJsonConfig extends ODConfig { #reloadListeners: Function[] = [] constructor(id:ODValidId, file:string, customPath?:string){ - super(id) + super(id,{}) this.file = (file.endsWith(".json")) ? file : file+".json" this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file) - + } + + /**Init the config. */ + init(): ODPromiseVoid { if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") try{ this.data = JSON.parse(fs.readFileSync(this.path).toString()) @@ -102,7 +84,6 @@ export class ODJsonConfig extends ODConfig { throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!") } } - /**Reload the JSON file. Be aware that this doesn't update classes that used individual parts of the config data! */ reload(){ if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index 9bb9966..24d4ab9 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //DATABASE MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODSystemError, ODValidId, ODValidJsonType } from "./base" +import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODPromiseVoid, ODSystemError, ODValidId, ODValidJsonType } from "./base" import fs from "fs" import nodepath from "path" import { ODDebugger } from "./console" @@ -13,51 +13,21 @@ import * as fjs from "formatted-json-stringify" * 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 { 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) + /**Init all database files. */ + async init(){ + for (const database of this.getAll()){ + try{ + await database.init() + }catch(err){ + process.emit("uncaughtException",new ODSystemError(err)) + } + } } } @@ -66,26 +36,17 @@ export class ODDatabaseManager extends ODManager { * 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 */ + /**The name of the file with extension. */ file: string = "" + /**The path to the file relative to the main directory. */ + path: string = "" + /**Init the database. */ + init(): ODPromiseVoid { + //nothing + } /**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */ set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return false @@ -122,24 +83,19 @@ export type ODJsonDatabaseStructure = {category:string, key:string, value:ODVali * 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! + * You will use this class if you want to create your own database or use an existing one! */ 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() + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file) } + /**Init the database. */ + init(): ODPromiseVoid { + 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 @@ -202,21 +158,21 @@ export class ODJsonDatabase extends ODDatabase { #system = { /**Read parsed data from the json file */ getData: (): ODJsonDatabaseStructure => { - if (fs.existsSync(this.file)){ + if (fs.existsSync(this.path)){ try{ - return JSON.parse(fs.readFileSync(this.file).toString()) + return JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) - throw new ODSystemError("Unable to read database "+this.file+"! getData() read error. (see error above)") + throw new ODSystemError("Unable to read database "+this.path+"! getData() read error. (see error above)") } }else{ - fs.writeFileSync(this.file,"[]") + fs.writeFileSync(this.path,"[]") return [] } }, /**Write parsed data to the json file */ setData: (data:ODJsonDatabaseStructure) => { - fs.writeFileSync(this.file,JSON.stringify(data,null,"\t")) + fs.writeFileSync(this.path,JSON.stringify(data,null,"\t")) } } } @@ -236,14 +192,15 @@ export class ODFormattedJsonDatabase extends ODDatabase { 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.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file) this.formatter = formatter - - //init file if it doesn't exist yet - this.#system.getData() } + /**Init the database. */ + init(): ODPromiseVoid { + 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 @@ -306,16 +263,16 @@ export class ODFormattedJsonDatabase extends ODDatabase { #system = { /**Read parsed data from the json file */ getData: (): ODJsonDatabaseStructure => { - if (fs.existsSync(this.file)){ - return JSON.parse(fs.readFileSync(this.file).toString()) + if (fs.existsSync(this.path)){ + return JSON.parse(fs.readFileSync(this.path).toString()) }else{ - fs.writeFileSync(this.file,"[]") + fs.writeFileSync(this.path,"[]") return [] } }, /**Write parsed data to the json file */ setData: (data:ODJsonDatabaseStructure) => { - fs.writeFileSync(this.file,this.formatter.stringify(data)) + fs.writeFileSync(this.path,this.formatter.stringify(data)) } } } \ No newline at end of file diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index d67625e..df9ecdf 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -29,8 +29,12 @@ export interface ODDefaults { flagInitiating:boolean, /**Load the default open ticket configs. */ configLoading:boolean, + /**Enable the default initializer for open ticket config. */ + configInitiating:boolean, /**Load the default open ticket databases. */ databaseLoading:boolean, + /**Enable the default initializer for open ticket database. */ + databaseInitiating:boolean, /**Load the default open ticket sessions. */ sessionLoading:boolean, @@ -230,7 +234,9 @@ export class ODDefaultsManager { flagLoading:true, flagInitiating:true, configLoading:true, + configInitiating:true, databaseLoading:true, + databaseInitiating:true, sessionLoading:true, languageLoading:true, diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index ffc967d..3aeff49 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -328,9 +328,12 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { 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) + this.#init() + } + + async #init(){ + if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await 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 @@ -347,9 +350,12 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { 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) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await 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 @@ -370,9 +376,12 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { 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,[]) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await 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 @@ -401,9 +410,13 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix { 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,[]) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await 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) diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 1b5bc7a..9aa5def 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -78,7 +78,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { const saveAllVersionsToDatabase = async () => { const globalDatabase = openticket.databases.get("openticket:global") - await openticket.versions.loopAll((version,id) => { - globalDatabase.set("openticket:last-version",id.value,version.toString()) + await openticket.versions.loopAll(async (version,id) => { + await globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index ab358b2..aee5ce3 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -86,14 +86,14 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused panels for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ - globalDatabase.delete("openticket:panel-update",panel.key) + await globalDatabase.delete("openticket:panel-update",panel.key) } } //delete panel from database on delete - openticket.client.client.on("messageDelete",(msg) => { - if (globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ - globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) + openticket.client.client.on("messageDelete",async (msg) => { + if (await globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ + await globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) } }) })) @@ -120,24 +120,24 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused suffix counters for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ - globalDatabase.delete("openticket:option-suffix-counter",counter.key) + await globalDatabase.delete("openticket:option-suffix-counter",counter.key) } } //remove all unused suffix histories for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ - globalDatabase.delete("openticket:option-suffix-history",history.key) + await globalDatabase.delete("openticket:option-suffix-history",history.key) } } })) //OPTION DATABASE CLEANER openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { - //delete all unused options - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + //delete all unused options (async) + openticket.options.getAll().forEach(async (option) => { + if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + await optionDatabase.delete("openticket:used-option",option.id.value) } }) })) @@ -172,7 +172,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused users for (const user of (await userDatabase.getAll())){ if (!validUsers.includes(user.key)){ - userDatabase.delete(user.category,user.key) + await userDatabase.delete(user.category,user.key) } } @@ -180,7 +180,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (!validUsers.includes(stat.key)){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -193,7 +193,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused user for (const user of (await userDatabase.getAll())){ if (user.key == member.id){ - userDatabase.delete(user.category,user.key) + await userDatabase.delete(user.category,user.key) } } @@ -201,7 +201,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (stat.key == member.id){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -237,7 +237,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused tickets for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ - ticketDatabase.delete(ticket.category,ticket.key) + await ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) } } @@ -246,7 +246,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (!validTickets.includes(stat.key)){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -258,7 +258,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused ticket for (const ticket of (await ticketDatabase.getAll())){ if (ticket.key == channel.id){ - ticketDatabase.delete(ticket.category,ticket.key) + await ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) } } @@ -267,7 +267,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (stat.key == channel.id){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -314,49 +314,49 @@ export const loadDatabaseSaversCode = async () => { openticket.code.add(new api.ODCode("openticket:ticket-saver",6,() => { const mainVersion = openticket.versions.get("openticket:version") - openticket.tickets.onAdd((ticket) => { - ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + openticket.tickets.onAdd(async (ticket) => { + await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ - optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ + await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } }) - openticket.tickets.onChange((ticket) => { - ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + openticket.tickets.onChange(async (ticket) => { + await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ - optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ + await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } //delete all unused options on ticket move - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + for (const option of openticket.options.getAll()){ + if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + await optionDatabase.delete("openticket:used-option",option.id.value) } - }) + } }) - openticket.tickets.onRemove((ticket) => { - ticketDatabase.delete("openticket:ticket",ticket.id.value) + openticket.tickets.onRemove(async (ticket) => { + await ticketDatabase.delete("openticket:ticket",ticket.id.value) //remove option from database if unused if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ - optionDatabase.delete("openticket:used-option",ticket.option.id.value) + await optionDatabase.delete("openticket:used-option",ticket.option.id.value) } }) })) //BLACKLIST SAVER openticket.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { - openticket.blacklist.onAdd((blacklist) => { - userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + openticket.blacklist.onAdd(async (blacklist) => { + await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onChange((blacklist) => { - userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + openticket.blacklist.onChange(async (blacklist) => { + await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onRemove((blacklist) => { - userDatabase.delete("openticket:blacklist",blacklist.id.value) + openticket.blacklist.onRemove(async (blacklist) => { + await userDatabase.delete("openticket:blacklist",blacklist.id.value) }) })) diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index 0371e4a..b9713ef 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -20,10 +20,14 @@ export const loadAllEvents = () => { //configs "onConfigLoad", "afterConfigsLoaded", + "onConfigInit", + "afterConfigsInitiated", //databases "onDatabaseLoad", "afterDatabasesLoaded", + "onDatabaseInit", + "afterDatabasesInitiated", //languages "onLanguageLoad", diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index 93d7811..8147738 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -8,24 +8,26 @@ export const loadAllTickets = async () => { const tickets = await ticketDatabase.getCategory("openticket:ticket") if (!tickets) return - tickets.forEach((ticket) => { + for (const ticket of tickets){ + console.log(ticket.value) try { - openticket.tickets.add(loadTicket(ticket.value)) + openticket.tickets.add(await loadTicket(ticket.value)) }catch (err){ + process.emit("uncaughtException",err) process.emit("uncaughtException",new api.ODSystemError("Failed to load ticket from database! => id: "+ticket.key+"\n ===> "+err)) } - }) + } } -export const loadTicket = (ticket:api.ODTicketJson) => { - const backupOption = optionDatabase.exists("openticket:used-option",ticket.option) ? api.ODTicketOption.fromJson(optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null +export const loadTicket = async (ticket:api.ODTicketJson) => { + const backupOption = (await optionDatabase.exists("openticket:used-option",ticket.option)) ? api.ODTicketOption.fromJson(await optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null const configOption = openticket.options.get(ticket.option) //check if option is of type "ticket" if (configOption && !(configOption instanceof api.ODTicketOption)) throw new api.ODSystemError("Unable to load ticket because option is not of 'ticket' type!") //manage backup option - if (configOption) optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) + if (configOption) await optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) else if (backupOption) openticket.options.add(backupOption) else throw new api.ODSystemError("Unable to use backup option! Normal option not found in config!") diff --git a/src/index.ts b/src/index.ts index 209f7e3..4e9b3af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -122,6 +122,13 @@ const main = async () => { await openticket.events.get("onConfigLoad").emit([openticket.configs]) await openticket.events.get("afterConfigsLoaded").emit([openticket.configs]) + //initiate config + await openticket.events.get("onConfigInit").emit([openticket.configs]) + if (openticket.defaults.getDefault("configInitiating")){ + await openticket.configs.init() + await openticket.events.get("afterConfigsInitiated").emit([openticket.configs]) + } + //UTILITY CONFIG const generalConfig = openticket.configs.get("openticket:general") @@ -138,6 +145,13 @@ const main = async () => { await openticket.events.get("onDatabaseLoad").emit([openticket.databases]) await openticket.events.get("afterDatabasesLoaded").emit([openticket.databases]) + //initiate database + await openticket.events.get("onDatabaseInit").emit([openticket.databases]) + if (openticket.defaults.getDefault("databaseInitiating")){ + await openticket.databases.init() + await openticket.events.get("afterDatabasesInitiated").emit([openticket.databases]) + } + //load sessions openticket.log("Loading sessions...","system") if (openticket.defaults.getDefault("sessionLoading")){