API’s in SUSI.AI BotBuilder

In this blog, I’ll explain the different API’s involved in the SUSI.AI Bot Builder and its working. Now if you are wondering how the SUSI.AI bot builder works or how drafts are saved, then this is the perfect blog. I’ll be explaining the different API’s grouped by different API endpoints.

API Implementation

fetchChatBots

export function fetchChatBots() {
 const url = `${API_URL}/${CMS_API_PREFIX}/getSkillList.json`;
 return ajax.get(url, {
   private: 1,
 });
}

This API is used to fetch all your saved chatbots, which are displayed on the BotBuilder Page. The API endpoint is getSkillList.json. Same endpoint is used when a user creates a skill, the difference is query parameter private is passed which then returns your chatbots. Now if you are wondering why we have same endpoint for skills and chatbots, the simple plain reason for this is chatbots are your private skills.

fetchBotDetails

export function fetchBotDetails(payload) {
 const { model, group, language, skill } = payload;
 const url = `${API_URL}/${CMS_API_PREFIX}/getSkill.json`;
 return ajax.get(url, {
   model,
   group,
   language,
   skill,
   private: 1,
 });
}

This API is used to fetch details of bot/skill respectively from the API endpoint getSkill.json. Group name, language, skill name, private and model are passed as query parameters.

fetchBotImages

export function fetchBotImages(payload) {
 const { name: skill, language, group } = payload;
 const url = `${API_URL}/${CMS_API_PREFIX}/getSkill.json`;
 return ajax.get(url, {
   group,
   language,
   skill,
   private: 1,
 });
}

This API is used to fetch skill and bot images from the API endpoint getSkill.json. Group name, language, skill name and private are passed as query parameters.

uploadBotImage

export function uploadBotImage(payload) {
 const url = `${API_URL}/${CMS_API_PREFIX}/uploadImage.json`;
 return ajax.post(url, payload, {
   headers: { 'Content-Type': 'multipart/form-data' },
   isTokenRequired: false,
 });
}

This API is used to upload the Bot image to the API endpoint uploadImage.json.The Content-Type entity header is used to indicate the media type of the resource. multipart/form-data means no characters will be encoded. This is used when a form requires a binary data like the contents of a file or image to be uploaded.

deleteChatBot

export function deleteChatBot(payload) {
 const { group, language, skill } = payload;
 const url = `${API_URL}/${CMS_API_PREFIX}/deleteSkill.json`;
 return ajax.get(url, {
   private: 1,
   group,
   language,
   skill,
 });
}

This API is used to delete Skill and Bot from the API endpoint deleteSkill.json.

storeDraft

export function storeDraft(payload) {
 const { object } = payload;
 const url = `${API_URL}/${CMS_API_PREFIX}/storeDraft.json`;
 return ajax.get(url, { object });
}

This API is used to store draft Bot to the API endpoint storeDraft.json. The object passed as parameter has the properties given by the user such as skill name,group etc., while saving the draft.

readDraft

export function readDraft(payload) {
 const url = `${API_URL}/${CMS_API_PREFIX}/readDraft.json`;
 return ajax.get(url, { ...payload });
}

This API is used to fetch draft from the API endpoint readDraft.json. This API is called on the BotBuilder Page where all the saved drafts are shown.

deleteDraft

export function deleteDraft(payload) {
 const { id } = payload;
 const url = `${API_URL}/${CMS_API_PREFIX}/deleteDraft.json`;
 return ajax.get(url, { id });
}

This API is used to delete the saved Draft from the API endpoint deleteDraft.json. It only needs one query parameter i.e. the draft ID.

In conclusion, the above API’s are the backbone of the SUSI.AI Bot Builder. API endpoints in server ensure the user has the same experience across the clients. Do checkout implementation of different API endpoints in server here.

Resources

Continue ReadingAPI’s in SUSI.AI BotBuilder

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

 

Continue ReadingLimit the Chatbots to Run on Specified Domains

Making API for Fetching Private Skill Bot Settings from Server

