vincent wong
Published © GPL3+

Inspirational Quote

Ask Alexa for an Inspirational Quote.

BeginnerFull instructions provided858

Things used in this project

Hardware components

Amazon Echo
Amazon Alexa Amazon Echo
×1

Software apps and online services

AWS Lambda
Amazon Web Services AWS Lambda
Alexa Skills Kit
Amazon Alexa Alexa Skills Kit
Forismatic API

Story

Read more

Code

AlexaSkill.js

JavaScript
/**
    Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at

        http://aws.amazon.com/apache2.0/

    or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

'use strict';

function AlexaSkill(appId) {
    this._appId = appId;
}

AlexaSkill.speechOutputType = {
    PLAIN_TEXT: 'PlainText',
    SSML: 'SSML'
}

AlexaSkill.prototype.requestHandlers = {
    LaunchRequest: function (event, context, response) {
        this.eventHandlers.onLaunch.call(this, event.request, event.session, response);
    },

    IntentRequest: function (event, context, response) {
        this.eventHandlers.onIntent.call(this, event.request, event.session, response);
    },

    SessionEndedRequest: function (event, context) {
        this.eventHandlers.onSessionEnded(event.request, event.session);
        context.succeed();
    }
};

/**
 * Override any of the eventHandlers as needed
 */
AlexaSkill.prototype.eventHandlers = {
    /**
     * Called when the session starts.
     * Subclasses could have overriden this function to open any necessary resources.
     */
    onSessionStarted: function (sessionStartedRequest, session) {
    },

    /**
     * Called when the user invokes the skill without specifying what they want.
     * The subclass must override this function and provide feedback to the user.
     */
    onLaunch: function (launchRequest, session, response) {
        throw "onLaunch should be overriden by subclass";
    },

    /**
     * Called when the user specifies an intent.
     */
    onIntent: function (intentRequest, session, response) {
        var intent = intentRequest.intent,
            intentName = intentRequest.intent.name,
            intentHandler = this.intentHandlers[intentName];
        if (intentHandler) {
            console.log('dispatch intent = ' + intentName);
            intentHandler.call(this, intent, session, response);
        } else {
            throw 'Unsupported intent = ' + intentName;
        }
    },

    /**
     * Called when the user ends the session.
     * Subclasses could have overriden this function to close any open resources.
     */
    onSessionEnded: function (sessionEndedRequest, session) {
    }
};

/**
 * Subclasses should override the intentHandlers with the functions to handle specific intents.
 */
AlexaSkill.prototype.intentHandlers = {};

AlexaSkill.prototype.execute = function (event, context) {
    try {
        console.log("session applicationId: " + event.session.application.applicationId);

        // Validate that this request originated from authorized source.
        if (this._appId && event.session.application.applicationId !== this._appId) {
            console.log("The applicationIds don't match : " + event.session.application.applicationId + " and "
                + this._appId);
            throw "Invalid applicationId";
        }

        if (!event.session.attributes) {
            event.session.attributes = {};
        }

        if (event.session.new) {
            this.eventHandlers.onSessionStarted(event.request, event.session);
        }

        // Route the request to the proper handler which may have been overriden.
        var requestHandler = this.requestHandlers[event.request.type];
        requestHandler.call(this, event, context, new Response(context, event.session));
    } catch (e) {
        console.log("Unexpected exception " + e);
        context.fail(e);
    }
};

var Response = function (context, session) {
    this._context = context;
    this._session = session;
};

function createSpeechObject(optionsParam) {
    if (optionsParam && optionsParam.type === 'SSML') {
        return {
            type: optionsParam.type,
            ssml: optionsParam.speech
        };
    } else {
        return {
            type: optionsParam.type || 'PlainText',
            text: optionsParam.speech || optionsParam
        }
    }
}

Response.prototype = (function () {
    var buildSpeechletResponse = function (options) {
        var alexaResponse = {
            outputSpeech: createSpeechObject(options.output),
            shouldEndSession: options.shouldEndSession
        };
        if (options.reprompt) {
            alexaResponse.reprompt = {
                outputSpeech: createSpeechObject(options.reprompt)
            };
        }
        if (options.cardTitle && options.cardContent) {
            alexaResponse.card = {
                type: "Simple",
                title: options.cardTitle,
                content: options.cardContent
            };
        }
        var returnResult = {
                version: '1.0',
                response: alexaResponse
        };
        if (options.session && options.session.attributes) {
            returnResult.sessionAttributes = options.session.attributes;
        }
        return returnResult;
    };

    return {
        tell: function (speechOutput) {
            this._context.succeed(buildSpeechletResponse({
                session: this._session,
                output: speechOutput,
                shouldEndSession: true
            }));
        },
        tellWithCard: function (speechOutput, cardTitle, cardContent) {
            this._context.succeed(buildSpeechletResponse({
                session: this._session,
                output: speechOutput,
                cardTitle: cardTitle,
                cardContent: cardContent,
                shouldEndSession: true
            }));
        },
        ask: function (speechOutput, repromptSpeech) {
            this._context.succeed(buildSpeechletResponse({
                session: this._session,
                output: speechOutput,
                reprompt: repromptSpeech,
                shouldEndSession: false
            }));
        },
        askWithCard: function (speechOutput, repromptSpeech, cardTitle, cardContent) {
            this._context.succeed(buildSpeechletResponse({
                session: this._session,
                output: speechOutput,
                reprompt: repromptSpeech,
                cardTitle: cardTitle,
                cardContent: cardContent,
                shouldEndSession: false
            }));
        }
    };
})();

