Skip to content

Commit

Permalink
Never answer in POST /message. Gladys now call user back
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierre-Gilles committed Mar 21, 2017
1 parent 99a56f7 commit 0843ec9
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 72 deletions.
2 changes: 1 addition & 1 deletion api/controllers/BrainController.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = {
* @apiParam {String} q the message for Gladys
*/
classify: function(req, res, next){
gladys.brain.classify(req.query.q)
gladys.brain.classify(req.session.User, {text: req.query.q})
.then(function(result){
return res.json(result);
})
Expand Down
3 changes: 1 addition & 2 deletions api/controllers/MessageController.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ module.exports = {
* @apiPermission authenticated
*
* @apiUse MessageParam
* @apiSuccess Object message message Object
* @apiSuccess Array responses Array of response
* @apiUse MessageSuccess
*/
send: function(req, res, next) {
gladys.message.send(req.session.User, req.body)
Expand Down
71 changes: 71 additions & 0 deletions api/core/brain/brain.answer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const queries = require('./brain.queries.js');
const Promise = require('bluebird');
const injector = require('./injector/injector.js');

module.exports = function answer(result, user) {
return gladys.utils.sql(queries.getAnswers, [user.language, result.response.label])
.then((answers) => {

// pick one answer randomly
var randomRow = Math.floor(Math.random() * (answers.length - 1)) + 0;

// test if answer exist, if yes pick the text
if(randomRow != -1 && answers[randomRow] != undefined) result.response.text = answers[randomRow].text;
else result.response.text = null;

// replace variables by values
result.response.text = injector.inject(result.response.text, result.response.scope);

return gladys.utils.sql(queries.getNotificationTypes, [user.id]);
})
.then((notificationTypes) => {

// test each notification system
return Promise.mapSeries(notificationTypes, function(notificationType) {
return trySendingMessage(result.response, notificationType, user);
})
.catch(function(err) {
if (err.message !== 'ok') {
sails.log.warn(err);
}
});
})
.then(() => result);
};

/**
* Call the service related to the notification
*/
function trySendingMessage(response, type, user) {

if (!gladys.modules[type.service] || typeof gladys.modules[type.service].notify !== "function") {
return Promise.reject(new Error(`${type.service} is not a valid service`));
}

sails.log.info(`Brain : answer : Trying to contact ${type.service}`);

var notification = {
title: user.assistantName,
text: response.text
};

return gladys.modules[type.service].notify(notification, user)
.then(function(result) {

sails.log.info(`Message sent with success with ${type.service}. Aborting the chain.`);

// if module resolved, we stop the promise chain
// it means one notification worked!
return Promise.reject(new Error('ok'));
})
.catch(function(e){

// if the error is because we want to exist the promise chain,
// we need to propagate the error
if(e.message === 'ok') return Promise.reject(e);

// if notification does not work, we resolve
// it means that we need to continue the flow
return Promise.resolve();
});
}
47 changes: 23 additions & 24 deletions api/core/brain/brain.classify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ const Promise = require('bluebird');
const clone = require('clone');
const shared = require('./brain.shared.js');
const parser = require('./parser/parser.js');
const injector = require('./injector/injector.js');
const answer = require('./brain.answer.js');

module.exports = function classify(originalText, language){
module.exports = function classify(user, message){
var start = process.hrtime();

if(!originalText || originalText.length === 0){
if(!message.text || message.text.length === 0){
return Promise.reject(new Error('BRAIN_NO_TEXT_GIVEN'));
}

return parser.parse(originalText)
return parser.parse(message.text)
.then((scope) => {

// add language to scope so that called module can adapt to the current language
scope.language = language;
scope.language = user.language;

var classifier = shared.getClassifier();

Expand All @@ -30,7 +30,7 @@ module.exports = function classify(originalText, language){
var splitted = classification.split(sails.config.brain.separator);
sails.log.info(`brain : classify : Identified label ${classification} `);
return callAction(clone(scope), splitted[0], splitted[1])
.then((result) => getAnswer(language, result));
.then((result) => answer(result, user));
});
})
.then((result) => {
Expand All @@ -42,7 +42,7 @@ module.exports = function classify(originalText, language){
});
};

function callAction(scope, service, label){
function callAction(scope, service, label) {
var toCall;

scope.label = label;
Expand Down Expand Up @@ -78,24 +78,23 @@ function callAction(scope, service, label){
},
response
};
});
}

function getAnswer(language, result) {
})
.catch((err) => {

return gladys.utils.sql('SELECT text FROM answer WHERE language = ? AND label = ?;', [language, result.response.label])
.then((answers) => {
sails.log.warn(`Brain : classify : Error while executing command in service = ${service}, label = ${label}`);
sails.log.warn(err);

// pick one answer randomly
var randomRow = Math.floor(Math.random() * (answers.length - 1)) + 0;

// test if answer exist, if yes pick the text
if(randomRow != -1 && answers[randomRow] != undefined) result.response.text = answers[randomRow].text;
else result.response.text = null;
var response = {
label: 'error'
};

// replace variables by values
result.response.text = injector.inject(result.response.text, result.response.scope);

return result;
});
return {
message: {
label,
service,
scope
},
response
};
});
}
13 changes: 13 additions & 0 deletions api/core/brain/brain.queries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {

getNotificationTypes: `
SELECT * FROM notificationtype nt
JOIN notificationuser nu ON (nt.id = nu.notificationtype)
WHERE nu.user = ?
ORDER BY nu.priority;
`,

getAnswers: `
SELECT text FROM answer WHERE language = ? AND label = ?;
`
};
2 changes: 2 additions & 0 deletions api/core/message/message.create.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const uuid = require('uuid');
module.exports = function create(message) {
message.conversation = message.conversation || uuid.v4();
message.datetime = message.datetime || new Date();
message.sender = message.sender || null;
message.receiver = message.receiver || null;

return Message.create(message);
};
37 changes: 5 additions & 32 deletions api/core/message/message.send.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
const uuid = require('uuid');
const Promise = require('bluebird');

module.exports = function send(user, message) {
message.sender = user.id;

// if receiver is null, it's a message for gladys
if(!message.receiver) return sendMessageGladys(user, message);
else sendMessageUser(message);
};
// if receiver is null, it's a message for gladys, so we send message to the brain
if(!message.receiver) gladys.brain.classify(user, message);

function sendMessageUser(message) {
return gladys.message.create(message)
.then((newMessage) => {
return {
message: newMessage
};
});
}

function sendMessageGladys(user, message) {

// first, classify the message
return gladys.brain.classify(message.text, user.language)
.then((results) => {

var responses = [];

results.forEach(function(result) {
responses.push(result.response);
});

// save the message in DB
return gladys.message.create(message)
.then((message) => {
return {message, responses};
});
});
}
return gladys.message.create(message);
};
4 changes: 4 additions & 0 deletions api/models/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ module.exports = {
type: 'uuid'
},

service: {
type: 'string'
},

isRead: {
type: 'boolean',
defaultsTo: false
Expand Down
2 changes: 1 addition & 1 deletion api/models/Notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module.exports = {
type: 'integer',
min: -2,
max: 2,
required: true
defaultsTo: 0
},

isRead: {
Expand Down
5 changes: 2 additions & 3 deletions test/unit/api/controllers/Message/message.post.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var request = require('supertest');
var validateMessage = require('../../validator/messageValidator.js');

describe('MessageController', function() {

Expand All @@ -13,9 +14,7 @@ describe('MessageController', function() {
.end(function(err, res) {
if(err) return done(err);

res.body.should.have.property('message');
res.body.should.have.property('responses');
res.body.responses.should.be.instanceOf(Array);
validateMessage(res.body);

done();
});
Expand Down
24 changes: 22 additions & 2 deletions test/unit/api/core/brain/brain.classify.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,32 @@ describe('Brain', function() {
describe('classify', function() {

it('should classify a sentence and call a service', function (done) {

var user = {
id: 1,
language: 'en'
};

var message = {
text:'THIS IS A TEST, ARE YOU GETTING ME ???'
};

gladys.brain.trainNew()
.then(function(){
return gladys.brain.classify('THIS IS A TEST, ARE YOU GETTING ME ???');
return gladys.brain.classify(user, message);
})
.then(function(result){
.then(function(result){
result.should.be.instanceOf(Array);
result.forEach(function(item){
item.should.have.property('message');
item.should.have.property('response');
item.message.should.have.property('label');
item.message.should.have.property('service');
item.message.should.have.property('scope');
item.response.should.have.property('label');
item.response.should.have.property('text');
item.response.should.have.property('scope');
});
done();
})
.catch(function(err){
Expand Down
8 changes: 1 addition & 7 deletions test/unit/api/core/message/message.send.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,10 @@ describe('Message', function() {

gladys.message.send({id: 1, language: 'en'}, {text: 'What time is it ?'})
.then(function(result){
result.should.have.property('message');
result.should.have.property('responses');
result.responses.should.be.instanceOf(Array);
result.responses.forEach(function(response) {
response.should.have.property('label');
});
validateMessage(result);
done();
}).catch(done);
});

});

});

0 comments on commit 0843ec9

Please sign in to comment.