Pianificare le riunioni da Google Chat

Livello di programmazione: intermedio
Durata: 25 minuti
Tipo di progetto: app Google Chat

Obiettivi

  • Comprendi cosa fa la soluzione.
  • Scopri cosa fanno i servizi Apps Script all'interno soluzione.
  • Configurare l'ambiente.
  • Configura lo script.
  • Esegui lo script.

Informazioni su questa soluzione

Programma una riunione in Google Calendar da un messaggio diretto o da un in Google Chat. Puoi impostare dettagli specifici per la riunione, ad esempio soggetto, l'ora di inizio o la durata oppure usa le impostazioni predefinite per programmazione di riunioni.

Interfaccia di dialogo dell'app Chat dello strumento di pianificazione delle riunioni

Come funziona

Lo script dell'app di chat utilizza comandi slash e di dialogo per i dettagli delle riunioni dagli utenti e pianificare un evento nel calendario. La lo script include impostazioni predefinite della riunione che possono essere personalizzate in base alle tue esigenze e alle esigenze aziendali.

Servizi Apps Script

Questa soluzione utilizza i seguenti servizi:

  • Servizio Calendar: crea il evento di calendario dalle informazioni fornite sulla riunione.
  • Servizio di base: utilizza la classe Session per ottenere al fuso orario dello script. Calendar utilizza questo fuso orario quando stai programmando l'evento.
  • Servizio di pubblica utilità: formatta la data per l'evento di calendario e codifica l'ID evento per facilitare il recupero dell'URL dell'evento.

Prerequisiti

Per utilizzare questo esempio, sono necessari i seguenti prerequisiti:

  • Un Account Google (gli account Google Workspace possono richiedono l'approvazione dell'amministratore).
  • Un browser web con accesso a internet.
  • Un progetto Google Cloud.

Configura l'ambiente

Apri il tuo progetto Cloud nella console Google Cloud

Se non è già aperto, apri il progetto Cloud che intendi utilizzare per questo esempio:

  1. Nella console Google Cloud, vai alla pagina Seleziona un progetto.

    Seleziona un progetto Cloud

  2. Seleziona il progetto Google Cloud che vuoi utilizzare. In alternativa, fai clic su Crea progetto e segui le istruzioni sullo schermo. Se crei un progetto Google Cloud, potrebbe essere necessario attivare la fatturazione per il progetto.

Attiva l'API

Prima di utilizzare le API di Google, devi attivarle in un progetto Google Cloud. Puoi attivare una o più API in un singolo progetto Google Cloud.

Tutte le app di chat richiedono una configurazione della schermata di consenso. Configurazione in corso... la schermata per il consenso OAuth dell'app definisce ciò che Google mostra agli utenti e registra la tua app per permetterti di pubblicarla in un secondo momento.

  1. Nella console Google Cloud, vai al Menu > API e Servizi > Schermata consenso OAuth.

    Vai alla schermata per il consenso OAuth

  2. In Tipo di utente, seleziona Interno, quindi fai clic su Crea.
  3. Compila il modulo di registrazione dell'app, quindi fai clic su Salva e continua.
  4. Per ora, puoi saltare l'aggiunta di ambiti e fare clic su Salva e continua. In futuro, quando creerai un'app da utilizzare al di fuori del tuo Nell'organizzazione Google Workspace, devi modificare il Tipo di utente in Esterno e poi aggiungi gli ambiti di autorizzazione richiesti dalla tua app.

  5. Esamina il riepilogo della registrazione dell'app. Per apportare modifiche, fai clic su Modifica. Se l'app la registrazione sembra a posto, fai clic su Torna alla Dashboard.

Configurare lo script

Creare il progetto Apps Script

  1. Fai clic sul pulsante seguente per aprire Pianifica riunioni da Google Chat progetto Apps Script.
    Apri il progetto
  2. Fai clic su Panoramica .
  3. Nella pagina Panoramica, fai clic su Crea una copia Icona per creare una copia.

