> For the complete documentation index, see [llms.txt](https://go-adam.gitbook.io/adam/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://go-adam.gitbook.io/adam/first-steps/commands.md).

# Creating Your First Command

A command is nothing more than a type implementing the `plugin.Command` interface. That interface is defined as follows:

```go
type Command interface {
    CommandMeta
    Invoke(*state.State, *Context) (interface{}, error)
}
```

`CommandMeta` is another interface consisting of getters for the command's metadata. You don't really need to worry about the methods it requires, as the `command` package provides us with predefined types.

## Creating a Command

Using that knowledge, you can create your first command. Create a package with your commands name, as detailed in [Project Layout](/adam/master.md#project-layout), and add a `{{package_name}}.go` file to it.

### Example: A Ping Command

In the `ping` package create a `ping.go` file where you create your command type. To implement the `plugin.CommandMeta` interface, which is part of the `plugin.Command` interface, you can embed `command.Meta` in your `Ping` type.

{% code title="plugins/ping/ping.go" %}

```go
package ping

import (
    "github.com/mavolin/adam/pkg/impl/command"
    "github.com/mavolin/adam/pkg/plugin"
)

type Ping struct {
    command.Meta
}

var _ plugin.Command = new(Ping) // compile time check
```

{% endcode %}

This leaves your `Ping` command with only `Invoke` left, to fully satisfy `plugin.Command`.

{% code title="plugins/ping/ping.go" %}

```go
import (
    ...
    "github.com/diamondburned/ariakwa/v2/state"
    "github.com/mavolin/adam/plg/plugin"
    
    "time"
)

...

func (p *Ping) Invoke(_ *state.State, ctx *plugin.Context) (interface{}, error) {
    t := time.Now()
    
    msg, err := ctx.Reply("The ping to discord is `calculating...`")
    if err != nil {
        return nil, err
    }
    
    _, err := ctx.Editf(msg.ID, "The ping to discord is %d ms", 
        time.Since(now).Milliseconds())
    return nil, err
}
```

{% endcode %}

Now that we've added `Invoke`, let's add a constructor function where we create a new `Ping` instance and fill the `command.Meta` struct we embedded earlier.

{% code title="plugins/ping/ping.go" %}

```go
import (
    ...
    "github.com/diamondburned/arikawa/v2/discord"
    "github.com/mavolin/adam/pkg/plugin"
    "github.com/mavolin/adam/pkg/impl/command"
)

var _ plugin.Command = new(Ping) // compile-time check

// New creates a new Ping command.
func New() *Ping {
    return &Ping{
        Meta: command.Meta{
            Name:             "ping",
            ShortDescription: "Tells you the ping to Discord's servers.",
            ChannelTypes:     plugin.AllChannels,
            BotPermissions:   discord.SendMessagesPermission,
        },
    }
}
    

func (p *Ping) Invoke(_ *state.State, ctx *plugin.Context) (interface{}, error) {
    ...
}
```

{% endcode %}

{% hint style="info" %}
`command.Meta` has a lot more fields than just those we used for the `Ping` command. Refer to its [documentation](https://pkg.go.dev/github.com/mavolin/adam/pkg/impl/command#Meta) for more information.
{% endhint %}

### Invoke's Return Values

As you might have noticed, `plugin.Command.Invoke` has two return values, and while the `error` return value might be a bit more self-explanatory, `interface{}` is probably not. So what can you use it for?

Everything you return as the first value will get turned into a message and sent in the invoking channel back to the user using the `plugin.Context`'s `Replier`. Obviously, not everything can be turned into a message, at least not without causing confusion. Therefore, only the following return types are allowed:

* `uint`, `uint8`, `uint16`, `uint32`, `uint64`
* `int`, `int8`, `int16`, `int32`, `int64`
* `float32`, `float64`
* `string`
* `discord.Embed` and `*discord.Embed`
* `*embedutil.Builder`
* `api.SendMessageData`
* `i18n.Term`
* `*i18n.Config`
* any type implementing`plugin.Reply`

Of course, just`nil` is also valid, and won't create any response.

The second return value, `error`, is handed to the bot's error handler if it's not `nil`. While you can define a custom error handler, the default one will wrap every error not implementing `errors.Error` into a `errors.InternalError` and call `Handle` on it. We'll take a closer look at this later on in the [Error Types](/adam/errors/error-types.md) chapter.
