# v2 to v3 Migration Guide

## Migration from v2 to v3

The v3 of the CommandHandler introduced a lot of new features I wanted to add for a long time, it is a complete rewrite from scratch for the commands & events part and the v2 code is completely incompatible, so this is the guide to migrate your code.

## How to install it

Library now requires at least `Node.js` v16, which will become LTS in october. Just select the beta version from npm.

```
npm i -s advanced-command-handler@beta
```

## Breaking changes

### AdvancedClient

**AdvancedClient#hasPermission**

This method has been removed because of the method being not coherent with the class itself.

```diff
- client.hasPermission(message, 'SEND_MESSAGES');

+ message.guild?.me?.hasPermission('SEND_MESSAGES, {checkOwner: false, checkAdmin: false})
```

### BetterEmbed

**BetterEmbed#checkSize**

```diff
- embed.checkSize(field?);

+ embed.throwIfTooLong(field?);
```

> Note : `checkSize` method still exists, but now just returns an object containing the fields too long.

### CommandHandler

**Methods**

Defaults functions have new names that are more coherent :

```diff
- setDefaultCommands()
- setDefaultEvents()

+ useDefaultEvents()
+ useDefaultCommands()
```

**Events**

Launch event emits now the `LaunchCommandHandlerOptions`.

```diff
- CommandHandler.on('launch', () => { //code });

+ CommandHandler.on('launch', (options /*: LaunchCommandHandlerOptions*/) => { //code });
```

### Command

Commands are created in a very different way, using now a subclass, methods for defining SubCommands, a `CommandContext` argument instead of a custom one depending on your `message` event etc.

Example :

```javascript
// before
module.exports = new Command(
    {
        name: 'ping',
        tags: ['guildOnly'],
        description = 'Get the ping of the bot.';
        userPermissions: ['MANAGE_MESSAGES'],
        category: 'utils',
    }, async (handler, message, args) => {
        const msg = await message.channel.send('Ping ?');
        const botPing = handler.client?.ws.ping;
        const apiPing = msg.createdTimestamp - message.createdTimestamp;
        await msg.edit(`Bot Latency: **${botPing}**ms\nAPI Latency: **${apiPing}**ms`);
    }
);

// now
module.exports = class PingCommand extends Command {
    name = 'ping';
    category = 'utils';
    description = 'Get the ping of the bot.';
    tags = ['guildOnly'];
    userPermissions = ['MANAGE_MESSAGES'];

    async run(ctx) {
        const msg = await ctx.reply('Ping ?');
        const botPing = ctx.client.ping; // using client.ping getter, see further down
        const apiPing = msg.createdTimestamp - ctx.message.createdTimestamp;
        await msg.edit(`WS Ping: **${botPing}**ms\nAPI Latency: **${apiPing}**ms`);
    }
}
```