Copia il numero del progetto Cloud

  1. Nella console Google Cloud, vai al Menu > IAM e Amministratore > Impostazioni.

    Vai a Impostazioni IAM e amministrazione

  2. Copia il valore nel campo Numero progetto.

Impostare il progetto Cloud del progetto Apps Script

  1. Nel progetto Apps Script copiato fai clic su Impostazioni progetto Icona delle impostazioni progetto.
  2. In Progetto Google Cloud Platform (Google Cloud), fai clic su Cambia progetto.
  3. In Numero di progetto Google Cloud, incolla il numero di progetto Google Cloud.
  4. Fai clic su Imposta progetto.

Crea un deployment di test

  1. Nel progetto Apps Script copiato, fai clic su Esegui il deployment. > Testa i deployment.
  2. Copia l'ID deployment principale per utilizzarlo in un passaggio successivo e fai clic su Fine.

Configura l'API Chat

  1. Nella console Google Cloud, vai alla pagina dell'API Chat.
    Vai all'API Chat
  2. Fai clic su Configurazione.
  3. Configura l'API Chat con le seguenti informazioni:
    • Nome: Meeting Scheduler
    • URL avatar: aggiungi un URL che indirizza a un'immagine con una dimensione minima di 256 x 256 pixel.
    • Descrizione: Quickly create meetings.
    • Funzionalità: seleziona entrambe le caselle per consentire agli utenti di inviare messaggi direttamente all'app e aggiungerla agli spazi.
    • Connection settings (Impostazioni di connessione): fai clic su Apps Script e inserisci il valore l'ID deployment head.
    • Comandi slash: aggiungi comandi slash per /help e /schedule_Meeting procedendo nel seguente modo:
      1. Fai clic su Aggiungi comando slash e configuralo con quanto segue informazioni:
          .
        • Nome: /help
        • ID comando: 1
        • Descrizione: Learn what this app does.
      2. Fai di nuovo clic su Aggiungi comando slash e configuralo con quanto segue informazioni:
          .
        • Nome: /schedule_Meeting
        • ID comando: 2
        • Descrizione: Schedule a meeting.
        • Seleziona la finestra di dialogo Apre una finestra di dialogo.
    • Autorizzazioni: seleziona Persone e gruppi specifici nel dominio e inserisci il tuo indirizzo email.
  4. Fai clic su Salva e aggiorna la pagina.
  5. Nella pagina di configurazione, in Stato applicazione, imposta lo stato su Dal vivo - Disponibile per gli utenti.
  6. Fai clic su Salva.

Esegui lo script

  1. Apri Google Chat.
  2. Fai clic su Avvia una chat .
  3. Cerca il nome dell'app, Meeting Scheduler.
  4. Invia un messaggio iniziale, ad esempio hello, per richiedere l'autorizzazione.
  5. Quando l'app risponde, fai clic su Configura e autorizza l'app. Se nella schermata per il consenso OAuth viene visualizzato l'avviso Questa app non è stata verificata. continua selezionando Avanzate > Vai a {Project Name} (non sicuro).

  6. Invia /schedule_Meeting all'app.

  7. Nella finestra di dialogo, aggiungi almeno un indirizzo email di invito. Puoi aggiornare altri campi o utilizzare le voci predefinite.

  8. Fai clic su Invia.

  9. Per visualizzare la riunione, fai clic su Apri evento di Calendar.

Esamina il codice

Per esaminare il codice Apps Script per questa soluzione, fai clic su Visualizza il codice sorgente di seguito:

Visualizza codice sorgente

Code.gs

solutions/chat-bots/schedule-meetings/Code.js
// To learn how to use this script, refer to the documentation:
// https://developers.google.com/apps-script/samples/chat-bots/schedule-meetings

/*
Copyright 2022 Google LLC

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

    https://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.
*/

// Application constants
const BOTNAME = 'Chat Meeting Scheduler';
const SLASHCOMMAND = {
  HELP: 1, // /help
  DIALOG: 2, // /schedule_Meeting
};

