deno-linebotでLIME Messageing APIを使ってみる

# はじめに

最近[Deno](https://deno.land/)を使っています。TypeScriptをそのまま実行できるので便利です。Denoのモジュールに[deno-linebot](https://deno.land/x/linebot@v1.1.0)というLINE Messaging APIのSDKがあったので使ってみました。

# 実行環境をセットアップする

[こちらの記事](https://qiita.com/bathtimefish/items/34e128cb2578c4db0845#messaging-api%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B)を参考にMessaging APIチャンネルとEC2のセットアップ、Let's Encryptのインストールを行います。

Messaging API チャンネルの `Webhook URL` は以下のように設定しました

```
https://line-bot.bathtimefish.com:3000/messaging/event
```

WebhookリクエストにはHTTPSが必須となりますが、Port 443でのサーバー実行は面倒なので、今回はPort 3000を使います。EC2インスタンスのセキュリティグループのインバウンドルール設定で3000を空けておいてください。

node.jsのインストールは省いても大丈夫です。

以下のコマンドでDenoをインストールします

```
apt install -y unzip
```

```shell
curl -fsSL https://deno.land/x/install/install.sh | sh
```

インストールが成功すると以下のように表示されるのでパスを通します

```shell
Deno was installed successfully to /home/ubuntu/.deno/bin/deno
Manually add the directory to your $HOME/.bashrc (or similar)
  export DENO_INSTALL="/home/ubuntu/.deno"
  export PATH="$DENO_INSTALL/bin:$PATH"
Run '/home/ubuntu/.deno/bin/deno --help' to get started

Stuck? Join our Discord https://discord.gg/deno
```

```shell
vi ~/.bashrc
# .bashrcに以下を追記する
===
export DENO_INSTALL="/home/ubuntu/.deno"
export PATH="$DENO_INSTALL/bin:$PATH"
===

source ~/.bashrc
```

```shell
deno --version
deno 1.31.1 (release, x86_64-unknown-linux-gnu)
v8 11.0.226.13
typescript 4.9.4
```

# Botサーバーを作成する

Botサーバーを作成していきます。ディレクトリを作成して、letsencryptの証明書を格納します

```shell
mkdir -p deno-linebot-example/src
cd deno-linebot-example
mkdir -p cert
```

```shell
sudo cp /etc/letsencrypt/live/[ドメイン名]/fullchain.pem ./cert/cert.pem
sudo cp /etc/letsencrypt/live/[ドメイン名]/privkey.pem ./cert/key.pem
sudo chown ubuntu:ubuntu ./cert/*.pem
```

`src/index.ts`を作成して以下のコードを入力します。簡単なエコーサーバーです。

```src/index.ts
import { opine, json } from "https://deno.land/x/opine@2.3.3/mod.ts";
import type { HTTPSOptions } from "https://deno.land/x/opine@2.3.3/mod.ts"
import { linebot } from "https://deno.land/x/linebot@v1.1.0/mod.ts"

const opineHttpsOptions: HTTPSOptions = {
    port: 3000,
    certFile: "cert/cert.pem",
    keyFile: "cert/key.pem",
}

const options = {
   channelId: "YOUR_CHANNEL_ID",
   channelSecret: "YOUR_CHANNEL_SECRET",
   channelAccessToken: "YOUR_CHANNEL_ACCESS_TOKEN",
   verify: true
}
const bot = linebot(options)
const app = opine()
const linebotParser = bot.parser(json)

app.post("/messaging/event", linebotParser)

bot.on('message', async (event: any) => {
    try {
        console.info(`Received message from LINE Client`)
        console.info(`Type: ${event.type} ID: ${event.message.id}, Text: ${event.message.text}`)
        await event.reply(event.message.text)
    } catch (e) {
        console.error(e)
    }
})

app.listen(opineHttpsOptions)
```

# 実行してみる

実行します

```shell
cd ~/deno-linebot-example
deno run -A ./src/index.ts
```

アプリからメッセージを送ると、オウム返しがきました。

![line-bot-example-client.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61995/2becd564-4afd-d872-4ffd-044c22652681.png)

Botサーバー側には以下のように表示されてメッセージが到着しているのがわかります

```shell
deno run -A ./src/index.ts 
Received message from LINE Client
Type: message ID: 17709072306682, Text: こんにちは
```

とりあえず基本的なメッセージのやりとりはできることがわかりました。

# おわりに

ソースコードを眺めましたが[Opine](https://github.com/cmorten/opine)に強く依存しているのと、型定義がろくにされてないので `bot.on('message', async (event: any) => {}` event: anyとかどうよ。とかちゃんと開発する場合の不安要素が多々ありますが、ちょっとDenoでLINE Botを使いたい程度のことなら無難に使えるかと思います。

レポジトリは現時点では1年以上前に作られてからほぼ放置状態ですが、DenoでのLINE開発のニーズが増えればメンテされるかもしれませんね。