-
-
Save anton-dudarev/6029e8640882690db469ed3a759de593 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const admin = require('firebase-admin'); | |
admin.initializeApp(); | |
const functions = require('firebase-functions'); // Cloud Functions for Firebase library | |
const DialogflowApp = require('actions-on-google').DialogflowApp; // Google Assistant helper library | |
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { | |
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers)); | |
console.log('Dialogflow Request body: ' + JSON.stringify(request.body)); | |
if (request.body.queryResult) { | |
processV2Request(request, response); | |
} else { | |
console.log('Invalid Request'); | |
return response.status(400).end('Invalid Webhook Request (expecting v2 webhook request)'); | |
} | |
}); | |
/* | |
* Function to handle v2 webhook requests from Dialogflow | |
*/ | |
function processV2Request (request, response) { | |
// An action is a string used to identify what needs to be done in fulfillment | |
let action = (request.body.queryResult.action) ? request.body.queryResult.action : 'default'; | |
// Parameters are any entites that Dialogflow has extracted from the request. | |
let parameters = request.body.queryResult.parameters || {}; // https://dialogflow.com/docs/actions-and-parameters | |
// Contexts are objects used to track and store conversation state | |
let inputContexts = request.body.queryResult.contexts; // https://dialogflow.com/docs/contexts | |
// Get the request source (Google Assistant, Slack, API, etc) | |
let requestSource = (request.body.originalDetectIntentRequest) ? request.body.originalDetectIntentRequest.source : undefined; | |
// Get the session ID to differentiate calls from different users | |
let session = (request.body.session) ? request.body.session : undefined; | |
// Create handlers for Dialogflow actions as well as a 'default' handler | |
const actionHandlers = { | |
// The default welcome intent has been matched, welcome the user (https://dialogflow.com/docs/events#default_welcome_intent) | |
'input.welcome': () => { | |
sendResponse('Hello, Welcome to Brighton Tide. Try asking for the next low tide.'); // Send simple response to user | |
}, | |
// The default fallback intent has been matched, try to recover (https://dialogflow.com/docs/intents#fallback_intents) | |
'input.unknown': () => { | |
// Use the Actions on Google lib to respond to Google requests; for other requests use JSON | |
sendResponse('I\'m having trouble understanding. Try asking for the next low tide.'); // Send simple response to user | |
}, | |
'next-low': () => { | |
var db = admin.firestore(); | |
const now = new Date(); | |
const nowUtc = now.getTime(); | |
const sameDay = (tide, date) => date.toISOString().substr(0, 10) === tide.date; | |
function express(tide, now) { | |
if (sameDay(tide, now)) { | |
return `There's a ${tide.height} metre low at ${tide.time12}.` | |
} else { | |
return `There's a ${tide.height} metre low at ${tide.time12} on ${tide.dow}.` | |
} | |
} | |
db.collection('tide-times') | |
.where('instant', '>=', nowUtc) | |
.where('highOrLow', '=', 'low') | |
.orderBy('instant', 'asc') | |
.limit(1) | |
.get().then((snapshot) => { | |
if (snapshot._size === 0) { | |
console.log('No tides', nowUtc); | |
sendResponse('Sorry, I can\'t find any tide times.'); | |
} else { | |
snapshot.forEach((doc) => { | |
var tide = doc.data(); | |
var replyText = express(tide, now); | |
sendResponse(replyText); | |
}); | |
} | |
}) | |
.catch((err) => { | |
console.log('Error getting documents', err); | |
sendResponse('Sorry, something went wrong. Maybe try again later.'); | |
}); | |
}, | |
// Default handler for unknown or undefined actions | |
'default': () => { | |
let responseToUser = { | |
//fulfillmentMessages: richResponsesV2, // Optional, uncomment to enable | |
//outputContexts: [{ 'name': `${session}/contexts/weather`, 'lifespanCount': 2, 'parameters': {'city': 'Rome'} }], // Optional, uncomment to enable | |
fulfillmentText: 'Sorry, I didn\'t understand that. You can ask for the next low tide.' // displayed response | |
}; | |
sendResponse(responseToUser); | |
} | |
}; | |
// If undefined or unknown action use the default handler | |
if (!actionHandlers[action]) { | |
action = 'default'; | |
} | |
// Run the proper handler function to handle the request from Dialogflow | |
actionHandlers[action](); | |
// Function to send correctly formatted responses to Dialogflow which are then sent to the user | |
function sendResponse (responseToUser) { | |
// if the response is a string send it as a response to the user | |
if (typeof responseToUser === 'string') { | |
let responseJson = {fulfillmentText: responseToUser}; // displayed response | |
console.log('Text Response to Dialogflow: ' + JSON.stringify(responseJson)); | |
response.json(responseJson); // Send response to Dialogflow | |
} else { | |
// If the response to the user includes rich responses or contexts send them to Dialogflow | |
let responseJson = {}; | |
// Define the text response | |
responseJson.fulfillmentText = responseToUser.fulfillmentText; | |
// Optional: add rich messages for integrations (https://dialogflow.com/docs/rich-messages) | |
if (responseToUser.fulfillmentMessages) { | |
responseJson.fulfillmentMessages = responseToUser.fulfillmentMessages; | |
} | |
// Optional: add contexts (https://dialogflow.com/docs/contexts) | |
if (responseToUser.outputContexts) { | |
responseJson.outputContexts = responseToUser.outputContexts; | |
} | |
// Send the response to Dialogflow | |
console.log('Response to Dialogflow: ' + JSON.stringify(responseJson)); | |
response.json(responseJson); | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment