Skip to content

Commit a1da302

Browse files
committed
Initial commit
1 parent 77c7579 commit a1da302

File tree

12 files changed

+578
-0
lines changed

12 files changed

+578
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.DS_Store
2+
node_modules
3+
package-lock.json
4+
15
# Logs
26
logs
37
*.log

01/README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Part 1 - Alexa-Hosted Skill (preset - Hello World)
2+
3+
## Milestones
4+
5+
1. **Developer Console**: Build, Code and Test tabs
6+
2. **Build tab**: Invocation name, Built-In and Custom Intents and Utterances in VIM. VIM as JSON
7+
3. **Code Tab**: Dependencies (require), package.json, Save/Deploy/Promote to Live, Handler Structure (canHandle/handle), Handler Input, Response Builder, Speak/Reprompt, Skill Builder, FallbackIntent handler
8+
4. **Test Tab**: Custom Skill opening, JSON in/out, LaunchRequest, IntentRequest, Help/Stop/Cancel, Session ended, Test physical device (same account)
9+
10+
## Concepts
11+
12+
1. Development and Production Lambda Stages
13+
2. Lambda Dependencies
14+
3. Handler structure
15+
4. Skill Builder functions
16+
5. Out-of-domain utterances
17+
6. Request Types

01/lambda/custom/index.js

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
2+
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
3+
// session persistence, api calls, and more.
4+
const Alexa = require('ask-sdk-core');
5+
6+
const LaunchRequestHandler = {
7+
canHandle(handlerInput) {
8+
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
9+
},
10+
handle(handlerInput) {
11+
const speechText = 'Welcome, you can say Hello or Help. Which would you like to try?';
12+
return handlerInput.responseBuilder
13+
.speak(speechText)
14+
.reprompt(speechText)
15+
.getResponse();
16+
}
17+
};
18+
19+
const HelloWorldIntentHandler = {
20+
canHandle(handlerInput) {
21+
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
22+
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
23+
},
24+
handle(handlerInput) {
25+
const speechText = 'Hello World!';
26+
return handlerInput.responseBuilder
27+
.speak(speechText)
28+
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
29+
.getResponse();
30+
}
31+
};
32+
33+
const HelpIntentHandler = {
34+
canHandle(handlerInput) {
35+
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
36+
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.HelpIntent';
37+
},
38+
handle(handlerInput) {
39+
const speechText = 'You can say hello to me! How can I help?';
40+
41+
return handlerInput.responseBuilder
42+
.speak(speechText)
43+
.reprompt(speechText)
44+
.getResponse();
45+
}
46+
};
47+
48+
const CancelAndStopIntentHandler = {
49+
canHandle(handlerInput) {
50+
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
51+
&& (handlerInput.requestEnvelope.request.intent.name === 'AMAZON.CancelIntent'
52+
|| handlerInput.requestEnvelope.request.intent.name === 'AMAZON.StopIntent');
53+
},
54+
handle(handlerInput) {
55+
const speechText = 'Goodbye!';
56+
return handlerInput.responseBuilder
57+
.speak(speechText)
58+
.getResponse();
59+
}
60+
};
61+
62+
const FallbackIntentHandler = {
63+
canHandle(handlerInput) {
64+
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
65+
&& handlerInput.requestEnvelope.request.intent.name === 'AMAZON.FallbackIntent';
66+
},
67+
handle(handlerInput) {
68+
const speechText = `Sorry, I don't know about that. Please try again.`;
69+
70+
return handlerInput.responseBuilder
71+
.speak(speechText)
72+
.reprompt(speechText)
73+
.getResponse();
74+
}
75+
};
76+
77+
const SessionEndedRequestHandler = {
78+
canHandle(handlerInput) {
79+
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
80+
},
81+
handle(handlerInput) {
82+
// Any cleanup logic goes here.
83+
return handlerInput.responseBuilder.getResponse();
84+
}
85+
};
86+
87+
// The intent reflector is used for interaction model testing and debugging.
88+
// It will simply repeat the intent the user said. You can create custom handlers
89+
// for your intents by defining them above, then also adding them to the request
90+
// handler chain below.
91+
const IntentReflectorHandler = {
92+
canHandle(handlerInput) {
93+
return handlerInput.requestEnvelope.request.type === 'IntentRequest';
94+
},
95+
handle(handlerInput) {
96+
const intentName = handlerInput.requestEnvelope.request.intent.name;
97+
const speechText = `You just triggered ${intentName}`;
98+
99+
return handlerInput.responseBuilder
100+
.speak(speechText)
101+
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
102+
.getResponse();
103+
}
104+
};
105+
106+
// Generic error handling to capture any syntax or routing errors. If you receive an error
107+
// stating the request handler chain is not found, you have not implemented a handler for
108+
// the intent being invoked or included it in the skill builder below.
109+
const ErrorHandler = {
110+
canHandle() {
111+
return true;
112+
},
113+
handle(handlerInput, error) {
114+
console.log(`~~~~ Error handled: ${error.message}`);
115+
const speechText = `Sorry, there was an error. Please try again.`;
116+
117+
return handlerInput.responseBuilder
118+
.speak(speechText)
119+
.reprompt(speechText)
120+
.getResponse();
121+
}
122+
};
123+
124+
// This handler acts as the entry point for your skill, routing all request and response
125+
// payloads to the handlers above. Make sure any new handlers or interceptors you've
126+
// defined are included below. The order matters - they're processed top to bottom.
127+
exports.handler = Alexa.SkillBuilders.custom()
128+
.addRequestHandlers(
129+
LaunchRequestHandler,
130+
HelloWorldIntentHandler,
131+
HelpIntentHandler,
132+
CancelAndStopIntentHandler,
133+
FallbackIntentHandler,
134+
SessionEndedRequestHandler,
135+
IntentReflectorHandler) // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
136+
.addErrorHandlers(
137+
ErrorHandler)
138+
.lambda();

