-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
175 lines (147 loc) · 5.94 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/**
/**
*
* Examples:
* One-shot model:
* User: "Alexa, ask Space Geek for a space fact"
* Alexa: "Here's your space fact: ..."
*/
/**
* App ID for the skill
*/
var APP_ID = "amzn1.echo-sdk-ams.app.743fa602-cccd-46cd-ada8-ac3273dedef6"; //replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";
/**
* The AlexaSkill prototype and helper functions
*/
var AlexaSkill = require('./AlexaSkill');
var http = require('http');
/**
* SpaceGeek 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 SpaceGeek = function () {
AlexaSkill.call(this, APP_ID);
};
// Extend AlexaSkill
SpaceGeek.prototype = Object.create(AlexaSkill.prototype);
SpaceGeek.prototype.constructor = SpaceGeek;
SpaceGeek.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
console.log("SpaceGeek onSessionStarted requestId: " + sessionStartedRequest.requestId
+ ", sessionId: " + session.sessionId);
// any initialization logic goes here
};
SpaceGeek.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
console.log("SpaceGeek onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
handleNewFactRequest(response);
};
/**
* Overridden to show that a subclass can override this function to teardown session state.
*/
SpaceGeek.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
console.log("SpaceGeek onSessionEnded requestId: " + sessionEndedRequest.requestId
+ ", sessionId: " + session.sessionId);
// any cleanup logic goes here
};
SpaceGeek.prototype.intentHandlers = {
"GetNewFactIntent": function (intent, session, response) {
handleNewFactRequest(response);
},
"AMAZON.HelpIntent": function (intent, session, response) {
response.ask("You can ask Buster when is my next bus, or, you can say exit.");
},
"AMAZON.StopIntent": function (intent, session, response) {
var speechOutput = "Goodbye";
response.tell(speechOutput);
},
"AMAZON.CancelIntent": function (intent, session, response) {
var speechOutput = "Goodbye";
response.tell(speechOutput);
}
};
/**
* Gets a random new fact from the list and returns to the user.
*/
function handleNewFactRequest(response) {
makeNextBusRequest("mbta", 2276, function nextBusRequestCallback(err, nextBusResponse) {
var speechOutput;
if (err) {
speechOutput = "Sorry, the Next Bus service is experiencing a problem. Please try again later";
} else {
speechOutput = "The next buses are " + nextBusResponse;
}
response.tellWithCard(speechOutput, "BusTimes", speechOutput)
});
}
/**
* Uses NextBus API, currently agency and stop ID are hardcoded.
* Get agency name from: http://webservices.nextbus.com/service/publicXMLFeed?command=agencyList
* For SF Muni, get stop ID from: http://www.nextbus.com/wirelessConfig/stopNumbers.jsp?a=sf-muni
*/
function makeNextBusRequest(agency, stopId, nextBusRequestCallback) {
var endpoint = 'http://webservices.nextbus.com/service/publicXMLFeed';
var queryString = '?command=predictions&a=' + agency + '&stopId=' + stopId;
http.get(endpoint + queryString, function(res) {
var nextBusResponseString = '';
res.on('data', function(data) {
nextBusResponseString += data;
});
res.on('end', function() {
var data = []
var parseString = require('xml2js').parseString;
var nextBusResponseObject = parseString(nextBusResponseString, function(err, result) {
for (var i = 0; i < result.body.predictions.length; i++) {
var currPredictions = result.body.predictions[i];
if (currPredictions.direction != undefined) {
for (var j = 0; j < currPredictions.direction.length; j++) {
for (var k = 0; k < currPredictions.direction[j].prediction.length; k++) {
var dict = {};
dict["route"] = currPredictions.$.routeTitle;
dict["minutes"] = Number(currPredictions.direction[j].prediction[k].$.minutes);
data[data.length] = dict;
}
}
}
}
// Sort by arrival times
data.sort(function(a, b) {
if (a["minutes"] < b["minutes"]) return -1;
if (a["minutes"] > b["minutes"]) return 1;
return 0;
});
});
if (nextBusResponseObject.error) {
console.log("NextBus error: " + nextBusResponseObject.error.message);
nextBusRequestCallback(new Error(nextBusResponseObject.error.message));
} else {
nextBusRequestCallback(null, convertDataToString(data));
}
});
}).on('error', function(e) {
console.log("Communications error: " + e.message);
nextBusRequestCallback(new Error(e.message));
});
}
function convertDataToString(data) {
var string = ""
var n = Math.min(data.length, 3)
for (var i = 0; i < n; i++) {
string += data[i]["route"] + " in " + data[i]["minutes"] + (data[i]["minutes"] == 1 ? " minute" : " minutes")
if (i < (n - 1)) {
string += ", "
if (i == (n - 2)) {
string += "and "
}
} else {
string += "."
}
}
return string
}
// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
// Create an instance of the SpaceGeek skill.
var spaceGeek = new SpaceGeek();
spaceGeek.execute(event, context);
};