Implementing a Chat Bubble in SUSI.AI

SUSI.AI now has a chat bubble on the bottom right of every page to assist you. Chat Bubble allows you to connect with susi.ai on just a click. You can now directly play test examples of skill on chatbot. It can also be viewed on full screen mode. Redux Code Redux Action associated with chat bubble is handleChatBubble. Redux state chatBubble can have 3 states: minimised - chat bubble is not visible. This set state is set when the chat is viewed in full screen mode.bubble - only the chat bubble is visible. This state is set when close icon is clicked and on toggle.full - the chat bubble along with message section is visible. This state is set when minimize icon is clicked on full screen mode and on toggle. const defaultState = { chatBubble: 'bubble', }; export default handleActions( { [actionTypes.HANDLE_CHAT_BUBBLE](state, { payload }) { return { ...state, chatBubble: payload.chatBubble, }; }, }, defaultState, ); Speech box for skill example The user can click on the speech box for skill example and immediately view the answer for the skill on the chatbot. When a speech bubble is clicked a query parameter testExample is added to the URL. The value of this query parameter is resolved and answered by Message Composer. To be able to generate an answer bubble again and again for the same query, we have a reducer state testSkillExampleKey which is updated when the user clicks on the speech box. This is passed as key parameter to messageSection. Chat Bubble Code The functions involved in the working of chatBubble code are: openFullScreen - This function is called when the full screen icon is clicked in the tab and laptop view and also when chat bubble is clicked in mobile view. This opens up a full screen dialog with message section. It dispatches handleChatBubble action which sets the chatBubble reducer state as minimised.closeFullScreen - This function is called when the exit full screen icon is clicked. It dispatches a handleChatBubble action which sets the chatBubble reducer state as full.toggleChat -  This function is called when the user clicks on the chat bubble. It dispatches handleChatBubble action which toggles the chatBubble reducer state between full and bubble.handleClose - This function is called when the user clicks on the close icon. It dispatches handleChatBubble action which sets the chatBubble reducer state to bubble. openFullScreen = () => { const { actions } = this.props; actions.handleChatBubble({ chatBubble: 'minimised', }); actions.openModal({ modalType: 'chatBubble', fullScreenChat: true, }); }; closeFullScreen = () => { const { actions } = this.props; actions.handleChatBubble({ chatBubble: 'full', }); actions.closeModal(); }; toggleChat = () => { const { actions, chatBubble } = this.props; actions.handleChatBubble({ chatBubble: chatBubble === 'bubble' ? 'full' : 'bubble', }); }; handleClose = () => { const { actions } = this.props; actions.handleChatBubble({ chatBubble: 'bubble' }); actions.closeModal(); }; Message Section Code (Reduced) The message section comprises of three parts the actionBar, messageSection and the message Composer. Action Bar The actionBar consists of the action buttons…

Continue ReadingImplementing a Chat Bubble in SUSI.AI

Limit the Chatbots to Run on Specified Domains

SUSI botbuilder enables users to make their own private skill and deploy a chatbot widget in their websites. Users can copy paste a javascript code into their website’s source code to activate the bot. But what if someone copies that code from your website and put it in their own website? You won’t want the chat bot to work for such users in some cases. Thus we have a feature through which the bot creator can restrict the usage of the chatbot to only certain domains. The chat bot will not work from other domains. Understanding the APIs Used In working of the chatbot, there are mainly two APIs used from the server which play a mainstream role. The first API is the cms/getSkillMetaData.json API. It is used to get the design and configurations of the chatbot. The second API is the susi/chat.json API. It is used to get responses from the server applying the private skill. By restricting the chatbot usage we try to restrict the usage of these two APIs. Also, on the client side we display the chatbot only if the server sends a valid response indicating that the chatbot is legitimate. However, this can be circumvented if the person modifies the javascript of the chatbot. Hence, we need to secure the above two APIs. We check the domain from where the request is coming by checking the referer field in the request’s header. Securing the APIs In each of the above two APIs, we check if the bot owner has checked “allow bot only on own site”. If no, then the APIs can be accessed from any domain we need not check. If selected yes, then we need to check if the current site’s domain is allowed in the allowed sites list. For this, we extract the current domain from the request’s referer field. The allowed sites list is fetched from the configure object of that skill. public static boolean allowDomainForChatbot(JSONObject configureObject, String referer) { Boolean allowed_site = true; if (configureObject.getBoolean("allow_bot_only_on_own_sites") && configureObject.has("allowed_sites") && configureObject.getString("allowed_sites").length() > 0) { allowed_site = false; if (referer != null && referer.length() > 0) { String[] sites = configureObject.getString("allowed_sites").split(","); for (int i = 0; i < sites.length; i++) { String site = sites[i].trim(); int referer_index = referer.indexOf("://"); String host = referer; if (referer.indexOf('/',referer_index+3) > -1) { host = referer.substring(0,referer.indexOf('/',referer_index+3)); } if (host.equalsIgnoreCase(site)) { allowed_site = true; break; } } } } return allowed_site; }   Result Not allowed from other domains: (For getSkillMetaData.json API) Allowed on approved domains: (For getSkillMetaData.json API) Resources JSON Object in java: https://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html Byte array input stream: https://www.javatpoint.com/java-bytearrayinputstream-class Work with Files in java: https://docs.oracle.com/javase/7/docs/api/java/io/File.html  

Continue ReadingLimit the Chatbots to Run on Specified Domains

Applying Private Skill as Web Bots in SUSI Chat

Along with public skills, we now have private skills as web bots! Users can create their own private skills which can be used only by them and in the chatbots deployed by them. The SUSI Server accepts parameters to identify a valid private skill and applies that private skill for a particular chat. It then executes the query and sends the response to the client. This blog explains how private skill is applied in the SUSI Chat. Understanding the API The API to receive response from SUSI is /susi/chat.json. For applying only the public skills, we can send a request like /susi/chat.json?q=hello. Here only one parameter “q” is involved in which we send the query. However, for a private skill, the following parameters are involved: privateskill - when the client sends this parameter, it indicates to use a private skill. userid - the userid of the user who has created the private skill group - the group name of the private skill language - the language of the private skill skill - the skill name of the private skill Thus, the four parameters userid, group, language, skill serves to uniquely identify a private skill. Fetching the private skill After the client sends the appropriate parameters to apply a private skill, the server must actually apply the private skill. This is done in a similar manner how persona and dream skills are applied. The First step is the fetch the private skill from the susi_private_skill_data folder. // read the private skill File private_skill_dir = new File(DAO.private_skill_watch_dir,userId); File group_file = new File(private_skill_dir, group_name); File language_file = new File(group_file, language); skillfile = SusiSkill.getSkillFileInLanguage(language_file, skill_name, false); String text = new String(Files.readAllBytes(skillfile.toPath()), StandardCharsets.UTF_8); Applying the private skill After we have fetched the private skill, the next step is to apply it. To do this, we create a SusiMind object and add it to the general minds variable. Thus the skill will be applied to the particular chat with the highest priority, since it will be the first skill to be added to the minds variable. Later, the public skills can be added to the minds variable, thus their priority will be lower than the private skill. String text = new String(Files.readAllBytes(skillfile.toPath()), StandardCharsets.UTF_8); // fill an empty mind with the private skill SusiMind awakeMind = new SusiMind(DAO.susi_chatlog_dir, DAO.susi_skilllog_dir); // we need the memory directory here to get a share on the memory of previous dialoges, otherwise we cannot test call-back questions JSONObject rules = SusiSkill.readLoTSkill(new BufferedReader(new InputStreamReader(new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)), SusiLanguage.unknown, dream); awakeMind.learn(rules, skillfile); SusiSkill.ID skillid = new SusiSkill.ID(skillfile); SusiSkill activeskill = awakeMind.getSkillMetadata().get(skillid); awakeMind.setActiveSkill(activeskill); // we are awake! minds.add(awakeMind);   Result Example API: http://localhost:4000/susi/chat.json?q=hi&privateskill=1&userid=17a70987d09c33e6f56fe05dca6e3d27&group=Knowledge&language=en&skill=knowprides The skill exists in the correct location: The skill file content is: Thus, on sending the query "tell me" with the other parameters, we get the correct reply i.e "yes sure" from the server: Resources JSON Object in java: https://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html Byte array input stream: https://www.javatpoint.com/java-bytearrayinputstream-class Work with Files in java: https://docs.oracle.com/javase/7/docs/api/java/io/File.html    

Continue ReadingApplying Private Skill as Web Bots in SUSI Chat

Store User’s Chatbots in SUSI Server

