Phone tracker for Alexa [Alpha testing]

View the Project on GitHub askquickly/phonetracker

The build so far

We've been building a new skill and android app that lets Alexa keep a eye on where you are.

package org.askquickly.phonetracker;

Also the app builds an early prototype android wear app that updates with location and a few other goodies direct to your alexa device.

User -
Where is Paul?
Alexa -
Paul is 5 mins away on oak road

The phone updates with location data and other set options

Dev builds

Showing internal communications

The other side

On the side of the Alexa is something as simple as this nodejs

//********"Alexa, open phone tracker "********************

'use strict';
var https = require('https');
var tokenaccessask = {}; // Globally scoped object
exports.handler = function (event, context) {
    try {
        console.log("event.session.application.applicationId=" + event.session.application.applicationId);
         if (event.session.application.applicationId !== "amzn1.ask.skill.x") {
           context.fail("Invalid Application ID");
         }
         
       tokenaccessask.key = event.session.user.accessToken;
        if (event.session.new) {
           onSessionStarted({requestId: event.request.requestId}, event.session);
        }
        // manual assign a user
        if (event.request.type === "LaunchRequest") {
            onLaunch(event.request,
                     event.session,
                     function callback(sessionAttributes, speechletResponse) {
                        context.succeed(buildResponse(sessionAttributes, speechletResponse));
                     });
        }  else if (event.request.type === "IntentRequest") {
            onIntent(event.request,
                     event.session,
                     function callback(sessionAttributes, speechletResponse) {
                         context.succeed(buildResponse(sessionAttributes, speechletResponse));
                     });
        } else if (event.request.type === "SessionEndedRequest") {
            onSessionEnded(event.request, event.session);
            context.succeed();
        }
    } catch (e) {
        context.fail("Exception: " + e);
    }
};

/**
 * Called when the session starts.
 */
function onSessionStarted(sessionStartedRequest, session) {
    console.log("onSessionStarted requestId=" + sessionStartedRequest.requestId
                + ", sessionId=" + session.sessionId);
}

/**
 * Called when the user launches the skill without specifying what they want.
 */
function onLaunch(launchRequest, session, callback) {
    console.log("onLaunch requestId=" + launchRequest.requestId
                + ", sessionId=" + session.sessionId);
                
                // do the check if linked or not
                
                if(tokenaccessask.key === undefined) {
                    getExtraResponse(callback);
                }else { 
                getWelcomeResponse(callback);
 }
}
/**
 * Called when the user specifies an intent for this skill.
 */

function onIntent(intentRequest, session, callback) {
    console.log("onIntent requestId=" + intentRequest.requestId +
            ", sessionId=" + session.sessionId);

    var intent = intentRequest.intent,
        intentName = intentRequest.intent.name;
        console.log("INTENT",intentName);

    // Dispatch to your skill's intent handlers
    if ("PairIntent" === intentName) {
      getExtraResponse(callback);
    } else if("HelpmeIntent"===intentName){
      getHelpResponse(callback);
    }else if("LocateIntent"===intentName){
      getUserResponse(callback);
    }
    else if("ToneIntent"===intentName){
        if(tokenaccessask.key === undefined) {
            getExtraResponse(callback);
                }else {
      getatone(callback);
    }
}
else if("NameeIntent"===intentName){
        if(tokenaccessask.key === undefined) {
            getExtraResponse(callback);
                }else { 
      sResponse(callback);
    }
    }else {
        throw "Invalid intent";
        //getNoResponse(callback);
    }
}
/**
 * Called when the user ends the session.
 * Is not called when the skill returns shouldEndSession=true.
 */
function onSessionEnded(sessionEndedRequest, session) {
    console.log("onSessionEnded requestId=" + sessionEndedRequest.requestId
                + ", sessionId=" + session.sessionId);
    // Add cleanup logic here
}

// --------------- Functions that control the skill's behavior -----------------------

function getWelcomeResponse(callback) {
    var sessionAttributes = {};
    var cardTitle = "Phone Tracker";
   var speechOutput = "Welcome to the Phone Tracker skill,";
    var repromptText = '';
    var shouldEndSession = true;
    var options = {
        host: 'x',
        port: 443,
       path: '/x?t='+ tokenaccessask.key,
        method: 'GET'
    };

    var req = https.request(options, function(res) {
        var body = '';
        console.log('Status:', res.statusCode);
        console.log('Headers:', JSON.stringify(res.headers));
        res.setEncoding('utf8');
        res.on('data', function(chunk) {
            body += chunk;
        });
        res.on('end', function() {
            console.log('Successfully processed HTTPS response');
            body = JSON.parse(body);

                speechOutput += "The last place " + body.ticker.loc;

                callback(sessionAttributes,
                 buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
             });
    });
    req.end();

}
function getHelpResponse(callback){
var sessionAttributes = {};
var cardTitle = "Phone Tracker";
    var repromptText = '';
    var shouldEndSession = true;
      var speechOutput = "This skill provides tracking information, and is for informational and educational purposes only"
                callback(sessionAttributes,
                 buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function getExtraResponse(callback) {
    var sessionAttributes = {};
    var cardTitle = "";
    var repromptText = '';
    var shouldEndSession = true;
    var speechOutput = "Please configure the skill using the Account Setup link in the Alexa App";
                callback(sessionAttributes,
                 ebuildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function getatone(callback) {
    var sessionAttributes = {};
   var cardTitle = "Phone Tracker";
   var speechOutput = "Your phone should now being ringing,";
    var repromptText = '';
    var shouldEndSession = true;

    var options = {
        host: 'x',
        port: 443,
        path: '/x?t='+ tokenaccessask.key,
        method: 'GET'
    };
    
    var req = https.request(options, function(res) {
       var sessionAttributes = {};
    var cardTitle = "";
    var repromptText = '';
    var shouldEndSession = true;
    var speechOutput = "A ring request has been sent to your phone";
                callback(sessionAttributes,
                 buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
    });
    req.end();

}
// --------------- Helpers that build all of the responses -----------------------

function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
    return {
        outputSpeech: {
            type: "PlainText",
            text: output
        },
        card: {
            type: "Simple",
            title: title,
            content: output
        },
        reprompt: {
            outputSpeech: {
                type: "PlainText",
                text: repromptText
            }
        },
        shouldEndSession: shouldEndSession
    }
}

function buildResponse(sessionAttributes, speechletResponse) {
    return {
        version: "1.0",
        sessionAttributes: sessionAttributes,
        response: speechletResponse
    }
}
function ebuildSpeechletResponse(title, output, shouldEndSession) {
    return {
        outputSpeech: {
            type: "PlainText",
            text: output
        },
        card: {
            "type": "LinkAccount"
        },
        shouldEndSession: true
    }
}