MetaView
Published © Apache-2.0

Alexa Skill: ISS Finder

A multilanguage Alexa skill with nested API calls.

IntermediateShowcase (no instructions)2 hours686
Alexa Skill: ISS Finder

Story

Read more

Code

Source code

JavaScript
Change UserID in geonames.org call (line 103) with your own registered user name.
/* eslint-disable  func-names */
/* eslint quote-props: ["error", "consistent"]*/
/**
 * This sample demonstrates a simple skill built with the Amazon Alexa Skills
 * nodejs skill development kit.
 * This sample supports multiple lauguages. (en-US, en-GB, de-DE).
 * The Intent Schema, Custom Slots and Sample Utterances for this skill, as well
 * as testing instructions are located at https://github.com/alexa/skill-sample-nodejs-fact
 **/

'use strict';

const http = require('http');
const https = require('https');
const Alexa = require('alexa-sdk');

const APP_ID = undefined;  // TODO replace with your app ID (OPTIONAL).

const languageStrings = {
    'en-GB': {
        translation: {
            SKILL_NAME: 'I.S.S. Finder',
            FIND_ISS_MESSAGE: "Just now, the I.S.S. is over ",
            WHEN_ISS_MESSAGE1: "Next time the I.S.S. is over ",
            WHEN_ISS_MESSAGE2: ", on ",
            HELP_MESSAGE: 'You can say where is the I.S.S., or, when is the I.S.S. over New York, or, you can say exit... What can I help you with?',
            HELP_REPROMPT: 'What can I help you with?',
            STOP_MESSAGE: 'Goodbye!',
        },
    },
    'en-US': {
        translation: {
            SKILL_NAME: 'I.S.S. Finder',
            FIND_ISS_MESSAGE: "Just now, the I.S.S. is over ",
            WHEN_ISS_MESSAGE1: "Next time the I.S.S. is over ",
            WHEN_ISS_MESSAGE2: ", on ",
            HELP_MESSAGE: 'You can say find the I.S.S., or, when is the I.S.S. over London, or, you can say exit... What can I help you with?',
            HELP_REPROMPT: 'What can I help you with?',
            STOP_MESSAGE: 'Goodbye!',
        },
    },
    'de-DE': {
        translation: {
            SKILL_NAME: 'I.S.S. Finder',
            FIND_ISS_MESSAGE: "Die I.S.S. ist gerade über ",
            WHEN_ISS_MESSAGE1: "Nächstes Mal ist die I.S.S. über ",
            WHEN_ISS_MESSAGE2: ", am ",
            HELP_MESSAGE: 'Du kannst sagen wo ist die I.S.S., oder wann ist die I.S.S. über Berlin, oder, Du kannst exit sagen... Womit kann ich Dir helfen?',
            HELP_REPROMPT: 'Wie kann ich dir helfen?',
            STOP_MESSAGE: 'Auf Wiedersehen!',
        },
    },
};

var ensure_digits = function(value, digits) {
    var str = "" + value;
    while (str.length < digits) {
        str = "0" + str;
    }
    return str;
}

