ゼロから始めるLINEBot(AWS×node.js) ①とりあえず動かす

# この記事で分かること
- 決まった時間に決まった文章を喋るとこまで
- 自分がハマったポイント

# この記事の対象者
- いろいろと初心者(自分がそうなので)
- MessagingAPIのような外部APIを使ったことがない
- AWSもあんま詳しくない(アカウントは持ってるくらい)

# 流れ
**第1回　とりあえず動かす　(この記事)**
**1.LINE Developersの登録/設定**
**2.実装(Lambda/node.js)**
**3.定期実行の設定(CloudWatch)**

第2回 オウム返しの実装
4.ドメイン取得,DNS設定,SSL証明書の設定(Route53/ACM/SNS/S3)
5.イベントの受け取り(APIGateWay)
6.ユーザへの返信(Lambda/node.js)

第3回 ユーザ情報、投稿画像の保存　(予定)
7.DBの連携


# 1.　LINE Developersの登録/設定

以下から。
https://developers.line.me/ja/
プロバイダーを作成し、その中にChannelを作成します。
ここまでは公式の説明に沿って行けば大丈夫だと思います。

次に、デフォルトの設定を以下の画像の通りに設定します。
~~・アクセストークンはこの画面から再発行が可能ですが、最大24時間で切れてしまうので後々自動更新を実装します。~~ →これは再発行時に、古いトークンが切れる期限であって、ここで設定する長期アクセストークンは有効期限はもっと長かったです。短期アクセストークンでも30日間有効でした。
・WebHook URLは次回の記事で設定します。とりあえず空欄でOK
・その他の設定はキャプチャ通りに設定

![スクリーンショット 2017-10-29 02.48.17.png](https://qiita-image-store.s3.amazonaws.com/0/79236/f31ceaae-8bca-e72b-cbab-94ce5bd37c18.png)

## 2.　実装(Lambda/node.js)

AWSにログインして、Lambda→関数の作成→一から作成

- [名前]...好きな名前
- [ロール]...[カスタムロールの作成]を選択。

IAM設定画面が開くので、以下のように設定

- [IAMロール]...[新しいIAMロールの作成]
- [ロール名]...好きな名前

![スクリーンショット 2017-10-29 09.49.23.png](https://qiita-image-store.s3.amazonaws.com/0/79236/35994ddc-f98d-0037-9bb9-0f6398a0e954.png)


```json:ポリシードキュメント(CloudWatchへの権限だけ付与。デフォルト設定)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
  ]
}
```

[許可]を押してIAMロールを作ったら、そのロールを指定して、Lambda関数を作成。
Lambda関数が作成されたら、関数コードに以下をコピペ。

- ランタイムはnode.js6.10で動作確認済みです。
- jsファイル名がindex.jsだと思うので、ハンドラ名はindex.handlerとしてください。

```js:index.js
var https = require('https');
exports.handler = (event, context, callback) => {

    var data = JSON.stringify({
       "to": process.env.USER_ID,//CHANNEL設定画面で確認
       "messages": [
         {
           "type": "text", 
           "text": "そろそろ寝ろ！！"
         }
       ]
    });
    opts = {
        hostname: 'api.line.me',
        path: '/v2/bot/message/push',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "Content-Length": Buffer.byteLength(data),
            "Authorization": "Bearer " + process.env.CHANNEL_ACCESS_TOKEN//CHANNEL設定画面で確認
        },
        method: 'POST',
    };

    var req = https.request(opts, function(res) {
        res.on('data', function(res) {
            console.log(res.toString());
        }).on('error', function(e) {
            console.log('ERROR: ' + e.stack);
        });
    });
    req.write(data);
    req.end();
};

```

LINE側のCHANNEL設定画面から、Your UserIDとアクセストークンを確認して、環境変数に設定します。

- USER_ID...Your UserID。グループIDや他の人のID取得方法は割愛。
- CHANNEL_ACCESS_TOKEN...アクセストークン。

![スクリーンショット 2017-10-29 10.34.18.png](https://qiita-image-store.s3.amazonaws.com/0/79236/17c262a9-ee80-f9c0-c903-56243927ab84.png)
 

ここで注意点。

ネットでググると似た記事が複数出てくるのですが、総じて動きませんでした。。
なんの仕様変更なのか、**リクエストヘッダーへのContent-Lengthの指定が必須です。**

そのため、body(ここではdataという変数)のバイト長を以下のように取得してヘッダーに含めました。
確か2016/10頃にChromeのバージョンアップでも同様のことがあって仕事で対応した気がします。。

```js:プログラムからリクエストを送る場合は必ずContent-Lengthを付けましょう。
"Content-Length": Buffer.byteLength(data),
```

テスト実行をしてみると、無事LINE上でメッセージが飛んできました！


![スクリーンショット 2017-10-29 10.30.03.png](https://qiita-image-store.s3.amazonaws.com/0/79236/3bda173a-ea9d-a04f-371e-69a964d0bc3e.png)


lambda上は正常終了してるのに反応がない場合はcurlで確認すると良いでしょう。

```bash:curlコマンドでリクエスト投げるならこう
curl -X POST -H 'Content-Type:application/json' -H 'Authorization: Bearer [AccesToken]' -d '{  "to": "[User ID]", "messages":[{"type":"text","text":"curlコマンドから投稿"}]}' https://api.line.me/v2/bot/message/push
```
## 3.定期実行の設定(CloudWatch)

さて、僕は夜更かしなので24時なったら寝るように促してくれると嬉しいです。
CloudWatchにcronの設定をします。

※標準時で設定してくださいね。

![スクリーンショット 2017-10-29 12.41.49.png](https://qiita-image-store.s3.amazonaws.com/0/79236/5c02855a-0691-6a6f-ccde-02e5c6819c26.png)

以上です。

上にも書きましたが、AccessTokenが切れると使えなくなってしまいます。
続きの記事で対応しますが、とりあえず動かすことができました。

次回は、ユーザの投稿をHookしてオウム返しする機能をつくります。

## 所感
- 1年未満の記事ですら動かないものばかり。コピペプログラマの自分にはしんどい
- ゼロから記事って、どこまでゼロから書くべきなのか悩む。