SUSI Server needs to provide an API which would return the private skill’s metadata. This metadata will include the chatbot’s design and configuration settings. The skill’s meta data is being stored in the chatbot.json file in the server. This API will be called from the websites where the chatbot has been deployed. The skill’s metadata will be used for customizing the design of the chatbot. This blog explains how the API for fetching a private skill bot’s metadata is made.

Understanding the API

The API used to fetch public skill’s metadata is /cms/getSkillMetadata.json, with the following parameters:

  • Model
  • Group
  • Language
  • Skill

These parameters help to uniquely identify the skill.

The same API is used to fetch private skill’s metadata too. But the parameters changes to:

  • userid
  • Group
  • Language
  • Skill

The userid also helps to secure the identity of the user. Unlike email id, the user can be easily identified using the userid. Also it prevents from accessing other user’s chatbots without knowing their userid.

Understanding the data stored

In the chatbot.json file, the skill’s metadata are stored in the following format:

{"17a70987d09c33e6f56fe05dca6e3d27": {"Knowledge": {"en": {"test2new1": {
  "design": {
    "botIconColor": "#000000",
    "userMessageTextColor": "#ffffff",
    "botMessageBoxBackground": "#f8f8f8",
    "userMessageBoxBackground": "#0077e5",
    "botMessageTextColor": "#455a64",
    "bodyBackground": "#ffffff"
  },
  "configure": {
    "sites_enabled": "website1.com, website2.com",
    "sites_disabled": "website3.com"
  },
  "timestamp": "2018-07-20 01:04:39.571"
}}}}}

 

Thus, each entry is stored as a key-value pair. This makes the retrieval of record very efficient.

Making API to fetch private skill bot’s settings

In GetSkillMetadataService.java file, we detect if the client is sending the “userid” parameter or not. For fetching public skill’s metadata, the client will send the “model” parameter and for fetching private skill bot’ settings, the client will send the “userid” parameter. To fetch the private skill bot’s settings, we need to extract it from the chatbot.json file. We fetch the entire object for the particular skill and return it:

// fetch private skill (chatbot) meta data
JsonTray chatbot = DAO.chatbot;
JSONObject json = new JSONObject(true);
JSONObject userObject = chatbot.getJSONObject(userid);
JSONObject groupObject = userObject.getJSONObject(group);
JSONObject languageObject = groupObject.getJSONObject(language);
JSONObject skillObject = languageObject.getJSONObject(skillname);
json.put("skill_metadata", skillObject);
json.put("accepted", true);
json.put("message", "Success: Fetched Skill's Metadata");
return new ServiceResponse(json);

 

Result

Example API request: http://127.0.0.1:4000/cms/getSkillMetadata.json?userid=17a70987d09c33e6f56fe05dca6e3d27&group=Knowledge&language=en&skill=testnew

This gives the following output:

{
  "skill_metadata": {
    "design": {
      "botIconColor": "#000000",
      "userMessageTextColor": "#ffffff",
      "botMessageBoxBackground": "#f8f8f8",
      "userMessageBoxBackground": "#0077e5",
      "botMessageTextColor": "#455a64",
      "bodyBackground": "#ffffff"
    },
    "configure": {
      "sites_enabled": "website1.com, website2.com",
      "sites_disabled": "website3.com"
    },
    "timestamp": "2018-07-20 01:39:55.205"
  },
  "accepted": true,
  "message": "Success: Fetched Skill's Metadata",
  "session": {"identity": {
    "type": "host",
    "name": "127.0.0.1_af2c1fe3",
    "anonymous": true
  }}
}

 

Resources

Continue ReadingMaking API for Fetching Private Skill Bot Settings from Server

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

 

Continue ReadingStore User’s Chatbots in SUSI Server

Creating API to Retrieve Images in SUSI.AI Server

SUSI Server needed to have an API where users can upload and store images. This images will be useful in setting custom theme for the botbuilder or for chat.susi.ai. User can upload image from their systems instead of pasting the link of an image stored in cloud. Also we need an API to retrieve the stored image given its full path. This blog explains how the SUSI Server returns the image stored upon requesting.