/**
 * Responds to an ADDED_TO_SPACE event in Google Chat.
 * Called when the bot is added to a space. The bot can either be directly added to the space
 * or added by a @mention. If the bot is added by a @mention, the event object includes a message property. 
 * Returns a Message object, which is usually a welcome message informing users about the bot.
 *
 * @param {Object} event The event object from Google Chat
 */
function onAddToSpace(event) {
  let message = '';

  // Personalizes the message depending on how the bot is called.
  if (event.space.singleUserBotDm) {
    message = `Hi ${event.user.displayName}!`;
  } else {
    const spaceName = event.space.displayName ? event.space.displayName : "this chat";
    message = `Hi! Thank you for adding me to ${spaceName}`;
  }

  // Lets users know what they can do and how they can get help.
  message = message + '/nI can quickly schedule a meeting for you with just a few clicks.' +
    'Try me out by typing */schedule_Meeting*. ' +
    '/nTo learn what else I can do, type */help*.'

  return { "text": message };
}

/**
 * Responds to a MESSAGE event triggered in Chat.
 * Called when the bot is already in the space and the user invokes it via @mention or / command.
 * Returns a message object containing the bot's response. For this bot, the response is either the
 * help text or the dialog to schedule a meeting.
 * 
 * @param {object} event The event object from Google Chat
 * @return {object} JSON-formatted response as text or Card message
 */
function onMessage(event) {

  // Handles regular onMessage logic.
  // Evaluates if and handles for all slash commands.
  if (event.message.slashCommand) {
    switch (event.message.slashCommand.commandId) {

      case SLASHCOMMAND.DIALOG: // Displays meeting dialog for /schedule_Meeting.

        // TODO update this with your own logic to set meeting recipients, subjects, etc (e.g. a group email).
        return getInputFormAsDialog_({
          invitee: '',
          startTime: getTopOfHourDateString_(),
          duration: 30,
          subject: 'Status Stand-up',
          body: 'Scheduling a quick status stand-up meeting.'
        });

      case SLASHCOMMAND.HELP: // Responds with help text for /help.
        return getHelpTextResponse_();

      /* TODO Add other use cases here. E.g:
      case SLASHCOMMAND.NEW_FEATURE:  // Your Feature Here
        getDialogForAddContact(message);
      */

    }
  }
  else {
    // Returns text if users didn't invoke a slash command.
    return { text: 'No action taken - use Slash Commands.' }
  }
}

/**
 * Responds to a CARD_CLICKED event triggered in Chat.
 * @param {object} event the event object from Chat
 * @return {object} JSON-formatted response
 * @see https://developers.google.com/chat/api/guides/message-formats/events
 */
function onCardClick(event) {
  if (event.action.actionMethodName === 'handleFormSubmit') {
    const recipients = getFieldValue_(event.common.formInputs, 'email');
    const subject = getFieldValue_(event.common.formInputs, 'subject');
    const body = getFieldValue_(event.common.formInputs, 'body');

    // Assumes dialog card inputs for date and times are in the correct format. mm/dd/yyy HH:MM
    const dateTimeInput = getFieldValue_(event.common.formInputs, 'date');
    const startTime = getStartTimeAsDateObject_(dateTimeInput);
    const duration = Number(getFieldValue_(event.common.formInputs, 'duration'));

    // Handles instances of missing or invalid input parameters.
    const errors = [];

    if (!recipients) {
      errors.push('Missing or invalid recipient email address.');
    }
    if (!subject) {
      errors.push('Missing subject line.');
    }
    if (!body) {
      errors.push('Missing event description.');
    }
    if (!startTime) {
      errors.push('Missing or invalid start time.');
    }
    if (!duration || isNaN(duration)) {
      errors.push('Missing or invalid duration');
    }
    if (errors.length) {
      // Redisplays the form if missing or invalid inputs exist.
      return getInputFormAsDialog_({
        errors,
        invitee: recipients,
        startTime: dateTimeInput,
        duration,
        subject,
        body
      });
    }

    //  Calculates the end time via duration.
    const endTime = new Date(startTime.valueOf());
    endTime.setMinutes(endTime.getMinutes() + duration);

    // Creates calendar event with notification.
    const calendar = CalendarApp.getDefaultCalendar()
    const scheduledEvent = calendar.createEvent(subject,
      startTime,
      endTime,
      {
        guests: recipients,
        sendInvites: true,
        description: body + '\nThis meeting scheduled by a Google Chat App!'
      });

    // Gets a link to the Calendar event.
    const url = getCalendarEventURL_(scheduledEvent, calendar)

    return getConfirmationDialog_(url);

  } else if (event.action.actionMethodName === 'closeDialog') {

    // Returns this dialog as success.
    return {
      actionResponse: {
        type: 'DIALOG',
        dialog_action: {
          actionStatus: 'OK'
        }
      }
    }
  }
}