Users can create their own private skill which corresponds to their susi bot in SUSI Server. We store these private skills inside the susi_private_skill_data directory. We also store the information of the chatbots of each user in chatbot.json file inside the local storage of the server. It contains the list of chatbots created by each user against their UUIDs. This makes it easier and more organised to retrieve the chatbots of the users and their associated settings. This blog explains how the chatbots are being saved in the chatbot.json file in the SUSI server. Receiving Private Skill from client The client can create a private skill by accessing the /cms/createSkill.txt API. Along with the other parameters used to create a skill, it also has to send private=1 so that the server can recognise that this is a private skill. The private skills are stored in the folder susi_private_skill_data. The API is made by the CreateSkillService.java file. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setHeader("Access-Control-Allow-Origin", "*"); // enable CORS String userEmail = null; JSONObject json = new JSONObject(); Part imagePart = req.getPart("image"); if (req.getParameter("access_token") != null) { if (imagePart == null) { json.put("accepted", false); json.put("message", "Image not given"); }   Getting skill parameters and Saving skill locally The client sends various parameters related to the skill. Such as the group name, language, skill name, image, etc. Also to identify the skill as a private skill, it needs to send private=1 parameter. If it is a private skill, then we call the function storePrivateSkillBot(). if(privateSkill != null){ this.storePrivateSkillBot(userId, skill_name, group_name, language_name); try (Git git = DAO.getPrivateGit()) { git.add().addFilepattern(".").call(); // commit the changes DAO.pushCommit(git, "Created " + skill_name, userEmail); json.put("accepted", true); } catch (IOException | GitAPIException e) { e.printStackTrace(); json.put("message", "error: " + e.getMessage()); } }   Creating the chatbot.json file and saving user’s bot Inside the function storePrivateSkillBot(), we create the json file in the local storage and save the user’s bot along with their user ids. If the bot with the same name already exists, then we update it or else create a new one. private static void storePrivateSkillBot(String userId, String skillName, String group, String language) { JsonTray chatbot = DAO.chatbot; JSONArray userBots = new JSONArray(); JSONObject botObject = new JSONObject(); JSONObject userChatBotsObject = new JSONObject(); if (chatbot.has(userId)) { userBots = chatbot.getJSONObject(userId).getJSONArray("chatbots"); } // save a new bot botObject.put("name",skillName); botObject.put("group",group); botObject.put("language",language); userBots.put(botObject); userChatBotsObject.put("chatbots",userBots); chatbot.put(userId,userChatBotsObject,true); }   In chatbot.json file, on creating private skills, the following json gets stored: Resources JSON Object in Java: https://docs.oracle.com/javaee/7/api/javax/json/JsonObject.html File operations in Java: https://docs.oracle.com/javase/tutorial/essential/io/file.html JGit documentation: https://git-scm.com/book/en/v2/Appendix-B%3A-Embedding-Git-in-your-Applications-JGit  

Continue ReadingStore User’s Chatbots in SUSI Server

Protected Skills for SUSI.AI Bot Wizard

The first version of SUSI AI web bot plugin is working like a protected skill. A SUSI.AI skill can be created by someone with minimum base user role USER, or in other words, anyone who is logged in.  Anyone can see this skill or edit it. This is not the case with a protected skill or bot. If a skill is protected it becomes a personal bot and then it can only be used by the SUSI AI web client (chatbot) created by that user. Also, only the person who created this skill will be able to edit it or delete it. This skill won’t be listed with all the other public skills on skills.susi.ai. How is a skill made private? To make a skill private, a new parameter is added to SusiSkill.java file. This is a boolean called protected. If this parameter is true (Yes) then the skill is protected else if the parameter is false (No) then the skill is not protected. To add protected parameter, we add the following code to SusiSkill.java: private Boolean protectedSkill; boolean protectedSkill = false; You can see that protectedSkill is a boolean with initial value false. We need to read the value of this parameter in skill code. This is done by the following code: if (line.startsWith("::protected") && (thenpos = line.indexOf(' ')) > 0) {   if (line.substring(thenpos+ 1).trim().equalsIgnoreCase("yes")) protectedSkill=true;   json.put("protected",protectedSkill); } As you can see that the value of protected is read from the skill code. If it’s ‘Yes’ then protectedSkill is set as true and if it’s ‘No’ then protectedSkill is set as false. If no protected parameter is given in the skill code, its value remains false. How to add only protected skills from bot wizard? Now that protected parameter has been added to the server, we need to add this parameter in the skill code but it should be ‘Yes’ if the user is creating a bot and ‘No’ if user is creating a skill using skill creator. In order to do this, we simply check if the user is creating a bot wizard. This can be done by passing a props in the CreateSkill.js file when the skill creator is being used to create a protected skill. Next, we can determine whether the user is using bot wizard or not simply by an if else statement. The following code will demonstrate it: if (this.props.botBuilder) {  code = '::protected Yes\n' + code; } else {  code = '::protected No\n' + code; } References: JSON with java - https://www.tutorialspoint.com/json/json_java_example.htm

Continue ReadingProtected Skills for SUSI.AI Bot Wizard

