Skip to content

KorChris/facebook_chatbot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

15 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๋‚˜๋งŒ์˜ ํŽ˜์ด์Šค๋ถ ๋ฉ”์‹ ์ € ๋ด‡ ๋งŒ๋“ค๊ธฐ

์ด ๊ธ€์€ Nodejs, Heroku server๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž์‹ ๋งŒ์˜ ํŽ˜์ด์Šค๋ถ ์ฑ—๋ด‡์„ ๋งŒ๋“ค์–ด๋ณด๋Š” ํ…œํ”Œ๋ฆฟ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์ดํ›„์— Api.ai๋ฅผ ์ด์šฉํ•˜์—ฌ ๋” ๋˜‘๋˜‘ํ•œ ์ฑ—๋ด‡์„ ๋งŒ๋“œ๋Š” ๊ณผ์ •์„ ํฌ์ŠคํŒ…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฑ—๋ด‡์ด๋ž€?

์ฑ—๋ด‡์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณ„๋„๋กœ ์›น์‚ฌ์ดํŠธ๋‚˜ ์•ฑ์„ ๋”ฐ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ ๋Œ€ํ™”ํ•˜๋“ฏ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค๋‹ค. ๊ธฐ์กด ์‚ฌ์šฉ์ž ์ž์‹ ์ด ์“ฐ๋Š” ๋ฉ”์‹ ์ €๋ฅผ ํ†ตํ•ด ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ํ˜„์žฌ ๊ตฌ๊ธ€, ํŽ˜์ด์Šค๋ถ, ๋งˆ์ดํฌ๋กœ์†Œํ”„ํŠธ, ํ…”๋ ˆ๊ทธ๋žจ์„ ๋น„๋กฏํ•ด ๊ตญ๋‚ด ๋„ค์ด๋ฒ„, ๋‹ค์Œ ๋“ฑ IT ๋ถ„์•ผ ๊ธฐ์—…๋“ค์ด ์ฑ—๋ด‡์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ๋ฉ”์‹ ์ € ํ”Œ๋žซํผ์„ ์„ ๋ณด์ด๋Š” ์ค‘์ด๋‹ค.

[๋„ค์ด๋ฒ„ ์ง€์‹๋ฐฑ๊ณผ] ์ฑ„ํŒ…๋ด‡, ์ฑ—๋ด‡ - ๋ฉ”์‹ ์ € ์„œ๋น„์Šค ์ธ๊ณต์ง€๋Šฅ(AI)๊ณผ ๋งŒ๋‚˜๋‹ค (์šฉ์–ด๋กœ ๋ณด๋Š” IT)

์ค€๋น„์‹œ์ž‘

  1. Javascript์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ง€์‹(๋ฌธ๋ฒ•)
  2. Nodejs
    • Nodejs์—์„œ ๋‹ค์šด๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. LTS ๋ฒ„์ „์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.
  3. Git
  4. Heroku
    • heroku ์— ๊ฐ€์ž…ํ•ฉ๋‹ˆ๋‹ค.
  5. Facebook Account
    • Facebook account๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Nodejs๋กœ ํ”„๋กœ์ ํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

Nodejs์„ค์น˜ํ•œ ํ›„์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์„ค์น˜๋Š” ์ƒํ™œ์ฝ”๋”ฉ Nodejs ์„ค์น˜ ๊ฐ•์˜๋ฅผ ๋ณด์‹œ๋ฉด ์ˆ˜์›”ํ•˜๊ฒŒ ์ง„ํ–‰ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค์น˜๋ฅผ ์™„๋ฃŒํ•˜์‹  ํ›„, ์›ํ•˜๋Š” ํด๋”/๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด๋กœ ๊ธฐ๋ณธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ €๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” dev๋ผ๋Š” ํด๋”๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ํ›„(mkdir dev)์—, dev๋กœ ๋“ค์–ด๊ฐ€์„œ(cd dev) ํ”„๋กœ์ ํŠธํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

mkdir dev
cd dev
sudo npm install npm -g
npm init
npm install express request body-parser --save

npm init๋ฅผ ์‹คํ–‰ํ•˜์‹œ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฌผ์–ด๋ณผํ…๋ฐ entry point๋งŒ app.js๋กœ ์„ค์ •ํ•ด์ฃผ์‹  ํ›„ ๋‚˜๋จธ์ง€๋Š” ์ž์œ ๋กญ๊ฒŒ ์„ค์ •ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

package name: (dev)
version: (1.0.0)
description:
entry point: (index.js) app.js
test command: 
git repository:
keywords:
author:
license: (ISC)

์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜์˜ค๋ฉด ์„ฑ๊ณต์ž…๋‹ˆ๋‹ค. version์€ ๋‹ค๋ฅด์…”๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

