Deploying Susper On Heroku

In Susper, currently we have two branches, master and development branch. The master branch is deployed on susper.com and we needed a deployment of development branch. For this we are using heroku and in this blog I will describe how we have deployed Susper’s development branch on heroku at http://susper-dev.herokuapp.com Here are the steps: 1.Get a free heroku account: To deploy our apps on heroku we must have a heroku account which can be created for free on https://www.heroku.com. 2.Create a new app on heroku: After creating an account we need to create an app with a name and a region, for Susper we have used name susper-dev and region as United States. 3.Link the app to Susper’s development branch: After successfully creating the app we need to link our app to Susper’s development branch and in Deploy section and then we have to enable automatic deployment from development branch after CI passes. Setup the Susper Project: Now we have deployed our and we need to configure it so that it can successfully start on heroku. Following are the steps to configure Susper. a) Add node and npm engine in package.json: Now we need to tell heroku which npm and node version to use while running our app,this can be done by defining an engine field in package.json and adding npm and node versions as values as shown here: "engines": { "node": "8.2.1", "npm": "6.0.1" }   b) Adding a postinstall field under scripts field in package.json: Now we need to tell heroku the command that we will be using to build our app. Since on susper.com we are using ng build --prod --build-optimizer that builds our app for production by optimizing the build artifacts. Therefore on heroku also we will be using the same command: "postinstall": "ng build --prod --build-optimizer"   c) Defining dependencies and typescript version for our project:This can be done by defining the @angular/cli ,@angular/compiler-cli and typescript and their version under dependencies field in package.json. In Susper we are using the following dependency versions. "@angular/cli": "^1.1.0", "@angular/compiler": "4.1.3", "typescript": "~2.3.4"   d) Creating a javascript file to install express server and run our app: Locally when we run ng serve angular cli automatically creates a express server where our app is deployed locally but on heroku we will be required to start our express server which will be used by our app using a javascript file. Here is the code for starting the server. //Install the server const express = require('express'); const path = require('path'); const app = express(); // Serving the static file from dist folder app.use(express.static(__dirname + '/dist')); app.get('/*', function(request,response) { response.sendFile(path.join(__dirname+'/dist/index.html')); }); // Starting the app and listening on default heroku port. app.listen(process.env.PORT || 8080);   Now we need to run this file, for this we will change start command in package.json file under script to start this file. "start": "node server.js"   Now everytime a new commit is made to development branch our app will be automatically deployed on heroku at https://susper-dev.herokuapp.com Resources…

Continue ReadingDeploying Susper On Heroku

Showing “Get started” button in SUSI Viber bot

