Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No appointment created! #6

Closed
shnathoskhan opened this issue Jul 25, 2018 · 10 comments
Closed

No appointment created! #6

shnathoskhan opened this issue Jul 25, 2018 · 10 comments

Comments

@shnathoskhan
Copy link

shnathoskhan commented Jul 25, 2018

when I ask an agent.

end result, always showing this message only.
I'm sorry, there are no slots available for Invalid Date, would you like to check another day?

No appointment created. :(

pls, help me.

@shnathoskhan shnathoskhan changed the title Error always Jul 25, 2018
@shnathoskhan shnathoskhan changed the title always date and time error Jul 25, 2018
@shnathoskhan shnathoskhan changed the title date and time error No appointment created! Jul 25, 2018
@aradwyr
Copy link

aradwyr commented Jul 25, 2018

Can you post your code?

@aradwyr
Copy link

aradwyr commented Jul 25, 2018

Make sure to have the most recent updated versions installed:

"dependencies": { "actions-on-google":"^2.2.0", "firebase-functions": "^0.6.2", "firebase-admin": "^5.2.1", "googleapis": "27.0.0", "dialogflow-fulfillment": "0.5.0" }

@shnathoskhan
Copy link
Author

@sarahdwyer

PFA.

index.js

/**

  • Copyright 2017 Google Inc. All Rights Reserved.
  • 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';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');

// Enter your calendar ID below and service account JSON below, see https://github.com/dialogflow/bike-shop/blob/master/README.md#calendar-setup
const calendarId = ' /deleted my self/'; // looks like "[email protected]"
const serviceAccount = { /deleted my self/ };
// Starts with {"type": "service_account",...

// Set up Google Calendar Service account credentials
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

const timeZone = 'Asia/Colombo';
const timeZoneOffset = '-05:30';

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });

function hours (agent) {
if (currentlyOpen()) {
agent.add(We're open now! We close at 5:30pm today.);
} else {
agent.add(We're currently closed, but we open every weekday at 9am!);
}
}

function makeAppointment (agent) {
// Calculate appointment start and end datetimes (end = +1hr from start)
const dateTimeStart = new Date(Date.parse(agent.parameters.date + 'T' + agent.parameters.time + timeZoneOffset));
const dateTimeEnd = new Date(new Date(dateTimeStart).setHours(dateTimeStart.getHours() + 1));
const appointmentTimeString = dateTimeStart.toLocaleString(
'en-US',
{ month: 'long', day: 'numeric', hour: 'numeric', timeZone: timeZone }
);

// Check the availibility of the time, and make an appointment if there is time on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd).then(() => {
  agent.add(`Ok, let me see if we can fit you in.  ${appointmentTimeString} is fine!.  Do you need a repair or just a tune-up?`);
}).catch(() => {
  agent.add(`I'm sorry, there are no slots available for ${appointmentTimeString}, would you like to check another day?`);
});

}

let intentMap = new Map();
intentMap.set('Hours', hours);
intentMap.set('Make Appointment', makeAppointment);
agent.handleRequest(intentMap);
});

function currentlyOpen () {
var currentDateTime = new Date(); // current time
var hours = currentDateTime.getHours();
var mins = currentDateTime.getMinutes();
var day = currentDateTime.getDay();

return day >= 1 &&
day <= 5 &&
hours >= 9 &&
(hours < 17 || hours === 17 && mins <= 30);
}

function createCalendarEvent (dateTimeStart, dateTimeEnd) {
return new Promise((resolve, reject) => {
calendar.events.list({
auth: serviceAccountAuth, // List events for time period
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there is a event already on the Bike Shop Calendar
if (err || calendarResponse.data.items.length > 0) {
reject(err || new Error('Requested time conflicts with another appointment'));
}
// Create event for the requested time period
calendar.events.insert({ auth: serviceAccountAuth,
calendarId: calendarId,
resource: {summary: 'Bike Appointment',
start: {dateTime: dateTimeStart},
end: {dateTime: dateTimeEnd}}
}, (err, event) => {
err ? reject(err) : resolve(event);
}
);
});
});
}

package.json
{
"name": "dialogflowFirebaseFulfillment",
"description": "Dialogflow fulfillment for the bike shop sample",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "~4.2"
},
"scripts": {
"lint": "semistandard --fix "**/*.js"",
"start": "firebase deploy --only functions",
"deploy": "firebase deploy --only functions"
},
"dependencies": {
"actions-on-google":"^2.2.0",
"firebase-functions": "^0.6.2",
"firebase-admin": "^5.2.1",
"googleapis": "27.0.0",
"dialogflow-fulfillment": "0.3.0-beta.1"
}
}

