Dave Green
Published © GPL3+

IP Location Alexa Skill

Monitoring your network and want to check the country an IP is located? Your screen already a little busy? Just ask our Alexa Skill

BeginnerFull instructions provided2 hours3,362
IP Location Alexa Skill

Things used in this project

Hardware components

Amazon Echo
Amazon Alexa Amazon Echo
×1
Echo Dot
Amazon Alexa Echo Dot
×1

Software apps and online services

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

Story

Read more

Schematics

VUI

Basic flow diagram of the simple Voice User Interface

Code

AWS Lambda Function for Alexa

JavaScript
Copy the code into a new AWS Lambda function (Node.js) to retrieve the IP Address from the intent and return the location information on the IP
'use strict';
var http = require('http');

function buildSpeechletResponseWithCard(title, output, cardOutput, reprompt, shouldEndSession) {
    return {
        outputSpeech:{
            type: 'PlainText',
            text: output,
        },
        card: {
            type: 'Simple',
            title: title,
            content: cardOutput,
        },
        reprompt: {
            outputSpeech: {
                type: 'PlainText',
                text: reprompt,
            },       
        },
        shouldEndSession,
    };
}

function buildSpeechletResponse(output, reprompt, shouldEndSession) {
    return {
        outputSpeech:{
            type: 'PlainText',
            text: output,
        },
        reprompt: {
            outputSpeech: {
                type: 'PlainText',
                text: reprompt,
            },       
        },
        shouldEndSession,
    };    
}

function buildResponse(attributes, response) {
    return {
      version: '1.0',
      attributes,
      response: response,
    };
}

