fossasia/susi_fbbot

View on GitHub
index.js

Summary

Maintainability
A
0 mins
Test Coverage
'use strict';
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var http = require("http");

var app = express();
app.set('port', (process.env.PORT || 8080));

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

app.use(bodyParser.json());

// recommended to inject access tokens as environmental variables, e.g.
var token = process.env.FB_PAGE_ACCESS_TOKEN;

var buttons;
var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Share';
var message = '';
// Wait until done and reply
request({
    url: queryUrl,
    json: true
}, function (error, response, body) {
    if (!error && response.statusCode === 200) {
        message = body.answers[0].actions[0].expression;
        buttons = [
                      {
                        "type":"element_share",
                          "share_contents": { 
                          "attachment": {
                            "type": "template",
                            "payload": {
                              "template_type": "generic",
                              "elements": [
                                {
                                  "title": message,
                                  "buttons": [
                                    {
                                      "type": "web_url",
                                      "url": "https://m.me/asksusiai", 
                                      "title": "Chat with SUSI AI"
                                    }
                                  ]
                                }
                              ]
                            }
                          }
                        }
                      } 
                  ];

    }
    else{
        message = 'Oops, Looks like Susi is taking a break, She will be back soon';
    }
});

function messengerCodeGenerator(){
    request({
            url: 'https://graph.facebook.com/v2.6/me/messenger_codes',
            qs: {access_token:token},
            method: 'POST',
            json: {
                    type: "standard",
                    image_size: 1000
            }
        }, function(error, response, body) {
            if (error) {
                console.log('Error sending messages: ', error);
            } else if (response.body.error) {
                console.log('Error: ', response.body.error);
            }
            else{
                console.log('Messenger code - '+response.body);
            }
        });
}

function sendTextMessage(sender, text, flag) {
    var messageData;
    if(flag === 1){
        messageData = { attachment: text };
    }
    else{
        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);
        }
        typingIndicator(sender,0);
    });
}

function sendGenericMessage(sender, message, url, buttonTitle){
    var messageT = {
                    "type": "template",
                    "payload": 
                    {
                        "template_type": "generic",
                        "elements": [
                                        {
                                            "title": message,
                                            "buttons": [
                                                        {
                                                          "type": "web_url",
                                                          "url": url, 
                                                          "title": buttonTitle
                                                        }
                                                      ]
                                        }
                        ]
                    }
                };
    sendTextMessage(sender, messageT, 1);
}

// Add a get started button to the messenger
function addGetStartedButton(){
    request({
        url: 'https://graph.facebook.com/v2.6/me/messenger_profile',
        qs: {access_token:token},
        method: 'POST',
        json: { 
          "get_started":{
            "payload":"GET_STARTED_PAYLOAD"
          }
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        }
    })
}

function typingIndicator(sender, flag){
    var typingState;
    if(flag === 1)
    {
        typingState = {
          "recipient":{
              "id":sender
          },
          "sender_action":"typing_on"
        };
    }
    else{
        typingState = {
          "recipient":{
              "id":sender
          },
          "sender_action":"typing_off"
        };
    }
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token:token},
        method: 'POST',
        json: typingState
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        }
    });
}


