Как найти время для встречи с несколькими участниками, используя Google Calendar API и Apps Script?

#google-apps-script #google-calendar-api #dialogflow-es

# #google-apps-script #google-calendar-api #dialogflow-es

Вопрос:

Я работаю над проектом чат-бота, используя Dialogflow API, Apps Script, Calendar API. Чат-бот должен иметь возможность организовать встречу между двумя или более участниками прямо из чата. Например, пользователь говорит что-то вроде «организуйте встречу с john.smith@mail.com на завтра в 5 часов вечера», и чат-бот должен перейти к обоим календарям — моему и Джона, проверить наличие свободных мест на этот период времени и забронировать встречу. Пока все хорошо. У меня уже есть решение для этого этапа (проверьте фрагмент кода ниже). Мой вопрос в том, заняты ли пользователи в течение этого периода времени, как я могу получить предлагаемое время, когда все участники свободны. Я использую свободный / занятый звонок, но он возвращается только тогда, когда пользователи заняты.

 //the function search in spreadshet containing all timezones and selects the corresponding offset
function setCorrectTimeZone(rawTime,rawDate){
  var spreadSheet = SpreadsheetApp.openById("10tJCi5bRHs3Cl8Gvw8NGMeHhfRBDnvPD338peH2MWyg"); //the timezones sheed ID stored in CEE Google Assistant shared drive
  var sheet = spreadSheet.getSheetByName("timezones");
  var timezoneRange = sheet.getRange(2, 1, 513, 2).getValues();
 
  //getting the user's timezone
  var userTimeZone = CalendarApp.getDefaultCalendar().getTimeZone();
  Logger.log("User time zone: "   userTimeZone);
  
  var userTimeZoneOffset = "";
  var correctDateTimeAndZone = "";

  //iterating over the timezones from the sheet and comparing with user's to find the correct offset
  for(var i = 0; i<timezoneRange.length; i  ){
    if(timezoneRange[i][1] == userTimeZone){
      userTimeZoneOffset = timezoneRange[i][0];
    }
  }
  
  //taking the date only
  var date = rawDate.split('T')[0];
  //taking the time only
   var timeNoTimeZone = rawTime.split(' ')[0].split('T')[1];
  //concatenating the date, time and the correct timezone together
  correctDateTimeAndZone = date   'T'   timeNoTimeZone   userTimeZoneOffset;
  return correctDateTimeAndZone;
}


