# Middlewares

Middlewares are functions that are run before a command is invoked. They can be used to inject data into a command's `plugin.Context`, conditionalize execution, or do things like performance and stats tracking.

Adam itself provides middlewares on both a global and a per-plugin level. Aside from that, you can also add middlewares through the state. The order of execution is as follows.

1. A message create event or message update event is received by the state's event handler.
2. All global state middlewares are called.
3. The `MessageCreateMiddlewares` or `MessageUpdateMiddlewares` found in the bot's `Option`s are called.
4. The router is called, which either routes the command or discards the message if it's not a command.
5. Adam's global middlewares are called.
6. The plugin's middlewares are called, starting from the highest-most module to the command itself.
7. Adam's global post-middlewares are called.
8. The command is invoked.

## Adding middlewares

Global middlewares can be added using `bot.Bot.AddMiddleware`. Similarly, global post middlewares can be added using `bot.Bot.AddPostMiddleware`.

To get the plugin middlewares, the bot checks if `interface { Middlewares() []bot.MiddlewareFunc }` is implemented. Every `module.Module` already does that, and you can add middlewares using `.AddMiddleware(f interface{})`. However, commands, being custom types, need to implement that interface manually. You can do so by embedding a `bot.MiddlewareManager` into your command's struct, which adds the required `Middlewares` function, as well as an `AddMiddleware` function to add middlewares to the command.

## Supported types

`bot.MiddlewareManager`, `bot.Bot`, and `module.Module` support the following middleware signatures:

* `func(*state.State, interface{})`
* `func(*state.State, interface{}) error`
* `func(*state.State, *state.Base)`
* `func(*state.State, *state.Base) error`
* `func(*state.State, *state.MessageCreateEvent)`
* `func(*state.State, *state.MessageCreateEvent) error`
* `func(*state.State, *state.MessageUpdateEvent)`
* `func(*state.State, *state.MessageUpdateEvent) error`
* `func(next CommandFunc) CommandFunc`
