├── .gitignore ├── speechAssets ├── IntentSchema.json └── SampleUtterances.txt ├── README.md └── src ├── index.js └── AlexaSkill.js /.gitignore: -------------------------------------------------------------------------------- 1 | Archive.zip 2 | src/node_modules 3 | -------------------------------------------------------------------------------- /speechAssets/IntentSchema.json: -------------------------------------------------------------------------------- 1 | { 2 | "intents": [ 3 | { 4 | "intent": "SecurityCameraIntent", 5 | "slots": [] 6 | }, 7 | { 8 | "intent": "HelpIntent", 9 | "slots": [] 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /speechAssets/SampleUtterances.txt: -------------------------------------------------------------------------------- 1 | SecurityCameraIntent record 2 | SecurityCameraIntent start recording 3 | SecurityCameraIntent record video 4 | SecurityCameraIntent record a video 5 | SecurityCameraIntent take a video 6 | SecurityCameraIntent video 7 | SecurityCameraIntent what is happening 8 | 9 | HelpIntent help 10 | HelpIntent help me 11 | HelpIntent what can I ask you 12 | HelpIntent get help 13 | HelpIntent to help 14 | HelpIntent to help me 15 | HelpIntent what commands can I ask 16 | HelpIntent what commands can I say 17 | HelpIntent what can I do 18 | HelpIntent what can I use this for 19 | HelpIntent what questions can I ask 20 | HelpIntent what can you do 21 | HelpIntent what do you do 22 | HelpIntent how do I use you 23 | HelpIntent how can I use you 24 | HelpIntent what can you tell me -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #AWS Lambda function for Alexa - Integrates wtih IFTTT Maker Chanel and Homeboy security Camera 4 | 5 | 6 | ## Setup 7 | `cd src/` 8 | then 9 | `npm install require` to get the one dependecy — require 10 | 11 | Then create your Alexa app through the [Amazon Developer Portal](https://developer.amazon.com). You will need the AppId from a screen there pasted into the src/index.js file before you package your code into a zip and upload it to Lamda. You will need to set up the [IFTTT maker channel](https://ifttt.com/maker) also. Copy the secret key from there into the index.js file as well. 12 | 13 | When you create a zip of the src/ directory for uploading to Lambda, include the node_modules/ directory in the zip. 14 | 15 | Here are the detailed instructions. 16 | 17 | To run this example skill you need to do two things. The first is to deploy the example code in lambda, and the second is to configure the Alexa skill to use Lambda. 18 | 19 | ### AWS Lambda Setup 20 | 1. Go to the AWS Console and click on the Lambda link. Note: ensure you are in us-east or you won't be able to use Alexa with Lambda. 21 | 2. Click on the Create a Lambda Function or Get Started Now button. 22 | 3. Name the Lambda Function "Hello_World_Example_Skill". 23 | 4. Go to the the src directory, select all files and then create a zip file, make sure the zip file does not contain the src directory itself, otherwise Lambda function will not work. 24 | 5. Upload the .zip file to the Lambda 25 | 6. Keep the Handler as index.handler (this refers to the main js file in the zip). 26 | 7. Create a basic execution role and click create. 27 | 8. Return to the main Lambda page, and click on "Actions" -> "Add Event Source" 28 | 9. Choose Alexa Skills Kit and click submit. 29 | 10. Click on your Lambda function name and copy the ARN to be used later in the Alexa Skill Setup 30 | 31 | ### Alexa Skill Setup 32 | 1. Go to the Alexa Console (https://developer.amazon.com/edw/home.html) and click Add a New Skill. 33 | 2. Set "SecurityCamera" as the skill name and "security camera" as the invocation name, this is what is used to activate your skill. For example you would say: "Alexa, tell security camera to record a video" 34 | 3. Select the Lambda ARN for the skill Endpoint and paste the ARN copied from above. Click Next. 35 | 4. Copy the Intent Schema from the included IntentSchema.json. 36 | 5. Copy the Sample Utterances from the included SampleUtterances.txt. Click Next. 37 | 6. [optional] go back to the skill Information tab and copy the appId. Paste the appId into the index.js file for the variable APP_ID, 38 | then update the lambda source zip file with this change and upload to lambda again, this step makes sure the lambda function only serves request from authorized source. 39 | 7. You are now able to start testing your sample skill! You should be able to go to the Echo webpage (http://echo.amazon.com/#skills) and see your skill enabled. 40 | 8. In order to test it, try to say some of the Sample Utterances from the Examples section below. 41 | 9. Your skill is now saved and once you are finished testing you can continue to publish your skill. 42 | 43 | ## Examples 44 | User: "Alexa, tell Security Camera to record a video" 45 | Alexa: "OK..." -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Alexa SDK for JavaScript v1.0.00 2 | // Copyright (c) 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. Use is subject to license terms. 3 | 4 | /** 5 | * This simple sample has no external dependencies or session management, and shows the most basic 6 | * example of how to create a Lambda function for handling Alexa Skill requests. 7 | * 8 | * Examples: 9 | * One-shot model: 10 | * User: "Alexa, tell Greeter to say hello" 11 | * Alexa: "Hello World!" 12 | */ 13 | 14 | /** 15 | * App ID for the skill 16 | */ 17 | var APP_ID = null; //replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]"; 18 | var EVENT_NAME = 'camera'; 19 | var IFTTT_SECRET = null; //replace with the token from setting up the IFTTT Maker channel. 20 | var IFTTT_URL = 'https://maker.ifttt.com/trigger/' + EVENT_NAME + '/with/key/' + IFTTT_TOKEN; 21 | /** 22 | * The AlexaSkill prototype and helper functions 23 | */ 24 | var AlexaSkill = require('./AlexaSkill'); 25 | var request = require('request'); 26 | /** 27 | * HelloWorld is a child of AlexaSkill. 28 | * To read more about inheritance in JavaScript, see the link below. 29 | * 30 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance 31 | */ 32 | var HelloWorld = function () { 33 | AlexaSkill.call(this, APP_ID); 34 | }; 35 | 36 | // Extend AlexaSkill 37 | HelloWorld.prototype = Object.create(AlexaSkill.prototype); 38 | HelloWorld.prototype.constructor = HelloWorld; 39 | 40 | HelloWorld.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) { 41 | console.log("HelloWorld onSessionStarted requestId: " + sessionStartedRequest.requestId 42 | + ", sessionId: " + session.sessionId); 43 | // any initialization logic goes here 44 | }; 45 | 46 | HelloWorld.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) { 47 | console.log("HelloWorld onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId); 48 | var speechOutput = "Welcome to the security camera. you can say record video."; 49 | response.ask(speechOutput); 50 | }; 51 | 52 | HelloWorld.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) { 53 | console.log("HelloWorld onSessionEnded requestId: " + sessionEndedRequest.requestId 54 | + ", sessionId: " + session.sessionId); 55 | // any cleanup logic goes here 56 | }; 57 | 58 | HelloWorld.prototype.intentHandlers = { 59 | // register custom intent handlers 60 | SecurityCameraIntent: function (intent, session, response) { 61 | 62 | var thatResponse = response; 63 | var testRequest = { 64 | url: IFTTT_URL 65 | }; 66 | request(testRequest, function (error, response, body) { 67 | if (error || response.statusCode != 200) { 68 | console.log("error: failed to send notification to IFTTT") 69 | thatResponse.tell("There was a small problem with the request to ifttt.com"); 70 | return; 71 | } 72 | console.log("success - sent notification"); 73 | thatResponse.tell("OK, I just started your security camera. You should get a new video in a few seconds."); 74 | return; 75 | }); 76 | 77 | }, 78 | HelpIntent: function (intent, session, response) { 79 | response.ask("You can say hello to me!"); 80 | } 81 | }; 82 | 83 | // Create the handler that responds to the Alexa Request. 84 | exports.handler = function (event, context) { 85 | // Create an instance of the HelloWorld skill. 86 | var helloWorld = new HelloWorld(); 87 | helloWorld.execute(event, context); 88 | }; 89 | 90 | -------------------------------------------------------------------------------- /src/AlexaSkill.js: -------------------------------------------------------------------------------- 1 | // Alexa SDK for JavaScript v1.0.00 2 | // Copyright (c) 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. Use is subject to license terms. 3 | 'use strict'; 4 | function AlexaSkill(appId) { 5 | this._appId = appId; 6 | } 7 | 8 | AlexaSkill.prototype.requestHandlers = { 9 | LaunchRequest: function (event, context, response) { 10 | this.eventHandlers.onLaunch.call(this, event.request, event.session, response); 11 | }, 12 | 13 | IntentRequest: function (event, context, response) { 14 | this.eventHandlers.onIntent.call(this, event.request, event.session, response); 15 | }, 16 | 17 | SessionEndedRequest: function (event, context) { 18 | this.eventHandlers.onSessionEnded(event.request, event.session); 19 | context.succeed(); 20 | } 21 | }; 22 | 23 | /** 24 | * Override any of the eventHandlers as needed 25 | */ 26 | AlexaSkill.prototype.eventHandlers = { 27 | /** 28 | * Called when the session starts. 29 | * Subclasses could have overriden this function to open any necessary resources. 30 | */ 31 | onSessionStarted: function (sessionStartedRequest, session) { 32 | }, 33 | 34 | /** 35 | * Called when the user launches the skill without specifying what they want. 36 | * The subclass must override this function and provide feedback to the user. 37 | */ 38 | onLaunch: function (launchRequest, session, response) { 39 | throw "onLaunch should be overriden by subclass"; 40 | }, 41 | 42 | /** 43 | * Called when the user specifies an intent. 44 | */ 45 | onIntent: function (intentRequest, session, response) { 46 | var intent = intentRequest.intent, 47 | intentName = intentRequest.intent.name, 48 | intentHandler = this.intentHandlers[intentName]; 49 | if (intentHandler) { 50 | console.log('dispatch intent = ' + intentName); 51 | intentHandler.call(this, intent, session, response); 52 | } else { 53 | throw 'Unsupported intent = ' + intentName; 54 | } 55 | }, 56 | 57 | /** 58 | * Called when the user ends the session. 59 | * Subclasses could have overriden this function to close any open resources. 60 | */ 61 | onSessionEnded: function (sessionEndedRequest, session) { 62 | } 63 | }; 64 | 65 | /** 66 | * Subclasses should override the intentHandlers with the functions to handle specific intents. 67 | */ 68 | AlexaSkill.prototype.intentHandlers = {}; 69 | 70 | AlexaSkill.prototype.execute = function (event, context) { 71 | try { 72 | console.log("session applicationId: " + event.session.application.applicationId); 73 | 74 | // Validate that this request originated from authorized source. 75 | if (this._appId && event.session.application.applicationId !== this._appId) { 76 | console.log("The applicationIds don't match : " + event.session.application.applicationId + " and " 77 | + this._appId); 78 | throw "Invalid applicationId"; 79 | } 80 | 81 | if (!event.session.attributes) { 82 | event.session.attributes = {}; 83 | } 84 | 85 | if (event.session.new) { 86 | this.eventHandlers.onSessionStarted(event.request, event.session); 87 | } 88 | 89 | // Route the request to the proper handler which may have been overriden. 90 | var requestHandler = this.requestHandlers[event.request.type]; 91 | requestHandler.call(this, event, context, new Response(context, event.session)); 92 | } catch (e) { 93 | console.log("Unexpected exception " + e); 94 | context.fail(e); 95 | } 96 | }; 97 | 98 | var Response = function (context, session) { 99 | this._context = context; 100 | this._session = session; 101 | }; 102 | 103 | Response.prototype = (function () { 104 | var buildSpeechletResponse = function (options) { 105 | var alexaResponse = { 106 | outputSpeech: { 107 | type: 'PlainText', 108 | text: options.output 109 | }, 110 | shouldEndSession: options.shouldEndSession 111 | }; 112 | if (options.reprompt) { 113 | alexaResponse.reprompt = { 114 | outputSpeech: { 115 | type: 'PlainText', 116 | text: options.reprompt 117 | } 118 | }; 119 | } 120 | if (options.cardTitle && options.cardContent) { 121 | alexaResponse.card = { 122 | type: "Simple", 123 | title: options.cardTitle, 124 | content: options.cardContent 125 | }; 126 | } 127 | var returnResult = { 128 | version: '1.0', 129 | response: alexaResponse 130 | }; 131 | if (options.session && options.session.attributes) { 132 | returnResult.sessionAttributes = options.session.attributes; 133 | } 134 | return returnResult; 135 | }; 136 | 137 | return { 138 | tell: function (speechOutput) { 139 | this._context.succeed(buildSpeechletResponse({ 140 | session: this._session, 141 | output: speechOutput, 142 | shouldEndSession: true 143 | })); 144 | }, 145 | tellWithCard: function (speechOutput, cardTitle, cardContent) { 146 | this._context.succeed(buildSpeechletResponse({ 147 | session: this._session, 148 | output: speechOutput, 149 | cardTitle: cardTitle, 150 | cardContent: cardContent, 151 | shouldEndSession: true 152 | })); 153 | }, 154 | ask: function (speechOutput, repromptSpeech) { 155 | this._context.succeed(buildSpeechletResponse({ 156 | session: this._session, 157 | output: speechOutput, 158 | reprompt: repromptSpeech, 159 | shouldEndSession: false 160 | })); 161 | }, 162 | askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) { 163 | this._context.succeed(buildSpeechletResponse({ 164 | session: this._session, 165 | output: speechOutput, 166 | reprompt: repromptSpeech, 167 | cardTitle: cardTitle, 168 | cardContent: cardContent, 169 | shouldEndSession: false 170 | })); 171 | } 172 | }; 173 | })(); 174 | 175 | module.exports = AlexaSkill; --------------------------------------------------------------------------------