Bot do discord com Elixir e Nostrum
Tags: elixir, tutorial, brasil
Published: 2020-08-25 17:29:41

## Requisitos

* Ter o elixir instalado
* Antes de tudo é necessário ter um bot criado no [Portal de desenvolvedores do discord](https://discord.com/developers), caso não tenha ou não saiba como fazer, recomendo seguir os passo desse [post](https://canaltech.com.br/apps/como-criar-bots-para-responder-discord/) do canaltech.

## Iniciando o projeto
Antes de tudo vamos iniciar nosso projeto rodando o comando:
`mix new <nome_do_aplicativo> --sup`

Passamos a flag `--sup` para que o mix inicie nosso projeto com um `Supervisor` configurado, assim ao iniciarmos nossa aplicação o supervisor irá iniciar todas as aplicações que pedirmos.

Com isso nossa estrutura de arquivos se encontra da seguinte forma: 

![Estrutura de arquivos](https://dev-to-uploads.s3.amazonaws.com/i/7azwh1yzhp5q6dhn1wjt.jpeg)

## Adicionando e configurando o nostrum

Com o projeto iniciado devemos adicionar o nostrum em nossas dependências, para isso basta modificiar o arquivo `mix.exs` e modificar a função `deps` ficando da seguinte forma:

```elixir
defp deps do
  [
    {:nostrum, "~> 0.4"}
  ]
end
``` 
e executar o comando:
`mix deps.get`

Com isso agora devemos configurar o nostrum e fornecer o token do nosso bot, para isso vamos criar o diretório config e dentro o arquivo `config.exs`, pode ser feito com o comando:
`mkdir config && touch config.exs`

Para configurar o nostrum basta adicionar o seguinte no arquivo:

```elixir
import Config

config :nostrum,
  token: "SEU TOKEN"
  # OU caso não queria deixar de forma explicita, podemos pegar ele de uma variável de ambiente ao inicializa-lo
  #token: System.get_env("BOT_TOKEN")
```
  

 e por vamos criar um modulo para iniciar o bot e adicionar esse modulo ao supervisor. vamos criar o arquivo consumer.ex, dentro de lib/<nome_do_projeto>/, com o seguinte conteúdo:
```elixir
defmodule Example.Consumer do
  use Nostrum.Consumer

  def start_link do
    Consumer.start_link(__MODULE__)
  end

  def handle_event(_) do
    :ok
  end
end
```
Trocando o `Example`, pelo nome da sua aplicação, agora em lib/<nome_da_aplicação>/application.ex, vai ficar da seguinte forma:

```elixir 
defmodule Example.Application do
  use Application
  
  def start(_type,_args) do 
    children = [
      Example.Consumer 
    ]

  opts = [strategy: :one_for_one, name: Example.Supervisor]
  Supervisor.start_link(children,opts)
  end
end
```
Com isso ao rodarmos o comando:
`mix run --no-halt` ou `iex -S mix`, nosso bot deve ficar online no discord 🙂

OBS: Caso você tenha optado por usar o `System.get_env("BOT_TOKEN")` é necessário rodar o comando da seguinte forma:
`BOT_TOKEN="TOKEN" mix run --no-halt` ou `BOT_TOKEN="TOKEN" iex -S mix` 

![Bot online](https://dev-to-uploads.s3.amazonaws.com/i/y0gklisv0v8bw4bkft8y.jpeg)

Mas estamos ignorando todos os eventos, então por enquanto ele não está fazendo nada 😥

## Lidando com comandos

Para lidar com comandos devemos cuidado do evento `:MESSAGE_CREATE`, então nosso `consumer.ex` fica da seguinte forma:

```elixir
defmodule Example.Consumer do
  use Nostrum.Consumer
  alias Nostrum.Api

  def start_link do
    Consumer.start_link(__MODULE__)
  end

  def handle_event({:MESSAGE_CREATE,msg, _ws_state}) do
     case msg.content do
      "!ping" -> Api.create_message(msg.channel_id, "Pong")
       _ -> :ok
     end
  end

  def handle_event(_) do
    :ok
  end
end

```
Com isso nosso bot responde ao comando !ping, com a mensagem pong, no canal que a mensagem foi enviada.


![bot responde Ping com Pong](https://dev-to-uploads.s3.amazonaws.com/i/g6jt10mz47q2c8zp3uoq.jpeg)

Com isso nosso bot já esta respondendo a comandos, mas está bem simples, agora você é livre para organizar os arquivos e lidar com os comandos da forma que deseja, aqui está o link do repositório do github com alguns comandos e a forma que preferi programar.

Qualquer dúvida pode deixar nos comentários ou mandar uma mensagem no discord: dudu#6876

Repo: https://github.com/uduDudu/discord-bot-elixir