function requestReply(sender, text){
    // Construct the query for susi
    var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+encodeURI(text);
    var message = '';
    // Wait until done and reply
    request({
        url: queryUrl,
        json: true
    }, function (error, response, body) {
        if (!error && response.statusCode === 200) {
            if(body.answers[0])
            {
                if(body.answers[0].actions[1]){
                    if(body.answers[0].actions[1].type === 'rss'){
                        sendTextMessage(sender, "I found this on the web:", 0);
                        var arr = [];
                        var metaCnt = body.answers[0].metadata.count;
                        for(var i=0;i<((metaCnt>10)?10:metaCnt);i++){
                            arr.push(
                                {
                                    "title": body.answers[0].data[i].title,
                                    "subtitle": body.answers[0].data[i].link,
                                    "buttons": buttons
                                }
                            );
                        }
                        message = {
                            "type": "template",
                            "payload": 
                            {
                                "template_type": "generic",
                                "elements": arr
                            }
                        };
                    }
                    else if(body.answers[0].actions[2].type === 'map'){
                        var mapMessage = body.answers[0].actions[0].expression;
                        var lat = body.answers[0].actions[2].latitude, lon = body.answers[0].actions[2].longitude;
                        console.log(lat +" "+ lon + " "+ mapMessage);
                        message = {
                          "type":"template",
                          "payload":{
                            "template_type":"generic",
                            "elements":[{
                                    "title": mapMessage,
                                    "image_url": "https://open.mapquestapi.com/staticmap/v4/getmap?key=0OlPA2eN9Bx9AyCLx15G5KbogcMJgRfM&size=600,400&zoom=13&center="+lat+","+lon,
                                    "item_url": body.answers[0].actions[1].link
                                }
                            ]
                          }
                        };
                    }
                }
                else{
                    if(body.answers[0].actions[0].type === 'table'){
                        var colNames = body.answers[0].actions[0].columns;
                        if((body.answers[0].metadata.count)>10)
                            sendTextMessage(sender, "Due to message limit, only some results are shown:", 0);
                        else
                            sendTextMessage(sender, "Results are shown below:", 0);
                        var metaCnt = body.answers[0].metadata.count;
                        var arr = [];
                        for(var i=0;i<((metaCnt>10)?10:metaCnt);i++){
                            var titleStr = '';
                            var subtitleStr = '';
                            for(var cN in colNames){
                                if(titleStr !== '')
                                    break;
                                titleStr = subtitleStr;
                                subtitleStr = body.answers[0].data[i][cN];     
                            }
                            arr.push(
                                {
                                    "title": subtitleStr,
                                    "subtitle": titleStr,
                                    "buttons": buttons             
                                }
                            );
                        }
                        message = {
                            "type": "template",
                            "payload": 
                            {
                                "template_type": "generic",
                                "elements": arr
                            }
                        };
                    }
                }
                else{
                    var messageTitle = body.answers[0].actions[0].expression;
                    message = {
                        "type": "template",
                        "payload": 
                        {
                            "template_type": "generic",
                            "elements": [
                                            {
                                                "title": messageTitle,
                                                "buttons": buttons
                                            }
                            ]
                        }
                    };
                }
                sendTextMessage(sender, message, 1);
            }
        } else {
            message = 'Oops, Looks like Susi is taking a break, She will be back soon';
            sendTextMessage(sender, message,0);
        }
    });
}

function persistentMenuGenerator(){
    request({
        url: 'https://graph.facebook.com/v2.6/me/messenger_profile',
        qs: {access_token:token},
        method: 'POST',
        json: {
                  "persistent_menu":[
                    {
                      "locale":"default",
                      "composer_input_disabled":false,
                      "call_to_actions":[
                        {
                          "type":"postback",
                          "title":"Latest News",
                          "payload":"news"
                        },{
                          "type":"web_url",
                          "title":"Visit Repository",
                          "url":"https://github.com/fossasia/susi_server",
                          "webview_height_ratio":"full"
                        }
                      ]
                    }
                  ]
                }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        } else {
            console.log(JSON.stringify(response.body));
        }
    })    
}

function deletePersistentMenu(){
    request({
        url: 'https://graph.facebook.com/v2.6/me/messenger_profile',
        qs: {access_token:token},
        method: 'DELETE',
        json: {
          "fields":[
            "persistent_menu"
          ]
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending messages: ', error)
        } else if (response.body.error) {
            console.log('Error: ', response.body.error)
        } else {
            console.log(JSON.stringify(response.body));
        }
    })
}

deletePersistentMenu();
persistentMenuGenerator();

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

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

addGetStartedButton();
messengerCodeGenerator();

