Defining the controller

Now that are done with defining the routes and updating the model, we will work on the logic discussed in the Solution design section earlier. Create a new file named cloud-ai-api.ts inside the server/controllers folder. First, we will add the required imports and configure the Cloudinary client as follows:

// SNIPP SNIPP
import * as request from 'request';
import * as fs from 'fs';
import * as dotenv from 'dotenv';
import * as cloudinary from 'cloudinary';

import Message from '../models/message';

dotenv.config();

const API_KEY = process.env.GCP_API_KEY;

cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
// SNIPP SNIPP

Next, we are going to implement the VisionAPI class with a respondErrorMessage helper:

// SNIPP SNIPP
export default class VisionAPI {
respondErrorMessage = (res, err) => {
return res.status(500).json(err);
}
// SNIPP

Next, we are going to define the uploadImage method:

// SNIPP SNIPP
uploadImage = (req, res) => {
// console.log('req.file', req.file);
const filePath = req.file.path;
this.base64_encode(filePath).then((BASE64_CONTENT) => {
const formData = JSON.stringify({
'requests': [
{
'image': {
'content': BASE64_CONTENT
},
'features': [
{
'type':
'LABEL_DETECTION'
}, {
'type':
'SAFE_SEARCH_DETECTION'
}
]
}
]
});
var options = {
method: 'POST',
url: 'https://vision.googleapis.com/v1/images:annotate',
qs: {
key: `${API_KEY}`
},
body: formData
};

request(options, (error, response, body) => {
if (error) {
// Delete the local file so we don't clutter

this.deleteFile(filePath);
return this.respondErrorMessage(res, error);
}

let results = this.getJSONObject(body);
if (!results) {
// Delete the local file so we don't clutter

this.deleteFile(filePath);
return this.respondErrorMessage(res, { 'message': 'Invalid Response from Google Cloud Vision API' });
}
results = results.responses;

let labelAnnotations = results[0].labelAnnotations;
let safeSearchAnnotations = results[0].safeSearchAnnotation;

if (safeSearchAnnotations.adult === 'POSSIBLE') {
// Delete the local file so we don't clutter

this.deleteFile(filePath);
return res.status(400).json({
message: 'Adult Content is not allowed'
})
}
if (safeSearchAnnotations.medical === 'POSSIBLE') {

// Delete the local file so we don't clutter

this.deleteFile(filePath);
return res.status(400).json({
message: 'Medical Content'
})
}
if (safeSearchAnnotations.violence === 'POSSIBLE') {

// Delete the local file so we don't clutter

this.deleteFile(filePath);
return res.status(400).json({
message: 'Violence Content violence'
})
}
let msg = new Message();
msg.thread = req.params.threadId;
msg.createdBy = req.user;
msg.lastUpdatedBy = req.user;
msg.labels = labelAnnotations;
msg.safeSearchProps = safeSearchAnnotations;

// Upload our image to cloudinary for external file hosting

// This is optional & you can use any service for the same

cloudinary.uploader.upload(filePath, (result) => {
// Delete the local file so we don't clutter

this.deleteFile(filePath);
if (result.error) {
return res.status(400).json({
message: result.error.message
});
}
msg.cloudinaryProps = result;
msg.description = `<img style="max-width:80%; height:auto;" src="${result.secure_url}" alt="${result.original_filename}">`

msg.save((err, msg) => {
if (err) {
return this.respondErrorMessage(res, err);
}
res.status(200).json(msg);
});
});
});
});
}
// SNIPP SNIPP

In the preceding method, we first extract the filePath from req.file and get the image we are trying to process. Using base64_encode(), we convert the image to a base64 encoded string programmatically. Next, we construct the request payload for sending this image to the Google Cloud Vision API. Using the request module, we are going to send the payload with our API key to get the results.

Once the results arrive, we extract labelAnnotations and safeSearchAnnotations, and check whether safeSearchAnnotations has a high possibility of adult, medical, or violence categories. If everything is good, we are going to upload the validated image to Cloudinary, and then save all the data we have gathered so far as a message and respond with the newly created message document. Finally, here are the three helper methods:

//SNIPP SNIPP
base64_encode = (filePath) => {
return new Promise((res, rej) => {
try {
// read binary data
const bitmap = fs.readFileSync(filePath);
// convert binary data to base64 encoded string
const base64String = new Buffer(bitmap).toString('base64');
res(base64String);
} catch (e) {
rej(e);
}
});
}
getJSONObject = (jsonStr) => {
try {
return JSON.parse(jsonStr);
} catch (ex) {
return false;
}
}
deleteFile = (filePath: string) => {
fs.unlink(filePath);
}
// SNIPP SNIPP

This wraps up our controller logic, as well as our service-side logic. In the next section, we are going to work on the client-side logic.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.109.8