diff --git a/src/WOK.ts b/src/WOK.ts index de5550d..2ca0dd5 100644 --- a/src/WOK.ts +++ b/src/WOK.ts @@ -19,6 +19,7 @@ class WOKCommands { private _eventHandler!: EventHandler private _isConnectedToDB = false private _defaultPrefix = '!' + private _autoDeleteCommand = false constructor(options: Options) { this.init(options) @@ -37,6 +38,7 @@ class WOKCommands { events = {}, validations = {}, defaultPrefix, + autoDeleteCommand } = options if (!client) { @@ -73,11 +75,16 @@ class WOKCommands { this._defaultPrefix = defaultPrefix } + if (autoDeleteCommand) { + this._autoDeleteCommand = autoDeleteCommand + } + if (commandsDir) { this._commandHandler = new CommandHandler( this as unknown as WOK, commandsDir, - client + client, + this._autoDeleteCommand ) } @@ -132,6 +139,10 @@ class WOKCommands { return this._defaultPrefix } + public get autoDeleteCommand(): boolean { + return this._autoDeleteCommand + } + private async connectToMongo(mongoUri: string) { await mongoose.connect(mongoUri, { keepAlive: true, diff --git a/src/command-handler/CommandHandler.ts b/src/command-handler/CommandHandler.ts index 2a2f8f8..cc60c7c 100644 --- a/src/command-handler/CommandHandler.ts +++ b/src/command-handler/CommandHandler.ts @@ -36,8 +36,9 @@ class CommandHandler { private _customCommands: CustomCommands private _disabledCommands: DisabledCommands private _prefixes: PrefixHandler + private _autoDeleteCommand: boolean - constructor(instance: WOK, commandsDir: string, client: Client) { + constructor(instance: WOK, commandsDir: string, client: Client, autoDeleteCommand: boolean) { this._instance = instance this._commandsDir = commandsDir this._slashCommands = new SlashCommands(client) @@ -46,13 +47,14 @@ class CommandHandler { this._customCommands = new CustomCommands(instance, this) this._disabledCommands = new DisabledCommands(instance) this._prefixes = new PrefixHandler(instance) + this._autoDeleteCommand = autoDeleteCommand this._validations = [ ...this._validations, ...this.getValidations(instance.validations?.runtime), ] - this.readFiles() + this.readFiles(this._autoDeleteCommand) } public get commands() { @@ -79,9 +81,61 @@ class CommandHandler { return this._prefixes } - private async readFiles() { + private async readFiles(autoDelete: boolean) { const defaultCommands = getAllFiles(path.join(__dirname, './commands')) const files = getAllFiles(this._commandsDir) + + const client = this._client + + const existingCommands = client.application?.commands; + // @ts-ignore + await existingCommands?.fetch() + + const existingCommandsLength = (await existingCommands?.fetch())?.size + + if ( + existingCommands && + existingCommandsLength && + files.length < existingCommandsLength + ) { + let a = 0 + let i = 0 + function findEscape() { + if (!existingCommandsLength) return false; + if (a < existingCommandsLength) { + const slashCommands = new SlashCommands(client) + const existingCommand = existingCommands?.cache.at(a) + const command = files.at(i) + if (!command) { + if (autoDelete === true) { + console.log(`Deleting "${existingCommand?.name}" command.`) + slashCommands.delete(existingCommand?.name!) + } + i = 0; + a++; + findEscape() + return + } + const { filePath: commandPath } = command + const split = commandPath.split(/[\/\\]/) + let commandName = split.pop()! + commandName = commandName.split(".")[0] + + if ( + existingCommand?.name !== commandName + ) { + i++ + findEscape(); + } else { + a++; + i = 0; + findEscape(); + } + } + } + findEscape() + } + const validations = [ ...this.getValidations(path.join(__dirname, 'validations', 'syntax')), ...this.getValidations(this._instance.validations?.syntax), diff --git a/src/command-handler/SlashCommands.ts b/src/command-handler/SlashCommands.ts index 739ae98..c344787 100644 --- a/src/command-handler/SlashCommands.ts +++ b/src/command-handler/SlashCommands.ts @@ -48,11 +48,17 @@ class SlashCommands { for (let i = 0; i < existing.options.length; ++i) { const existingOption = existing.options[i]; const addOption = option.options[i]; - if ( - JSON.stringify(existingOption) === JSON.stringify(addOption) - ) { + + Object.entries(existingOption).forEach(([optionKey, optionValue]) => { + const existingAddOption = existingOption[optionKey] ? existingOption[optionKey] : false; + const optionAddOption = addOption[optionKey] ? addOption[optionKey] : false; + + if ( + String(existingAddOption) !== String(optionAddOption) + ) { different = true; - } + } + }); } } else if ( String(existingElement) !== String(optionElement) diff --git a/typings.d.ts b/typings.d.ts index 206b22b..1ec294d 100644 --- a/typings.d.ts +++ b/typings.d.ts @@ -25,6 +25,7 @@ export default class WOK { private _eventHandler!: EventHandler private _isConnectedToDB = false private _defaultPrefix = '!' + private _autoDeleteCommand = false constructor(options: Options) @@ -38,6 +39,7 @@ export default class WOK { public get eventHandler(): EventHandler public get isConnectedToDB(): boolean public get defaultPrefix(): string + public get autoDeleteCommand(): boolean } export interface Options { @@ -52,6 +54,7 @@ export interface Options { events?: Events validations?: Validations defaultPrefix?: string + autoDeleteCommand?: boolean } export interface CooldownConfig { @@ -105,7 +108,7 @@ export interface CommandUsage { } export interface CommandObject { - callback: (commandUsage: CommandUsage) => unknown + callback: (commandUsage: CommandUsage) => { content?: string, ephemeral?: boolean } | undefined type: CommandType init?: function description?: string