Making Tree View in SUSI botbuilder

SUSI botbuilder enables you to create your own bot which you can integrate in your own website. While creating the skill for the bot, you often need to visualize the dialog flow. The Tree View helps you to visualize the conversation flow. The queries from the user and the related responses from the bot can easily be understood by seeing the tree. Installing package We will be using react-orgchart to make the tree. React-orgchart offers minimum basic implementation of the tree and we can easily customise the nodes. To install the package, type the following command in your terminal: npm i react-orgchart --save   Using the Orgchart In the TreeView.js file, we import the orgchart and render it. The tree data and node component is passed to the OrgChart component. Tree data stores the format and conversations in the tree and the node component represents the rendering of the individual node. We can customise the node according to our needs. const MyNodeComponent = ({node}) => { return ( 'initechNode'>{node.type==='bot' && '#4285f5' style={styles.icon}/>}{node.type==='user' && } { node.name } ); }; <OrgChart tree={this.props.treeData} NodeComponent={MyNodeComponent} />   Generating the Tree Data The data for the tree is generated by the code view. As user adds or edit skills in the code view, the skill language is interpreted and converted to a tree data structure. The generateTreeData() function in Build.js file does this job. //generation of skills from the code view for (let i = 0; i < lines.length; i++) { let bot_response = null; let line = lines[i]; if (line && !line.startsWith('::') && !line.startsWith('!') && !line.startsWith('#')) { let user_query = line; while (true) { i++; if (i >= lines.length) { break; } line = lines[i]; if (line && !line.startsWith('::') && !line.startsWith('!') && !line.startsWith('#')) { bot_response = lines[i]; break; } } let obj = { user_query, bot_response, }; skills.push(obj); } }   Thus, we are separating the skills in the code view and separating the bot and user response. A sample Tree data looks like: const treeData = { name: 'Welcome!', children: [ { name: 'User query 1', type: 'user', children: [ { name: 'Answer for the user query', type: 'bot', } ] }, { name: 'User query 2', type: 'user', children: [ { name: 'Answer for the user query', type: 'bot', } ] }, { name: 'User query 3', type: 'user', children: [ { name: 'Answer for the user query', type: 'bot', } ] } ] }   Result: Resources React-orgchart: https://www.npmjs.com/package/react-orgchart Passing functions to components: https://reactjs.org/docs/faq-functions.html Using props in react: https://reactjs.org/docs/render-props.html

Continue ReadingMaking Tree View in SUSI botbuilder

Adding feature to preview chatbot

