Besprechungen in Google Chat planen

Programmierstufe: Mittel
Dauer: 25 Minuten
Projekttyp: Google Chat App

Zielsetzungen

  • Verstehen Sie, was die Lösung leisten kann.
  • Was die Apps Script-Dienste innerhalb der Lösung leisten
  • die Umgebung einrichten
  • Richten Sie das Skript ein.
  • Führen Sie das Skript aus.

Informationen zu dieser Lösung

Sie können eine Besprechung in Google Kalender über eine Direktnachricht (DM) oder einen Gruppenbereich in Google Chat planen. Sie können bestimmte Details für die Videokonferenz festlegen, z. B. Betreff, Beginn oder Dauer, oder die Standardeinstellungen für die Planung von Videokonferenzen verwenden.

Dialogfeld der Chat-App für den Terminplaner

Funktionsweise

Im Script der Chat-App werden Slash-Befehle und Dialogfelder verwendet, um Besprechungsdetails von Nutzern abzurufen und einen Kalendertermin zu planen. Das Skript enthält Standardeinstellungen für Videokonferenzen, die an Ihre Anforderungen angepasst werden können.

Apps Script-Dienste

Diese Lösung verwendet die folgenden Dienste:

  • Kalenderdienst: Erstellt den Kalendertermin aus den bereitgestellten Besprechungsinformationen.
  • Basisdienst: Verwendet die Klasse Session, um die Zeitzone des Skripts abzurufen. Diese Zeitzone wird in Google Kalender für die Terminplanung verwendet.
  • Dienstprogramme: Formatiert das Datum für den Kalendertermin und codiert die Termin-ID, um die Termin-URL abzurufen.

Voraussetzungen

Sie benötigen die folgenden Voraussetzungen, um dieses Beispiel verwenden zu können:

  • Ein Google-Konto (Google Workspace-Konten erfordern möglicherweise die Administratorgenehmigung).
  • Ein Webbrowser mit Zugang zum Internet.
  • Ein Google Cloud-Projekt

Umgebung einrichten

Cloud-Projekt in der Google Cloud Console öffnen

Falls noch nicht geschehen, öffnen Sie das Cloud-Projekt, das Sie für dieses Beispiel verwenden möchten:

  1. Rufen Sie in der Google Cloud Console die Seite Projekt auswählen auf.

    Cloud-Projekt auswählen

  2. Wählen Sie das Google Cloud-Projekt aus, das Sie verwenden möchten. Oder klicken Sie auf Projekt erstellen und folgen Sie der Anleitung auf dem Bildschirm. Wenn Sie ein Google Cloud-Projekt erstellen, müssen Sie möglicherweise die Abrechnung für das Projekt aktivieren.

API aktivieren

Bevor Sie Google APIs verwenden können, müssen Sie sie in einem Google Cloud-Projekt aktivieren. Sie können eine oder mehrere APIs in einem einzelnen Google Cloud-Projekt aktivieren.
  • Aktivieren Sie in Ihrem Cloud-Projekt die Google Chat API.

    API aktivieren

Für alle Chat-Apps ist ein Zustimmungsbildschirm konfiguriert. Wenn Sie den OAuth-Zustimmungsbildschirm Ihrer Anwendung konfigurieren, legen Sie fest, was Google den Nutzern anzeigt. Außerdem wird die Anwendung registriert, damit Sie sie später veröffentlichen können.

  1. Rufen Sie in der Google Cloud Console das Menü auf > APIs und Dienste > OAuth-Zustimmungsbildschirm.

    Zum OAuth-Zustimmungsbildschirm

  2. Wählen Sie für Nutzertyp die Option Intern aus und klicken Sie dann auf Erstellen.
  3. Füllen Sie das App-Registrierungsformular aus und klicken Sie dann auf Speichern und fortfahren.
  4. Vorerst können Sie das Hinzufügen von Bereichen überspringen und auf Speichern und fortfahren klicken. Wenn Sie in Zukunft eine Anwendung außerhalb Ihrer Google Workspace-Organisation erstellen, müssen Sie den Nutzertyp in Extern ändern und dann die für die Anwendung erforderlichen Autorisierungsbereiche hinzufügen.

  5. Prüfen Sie die Zusammenfassung der App-Registrierung. Wenn Sie Änderungen vornehmen möchten, klicken Sie auf Bearbeiten. Wenn die Anwendungsregistrierung in Ordnung ist, klicken Sie auf Zurück zum Dashboard.

Skript einrichten

Apps Script-Projekt erstellen

  1. Klicken Sie auf die folgende Schaltfläche, um das Apps Script-Projekt Besprechungen über Google Chat planen zu öffnen.
    Projekt öffnen
  2. Klicke auf Übersicht .
  3. Klicken Sie auf der Übersichtsseite auf „Kopie erstellen“ Das Symbol zum Erstellen einer Kopie.

Cloud-Projektnummer kopieren

  1. Öffnen Sie in der Google Cloud Console das Dreistrich-Menü > IAM und Verwaltung > Einstellungen.

    Zur Seite „IAM und Verwaltung“

  2. Kopieren Sie den Wert im Feld Projektnummer.

Cloud-Projekt des Apps Script-Projekts festlegen

  1. Klicken Sie im kopierten Apps Script-Projekt auf Projekteinstellungen Das Symbol für die Projekteinstellungen.
  2. Klicken Sie unter Google Cloud Platform-Projekt (GCP) auf Projekt ändern.
  3. Fügen Sie unter GCP-Projektnummer die Google Cloud-Projektnummer ein.
  4. Klicken Sie auf Projekt festlegen.

Testbereitstellung erstellen

  1. Klicken Sie im kopierten Apps Script-Projekt auf Bereitstellen > Bereitstellungen testen.
  2. Kopieren Sie die Head-Deployment-ID zur Verwendung in einem späteren Schritt und klicken Sie auf Done (Fertig).

Chat API konfigurieren

  1. Rufen Sie in der Google Cloud Console die Seite Chat API auf.
    Zur Chat API
  2. Klicken Sie auf Konfiguration.
  3. Konfigurieren Sie die Chat API mit den folgenden Informationen:
    • Name: Meeting Scheduler
    • Avatar-URL: Geben Sie eine URL ein, die auf ein Bild mit einer Mindestgröße von 256 × 256 Pixeln verweist.
    • Description: Quickly create meetings.
    • Funktionalität: Klicken Sie beide Kästchen an, damit Nutzer direkt Nachrichten an die App senden und in Gruppenbereiche einfügen können.
    • Verbindungseinstellungen: Klicken Sie auf Apps Script und geben Sie die Bereitstellungs-ID des Heads ein.
    • Slash-Befehle: Fügen Sie mit den folgenden Schritten Slash-Befehle für /help und /schedule_Meeting hinzu:
      1. Klicken Sie auf Slash-Befehl hinzufügen und konfigurieren Sie ihn mit den folgenden Informationen:
        • Name: /help
        • Befehls-ID: 1
        • Description: Learn what this app does.
      2. Klicken Sie noch einmal auf Slash-Befehl hinzufügen und konfigurieren Sie ihn mit den folgenden Informationen:
        • Name: /schedule_Meeting
        • Befehls-ID: 2
        • Description: Schedule a meeting.
        • Klicken Sie auf das Kästchen Öffnet ein Dialogfeld.
    • Berechtigungen: Wählen Sie Bestimmte Personen und Gruppen in Ihrer Domain aus und geben Sie Ihre E-Mail-Adresse ein.
  4. Klicken Sie auf Speichern und aktualisieren Sie die Seite.
  5. Legen Sie auf der Konfigurationsseite unter Anwendungsstatus den Status auf Live – für Nutzer verfügbar fest.
  6. Klicken Sie auf Speichern.

Skript ausführen

  1. Öffnen Sie Google Chat.
  2. Klicken Sie auf „Chat starten“ .
  3. Suchen Sie nach dem Namen der App: Meeting Scheduler.
  4. Senden Sie eine erste Nachricht wie hello, um die Autorisierung aufzufordern.
  5. Wenn die App antwortet, klicken Sie auf Konfigurieren und autorisieren Sie die App. Wenn auf dem OAuth-Zustimmungsbildschirm die Warnung Diese App wurde nicht verifiziert angezeigt wird, wählen Sie Erweitert > Zu {Projektname} (unsicher) aus.

  6. /schedule_Meeting an die App senden.

  7. Geben Sie im Dialogfeld mindestens eine E-Mail-Adresse der eingeladenen Person ein. Sie können die anderen Felder aktualisieren oder die Standardeinträge verwenden.

  8. Klicke auf Senden.

  9. Klicken Sie auf Kalendertermin öffnen, um sich die Videokonferenz anzusehen.

Code ansehen

Klicken Sie unten auf Quellcode ansehen, um den Apps Script-Code für diese Lösung zu überprüfen:

Quellcode ansehen

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);

}

Beitragende

Dieses Beispiel wird von Google mit Unterstützung von Google Developers-Experten verwaltet.

Nächste Schritte