ํŽ˜์ด์Šค๋ถ ์•ฑ ์„ธํŒ…ํ•˜๊ธฐ

  1. Facebook Page
    • Chat bot์„ ์ ์šฉ์‹œํ‚ฌ Facebook Page๋ฅผ ๋งŒ๋“œ์‹  ํ›„์— Facebook Developer Page์— ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

facebook page ๋งŒ๋“ค๊ธฐ ํŽ˜์ด์Šค๋ถ ๊ฐœ๋ฐœ์ž ํŽ˜์ด์ง€

  1. Facebook App
  • Add a new App์„ ๋ˆ„๋ฅด์‹œ๊ณ  ์ƒˆ๋กœ์šด App์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

add_app

new_app

create_app

  • Messenger์—์„œ set up๋ฒ„ํŠผ์„ ๋ˆ„๋ฆ…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๊ฐ€์ง€ ํ”Œ๋žซํผ์ค‘์— ์ฑ—๋ด‡์„ ์œ„ํ•œ messenger๋ฅผ ์„ ํƒ

app.js ํŒŒ์ผ ์ž‘์„ฑ

์ด์ œ Heroku ์„œ๋ฒ„์— ๋ฐฐํฌ์‹œํ‚ฌ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. app.js๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ฒ˜์Œ nodejs๋ฅผ ํ†ตํ•ด npm install์„ ์ง„ํ–‰ํ–ˆ๋˜ ํด๋”(์ด ๊ธ€์˜ ๊ฒฝ์šฐ, devํด๋”)์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

'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));

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/', function(req, res) {
    res.send('Hello world');
})

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

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

app.js๋ฅผ ์™„์„ฑํ•˜์…จ๋‹ค๋ฉด ํด๋” ์•ˆ์— ์žˆ๋Š” package.json์„ ์ˆ˜์ •ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ ๋‚ด์˜ main๊ณผ scripts ์•ˆ์— ์žˆ๋Š” ๋‚ด์šฉ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•ด์ค๋‹ˆ๋‹ค.

...
"main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
 ...

์ด์ œ ๋ฐฐํฌ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค. git์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“œ์‹œ๊ณ  heroku server๋ฅผ ๋งŒ๋“œ์‹  ํ›„์—, git push๋ฅผ ํ†ตํ•ด heroku์— ๋ฐฐํฌํ•ด์ค๋‹ˆ๋‹ค.

git init
git add .
git commit -m 'init'
heroku create
git push heroku master

์ €๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

KorChris$ heroku create
Creating app... done, โฌข YOUR_DYNO_NAME
https://YOUR_DYNO_NAME.herokuapp.com/ | https://git.heroku.com/YOUR_DYNO_NAME.git

KorChris$ git push heroku master
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 1018 bytes | 0 bytes/s, done.
...
...
...

remote: Verifying deploy... done.
To https://git.heroku.com/YOUR_DYNO_NAME.git
   199.........73c  master -> master

ํŽ˜์ด์Šค๋ถ App ์„ธํŒ…ํ•˜๊ธฐ

์ด์ œ Heroku server์™€ ํŽ˜์ด์Šค๋ถ App์„ ์—ฐ๊ฒฐ์‹œ์ผœ์ค๋‹ˆ๋‹ค. ํŽ˜์ด์Šค๋ถ ์•ฑ ๊ด€๋ฆฌ์ฐฝ์— ๊ฐ€์…”์„œ ์ „ ๋‹จ๊ณ„์™€ ๊ฐ™์ด Messenger ํƒญ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

Token Generation

  • Token Generation์—์„œ ์ž์‹ ์ด ๋งŒ๋“  page๋ฅผ ๊ณ ๋ฅด์‹œ๊ณ 

token_generation

token_ex

  • ์ƒ์„ฑ๋œ Token์„ Clickํ•ด์„œ ๋ณธ์ธ๋งŒ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋กํ•ด๋‘ก๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์ด token์„ ์ด์šฉํ•ด์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๊ทธ ํ›„์—๋Š” Webhook์„ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Webhook Setting

  • token generation ํ•˜๋‹จ์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด Webhook์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํƒญ์„ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Webhook Set up

์•„๋ž˜์™€ ๊ฐ™์ด heroku์—์„œ ์ƒ์„ฑ๋œ Dyno์˜ URL์„ ์ž…๋ ฅํ•˜๊ณ  ๋’ค์— /webhook์„ ๋„ฃ์–ด์ฃผ์‹œ๊ณ  VERIFY TOKEN์—๋Š” 'VERIFY_TOKEN'์„ ๋„ฃ์–ด์ค๋‹ˆ๋‹ค. set_webhook

Webhook set up์ด ๋๋‚ฌ๋‹ค๋ฉด token generation๋•Œ ์‚ฌ์šฉํ–ˆ๋˜ page๋ฅผ ๋‹ค์‹œ ์„ ํƒํ•ด์ฃผ์‹œ๊ณ , subscribe๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์ค๋‹ˆ๋‹ค. subscribe