//Json doc for country codes to name from country.io!! Thanks guys!!
function getCountryFromCode(code) {
    var countries = JSON.parse("{\"BD\": \"Bangladesh\", \"BE\": \"Belgium\", \"BF\": \"Burkina Faso\", \"BG\": \"Bulgaria\", \"BA\": \"Bosnia and Herzegovina\", \"BB\": \"Barbados\", \"WF\": \"Wallis and Futuna\", \"BL\": \"Saint Barthelemy\", \"BM\": \"Bermuda\", \"BN\": \"Brunei\", \"BO\": \"Bolivia\", \"BH\": \"Bahrain\", \"BI\": \"Burundi\", \"BJ\": \"Benin\", \"BT\": \"Bhutan\", \"JM\": \"Jamaica\", \"BV\": \"Bouvet Island\", \"BW\": \"Botswana\", \"WS\": \"Samoa\", \"BQ\": \"Bonaire, Saint Eustatius and Saba \", \"BR\": \"Brazil\", \"BS\": \"Bahamas\", \"JE\": \"Jersey\", \"BY\": \"Belarus\", \"BZ\": \"Belize\", \"RU\": \"Russia\", \"RW\": \"Rwanda\", \"RS\": \"Serbia\", \"TL\": \"East Timor\", \"RE\": \"Reunion\", \"TM\": \"Turkmenistan\", \"TJ\": \"Tajikistan\", \"RO\": \"Romania\", \"TK\": \"Tokelau\", \"GW\": \"Guinea-Bissau\", \"GU\": \"Guam\", \"GT\": \"Guatemala\", \"GS\": \"South Georgia and the South Sandwich Islands\", \"GR\": \"Greece\", \"GQ\": \"Equatorial Guinea\", \"GP\": \"Guadeloupe\", \"JP\": \"Japan\", \"GY\": \"Guyana\", \"GG\": \"Guernsey\", \"GF\": \"French Guiana\", \"GE\": \"Georgia\", \"GD\": \"Grenada\", \"GB\": \"United Kingdom\", \"GA\": \"Gabon\", \"SV\": \"El Salvador\", \"GN\": \"Guinea\", \"GM\": \"Gambia\", \"GL\": \"Greenland\", \"GI\": \"Gibraltar\", \"GH\": \"Ghana\", \"OM\": \"Oman\", \"TN\": \"Tunisia\", \"JO\": \"Jordan\", \"HR\": \"Croatia\", \"HT\": \"Haiti\", \"HU\": \"Hungary\", \"HK\": \"Hong Kong\", \"HN\": \"Honduras\", \"HM\": \"Heard Island and McDonald Islands\", \"VE\": \"Venezuela\", \"PR\": \"Puerto Rico\", \"PS\": \"Palestinian Territory\", \"PW\": \"Palau\", \"PT\": \"Portugal\", \"SJ\": \"Svalbard and Jan Mayen\", \"PY\": \"Paraguay\", \"IQ\": \"Iraq\", \"PA\": \"Panama\", \"PF\": \"French Polynesia\", \"PG\": \"Papua New Guinea\", \"PE\": \"Peru\", \"PK\": \"Pakistan\", \"PH\": \"Philippines\", \"PN\": \"Pitcairn\", \"PL\": \"Poland\", \"PM\": \"Saint Pierre and Miquelon\", \"ZM\": \"Zambia\", \"EH\": \"Western Sahara\", \"EE\": \"Estonia\", \"EG\": \"Egypt\", \"ZA\": \"South Africa\", \"EC\": \"Ecuador\", \"IT\": \"Italy\", \"VN\": \"Vietnam\", \"SB\": \"Solomon Islands\", \"ET\": \"Ethiopia\", \"SO\": \"Somalia\", \"ZW\": \"Zimbabwe\", \"SA\": \"Saudi Arabia\", \"ES\": \"Spain\", \"ER\": \"Eritrea\", \"ME\": \"Montenegro\", \"MD\": \"Moldova\", \"MG\": \"Madagascar\", \"MF\": \"Saint Martin\", \"MA\": \"Morocco\", \"MC\": \"Monaco\", \"UZ\": \"Uzbekistan\", \"MM\": \"Myanmar\", \"ML\": \"Mali\", \"MO\": \"Macao\", \"MN\": \"Mongolia\", \"MH\": \"Marshall Islands\", \"MK\": \"Macedonia\", \"MU\": \"Mauritius\", \"MT\": \"Malta\", \"MW\": \"Malawi\", \"MV\": \"Maldives\", \"MQ\": \"Martinique\", \"MP\": \"Northern Mariana Islands\", \"MS\": \"Montserrat\", \"MR\": \"Mauritania\", \"IM\": \"Isle of Man\", \"UG\": \"Uganda\", \"TZ\": \"Tanzania\", \"MY\": \"Malaysia\", \"MX\": \"Mexico\", \"IL\": \"Israel\", \"FR\": \"France\", \"IO\": \"British Indian Ocean Territory\", \"SH\": \"Saint Helena\", \"FI\": \"Finland\", \"FJ\": \"Fiji\", \"FK\": \"Falkland Islands\", \"FM\": \"Micronesia\", \"FO\": \"Faroe Islands\", \"NI\": \"Nicaragua\", \"NL\": \"Netherlands\", \"NO\": \"Norway\", \"NA\": \"Namibia\", \"VU\": \"Vanuatu\", \"NC\": \"New Caledonia\", \"NE\": \"Niger\", \"NF\": \"Norfolk Island\", \"NG\": \"Nigeria\", \"NZ\": \"New Zealand\", \"NP\": \"Nepal\", \"NR\": \"Nauru\", \"NU\": \"Niue\", \"CK\": \"Cook Islands\", \"XK\": \"Kosovo\", \"CI\": \"Ivory Coast\", \"CH\": \"Switzerland\", \"CO\": \"Colombia\", \"CN\": \"China\", \"CM\": \"Cameroon\", \"CL\": \"Chile\", \"CC\": \"Cocos Islands\", \"CA\": \"Canada\", \"CG\": \"Republic of the Congo\", \"CF\": \"Central African Republic\", \"CD\": \"Democratic Republic of the Congo\", \"CZ\": \"Czech Republic\", \"CY\": \"Cyprus\", \"CX\": \"Christmas Island\", \"CR\": \"Costa Rica\", \"CW\": \"Curacao\", \"CV\": \"Cape Verde\", \"CU\": \"Cuba\", \"SZ\": \"Swaziland\", \"SY\": \"Syria\", \"SX\": \"Sint Maarten\", \"KG\": \"Kyrgyzstan\", \"KE\": \"Kenya\", \"SS\": \"South Sudan\", \"SR\": \"Suriname\", \"KI\": \"Kiribati\", \"KH\": \"Cambodia\", \"KN\": \"Saint Kitts and Nevis\", \"KM\": \"Comoros\", \"ST\": \"Sao Tome and Principe\", \"SK\": \"Slovakia\", \"KR\": \"South Korea\", \"SI\": \"Slovenia\", \"KP\": \"North Korea\", \"KW\": \"Kuwait\", \"SN\": \"Senegal\", \"SM\": \"San Marino\", \"SL\": \"Sierra Leone\", \"SC\": \"Seychelles\", \"KZ\": \"Kazakhstan\", \"KY\": \"Cayman Islands\", \"SG\": \"Singapore\", \"SE\": \"Sweden\", \"SD\": \"Sudan\", \"DO\": \"Dominican Republic\", \"DM\": \"Dominica\", \"DJ\": \"Djibouti\", \"DK\": \"Denmark\", \"VG\": \"British Virgin Islands\", \"DE\": \"Germany\", \"YE\": \"Yemen\", \"DZ\": \"Algeria\", \"US\": \"United States\", \"UY\": \"Uruguay\", \"YT\": \"Mayotte\", \"UM\": \"United States Minor Outlying Islands\", \"LB\": \"Lebanon\", \"LC\": \"Saint Lucia\", \"LA\": \"Laos\", \"TV\": \"Tuvalu\", \"TW\": \"Taiwan\", \"TT\": \"Trinidad and Tobago\", \"TR\": \"Turkey\", \"LK\": \"Sri Lanka\", \"LI\": \"Liechtenstein\", \"LV\": \"Latvia\", \"TO\": \"Tonga\", \"LT\": \"Lithuania\", \"LU\": \"Luxembourg\", \"LR\": \"Liberia\", \"LS\": \"Lesotho\", \"TH\": \"Thailand\", \"TF\": \"French Southern Territories\", \"TG\": \"Togo\", \"TD\": \"Chad\", \"TC\": \"Turks and Caicos Islands\", \"LY\": \"Libya\", \"VA\": \"Vatican\", \"VC\": \"Saint Vincent and the Grenadines\", \"AE\": \"United Arab Emirates\", \"AD\": \"Andorra\", \"AG\": \"Antigua and Barbuda\", \"AF\": \"Afghanistan\", \"AI\": \"Anguilla\", \"VI\": \"U.S. Virgin Islands\", \"IS\": \"Iceland\", \"IR\": \"Iran\", \"AM\": \"Armenia\", \"AL\": \"Albania\", \"AO\": \"Angola\", \"AQ\": \"Antarctica\", \"AS\": \"American Samoa\", \"AR\": \"Argentina\", \"AU\": \"Australia\", \"AT\": \"Austria\", \"AW\": \"Aruba\", \"IN\": \"India\", \"AX\": \"Aland Islands\", \"AZ\": \"Azerbaijan\", \"IE\": \"Ireland\", \"ID\": \"Indonesia\", \"UA\": \"Ukraine\", \"QA\": \"Qatar\", \"MZ\": \"Mozambique\"}");
    return countries[code];
}