Understanding where the image is stored

The images uploaded to the SUSI Server is stored in its local storage. The local storage is where all the json files and other data are stored. We store the images inside “image_uploads” folder. In the get image API, the client will provide the full path of the image i.e the user UUID and the image’s full name. Then we need to fetch this image from the local storage and return it.

Retrieving the image from local storage

The Retrieving image API has the endpoint “/cms/getImage.png”. The servlet file is “GetImageServlet.java”. The client has to send the full path of the image in the parameter “image”. A sample GET request is “http://127.0.0.1:4000/cms/getImage.png?image=963e84467b92c0916b27d157b1d45328/1529692996805_susi icon.png”.

We need to retrieve the given image from the correct path.

Query post = RemoteAccess.evaluate(request);
String image_path = post.get("image","");
File imageFile = new File(DAO.data_dir  + File.separator + "image_uploads" + File.separator+ image_path);
if (!imageFile.exists()) {response.sendError(503, "image does not exist"); return;}
String file = image_path.substring(image_path.indexOf("/")+1);

 

Writing the image in Byte Stream

Now that we have the image file, we need to write that image in a Byte array output stream. We read the pixels data from the image using “FileInputStream” method.

ByteArrayOutputStream data = new ByteArrayOutputStream();
byte[] b = new byte[2048];
InputStream is = new BufferedInputStream(new FileInputStream(imageFile));
int c;
try {
while ((c = is.read(b)) >  0) {data.write(b, 0, c);}
} catch (IOException e) {}

 

Returning the image to the client

Now that we have the image data in the Byte array, we can send that data to the client. Before that we have to set the response type. We set the response type accordingly if the image is png, gif, or jpg. For other types, we the response type as “octet-stream”. Finally we attach the image in the response object and send it.

if (file.endsWith(".png") || (file.length() == 0 && request.getServletPath().endsWith(".png"))) post.setResponse(response, "image/png");
else if (file.endsWith(".gif") || (file.length() == 0 && request.getServletPath().endsWith(".gif"))) post.setResponse(response, "image/gif");
else if (file.endsWith(".jpg") || file.endsWith(".jpeg") || (file.length() == 0 && request.getServletPath().endsWith(".jpg"))) post.setResponse(response, "image/jpeg");
else post.setResponse(response, "application/octet-stream");

ServletOutputStream sos = response.getOutputStream();
sos.write(data.toByteArray());
post.finalize();

 

Result:

Resources

 

Continue ReadingCreating API to Retrieve Images in SUSI.AI Server

Creating API to Upload Images in SUSI.AI Server

SUSI Server needed to have an API where users can upload and store images. This images will be useful in setting custom theme for the botbuilder or for chat.susi.ai. User can upload image from their systems instead of pasting the link of an image stored in cloud. This blog explains how the SUSI Server stores the images in its local storage.

Creating Upload Image Service

UploadImageService.java is the file which creates the API to upload image. After creating the UploadImageService class in this file, we need to include the class in SusiServer.java to enable the API:

// add services
  services = new Class[]{
...
UploadImageService.class

Restricting access rights and giving API endpoint name

The Upload Image API should be available only to logged in users and not to anonymous users. Therefore we need to set the base user role to “USER”.  Also we need to set the name of the API endpoint. Lets set it to “/cms/uploadImage.json”.

@Override
public UserRole getMinimalUserRole() {
return UserRole.USER;
}

@Override
public String getAPIPath() {
return "/cms/uploadImage.json";
}

 

Creating API to accept the Post request

We need to accept the image uploaded by the client in a post request. The post request will contain the following parameters:

  • access_token – used to verify identity of the user and get their UUID
  • image_name – the name of the image
  • image (the image file) – the actual image file

To accept the post request on this route, we define the following function:

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("Access-Control-Allow-Origin", "*"); // enable CORS
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");
} else {
// save image

 

Getting the correct storage location

We are saving the image in the local storage of the server, i.e inside the “data” folder. Inside it, we store inside the “image_uploads” folder. The image path and name has three parts:

  • User’s UUID as the sub folder’s name
  • System time in milliseconds as the first part of the image’s name
  • The image’s name given by the user as the second part of the image’s name

String image_name = req.getParameter("image_name");
ClientCredential credential = new ClientCredential(ClientCredential.Type.access_token, req.getParameter("access_token"));
Authentication authentication = DAO.getAuthentication(credential);
ClientIdentity identity = authentication.getIdentity();
String userId = identity.getUuid();
String imagePath = DAO.data_dir  + File.separator + "image_uploads" + File.separator + userId;

 

Saving the image

After we have formed the location of the image to be stored, we need to actually write that file to the local storage. Here is the code snippet which does that:

// Reading content for image
Image image = ImageIO.read(imagePartContent);
BufferedImage bi = this.toBufferedImage(image);
// Checks if images directory exists or not. If not then create one
if (!Files.exists(Paths.get(imagePath))) new File(imagePath).mkdirs();
String new_image_name = System.currentTimeMillis() + "_" + image_name;
File p = new File(imagePath + File.separator + new_image_name);
if (p.exists()) p.delete();
ImageIO.write(bi, "jpg", new File(imagePath + File.separator + new_image_name));

 

Thus the image gets stored in the local storage inside of the folder named by user’s UUID

Here, the number 963e84467b92c0916b27d157b1d45328 is the user UUID of the user and 1529692996805 is generated by getting the System time in milliseconds. This helps to differentiate between images of same name uploaded by the same user.

Resources

Continue ReadingCreating API to Upload Images in SUSI.AI Server

Code view and UI View in design tab of bot wizard

Design tab is for designing your SUSI AI chatbot. You can change the background colour, add an image as background color, change colour of user text box, bot text box etc. On SUSI AI bot wizard design tab, we have two views. These views show the same thing but in a different way for different people. The code view is mainly for the developers while the UI (User Interface) view is for a non-developer user because we can not expect them to know how to code even if it is easy.

Code View

The current code view of design tab looks like this:

::bodyBackground #ffffff
::bodyBackgroundImage
::userMessageBoxBackground #0077e5
::userMessageTextColor #ffffff
::botMessageBoxBackground #f8f8f8
::botMessageTextColor #455a64
::botIconColor #000000
::botIconImage

For changing colours, you simply have to change the hex codes and for adding images as background, you need to add the url of image. You can also upload an image but that function is provided in the UI View.

UI View

The current UI view of design tab looks like this:

Here, we have colour picker for user to choose a colour for various components of the chatbot. There’s also a small box with the same colour as specified in hex code for previewing.

Switching and Synchronising between Code view and UI view

We have different components for code view and UI view. In order to synchronise both the views, we need to have the same code in state of both components. To do that, we add the code in state of the parent component i.e. design.js and then pass it to code view and UI view as states.

The following code snippet will demonstrate this:

<CodeView
    design={{
        sendInfoToProps: this.sendInfoToProps,
        updateSettings: this.updateSettings,
        code: this.state.code,
    }}
/>

You can see that we pass a whole object as props.
Using this approach, same code is passed to both the views. This solves the first problem. The next problem is that if we do a change in code view then it should happen in the code state of parent file as well. Same goes for UI view.
To do this, whenever we change the code in code view or UI view, we call a function in the parent file (design.js) which was passed as props and we pass the state of code view or UI view as arguments of this function. This function then updates the state accordingly. The name of the function is sendInfoToProps and it is as follows:

sendInfoToProps = values => {
    this.setState({ ...values });
};

You can see that it simply updates the state value as per the parameters passed to it.
So this is how synchronisation works between different views.

References:

Continue ReadingCode view and UI View in design tab of bot wizard

Code view in Configure tab of SUSI.AI Bot Wizard

The purpose of configure tab in SUSI.AI bot wizard is to provide the bot creator various options on how the bot will interact with different websites. It currently provides an option of enabling or disabling the chatbot on different websites.
The configure tab has two parts. One is the code view which allows the users to write websites on which they want to enable/disable the chatbot and a table below it which lists those websites.

The default code in code view is passed in a state in the Configure.js file. The following code demonstrates that:

this.state = {
  code: this.props.code,
};

Fetching data from code view:

After writing the websites on which the user wants the chatbot to be enabled/disabled and pressing on the ‘Save’ button, a functiongenerateConfigData is called.
This function takes the code in code view and stores in inside of a variable. Then it splits the code and makes two arrays:

  • enabledSites: This array contains all the websites that are written in  enabled field.
  • disabledSites: This array contains all the websites that are written in disabled field.

This process can be easily understood from the following code snippet:

let newCode = this.state.code;
let websiteData = newCode
 .split('::sites_enabled')[1]
 .split('::sites_disabled');
let enabledSites = websiteData[0].split(',');
let disabledSites = websiteData[1].split(',');

This data is stored inside an object.

Displaying the data:

The data fetched from the code view now has to be displayed in form of a table. This data is looks like this:

let configData = [
 {
   id: '1',
   name: 'website1.com',
   last: 'Jan 12, 2018 20:08 hrs',
   status: 1,
 },
 {
   id: '2',
   name: 'website2.com',
   last: 'Feb 19, 2018 13:00 hrs',
   status: 1,
 },
 {
   id: '3',
   name: 'website3.com',
   last: 'Mar 14, 2018 10:15 hrs',
   Status: 2,
 }
];

Status is 1 if the website is in enabled column and 2 if the website is in disabled column.
To display this data on the screen, we simply map through the data and display the rows of the table. The following code demonstrates it:

{configData.map((item, index) => {
 if (item.name) {
   return (
    <TableRow key={index}>
      <TableRowColumn style={{ fontSize: '16px' }}>
         {item.name}
     </TableRowColumn>
      <TableRowColumn style={{ fontSize: '16px' }}>
         {item.last}
     </TableRowColumn>
     <TableRowColumn>
       <SelectField
         floatingLabelText="Status"
         fullWidth={true}
         value={item.status}
       >
         <MenuItem value={1} primaryText="Enable" />
         <MenuItem value={2} primaryText="Disable" />
       </SelectField>
     </TableRowColumn>
    </TableRow>
   );
 }
})}

References:

Continue ReadingCode view in Configure tab of 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

Continue ReadingMaking Tree View in SUSI botbuilder

Add auto copy code feature in botbuilder

SUSI botbuilder lets you create your own skill bot and deploy on your website. After you have customised your bot, you will get a javascript code that you need to paste in your website’s source code. To make the process of copying the code easy, we have developed a feature for auto copying of the code to your clipboard. You just need to click on a button “copy” and the code will be copied to your clipboard.

Installing package

We use react-copy-to-clipboard package to enable auto copy feature. Install it in your project using the following command.

npm i react-copy-to-clipboard --save

 

Adding code inside render function

Inside the render() function in react file, paste the following code where you want the copy button to be displayed. Here we need to provide the text to be copied to the CopyToClipboard component via the text props. We pass the script code. We get the access token for the bot via the saved cookie. Inside the children of CopyToClipboard we need to pass the copy button which we want to show.

<CopyToClipboard
  text={
    " +cookies.get('uuid') +"' data-group='" +
    group + "' data-language='" + language + "' data-skill='" + skill + "' src='" + api + "/susi-chatbot.js'>"
  }
  onCopy={() => this.setState({ copied: true })}
>
  <span className="copy-button">copy</span>
</CopyToClipboard>

 

Thus, when the user clicks on the “copy” button, the code will be automatically copied to the user’s clipboard.

Showing snackbar message

After the code has been copied to the user’s clipboard, we can show a snackbar message to inform the user. First we pass a function onCopy to the CopyToClipboard component. This sets the state variable copied to true. Then we have a snackbar component which displays the message.

<Snackbar
   open={this.state.copied}
   message="Copied to clipboard!"
   autoHideDuration={2000}
   onRequestClose={() => {
      this.setState({ copied: false });
   }}
/>

 

Result:

 

Resources

 

Continue ReadingAdd auto copy code feature in botbuilder