@shnathoskhan
Copy link
Author

shnathoskhan commented Jul 29, 2018

Always showing this result...

I'm sorry, there are no slots available for Invalid Date, would you like to check another day?

Pls, anyone Help me.

@aradwyr
Copy link

aradwyr commented Aug 1, 2018

@shnathoskhan
First try updating your dependencies:

"node": "6"

"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"dialogflow-fulfillment": "0.5.0"
}

@aradwyr aradwyr closed this as completed Aug 7, 2018
@urpandey88
Copy link

Hi sarah,
I am also getting same error, there are no slots available for Invalid Date, would you like to check another day?

My code package.json

{
"name": "DialogflowFirebaseWebhook",
"description": "Firebase Webhook dependencies for a Dialogflow agent.",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "6"
},
"scripts": {
"lint": "semistandard --fix "**/*.js"",
"start": "firebase deploy --only functions",
"deploy": "firebase deploy --only functions"
},

"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^0.6.0",
"googleapis": "^27.0.0",
"dialogflow-fulfillment": "0.5.0"
}
}

index.js

/**

  • Copyright 2017 Google Inc. All Rights Reserved.
  • 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';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');

// Enter your calendar ID and service account JSON below.
const calendarId = '[email protected]'; // Example: [email protected]
const serviceAccount = {}; // The JSON object looks like: { "type": "service_account", ... }

// Set up Google Calendar service account credentials
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:*'; // It enables lib debugging statements

const timeZone = 'America/Los_Angeles'; // Change it to your time zone
const timeZoneOffset = '-07:00'; // Change it to your time zone offset

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });

function makeAppointment (agent) {
// Use the Dialogflow's date and time parameters to create Javascript Date instances, 'dateTimeStart' and 'dateTimeEnd',
// which are used to specify the appointment's time.
const appointmentDuration = 1;// Define the length of the appointment to be one hour.
const dateTimeStart = convertParametersDate(agent.parameters.date, agent.parameters.time);
const dateTimeEnd = addHours(dateTimeStart, appointmentDuration);
const appointmentTimeString = getLocaleTimeString(dateTimeStart);
const appointmentDateString = getLocaleDateString(dateTimeStart);
// Check the availability of the time slot and set up an appointment if the time slot is available on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd).then(() => {
agent.add(Got it. I have your appointment scheduled on ${appointmentDateString} at ${appointmentTimeString}. See you soon. Good-bye.);
}).catch(() => {
agent.add(Sorry, we're booked on ${appointmentDateString} at ${appointmentTimeString}. Is there anything else I can do for you?);
});
}
let intentMap = new Map();
intentMap.set('Make Appointment', makeAppointment); // It maps the intent 'Make Appointment' to the function 'makeAppointment()'
agent.handleRequest(intentMap);
});

function createCalendarEvent (dateTimeStart, dateTimeEnd) {
return new Promise((resolve, reject) => {
calendar.events.list({ // List all events in the specified time period
auth: serviceAccountAuth,
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there exists any event on the calendar given the specified the time period
if (err || calendarResponse.data.items.length > 0) {
reject(err || new Error('Requested time conflicts with another appointment'));
} else {
// Create an event for the requested time period
calendar.events.insert({ auth: serviceAccountAuth,
calendarId: calendarId,
resource: {summary: 'Bike Appointment',
start: {dateTime: dateTimeStart},
end: {dateTime: dateTimeEnd}}
}, (err, event) => {
err ? reject(err) : resolve(event);
}
);
}
});
});
}

// A helper function that receives Dialogflow's 'date' and 'time' parameters and creates a Date instance.
function convertParametersDate(date, time){
return new Date(Date.parse(date.split('T')[0] + 'T' + time.split('T')[1].split('-')[0] + timeZoneOffset));
}

// A helper function that adds the integer value of 'hoursToAdd' to the Date instance 'dateObj' and returns a new Data instance.
function addHours(dateObj, hoursToAdd){
return new Date(new Date(dateObj).setHours(dateObj.getHours() + hoursToAdd));
}

// A helper function that converts the Date instance 'dateObj' into a string that represents this time in English.
function getLocaleTimeString(dateObj){
return dateObj.toLocaleTimeString('en-US', { hour: 'numeric', hour12: true, timeZone: timeZone });
}

// A helper function that converts the Date instance 'dateObj' into a string that represents this date in English.
function getLocaleDateString(dateObj){
return dateObj.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', timeZone: timeZone });
}

Kindly help me to solve this issue.

@SCUSHI
Copy link

SCUSHI commented Apr 14, 2019

Hi,

I do have the same problem. Please help us find a solution.

@SCUSHI
Copy link

SCUSHI commented Apr 14, 2019

Invalid Date

{
"name": "dialogflowFirebaseFulfillment",
"description": "Dialogflow fulfillment for the bike shop sample",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "6"
},
"scripts": {
"lint": "semistandard --fix "**/*.js"",
"start": "firebase deploy --only functions",
"deploy": "firebase deploy --only functions"
},
"dependencies": {
"firebase-functions": "2.0.2",
"firebase-admin": "^5.13.1",
"actions-on-google": "2.2.0",
"googleapis": "^27.0.0",
"dialogflow-fulfillment": "0.5.0"
}
}