So you will have to change all of your commands. This choice was taken by me, so you can define methods in your classes that will do special things, see on the [Added](broken://pages/-MfJYElZG0M1eUvbCX84#Added) section.

### DeleteMessageOptions

`DeleteMessageOptions#options` has been removed, as a message cannot be deleted with a reason in the new Discord API.

```diff
- command.deleteMessage({message, {timeout: 1000}});

+ command.deleteMessage({message, timeout: 1000});
```

> Note\
> &#x20;You can also do this to delete the message of the command :
>
> ```javascript
> ctx.deleteMessage(1000);
> ```

### Event

It's the same thing as commands, now using classes to have improved behaviors.

Example :

```javascript
// before 
module.exports = new Event(
    {
        name: 'ready'
    },
    async (handler) => {
        console.log(`Bot is ready, username : '${handler.client?.user?.username}'`);
    }
);

// now
module.exports = class ReadyEvent extends Event {
    name = 'ready';

    async run(ctx) {
        console.log(`Bot is ready, username : '${ctx.client?.username}'`); // using client.username getter, see further down
    }
}
```

> Note: Notice that in both case, syntax is shorter and more readable.

### Functions

`argError`, `codeError` and `permissionsError` now only accept a `CommandContext` argument instead of `message` and `command`.

`saveJSON` only accept a JSON instead of `any` for the value type.

### Logger

**Logger#test**

```diff
- Logger.test(`debug ${setColor(LogType.test, 'message')}`);

+ Logger.debug(`debug ${setColor(LogType.debug, 'message')}`);
```

`test` has been renamed to `debug` because it's a more logic feature & name, and it was more used for debugging than testing

`LogType` is now a TS enum rather than an object, it's for having better type checking and better code.

## Added

### AdvancedClient

**Getters**

```diff
+ client.id
+ client.mention
+ client.ping
+ client.tag
+ client.username
```

These are just shortcuts of the normal code to get them.

### BetterEmbed

**BetterEmbed#setImageFromFile**

`setImageFromFile(path)` lets you set the image of the embed from a local file.

**BetterEmbed#setThumbnailFromFile**

`setThumbnailFromFile(path)` lets you set the thumbnail of the embed from a local file.

### Command

As you now have to extend the `Command` class to define a command, there are some included new classes with pre-defined methods, see [ImageCommand](broken://pages/-MfJYElZG0M1eUvbCX84#Imagecommand) & [SlowCommand](broken://pages/-MfJYElZG0M1eUvbCX84#SlowCommand), you should also do this for commands with a lot of same behavior.

Commands can now have an overwritten `registerSubCommands` method for defining SubCommands. They also have a new `subCommand` method for registering a new SubCommand.

**Command#execute**

`execute(ctx)` is a new internal method that should not be overwritten, otherwise command will not be properly executed with SubCommands.

> Note : This method should on the other hand be used for custom `message` events.

**Command#nameAndAliases**

`nameAndAliases` is a new getter to get an array containing the name & the aliases of the command if any.

**Command#registerSubCommands**

`registerSubCommands()` is a new empty method than have to be overwritten for defining SubCommands.

**Command#run**

`run(ctx)` is the method to overwrite to define the behavior of the command when executed.

**Command#subcommand**

`subCommand(name, options?, callback)` is a new method for defining a SubCommand, it has to be used in the `registerSubcommands` method, if you register a SubCommand in the `run` method, the SubCommand will not be executed the first time. Example :

```javascript
class MyCommand extends Command {
    registerSubcommands() {
        this.subCommand('test', (ctx) => ctx.send('success !'));
    }
}
```

**Command#subCommands**

`subCommands` is a new property containing all the SubCommands of the command.

**Command#validate**

`validate(ctx)` is a new method to test all the other validation methods, it returns an object with the details of the error and the error data (like message content). It is used by the `execute` method.

### CommandContext

CommandContext is a new class used across many methods in the [Command](broken://pages/-MfJYElZG0M1eUvbCX84#Command) class.

See on the [documentation](https://advanced-command-handler.github.io/classes/commandcontext.html) what properties & methods this class include.

### CommandHandler

**CommandHandler#create**

The method has a new property `useMentionPrefix` and is a boolean, if set to true the mention of the bot will be added to the prefixes. The property is set to `true` by default to follow the behavior of v2.

**CommandHandler#getCommandAliasesAndNames**

`CommandHandler.getCommandAliasesAndNames()` is a new function returning in one array the name & all the aliases of all commands.

**CommandHandler#getPrefixFromMessage**

`CommandHandler.getPrefixFromMessage(message)` is a new function returning the prefix (if found) used in the message.

**CommandHandler#launch**

The methods now lets you set the presence of the bot or cycling presences, see [here](https://ayfri.gitbook.io/advanced-command-handler/concepts/command-handler#presence) how to do it.

**CommandHandler#loadEvent**

`CommandHandler#loadEvent(directory, filename)` is a new function to load a single event.

**CommandHandler#unloadCommand**

`CommandHandler.unloadCommand(name)` is a new function, unloading the following command if found.

**CommandHandler#unloadEvent**

`CommandHandler.unloadEvent(name)` is a new function unloading the following event and unbinding it to the client if found.

### Defaults

There is now a new default `help` command.

See their documentation [here](/advanced-command-handler/defaults.md).

### Event

**Event#run**

`run(ctx)` is the method to overwrite to define the behavior of the event when fired.

### ImageCommand

`ImageCommand` is a new subclass of the class `Command` that should be used for commands returning embeds with an image or local images.

It adds `sendLocalImage(options)` & `sendImageEmbed(options)` methods, see on the [documentation](https://advanced-command-handler.github.io/classes/imagecommand.html) how to use them.

### Logger

#### LogLevel

`LogLevel` is a new TS enum to define levels of logs, so you can ignore or test Levels.

```typescript
export enum LogLevel {
    OFF = 0,
    ERROR = 1,
    WARNING = 2,
    INFO = 3,
    EVENT = 4,
    LOG = 5,
    DEBUG = 6,
    COMMENT = 7,
    ALL = 7,
}
```

**Logger#LEVEL**

`Logger.LEVEL` is a new property to ignore some logs that are lower than the level.\
&#x20;Example :

```javascript
Logger.LEVEL = LogLevel.INFO
// this will not be logged because 'log' level is lower than 'info' level.
Logger.log("something");
// this will be logged
Logger.info("something");
```

**Logger#ignore**

`Logger.ignore` is an array for defining ignored titles and even titles with a lower level than the one set.\
&#x20;Example :

```javascript
Logger.ignores.push('myTitle');
// This will not be logged because title is 'myTitle'
Logger.warn('this is a message', 'myTitle');

Logger.ignores.push(['something', LogLevel.LOG]);
// This will not be logged because title is 'something' and level is 'log'
Logger.log('bla bla', 'something');
// This will be logged because level is not 'log'
Logger.warn('bla bla', 'something');
```

**Logger#savingFiles**

`Logger.savingFiles` is an array for defining in which files the logs should be emitted in, logs are appended, the file is not overwritten.

### SlowCommand

`SlowCommand` is a new subclass of the class `Command` that should be used for commands where the user has to wait.

It adds a `waitEmoji` property that is by default equals to `⌛` and the `startWait(message)` & `stopWait(message)` methods to add then remove the emoji.

### SubCommand

`SubCommand` is a new subclass of the class `Command`, it's useful for handling commands with different behavior of one command, it's not similar as arguments that are not currently handled.

SubCommand has the same field as `Command` class, except that its run function uses a `SubCommandContext` instead of a `CommandContext`.

See [here ](https://ayfri.gitbook.io/advanced-command-handler/concepts/commands/subcommands)how to create and use SubCommands.

### SubCommandContext

`SubCommandContext` is a new class extending `CommandContext`, used in `run` functions of SubCommands.

See on the [documentation](https://advanced-command-handler.github.io/docs/classes/subcommandcontext.html) what properties & methods this class include.

### Types

There are some new useful types exported.

```typescript
export type Constructor<T extends {} = {}> = new (...args: any[]) => T;
export type MaybeCommand = Constructor<Command> | {default: Constructor<Command>} | {[k: string]: Constructor<Command>};
export type MaybeEvent = Constructor<Event> | {default: Constructor<Event>} | {[k: string]: Constructor<Event>};
```

They are primarily used internally, but I think that it would be useless to export them.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ayfri.gitbook.io/advanced-command-handler/v2-v3-migration-guide.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
