Things used in this project

Hardware components:
Echo
Amazon Alexa Amazon Echo
×1
Software apps and online services:
Screen%20shot%202015 07 20%20at%206.10.26%20pm
Amazon Web Services AWS Lambda
Yahoo Query Language

Schematics

Alexa AppKit Architecture
Building spoken language apps and experiences for amazon echo 18 638

Code

IntentSchema.jsonJSON
{
  "intents": [
    {
      "intent": "DxsIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    }
  ]
}
SampleUtterances.txtPlain text
DxsIntent Hello
DxsIntent Tell me
DxsIntent How many active challenges has Hackster
DxsIntent There are how many active challenges on Hackster
DxsIntent Number of active challenges
atom.jsonJSON
Atom RSS XML converted to JSON
{
 "query": {
  "count": 1,
  "created": "2016-04-17T17:47:22Z",
  "lang": "es-ES",
  "results": {
   "feed": {
    "lang": "en-US",
    "xmlns": "http://www.w3.org/2005/Atom",
    "id": "tag:www.hackster.io,2005:/challenges?format=atom",
    "link": [
     {
      "href": "https://www.hackster.io",
      "rel": "alternate",
      "type": "text/html"
     },
     {
      "href": "https://www.hackster.io/challenges?format=atom",
      "rel": "self",
      "type": "application/atom+xml"
     }
    ],
    "title": "Active hardware contests",
    "updated": "2016-04-17T17:19:46Z",
    "entry": [
     {
      "id": "tag:www.hackster.io,2005:Challenge/35",
      "published": [
       "2016-04-08T18:18:20Z",
       "2016-04-15T10:00:00Z"
      ],
      "updated": [
       "2016-04-17T17:19:46Z",
       "2016-04-17T17:19:46Z"
      ],
      "link": [
       {
        "href": "https://www.hackster.io/challenges/sparkfun-blynk-contest",
        "rel": "alternate",
        "type": "text/html"
       },
       {
        "href": "https://hackster.imgix.net/uploads/cover_image/file/141974/09-07-Action-Battery.jpg?w=450&h=130&fit=min&fm=jpg",
        "rel": "enclosure",
        "type": "image/jpeg"
       }
      ],
      "url": "https://www.hackster.io/challenges/sparkfun-blynk-contest",
      "title": "IoT For Everyone!",
      "author": [
       {
        "name": "SparkFun",
        "url": "https://www.hackster.io/sparkfun"
       },
       {
        "name": "Blynk",
        "url": "https://www.hackster.io/blynk"
       }
      ]
     },
     {
      "id": "tag:www.hackster.io,2005:Challenge/32",
      "published": [
       "2016-02-15T23:07:46Z",
       "2016-03-11T03:00:00Z"
      ],
      "updated": [
       "2016-04-17T02:20:46Z",
       "2016-04-17T02:20:46Z"
      ],
      "link": [
       {
        "href": "https://www.hackster.io/challenges/KinetisFlexIO",
        "rel": "alternate",
        "type": "text/html"
       },
       {
        "href": "https://hackster.imgix.net/uploads/cover_image/file/132363/2800x800_text.png?w=450&h=130&fit=min",
        "rel": "enclosure",
        "type": "image/jpeg"
       }
      ],
      "url": "https://www.hackster.io/challenges/KinetisFlexIO",
      "title": "Flex Your Mind with Kinetis FlexIO",
      "content": "Go To The Next Level - Learn Embedded Design!",
      "author": {
       "name": "NXP",
       "url": "https://www.hackster.io/NXP"
      }
     },
     {
      "id": "tag:www.hackster.io,2005:Challenge/34",
      "published": [
       "2016-03-31T19:41:13Z",
       "2016-04-08T15:00:00Z"
      ],
      "updated": [
       "2016-04-17T15:20:32Z",
       "2016-04-17T15:20:32Z"
      ],
      "link": [
       {
        "href": "https://www.hackster.io/challenges/amazon-alexa-skill-contest-one",
        "rel": "alternate",
        "type": "text/html"
       },
       {
        "href": "https://hackster.imgix.net/uploads/cover_image/file/140777/header-2.jpg?w=450&h=130&fit=min&fm=jpg",
        "rel": "enclosure",
        "type": "image/jpeg"
       }
      ],
      "url": "https://www.hackster.io/challenges/amazon-alexa-skill-contest-one",
      "title": "Hey Alexa! The Amazon Alexa Skill Contest Series",
      "content": "Natural voice interfaces are the next major disruption in computing. Be part of what's next!",
      "author": {
       "name": "Alexa",
       "url": "https://www.hackster.io/amazon-alexa"
      }
     },
     {
      "id": "tag:www.hackster.io,2005:Challenge/27",
      "published": [
       "2015-10-22T00:38:18Z",
       "2016-02-05T16:00:00Z"
      ],
      "updated": [
       "2016-04-16T15:04:06Z",
       "2016-04-16T15:04:06Z"
      ],
      "link": [
       {
        "href": "https://www.hackster.io/challenges/CI20",
        "rel": "alternate",
        "type": "text/html"
       },
       {
        "href": "https://hackster.imgix.net/uploads/cover_image/file/85748/shutterstock_274028849.jpg?w=450&h=130&fit=min&fm=jpg",
        "rel": "enclosure",
        "type": "image/jpeg"
       }
      ],
      "url": "https://www.hackster.io/challenges/CI20",
      "title": "Terminate the competition with Creator Ci20!",
      "author": {
       "name": "Creator",
       "url": "https://www.hackster.io/creator"
      }
     }
    ]
   }
  }
 }
}
AlexaSkill.jsonJavaScript
/**
    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.jsonJavaScript
/**
    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.
*/

/**
 * This simple sample has no external dependencies or session management, and shows the most basic
 * example of how to create a Lambda function for handling Alexa Skill requests.
 *
 * Examples:
 * One-shot model:
 *  User: "Alexa, tell Greeter to say hello"
 *  Alexa: "Hello World!"
 */

/**
 * App ID for the skill
 */
var APP_ID = undefined; //replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";

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


/**
 * DxsSkill is a child of AlexaSkill.
 * To read more about inheritance in JavaScript, see the link below.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
 */
var DxsSkill = function () {
    AlexaSkill.call(this, APP_ID);
};

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

DxsSkill.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
    console.log("DxsSkill onSessionStarted requestId: " + sessionStartedRequest.requestId
        + ", sessionId: " + session.sessionId);
    // any initialization logic goes here
};