/**

  • Copyright 2017 Google Inc. All Rights Reserved.
  • 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';

const functions = require('firebase-functions');
const {google} = require('googleapis');
const {WebhookClient} = require('dialogflow-fulfillment');

// Enter your calendar ID below and service account JSON below, see https://github.com/dialogflow/bike-shop/blob/master/README.md#calendar-setup
const calendarId = '[email protected]'; // looks like "[email protected]"
const serviceAccount = {
"type": "service_account",
"project_id": "bikeshopsample-d7b5b",
"private_key_id": "e8c94e4776bebb61f6505642936b80bcfdb8fd25",
"private_key": "e8c94e4776bebb61f6505642936b80bcfdb8fd25\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDaiEFtVJ8DgYZJ\neiWY33I0c9dsCf1QxefySd5ACepBIT3+GxixbooXLCndojiGPot6qLhnL+hM0sTf\nNl1p3SizTQHOGkiHWvVlyMtSPYUw4dz2PZfufm4sjcZbmC+0EeWE3S4V8ul2kHmv\n5OcAnaZehFjSG/3NhEqKW1+BwvRGeUbZY0ZbGnaSIGT0hss29//oiK+pnkB2egUn\niom1XGpLbxr5anbutVyJaWZ+x3TojMcFpC+78TToiOSdt2GrDXEoP8SN/zbfs6+b\nsQhMXTahYG5YGGBRv3dXaiBCyGrGaOuFjVCVDAy3rEIKVrAYR4IeIR1EZkAJkTrN\nJDSnrM+DAgMBAAECggEACoYNQIqWrcCLCvbK4LXB9iyt7xH8FOuy48QS49qWYVSM\ne7QqWEEOfVcvHPE276ALb3i4iJ+R/EEaIfWoQfTYhOnscFRrsbj7oE8vG2LDCzuV\nPHZy3pVQEO0y5C5L/cvu1ZshIQV1oLQMaCAJz8nHvT16WYPnkQIR5N/JlaIhyVLu\n8i8+B7JVxZ/A1tWlNePeQxHcxlSscGSb1//KWdQob/3pFku7dD3/PZshnTn+VzZR\ncQ5FS1qArff/TD+mHwmKXdm7pU3ZZErQCdb/D+RQmBKs9qVZEVERBlxf29D1AE08\nW7AvCQUzSanj9hED8l9uzN9PtEJD17ppWv55UMGlgQKBgQD+/neoOEXfzedhpl0d\nvMl3Txk3tErKd8m5PVd7vYz3DnFAbazJmMd7/s5ljs6n2dZ1atGv0JYpf233IKA7\nLgvC5I7i0J/A09n/sZMucl4Olfydfapj8Tly8NHilQqGSc9xUssMk1gv6D80Nw5r\neJHnad8lWMJbiPUGpDte+AobcQKBgQDbZPahyowda9hytcn1OI2Woyi/pgo7gVyQ\n+c2hyoG4Vhvw6r3cD2dEgfoiU/ATXibalAgrbXsp3yd6m//r3gxGKWbIgoYthIiL\nhZykZ9Y8ITAkdQKcxO7z5lGnHPdBgUj1GBvrp87EkVu5yxdvgJyGkBI50iwoekM2\npDf6aaLYMwKBgQCfyABernRKWxGDxOVQPv3W/v+EQjsjR5BlvKRW612raadZgd/l\nqxBFCFN4m9Wuo/eYN8kQ7BlMA4d6dT0yGBZSlzlZsvSHtbhCWpkpX4zEgwN6BEaC\nvaML/Q7ndhDUOOf90K1fQezeiB8iruUgPrreUR78nfObu+Qdt0dkqPRcYQKBgQDU\nRGsbPo0yKhXRZnFwALd893+FbXCZAiA9ZHPABd5cK3P9NCFduMmBTwBkFjJBiuas\ntGzzF4oCiRX5WtXRr5TQjV4UwbRwdbpmw2864fw1USbzHwLYCvHmqQB3X18a0at0\n906MQl+bb8f/iq+yAg1vZBU+PErdHu3JADno3ivgYQKBgFB+bXO4gR+qNjowpch2\n8DyMqDgmfEjQK57MoApG29KOENWLK5CXMAT6JK4uQwJPQJZYMsqxUnzGqJpIihsF\nBwKe/sJPgXAm5AgoDKnZzcEnruW7uG0Qheh1YqmEJwKuUsQmk1NmKRWFxMn5QMyz\nZEJ0D83A5kxPL5LSuozASq3h\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "103027792139444114351",
"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/bike-shop-calender%40bikeshopsample-d7b5b.iam.gserviceaccount.com"
} ; // Starts with {"type": "service_account",...

// Set up Google Calendar Service account credentials
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

const timeZone = 'Europe/Berlin';
const timeZoneOffset = '+02:00';

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });

function hours (agent) {
if (currentlyOpen()) {
agent.add(We're open now! We close at 5pm today.);
} else {
agent.add(We're currently closed, but we open every weekday at 9am!);
}
}

function makeAppointment (agent) {
// 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() + 1));
const appointmentTimeString = dateTimeStart.toLocaleString(
'en-US',
{ month: 'long', day: 'numeric', hour: 'numeric', timeZone: timeZone }
);

// Check the availibility of the time, and make an appointment if there is time on the calendar
return createCalendarEvent(dateTimeStart, dateTimeEnd).then(() => {
  agent.add(`Ok, let me see if we can fit you in. ${appointmentTimeString} is fine!. Do you need a repair or just a tune-up?`);
}).catch(() => {
  agent.add(`I'm sorry, there are no slots available for ${appointmentTimeString}.`);
});

}

let intentMap = new Map();
intentMap.set('Hours', hours);
intentMap.set('Make Appointment', makeAppointment);
agent.handleRequest(intentMap);
});

function currentlyOpen () {
// Get current datetime with proper timezone
let date = new Date();
date.setHours(date.getHours() + parseInt(timeZoneOffset.split(':')[0]));
date.setMinutes(date.getMinutes() + parseInt(timeZoneOffset.split(':')[0][0] + timeZoneOffset.split(':')[1]));

return date.getDay() >= 1 &&
date.getDay() <= 5 &&
date.getHours() >= 9 &&
date.getHours() <= 17;
}

function createCalendarEvent (dateTimeStart, dateTimeEnd) {
return new Promise((resolve, reject) => {
calendar.events.list({
auth: serviceAccountAuth, // List events for time period
calendarId: calendarId,
timeMin: dateTimeStart.toISOString(),
timeMax: dateTimeEnd.toISOString()
}, (err, calendarResponse) => {
// Check if there is a event already on the Bike Shop 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
calendar.events.insert({ auth: serviceAccountAuth,
calendarId: calendarId,
resource: {summary: 'Bike Appointment',
start: {dateTime: dateTimeStart},
end: {dateTime: dateTimeEnd}}
}, (err, event) => {
err ? reject(err) : resolve(event);
}
);
}
});
});
}

@Tsitsi-Primrose
Copy link

Hi guys, I don't know if this is still going to help anyone. Battled with the same issue for 2 days and it finally worked today. So in stripping the dates, I had to strip a + instead of a - since my time formats have a + since I'm in South Africa. This solved the 'invalid date' part but it still didn't insert in the calendar. Then I realised that in calendar permissions I had to change the permissions for the email that we get from the json file to "make changes to events". Then it worked.

@mdfarooq0815
Copy link

Someone has discussed this issue here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants