DenoでDiscordのbotを作ってherekuにデプロイしてみた。

ふとDiscordのBotを作ってみたくなり、ついでにDenoがv1.0.0になったと聞いて、どちらも初めてですが少し遊んでみました。

# 追記 2021-02-02

Discord APIのライブラリ
https://deno.land/x/coward@v0.1.0/mod.ts
の開発は停止されたようです。

代替として
https://github.com/discordeno/discordeno
を使うのが良さそうです。

# Denoのインストール

ちょうどWSL2も使えるようになったので、今回はWSL2(Ubuntu)にDenoを入れるところからはじめました。Ubuntu自体は再インストールした直後のため、ほぼまっさらな状態です。


[公式の手順](https://deno.land/manual/getting_started/installation)に従ってインストールしましょう。

```sh
# Ubuntuの場合
$ curl -fsSL https://deno.land/x/install/install.sh | sh
$ deno --version
deno 1.0.1
v8 8.4.300
typescript 3.9.2
```

# Discordのbot作成

まずはBotをDiscordに導入しておきます。

1. [DEVELOPER PORTAL](https://discord.com/developers/applications)にアクセスします。
2. **NEW APPLICATION**から適当なアプリ名を付けます。
3. Botメニューの**Add Bot**から新しいBotを作ります。
    4. **TOKEN**の文字列をどこかにメモしておきます。
4. OAuth2メニューの**SCOPES**の**bot**にチェックを入れます。
    4. 下部の**BOT PERMISSIONS**は、ひとまず**TEXT PERMISSIONS**の**Send Messages**にチェックを入れておきます。
    5. `https://discord.com/api/oauth2/authorize?client_id=XXXXXXXXXXXXXXXXXXXXXXXXXXX&permissions=Y&scope=bot`のようなリンクが見えていると思いますが、そのリンクを開くと任意のサーバにBotを導入できます。

以上でBotの作成とサーバへの導入ができました。

# Botのプログラム作成

次に、導入したBotのプログラムをTypeScript(Deno)で用意します。([参考記事](https://qiita.com/Seraimu/items/414b78c5bf1a40698f41))

```typescript 
//main.ts
import { Coward, Message } from "https://deno.land/x/coward@v0.1.0/mod.ts";

let client = new Coward(Deno.env.get("BOT_TOKEN") as string);

client.on("ready", () => {console.log("Bot is ready!");});

client.on("messageCreate", async (message: Message) => {
    if(message.content == "Hello") {
        client.postMessage(message.channel.id, "World!");
    }
});

client.connect();
```

以上で、`Hello`というメッセージに反応して`World!`と返すBotの実装ができました。
やはり面倒な設定ファイルが不要で、`main.ts`だけで完結するのは気持ちいいですね。

# ローカルでの動作確認

```sh
$ export BOT_TOKEN=メモしたbotのトークン
$ deno run --allow-net --allow-env --cached-only main.ts
Bot is ready!
```
上記コマンドを実行し、Botを起動させた状態でDiscordに`Hello`とメッセージを入力・送信してみます。
作成したBotが`World!`とメッセージを送信してくれると思います。
確認ができたら`Ctrl + C`で停止しておきましょう。

# デプロイ

最後に、このBotをherokuで動かすようにしてみたいと思います。

## HerokuとGit
WSLに何も入っていなかったのでサクッと導入してしまいます。
導入済みの方は、適宜スキップしましょう。

### Herokuの導入とアプリ作成
herokuのアカウントは、無ければ作ってしまいましょう。
heroku-cliのインストールは[公式のページ](https://devcenter.heroku.com/articles/heroku-cli#other-installation-methods)にあるコマンドを使います。
デプロイ方法は[こちらの記事](https://qiita.com/chibato/items/839e13ab09428dc1481c)を参考にしました。


```sh
$ curl https://cli-assets.heroku.com/install.sh | sh
$ heroku -v
heroku/7.41.1 linux-x64 node-v12.16.2
$ heroku create --buildpack https://github.com/chibat/heroku-buildpack-deno.git
#ブラウザが自動で開くので、ログインすると適当な名前のアプリが作成されていると思います。
$ heroku config:set BOT_TOKEN=メモしたbotのトークン
```

#### Procfile
ここで、`Procfile`というherokuに実行してもらうコマンドファイルを作成しておきます。
拡張子も無く、`Procfile`がそのままファイル名です。
ファイルの中身は、下記のように、`worker: `というラベルに続けて、ローカル実行時と同じコマンドを記入しておきます。

```sh
worker: deno run --allow-net --allow-env --cached-only main.ts
```


### Gitの設定とHerokuへPush
こちらも、サクッとやってしまいます。

```sh
# gitのユーザ名、メールアドレス、パスワードの保存設定をします。
$ git config --global user.name 'USER NAME'
$ git config --global user.email 'example@com'
$ git config --global credential.helper 'store --file ~/.git_credentials' # とても危ないので良い子は真似してはいけない
$ git add .
$ git commit -m "first commit"
$ git push heroku master --force
```

`main.ts`と`Procfile`がherokuにpushされていると思います。

```
$ heroku logs --tail
```

で、ビルドエラーなど発生していないか確認して見ましょう。

## herokuの設定変更

作成したherokuアプリのWeb設定メニューから、Procfileの設定をする必要があります。

下記画像のように、Resourcesタブを開くと中央にProcfileの内容が表示されていると思います。
右端のペンマークをクリックし、編集可能状態にしたうえで、トグルボタンを押し、有効化させましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152282/617d77c9-4ad5-2a52-84af-c8ddbf56cd0d.png)

この状態で、ローカル動作確認のときと同様に、Discordに`Hello`とメッセージを入力・送信してみます。
Herokuで動いているBotが`World!`とメッセージを送信してくれば、完璧です。
(初回は、もしかしたら起きるのに時間がかかるかもしれないです)

# まとめ
TypeScriptなのに`main.ts`程度しかファイルが生まれないDeno、やはり気持ち良いですね。