// to post data
app.post('/webhook/', function (req, res) {
    var messaging_events = req.body.entry[0].messaging;
    typingIndicator(req.body.entry[0].messaging[0].sender.id,1);
    for (var i = 0; i < messaging_events.length; i++) {
        var event = req.body.entry[0].messaging[i];
        console.log(JSON.stringify(event)+'\n');
        var sender = event.sender.id;
        if (event.message && event.message.text) {
            var text = event.message.text;
            if (text === 'image') {
                // Sample testing URL
                sendGenericMessage(sender, 'Map Location', 'This is the location', 'http://loklak.org/vis/map.png?mlat=17.77262&mlon=78.2728192&zoom=12');
                // Images are sent similar to this.
                // Implement actual logic later here.
                continue
            }

            requestReply(sender, text);
        }
        else if (event.postback) {
            var errMessage = 'Oops, Looks like Susi is taking a break, She will be back soon';
            if(event.postback.payload === 'start_chatting'){
                var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Start+chatting';
                var startMessage = '';
                // Wait until done and reply
                request({
                    url: queryUrl,
                    json: true
                }, function (error, response, body) {
                    if (!error && response.statusCode === 200) {
                        startMessage = body.answers[0].actions[0].expression;
                    }
                    else{
                        startMessage = errMessage;
                    }
                      sendTextMessage(sender, startMessage, 0);

                      var messageT = {
                        "type": "template",
                        "payload": 
                        {
                            "template_type": "generic",
                            "elements": [
                                            {
                                                "title": 'You can try the following:',
                                                "buttons": [
                                                                {
                                                                  "type":"postback",
                                                                  "title":"What is FOSSASIA?",
                                                                  "payload":"What is FOSSASIA?"
                                                                },{
                                                                  "type":"postback",
                                                                  "title":"Who is Einstein?",
                                                                  "payload":"Who is Einstein?"
                                                                },{
                                                                  "type":"postback",
                                                                  "title":"Borders with INDIA",
                                                                  "payload":"Borders with INDIA"
                                                                }
                                                            ]
                                            }
                            ]
                        }
                    };
                    sendTextMessage(sender, messageT, 1);
                });
            }
            else if(event.postback.payload === "start_contributing"){
                var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Contribution';
                var contributeMessage = '';

                // Wait until done and reply
                request({
                    url: queryUrl,
                    json: true
                }, function (error, response, body) {
                    if (!error && response.statusCode === 200) {
                        contributeMessage = body.answers[0].actions[0].expression;
                    }
                    else{
                        contributeMessage = errMessage;
                    }
                    var url = "https://github.com/fossasia/susi_server";
                    var buttonTitle = "Visit repository";
                    sendGenericMessage(sender, contributeMessage, url, buttonTitle);

                    var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Gitter+channel';
                    var gitterMessage = '';
                    // Wait until done and reply
                    request({
                        url: queryUrl,
                        json: true
                    }, function (error, response, body) {
                        if (!error && response.statusCode === 200) {
                            gitterMessage = body.answers[0].actions[0].expression;
                        }
                        else{
                            gitterMessage = errMessage;
                        }
                        url = "https://gitter.im/fossasia/susi_server";
                        buttonTitle = "Chat on Gitter"
                        sendGenericMessage(sender, gitterMessage, url, buttonTitle);
                    });
                });
            }
            else if(event.postback.payload === 'GET_STARTED_PAYLOAD'){
                var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Welcome';
                var welMessage = '';
                // Wait until done and reply
                request({
                    url: queryUrl,
                    json: true
                }, function (error, response, body) {
                    if (!error && response.statusCode === 200) {
                        welMessage = body.answers[0].actions[0].expression;
                    }
                    else{
                        welMessage = errMessage;
                    }

                    var queryUrl = 'http://api.susi.ai/susi/chat.json?q='+'Get+started';
                    var introMessage = '';
                    // Wait until done and reply
                    request({
                        url: queryUrl,
                        json: true
                    }, function (error, response, body) {
                        if (!error && response.statusCode === 200) {
                            introMessage = body.answers[0].actions[0].expression;
                        }
                        else{
                            introMessage = errMessage;
                        }
                        var messageData = {
                          "type":"template",
                          "payload":{
                            "template_type":"generic",
                            "elements":[
                               {
                                "title":welMessage,
                                "subtitle":introMessage,
                                "buttons":[
                                  {
                                    "type":"web_url",
                                    "url":"https://github.com/fossasia/susi_server",
                                    "title":"View Repository"
                                  },{
                                    "type":"postback",
                                    "title":"Start Chatting",
                                    "payload":"start_chatting"
                                  },{
                                    "type":"postback",
                                    "title":"How to contribute?",
                                    "payload":"start_contributing"
                                  }                 
                                ]      
                              }
                            ]
                          }
                        }
                          sendTextMessage(sender, messageData, 1);
                    });
                });
            }
            else{
                requestReply(sender, event.postback.payload);
            }
            continue;
        }
        else{
            typingIndicator(sender,0);    
        }
    }
    res.sendStatus(200)
})

// Getting Susi up and running.
app.listen(app.get('port'), function() {
    console.log('running on port', app.get('port'));
});