When we start a chat with SUSI.AI on Viber i.e. SUSI Viberbot, there should be an option on how to get started with the bot. The response to it are some options like “Visit repository”, “How to contribute” which direct the user to check how SUSI.AI bot is made and prompts him/her to contribute to it. Along with that an option of “start chatting” can be shown to add up some sample queries for the user to try. To accomplish the task at hand, we will accomplish these sub tasks: To show the “Get started” button. To show the reply to “Get started” query. To respond to the queries, nested in the response of “Get started” Showing “Get started”: The Viber developers platform notifies us when a user starts a conversation with our bot. To be exact, a conversation_started event is sent to our webhook and can be handled accordingly. The Viberbot shows a welcome message to the user along with a Get started button to help him/her start. To send just the welcome message: if (req.body.event === 'conversation_started') { // Welcome Message var options = { method: 'POST', url: 'https://chatapi.viber.com/pa/send_message', headers: headerBody, body: { // some required body properties here text: 'Welcome to SUSI.AI!, ' + req.body.user.name + '.', // code for showing the get started button here. } json: true }; request(options, function(error, res, body) { // handle error }); } The next step is to show the “Get started” button. To show that we use a keyboard tool, provided by Viber developers platform. So after the “text” key we have the “keyboard” key and a value for it: keyboard: { "Type": "keyboard", "DefaultHeight": true, "Buttons": [{ "ActionType": "reply", "ActionBody": "Get started", }] } The action type as shown in the code, can be “reply” or “open-url”. The “reply” action type, triggers an automatic query sent back with “Get started” (i.e. the value of "ActionBody" key), when that button gets clicked. Hence, this code helps us tackle our first sub task: Reply to “Get started”: We target to make each SUSI.AI bot generic. The SUSI FBbot and SUSI Tweetbot shows some options like “Visit repository”, “Start chatting” and “How to contribute?” for the “Get started” query. We render the same answer structure in Viberbot. The “rich_media” type helps us send buttons in our reply message. As we ought to use three buttons in our message, the button rows are three in the body object: if(message === "Get started"){ var options = { method: 'POST', url: 'https://chatapi.viber.com/pa/send_message', headers: headerBody, body: { // some body object properties here type: 'rich_media', rich_media: { Type: "rich_media", ButtonsGroupColumns: 6, ButtonsGroupRows: 3, BgColor: "#FFFFFF", Buttons: buttons } }, json: true }; request(options, function(error, res, body) { if (error) throw new Error(error); console.log(body); }); As said before, 2 type of Action types are available - “open-url” and “reply”. “Visit repository” button has an “open-url” action type and “How to contribute?” or “start chatting” has a “reply” action type. Example of “Visit repository” button: var buttons…

Continue ReadingShowing “Get started” button in SUSI Viber bot

Showing location response in SUSI.AI bots

SUSI.AI has a capability to tell the basic information about a location, it is asked for. Along with the basic information about that place, it shows a map (i.e. open street map) pointing to that location. The task at hand is to inculcate this “location” feature to the SUSI.AI messenger bots. The SUSI Tweetbot and SUSI Fbbot are used as examples in this blog. Let’s first check on what response do we get, when a person asks a query like “where is london” to the SUSI API. Along with the basic information about that location, the result as shown below has the type of reply (i.e. map), latitude, longitude and a link to the open street map. "actions": [ { "type": "answer", "language": "en", "expression": "Ludhiana is a city and a municipal corporation in Ludhiana district in the Indian state of Punjab, and is the largest city north of Delhi." }, { "type": "anchor", "link": "https://www.openstreetmap.org/#map=13/30.912040570244187/75.85379021980509", "text": "Here is a map", "language": "en" }, { "type": "map", "latitude": "30.912040570244187", "longitude": "75.85379021980509", "zoom": "13", "language": "en" } ] The response for a location type query has these 3 main parts: Clickable static map image. A basic information of the place asked about. The link i.e. when the static map image is clicked it should redirect to the corresponding map location. Let’s try to make up with the 1st part of the response i.e. Static map image. The map quest API is used to result in a static map image of the location. We need an API key to access the map quest API, which can be requested from their developer site. Along with that we need the latitude and longitude of the location at hand. The SUSI API’s response helps us to get the latitude value: // if body represents the response object var lat = body.answers[0].actions[2].latitude; And the longitude value: var lon = body.answers[0].actions[2].longitude; Using the three values that are API key, latitude and longitude, the static image is rendered by this link: var static_image_url = "https://open.mapquestapi.com/staticmap/v4/getmap?key=API_KEY&size=600,400&zoom=13&center="+lat+","+lon; The second part is, basic information about the place asked, can be fetched from: // if body is the JSON response object from SUSI API var mapMessage = body.answers[0].actions[0].expression; The link to the map location can be easily fetched from the SUSI API’s response: var link = body.answers[0].actions[1].link; As all the three parts are ready, let’s look on how to render them on the SUSI.AI bot’s screen. Facebook: Sending a generic template message object: message = { "type":"template", "payload":{ "template_type":"generic", "elements":[{ "title": mapMessage, "image_url": static_image_url, "Item_url": link }] } }; sendTextMessage(sender, message, 1); Twitter: The Twitter API does not need a static image of the map to be rendered. It does that work for us. We just need to send an event to the Twitter API with the message data object constituting of the map message, the latitude and longitude values: "message_data": { "text": mapMessage, "attachment": { "type": "location", "location": { "type": "shared_coordinate", "shared_coordinate": { "coordinates": { "type": "Point", "coordinates": [lon, lat] }…

Continue ReadingShowing location response in SUSI.AI bots

Making SUSI Alexa skill as an express app

Previously SUSI Alexa skill was deployed using AWS Lambda service (Refer to this blog). Each SUSI.AI Bot should be deployed on Google cloud using Kubernetes. To accomplish that, we need to remove the dependency of the SUSI Alexa skill from AWS Lambda service. We need to make it an express app, to be able to deploy it to Google cloud. Let’s start with on how to achieve it: SUSI Alexa skill: We require three files to make the skill as an express app. The main entry point for the skill would be server.js file, which will serve the incoming request using two helper files alexa.js and handlers.js. Server.js: This file acts as the main entry point for the incoming request. We handle two type of requests using it, that are: Launch request Intent request Launch request is triggered when a person utters “Alexa, open susi chat” , “Alexa, start susi chat”, “Alexa, launch susi chat” etc. This request is responded with an introductory phrase about SUSI.AI. To catch this request: if (type === "LaunchRequest") { var endpoint = "http://api.susi.ai/susi/chat.json?q="+"Welcome"; // ENDPOINT GOES HERE http.get(endpoint, (response1) => { var body = ""; response1.on("data", (chunk) => { body += chunk; }); response1.on("end", () => { var viewCount; viewCount = JSON.parse(body).answers[0].actions[0].expression; endpoint = "http://api.susi.ai/susi/chat.json?q="+"Get+started"; // ENDPOINT GOES HERE body = ""; http.get(endpoint, (response2) => { response2.on("data", (chunk) => { body += chunk; }); response2.on("end", () => { viewCount += JSON.parse(body);.answers[0].actions[0].expression; response.say(viewCount,false); }); }); }); }); } Intent request gets triggered, when any other phrase is uttered by the user except Launch related phrases. We check if the intent triggered has a corresponding handler to handle the request. If the handler is found in handlers.js file, we call it passing the required arguments to the handler function. Let’s see how handlers make this step possible. Handler.js: This file decides on what function to run when a particular type of intent is triggered. As we have just one intent for our SUSI Alexa skill i.e. callSusiApi, we have just one function in our handlers.js file. During its execution, the first step we do is extract the query value: let query = slots.query.value; Depending upon the query value, we run its corresponding code. For example, in case of a generic query (i.e. any query except stop, cancel and help): var endpoint = "http://api.susi.ai/susi/chat.json?q="+query; // ENDPOINT GOES HERE http.get(endpoint, (response1) => { var body = ""; response1.on("data", (chunk) => { body += chunk; }); response1.on("end", () => { var data = JSON.parse(body); if(data.answers[0].actions[1]){ // handle rss and table type results } else { viewCount = data.answers[0].actions[0].expression; } response.say(viewCount,true); }); }); At the end of the function we respond to the user with an answer to his/her query using: response.say(viewCount,true); Alexa.js: When we get a request from the user, we pass that request and response object to this file. This file helps us wrap the required request properties into an object and return that back to the server file, which was the entry point for the request. Now,…

Continue ReadingMaking SUSI Alexa skill as an express app

Showing sample queries in SUSI.AI Bots

We need to give the user a good start to their chat with SUSI.AI. Engaging the users with some good skills at the start of the conversation, can leave a good impression about SUSI.AI. In SUSI messenger bots, we show up with some sample queries to try, during the conversation with SUSI.AI. In this blog, SUSI_Tweetbot and SUSI_FBbot are used as examples. These queries are shown as quick replies i.e. the user can click on any of these sample queries and get an answer from SUSI.AI.   Facebook: When the user clicks on the “Start chatting” button, we send a descriptive message on what can the user ask to SUSI.AI . Code snippet used for this step is: 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); Just a text message is not much engaging. To further enhance the experience of the user, we show some quick reply options to the user. We have finalized some skills to show to the user: Due to the character limit for the text shown on buttons, we try to show short queries as shown in the above picture. This way the user gets an idea about what type of queries can be asked. Generic template, help us achieve this feature in SUSI_FBbot. The code snippet used: 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?" }] }] } }; sendTextMessage(sender, messageT, 1); As seen in the code above, each button has a corresponding postback text. So that whenever that button is clicked the postback text is sent to our chat automatically: This postback text acts as a query to SUSI API which fetches the response from the server and shows it back to the user. Twitter: As SUSI.AI bots must be generic among all the messenger platforms available , we will inculcate the same skills available in SUSI_FBbot to SUSI_Tweetbot. The quick reply feature provided by Twitter devs help us to accomplish this task at hand. As in SUSI_FBbot a descriptive message is shown to the users first and then some quick reply options following it. Message_create event helps in adding quick replies: var msg = { "event": { "type": "message_create", "message_create": { "target": { "recipient_id": senderId }, "message_data": { "text": "You can try the following:", "quick_reply": { "type": "options", "options": [{ "label": "What is FOSSASIA?", "metadata": "external_id_4" }] } } } } }; T.post('direct_messages/events/new', msg, sent); One thing to keep in mind while coding is to send the quick reply message after the initial descriptive message i.e. the code used to send quick replies should be written inside the function, which sends the descriptive message first and aafter that step is complete it runs the code for quick replies.…

Continue ReadingShowing sample queries in SUSI.AI Bots

Making SUSI.AI reach more users through messenger bots

SUSI.AI learns from the queries asked to it by the users. More are the number of queries asked, the better is the learning by SUSI.AI. More are the number of users involved with SUSI.AI, better is the amount of content available to SUSI to learn from. Now, the challenge in front of us is to indulge more users with SUSI.AI. In this blog post, SUSI Tweetbot and SUSI FBbot are used as examples to show how we increase our user base through messenger bots. Twitter: Twitter has a 328 million user base according to this article’s data. Integration of SUSI.AI to just Twitter makes it available to around 300 million users. Even if some percentage of these users start using SUSI.AI, increase in the user base of SUSI.AI could be exponential. Increasing the user base is advantageous as it provides with more training data for SUSI.AI to learn from. Sharing by public tweet: Integrating to it is just the first step towards increasing SUSI.AI’s user base. Next step is to reach the users and indulge them into chatting with SUSI.AI. Suppose a user asked something to SUSI.AI and really liked the reply from it. He/she wants to share it with his/her followers. This can prove to be a golden opportunity for us, to increase the reach of SUSI.AI. This way we can indulge their friends to try SUSI.AI and have an amazing time with it. It becomes clear that sharing messages is an indispensable feature and can help us a lot. Twitter doesn’t provide sharing with friends through direct messages but with a feature much better than it. We can share that message as a public tweet and cover more users including the followers of the user.   To show this button we use Call to action support by twitter: "message_data": { "text": txt, "ctas": [{ "type": "web_url", "label": "Share with your followers", "url": "" }] } The url key in the above code must have a value that redirects to a U.I. that allows to publicly tweet this reply by SUSI.AI. Using this “https://twitter.com/intent/tweet?text=" as the url value shows a new page with an empty tweet message, as the text query in the url has no value. We set the text field with a value such that we end up like this: and after tweeting it: Sending a direct message link with the tweet: Twitter provides with a lot of features when sending direct messages. Shifting a user from tweets to direct messages is beneficial in a way that we can efficiently tell the user about the capabilities of SUSI.AI and show important links to him/her like of its repository, web chat client etc. When a user tweets to the SUSI.AI page with a query, we reply with a tweet back to the user. Along with that, we provide a link to privately message SUSI.AI account if the user wants to. This way if user ends up visiting SUSI.AI in a chat window: To achieve this in SUSI Tweetbot,…

Continue ReadingMaking SUSI.AI reach more users through messenger bots

Implementing Logging Functionality in Open Event Webapp

Open Event Webapp allows event organizers to generate an event website by providing JSON data in the form of a zip file or an API endpoint. The generation of event website is a multi step process and takes some time to complete. In order to see the ongoing progress of the process and catch any errors, logging feature is a must. The challenging part was to send the log messages in real time about the tasks being performed in the generator instead of sending it after some time when the task is already finished. To enable real time communication between the web server and the client, we use the Socket IO library. But before using that library for sending log messages from server to client, we have to design the architecture of the logging feature. The log statements can be of several types. It could be about the inception of a task, the successful completion of it or some error which occurred while performing the task. The log message object contains a field named type to show the type of the statements. We define three categories of logs messages:- INFO: Info statements give information about the task currently being performed by the webapp SUCCESS: Success statements give the information of a task being successfully completed ERROR: Error statements give information about a task failing to complete. These statements also contain a detailed error log Along with the type of the statement, the object also contains information about the task. For all types of statements, there is a field called smallMessage containing short information about the task. For the ERROR statements where more information is required to see what went wrong, the message object has an additional field called largeMessage which holds detailed information about the event. We also create a new file called buildlogger.js and define a function for creating log statements about the tasks being performed by generator and export it. The function creates a message object from the arguments received and then return it to the client under the buildLog event via the socket IO. exports.addLog = function(type, smallMessage, socket, largeMessage) { var obj = {'type' : type, 'smallMessage' : smallMessage, 'largeMessage': largeMessage}; var emit = false; if (socket.constructor.name === 'Socket') { emit = true; } if (emit) { socket.emit('buildLog', obj); } }; Most of the steps of the generation process are defined in the generator.js file. So, we include the logging file there and call the addLog function for sending logs messages to the client. All the different steps like cleaning temporary folders, copying assets, fetching JSONs, creating the website directory, resizing images etc have multiple log statements for their inception and successful/erroneous completion. Below is an excerpt from the cleaning step. var logger = require('./buildlogger.js'); async.series([ (done) => { console.log('CLEANING TEMPORARY FOLDERS\n'); logger.addLog('Info', 'Cleaning up the previously existing temporary folders', socket); fs.remove(distHelper.distPath + '/' + appFolder, (err) => { if(err !== null) { // Sending Error Message when the remove process failed logger.addLog('Error', 'Failed to clean up the previously existing temporary folders', socket, err); } // Success message denoting the completion of the…

Continue ReadingImplementing Logging Functionality in Open Event Webapp

Implementing Tracks Filter in Open Event Webapp using the side track name list

Event Websites generated by Open Event Webapp may contain a large number of sessions presented by different speakers. The Sessions are divided into the different group based on their type of track. For example, few sessions may belong to Database Track, few may belong to Machine Learning Track and so on. It is natural that the user may want to filter the visible sessions on the basis of tracks. Before we implemented the tracks filter using the track names list, we had a sub navbar on the tracks page for jumping to the different tracks of the event on a particular day. Below are the screenshots of that feature. On Clicking the Design, Art, Community Track But, it was not an elegant solution. We already had a track names list present on the side of the page which remained unused. A better idea was to use this side track names list to filter the sessions. Other event management sites like http://sched.org follow the same idea. The relevant issue for it is here and the major work can be seen in this Pull Request. Below is the screenshot of the unused side track names list. The end behavior should be something like this, the user clicks on a track and only sessions belonging to the track should be visible and the rest be hidden. There should also be a button for clearing the applied filter and reverting the page back to its default view. Let’s jump to the implementation part. First, we make the side track name list and make the individual tracks clickable. <div class="track-names col-md-3 col-sm-3"> {{#tracknames}} <div class="track-info"> <span style="background-color: {{color}};" class="titlecolor"></span> <span class="track-name" style="cursor: pointer">{{title}} </span> </div> {{/tracknames}} </div> Now we need to write a function for handling the user click event on the track name. Before writing the function, we need to see the basic structure of the tracks page. The divs with the class date-filter contain all the sessions scheduled on a given day. Inside that div, we have another div with class tracks-filter which contains the name of the track and all the sessions of that track are inside the div with class room-filter. Below is a relevant block of code from the tracks.hbs file <div class="date-filter"> // Contains all the sessions present in a single day <div class="track-filter row"> // Contains all the sessions of a single track <div class="row"> // Contains the name of the track <h5 class="text">{{caption}}</h4> </div> <div class="room-filter" id="{{session_id}}"> // Contain the information about the session </div> </div> </div> We iterate over all the date-filter divs and check all the track-filter divs inside it. We extract the name of the track and compare it to the name of the track which the user selected. If both of them are same, then we show that track div and all the sessions inside it. If the names don’t match, then we hide that track div and all the content inside it. We also keep a variable named flag and set it to 0 initially. If the user selected track is present on a given day, we set the flag to 1. Based on it, we decide whether to display that particular day or not. If the flag is set, we display the date-filter div of that…

Continue ReadingImplementing Tracks Filter in Open Event Webapp using the side track name list

Advanced functionality in SUSI Tweetbot

SUSI AI is integrated to Twitter (blog). During the initial phase, SUSI Tweetbot had basic UI and functionalities like just “plain text” replies. Twitter provides with many more features like quick replies i.e. presenting to the user with some choices to choose from or visiting SUSI server repository by just clicking buttons during the chat etc. All these features are provided to enhance the user experience with our chatbot on Twitter. This blog post walks you through on adding these functionalities to the SUSI Tweetbot: Quick replies Buttons Quick replies: This feature provides options to the user to choose from. The user doesn’t need to type the next query but rather select a quick reply from the options available. This speeds up the process and makes it easy for the user. Also, it helps developers know all the possible queries which can come next, from the user. Hence, it helps in efficient coding on how to handle those queries.In SUSI Tweetbot this feature is used to welcome a new user to the SUSI A.I.’s chat window, as shown in the image above. The user can select any option among “Get started” and “Start chatting”.The “Get started” option is basically for introduction of SUSI A.I. to the user. While, “Start chatting” when clicked shows the user of what all queries the user can try.Let’s come to the code part on how to show these options and what events happen when a user selects one of the options. To show the Welcome message, we call SUSI API with the query as string “Welcome” and store the reply in message variable. The code snippet used: var queryUrl = 'http://api.susi.ai/susi/chat.json?q=Welcome'; var message = ''; request({ url: queryUrl, json: true }, function (err, response, data) { if (!err && response.statusCode === 200) { message = data.answers[0].actions[0].expression; } else { // handle error } }); To show options with the message: var msg = { "welcome_message" : { "message_data": { "text": message, "quick_reply": { "type": "options", "options": [ { "label": "Get started", "metadata": "external_id_1" }, { "label": "Start chatting", "metadata": "external_id_2" } ] } } } }; T.post('direct_messages/welcome_messages/new', msg, sent); The line T.post() makes a POST request to the Twitter API, to register the welcome message with Twitter for our chatbot. The return value from this request includes a welcome message id in it corresponding to this welcome message. We set up a welcome message rule for this welcome message using it’s id. By setting up the rule is to set this welcome message as the default welcome message shown to new users. Twitter also provides with custom welcome messages, information about which can be found in their official docs. The welcome message rule is set up by sending the welcome message id as a key in the request body: var welcomeId = data.welcome_message.id; var welcomeRule = { "welcome_message_rule": { "welcome_message_id": welcomeId } }; T.post('direct_messages/welcome_messages/rules/new', welcomeRule, sent); Now, we are all set to show the new users with a welcome message. Buttons: Let’s go a bit…

Continue ReadingAdvanced functionality in SUSI Tweetbot

Advanced functionality in SUSI FBbot

SUSI AI is integrated to Facebook (blog). During the initial phase, SUSI FBbot had basic UI and functionalities like just “plain text” replies. Facebook provides many more features like replies enclosed in templates (blog link), sharing the replies by SUSI A.I. with friends, get started button or a persistent menu to show quick reply options to the user etc. All these features to enhance the user experience with SUSI AI chatbot. This blog post walks you through on adding these functionalities to the SUSI FBbot: Adding Get Started button A Get Started button is added to the SUSI FBbot to give the user a brief introduction about SUSI AI and what the user can try next. Clicking on the get started button , will send the message as “Get Started” to the SUSI FBbot: The reply message, provides the user with options to visit SUSI A.I. repository or to just start chatting. To have this button in our bot, we use this code snippet: // Add a get started button to the messenger 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) { // handle errors and response here }) When a user clicks this button, a postback is sent to the webhook of SUSI FBbot with payload as “GET_STARTED_PAYLOAD”. When we receive such postback, we reply with a message as shown above using generic template. Adding a persistent menu to the bot If not at the start, while chatting with SUSI AI for sometime, it is quite possible that the user becomes curious to visit the repository of SUSI A.I. . So we need a quick access to the “Visit repository” button all the time. Persistent menu, helps us with this feature: This way it is accessible at each point of time. Some other buttons can also be added to the menu like “Latest News” as shown in the image above. To have a persistent menu for the SUSI FBbot, the following code snippet is used: 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":"web_url", "title":"Visit Repository", "url":"https://github.com/fossasia/susi_server", "webview_height_ratio":"full" }] }] } }, function(error, response, body) { // handle errors and response }) We can add more buttons to the menu. JSON object having the required properties of that button can be appended to the key “call_to_actions” to do so. Adding a messenger code to join SUSI FBbot To enable Facebook users to chat with SUSI AI by scanning a code through messenger. This feature is added to the bot by making the following POST request: 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) { // handle errors and response. }); Adding message sharing feature To increase the reach of SUSI A.I. to more users on Facebook, message sharing proves to be a big boon. The reply by SUSI A.I. to users can be shared with their friends. Along with the message we can also send…

Continue ReadingAdvanced functionality in SUSI FBbot