You can access all features of SUSI.AI on chat.susi.ai. But this restricts the usage of SUSI.AI to this site only. To solve this issue, we can use a Chatbot which can be embedded on any website and then can be used by the people who visit that website, hence generalising the usage of SUSI.AI. How to embed SUSI.AI Chatbot on any website? To embed SUSI.AI Chatbot on any website, go to skills.susi.ai and login and then check out the Botbuilder section. There you can find a deploy button which will give you a code which looks something like this : <script type="text/javascript" id="susi-bot-script" data-userid="" data-group="" data-language="" data-skill="" src="https://skills.susi.ai/susi-chatbot.js" > </script>   As can be seen from the code above, it is simply a script tag with an id and a custom attribute data-token (which is the unique access token of the User for that session). The source file for this script is susi-chatbot.js. This is the file that is responsible for displaying the Chatbot on the screen. But, let’s say that you configured your Chatbot in the entire Botbuilder process. So, we need to have a Preview button which could show us a preview of the Chatbot with the chosen configurations, otherwise we would have to test it out by embedding it on our website, which would be tiresome. How does the Preview Button work? The code for Botbuilder page is in the Botbuilder.js file. The code for the Preview button is as follows : {!this.state.chatbotOpen?(<RaisedButton label='Preview' style={{ width: '148px' }} onClick={this.injectJS} />):(<RaisedButton label='Close Preview' style={{ width: '148px' }} onClick={this.handleChatbotClose} />)}   It can be seen that on clicking the ‘Preview’ button, injectJS() function is called, and on clicking the ‘Close Preview’ button, handleChatbotClose() function is called. injectJS = () => { const myscript = document.createElement('script'); myscript.type = 'text/javascript'; myscript.id = 'susi-bot-script'; myscript.setAttribute('data-token',cookies.get('loggedIn')); myscript.src = '/susi-chatbot.js'; myscript.async = true; document.body.appendChild(myscript); // some code }; handleChatbotClose = () =>{ // some code $('#susi-launcher-container').remove(); $('#susi-frame-container').remove(); $('#susi-launcher-close').remove(); $('#susi-bot-script').remove(); }   The above 2 functions are the key functions in understanding how the Preview button is previewing the Chatbot on the screen. Let us see the functioning of injectJS() function first. Firstly, the createElement() method creates an element node of type ‘script’. We store this element node in a variable myscript. We then add attribute values to the script tag by using myscript.attribute_name = attribute_value. We can add ‘type’, ‘id’, ‘src’ and ‘async’ attributes in this way because they are predefined attributes. However, we need to also add a custom attribute to store the access_token of the User, because we would need to pass down this information to detect the owner of the Chatbot. To add a custom attribute, we use the following code : myscript.setAttribute('data-token',cookies.get('loggedIn'));   This add a custom attribute ‘data-token’ and sets its value to the access token of the session, which would later be used to identify the User. This script is then appended to the body of the document. As soon as the script is appended to the page,…

Continue ReadingAdding feature to preview chatbot

How to make SUSI AI Twitch Bot

In this blog post, we’ll learn how to make SUSI AI Twitch bot. SUSI.AI is an intelligent Open Source personal assistant. SUSI AI Bots are built to enable users to chat with SUSI on different clients. Twitch is a live streaming video platform. We can integrate SUSI AI to the live chat on any of its channels. Pre-requisites: A Main Twitch account (This is the account on whose channel users would be able to talk to SUSI) A separate Twitch account for SUSI. GitHub Account Create a GitHub from here - Sign up on GitHub Heroku Account To create Heroku account, go to Heroku and click on Sign Up. Node.js Install Node.js from https://nodejs.org/en/ if it isn’t installed already on your computer. To check if node is already installed or not, open terminal and type the command: node -v If you see something like this - (version can be different) v9.4.0 Then Node.js is installed on your computer and you can follow along. Procedure: You can either fork susi_twitchbot repository and then simply deploy it on Heroku to create SUSI AI Twitch bot or you can create a new repository on your account then deploy it. The following section will describe how to create a new repository for SUSI AI Twitch bot. If you want to deploy susi_twitchbot directly then skip this section and directly move on to the deployment section. Creating the SUSI AI Twitch codebase: 1. Create a folder on your computer with any name. Open terminal and change your current directory to the new folder that you just created. 2. Type npm init command and enter details like name, version etc. (preferably just keep pressing enter key and let the values stay default) 3. Create a file with the same name that you wrote in entry point (index.js by default). NOTE - It should be in the same folder that you created earlier. 4. In the same folder, type the following commands in command line - npm i -s tmi.js We need tmi.js module to easily interact with Twitch messaging interface. For more details, visit https://www.tmijs.org/. npm i -s request We need request module to make a GET request to the SUSI API and retrieve JSON data for a particular query. npm i -s express We need express module to create successful connection with Heroku through the port provided by it. 5. Open package.json file. It should look like this: (Adding “start” script is necessary for deploying the app on Heroku) {   "name": "susi_twitchbot",   "version": "1.0.0",   "description": "SUSI.AI Twitchbot",   "main": "index.js",   "scripts": {     "start": "node index.js"   },   "author": "",   "license": "ISC",   "dependencies": {     "express": "^4.16.3",     "request": "^2.86.0",     "tmi.js": "^1.2.1"   } } 6. Copy the following code into the file that you created i.e. index.js var tmi = require('tmi.js'); var request = require('request'); const express = require('express'); const app = express(); const userChannel = process.env.CHANNEL; var ans; var options = {         options: {                 debug: true         },         connection: {                 reconnect: true         },         identity: {                 username: process.env.USERNAME,                 password: process.env.OAUTH_TOKEN         },         channels: [userChannel] }; var client = new tmi.client(options); // Connect the client to the server client.connect(); client.on('chat', function(channel, userstate, message, self){         if(message.includes("@"+process.env.USERNAME)){ // checking if SUSI is tagged                 var u = message.split("@" + process.env.USERNAME + " ");                 // Setting options to make a successful call to SUSI API                 var options1 = {                         method: 'GET',                         url: 'http://api.susi.ai/susi/chat.json',                         qs:                         {                                 timezoneOffset: '-300',                                 q: u[1]                         }                 };                 request(options1, function(error, response, body) {                         if (error) throw new Error(error);                         if((JSON.parse(body)).answers[0])                                 ans = userstate['display-name'] + " " + (JSON.parse(body)).answers[0].actions[0].expression;                         else                                 ans = userstate['display-name'] + " Sorry, I could not understand what you just said."                 …

Continue ReadingHow to make SUSI AI Twitch Bot

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

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