-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
212 lines (183 loc) · 6.97 KB
/
app.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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// Copyright 2016, Google, Inc.
// Licensed under the Apache License, Version 2.0 (the 'License');
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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';
process.env.DEBUG = 'actions-on-google:*';
let Assistant = require('actions-on-google').ApiAiAssistant;
let express = require('express');
let bodyParser = require('body-parser');
let app = express();
app.use(bodyParser.json({type: 'application/json'}));
// API.AI actions
const UNRECOGNIZED_DEEP_LINK = 'deeplink.unknown';
const SAY_CAT_FACT = 'say_cat_fact';
const SAY_GOOGLE_FACT = 'say_google_fact';
// API.AI parameter names
const UNRECOGNIZED_DEEP_LINK_ARGUMENT = 'raw_text';
const CATEGORY_ARGUMENT = 'category';
// API.AI Contexts/lifespans
const GOOGLE_CONTEXT = 'google-facts';
const CAT_CONTEXT = 'cat-facts';
const DEFAULT_LIFESPAN = 5;
const END_LIFESPAN = 0;
const FACT_TYPE = {
HISTORY: 'history',
HEADQUARTERS: 'headquarters',
CATS: 'cats'
};
const HISTORY_FACTS = new Set([
'Google was founded in 1998.',
'Google was founded by Larry Page and Sergey Brin.',
'Google went public in 2004.',
'Google has more than 70 offices in more than 40 countries.'
]);
const HQ_FACTS = new Set([
'Google\'s headquarters is in Mountain View, California.',
'Google has over 30 cafeterias in its main campus.',
'Google has over 10 fitness facilities in its main campus.'
]);
const CAT_FACTS = new Set([
'Cats are animals.',
'Cats have nine lives.',
'Cats descend from other cats.'
]);
const NEXT_FACT_DIRECTIVE = ' Would you like to hear another fact?';
// This sample uses this sound from Freesound:
// 'cat meow' by tuberatanka (https://www.freesound.org/people/tuberatanka/sounds/110011/)
const MEOW_SRC = 'https://freesound.org/data/previews/110/110011_1537422-lq.mp3';
function getRandomFact (facts) {
if (facts.size <= 0) {
return null;
}
let randomIndex = (Math.random() * (facts.size - 1)).toFixed();
let randomFactIndex = parseInt(randomIndex, 10);
let counter = 0;
let randomFact = '';
for (let fact of facts.values()) {
if (counter === randomFactIndex) {
randomFact = fact;
break;
}
counter++;
}
facts.delete(randomFact);
return randomFact;
}
// [START google_facts]
app.post('/', function (req, res) {
const assistant = new Assistant({request: req, response: res});
console.log('Request headers: ' + JSON.stringify(req.headers));
console.log('Request body: ' + JSON.stringify(req.body));
// Greet the user and direct them to next turn
function unhandledDeepLinks (assistant) {
assistant.ask(`Welcome to Facts about Google! I'd really rather
not talk about ${assistant.getArgument(UNRECOGNIZED_DEEP_LINK_ARGUMENT)}.
Wouldn't you rather talk about Google? I can tell you about
Google's history or its headquarters. Which do you want to hear about?`);
}
// Say a Google fact
function tellGoogleFact (assistant) {
let historyFacts = assistant.data.historyFacts
? new Set(assistant.data.historyFacts) : HISTORY_FACTS;
let hqFacts = assistant.data.hqFacts
? new Set(assistant.data.hqFacts) : HQ_FACTS;
if (historyFacts.size === 0 && hqFacts.size === 0) {
assistant.tell('Actually it looks like you heard it all. ' +
'Thanks for listening!');
return;
}
let factCategory = assistant.getArgument(CATEGORY_ARGUMENT);
if (factCategory === FACT_TYPE.HISTORY) {
let fact = getRandomFact(historyFacts);
if (fact === null) {
assistant.ask(noFactsLeft(assistant, factCategory,
FACT_TYPE.HEADQUARTERS));
return;
}
let factPrefix = 'Sure, here\'s a history fact. ';
assistant.data.historyFacts = Array.from(historyFacts);
assistant.ask(factPrefix + fact + NEXT_FACT_DIRECTIVE);
return;
} else if (factCategory === FACT_TYPE.HEADQUARTERS) {
let fact = getRandomFact(hqFacts);
if (fact === null) {
assistant.ask(noFactsLeft(assistant, factCategory,
FACT_TYPE.HISTORY));
return;
}
let factPrefix = 'Okay, here\'s a headquarters fact. ';
assistant.data.hqFacts = Array.from(hqFacts);
assistant.ask(factPrefix + fact + NEXT_FACT_DIRECTIVE);
return;
} else {
// Conversation repair is handled in API.AI, but this is a safeguard
assistant.ask(`Sorry, I didn't understand. I can tell you about
Google's history, or its headquarters. Which one do you want to
hear about?`);
}
}
// Say a cat fact
function tellCatFact (assistant) {
let catFacts = assistant.data.catFacts
? new Set(assistant.data.catFacts) : CAT_FACTS;
let fact = getRandomFact(catFacts);
if (fact === null) {
let parameters = {};
// Add google-facts context to outgoing context list
assistant.setContext(GOOGLE_CONTEXT, DEFAULT_LIFESPAN,
parameters);
// Replace outgoing cat-facts context with lifespan = 0 to end it
assistant.setContext(CAT_CONTEXT, END_LIFESPAN, {});
assistant.ask('Looks like you\'ve heard all there is to know ' +
'about cats. Would you like to hear about Google?');
return;
}
let factPrefix = 'Alright, here\'s a cat fact. ' +
'<audio src="' + MEOW_SRC + '"></audio>';
let factSpeech = '<speak>' + factPrefix + fact +
NEXT_FACT_DIRECTIVE + '</speak>';
assistant.data.catFacts = Array.from(catFacts);
assistant.ask(factSpeech);
return;
}
// Say they've heard it all about this category
function noFactsLeft (assistant, currentCategory, redirectCategory) {
let parameters = {};
parameters[CATEGORY_ARGUMENT] = redirectCategory;
// Replace the outgoing google-facts context with different parameters
assistant.setContext(GOOGLE_CONTEXT, DEFAULT_LIFESPAN,
parameters);
let response = `Looks like you've heard all there is to know
about the ${currentCategory} of Google. Would you like to hear
about its ${redirectCategory}? `;
if (!assistant.data.catFacts || assistant.data.catFacts.length > 0) {
response += 'By the way, I can tell you about cats too.';
}
return response;
}
let actionMap = new Map();
actionMap.set(UNRECOGNIZED_DEEP_LINK, unhandledDeepLinks);
actionMap.set(SAY_GOOGLE_FACT, tellGoogleFact);
actionMap.set(SAY_CAT_FACT, tellCatFact);
assistant.handleRequest(actionMap);
});
// [END google_facts]
if (module === require.main) {
// [START server]
// Start the server
let server = app.listen(process.env.PORT || 8080, function () {
let port = server.address().port;
console.log('App listening on port %s', port);
});
// [END server]
}
module.exports = app;