function getCountry(intent, session, callback) {
    var attributes = {};
    var address = intent.slots.Address.value.replace(" point ", ".");   
    var address = address.replace(/ /g, "");
    var address = address.replace(/[^\d.]/g, "");
    var output = address;
    var repromptText = "I'm sorry, I didn't catch that.";
    var shouldEnd = false;
    http.get('http://ipinfo.io/' + address, function(res) {
        output = 'http://ipinfo.io/' + address + " - " + res.statusCode;
        if (res.statusCode === 200)
        {
            res.on('data', (chunk) => {
                var js = JSON.parse(chunk);
                var loc = js.city + " " + js.region + " " + getCountryFromCode(js.country);
                output = "That IP address is located in: " + loc.trim();
                repromptText = "Is there anything else I can do?";
                callback(attributes, buildSpeechletResponse(output, repromptText, shouldEnd));
            });
        }
        else
        {   
            output = "Sorry but there is a problem with the entered address. " + address;
            repromptText = "Is there anything else I can do?";
            callback(attributes, buildSpeechletResponse(output, repromptText, shouldEnd));
        }
    }).on('error', function(e) {
        output = "Sorry but there is a problem with the entered address. " + address;
        repromptText = "Is there anything else I can do?";
        callback(attributes, buildSpeechletResponse(output, repromptText, shouldEnd));
    });
}

