Line botをAWS LambdaとAPI Gatewayでアモーレ！！- code解説編

どうも！アモーレkoooheiです。前回**[Line botをAWS LambdaとAPI Gatewayでアモーレ！！- 実装編」](http://qiita.com/kooohei/items/650c331f95f83072f4d6)**では、リトルに言われて自分でアモーレをつくっちゃいました♪
と言っても街行くレディに声かけてもダメなので、Line botとAWSを組み合わせたですよ！
名付けて「ぼくのアモーレ」！！

今回はそこで利用したLambdaのcodeについて解説しちゃいます。


# はじめに
まずは今回のcodeを見てみましょう。

```js:myAmore
var https = require('https');

exports.handler = function(event, context) {
    console.log('EVENT:', JSON.stringify(event, null, 0));
    var msg = event.result[0];
    var data = JSON.stringify({
      to: [msg.content.from.toString()],
      toChannel: 1383378250,
      eventType: "138311608800106203",
      content: msg.content
    });
    var url ='https://trialbot-api.line.me/v1/events';
    var opts = {
        host: 'trialbot-api.line.me',
        path: '/v1/events',
        headers: {
            "Content-type": "application/json; charset=UTF-8",
            "X-Line-ChannelID": "【Channel ID】",
            "X-Line-ChannelSecret": "【Channel Secret】",
            "X-Line-Trusted-User-With-ACL": "【MID】"
        },
        method: 'POST'
    };
    var req = https.request(opts, function(res){
        res.on('data', function (chunk) {
            console.log(res.statusCode + chunk.toString());
        });
        req.on('error', function(err) {
          console.log('ERROR: ' + err.message);
        });
    });
    req.write(data);
    req.end();
};
```

このアモーレは「node.js 4.3」(現在Lambdaの最新)でできています。


# 説明
ということで内容を見ていきましょう。

## モジュールの読み込み
Line botではやり取りはhttpsで行うため、まずはじめに[httpsモジュール](http://nodejs.jp/nodejs.org_ja/api/https.html#https_https
)を読み込みます。

```js:モジュールの読み込み
var https = require('https');
```


## モジュール化
次に[関数をモジュール化](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/nodejs-prog-model-handler.html)を行います。lambdaのイベントハンドラで指定しているのはこの部分です。
index.handlerはindex.jsのhandlerを呼び出しているということになります。
そのため、基本的にはこの中に行いたい処理を記載していきます。

```js:モジュール化
exports.handler = function(event, context) {
  ...................
}
```


## 受け取りデータの処理
はじめに受け取ったデータの処理を行います。
まずはどんなデータを受け取っているのかを確認する必要がありますね。
ここでは[console.log](http://nodejs.jp/nodejs.org_ja/api/console.html#console_console_log_data)で標準出力をプリントしています。

```js:consoleモジュール
    console.log('EVENT:', JSON.stringify(event, null, 0));
```
consoleモジュールは標準出力と標準エラーに出力するためのものです。
この関数は引数を複数受けることができるため、この場合は`Received event:`と`JSON.stringify(event, null, 0)`の二つの引数を受けています。

出力イメージとしては、

```text:イメージ
'EVENT:'
"JSON.stringify(event, null, 0)で取得した内容。"
```
となります。
またLambdaの場合、`console.log`の出力はCloudWatchのログへ吐き出されます。

さらに、`JSON.stringify(event, null, 0)`を見てみます。
[JSON.stringify](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)はJavaScriptの値をJSON文字列に変換するメソッドです。
さらに詳しく説明すると、このオブジェクトの構文は

```js:構文
JSON.stringify(value[, replacer[, space]])
```
- 第１引数：value・・・データ
- 第２引数：replacer・・・変換する関数または配列
- 第３引数：space・・・戻り値のJSONテキストにインデントや空白文字、改行文字を追加

となります。

AWS Lambdaでは、`event`パラメーターを使用してイベントデータをハンドラーへ渡します。

そのためここでは、`event`パラーメーターに入っているデータを標準出力する処理となります。
実際にCloudWatchに吐き出されたログは以下になります。
![amore04_log.png](https://qiita-image-store.s3.amazonaws.com/0/82090/bf74e2eb-5d76-bf3c-4cad-ce2576e102e9.png)


## 送信データの作成
続いて送信データの作成を行います。
まず_msg_という変数を用意します。

```js:event
var msg = event.result[0];
```
ここでは受け取った_event_データの_result_部分を格納しています。
![amore04_log2.png](https://qiita-image-store.s3.amazonaws.com/0/82090/fc7a7c6b-b53f-6210-f710-2665fc5f024a.png)


次に送信するためのデータを作成します。

```js:JSON.stringify
var data = JSON.stringify({
  to: [msg.content.from.toString()],
  toChannel: 1383378250,
  eventType: "138311608800106203",
  content: msg.content
});
```
内容はline-bot-apiの[データモデル](http://line.github.io/line-bot-api-doc/ja/api/events/post.html#id6)を元に作成しています。
各フィールドについては以下のとおりです。

|フィールド  |タイプ            |内容                            |
|:--------|:---------------|:-------------------------------|
|to       |Array of Strings|送信先ユーザーの識別子の配列 (最大150)|
|toChannel|Integer         |定数 1383378250                  |
|eventType|String          |定数 "138311608800106203"        |
|content  |Content Object  |このイベントのコンテンツ               |

_[msg.content.from.toString()]_は**クライアントから送られてきたメッセージ**の_from_です。つまりこの値が今回の_to_になります。
![amore04_log3.png](https://qiita-image-store.s3.amazonaws.com/0/82090/5677590d-686d-6e4f-3b87-bc562c15f9db.png)

_toChannel_は**送信先のChannel ID**となります。値は固定値なので「1383378250」を設定します。

_eventType_は**メッセージ送信のイベント**であることを示す「138311608800106203」を指定します。

_content_の_msg.content_はクライアントから送られてきたメッセージの_contet_部分になります。
![amore04_log4.png](https://qiita-image-store.s3.amazonaws.com/0/82090/76fcbf3b-b3d0-722f-277e-9a9041c48343.png)

これが送信コンテンツに入るためオウム返しになっています。


# リクエストの作成
_opts_変数を用意し、そこにリクエストを送るために必要なデータを格納しています。
内容は[https.request](https://nodejs.org/dist/latest-v4.x/docs/api/https.html#https_https_request_options_callback)で送るため、その形式で作ります。

```js:requestオプション
var opts = {
    host: 'trialbot-api.line.me',
    path: '/v1/events',
    headers: {
        "Content-type": "application/json; charset=UTF-8",
        "X-Line-ChannelID": "【LINE_CHANNEL_ID】",
        "X-Line-ChannelSecret": "【LINE_CHANNEL_SECRET】",
        "X-Line-Trusted-User-With-ACL": "【LINE_CHANNEL_MID】"
    },
    method: 'POST'
};
```
_header_部分はline-bot-apiの[エンドポイント](http://line.github.io/line-bot-api-doc/ja/api/events/post.html#id1)の「_-H_」のとおりになります。

次に、[https.request(options, callback)](https://nodejs.org/dist/latest-v4.x/docs/api/https.html#https_https_request_options_callback)に_opts_を与え、リクエストを作成します。

```js:https.request
    var req = https.request(opts, function(res){
        res.on('data', function (chunk) {
            console.log(res.statusCode + chunk.toString());
        });
        req.on('error', function(err) {
          console.log('ERROR: ' + err.message);
        });
    });
```
さらに、_callback_を引数として[responseイベント](https://nodejs.org/dist/latest-v4.x/docs/api/http.html#http_event_response)である_function(res){}_を設定します。

リクエストを作成したら、[https.request.write](http://nodejs.jp/nodejs.org_ja/api/http.html#http_request_write_chunk_encoding)で作成したリクエストを送信します。

```js:https.request.write
req.write(data);
```



送信が完了したら最後は[https.request.end](http://nodejs.jp/nodejs.org_ja/api/http.html#http_request_end_data_encoding)でリクエストの送信を終了します。

```js:https.request.end
req.end();
```

以上が今回利用したcode処理についてです。


# おわりに
「とにかく動かす！」とは言ったけれども、やっぱ作ったからには相手のことを知らねばなりませんね。というか知りたくなりますね！アモーレとはそういう存在ですね！ということでの解説編なわけです。
とはいえ、グラッツェ・アモーレkoooheiは実のところシェルスクリプトしか組んだことのない、プログラミング初心者なんですね。
とはいえいい加減なことはなかなか書けません！
なので一応、[ドットインストール](http://dotinstall.com/lessons/basic_nodejs/)で学習し、[Node.js v4.4.7 Documentation](https://nodejs.org/dist/latest-v4.x/docs/api/)や[Node.js v0.11.11 マニュアル & ドキュメンテーション](http://nodejs.jp/nodejs.org_ja/api/)などを読みまくりました！
なのでおかしな点がちらほろあるかも。。。ほら！
ということで暖かい目で見ていただければ幸いですm(__)m


### 関連
[Line botをAWS LambdaとAPI Gatewayでアモーレ！！- 実装編](http://qiita.com/kooohei/items/650c331f95f83072f4d6)
[Line botをAWS LambdaとAPI Gatewayでアモーレ！！- code解説編](http://qiita.com/kooohei/items/daf864f2b56d95311030)
[Line botをAWS LambdaとAPI Gatewayでアモーレ！！- システム解説編](http://qiita.com/kooohei/items/a98669f54451143591c2)