DxsSkill.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
    console.log("DxsSkill onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
    var speechOutput = "Welcome to the Hackster Active Challenges. You can say: Hello, or ask me: How many active challenges has Hackster";
    var repromptText = "You can say: Hello, or ask me: How many active challenges has Hackster";
    response.ask(speechOutput, repromptText);
};

DxsSkill.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
    console.log("DxsSkill onSessionEnded requestId: " + sessionEndedRequest.requestId
        + ", sessionId: " + session.sessionId);
    // any cleanup logic goes here
};

DxsSkill.prototype.intentHandlers = {
    // register custom intent handlers
    "DxsIntent": function (intent, session, response) {
        
        var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%20%3D%20'https%3A%2F%2Fwww.hackster.io%2Fchallenges%3Fformat%3Datom'&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";

        var res = request('GET', url );
        var data = JSON.parse(res.getBody('utf8'));
        //console.log(data.query.results.feed.entry.length);
        if(data.query.results.feed.entry.length > 0){
            var contests = []; var nc=0;
            var te = data.query.results.feed.entry.length;
            for(var i in data.query.results.feed.entry){ nc++;
                var contest_txt = '';
                var entry = data.query.results.feed.entry[i];
                //console.log(entry);
                var url = entry.url;
                var title = entry.title;        
                //console.log(title);
                var authors = entry.author; //console.log(authors);
                var authors_name = [];
                if(authors){
                    if(Array.isArray(authors)){
                        //console.log('xxxxx');
                        for(var j in authors){
                            var a = authors[j]; //console.log(a);
                            var n = a.name;
                            authors_name.push(n);
                        }
                    }else{
                        var a = authors;                
                        //console.log('+++');
                        //console.log(a);
                        var n = a.name;
                        authors_name.push(n)
                    }
                }
                contest_txt += nc + '. ';
                contest_txt += title;
                if(authors) contest_txt += ' by ';
                contest_txt += authors_name.join(', ');
                contest_txt += '.';
                
                contests.push(contest_txt);
            }
            //console.log(contests);
            var contests_txt = contests.join(' ');

            var speech = 'There ';
                speech+= (te>1)?'are ':'is ';
                speech+= te;
                speech+= ' active challenges';
                speech+= (te>1)?'s':'';
                speech+= ': ';
                speech+= contests_txt;

        }else{
            var speech = 'No active challenges';
        }                
        //console.log(speech);
        
        response.tellWithCard(speech, "Active Challenges", speech);
        
    },
    "AMAZON.HelpIntent": function (intent, session, response) {
        response.ask("You can ask me: How many active challenges has Hackster", "You can ask me: How many active challenges has Hackster");
    }
};

// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {    
    var dxsSkill = new DxsSkill();
    dxsSkill.execute(event, context);
};
test.jsJavaScript
var request = require('sync-request');

var url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%20%3D%20'https%3A%2F%2Fwww.hackster.io%2Fchallenges%3Fformat%3Datom'&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";

var res = request('GET', url );
var data = JSON.parse(res.getBody('utf8'));
//console.log(data.query.results.feed.entry.length);
if(data.query.results.feed.entry.length > 0){
	var contests = []; var nc=0;
	var te = data.query.results.feed.entry.length;
	for(var i in data.query.results.feed.entry){ nc++;
		var contest_txt = '';
		var entry = data.query.results.feed.entry[i];
		//console.log(entry);
		var url = entry.url;
		var title = entry.title;		
		//console.log(title);
		var authors = entry.author;		
		var authors_name = [];
		if(Array.isArray(authors)){
			for(var j in authors){
				var a = authors[j];
				var n = a.name;
				authors_name.push(n);
			}
		}else{
			var a = authors;
			var n = a.name;
			authors_name.push(n)
		}

		contest_txt += nc + '. ';
		contest_txt += title;
		contest_txt += ' by ';
		contest_txt += authors_name.join(', ');
		contest_txt += '.';
		
		contests.push(contest_txt);
	}
	//console.log(contests);
	var contests_txt = contests.join(' ');

	var speech = 'There ';
		speech+= (te>1)?'are ':'is ';
		speech+= te;
		speech+= ' active contest';
		speech+= (te>1)?'s':'';
		speech+= ': ';
		speech+= contests_txt;

}else{
	var speech = 'No active contests';
}

console.log(speech);
console.log('end');

Credits

Replications

Did you replicate this project? Share it!

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Similar projects you might like

Personal Healthcare Assistant PHA
Intermediate
  • 2,532
  • 119

Full instructions

Wearable for monitoring the health condition of patients who have suffered or are in risk of having a cardiac arrest.

Convo-Care: Alexa-Controlled E-Health App
Intermediate
  • 295
  • 8

Protip

Convo-Care provides a better e-health experience through a conversational UI.

OIKOS
Intermediate
  • 303
  • 8

Work in progress

OIKOS is a smart social-connected home for everyone. Our goal is to put the society in connection with homeless through IoT.

OIKOS

OIKOS NGO TEAM

Where'sMyPhone
Intermediate
  • 186
  • 3

Ever lose your phone under the couch? Find any mobile phone in seconds with Where'sMyPhone.

Smart and Safe Cabinets
Intermediate
  • 485
  • 10

Full instructions

With 41% of poisonings happening to children under 4, more needs to be done. We use Amazon Alexa and Intel IoT to lock and unlock cabinets.

Smart and Safe Cabinets

Magic Smoke Replacement Team

Let There Be Smart Light!
Intermediate
  • 314
  • 4

Work in progress

A solution to identify and report city street lights that are not working and need to be repaired.

Let There Be Smart Light!

Team The Ravishers

ProjectsCommunitiesContestsLiveJobsFree StoreBlogAdd projectSign up / Login
Respect project