function getHelpMessage(callback) {
    const attributes = {};
    const title = "Where is that IP Help?";
    const speechOutput = "Use Where is that IP to easily locate a city, region and country an IP address is located. To locate a country based on IP say, Locate 192 point 168 point 0 point 1. Remember to state point between the numbers to ensure the address is formatted correctly.";
    const repromptText = "Sorry I didnt get that, can you repeat the request?";
    const shouldEnd = false;
    callback(attributes, buildSpeechletResponseWithCard(title, speechOutput, speechOutput, repromptText, shouldEnd));
}

function getWelcomeMessage(callback) {
    const attributes = {};
    const speechOutput = "Hi and welcome to Where is that IP, your helpful IP locator tool. What can I do for you?";
    const repromptText = "What was that again?";
    const shouldEnd = false;
    callback(attributes, buildSpeechletResponse(speechOutput, repromptText, shouldEnd));
}

function getEndMessage(callback) {
    const attributes = {}; 
    const speechOutput = "Thank you for using Where is that IP.";
    const shouldEnd = true;
    callback(attributes, buildSpeechletResponse(speechOutput, null, shouldEnd));
}

function onLaunch(launchRequest, session, callback) {
    getWelcomeMessage(callback);
}
    
function onSessionEnded(request, session, callback) {
    getEndMessage(callback);
}

function onIntent(intentRequest, session, callback) {
    const intent = intentRequest.intent;
    const intentName = intentRequest.intent.name;
    
    if (intentName === "GetCountry") {
        return getCountry(intent, session, callback);
    } else if (intentName === "AMAZON.HelpIntent") {
        return getHelpMessage(callback);
    } else if (intentName === "AMAZON.CancelIntent") {
        return getEndMessage(callback);
    } else if (intentName === "AMAZON.StopIntent") {
        return getEndMessage(callback);
    } else {
        throw new Error('Invalid intent');
    }
}

exports.handler = (event, context, callback) => {
    try
    {
        if (event.session.application.applicationId != 'Add Your Own App ID here') {
             callback('Invalid Application ID');
        }
        if (event.request.type === 'LaunchRequest') {
            onLaunch(event.request,
                event.session,
                (sessionAttributes, speechletResponse) => {
                    callback(null, buildResponse(sessionAttributes, speechletResponse));
                });
        } else if (event.request.type === 'IntentRequest') {
            onIntent(event.request,
                event.session,
                (sessionAttributes, speechletResponse) => {
                    callback(null, buildResponse(sessionAttributes, speechletResponse));
                });
        } else if (event.request.type === 'SessionEndedRequest') {
            onSessionEnded(event.request, event.session);
            callback();
        }
    } catch (err) {
        callback(err);
    }
};

Alexa Intent Scheme

JSON
Copy the code into the Intent Schema for your Alexa skill. We are only going to have one intent for this app which is GetCountry
{
  "intents": [
    {
      "intent": "GetCountry",
      "slots": [
        {
          "name": "Address",
          "type": "AddressValues"
        }
      ]
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    }
  ]
}

Alexa Sample Utterances

Plain text
GetCountry what country is {Address} in
GetCountry where is {Address}
GetCountry what country is {Address}
GetCountry locate {Address}
AMAZON.StopIntent no
AMAZON.StopIntent bye
AMAZON.StopIntent goodbye

Credits

Dave Green

Dave Green

2 projects • 3 followers
Thanks to IpInfo.io and Country.io.

Comments

Add projectSign up / Login