KJのぶろぐ

チャットボット・Javascript・哲学

Facebook Messenger BOTをNode.js + Expressで作ってみた

Facebook Messenger botをNode.js + Expressで作る記事があまりなくて、Githubの英語チュートリアルをみたりしてました。とはいえきっと苦労している人もいるはず。

ということで、Facebook MessengerチャットボットをNode.js + Expressで作ったので、チュートリアルとしてメモ。

Bot開発で参考になるリンク

Facebookの公式ドキュメント(これをみてスラスラできる人はそもそもこの記事を読む必要がない)
スタートガイド - Messengerプラットフォーム - ドキュメンテーション - 開発者向けFacebook

Githubにいたとても参考になるチュートリアル(これの日本語verを書きたい)
GitHub - jw84/messenger-bot-tutorial: Facebook Messenger bot 15 minute tutorial

Node.jsの公式サイト
Node.js

そもそもNode.jsって?
Node.js を5分で大雑把に理解する - Qiita

そもそもExpressって?
ゼロからはじめるExpress + Node.jsを使ったアプリ開発 - Qiita

その他良い情報は更新するかもしれません

おすすめ本

前提条件

まず前提として、Node.jsとExpressがなければ意味がないので、コマンドラインからインストールしてくださいね。

Node.jsとnpmをインストールする
Macにnode.jsをインストールする手順。 - Qiita

Expressをインストール(Node.jsやnpmのあとです。)
Express のインストール

Expressに関してはいろんな記事をみてインストールしてみてください。1つの記事に頼りすぎるのも良くないです。(経験上)

正直初心者の方(僕も実は初心者)もNode.jsとかnpmとか理解していなくても、チャットボット作れるので心配ないです。

あ、これからボットを作ろうとしている方々なのでいないとは思いますが、Facebookのアカウントは必須ですよ(もち)

大まかな手順

  • FacebookAppを作成
  • サーバーを構築(コピペ)
  • Botを作るです
  • herokuでデプロイ

多少、gitなどの知識も必要ですが、add、commit、pushぐらいしか使わないの問題ないです。

www.backlog.jp

⇡ここらへん読んどこう。

最後の準備はherokuのアカウントを作るです。

www.heroku.com

英語だけど、あまりいじらないので怖がらなくていいです。

サーバー構築

Node.jsもExpressもherokuアカウントの準備もできたら、本題です。

まずはターミナルで新しいディレクトリを作成

①ますは新規ディレクトリを作成(あえてターミナルで作成)

mkdir bot

botというディレクトリを作成しました。

botに移動。

cd bot

②Nodeプロジェクトを作ります。

npm init

次にこちら。

npm install express request body-parser --save

③エディタでindex.jsファイルを作成
以下のコードをコピペしてください。

'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()

app.set('port', (process.env.PORT || 5000))

// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// Process application/json
app.use(bodyParser.json())

// Index route
app.get('/', function (req, res) {
    res.send('Hello world, I am a chat bot')
})

// for Facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token')
})

// Spin up the server
app.listen(app.get('port'), function() {
    console.log('running on port', app.get('port'))
})

④「Procfile」というファイルを作成 この中に以下を。

web: node index.js

gitでいろいろ and herokuにpush

git init
git add .
git commit -m "なんでもいいよ"
heroku create [ここにappの名前を入れます]
git push heroku master

ここまでやればサーバーの構築一段落。

FacebookApp作成

この手順に関してはスクショとかめんどくさいので、省きますが簡単です。

とりあえずFacebookページ、Appを作ります。 developers.facebook.com

f:id:kawakensan:20170720222504p:plain

次はMessengerをクリック。

f:id:kawakensan:20170720222544p:plain

ページアクセストークンをメモしておいてください。 f:id:kawakensan:20170724213142p:plain

次にherokuにいき、verifyトークンを指定します。場所はここから。
ちなみに“keyがメモしたアクセストークン”“valueは適当に自分で指定”してください。 f:id:kawakensan:20170724213859p:plain

最後にここを埋めるだけ。

f:id:kawakensan:20170724214037p:plain

しめにターミナルでこのコマンドを打ってください。

curl -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<FBページのPAGE_ACCESS_TOKEN>"

すべてのコード

あとは以下のコードをindex.jsにペッとすると動きます。

  • オウム返し
  • Genericと入力するとカルーセルで返信

こんな実装をしています。 このあとは自分の作りたいようにチャットボットを作っていきます。

'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()

app.set('port', (process.env.PORT || 5000))

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// parse application/json
app.use(bodyParser.json())

// index
app.get('/', function (req, res) {
    res.send('hello world i am a secret bot')
})

// for facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'my_voice_is_my_password_verify_me') {
        res.send(req.query['hub.challenge'])
    } else {
        res.send('Error, wrong token')
    }
})

// to post data
app.post('/webhook/', function (req, res) {
    let messaging_events = req.body.entry[0].messaging
    for (let i = 0; i < messaging_events.length; i++) {
        let event = req.body.entry[0].messaging[i]
        let sender = event.sender.id
        if (event.message && event.message.text) {
            let text = event.message.text
            if (text === 'Generic'){ 
                console.log("welcome to chatbot")
                sendGenericMessage(sender)
                continue
            }
            sendTextMessage(sender, "Text received, echo: " + text.substring(0, 200))
        }
        if (event.postback) {
            let text = JSON.stringify(event.postback)
            sendTextMessage(sender, "Postback received: "+text.substring(0, 200), token)
            continue
        }
    }
    res.sendStatus(200)
})


// recommended to inject access tokens as environmental variables, e.g.
// const token = process.env.FB_PAGE_ACCESS_TOKEN
const token = "<FB_PAGE_ACCESS_TOKEN>"

function sendTextMessage(sender, text) {
    let messageData = { text:text }
    
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token:token},
        method: 'POST',
        json: {
            recipient: {id:sender},
            message: messageData,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        }
    })
}

function sendGenericMessage(sender) {
    let messageData = {
        "attachment": {
            "type": "template",
            "payload": {
                "template_type": "generic",
                "elements": [{
                    "title": "First card",
                    "subtitle": "Element #1 of an hscroll",
                    "image_url": "http://messengerdemo.parseapp.com/img/rift.png",
                    "buttons": [{
                        "type": "web_url",
                        "url": "https://www.messenger.com",
                        "title": "web url"
                    }, {
                        "type": "postback",
                        "title": "Postback",
                        "payload": "Payload for first element in a generic bubble",
                    }],
                }, {
                    "title": "Second card",
                    "subtitle": "Element #2 of an hscroll",
                    "image_url": "http://messengerdemo.parseapp.com/img/gearvr.png",
                    "buttons": [{
                        "type": "postback",
                        "title": "Postback",
                        "payload": "Payload for second element in a generic bubble",
                    }],
                }]
            }
        }
    }
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token:token},
        method: 'POST',
        json: {
            recipient: {id:sender},
            message: messageData,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        }
    })
}

// spin spin sugar
app.listen(app.get('port'), function() {
    console.log('running on port', app.get('port'))
})

ちなみにチャットボットに関する書籍少ないと思ったのですが、海外にありました! 英語に免疫がある方はどうぞ!僕は購入しました!

Messengerbotの情報少なすぎ!

とりあえずGithubのおかげでかろうじて基礎的なボットを開発することができました。

情報が少ないので、良い記事やサイトなどあればぜひ教えてください。

ほんの一部ですが、以下は僕が追跡している情報源です。

twitter.com

chatbotsmagazine.com

では、チュートリアルの中でおかしなところがあればコメントなどしていただければ修正させていただきますので、お気軽に!