๊ฐ„๋‹จํ•œ Echo bot ๋งŒ๋“ค๊ธฐ

app.js๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋ณด๋‚ธ text๋ฅผ ๊ทธ๋Œ€๋กœ ๋‹ค์‹œ ๋ณด๋‚ด๋Š” Echo Bot์„ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Token generation๋‹จ๊ณ„์—์„œ ๋ฐ›์€ token์„ PAGE_ACCESS_TOKEN์— ๋„ฃ์–ด์ฃผ๊ณ , app.js๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์ฝ”๋“œ ์„ค๋ช…์€ ๋‹ค์Œ ๊ธ€์—์„œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

'use strict'

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

//์ž‘์€ ๋”ฐ์˜ดํ‘œ ์‚ฌ์ด์— ๋ณธ์ธ์ด ๋ฐ›์œผ์‹  token์„ pasteํ•ฉ๋‹ˆ๋‹ค.
//๋‚˜์ค‘์— ๋ณด์•ˆ์„ ์œ„ํ•ด์„œ ๋”ฐ๋กœ setting์„ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.
//์ด ํ† ํฐ์ด ํฌํ•จ๋œ ํŒŒ์ผ์„ ์ ˆ๋Œ€ ์—…๋กœ๋“œํ•˜๊ฑฐ๋‚˜ github์— ์ ์šฉ์‹œํ‚ค์ง€ ๋งˆ์„ธ์š”.
var PAGE_ACCESS_TOKEN = 'YOUR TOKEN HERE';

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

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get('/', function(req, res) {
    res.send('Hello world');
})


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

app.post("/webhook", function(req, res) {
    console.log("WEBHOOK GET IT WORKS");
    var data = req.body;
    console.log(data);

    // Make sure this is a page subscription
    if (data.object == 'page') {
        // Iterate over each entry
        // There may be multiple if batched
        data.entry.forEach(function(pageEntry) {
            var pageID = pageEntry.id;
            var timeOfEvent = pageEntry.time;

            // Iterate over each messaging event
            pageEntry.messaging.forEach(function(messagingEvent) {
                if (messagingEvent.optin) {
                    receivedAuthentication(messagingEvent);
                } else if (messagingEvent.message) {
                    receivedMessage(messagingEvent);
                } else if (messagingEvent.postback) {
                    receivedPostback(messagingEvent);
                } else {
                    console.log("Webhook received unknown messagingEvent: ", messagingEvent);
                }
            });
        });

        res.sendStatus(200);
    }
});

function receivedMessage(event) {
    var senderId = event.sender.id;
    var content = event.message.text;
    var echo_message = "ECHO : " + content;
    sendTextMessage(senderId, echo_message);
}

function receivedPostback(event) {
    console.log("RECEIVED POSTBACK IT WORKS");
    var senderID = event.sender.id;
    var recipientID = event.recipient.id;
    var timeOfPostback = event.timestamp;

    var payload = event.postback.payload;

    console.log("Received postback for user %d and page %d with payload '%s' " +
        "at %d", senderID, recipientID, payload, timeOfPostback);

    sendTextMessage(senderID, "Postback called");
}

function sendTextMessage(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {
            recipient: { id: recipientId },
            message: { text: message }
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ' + response.error);
        }
    });
}

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

app.js๋ฅผ ๋ชจ๋‘ ์ž‘์„ฑํ•˜์…จ์œผ๋ฉด Git์„ ์ด์šฉํ•˜์—ฌ ์ˆ˜์ •๋œ ํŒŒ์ผ์„ ๋‹ค์‹œ ๋ฐฐํฌํ•ด์ค๋‹ˆ๋‹ค.

git add .
git commit -m 'echo bot'
git push heroku master

์ด์ œ Echo bot์ด ์™„์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํŽ˜์ด์Šค๋ถ์„ ํ†ตํ•ด์„œ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด๋ด…์‹œ๋‹ค.

echo bot

๋งˆ์น˜๋ฉฐ

๋‹ค์Œ ๊ธ€์—์„œ๋Š” ์ฝ”๋“œ ๋ถ„์„ ๋ฐ ๋” ๋งŽ์€ ํŽ˜์ด์Šค๋ถ ๋ฉ”์‹ ์ € ๊ธฐ๋Šฅ์„ ์ ์šฉํ•˜๋Š” ๋ฒ•์„ ๋‹ค๋ฃจ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ œ๊ฐ€ ๋‹ค๋ฃฌ ์ฝ”๋“œ๋Š” ์ œ Github์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

Ref :

  1. https://www.sitepoint.com/building-facebook-chat-bot-node-heroku
  2. https://github.com/fbsamples/messenger-platform-samples
  3. https://github.com/jw84/messenger-bot-tutorial

Releases

No releases published

Packages

No packages published