我正在通过对话流、谷歌日历和 voximplant 开发语音助手。我需要管理多个日历,并根据一系列优先级选择首先在哪个日历上插入事件:例如,如果我有 4 个日历,我想检查第一个日历,如果后者没有。空间第二个日历被检查等等。我很难处理异步承诺和函数。有人知道如何帮我一把吗?
我将在下面发布代码:
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const parsePhoneNumber = require('libphonenumber-js/max');
const functions = require('firebase-functions');
const {
google
} = require('googleapis');
const {
WebhookClient
} = require('dialogflow-fulfillment');
// Enter your calendar ID below and service account JSON below
// The user has to insert his personal <'calendarId'>
const calendarId = ['xxxxxxxxxxxxxx@group.calendar.google.com', 'xxxxxxxxxxxxxxx@group.calendar.google.com', 'xxxxxxxxxxxxxx@group.calendar.google.com', 'xxxxxxxxxxxxxx@group.calendar.google.com'];
const serviceAccount = {
"type": "service_account",
"project_id": "",
"private_key_id": "",
"private_key": "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----\n",
"client_email": "",
"client_id": "",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/scheduler%40italians-do-it-better.iam.gserviceaccount.com"
};
//Authentication in google calendar
const serviceAccountAuth = new google.auth.JWT({
email: serviceAccount.client_email,
key: serviceAccount.private_key,
scopes: 'https://www.googleapis.com/auth/calendar'
});
const calendar = google.calendar('v3');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements
//time zone and time zone setting.
//This parameter can be overridden by the user
const timeZone = 'Europe/Kaliningrad';
const timeZoneOffset = '+02:00';
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({
request,
response
});
console.log("Parameters", agent.parameters);
//Insert your <'company name'> here
var company = "Deedy";
const appointment_type = company + ' and ' + agent.parameters.name;
//Make appointment function
function makeAppointment(agent) {
console.log("Parameters", agent.parameters.date);
//Variable acquisition
//const guests = agent.parameters.guests; //paremetro in più
//const email = agent.parameters.email; //parametro in più
const phonenumber = agent.parameters.phonenumber;
var phone = phonenumber.toString().length;
let name = agent.parameters.name;
//Declaration of the duration of the event.
//By default it is 1 hour from the start of the event.
//It can be modified by the customer
const eventDuration = 1; //hours, so if you want an event of a day duration you have to write "24"
// Calculate appointment start and end datetimes (end = +1hr from start)
const dateTimeStart = new Date(Date.parse(agent.parameters.date.split('T')[0] + 'T' + agent.parameters.time.split('T')[1].split('+')[0] + timeZoneOffset));
const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + eventDuration));
console.log("date start ", dateTimeStart, " date end ", dateTimeEnd);
const date = new Date(agent.parameters.date);
const bookingDate = new Date(date);
const now = new Date();
const appointmentTimeString = dateTimeStart.toLocaleString('en-US', {
timeZone: 'Europe/Kaliningrad',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
//Checks
/*if (guests < 1) {
agent.add(`You need to reserve a table for at least one person. Please try remaking the reservation!`);
//} else if (guests > 100) {
agent.add(`You can't make a reservation for more than 100 guests. Please try remaking the reservation!`);
} else*/
if (dateTimeStart < now) {
agent.add(`You can't make a reservation in the past. Please try remaking the reservation.`);
} else if (bookingDate.getFullYear() > now.getFullYear()) {
agent.add(`You can't make a reservation for ${bookingDate.getFullYear()} yet. Please choose a date in ${now.getFullYear()}.`);
} else if (phone < 10) {
agent.add(`Your phone number has to be atleast 10 digits. Please try remaking the reservation!`);
} else if (phone > 15) {
agent.add(`Your phone number is too long. Please try remaking the reservation!`);
} else {
console.log("appointmentTimeString: ", appointmentTimeString);
// Check the availibility of the time, and make an appointment if there is time on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd, name, phonenumber, appointment_type).then(() => {
agent.add(`Ok, let me see if we can fit you in. ${appointmentTimeString} is fine!.`);
}).catch(() => {
agent.add(`I'm sorry, there are no slots available for ${appointmentTimeString}.`);
});
}
}
//Make the webhook calls
let intentMap = new Map();
intentMap.set('ScheduleAppointment.yes', makeAppointment);
agent.handleRequest(intentMap);
});
function createCalendarEvent(dateTimeStart, dateTimeEnd, name, phonenumber, appointment_type) {
const appointmentTimeString = dateTimeStart.toLocaleString('en-US', {
timeZone: 'Europe/Kaliningrad',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
return new Promise((resolve, reject) => {
for(let i=0;i<calendarId.length;i++){
calendar.events.list({
auth: serviceAccountAuth, // List events for time period
calendarId: calendarId[i],
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there is a event already on the Calendar
if (err || calendarResponse.data.items.length > 0) {
reject(err || new Error('Requested time conflicts with another appointment'));
} else {
// Create event for the requested time period
//let fatto=true;
calendar.events.insert({
auth: serviceAccountAuth,
calendarId: calendarId[i],
resource: {
summary: 'Appointment: ' + appointment_type,
description: "Date and time: " + appointmentTimeString + ',\n Name: ' + name + ',\n Phone number: ' + phonenumber,
start: {
dateTime: dateTimeStart
},
end: {
dateTime: dateTimeEnd
}
}
},(err, event) => {
err ? reject(event) : resolve(event);
});
}
});
}
});
}
包.json:
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "^0.6.1",
"nodemailer": "6.6.3",
"libphonenumber-js": "1.9.23"
}
}