/**
 * Responds with help text about this chat bot.
 * @return {string} The help text as seen below
 */
function getHelpTextResponse_() {
  const help = `*${BOTNAME}* lets you quickly create meetings from Google Chat. Here\'s a list of all its commands:
  \`/schedule_Meeting\`  Opens a dialog with editable, preset parameters to create a meeting event
  \`/help\`  Displays this help message

  Learn more about creating Google Chat bots at https://developers.google.com/chat.`

  return { 'text': help }
}

Dialog.gs

solutions/chat-bots/schedule-meetings/Dialog.js
/**
 * Copyright 2022 Google LLC
 *
 * 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.
 */

/**
* Form input dialog as JSON.
* @return {object} JSON-formatted cards for the dialog.
*/
function getInputFormAsDialog_(options) {
  const form = getForm_(options);
  return {
    'actionResponse': {
      'type': 'DIALOG',
      'dialogAction': {
        'dialog': {
          'body': form
        }
      }
    }
  };
}

/**
* Form JSON to collect inputs regarding the meeting.
* @return {object} JSON-formatted cards.
*/
function getForm_(options) {
  const sections = [];

  // If errors present, display additional section with validation messages.
  if (options.errors && options.errors.length) {
    let errors = options.errors.reduce((str, err) => `${str}• ${err}<br>`, '');
    errors = `<b>Errors:</b><br><font color="#ba0000">${errors}</font>`;
    const errorSection = {
      'widgets': [
        {
          textParagraph: {
            text: errors
          }
        }
      ]
    }
    sections.push(errorSection);
  }
  let formSection = {
    'header': 'Schedule meeting and send email to invited participants',
    'widgets': [
      {
        'textInput': {
          'label': 'Event Title',
          'type': 'SINGLE_LINE',
          'name': 'subject',
          'value': options.subject
        }
      },
      {
        'textInput': {
          'label': 'Invitee Email Address',
          'type': 'SINGLE_LINE',
          'name': 'email',
          'value': options.invitee,
          'hintText': 'Add team group email'
        }
      },
      {
        'textInput': {
          'label': 'Description',
          'type': 'MULTIPLE_LINE',
          'name': 'body',
          'value': options.body
        }
      },
      {
        'textInput': {
          'label': 'Meeting start date & time',
          'type': 'SINGLE_LINE',
          'name': 'date',
          'value': options.startTime,
          'hintText': 'mm/dd/yyyy H:MM'
        }
      },
      {
        'selectionInput': {
          'type': 'DROPDOWN',
          'label': 'Meeting Duration',
          'name': 'duration',
          'items': [
            {
              'text': '15 minutes',
              'value': '15',
              'selected': options.duration === 15
            },
            {
              'text': '30 minutes',
              'value': '30',
              'selected': options.duration === 30
            },
            {
              'text': '45 minutes',
              'value': '45',
              'selected': options.duration === 45
            },
            {
              'text': '1 Hour',
              'value': '60',
              'selected': options.duration === 60
            },
            {
              'text': '1.5 Hours',
              'value': '90',
              'selected': options.duration === 90
            },
            {
              'text': '2 Hours',
              'value': '120',
              'selected': options.duration === 120
            }
          ]
        }
      }
    ],
    'collapsible': false
  };
  sections.push(formSection);
  const card =  {
    'sections': sections,
    'name': 'Google Chat Scheduled Meeting',
    'fixedFooter': {
      'primaryButton': {
        'text': 'Submit',
        'onClick': {
          'action': {
            'function': 'handleFormSubmit'
          }
        },
        'altText': 'Submit'
      }
    }
  };
  return card;
}

/**
* Confirmation dialog after a calendar event is created successfully.
* @param {string} url The Google Calendar Event url for link button
* @return {object} JSON-formatted cards for the dialog
*/
function getConfirmationDialog_(url) {
  return {
    'actionResponse': {
      'type': 'DIALOG',
      'dialogAction': {
        'dialog': {
          'body': {
            'sections': [
              {
                'widgets': [
                  {
                    'textParagraph': {
                      'text': 'Meeting created successfully!'
                    },
                    'horizontalAlignment': 'CENTER'
                  },
                  {
                    'buttonList': {
                      'buttons': [
                        {
                          'text': 'Open Calendar Event',
                          'onClick': {
                            'openLink': {
                              'url': url
                            }
                          }
                        }

                      ]
                    },
                    'horizontalAlignment': 'CENTER'
                  }
                ]
              }
            ],
            'fixedFooter': {
              'primaryButton': {
                'text': 'OK',
                'onClick': {
                  'action': {
                    'function': 'closeDialog'
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Utilities.gs

solutions/chat-bots/schedule-meetings/Utilities.js
/**
 * Copyright 2022 Google LLC
 *
 * 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.
 */

/**
* Helper function that gets the field value from the given form input.
* @return {string} 
*/
function getFieldValue_(formInputs, fieldName) {
  return formInputs[fieldName][''].stringInputs.value[0];
}

// Regular expression to validate the date/time input.
const DATE_TIME_PATTERN = /\d{1,2}\/\d{1,2}\/\d{4}\s+\d{1,2}:\d\d/;

/**
* Casts date and time from string to Date object.
* @return {date} 
*/
function getStartTimeAsDateObject_(dateTimeStr) {
  if (!dateTimeStr || !dateTimeStr.match(DATE_TIME_PATTERN)) {
    return null;
  }

  const parts = dateTimeStr.split(' ');
  const [month, day, year] = parts[0].split('/').map(Number);
  const [hour, minute] = parts[1].split(':').map(Number);


  Session.getScriptTimeZone()

  return new Date(year, month - 1, day, hour, minute)
}

/** 
* Gets the current date and time for the upcoming top of the hour (e.g. 01/25/2022 18:00).
* @return {string} date/time in mm/dd/yyy HH:MM format needed for use by Calendar
*/
function getTopOfHourDateString_() {
  const date = new Date();
  date.setHours(date.getHours() + 1);
  date.setMinutes(0, 0, 0);
  // Adding the date as string might lead to an incorrect response due to time zone adjustments.
  return Utilities.formatDate(date, Session.getScriptTimeZone(), 'MM/dd/yyyy H:mm');
}


/** 
* Creates the URL for the Google Calendar event.
*
* @param {object} event The Google Calendar Event instance
* @param {object} cal The associated Google Calendar 
* @return {string} URL in the form of 'https://www.google.com/calendar/event?eid={event-id}'
*/
function getCalendarEventURL_(event, cal) {
  const baseCalUrl = 'https://www.google.com/calendar';
  // Joins Calendar Event Id with Calendar Id, then base64 encode to derive the event URL.
  let encodedId = Utilities.base64Encode(event.getId().split('@')[0] + " " + cal.getId()).replace(/\=/g, '');
  encodedId = `/event?eid=${encodedId}`;
  return (baseCalUrl + encodedId);

}

Collaboratori

Questo campione è gestito da Google con l'aiuto degli Esperti Google Developers.

Passaggi successivi