module.exports = AlexaSkill;

index.js

JavaScript
'use strict';
/**
 * App ID for the skill
 */
var APP_ID = "your app id"; 

var http = require("http");

var optionsGet = {
	host : 'api.forismatic.com', 
    port : 80,
    path : '', 
    method : 'GET'
};

/**
 * The AlexaSkill prototype and helper functions
 */
var AlexaSkill = require('./AlexaSkill');


var Inspire = function () {
    AlexaSkill.call(this, APP_ID);
};

// Extend AlexaSkill
Inspire.prototype = Object.create(AlexaSkill.prototype);
Inspire.prototype.constructor = Inspire;

Inspire.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    console.log("Inspire onSessionStarted requestId: " + sessionStartedRequest.requestId
        + ", sessionId: " + session.sessionId);

    // any session init logic would go here
};

Inspire.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    console.log("Inspire onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    getQuote(launchRequest, session, response);
};

Inspire.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    console.log("Inspire onSessionEnded requestId: " + sessionEndedRequest.requestId
        + ", sessionId: " + session.sessionId);

    // any session cleanup logic would go here
};

Inspire.prototype.intentHandlers = {
    "GetQuote": function (intent, session, response) {
        getQuote(intent, session, response);
    },

    "AMAZON.HelpIntent": function (intent, session, response) {
        helpTheUser(intent, session, response);
    },

    "AMAZON.StopIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    },

    "AMAZON.CancelIntent": function (intent, session, response) {
        var speechOutput = "Goodbye";
        response.tell(speechOutput);
    }
};

// return a inspirational quote with REST API
function getQuote(intent, session, response) {
    var speechText = "",
        repromptText = "",
        speechOutput,
        repromptOutput;

		optionsGet.path = "/api/1.0/?method=getQuote&key=457653&format=json&lang=en";
		
		// do the GET request
		var reqGet = http.request(optionsGet, function(res) {
			console.log("statusCode: ", res.statusCode);
			// uncomment it for header details
			// console.log("headers: ", res.headers);
		 
		 
			res.on('data', function(d) {
				console.info('GET result:\n');
				process.stdout.write(d);
				console.info('\n\nCall completed');

				var obj = JSON.parse(d);
				speechText = obj.quoteText;
				if (speechText == "[]") {
					speechText = "Sorry.  There in inspirational quote.  Please try again later.";
				} 
				
				repromptText = "<speak>" + obj.quoteText + "</speak>";
				
				speechOutput = {
					speech: speechText,
					type: AlexaSkill.speechOutputType.PLAIN_TEXT
				};
				repromptOutput = {
					speech: repromptText,
					type: AlexaSkill.speechOutputType.SSML
				};
				
				response.tell(speechText);
				
				// response.ask(speechOutput, repromptOutput);
			});
		 
		});
		 
		reqGet.end();
		reqGet.on('error', function(e) {
			console.error(e);

			speechText = "Sorry.  There in inspirational quote.  Please try again later.";
			repromptText = "Sorry.  There in inspirational quote.  Please try again later.";
			
			speechOutput = {
				speech: speechText,
				type: AlexaSkill.speechOutputType.PLAIN_TEXT
			};
			repromptOutput = {
				speech: repromptText,
				type: AlexaSkill.speechOutputType.SSML
			};
			response.tell(speechOutput, repromptOutput);

		});
	
}


/**
 * Instructs the user on how to interact with this skill.
 */
function helpTheUser(intent, session, response) {
    var speechText = "You can ask for an inspirational quote. " +
        "Now, what can I help you with?";
    var repromptText = "<speak> I'm sorry I didn't understand that. You can ask for an inspiration quote. " +
        "Now, what can I help you with? </speak>";

    var speechOutput = {
        speech: speechText,
        type: AlexaSkill.speechOutputType.PLAIN_TEXT
    };
    var repromptOutput = {
        speech: repromptText,
        type: AlexaSkill.speechOutputType.SSML
    };
    response.ask(speechOutput, repromptOutput);
}

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
    var inspire = new Inspire();
    inspire.execute(event, context);
};

IntentSchema.json

JSON
{
  "intents": [
    {
      "intent": "GetQuote"
    }
  ]
}

SampleUtterances.txt

Plain text
GetQuote ask inspire quote
GetQuote ask inspire quote to tell me an inspirational quote
GetQuote ask inspire quote for an inspirational quote
GetQuote ask inspire quote for inspirational quote
GetQuote ask inspire quote an inspirational quote
GetQuote ask inspire quote inspirational quote
GetQuote an inspirational quote
GetQuote tell me an inspirational quote

Credits

vincent wong

vincent wong

80 projects • 203 followers

Comments