01/lambda/custom/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "hello-world",
3+
"version": "0.9.0",
4+
"description": "alexa utility for quickly building skills",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "Amazon Alexa",
10+
"license": "ISC",
11+
"dependencies": {
12+
"ask-sdk-core": "^2.0.7",
13+
"ask-sdk-model": "^1.4.1",
14+
"aws-sdk": "^2.326.0"
15+
}
16+
}

01/lambda/custom/util.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const AWS = require('aws-sdk');
2+
3+
const s3SigV4Client = new AWS.S3({
4+
signatureVersion: 'v4'
5+
});
6+
7+
module.exports.getS3PreSignedUrl = function getS3PreSignedUrl(s3ObjectKey) {
8+
9+
const bucketName = process.env.S3_PERSISTENCE_BUCKET;
10+
const s3PreSignedUrl = s3SigV4Client.getSignedUrl('getObject', {
11+
Bucket: bucketName,
12+
Key: s3ObjectKey,
13+
Expires: 60*1 // the Expires is capped for 1 minute
14+
});
15+
console.log(`Util.s3PreSignedUrl: ${s3ObjectKey} URL ${s3PreSignedUrl}`);
16+
return s3PreSignedUrl;
17+
18+
}

01/models/en-US.json

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"interactionModel": {
3+
"languageModel": {
4+
"invocationName": "hello world",
5+
"intents": [
6+
{
7+
"name": "AMAZON.CancelIntent",
8+
"samples": []
9+
},
10+
{
11+
"name": "AMAZON.HelpIntent",
12+
"samples": []
13+
},
14+
{
15+
"name": "AMAZON.StopIntent",
16+
"samples": []
17+
},
18+
{
19+
"name": "HelloWorldIntent",
20+
"slots": [],
21+
"samples": [
22+
"hello",
23+
"how are you",
24+
"say hi world",
25+
"say hi",
26+
"hi",
27+
"say hello world",
28+
"say hello"
29+
]
30+
},
31+
{
32+
"name": "AMAZON.NavigateHomeIntent",
33+
"samples": []
34+
},
35+
{
36+
"name": "AMAZON.FallbackIntent",
37+
"samples": []
38+
}
39+
],
40+
"types": []
41+
}
42+
}
43+
}

02/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Part 2 - i18n, Interceptors, Error Handlers & Session Ended
2+
3+
## Milestones
4+
5+
1. **Developer Console**: adding an extra locale (es-ES, translated from en-US)
6+
2. **Code Tab**: Intent Reflector
7+
3. **Code Tab**: i18next dependency, sprintf, languageStrings (embedded)
8+
4. **Code Tab**: Request and Response Interceptors (loggers), Localization Interceptor (simplest, sprintf but no arrays)
9+
5. **Code Tab**: Attributes Manager, Request Attributes, requestAttributes.t and requestAttributes.t with parameters (sprintf)

0 commit comments

Comments
 (0)