From 68287d49fff8e474f7cb869eafcedab3fb4b5069 Mon Sep 17 00:00:00 2001 From: GotPPay Date: Thu, 18 Jan 2018 21:33:44 +0100 Subject: [PATCH] complete switch to new alexa package --- backend/components/alexa.js | 204 ----------------------- backend/controllers/saburlyEntryPoint.js | 39 +---- backend/controllers/skill.js | 6 +- backend/helpers/amazon.js | 2 + backend/models/alexa.js | 50 ++++++ backend/package.json | 1 - backend/server.js | 13 +- 7 files changed, 62 insertions(+), 253 deletions(-) delete mode 100644 backend/components/alexa.js create mode 100644 backend/models/alexa.js diff --git a/backend/components/alexa.js b/backend/components/alexa.js deleted file mode 100644 index 2fc124d..0000000 --- a/backend/components/alexa.js +++ /dev/null @@ -1,204 +0,0 @@ -var alexa = require ('alexa-app'); -const config = require ('../config/config'); -var databaseHelper = require ('../helpers/database'); - -//User data for sending message, this is skill-related and will be in some skill container -var Name = null; -var Email = null; -var Message = null; -var State = 0; // states should be defined in seperate file. (Not sending message, Waiting for name, Waiting for email, Waiting for message) -//For now (this is not long term solution) -// 0 : Not sending Message -// 1 : Waiting for name -// 2 : Waiting for email -// 3 : Waiting for message - -var alexaApp = new alexa.app ('saburly'); // this means we still work with one skill - -module.exports = { - init: function (express) { - alexaApp.express ({ - expressApp: express, - - // verifies requests come from amazon alexa. Must be enabled for production. - // You can disable this if you're running a dev environment and want to POST - // things to test behavior. enabled by default. - checkCert: false, - - // sets up a GET route when set to true. This is handy for testing in - // development, but not recommended for production. disabled by default - debug: true, - }); - }, - - updateIntentsJSON: function () { - databaseHelper - .getSkill (config.SKILL_DB_ID) - .then (skill => { - skill.intents.map (intent => { - alexaApp.intent ( - intent.intentName, - { - slots: [], - utterances: intent.questions, - }, - function (request, response) { - return response.say (intent.answer).shouldEndSession (false); - } - ); - }); - - alexaApp.launch ((request, response) => { - return response.say (skill.invocationAnswer).shouldEndSession (false); - }); - - alexaApp.intent ( - 'EmailIntentLaunch', - { - slots: [], - utterances: [ - 'I want to send a message', - 'I would like to send a message', - 'I would like to leave a message', - 'Leave a message', - ], - }, - function (request, response) { - Name = null; - Email = null; - Message = null; - State = 1; - - return response - .say ('Ok. What is your name') - .shouldEndSession (false); - } - ); - - //TODO : Watch out for this intent. It will make trouble with other regular intents - //if other intents have utterance with just one slot like {Data} - //It should be taken care somwhere before this, to check if Email Intent is invoked - //This is problem only if we introduce slot options for regular intents for users - alexaApp.intent ( - 'EmailIntent', - { - slots: { - Name: 'AMAZON.US_FIRST_NAME', - Email: 'AMAZON.LITERAL', - Message: 'AMAZON.LITERAL', - Data: 'AMAZON.LITERAL', - }, - utterances: [ - 'My name is {-|Name}', - 'I am {-|Name}', - '{dawdw at dwd wdw|Data}', - 'My email is {wadwwdw at wadwwd wdw|Email}', - 'Send replay to {fkofkeofe at dppfam wd|Email}', - 'My message is {Quick brown fox jumps over lazy dog|Message}', - ], - }, - function (request, response) { - let Data = undefined; - try { - if (!Name) Name = request.slot ('Name'); - } catch (e) { - console.log ('Error. No name slot '); - Name = undefined; - } - try { - if (!Email) Email = request.slot ('Email'); - } catch (e) { - console.log ('Error. No Email slot'); - Email = undefined; - } - try { - if (!Message) Message = request.slot ('Message'); - } catch (e) { - console.log ('Error. No Message slot'); - Message = undefined; - } - try { - Data = request.slot ('Data'); - } catch (e) { - console.log ('Error. No Data slot'); - Data = undefined; - } - console.log ('State : ' + State); - - //TODO : Responses could be configurable for each skill ? - - if (State === 1) { - //Was waiting for name, so if Name is null, name is probably in Data - if ((!Name && Data) || Name) { - //got the name, let's continue for the email - if (!Name) Name = Data; - State = 2; - return response - .say ('Ok ' + Name + '. What is your email ?') - .shouldEndSession (false); - } else { - //Something is wrong, ask for name again - return response - .say ( - 'Sorry, I didnt understand your name. Can you say it again ?' - ) - .shouldEndSession (false); - } - } else if (State === 2) { - //was waiting for email, so if Email is null, email is probably in Data - if ((!Email && Data) || Email) { - //Got the email, first verify email and than continue to message - if (!Email) Email = Data; - //TODO : verify email - State = 3; - return response - .say ('Great. Whats the message ?') - .shouldEndSession (false); - } else { - //Something is wrong, ask for the email again - return response - .say ( - 'Sorry, I didnt understan you email. Can you say it again ?' - ) - .shouldEndSession (false); - } - } else if (State === 3) { - //Was waiting for message, so if Message is null, message is probably in Data - if ((!Message && Data) || Message) { - //Ok, we got all informations. Exit email intent - if (!Message) Message = Data; - State = 0; - //TODO : Send email - console.log ( - 'Name : ' + - Name + - ' | Email : ' + - Email + - ' | Message : ' + - Message - ); - return response.say ( - 'Message sent. Someone will contact you ASAP' - ); - } else { - //Something is wrong, ask for the message again - return response - .say ( - 'Sorry, I didnt understand your message. Can you say it again ?' - ) - .shouldEndSession (false); - } - } else { - console.log ('State strange ! ' + State); - } - } - ); - }) - .catch (err => { - console.log (err); - alexaApp.launch ((request, response) => { - return response.say ('Sorry, there was no skill with that name'); - }); - }); - }, -}; diff --git a/backend/controllers/saburlyEntryPoint.js b/backend/controllers/saburlyEntryPoint.js index 8b3f90e..e698d84 100644 --- a/backend/controllers/saburlyEntryPoint.js +++ b/backend/controllers/saburlyEntryPoint.js @@ -1,40 +1,9 @@ var express = require ('express'), router = express.Router (); -const config = require('../config/config'); var bodyParser = require ('body-parser'); -var Alexa = require('alexa-sdk'); +var alexa = require ('../models/alexa'); - -router.get('/', async (req, res) => { - console.log("GET request on /saburly"); - // Build the context manually, because Amazon Lambda is missing - var context = { - succeed: function (result) { - console.log(result); - res.json(result); - }, - fail:function (error) { - console.log(error); - } - }; - - const handlers = { - 'LaunchRequest': function () { - console.log("Launch request"); - this.emit(':tell', 'Welcome to Saburly'); - this.emit('HelloWorldIntent'); - }, - - 'HelloWorldIntent': function () { - console.log("Hello world intent"); - this.emit(':tell', 'Hello World!'); - } - }; - - // Delegate the request to the Alexa SDK and the declared intent-handlers - var alexa = Alexa.handler(req.body, context); - alexa.appId = config.SKILL_ID; - alexa.registerHandlers(handlers); - alexa.execute(); +router.post ('/', bodyParser.json (), async (req, res) => { + alexa.run (req, res); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/backend/controllers/skill.js b/backend/controllers/skill.js index 1d8cd44..6cc36e7 100644 --- a/backend/controllers/skill.js +++ b/backend/controllers/skill.js @@ -3,7 +3,7 @@ const constants = require ('../config/constants'); var databaseHelper = require ('../helpers/database'); var amazonHelper = require ('../helpers/amazon'); var bodyParser = require ('body-parser'); -var alexa = require ('../components/alexa'); +var alexa = require ('../models/alexa'); router.get ('/:id', async (req, res, next) => { const id = req.params.id; @@ -49,7 +49,7 @@ router.put ('/:id', bodyParser.json (), async (req, res, next) => { amazonResult === constants.amazonResultCodes.ACCEPTED ) { res.json ({result: constants.apiResultCodes.OK, message: ''}); - alexa.updateIntentsJSON (); + alexa.updateModel (); } else { res.status(constants.HTTPResultCodes.INTERNAL_SERVER_ERROR).json ({ result: constants.apiResultCodes.AMAZON_ERROR, @@ -65,7 +65,7 @@ router.put ('/:id', bodyParser.json (), async (req, res, next) => { }); }else{ res.json ({result: constants.apiResultCodes.OK, message: ''}); - alexa.updateIntentsJSON (); + alexa.updateModel (); } }) .catch (() => { diff --git a/backend/helpers/amazon.js b/backend/helpers/amazon.js index 1fd9410..d6c554b 100644 --- a/backend/helpers/amazon.js +++ b/backend/helpers/amazon.js @@ -82,6 +82,7 @@ var generateInteractionModel = function (skill) { }); //Special Email Intents : + /* allIntents.push ({ name: 'EmailIntentLaunch', slots: [], @@ -123,6 +124,7 @@ var generateInteractionModel = function (skill) { 'My message is {The quick brown fox jumps over the lazy dog.The quick brown fox jumps over the lazy dog.The quick brown fox jumps over the lazy dog.|Message}', ], }); + */ result.interactionModel = {}; diff --git a/backend/models/alexa.js b/backend/models/alexa.js new file mode 100644 index 0000000..a4b0471 --- /dev/null +++ b/backend/models/alexa.js @@ -0,0 +1,50 @@ +var Alexa = require ('alexa-sdk'); +const config = require ('../config/config'); +var databaseHelper = require ('../helpers/database'); + +// Build the context manually, because Amazon Lambda is missing +var context = { + succeed: function (result) { + console.log (result); + res.json (result); + }, + fail: function (error) { + console.log (error); + //We could send error json from here + }, +}; + +var handlers = {}; + +module.exports = { + run: function (req, res) { + var alexa = Alexa.handler (req.body, context); + alexa.appId = config.SKILL_ID; + alexa.registerHandlers (handlers); + alexa.execute (); + }, + updateModel: function () { + //Get info from database, and store it for faster response on intent + databaseHelper + .getSkill (config.SKILL_DB_ID) + .then (activeSkill => { + handlers = {}; + handlers = { + LaunchRequest: function () { + this.response.speak (activeSkill.invocationAnswer); + this.emit (':responseReady'); + }, + }; + activeSkill.intents.map (intent => { + handlers[intent.intentName] = function () { + this.response.speak (intent.answer); + this.emit (':responseReady'); + }; + }); + }) + .catch (e => { + //Something is wrong, skill is not ready, use catch-all intent to inform user + console.log ('Error. Skill doesnt exist'); + }); + }, +}; diff --git a/backend/package.json b/backend/package.json index 421c735..b0c0319 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,6 @@ "description": "", "main": "test.js", "dependencies": { - "alexa-app": "4.2.0", "alexa-sdk": "^1.0.25", "body-parser": "^1.13.1", "ejs": "^2.5.7", diff --git a/backend/server.js b/backend/server.js index 32e38e1..f39f9b9 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,11 +1,7 @@ -var amazonHelper = require ('./helpers/amazon'); var databaseHelper = require ('./helpers/database'); const config = require ('./config/config'); -const constants = require ('./config/constants'); -require ('isomorphic-fetch'); var express = require ('express'); -//var alexa = require('./components/alexa'); - +var alexa = require ('./models/alexa'); var MongoClient = require ('mongodb').MongoClient; var ObjectID = require ('mongodb').ObjectID; @@ -13,10 +9,7 @@ var ObjectID = require ('mongodb').ObjectID; const router = express.Router (); var app = express (); -// ALWAYS setup the alexa app and attach it to express before anything else. -//alexa.init (app); - -app.set ('view engine', 'ejs'); +app.set ('view engine', 'ejs'); // Should be removed app.use (require ('./middleware')); //common middleware for all requests app.use (require ('./controllers')); //all routes @@ -26,7 +19,7 @@ MongoClient.connect (config.DB_URL) app.listen (config.PORT, () => { console.log ('Express server running on port ' + config.PORT); - //alexa.updateIntentsJSON (); + alexa.updateModel (); databaseHelper.loadTokens (); }); })