Awesome
Alexa Parrot
A simple parroting skill for Alexa to grasp basics of creating alexa skills with Alexa-App library and deploying to AWS Lambda Functions. Requires Use NodeJS v8.x or higher.
Prerequisite files
Package JSON
Require alexa-app.
{
"name": "parrot",
"version": "1.0.0",
"description": "Alexa parroting skill",
"main": "parrot.js",
"dependencies": {
"alexa-app": "^4.2.2"
},
"author": "Daniel Doubrovkine (db@artsy.net)",
"license": "MIT",
"engines": {
"node": ">=8.0.0"
}
}
.gitignore
node_modules
Install
yarn install
Coding the skill
Basic Alexa App
const alexa = require('alexa-app');
const app = new alexa.app('parrot');
app.launch((req, res) => {
res.say('I am a parrot.');
});
module.exports = app;
Writing basic MochaJS tests
Add express
and mocha
to package.json
and support for yarn test
.
"devDependencies": {
"chai": "4.1.2",
"eslint": "^4.19.1",
"express": "^4.14.0",
"mocha": "5.2.0",
"supertest": "3.1.0"
},
"scripts": {
"test": "mocha test"
}
A test in test/test_parrot.js
.
/* eslint-disable no-undef, no-unused-vars, sort-vars, no-mixed-requires, global-require*/
const express = require('express');
const request = require('supertest');
const {expect} = require('chai');
describe('Parrot', () => {
let server = null;
beforeEach(() => {
const app = express();
const parrot = require('../parrot');
parrot.express({
expressApp: app,
debug: true,
checkCert: false
});
server = app.listen(3000);
});
afterEach(() => {
server.close();
});
});
Respond to Invalid Data
it('responds to invalid data', () => request(server)
.post('/parrot')
.send({})
.expect(200)
.then(response => expect(response.body).to.eql({
version: '1.0',
response: {
directives: [],
shouldEndSession: true,
outputSpeech: {
type: 'SSML',
ssml: '<speak>Error: not a valid request</speak>'
}
},
sessionAttributes: {}
})));
Responds to a Launch Request
it('responds to a launch event', () => request(server)
.post('/parrot')
.send({request: {type: 'LaunchRequest'}})
.expect(200)
.then((response) => {
const {ssml} = response.body.response.outputSpeech;
console.log(ssml);
return expect(ssml).to.eql('<speak>I am a parrot.</speak>');
}));
Deployment to AWS Lambda
For the deployment we will use Apex, which requires files to be in a functions
directory so lets move some files around:
mkdir -p functions/parrot
mv parrot.js functions/parrot
mv package.json functions/parrot
mv test functions/parrot
New folder structure is:
.
| functions/
|─── parrot/
| | parrot.js
| | package.json
| |──test/
| | | test_parrot.js
└
- Sign into AWS Console, https://console.aws.amazon.com, choose Lambda.
- Ensure your region is set to
Asia Pacific (Tokyo)
,EU (Ireland)
,US East (N. Virginia)
orUS West (Oregon)
as other regions do not have the Alexa Skills kit - Click
Services
near the top then search forLambda
- Click
Create function
to create a new Lambda function- Leave it on
Author from scratch
- Leave it on
- Name
alexa_parrot
- Create a new role,
alexa-parrot
- In the designer menu select
Alexa Skills Kit
- Get Apex
- MacOS, Linux or OpenBSD:
curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh
- Windows: Download the binary
- More info on official website
- MacOS, Linux or OpenBSD:
- Get AWS CLI
- MacOS through homebrew:
brew install awscli
- Linux: Read this AWS article for pip method or get it through APT / yum
- Windows: Read this AWS article for MSI installer
- MacOS through homebrew:
- Configure access to AWS the first time,
aws configure
- In AWS find the
IAM
service - Go to
Users
- Create a new user with
Programmatic access
- Copy access key ID and secret access key
- Fill in the region where you created the lambda function (you can see it when going to the function as part of the ARN near the top right)
- Set
default output
tojson
- In AWS find the
Create functions/parrot/index.js
.
const parrot = require('parrot');
exports.handle = parrot.lambda();
Create project.json
.
{
"name": "alexa",
"description": "I am a parrot.",
"memory": 128,
"timeout": 5,
"role": ""
}
For the role value go to AWS → IAM → Roles → Open the role you created while creating the function → Copy the ARN
To deploy run this command:
apex deploy
Creating a replying function
Add this to functions/parrot/parrot.js
.
app.intent('RepeatIntent', {
slots: {VALUE: 'AMAZON.NUMBER'},
utterances: ['repeat {-|VALUE}', 'to repeat {-|VALUE}']
}, (req, res) => {
const value = req.slot('VALUE') || 2;
res.say(`You said ${value}.`);
for (let i = 0; i < value; i++) {
res.say(`I repeat, you said ${value}.`);
}
});
And a test to functions/parrot/test/test_parrot.js
.
it('responds to a repeat event', () => request(server)
.post('/parrot')
.send({
request: {
type: 'IntentRequest',
intent: {
name: 'RepeatIntent',
slots: {
VALUE: {
name: 'VALUE',
value: '2'
}
}
}
}
})
.expect(200)
.then((response) => {
const { ssml } = response.body.response.outputSpeech;
return expect(ssml).to.eql('<speak>You said 2. I repeat, you said 2. I repeat, you said 2.</speak>');
}));
});
Create a new Alexa Skill
- Sign into Alexa Developer Console.
- Hover over
Your Alexa Consoles
then selectSkills
- Click
Create Skill
- Name the skill
Parrot
- Select
Custom
thenCreate skill
- Go to
invocations
and in theSkill Invocation Name
typeparrot
- Create the intent required for the skill
- Go to
Endpoint
and selectAWS Lambda ARN
- Copy the AWS Lambda Function ARN by accessing it in the AWS dashboard and paste it in the text field for
Default Region
- In the Alexa Skills endpoint copy the skill ARN then in the Lambda Function configuration click the
Alexa Skills Kit
trigger, make sureSkill ID verifcation
is enabled and paste the skill ARN in the text field then save the function - Save and build the model to test it (example:
ask parrot to repeat 3
)
Intent data can be generated with functions/parrot/skill.js
. Format the output of this file as proper JSON then paste it in the JSON Editor
.
const parrot = require('./parrot');
console.log('Intent Schema:');
console.log();
console.log(parrot.schemas.skillBuilder());
console.log('Utterances');
console.log(parrot.utterances());
The skill is now available in http://alexa.amazon.com under Skills → Your Skills → Dev Skills
Try It
- Alexa, open parrot.
- Alexa, ask parrot to repeat 3.
Setting up a CI service
CI (Continuous Integration) services will run your tests every time you commit some code and integrate flawlessly with major Git players such as GitHub, BitBucket and GitLab. Having a CI service set up will motivate you to always ensure the code you push works lest you'll be seeing the "tests failed" everywhere you have notifiers for the service set up.
For this project we have provided examples for setting up CI on Travis and on CircleCI. You can find the Travis setup by clicking here and the CircleCI setup here
Setting up TravisCI
- Go to TravisCI.org and create an account by signing in with your GitHub
- Once logged in click the
+
next toMy repositories
or navigate to your profile by clicking your name at the top right of the window - Enable the repo you want to build for
- Push some code to the repo to start building
Note: for private repositories please go to TravisCI.com instead
Setting up CircleCI
- Go to CircleCI and create your account by signing in with GitHub or BitBucket
- Once on the dashboard go to
Add Projects
on the left and add your Alexa Skill project - If you haven't committed your
config.yml
(in a folder.circleci
in root) yet do so now - Press the button
start building
to start testing your repo from this point forward