Node.js express 4.xでLINE Messaging APIを利用したBOTを開発しはじめる

# はじめに
LINE Messaging APIを利用したNode.jsでの開発事例はあまり多くないように思いますが、BOTでは小さい非同期処理を大量することが多いので、Node.jsはなかなか適していると言えると思います。

開発にはServerとSSL環境が必要ですので、前段にプロキシサーバーを設けるなどして対応するようにしてください。この記事では実装部分にフォーカスして書いています。

# Hello world!
始める前に、アカウントの作成や必要な設定、認証情報の取得などを済ませておきましょう。
https://business.line.me/ja/services/bot

## 下準備
Node.jsはv6.9.1を利用します。

``` bash
$ echo v6.9.1 >> .nvmrc
$ nvm use
Now using node v6.9.1 (npm v3.10.8)
```

必要なpackageのinstallを行います。

```bash
$ npm install express —save
$ npm install body-parser —save
$ npm install node-line-bot-api —save
```

Node.jsでは公式のSDKがありませんので、こちらのnpm moduleを利用します。documentに記載がないものもありますが、基本的な機能は全て網羅されています。
https://github.com/tejitak/node-line-bot-api

## 書き初め
READMEを参考にオウム返しBOTを作成します。

``` javascript:app.js
const express = require('express');
const line = require('node-line-bot-api');
const bodyParser = require('body-parser');
const app = express();

// 送信元の検証にrawBodyが必要
app.use(bodyParser.json({
  verify(req,res,buf) {
    req.rawBody = buf
  }
}));

// LINE BOT SDK 初期化
line.init({
  accessToken: '{YOUR_ACCESS_TOKEN}',
  channelSecret: '{YOUR_CHANNEL_SECRET}'
});

app.post('/webhook/', line.validator.validateSignature(), (req, res) => {
  // get content from request body
  const promises = req.body.events.map(event => {
    // reply message
    return line.client.replyMessage({
      replyToken: event.replyToken,
      messages: [{ // 最大5件
        type: 'text',
        text: event.message.text
      }]
    });
  });
  Promise.all(promises).then(() => res.json({ success: true }));
});

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});
```
```bash
$ node app.js
```

BOTが受け取れるwebhook eventの詳細はこちらで確認することができます。テキストは勿論、画像やファイルは別途Get Content APIを通じて取得することができます。また、replayTokenを使ったメッセージングは友達数制限のないフリープランでも利用できます。
https://devdocs.line.me/ja/#webhook

# Template Message
Messaging APIでは従来のimagemap Messageなどに加え、template Messageというユーザーがトーク上でリアクションできるメッセージ形式が追加されました。
https://devdocs.line.me/ja/#template-message

template Messageはバリデーションが厳しく、エラー内容が読めないとつらいので、以下の3行を追記します。（雑な方法なので、きちんとしたいひとはunhandledRejectionで調べてください。）

```javascript:app.js
process.on('unhandledRejection', function(reason, p) {
  console.error(reason);
});
```

webhookの部分を少し変更して、buttons templateを返すようにしてみます。その際、PC版LINEや古いLINEのサポートのためにaltTextという代替テキストを指定する必要があることに注意してください。

```javascript:app.js
app.post('/webhook/', line.validator.validateSignature(), (req, res) => {
  const promises = req.body.events.map(event => {
    return line.client.replyMessage({
      replyToken: event.replyToken,
      messages: [{
        type: 'template',
        altText: 'スマートフォンから確認してください',
        template: {
          type: 'buttons',
          title: 'TITLE', // 40文字以内
          text: 'TEXT', // 60文字以内
          thumbnailImageUrl: 'https://***.**/icon.png', // httpsのみ可
          actions: [{
            type: 'message',
            label: 'pen',
            text: 'I have a pen.'
          }, {
            type: 'message',
            label: 'apple',
            text: 'I have a apple.'
          }, {
            type: 'message',
            label: 'apple pen',
            text: 'mmm... apple-pen'
          }]
        }
      }]
    });
  });
  Promise.all(promises).then(() => res.json({ success: true }));
});
```

ドキュメントのバリデーションに従わないと、Messaging API 側でエラーを返します。actionsはURLを開かせるuriタイプや、webhookにeventを送信できるpostbackタイプなどがあります。

# さいごに
今回紹介したtemplate Messageなどを利用して、メモ帳代わりに使えるNode.js製のLINE BOTを開発しました。話しかけられた内容をメモ書きとして記録して、あとからブラウザで一覧して見ることができるBOTです。簡単なタスク管理や、ブックマークとしても利用したり、公開設定にして共有したりできます。（宣伝）
https://memoma.me/notes/kawasako3
https://line.me/R/ti/p/%40pnr9158m

SSL対応やLINE側の設定が少し面倒ですが、BOT自体は割とカジュアルに書き始められると思います。グループにも招待できるようになり、LINEだと色んなひとと遊べるので、ネタでBOTを作ったりすると面白いです。