-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #186 from internetarchive/feature/init-alexa-skill
Feature/init alexa skill
- Loading branch information
Showing
25 changed files
with
513 additions
and
75 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# deps | ||
|
||
functions/node_modules | ||
node_modules | ||
|
||
|
||
# dev env | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use strict'; | ||
|
||
const {defaultActions} = require('./src/actions'); | ||
const alexaHandler = require('./src/platform/alexa/handler'); | ||
const setup = require('./src/setup'); | ||
const logAppStart = require('./src/utils/logger/log-app-start'); | ||
|
||
const actionsMap = defaultActions(); | ||
|
||
logAppStart(actionsMap); | ||
|
||
setup(); | ||
|
||
/** | ||
* Alexa Lambda Endpoint | ||
* | ||
* @type {HttpsFunction} | ||
*/ | ||
exports.handler = alexaHandler(actionsMap); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
const _ = require('lodash'); | ||
|
||
// const dialog = require('../dialog'); | ||
// const query = require('../state/query'); | ||
const welcomeStrings = require('../strings').intents.welcome; | ||
|
||
/** | ||
* Handle `LaunchRequest` intent from Alexa | ||
* TODO: merge with welcome action handler | ||
* | ||
* @param app | ||
*/ | ||
function handler (app) { | ||
let reprompt = welcomeStrings.reprompt || welcomeStrings.speech; | ||
|
||
let speech; | ||
if (app.isFirstTry()) { | ||
speech = '<audio src="https://s3.amazonaws.com/gratefulerrorlogs/CrowdNoise.mp3" />' + _.sample(welcomeStrings.acknowledges) + ' ' + welcomeStrings.speech; | ||
} else { | ||
speech = _.sample(welcomeStrings.acknowledges) + ' ' + welcomeStrings.speech; | ||
} | ||
|
||
// TODO: | ||
// query.resetSlots(app); | ||
// dialog.ask(app, Object.assign({}, welcomeStrings, {speech, reprompt})); | ||
|
||
app.response.ask(Object.assign({}, welcomeStrings, {speech, reprompt})); | ||
} | ||
|
||
module.exports = { | ||
handler, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const persistance = require('./persistence'); | ||
const response = require('./response'); | ||
|
||
/** | ||
* Facade of Alexa App | ||
*/ | ||
class App { | ||
constructor (alexa) { | ||
this.alexa = alexa; | ||
|
||
// define interfaces | ||
this.persist = persistance(alexa); | ||
this.response = response(alexa); | ||
} | ||
|
||
/** | ||
* is first skill used time | ||
* | ||
* @returns {boolean} | ||
*/ | ||
isFirstTry () { | ||
return true; | ||
} | ||
} | ||
|
||
module.exports = { | ||
App, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const {App} = require('../app'); | ||
const {debug} = require('../../../utils/logger')('ia:platform:alexa:handler'); | ||
|
||
const kebabToCamel = require('../../../utils/kebab-to-camel'); | ||
|
||
/** | ||
* Map actions to alexa handlers | ||
* - alexa intenets should be camel styled and Object type | ||
* | ||
* @param actions {Map} | ||
* @returns {Object} | ||
*/ | ||
module.exports = (actions) => { | ||
if (!actions) { | ||
return {}; | ||
} | ||
|
||
return Array | ||
.from(actions.keys()) | ||
.reduce((acc, name) => { | ||
const intent = kebabToCamel(name); | ||
return Object.assign({}, acc, { | ||
[intent]: function () { | ||
debug(`begin handle intent "${intent}"`); | ||
actions.get(name)(new App(this)); | ||
debug(`end handle intent "${intent}"`); | ||
this.emit(':responseReady'); | ||
}, | ||
}); | ||
}, {}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const Alexa = require('alexa-sdk'); | ||
const {debug, error} = require('../../../utils/logger')('ia:platform:alexa:handler'); | ||
|
||
const handlersBuilder = require('./handlers-builder'); | ||
|
||
module.exports = (actions) => { | ||
const handlers = handlersBuilder(actions); | ||
debug(`We can handle intents: ${Object.keys(handlers).map(name => `"${name}"`).join(', ')}`); | ||
return (event, context, callback) => { | ||
const alexa = Alexa.handler(event, context, callback); | ||
|
||
// TODO: get from process.env | ||
// alexa.appId | ||
// alexa.dynamoDB | ||
alexa.registerHandlers(handlers); | ||
|
||
try { | ||
alexa.execute(); | ||
} catch (err) { | ||
error('Caught Error:', err); | ||
alexa.emit(':tell', 'Sorry, I\'m experiencing some technical difficulties at the moment. Please try again later.'); | ||
} | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const persistance = require('./session'); | ||
|
||
/** | ||
* Return persistance interface | ||
* | ||
* @param alexa | ||
*/ | ||
module.exports = (alexa) => persistance(alexa); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
const _ = require('lodash'); | ||
|
||
const {debug} = require('../../../utils/logger')('ia:platform:alexa:persistance:device-level'); | ||
|
||
/** | ||
* Session level persistance | ||
* | ||
* @param alexa | ||
*/ | ||
module.exports = (alexa) => { | ||
debug('create'); | ||
|
||
const deviceId = alexa.event.context.System.device.deviceId; | ||
debug('deviceId:', deviceId); | ||
|
||
if (!alexa) { | ||
throw new Error('parameter alexa should be defined'); | ||
} | ||
|
||
return { | ||
/** | ||
* Get data | ||
* | ||
* @param name | ||
* @returns {{}} | ||
*/ | ||
getData: (name) => { | ||
return _.get(alexa.attributes, [deviceId, name]); | ||
}, | ||
|
||
/** | ||
* Update data | ||
* | ||
* @param name | ||
* @param value | ||
*/ | ||
setData: (name, value) => { | ||
debug(`set attribute ${name} to ${JSON.stringify(value)}`); | ||
_.set(alexa.attributes, [deviceId, name], value); | ||
}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/** | ||
* create alexa.ask wrapper | ||
* | ||
* @param alexa | ||
*/ | ||
module.exports = (alexa) => | ||
/** | ||
* Response with question | ||
* | ||
* @param speech {String} | ||
* @param suggestions {Array} | ||
*/ | ||
({speech, suggestions}) => { | ||
alexa.response.speak(speech); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
const askBuilder = require('./ask'); | ||
|
||
/** | ||
* Return response interface | ||
* | ||
* @param alexa | ||
* @returns {Object} | ||
*/ | ||
module.exports = (alexa) => ({ | ||
ask: askBuilder(alexa), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const DialogflowApp = require('actions-on-google').DialogflowApp; | ||
const functions = require('firebase-functions'); | ||
const bst = require('bespoken-tools'); | ||
const dashbotBuilder = require('dashbot'); | ||
|
||
const dialog = require('./../../dialog'); | ||
const {storeAction} = require('./../../state/actions'); | ||
const strings = require('./../../strings'); | ||
const {debug, warning} = require('./../../utils/logger')('ia:index'); | ||
const logRequest = require('./../../utils/logger/log-request'); | ||
|
||
module.exports = (actionsMap) => { | ||
const dashbot = dashbotBuilder( | ||
functions.config().dashbot.key, { | ||
printErrors: false, | ||
}).google; | ||
|
||
return functions.https.onRequest(bst.Logless.capture(functions.config().bespoken.key, function (req, res) { | ||
const app = new DialogflowApp({request: req, response: res}); | ||
|
||
logRequest(app, req); | ||
|
||
storeAction(app, app.getIntent()); | ||
|
||
// it seems pre-flight request from google assistant, | ||
// we shouldn't handle it by actions | ||
if (!req.body || !app.getIntent()) { | ||
debug('we get empty body. so we ignore request'); | ||
app.ask('Internet Archive is here!'); | ||
return; | ||
} | ||
|
||
if (app.hasSurfaceCapability(app.SurfaceCapabilities.MEDIA_RESPONSE_AUDIO)) { | ||
app.handleRequestAsync(actionsMap) | ||
.catch(err => { | ||
warning(`We missed action: "${app.getIntent()}". | ||
And got an error:`, err); | ||
}); | ||
} else { | ||
dialog.tell(app, strings.errors.device.mediaResponse); | ||
} | ||
|
||
dashbot.configHandler(app); | ||
})); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const persistance = require('./session'); | ||
|
||
/** | ||
* Return persistance interface | ||
* | ||
* @param assistant app | ||
*/ | ||
module.exports = (app) => persistance(app); |
Oops, something went wrong.