const handlers = {
    'LaunchRequest': function () {
        this.emit('GetISSPositionIntent');
    },
    'GetISSPositionIntent': function () {
        var url = "http://api.open-notify.org/iss-now.json";
        var skill_name = this.t('SKILL_NAME');
        var find_iss_msg = this.t('FIND_ISS_MESSAGE');
        var emit = this.emit;
        //console.log(url);
        http.get(url, function(res) {
            var body = '';
    
            res.on('data', function (chunk) {
                body += chunk;
            });
    
            res.on('end', function () {
                //console.log("Antwort erhalten ", body);

                var latidx = body.indexOf('"latitude"');
                var latstr = body.substring(latidx);
                latidx = latstr.indexOf(':');
                latstr = latstr.substring(latidx);
                latidx = latstr.indexOf('"');
                latstr = latstr.substring(latidx + 1);
                latidx = latstr.indexOf('"');
                latstr = latstr.substring(0, latidx);
                var lonidx = body.indexOf('"longitude"');
                var lonstr = body.substring(lonidx);
                lonidx = lonstr.indexOf(':');
                lonstr = lonstr.substring(lonidx);
                lonidx = lonstr.indexOf('"');
                lonstr = lonstr.substring(lonidx + 1);
                lonidx = lonstr.indexOf('"');
                lonstr = lonstr.substring(0, lonidx);
                //var stringResult = parseJson(body);
                var lat = 1 * latstr; //data['iss_position']['latitude'];
                var lon = 1 * lonstr; //data['iss_position']['longitude'];
                
                url = "http://api.geonames.org/extendedFindNearby?lat=" + lat + "&lng=" + lon + "&username=metaview";
                //console.log(url);
                http.get(url, function(res) {
                    var body = '';
            
                    res.on('data', function (chunk) {
                        body += chunk;
                    });
            
                    res.on('end', function () {
                        //console.log("Antwort erhalten ", body);
                        
                        var position = "unknown place.";

                       	if (body.indexOf('<ocean>') > 0) {
                    	    var idx = body.indexOf('<name>');
                    	    var str = body.substring(idx + 6);
                    	    idx = str.indexOf('</name>');
                    	    position = str.substring(0, idx);
                    	} else {
                	        var idx = body.indexOf("<countryName>");
                            var locstr = body.substring(idx + 13);
                            idx = locstr.indexOf("</countryName>");
                            var country = locstr.substring(0, idx);
                            idx = locstr.indexOf("<toponymName>");
                            locstr = locstr.substring(idx + 13);
                            idx = locstr.indexOf("</toponymName>");
                            var location = locstr.substring(0, idx);
                            position = location + " " + country;
                    	}
	
                        // Create speech output
                        const speechOutput = find_iss_msg + position;
                        emit(':tellWithCard', speechOutput, skill_name, position);
                    });
                }).on('error', function (e) {
                    console.log("Got error: ", e);
                });
            });
        }).on('error', function (e) {
            console.log("Got error: ", e);
        });
    },
    'GetISSFlyByIntent': function () {
        var skill_name = this.t('SKILL_NAME');
        var when_msg_1 = this.t('WHEN_ISS_MESSAGE1');
        var when_msg_2 = this.t('WHEN_ISS_MESSAGE2');
        var emit = this.emit;
        var state = this.event.request.intent.slots.state ? this.event.request.intent.slots.state.value : undefined;
        var town = this.event.request.intent.slots.town ? this.event.request.intent.slots.town.value : undefined;
        var gbstate = this.event.request.intent.slots.gbstate ? this.event.request.intent.slots.gbstate.value : undefined;
        var gbtown = this.event.request.intent.slots.gbtown ? this.event.request.intent.slots.gbtown.value : undefined;
        var destate = this.event.request.intent.slots.destate ? this.event.request.intent.slots.destate.value : undefined;
        var detown = this.event.request.intent.slots.detown ? this.event.request.intent.slots.detown.value : undefined;
        var atstate = this.event.request.intent.slots.atstate ? this.event.request.intent.slots.atstate.value : undefined;
        var attown = this.event.request.intent.slots.attown ? this.event.request.intent.slots.attown.value : undefined;
        var eutown = this.event.request.intent.slots.eutown ? this.event.request.intent.slots.eutown.value : undefined;

        var location = "";
        if (state) {
            location = state + ",US";
        } else if (town) {
            location = town + ",US";
        } else if (gbtown) {
            location = gbtown + ",GB";
        } else if (gbstate) {
            location = gbstate + ",GB";
        } else if (detown) {
            location = detown + ",DE";
        } else if (destate) {
            location = destate + ",DE";
        } else if (attown) {
            location = attown + ",AT";
        } else if (atstate) {
            location = atstate + ",AT";
        } else if (eutown) {
            location = eutown;
        } else {
            const speechOutput = this.t('HELP_MESSAGE');
            const reprompt = this.t('HELP_MESSAGE');
            this.emit(':ask', speechOutput, reprompt);
            return;
        }

        var url = "https://maps.googleapis.com/maps/api/geocode/json?address=" + location;
        https.get(url, function(res) {
            var body = '';
    
            res.on('data', function (chunk) {
                body += chunk;
            });
    
            res.on('end', function () {
                //console.log("Antwort erhalten ", body.length);

                var idx = body.indexOf("formatted_address");
                var addstr = body.substring(idx);
                idx = addstr.indexOf(":");
                addstr = addstr.substring(idx);
                idx = addstr.indexOf("\"");
                addstr = addstr.substring(idx+1);
                idx = addstr.indexOf("\"");
                location = addstr.substring(0, idx);

                idx = body.indexOf("location");
                var locstr = body.substring(idx);
                idx = locstr.indexOf("lat");
                var str = locstr.substring(idx);
                idx = str.indexOf(":");
                str = str.substring(idx+1);
                idx = str.indexOf(",");
                var lat = 1.0 * str.substring(0, idx);
                idx = locstr.indexOf("lng");
                str = locstr.substring(idx);
                idx = str.indexOf(":");
                str = str.substring(idx+1);
                idx = str.indexOf("}");
                var lng = 1.0 * str.substring(0, idx);

                url = "http://api.open-notify.org/iss-pass.json?lat=" + lat + "&lon=" + lng + "&n=1";
                http.get(url, function(res) {
                    var body = '';
            
                    res.on('data', function (chunk) {
                        body += chunk;
                    });
            
                    res.on('end', function () {
                        //console.log("Antwort erhalten ", body.length);
                        
                        var idx = body.indexOf("risetime");
                        var str = body.substring(idx);
                        idx = str.indexOf(":");
                        str = str.substring(idx+1);
                        //console.log(str);
                        var time = parseInt(str);

                        // Create speech output
                        var dt = new Date(time * 1000);
                        const speechOutput = when_msg_1 + location + when_msg_2 +
                            '<say-as interpret-as="date">' + ensure_digits(dt.getFullYear(), 4) + "" + ensure_digits(dt.getMonth()+1, 2) + "" + ensure_digits(dt.getDate(), 2) + "</say-as>" +
                            '<say-as interpret-as="time">' + ensure_digits(dt.getHours(), 2) + ":" + ensure_digits(dt.getMinutes(), 2) + "</say-as> U T C";
                        emit(':tellWithCard', speechOutput, skill_name, location);
                    });
                }).on('error', function (e) {
                    console.log("Got error: ", e);
                });
            });
        }).on('error', function (e) {
            console.log("Got error: ", e);
        });
    },
    'AMAZON.HelpIntent': function () {
        const speechOutput = this.t('HELP_MESSAGE');
        const reprompt = this.t('HELP_MESSAGE');
        this.emit(':ask', speechOutput, reprompt);
    },
    'AMAZON.CancelIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'AMAZON.StopIntent': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
    'SessionEndedRequest': function () {
        this.emit(':tell', this.t('STOP_MESSAGE'));
    },
};

exports.handler = (event, context) => {
    const alexa = Alexa.handler(event, context);
    alexa.APP_ID = APP_ID;
    // To enable string internationalization (i18n) features, set a resources object.
    alexa.resources = languageStrings;
    alexa.registerHandlers(handlers);
    alexa.execute();
};

Credits

MetaView

MetaView

8 projects • 15 followers

Comments