Fetching Private Skill from SUSI Server

SUSI Server needs to provide an API which would return the private skill’s file content. The private skill is used for the botbuilder project. Since the skill is private, the fetching process is little different from that of the public skills. The client has to provide the user’s access_token and a parameter private to access the private skill instead of the public skill. This blog explains how the private skill is being fetched from the SUSI Server.

Understanding the API

The API used to fetch public skill is /cms/getSkill.json, with the following parameters:

  • Model
  • Group
  • Language
  • Skill

These parameters helps to uniquely identify the skill.

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

  • Access_token
  • Private
  • Group
  • Language
  • Skill

The access token is used to authenticate the user, since the user should only be able to fetch their own private skill. The access token is also used to extract the user’s UUID which will be useful for locating the private skill.

String userId = null;
if (call.get("access_token") != null) { // access tokens can be used by api calls, somehow the stateless equivalent of sessions for browsers
ClientCredential credential = new ClientCredential(ClientCredential.Type.access_token, call.get("access_token"));
Authentication authentication = DAO.getAuthentication(credential);
// check if access_token is valid
if (authentication.getIdentity() != null) {
ClientIdentity identity = authentication.getIdentity();
userId = identity.getUuid();
}
}

 

Fetching the Private Skill from private skill repository

Now that we have all the necessary parameters, we can fetch the private skill from the susi_private_skill_data repository. The susi_private_skill_data folder has the following structure:

Thus to locate the skill, we will need the above parameters which we got from client and the user’s UUID. The following code checks if the client is requesting for private skill and changes the directory path accordingly.

// if client sends private=1 then it is a private skill
String privateSkill = call.get("private", null);
File private_skill_dir = null;
if(privateSkill != null){
private_skill_dir = new File(DAO.private_skill_watch_dir,userId);
}
String model_name = call.get("model", "general");
File model = new File(DAO.model_watch_dir, model_name);
if(privateSkill != null){
model = private_skill_dir;
}

 

Result:

Resources

Continue Reading

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 Reading
Close Menu