【Node.js】Line Messaging APIでLine Botを作るまでに躓いた箇所をまとめる

#はじめに
普段はVue.jsやNuxt.jsを使っている者です。バックエンド側の知見も得ようと言うことでExpressを最近触りはじめたのですが、今回はLINE botを作るにあたって躓いた箇所をまとめていきたいと思います。

#LINE Messageing APIの導入①（ngrokでトンネリングさせる）

LINE Messageing APIのwebhookを使用する際はhttps通信でやりとりをしなくてはいけません。しかしhttpsでやりとりをローカルで行うことはできずherokuに一度アップして動作の確認をする記事が散見しました。

毎回デプロイする手間を省くためにngrokを使用することによってローカルでhttps通信でLINE Messageing APIを試すことができるのでこちらを採用した方が良いかと思います。不便な点としては1時間でsessionが切れてしまうので都度URLを登録し直すのがめんどくさいというところでしょうか。

###■ngrokで引っかかったポイント

ngrokを使用する際は、ターミナルを2つ開く必要があり、片方ではlocalhost3000でローカルサーバーを立てておき（console.logの監視用）もう片方ではngrokのサーバー用に立てておく必要があります。

###■解決方法
→サーバーは2つ立てる必要がある。
※Shopifyアプリも同様にngrokを使用しなくてはいけない模様（https通信が必要）。

```bash
ngrok http 3000
#コマンドを打ち込むと下記表示になる
```
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175826/649b01cc-5b82-afb4-3e41-56e2726636a0.png)

httpsから始めるurlをLINEに登録します。ちなみに上記の「200OK」や「502 Bad Gateway」などはLINEアプリでテキストメッセージを打った時の判定です。

```javascript
app.post("/webhook", line.middleware(config), (req, res, next) => {
  res.sendStatus(200);
});
```
→とりあえず上記の設定でレスポンス200が返るようになりました。全体のコードは後述します。

#LINE Messageing APIの導入②（line.middlewareについて）

###■line.middlewareで引っかかったポイント

line.middleware(config)でエラーが発生したので調査。LINE Messageing APIが使えず困っていたがどうやらmiddlewareが機能していないのが原因だったっぽい。

###■解決方法

まさかのbodypersorとバッティングしていたようです。LINEの公式にもエビデンスが載っていたのでそちらを参考に解決しました。Passport.jsの時もありましたが外部モジュールやAPIを使用する際は記述する順番（依存関係）も考慮しないといけないのですね。

```javascript
// don't
app.use(bodyParser.json())
app.use(middleware(config))

// do
app.use(middleware(config))
app.use(bodyParser.json())
```

#LINE Messageing APIの導入③（MVCに整形する）
MVCっぽく書き出しました。特に躓いたというわけではありませんが、下記コードで処理が正常に走りましたので参考までに載せます。

```javascript:index.js
const lineRoutes = require("./routes/lineRoutes");
app.use(lineRoutes);
```
```javascript:lineRoute.js
const express = require("express");
const router = express.Router();
const lineController = require("../controllers/lineController.js");
const line = require("@line/bot-sdk");
require("dotenv").config();

const config = {
  channelSecret: process.env.LINE_CHANNEL_SECRET,
  channelAccessToken: process.env.LINE_ACCESS_TOKEN,
};

router.post("/webhook", line.middleware(config), lineController.line_post);

module.exports = router;
```
```javascript:lineController.js
const { handleEvent } = require("../middleware/lineMiddleware");

const line_post = (req, res) => {
  const events = req.body.events;
  events.map(handleEvent);
};

module.exports = {
  line_post,
};
```
```javascript:lineMiddleware.js
const line = require("@line/bot-sdk");
require("dotenv").config();
const config = {
  channelSecret: process.env.LINE_CHANNEL_SECRET,
  channelAccessToken: process.env.LINE_ACCESS_TOKEN,
};
const client = new line.Client(config);

const handleEvent = async (event) => {
  if (event.type !== "message" || event.message.type !== "text") {
    return null;
  }
  await client.replyMessage(event.replyToken, {
    type: "text",
    text: event.message.text,
  });
};

module.exports = { handleEvent };
```

#さいごに
何が言いたいかと言うとngrokに対しての知見不足とLINEの公式ドキュメントを読まなかったため時間がかかったと言うことです。思わぬところでハマってしまうので初見の実装ではしっかりとドキュメントを読む癖をつけたいです。

振り返ってみればわりと単純なコードでLINE連携を行うことができるということがわかりました。実際にLINEからメッセージが返ってきたのを確認した時は素直に嬉しかったです。またLIFFでアプリを作ればかなりリッチな画面実装をすることができるなという感じがしました。機会があれば試してみたいです。

#参考URL
https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d#2-nodejs%E3%81%A7bot%E9%96%8B%E7%99%BA

https://line.github.io/line-bot-sdk-nodejs/api-reference/middleware.html#usage