AWS API GatewayとAWS LambdaとWit.aiで自動応答 Facebook Botを作成する


# 事前準備

Node.jsで、Wit.aiをテストする
http://qiita.com/akira-sasaki/items/72ab3d405a6f64942720

AWS API GatewayとAWS Lambdaで、HelloWorldを作成する
http://qiita.com/akira-sasaki/items/b9e8e8a0330818e3b71d

AWS API GatewayとAWS Lambdaで、Facebook Botを作成する
http://qiita.com/akira-sasaki/items/961cb7a1aa7386764863

Facebook Bot向けアプリをAWS Lambdaで実装する
http://qiita.com/akira-sasaki/items/cbb667653579db9743ec

# Scriptの作成

```js:index.js
'use strict';

var http = require ('https');
const Wit = require('node-wit').Wit;

var accessToken = "FacebookBot用のアクセストークン";
var clientTokenWIT = "Wit.ai用のクライアントトークン";
var sendingCount = 0;
var myContext;


exports.handler = function(event, context) {
    console.log('Received event:', JSON.stringify(event, null, 2));
    myContext = context;

    // Wit.aiのAction
    const actions = {
      say(sessionId, context, message, cb) {
        console.log(message);
        cb();
        sendMessage(sender, {text: message});
      },
      merge(sessionId, context, entities, message, cb) {
        cb(context);
      },
      error(sessionId, context, err) {
        console.log(err.message);
      },
    };

    // Wit.aiのインスタンス
    const client = new Wit(clientTokenWIT, actions);

    // パラメータチェック
    var entry = event.entry;
    if (!entry || entry.length === 0) {
        context.fail("invalid parameter");
        return;
    }

    // 各メッセージの処理
    for (var i = 0; i < entry.length; i++) {
        var messaging_events = entry[i].messaging;
        var timestamp = entry[i].time;
        for (var j = 0; j < messaging_events.length; j++) {
            var messaging = entry[i].messaging[j];
            var sender = messaging.sender.id;
            // メッセージ
            if (messaging.message && messaging.message.text) {
                var text = messaging.message.text;

                // 取得したメッセージをWit.aiに渡す
                var sessionContext = {};
                client.runActions(
                    "lamdba_test001", // the user's current session
                    text, // the user's message 
                    sessionContext, // the user's current session state
                    (error, context) => {
                    if (error) {
                        console.log('Oops! Got an error from Wit:', error);
                    } else {
                        console.log('Waiting for futher messages.');
                    }
                });

            }
        }
    }
    // context.done();
};

// メッセージ送信
function sendMessage(sender, messageData) {
    var json_data = {
        recipient: {id: sender},
        message: messageData
    };
    var post_data = JSON.stringify(json_data);
    console.log("* sendMessage *" + post_data);

    var post_options = {
        host: 'graph.facebook.com',
        port: '443',
        path: '/v2.6/me/messages?access_token='+accessToken,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': Buffer.byteLength(post_data)
        }
    };

    var post_req = http.request(post_options, function(res) {
        res.setEncoding('utf8');
        // res.on('data', function (chunk) {
        //     console.log('Response: ' + chunk);
        // });
        res.on('end', function () {
            // console.log('End');
            sendingCount -= 1;
            if (sendingCount === 0) {
                myContext.done();
            }
        });
    });

    post_req.on('error', function (e) {
        console.error('HTTP error: ' + e.message);
        sendingCount -= 1;
        if (sendingCount === 0) {
            myContext.done();
        }
    });

    // post the data
    post_req.write(post_data);
    post_req.end();
}
```

# アップロードファイルの作成

- index.js
- node_modules/node-wit/

というフォルダ構成になっているので

> $ zip -r lamdba.zip index.js node_modules/

を実行して、ZIP形式でパッケージにまとめる。

# アップロード

lamdba.zipをアップロードする。

![lam001.png](https://qiita-image-store.s3.amazonaws.com/0/63450/77c2f2cd-4561-77ba-367c-d89bd70ce7fd.png)

![lam002.png](https://qiita-image-store.s3.amazonaws.com/0/63450/191a9cce-5739-5cf4-c125-027c3155f14c.png)

![lam003.png](https://qiita-image-store.s3.amazonaws.com/0/63450/0b862aba-6105-d481-5b71-a9ae9a4fd95c.png)


> It looks like your Lambda function "FacebookBotCallback" is unable to be edited inline, so you need to re-upload any changes. This may be because your file is too large or your zip file contains more than one file to edit. However, you can still invoke your function right now.

というメッセージが表示されますが、問題なくアップロードされているはずです。

# TEST

![test001.png](https://qiita-image-store.s3.amazonaws.com/0/63450/97b5cdd4-529a-545b-26d0-8ac6f4837e07.png)

テスト用のJSONを作成する。messaging.sender.idは、実在するIDにすれば、メッセージがそのIDに返信される。messaging.textは、Wit.aiで設定している「こんにちわ」にする。

```json:Test用
{
  "object":"page",
  "entry":[
    {
      "id":1,
      "time":1457764198246,
      "messaging":[
        {
          "sender":{
            "id":111111111111
          },
          "recipient":{
            "id":1
          },
          "timestamp":1457764197627,
          "message":{
            "mid":"mid.1457764197618:41d102a3e1ae206a38",
            "seq":73,
            "text":"こんにちわ"
          }
        }
      ]
    }
  ]
}
```

![test002.png](https://qiita-image-store.s3.amazonaws.com/0/63450/be9de564-1ae1-80d1-9fa3-49e144730a3d.png)

Timeoutの時間を10秒にしておく。

![test003.png](https://qiita-image-store.s3.amazonaws.com/0/63450/81c409ea-9b54-8918-1325-db921e7dd73a.png)

Logで「こんにちわ!!」が返ってくれば、Wit.aiの結果が正常に取れたことになる。

![test004.png](https://qiita-image-store.s3.amazonaws.com/0/63450/643d5606-a95d-5250-819a-fc55aba4e847.png)

# Facebookで実行

実行するとこんな感じ。

![fbook001.png](https://qiita-image-store.s3.amazonaws.com/0/63450/4e704f7a-6d39-6708-a2f6-7d5456b77b45.png)