UNPKG

9.47 kBJavaScriptView Raw
1"use strict";
2/**
3 * Copyright 2018 Google Inc. All Rights Reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.DialogflowConversation = void 0;
19const actionssdk_1 = require("../actionssdk");
20const context_1 = require("./context");
21const incoming_1 = require("./incoming");
22const CONV_DATA_CONTEXT = '_actions_on_google';
23const CONV_DATA_CONTEXT_LIFESPAN = 99;
24const SIMULATOR_WARNING = 'Cannot display response in Dialogflow simulator. ' +
25 'Please test on the Google Assistant simulator instead.';
26const isV1 = (body) => !!body.result;
27const isSimulator = (body) => {
28 if (isV1(body)) {
29 return !body.originalRequest;
30 }
31 if (!body.originalDetectIntentRequest) {
32 return false;
33 }
34 return (Object.keys(body.originalDetectIntentRequest.payload).length === 0 &&
35 !!body.responseId);
36};
37const getRequest = (body) => {
38 if (isV1(body)) {
39 const { originalRequest = {} } = body;
40 const { data = {} } = originalRequest;
41 return data;
42 }
43 const { originalDetectIntentRequest = {} } = body;
44 const { payload = {} } = originalDetectIntentRequest;
45 return payload;
46};
47const serializeData = (data) => JSON.stringify(data);
48const deserializeData = (contexts, defaultData) => {
49 const context = contexts.get(CONV_DATA_CONTEXT);
50 if (context) {
51 const { data } = context.parameters;
52 if (typeof data === 'string') {
53 return JSON.parse(data);
54 }
55 }
56 return Object.assign({}, defaultData);
57};
58/** @public */
59class DialogflowConversation extends actionssdk_1.Conversation {
60 /** @public */
61 constructor(options = {}) {
62 const { body = {} } = options;
63 super({
64 request: getRequest(body),
65 headers: options.headers,
66 init: options.init,
67 ordersv3: options.ordersv3,
68 });
69 this.body = body;
70 if (isV1(this.body)) {
71 this.version = 1;
72 const { result = {} } = this.body;
73 const { action = '', parameters = {}, contexts, resolvedQuery = '', metadata = {}, fulfillment, } = result;
74 const { intentName = '' } = metadata;
75 this.action = action;
76 this.intent = intentName;
77 this.parameters = parameters;
78 this.contexts = new context_1.ContextValues(contexts);
79 this.incoming = new incoming_1.Incoming(fulfillment);
80 this.query = resolvedQuery;
81 }
82 else {
83 this.version = 2;
84 const { queryResult = {} } = this.body;
85 const { action = '', parameters = {}, outputContexts, intent = {}, queryText = '', fulfillmentMessages, } = queryResult;
86 const { displayName = '' } = intent;
87 this.action = action;
88 this.intent = displayName;
89 this.parameters = parameters;
90 this.contexts = new context_1.ContextValues(outputContexts, this.body.session);
91 this.incoming = new incoming_1.Incoming(fulfillmentMessages);
92 this.query = queryText;
93 }
94 for (const key in this.parameters) {
95 const value = this.parameters[key];
96 if (typeof value !== 'object') {
97 // Convert all non-objects to strings for consistency
98 this.parameters[key] = String(value);
99 }
100 }
101 this.data = deserializeData(this.contexts, this._init.data);
102 }
103 /**
104 * Triggers an intent of your choosing by sending a followup event from the webhook.
105 * Final response can theoretically include responses but these will not be handled
106 * by Dialogflow. Dialogflow will not pass anything back to Google Assistant, therefore
107 * Google Assistant specific information, most notably conv.user.storage, is ignored.
108 *
109 * @example
110 * ```javascript
111 *
112 * const app = dialogflow()
113 *
114 * // Create a Dialogflow intent with event 'apply-for-license-event'
115 *
116 * app.intent('Default Welcome Intent', conv => {
117 * conv.followup('apply-for-license-event', {
118 * date: new Date().toISOString(),
119 * })
120 * // The dialogflow intent with the 'apply-for-license-event' event
121 * // will be triggered with the given parameters `date`
122 * })
123 * ```
124 *
125 * @param event Name of the event
126 * @param parameters Parameters to send with the event
127 * @param lang The language of this query.
128 * See {@link https://dialogflow.com/docs/languages|Language Support}
129 * for a list of the currently supported language codes.
130 * Note that queries in the same session do not necessarily need to specify the same language.
131 * By default, it is the languageCode sent with Dialogflow's queryResult.languageCode
132 * @public
133 */
134 followup(event, parameters, lang) {
135 this._responded = true;
136 if (this.version === 1) {
137 this._followup = {
138 name: event,
139 data: parameters,
140 };
141 return this;
142 }
143 const body = this.body;
144 this._followup = {
145 name: event,
146 parameters,
147 languageCode: lang || body.queryResult.languageCode,
148 };
149 return this;
150 }
151 /** @public */
152 serialize() {
153 if (this._raw) {
154 return this._raw;
155 }
156 let payload;
157 if (this._followup) {
158 this.digested = true;
159 }
160 else {
161 const { richResponse, expectUserResponse, userStorage, expectedIntent, noInputPrompts, speechBiasingHints, } = this.response();
162 const google = {
163 expectUserResponse,
164 systemIntent: expectedIntent && {
165 intent: expectedIntent.intent,
166 data: expectedIntent.inputValueData,
167 },
168 noInputPrompts,
169 speechBiasingHints,
170 };
171 if (richResponse.items.length) {
172 google.richResponse = richResponse;
173 }
174 if (userStorage) {
175 google.userStorage = userStorage;
176 }
177 payload = { google };
178 }
179 const convDataDefault = deserializeData(this.contexts, this._init.data);
180 const convDataIn = serializeData(convDataDefault);
181 const convDataOut = serializeData(this.data);
182 if (convDataOut !== convDataIn) {
183 // Previously was setting every webhook call
184 // But now will only set if different so lifespan does not get reset
185 this.contexts.set(CONV_DATA_CONTEXT, CONV_DATA_CONTEXT_LIFESPAN, {
186 data: convDataOut,
187 });
188 }
189 const simulator = isSimulator(this.body);
190 if (this.version === 1) {
191 const response = {
192 data: payload,
193 followupEvent: this._followup,
194 };
195 const contextOut = this.contexts._serializeV1();
196 if (contextOut.length) {
197 response.contextOut = contextOut;
198 }
199 if (simulator && payload) {
200 const { richResponse = {} } = payload.google;
201 const { items = [] } = richResponse;
202 // Simulator only shows speech response
203 // Since this is only shown to the simulator as text, the speech is the displayText
204 response.speech = SIMULATOR_WARNING;
205 if (!payload.google.systemIntent && items.length < 2) {
206 for (const { simpleResponse } of items) {
207 if (simpleResponse) {
208 response.speech =
209 simpleResponse.displayText || simpleResponse.textToSpeech;
210 break;
211 }
212 }
213 }
214 }
215 return response;
216 }
217 const response = {
218 payload,
219 followupEventInput: this._followup,
220 };
221 const outputContexts = this.contexts._serialize();
222 if (outputContexts.length) {
223 response.outputContexts = outputContexts;
224 }
225 if (simulator && payload) {
226 const { richResponse = {} } = payload.google;
227 const { items = [] } = richResponse;
228 response.fulfillmentText = SIMULATOR_WARNING;
229 if (!payload.google.systemIntent && items.length < 2) {
230 for (const { simpleResponse } of items) {
231 if (simpleResponse) {
232 response.fulfillmentText =
233 simpleResponse.displayText || simpleResponse.textToSpeech;
234 break;
235 }
236 }
237 }
238 }
239 return response;
240 }
241}
242exports.DialogflowConversation = DialogflowConversation;
243//# sourceMappingURL=conv.js.map
\No newline at end of file