-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit bcf54c8
Showing
30 changed files
with
4,090 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,111 @@ | ||
junit.xml | ||
# Sphinx documentation | ||
docs/_build/ | ||
#### Vim | ||
# swap | ||
[._]*.s[a-w][a-z] | ||
[._]s[a-w][a-z] | ||
# session | ||
Session.vim | ||
# temporary | ||
.netrwhist | ||
*~ | ||
# auto-generated tag files | ||
tags | ||
|
||
#### SublimeText | ||
# cache files for sublime text | ||
*.tmlanguage.cache | ||
*.tmPreferences.cache | ||
*.stTheme.cache | ||
|
||
# workspace files are user-specific | ||
*.sublime-workspace | ||
|
||
# project files should be checked into the repository, unless a significant | ||
# proportion of contributors will probably not be using SublimeText | ||
# *.sublime-project | ||
|
||
# sftp configuration file | ||
sftp-config.json | ||
|
||
# Package control specific files | ||
Package Control.last-run | ||
Package Control.ca-list | ||
Package Control.ca-bundle | ||
Package Control.system-ca-bundle | ||
Package Control.cache/ | ||
Package Control.ca-certs/ | ||
bh_unicode_properties.cache | ||
|
||
# Sublime-github package stores a github token in this file | ||
# https://packagecontrol.io/packages/sublime-github | ||
GitHub.sublime-settings | ||
|
||
#### Node | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules | ||
jspm_packages | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
#### OSX | ||
*.DS_Store | ||
.AppleDouble | ||
.LSOverride | ||
|
||
# Icon must end with two \r | ||
Icon | ||
|
||
|
||
# Thumbnails | ||
._* | ||
|
||
# Files that might appear in the root of a volume | ||
.DocumentRevisions-V100 | ||
.fseventsd | ||
.Spotlight-V100 | ||
.TemporaryItems | ||
.Trashes | ||
.VolumeIcon.icns | ||
.com.apple.timemachine.donotpresent | ||
|
||
# Directories potentially created on remote AFP share | ||
.AppleDB | ||
.AppleDesktop | ||
Network Trash Folder | ||
Temporary Items | ||
.apdisk |
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,186 @@ | ||
|
||
|
||
Account Linking | ||
================== | ||
|
||
This project is designed to be a simple template for your new skills with account linking. User's information is stored in a DynamoDB table so you can fetch it from the skill once users are authenticated. | ||
|
||
Directory Structure | ||
--------------------- | ||
|
||
It has the following directory structure | ||
|
||
|
||
. | ||
├── README.md | ||
├── config | ||
│ ├── env.js | ||
│ ├── index.js | ||
│ ├── local.json.example | ||
│ ├── production.json | ||
│ └── staging.json | ||
├── gulpfile.js | ||
├── package.json | ||
├── serverless.yml | ||
├── services | ||
│ ├── model.js | ||
│ └── userStorage.js | ||
├── skill | ||
│ ├── MainStateMachine.js | ||
│ ├── index.js | ||
│ ├── states.js | ||
│ ├── variables.js | ||
│ └── views.js | ||
├── speechAssets | ||
│ ├── IntentSchema.json | ||
│ ├── SampleUtterances.txt | ||
│ └── customSlotTypes | ||
├── test | ||
└── www | ||
├── infrastructure | ||
│ └── mount.js | ||
├── routes | ||
│ ├── index.js | ||
│ └── skill.js | ||
└── server.js | ||
|
||
|
||
### config | ||
|
||
By default your skill will have the following environments: | ||
|
||
- local | ||
- staging | ||
- production | ||
|
||
What environment you're is determined in the ``config/env.js`` module using the following code: | ||
|
||
.. literalinclude:: ../samples/starterKit/config/env.js | ||
|
||
## skill | ||
|
||
### index.js | ||
----------------------- | ||
First file invoked by the lambda function, it initializes the state machine. You don't need to modify this file. | ||
|
||
|
||
### MainStateMachine.js | ||
----------------------- | ||
State machine is initialized with your model, views and variables. The class `states.js` will be in charge to handle all intents and events coming from Alexa. You don't need to modify this file. | ||
|
||
|
||
### states.js | ||
----------------------- | ||
All events and intents dispatched by the Alexa Voice Service to your skill are handled here. You can integrate any other module or API calls to third party services, call database resources or just simply reply a Hello or Goodbye response to the user. Before the very beginning of the lesson, you can implement the method `onRequestStarted` to fetch user's data from DynamoDB based on the accessToken coming from Alexa | ||
|
||
```javascript | ||
skill.onRequestStarted((alexaEvent) => { | ||
if (!alexaEvent.session.user.accessToken) { | ||
return alexaEvent; | ||
} | ||
const storage = new UserStorage(); | ||
|
||
return storage.get(alexaEvent.session.user.accessToken) | ||
.then((user) => { | ||
alexaEvent.model.user = user; | ||
return alexaEvent; | ||
}); | ||
}); | ||
``` | ||
|
||
If the user is not authenticated you can also send a `LinkingAccount` card to the Alexa app so users know that before using your skill, they must get authenticated. | ||
|
||
## speechAssets | ||
|
||
This should be a version controlled copy of your intent schema, sample utterrances and custom slots. | ||
|
||
## www | ||
|
||
A standard express project configured to serve your skill in the ``/skill`` route. Combined with `ngrok <https://ngrok.com/>`_ this is a great tool when developing or debugging. | ||
|
||
|
||
### routes/index.js | ||
----------------------- | ||
|
||
You can handle all GET and POST requests for your account linking projects here. The most common one will be the POST call of the form after users hit the submit button. In this example, we gather user's information and create a row in DynamoDB for their information. For example you can generate an UUID to identify the users as the primary key and send it back to Alexa as the accessToken so you can easily fetch user's information later on. | ||
|
||
```javascript | ||
router.post('/', (req, res, next) => { | ||
const md = new MobileDetect(req.headers['user-agent']); | ||
const db = new Storage(); | ||
const email = req.body.email; | ||
const code = uuidV4().replace(/-/g, ''); | ||
|
||
const params = { | ||
id: code, | ||
email, | ||
}; | ||
|
||
return db.put(params) | ||
.then(() => { | ||
const redirect = `${req.query.redirect_uri}#state=${req.query.state}&access_token=${code}&token_type=Bearer`; | ||
|
||
if (md.is('AndroidOS')) { | ||
console.log(`redirecting android to: ${redirect}`); | ||
res.redirect(redirect); | ||
} else { | ||
console.log(`redirecting web to: ${redirect}`); | ||
res.render('auth/success', { | ||
page: 'success', | ||
title: 'Success', | ||
redirectUrl: redirect, | ||
}); | ||
} | ||
}) | ||
.catch(next); | ||
}); | ||
``` | ||
|
||
To finish the authentication process you have to make a redirection to the `redirect_uri` Amazon sends to our service. Since there could be 2 origins to redirect to, we create this URL dynamically; these endpoints could look like this: | ||
|
||
- https://pitangui.amazon.com/spa/skill/account-linking-status.html?vendorId=xxx -> For United States store | ||
- https://layla.amazon.com/spa/skill/account-linking-status.html?vendorId=xxxxxx -> For UK and Germany store | ||
|
||
The other parameters to send are: | ||
|
||
- access_token=YOUR-TOKEN | ||
- token_type=Bearer | ||
|
||
## services | ||
|
||
Just a common place to put models and libraries | ||
|
||
|
||
### userStorage.js | ||
----------------------- | ||
|
||
Use this file as an example to handle database logic. Since we use DynamoDB for this example, we included 2 methods, a put and a get, so user's information get stored from the account linking project and get fetched from the alexa skill side. For reaching out DynamoDB you need some permissions for your lambda function. Make sure to grant your lambda function with a role with DynamoDB access. | ||
|
||
## test | ||
|
||
You write tests right? | ||
|
||
### gulpfile | ||
|
||
A gulp runner configured with a watch task that starts your express server and listens for changes to reload your application. | ||
|
||
### serverless.yml | ||
|
||
The serverless framework is a tool that helps you manage your lambda applications, assuming you have your AWS credentials setup properly this starter kit defines the very minimum needed so you can deploy your skill to lambda with the following command: | ||
|
||
$ sls deploy | ||
|
||
## Running the project | ||
--------------------- | ||
|
||
1. Clone the `Voxa <https://github.com/mediarain/voxa>`_ repository | ||
|
||
2. Create a new skill project using the ``samples/starterKit`` directory as a basis | ||
|
||
3. Make sure you're running node 4.3, this is easiest with `nvm <https://github.com/creationix/nvm>`_ | ||
|
||
4. Create a ``config/local.json`` file using ``config/local.json.example`` as an example | ||
|
||
5. Run the project with ``gulp watch`` | ||
|
||
6. At this point you should start ``ngrok http 3000`` and configure your skill in the Amazon Developer panel to use the ngrok https endpoint. |
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,14 @@ | ||
'use strict'; | ||
|
||
function getEnv() { | ||
if (process.env.NODE_ENV) return process.env.NODE_ENV; | ||
if (process.env.AWS_LAMBDA_FUNCTION_NAME) { | ||
// TODO put your own lambda function name here | ||
if (process.env.AWS_LAMBDA_FUNCTION_NAME === '') return 'production'; | ||
return 'staging'; | ||
} | ||
|
||
return 'local'; | ||
} | ||
|
||
module.exports = getEnv(); |
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,30 @@ | ||
'use strict'; | ||
|
||
const path = require('path'); | ||
const env = require('./env').toLowerCase(); | ||
const AWS = require('aws-sdk'); | ||
const https = require('https'); | ||
const _ = require('lodash'); | ||
|
||
const configFile = require(path.join(__dirname, `${env}.json`)); | ||
|
||
AWS.config.update(_.merge({ | ||
maxRetries: 8, | ||
httpOptions: { | ||
/** | ||
* See known issue: https://github.com/aws/aws-sdk-js/issues/862 | ||
*/ | ||
timeout: 4000, | ||
agent: new https.Agent({ | ||
keepAlive: false, | ||
rejectUnauthorized: true, | ||
secureProtocol: 'TLSv1_method', | ||
ciphers: 'ALL', | ||
}), | ||
}, | ||
}, configFile.aws)); | ||
|
||
configFile.env = env; | ||
|
||
module.exports = configFile; | ||
module.exports.asFunction = () => configFile; |
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,26 @@ | ||
{ | ||
"server": { | ||
"port": 3000, | ||
"hostSkill": true | ||
}, | ||
"alexa": { | ||
"auth": { | ||
"redirectUrl": "", | ||
"clientId": "", | ||
"clientSecret": "", | ||
"codeKey": "", | ||
"token_expiration": 1576800000 | ||
} | ||
}, | ||
"s3": { | ||
"bucket": "" | ||
}, | ||
"dynamoDB": { | ||
"tables": { | ||
"users": "" | ||
} | ||
}, | ||
"aws": { | ||
"region": "us-east-1" | ||
} | ||
} |
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,26 @@ | ||
{ | ||
"server": { | ||
"port": 3000, | ||
"hostSkill": true | ||
}, | ||
"alexa": { | ||
"auth": { | ||
"redirectUrl": "", | ||
"clientId": "", | ||
"clientSecret": "", | ||
"codeKey": "", | ||
"token_expiration": 1576800000 | ||
} | ||
}, | ||
"s3": { | ||
"bucket": "" | ||
}, | ||
"dynamoDB": { | ||
"tables": { | ||
"users": "" | ||
} | ||
}, | ||
"aws": { | ||
"region": "us-east-1" | ||
} | ||
} |
Oops, something went wrong.