function organizeMeeting(dialogflowRawResponse, email) {  
  var guestEmail = dialogflowRawResponse.queryResult.parameters.email; //the list of all guests
  var rawDate = dialogflowRawResponse.queryResult.parameters.date; 
  var rawTime = dialogflowRawResponse.queryResult.parameters.time;
  var eventTitle = dialogflowRawResponse.queryResult.parameters.meetingName;
  var hasAllParams = dialogflowRawResponse.queryResult.hasOwnProperty('allRequiredParamsPresent'); //checker for all parameters
  var correctedTimezone = setCorrectTimeZone(rawTime,rawDate);
  Logger.log("Has all required parameters? "   hasAllParams);
  
  //check if all parameters are passed
  while(hasAllParams == false){
    Logger.log("Parameters are missing");
    Logger.log(dialogflowRawResponse.queryResult.fulfillmentText);
    return { text: dialogflowRawResponse.queryResult.fulfillmentText };
  }
  
  Logger.log("Guests email list detected: "   JSON.stringify(guestEmail)   "nDate-time detected: "   rawTime   "nCorrect date-time timezone: "   correctedTimezone  "nTitle detected: "   eventTitle);

  //setting the date-time for the start and the end of the event
  var dateTimeStart = new Date(correctedTimezone);
  var dateTimeEnd = new Date(correctedTimezone);
  dateTimeEnd.setHours(dateTimeEnd.getHours()   1);
  dateTimeStart = dateTimeStart.toISOString();
  dateTimeEnd = dateTimeEnd.toISOString();
  Logger.log("ISO dateTimeStart: "   dateTimeStart);
  Logger.log("ISO dateTimeEnd: "   dateTimeEnd);
  
  
  var participants = [{"id": email}]; //array of objects. Each object is a particpant for the event
  for(var i = 0; i < guestEmail.length; i  ){
    participants.push({"id": guestEmail[i]}); //filling the participant array
  }
 
  //preparing the body for the Calendar API free-busy request
  var requestBody = {
    "timeMin": dateTimeStart,
    "timeMax": dateTimeEnd,
    "items": participants
  }
  
  //Calendar freebusy request to check if the slot is available for all particiaptns
  var response = Calendar.Freebusy.query(requestBody);
  
  for(var i = 0; i < participants.length; i  ){
    var calendarId = participants[i].id;
    if(response.calendars[calendarId]['busy'].length != 0){
      Logger.log(calendarId   " is busy at this time");
      return { text: calendarId   " is busy at this time" };
      break;
    }
  } 
  
  //guest array of objects for each participant
  var guestsArr = [{"email":email}];
  for(var i = 0; i < guestEmail.length; i  ){
    guestsArr.push({"email": guestEmail[i]});
  }
  
  //preparing the event details for the Calendar API call
  var event = {
    "summary": eventTitle,
    "end": {
      "dateTime": dateTimeEnd
    },
    "start": {
      "dateTime": dateTimeStart
    },
    "attendees": guestsArr
  }
  
  //preapring the event options for the Calendar API call
  var eventOptions = {
    "sendNotifications": true,
    "sendUpdates": "all"
  }
  
  //Calendar API call
  var calendarEventRequest = Calendar.Events.insert(event, "primary",eventOptions);
  
  //logs the Calendar API response to the logs
  Logger.log(JSON.stringify(calendarEventRequest));
  
  
  return { text: "Done! Check you calendar." };
}
 

Приведенный выше код принимает параметры из API Dialogflow — дату, время, название собрания и участников и использует эту информацию для выполнения свободного / занятого вызова, а затем, в конечном итоге, вызова API календаря. Он также использует базу данных электронных таблиц для поиска правильного часового пояса пользователя на основе местоположения пользователя.

Любая помощь будет высоко оценена, если кто-то уже использовал такую функцию, чтобы получить доступные временные интервалы.

Комментарии:

1. Я не думаю, что есть API для Google Calendar, чтобы получить свободное время, вам нужно будет вычислить это самостоятельно. Существует бесплатный API, который может быть полезен developers.google.com/calendar/v3/reference/freebusy/query

Ответ №1:

Вы можете проверить каждый часовой временной интервал, если все свободны, если все свободны, затем отправить приглашения в Календаре.

Пример кода:

     var dateTimeStart = new Date(correctedTimezone);
    var dateTimeEnd = new Date(correctedTimezone);

do {

    dateTimeEnd.setHours(dateTimeStart.getHours()   1);
    dateTimeStart = dateTimeStart.toISOString();
    dateTimeEnd = dateTimeEnd.toISOString();
    Logger.log("ISO dateTimeStart: "   dateTimeStart);
    Logger.log("ISO dateTimeEnd: "   dateTimeEnd);
  
  
    var participants = [{"id": email}]; //array of objects. Each object is a particpant for the event
    for(var i = 0; i < guestEmail.length; i  ){
        participants.push({"id": guestEmail[i]}); //filling the participant array
    }
 
  //preparing the body for the Calendar API free-busy request
    var requestBody = {
        "timeMin": dateTimeStart,
        "timeMax": dateTimeEnd,
        "items": participants
    }
  
  //Calendar freebusy request to check if the slot is available for all particiaptns
    var response = Calendar.Freebusy.query(requestBody);
  
    for(var i = 0; i < participants.length; i  ){
        var calendarId = participants[i].id;
        if(response.calendars[calendarId]['busy'].length != 0){
           dateTimeStart.setHours(dateTimeStart.getHours()   1);
           Logger.log(calendarId   " is busy at this time");
           //return { text: calendarId   " is busy at this time" };
        break;
    }
  } 

}
while (response.calendars[calendarId]['busy'].length != 0);