Workspace: Add-ons
1. CREATING A GMAIL ADD-ON (GSP249)
Overview
Gmail add-ons automate tasks within Gmail, saving time and effort for users. Gmail add-ons can examine incoming messages, then act on these messages in various ways, such as:
- Displaying additional information for the user in the Gmail UI.
- Connecting to non-Google services, to retrieve information or take other actions.
- Providing an interactive interface to allow the user to control the add-on or send information to another service.
Objectives
In this hands-on lab you create a Gmail Add-on that allows you to quickly change the labels of an email thread.
Setup and Requirements
Note: Use an Incognito (recommended) or private browser window to run this lab. This prevents conflicts between your personal account and the student account, which may cause extra charges incurred to your personal account.
Note: Use only the student account for this lab. If you use a different Google Cloud account, you may incur charges to that account.
How to start your lab and sign in to Google Cloud Console
- Click the Start Lab button. If you need to pay for the lab, a dialog opens for you to select your payment method. On the left is the Lab Details pane with the following:
- The Open Google Cloud console button
- Time remaining
- The temporary credentials that you must use for this lab
- Other information, if needed, to step through this lab
-
Click Open Google Cloud console (or right-click and select Open Link in Incognito Window if you are running the Chrome browser).
The lab spins up resources, and then opens another tab that shows the Sign in page.
Tip: Arrange the tabs in separate windows, side-by-side.
Note: If you see the Choose an account dialog, click Use Another Account.
-
If necessary, copy the Username below and paste it into the Sign in dialog.
"Username"
You can also find the Username in the Lab Details pane.
-
Click Next.
-
Copy the Password below and paste it into the Welcome dialog.
"Password"
You can also find the Password in the Lab Details pane.
-
Click Next.
Important: You must use the credentials the lab provides you. Do not use your Google Cloud account credentials.
Note: Using your own Google Cloud account for this lab may incur extra charges.
-
Click through the subsequent pages:
- Accept the terms and conditions.
- Do not add recovery options or two-factor authentication (because this is a temporary account).
- Do not sign up for free trials.
After a few moments, the Google Cloud console opens in this tab.
Note: To access Google Cloud products and services, click the Navigation menu or type the service or product name in the Search field.
Task 1. Create the script project
Launch Apps Script
-
Click this Apps Script link to open in a new tab or browser window. A new project opens.
Note: Apps Script places the project file in your Drive root folder.
-
Click the Settings icon then select the Show âappsscript.jsonâ manifest file in editor option.
3.Click the Editor icon.
Name the project
- Click Untitled project in the upper left.
- Name the project Gmail Add-on Quickstart, and then click Rename.
Create the script file, Code.gs
-
Replace the Code.gs file contents with the following:
// Code.gs /** * Copyright 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. */ /** * Returns the array of cards that should be rendered for the current * e-mail thread. The name of this function is specified in the * manifest 'onTriggerFunction' field, indicating that this function * runs every time the add-on is started. * * @param {Object} e The data provided by the Gmail UI. * @return {Card[]} */ function buildAddOn(e) { // Activate temporary Gmail add-on scopes. var accessToken = e.messageMetadata.accessToken; GmailApp.setCurrentMessageAccessToken(accessToken); var messageId = e.messageMetadata.messageId; var message = GmailApp.getMessageById(messageId); // Get user and thread labels as arrays to enable quick sorting and indexing. var threadLabels = message.getThread().getLabels(); var labels = getLabelArray(GmailApp.getUserLabels()); var labelsInUse = getLabelArray(threadLabels); // Create a section for that contains all user Labels. var section = CardService.newCardSection() .setHeader("<font color=\"#1257e0\"><b>Available User Labels</b></font>"); // Create a checkbox group for user labels that are added to prior section. var checkboxGroup = CardService.newSelectionInput() .setType(CardService.SelectionInputType.CHECK_BOX) .setFieldName('labels') .setOnChangeAction(CardService.newAction().setFunctionName('toggleLabel')); // Add checkbox with name and selected value for each User Label. for(var i = 0; i < labels.length; i++) { checkboxGroup.addItem(labels[i], labels[i], labelsInUse.indexOf(labels[i])!= -1); } // Add the checkbox group to the section. section.addWidget(checkboxGroup); // Build the main card after adding the section. var card = CardService.newCardBuilder() .setHeader(CardService.newCardHeader() .setTitle('Quick Label') .setImageUrl('https://www.gstatic.com/images/icons/material/system/1x/label_googblue_48dp.png')) .addSection(section) .build(); return [card]; } /** * Updates the labels on the current thread based on * user selections. Runs via the OnChangeAction for * each CHECK_BOX created. * * @param {Object} e The data provided by the Gmail UI. */ function toggleLabel(e){ var selected = e.formInputs.labels; // Activate temporary Gmail add-on scopes. var accessToken = e.messageMetadata.accessToken; GmailApp.setCurrentMessageAccessToken(accessToken); var messageId = e.messageMetadata.messageId; var message = GmailApp.getMessageById(messageId); var thread = message.getThread(); if (selected != null){ for each (var label in GmailApp.getUserLabels()) { if(selected.indexOf(label.getName()) != -1){ thread.addLabel(label); } else { thread.removeLabel(label); } } } else { for each (var label in GmailApp.getUserLabels()) { thread.removeLabel(label); } } } /** * Converts an GmailLabel object to a array of strings. * Used for easy sorting and to determine if a value exists. * * @param {labelsObjects} A GmailLabel object array. * @return {lables[]} An array of labels names as strings. */ function getLabelArray(labelsObjects){ var labels = []; for(var i = 0; i < labelsObjects.length; i++) { labels[i] = labelsObjects[i].getName(); } labels.sort(); return labels; }
Note: Before saving, youâll need to update the script manifest to avoid errors.
Task 2. Update the script manifest
Update the manifest (appsscript.json) to provide the add-on with required deployment information.
- In the script editor, select the appsscript.json file from the left menu.
-
Replace the content of the manifest (appsscript.json) with the following:
{ "oauthScopes": [ "https://www.googleapis.com/auth/gmail.addons.execute", "https://www.googleapis.com/auth/gmail.addons.current.message.metadata", "https://www.googleapis.com/auth/gmail.modify" ], "gmail": { "name": "Gmail Add-on Quickstart - QuickLabels", "logoUrl": "https://www.gstatic.com/images/icons/material/system/1x/label_googblue_24dp.png", "contextualTriggers": [{ "unconditional": {}, "onTriggerFunction": "buildAddOn" }], "openLinkUrlPrefixes": [ "https://mail.google.com/" ], "primaryColor": "#4285F4", "secondaryColor": "#4285F4" } }
- Click the Save project icon to save the changes to the manifest and Code.gs. This step provides the add-on with required deployment information. If you get an error, save Code.gs again.
Task 3. Deploy the add-on
- Click the Deploy > Test deployments button at the top of the screen.
- For Application(s): Gmail, click Install.
- Click Done.
- Open the Gmail add-on settings tab.
-
This brings you to the Setting dialog at the Add-ons tab.
When you have completed these steps, the add-on appears in the Installed developer add-ons list and becomes available for use in Gmail.
Note: If you donât see your add-on in the Installed developer add-ons list, refresh the browser window. If the add-on is still not in the list, return to the Gmail Add-on Quickstart tab, uninstall and reinstall the add-on from the Test deployments window.
Task 4. Run the add-on
- Return to your Gmail tab and refresh the tab.
- Choose a message in Gmail and open it.
- Make sure the right side menu is open - click the arrow to expand if it has been collapsed.
Create some labels
- Click the Labels button (Gmail Label icon) from the Gmail menu bar above the email.
- Click Create new.
- Enter âTest 1â as your label name and click the Create button.
- Repeat these steps to create another label named âTest 2â.
Authorize add-on
The add-ons you installed appear in the right menu of the open email thread.
-
On the right side of the screen, click on the Gmail Label icon.
The add-on will place a contextual card on the right side of the window, with a message asking for authorization.
- Click the Authorize access link to open a dialog where you can authorize the add-on.
- Select the student account that should authorize the add-on.
-
Click Allow.
-
If the next dialog informs you that the app is not verified:
- Click Advanced.
- At the bottom of the dialog, click Go to Gmail Add-on Quickstart (unsafe).
- In the new dialog, type âContinueâ into the text field, then click Next.
- Once authorized, the add-on should automatically refresh and start operating.
Task 5. Use the add-on
The Test 1 and the Test 2 labels are checked under the Available User Labels section of the add-on (right side menu).
- Click the Test 2 checkbox to deselect the label. This will remove the label from the email thread youâre currently in.
- Verify that the appropriate labels have been applied by navigating back to the Inbox and refreshing the browser. Only the Test 1 label is still applied and Test 2 has been removed.
- Open a different email.
- In the add-on menu, select the Test 1 and Test 2 checkboxes, enabling them both.
- Return to the Inbox and refresh the browser. Both labels have been applied to the email thread.
Congratulations!
You now have an idea of what Gmail add-ons are capable of. You could do many other things like displaying other recent threads that the sender has started, or translating the text of an email from one language to another without leaving Gmail.
2. USING THE NATURAL LANGUAGE API FROM GOOGLE DOCS (GSP126)
Overview
The Natural Language API is a pretrained machine learning model that can analyze syntax, extract entities, and evaluate the sentiment of text. You can call the Natural Language API from Google Docs to perform all of these functions.
This lab focuses on calling the Natural Language API from Google Docs. You use the Natural Language API to recognize the sentiment of selected text in a Google Doc and highlight it based on that sentiment.
When you complete this lab, you are able to select text in a document and mark its sentiment, using a menu choice, as shown below. Text is highlighted in red for negative sentiment, green for positive sentiment, and yellow for neutral sentiment.
Objectives
In this lab, you learn how to:
- Call the Natural Language API from Google Docs
- Add menus to Google Docs
- Recognize and work with selected text in Google Docs
Setup and Requirements
Note: Use an Incognito (recommended) or private browser window to run this lab. This prevents conflicts between your personal account and the student account, which may cause extra charges incurred to your personal account.
Note: Use only the student account for this lab. If you use a different Google Cloud account, you may incur charges to that account.
How to start your lab and sign in to Google Cloud Console
- Click the Start Lab button. If you need to pay for the lab, a dialog opens for you to select your payment method. On the left is the Lab Details pane with the following:
- The Open Google Cloud console button
- Time remaining
- The temporary credentials that you must use for this lab
- Other information, if needed, to step through this lab
-
Click Open Google Cloud console (or right-click and select Open Link in Incognito Window if you are running the Chrome browser).
The lab spins up resources, and then opens another tab that shows the Sign in page.
Tip: Arrange the tabs in separate windows, side-by-side.
Note: If you see the Choose an account dialog, click Use Another Account.
-
If necessary, copy the Username below and paste it into the Sign in dialog.
"Username"
You can also find the Username in the Lab Details pane.
-
Click Next.
-
Copy the Password below and paste it into the Welcome dialog.
"Password"
You can also find the Password in the Lab Details pane.
-
Click Next.
Important: You must use the credentials the lab provides you. Do not use your Google Cloud account credentials.
Note: Using your own Google Cloud account for this lab may incur extra charges.
-
Click through the subsequent pages:
- Accept the terms and conditions.
- Do not add recovery options or two-factor authentication (because this is a temporary account).
- Do not sign up for free trials.
After a few moments, the Google Cloud console opens in this tab.
Note: To access Google Cloud products and services, click the Navigation menu or type the service or product name in the Search field.
Task 1. Enable the Natural Language API
Before you start, make sure that the Natural Language API is enabled.
-
In the Google Cloud console, select Navigation menu > APIs & Services > Library.
-
Search for Cloud Natural Language API and click on the API to enable it or to confirm that the API is enabled.
Task 2. Get an API key
Generate an API user key to pass in the request URL.
-
To create an API key, select Navigation menu > APIs & Services > Credentials.
-
Click Create credentials at the top and select API key:
-
Copy the API key to a text file or a Google Doc to use in a later step. Click Close.
Once you have the API key, you are ready to move into Google Docs.
Task 3. Set up your Google Doc
Before you call the Natural Language API, make an Apps Script program to create the menu, link it to a function to mark the text, and extract the text from the user selection.
- Create a new Google Doc.
- From within your new document, select the menu item Extensions > Apps Script.
-
Delete any code in the script editor and paste in the code below. This code creates a menu item, extracts the text from the current selected text, and highlights the text based on its sentiment. It does not call the Natural Language API yet.
/** * @OnlyCurrentDoc * * The above comment directs Apps Script to limit the scope of file * access for this add-on. It specifies that this add-on will only * attempt to read or modify the files in which the add-on is used, * and not all of the user's files. The authorization request message * presented to users will reflect this limited scope. */ /** * Creates a menu entry in the Google Docs UI when the document is * opened. * */ function onOpen() { var ui = DocumentApp.getUi(); ui.createMenu('Natural Language Tools') .addItem('Mark Sentiment', 'markSentiment') .addToUi(); } /** * Gets the user-selected text and highlights it based on sentiment * with green for positive sentiment, red for negative, and yellow * for neutral. * */ function markSentiment() { var POSITIVE_COLOR = '#00ff00'; // Colors for sentiments var NEGATIVE_COLOR = '#ff0000'; var NEUTRAL_COLOR = '#ffff00'; var NEGATIVE_CUTOFF = -0.2; // Thresholds for sentiments var POSITIVE_CUTOFF = 0.2; var selection = DocumentApp.getActiveDocument().getSelection(); if (selection) { var string = getSelectedText(); var sentiment = retrieveSentiment(string); // Select the appropriate color var color = NEUTRAL_COLOR; if (sentiment <= NEGATIVE_CUTOFF) { color = NEGATIVE_COLOR; } if (sentiment >= POSITIVE_CUTOFF) { color = POSITIVE_COLOR; } // Highlight the text var elements = selection.getSelectedElements(); for (var i = 0; i < elements.length; i++) { if (elements[i].isPartial()) { var element = elements[i].getElement().editAsText(); var startIndex = elements[i].getStartOffset(); var endIndex = elements[i].getEndOffsetInclusive(); element.setBackgroundColor(startIndex, endIndex, color); } else { var element = elements[i].getElement().editAsText(); foundText = elements[i].getElement().editAsText(); foundText.setBackgroundColor(color); } } } } /** * Returns a string with the contents of the selected text. * If no text is selected, returns an empty string. */ function getSelectedText() { var selection = DocumentApp.getActiveDocument().getSelection(); var string = ""; if (selection) { var elements = selection.getSelectedElements(); for (var i = 0; i < elements.length; i++) { if (elements[i].isPartial()) { var element = elements[i].getElement().asText(); var startIndex = elements[i].getStartOffset(); var endIndex = elements[i].getEndOffsetInclusive() + 1; var text = element.getText().substring(startIndex, endIndex); string = string + text; } else { var element = elements[i].getElement(); // Only translate elements that can be edited as text; skip // images and other non-text elements. if (element.editAsText) { string = string + element.asText().getText(); } } } } return string; } /** Given a string, will call the Natural Language API and retrieve * the sentiment of the string. The sentiment will be a real * number in the range -1 to 1, where -1 is highly negative * sentiment and 1 is highly positive. */ function retrieveSentiment (line) { // TODO: Call the Natural Language API with the line given // and return the sentiment value. return 0.0; }
Note: To learn more about Apps Script, refer to the Google Apps Script reference.
- On the menu bar, click Save project. (The scriptâs name is shown to end users in several places, including the authorization dialog.)
- Return to your document. Add text to your document. You can use the sample that comes from Alice in Wonderland on Project Gutenberg (copy and paste the Plain Text UTF-8 version into the document), but feel free to use any text you wish.
- Reload the document to see the new menu, Natural Language Tools, which you created, appear in the Google Docs toolbar.
- Select text and then the Mark Sentiment option from the Natural Language Tools menu. The first time you select this option, you are prompted to authorize the script to run. Click Continue, and then confirm your account.
- Allow Natural Language Tools to view and manage documents that this application has been installed in.
- Once the script is authorized, the selected text is highlighted in yellow, since the stub for sentiment analysis always returns
0.0
, which is neutral.
Task 4. Call the Natural Language API
Once your program can extract text from the selection and highlight it, itâs time to call the Natural Language API. All of this is done in the body of the retrieveSentiment
function.
Note: To learn more about the Natural Language API, refer to the Cloud Natural Language API reference.
- Return to Extensions > Apps Script in Google Docs.
-
In the
retrieveSentiment
function, replace âyour key hereâ with your actual API key from the Google Cloud Console.var apiKey = "your key here"; // Replace with your actual API key
-
Create a variable to hold the URL of the Natural Language API with your API key appended to it:
var apiEndpoint = "https://language.googleapis.com/v1/documents:analyzeSentiment?key=" + apiKey;
-
Build a structure from the line passed into the function that holds the text of the line, along with its type and language. Currently, the only supported language is English.
var docDetails = { language: 'en-us', type: 'PLAIN_TEXT', content: line };
-
Build the entire data payload from the document details by adding the encoding type:
var nlData = { document: docDetails, encodingType: 'UTF8' };
-
Create a structure containing the payload and the necessary header information:
var nlOptions = { method : 'post', contentType: 'application/json', payload : JSON.stringify(nlData) };
-
Make the call, saving the response:
var response = UrlFetchApp.fetch(apiEndpoint, nlOptions);
-
The response is returned in JSON format; parse it and extract the
score
field, if it exists. Return either that field or0.0
.var data = JSON.parse(response); var sentiment = 0.0; // Ensure all pieces were in the returned value if (data && data.documentSentiment && data.documentSentiment.score){ sentiment = data.documentSentiment.score; } return sentiment;
The complete code to retrieve the sentiment is below:
function retrieveSentiment (line) { var apiKey = "your key here"; // Replace with your actual API key var apiEndpoint = "https://language.googleapis.com/v1/documents:analyzeSentiment?key=" + apiKey; // Create a structure with the text, its language, its type, and its encoding var docDetails = { language: 'en-us', type: 'PLAIN_TEXT', content: line }; var nlData = { document: docDetails, encodingType: 'UTF8' }; // Package all of the options and the data together for the call var nlOptions = { method : 'post', contentType: 'application/json', payload : JSON.stringify(nlData) }; // Make the call var response = UrlFetchApp.fetch(apiEndpoint, nlOptions); var data = JSON.parse(response); var sentiment = 0.0; // Ensure all pieces were in the returned value if (data && data.documentSentiment && data.documentSentiment.score){ sentiment = data.documentSentiment.score; } return sentiment; }
-
Save your script, reload the document, and try out the full program. You may need to re-authorize with your credentials to enable the new functionality. Select different sections of your document to see how the sentiment may differ over its parts.
- (Optional) Type and then analyze your own words. For example, type and analyze:
- âIâm madâ
- âIâm happyâ
Experiment to see how the Natural Language API interprets different groups, for example, if you analyze:
I'm happy. I'm happy. I'm sad.
What happens if you add another âIâm sad.â?
Congratulations!
You created a Google Doc and called the Natural Language API to analyze the sentiment of selected portions of the document.
3. GOOGLE CHAT BOT - APPS SCRIPT (GSP250)
Overview
Google Chat bots provide easy-to-use access points to your organizationâs data and services. Users can converse with bots within a chat experience.
One way to create a Google Chat bot is to use Google Apps Script. This also gives you easy access to other Google services like Drive, Gmail, Calendar, Docs, Sheets, and much more.
In this lab, you use Google Apps Script to create a simple Google Chat bot, which youâll name âAttendance Botâ. The bot integrates with Gmail to set a userâs vacation responder and integrates with Calendar to put a meeting on the userâs calendar.
Objectives
In this lab, you perform the following tasks:
- Create a chat app from a template with pre-populated event handlers.
- Configure and publish the chat bot.
- Add new handlers for events raised in Google Chat.
- Parse event objects sent from Google Chat.
- Respond to Google Chat with card-formatted responses.
- Define and react to custom actions for button clicks in cards.
Setup and Requirements
Note: Use an Incognito (recommended) or private browser window to run this lab. This prevents conflicts between your personal account and the student account, which may cause extra charges incurred to your personal account.
Note: Use only the student account for this lab. If you use a different Google Cloud account, you may incur charges to that account.
How to start your lab and sign in to Google Cloud Console
- Click the Start Lab button. If you need to pay for the lab, a dialog opens for you to select your payment method. On the left is the Lab Details pane with the following:
- The Open Google Cloud console button
- Time remaining
- The temporary credentials that you must use for this lab
- Other information, if needed, to step through this lab
-
Click Open Google Cloud console (or right-click and select Open Link in Incognito Window if you are running the Chrome browser).
The lab spins up resources, and then opens another tab that shows the Sign in page.
Tip: Arrange the tabs in separate windows, side-by-side.
Note: If you see the Choose an account dialog, click Use Another Account.
-
If necessary, copy the Username below and paste it into the Sign in dialog.
"Username"
You can also find the Username in the Lab Details pane.
-
Click Next.
-
Copy the Password below and paste it into the Welcome dialog.
"Password"
You can also find the Password in the Lab Details pane.
-
Click Next.
Important: You must use the credentials the lab provides you. Do not use your Google Cloud account credentials.
Note: Using your own Google Cloud account for this lab may incur extra charges.
-
Click through the subsequent pages:
- Accept the terms and conditions.
- Do not add recovery options or two-factor authentication (because this is a temporary account).
- Do not sign up for free trials.
After a few moments, the Google Cloud console opens in this tab.
Note: To access Google Cloud products and services, click the Navigation menu or type the service or product name in the Search field.
Task 1. Create a chat app from a template
To implement your bot, create a new Google Apps Script project using the Chat App template.
Note: Signing into Google Cloud console sets your project and credentials. Before you click the Google Apps Script editor link in Step 1, be sure you have signed into the Google Cloud console.
- Click this Google Apps Script homepage link to open the Google Apps Script online editor.
- Scroll down to the bottom of the page, and click on Chat App.
- Click Untitled project (the current name).
- In the Edit project name dialog, rename the project to Attendance Bot, and then click Rename.
Events in Google Chat
Most Apps Script bot interactions with Google Chat are event-driven. The interaction between the user, the bot, and Google Chat typically follows a sequence:
- A user initiates an action, like adding a bot to a room, starting a direct message (DM) with a bot, or removing the bot from a room.
- The action raises an event aimed at the bot in Google Chat.
- Google Chat calls the corresponding event handler defined in the botâs script.
Google Chat raises four events that your Apps Script bot can listen for:
- ADDED_TO_SPACE: This event occurs when a human user adds a bot to a room or a DM. In Apps Script, you define an
onAddToSpace()
function to handle this event. - REMOVED_FROM_SPACE: This event occurs when a user removes the bot from a room or DM. This event does not post a response back to Google Chat. In Apps Script, you define an
onRemoveFromSpace()
function to handle this event. - MESSAGE: This event occurs when a user messages the bot, either directly in a DM or as an @mention in a room. In Apps Script, you define an
onMessage()
function to respond to this event. - CARD_CLICKED: This event occurs when the user clicks a button with a custom action assigned to it. In Apps Script, you define an
onCardClick()
function to respond to this event.
Update the code for the MESSAGE event handler
The Chat App template pre-populates the code file containing the event handlers.
-
Click on the Code.gs file to see the pre-populated event handlers.
Notice the event handlers for the
MESSAGE
,ADDED_TO_SPACE
, andREMOVE_FROM_SPACE
events. (You will add a handler for theCARD_CLICKED
events later in this lab.) -
On line 38, align the cursor to the line below it (a single tab indentation like line 39), and then copy and paste the following code line to prompt logging of the event:
console.log('Attendance Bot added in ', event.space.name);
-
Click Save project to drive (Save icon) to save the change to the Code.gs file.
Task 2. Publish the bot
Before you can run and test the bot, the Google Chat API must be enabled for your Google Cloud project, and your bot must be published to Google Chat.
Configure the Google Cloud project and update the script to use it
- Go to the Google Cloud console, click the Navigation menu (â°) in the upper left and navigate to APIs & Services > OAuth consent screen.
- Click Get Started.
-
For the Project configuration page, under App Information, configure the following and click Next:
Field Value App name Attendance Bot User support email Select the email ID from the drop-down. - For Audience, select Internal and click Next.
- Type the email address for Contact Information and click Next.
- Accept the policy and click Continue then Create.
- From the Navigation Menu, click Cloud Overview > Dashboard.
- In the Dashboard, click Go to project settings in the Project Info section.
- Record the Project number to use in the next step to configure your project.
- Return to the Apps Script editor, and navigate to the Project Settings for the Attendance Bot project (gear icon for project settings).
- Under Google Cloud Platform (GCP) Project, click Change project.
- For GCP Project number, enter the project number that you copied earlier. Then, click Set project.
Configure and publish the chat bot
- In the Apps Script editor, get the Head Deployment ID for the test deployment by clicking on Deploy > Test Deployments (top-right of the screen), and then clicking Copy next to Head Deployment ID.
- In the Google Cloud console, navigate to Navigation Menu (â°) > APIs & Services > Library.
- In the Library, search for Google Chat API. Select the API from the list of results.
- The Google Chat API is already enabled in this project. If it is not enabled, click Enable.
- Click Manage, and then click the Configuration tab under the Google Chat API section.
-
In the Configuration dialog, set the fields with the following values:
Field Value App name Attendance Bot Avatar URL https://goo.gl/kv2ENA Description Apps Script lab bot Functionality Select Receive 1:1 messages and Join spaces and group conversations Connection settings Check Apps Script project, and then paste the Head Deployment ID that you copied earlier into the Deployment ID field. Visibility username - Click SAVE.
-
After the changes are saved, scroll to the top of the Configuration dialog to update the App Status to LIVE â available to users.
You may have to refresh the page to see the App Status field.
- Click SAVE again.
Test the bot
To test your bot in Google Chat, do the following:
- Click the Google Chat link to open Google Chat.
- Select Start a chat (đŹ) in the Chat section.
- Search for Attendance bot.
-
From the results, select the Attendance Bot, Apps Script lab bot that you created, and click Start chat.
When the direct message thread opens, you should see a message from the bot thanking you for adding it to a DM.
Note: It can take a few minutes for the progress check below to return a successful completion mark for this task. If not successful, wait a few mins and try again.
Task 3. Define a card-formatted response
In the previous task, your bot responded to Google Chat events with a simple text response. In this task, you update your bot to respond with cards.
Card responses
Google Chat supports the use of cards for responses. Cards are visual containers that allow you to group sets of user interface widgets together. Cards can display headers, text paragraphs, sets of buttons, images, and key/value text. Your bot can define one or many cards in its JSON response to Google Chat, which then translates your response into the corresponding UI elements.
The following image shows an example card response with three sections that includes a header, a key/value widget, an image widget, and a text button.
- In Apps Script, click Editor (editor_icon), and open the
Code.gs
file. -
Locate the existing code for function
onMessage(event)
at the top ofCode.gs
file, and delete code lines 1 to 17.You replace these code lines for function
onMessage(event)
with new code in the next step. -
Copy the following code, and paste these lines at the top of the
Code.gs
file:Code.gs
var DEFAULT_IMAGE_URL = 'https://goo.gl/bMqzYS'; var HEADER = { header: { title : 'Attendance Bot', subtitle : 'Log your vacation time', imageUrl : DEFAULT_IMAGE_URL } }; /** * Creates a card-formatted response. * @param {object} widgets the UI components to send * @return {object} JSON-formatted response */ function createCardResponse(widgets) { return { cards: [HEADER, { sections: [{ widgets: widgets }] }] }; } /** * Responds to a MESSAGE event triggered * in Google Chat. * * @param event the event object from Google Chat * @return JSON-formatted response */ function onMessage(event) { var userMessage = event.message.text; var widgets = [{ "textParagraph": { "text": "You said: " + userMessage } }]; console.log('You said:', userMessage); return createCardResponse(widgets); }
-
Click Save project to drive (Save icon) to save the
Code.gs
file.By replacing the
onMessage()
function and adding thecreateCardResponse()
function, you accomplish the following:- The
onMessage()
function reads the userâs original message and constructs a response as a simpleTextParagragh
widget. - The
onMessage()
function then callscreateCardResponse()
, which places theTextParagraph
widget within a section of a single card. - The bot returns the JavaScript object constructed with the card response to Google Chat.
- The
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
var DEFAULT_IMAGE_URL = 'https://goo.gl/bMqzYS';
var HEADER = {
header: {
title : 'Attendance Bot',
subtitle : 'Log your vacation time',
imageUrl : DEFAULT_IMAGE_URL
}
};
/**
* Creates a card-formatted response.
* @param {object} widgets the UI components to send
* @return {object} JSON-formatted response
*/
function createCardResponse(widgets) {
return {
cards: [HEADER, {
sections: [{
widgets: widgets
}]
}]
};
}
/**
* Responds to a MESSAGE event triggered
* in Google Chat.
*
* @param event the event object from Google Chat
* @return JSON-formatted response
*/
var REASON = {
SICK: 'Out sick',
OTHER: 'Out of office'
};
/**
* Responds to a MESSAGE event triggered in Google Chat.
* @param {object} event the event object from Google Chat
* @return {object} JSON-formatted response
*/
function onMessage(event) {
console.info(event);
var reason = REASON.OTHER;
var name = event.user.displayName;
var userMessage = event.message.text;
// If the user said that they were 'sick', adjust the image in the
// header sent in response.
if (userMessage.indexOf('sick') > -1) {
// Hospital material icon
HEADER.header.imageUrl = 'https://goo.gl/mnZ37b';
reason = REASON.SICK;
} else if (userMessage.indexOf('vacation') > -1) {
// Spa material icon
HEADER.header.imageUrl = 'https://goo.gl/EbgHuc';
}
var widgets = [{
textParagraph: {
text: 'Hello, ' + name + '.<br>Are you taking time off today?'
}
}, {
buttons: [{
textButton: {
text: 'Set vacation in Gmail',
onClick: {
action: {
actionMethodName: 'turnOnAutoResponder',
parameters: [{
key: 'reason',
value: reason
}]
}
}
}
}, {
textButton: {
text: 'Block out day in Calendar',
onClick: {
action: {
actionMethodName: 'blockOutCalendar',
parameters: [{
key: 'reason',
value: reason
}]
}
}
}
}]
}];
return createCardResponse(widgets);
}
/**
* Responds to a CARD_CLICKED event triggered in Google Chat.
* @param {object} event the event object from Google Chat
* @return {object} JSON-formatted response
* @see https://developers.google.com/chat/reference/message-formats/events
*/
function onCardClick(event) {
console.info(event);
var message = '';
var reason = event.action.parameters[0].value;
if (event.action.actionMethodName == 'turnOnAutoResponder') {
turnOnAutoResponder(reason);
message = 'Turned on vacation settings.';
} else if (event.action.actionMethodName == 'blockOutCalendar') {
blockOutCalendar(reason);
message = 'Blocked out your calendar for the day.';
} else {
message = "I'm sorry; I'm not sure which button you clicked.";
}
return { text: message };
}
var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;
/**
* Turns on the user's vacation response for today in Gmail.
* @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
*/
function turnOnAutoResponder(reason) {
var currentTime = (new Date()).getTime();
Gmail.Users.Settings.updateVacation({
enableAutoReply: true,
responseSubject: reason,
responseBodyHtml: "I'm out of the office today; will be back on the next business day.<br><br><i>Created by Attendance Bot!</i>",
restrictToContacts: true,
restrictToDomain: true,
startTime: currentTime,
endTime: currentTime + ONE_DAY_MILLIS
}, 'me');
}
/**
* Places an all-day meeting on the user's Calendar.
* @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER
*/
function blockOutCalendar(reason) {
CalendarApp.createAllDayEvent(reason, new Date(), new Date(Date.now() + ONE_DAY_MILLIS));
}
/**
* Responds to an ADDED_TO_SPACE event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
function onAddToSpace(event) {
var message = "";
if (event.space.singleUserBotDm) {
message = "Thank you for adding me to a DM, " + event.user.displayName + "!";
} else {
message = "Thank you for adding me to " +
(event.space.displayName ? event.space.displayName : "this chat");
}
if (event.message) {
// Bot added through @mention.
message = message + " and you said: \"" + event.message.text + "\"";
}
console.log('Attendance Bot added in ', event.space.name);
return { "text": message };
}
/**
* Responds to a REMOVED_FROM_SPACE event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
function onRemoveFromSpace(event) {
console.info("Bot removed from ",
(event.space.name ? event.space.name : "this chat"));
}
Test the bot
-
To retest this bot, return to your direct message chat with the bot in Google Chat, and type any message, such as âHelloâ.
The Attendance bot should respond with a Log your vacation time card.
Note: The onMessage() event handler parses the event object passed to it by Google Chat to extract the userâs original message. You can also get other types of information about the event, including the name of the user that initiated the event, their email address, the name of the room that the event occurred in, and much more.
For more information about the structure of the event objects sent by Google Chat, you can refer to the Event formats reference guide.
Note: It can take a few minutes for the progress check below to return a successful completion mark for this task. If not successful, wait a few mins and try again.
Task 4. React to button clicks in cards
In the previous step, your bot responded to a message from a userâa MESSAGE
eventâwith a simple card that contained a TextParagragh
widget. In this step, you will create a response that includes buttons, where each button has a custom action defined for it.
Interactive cards
Card responses can contain one of two types of buttons: TextButton
widgets, which display text-only buttons; and ImageButton
widgets, which display a button with a simple icon or image without text.
Both TextButton
and ImageButton
widgets support one of two onClick
behaviors (as defined in the JSON response sent back to Google Chat): either openLink
or action
. As the name implies, openLink
opens a specified link in a new browser tab.
The action
object, however, specifies a custom action for the button to perform. You can specify several arbitrary values in the action
object, including a unique actionMethodName
and a set of key / value parameter pairs.
Specifying an action
object for the button creates an interactive card. When the user clicks the button in the message, Google Chat raises a CARD_CLICKED
event and sends a request back to the bot that sent the original message. The bot then needs to handle the event raised from Google Chat and return a response back to the space.
Add buttons to the card
- Return to Apps Script, and click Editor(Editor icon) in the Files panel.
- In
Code.gs
, remove theonMessage()
function again by deleting lines 25-44. -
Copy the following code, and paste at line 25.
This code creates two buttons, a Set vacation in Gmail and a Block out day in Calendar button in the card sent to Google Chat.
Code.gs
var REASON = { SICK: 'Out sick', OTHER: 'Out of office' }; function onMessage(event) { console.info(event); var reason = REASON.OTHER; var name = event.user.displayName; var userMessage = event.message.text; if (userMessage.indexOf('sick') > -1) { HEADER.header.imageUrl = 'https://goo.gl/mnZ37b'; reason = REASON.SICK; } else if (userMessage.indexOf('vacation') > -1) { HEADER.header.imageUrl = 'https://goo.gl/EbgHuc'; } var widgets = [{ textParagraph: { text: 'Hello, ' + name + '.<br>Are you taking time off today?' } }, { buttons: [{ textButton: { text: 'Set vacation in Gmail', onClick: { action: { actionMethodName: 'turnOnAutoResponder', parameters: [{ key: 'reason', value: reason }] } } } }, { textButton: { text: 'Block out day in Calendar', onClick: { action: { actionMethodName: 'blockOutCalendar', parameters: [{ key: 'reason', value: reason }] } } } }] }]; return createCardResponse(widgets); }
-
To handle the
CARD_CLICKED
event, add theonCardClick()
function to the end of theCode.gs
file.Code.gs
function onCardClick(event) { console.info(event); var message = ''; var reason = event.action.parameters[0].value; if (event.action.actionMethodName == 'turnOnAutoResponder') { turnOnAutoResponder(reason); message = 'Turned on vacation settings.'; } else if (event.action.actionMethodName == 'blockOutCalendar') { blockOutCalendar(reason); message = 'Blocked out your calendar for the day.'; } else { message = "I'm sorry; I'm not sure which button you clicked."; } return { text: message }; }
In responding to user clicks, now the bot does one of two things: It sets the userâs vacation responder in Gmail to an âout of officeâ message; or it schedules an all-day meeting on the userâs Calendar. To accomplish these tasks, the bot calls the Gmail advanced service and the Calendar Apps Script API.
var ONE_DAY_MILLIS = 24 * 60 * 60 * 1000; /** * Turns on the user's vacation response for today in Gmail. * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER */ function turnOnAutoResponder(reason) { var currentTime = (new Date()).getTime(); Gmail.Users.Settings.updateVacation({ enableAutoReply: true, responseSubject: reason, responseBodyHtml: "I'm out of the office today; will be back on the next business day.<br><br><i>Created by Attendance Bot!</i>", restrictToContacts: true, restrictToDomain: true, startTime: currentTime, endTime: currentTime + ONE_DAY_MILLIS }, 'me'); } /** * Places an all-day meeting on the user's Calendar. * @param {string} reason the reason for vacation, either REASON.SICK or REASON.OTHER */ function blockOutCalendar(reason) { CalendarApp.createAllDayEvent(reason, new Date(), new Date(Date.now() + ONE_DAY_MILLIS)); }
- Click Save project to drive (Save icon) to save the
Code.gs
file. -
In the left-side menu, next to Services, click Add a service, and select Gmail API from the list.
- Click Add.
Check that the Gmail API is enabled
Make sure that the Gmail Advanced Service is enabled in this project. To check the Gmail API status, do the following:
- In the Google Cloud Console, navigate to Navigation Menu (â°) > APIs & Services > Library.
- In the Library, search for Gmail API. Select the API from the list of results.
- If the Gmail API is not already enabled, click Enable.
Test the bot
-
Return to the DM in Google Chat, and type:
I'm sick
The bot should respond with a card similar to the image below that prompts you to configure the bot.
-
To configure the Attendance Bot, click Configure, choose your user account, click ALLOW, and then close the page when you see the message âYou may close this page nowâ. Now the bot displays the available options.
-
Click SET VACATION IN GMAIL. You should see the message âTurned on vacation settings.â
-
Click BLOCK OUT DAY IN CALENDAR. You should see the message âBlocked out your calendar for the day.â
-
Click the Google Apps icon to access and check Gmail and Calendar associated with this account.
You should see the Vacation Setting enabled in Gmail.
You should see a day blocked out in the Calendar.
Note: It can take a few minutes for the progress check below to return a successful completion mark for this task. If not successful, wait a few minutes and try again.
Congratulations!
You created a bot that responds to user messages, sets their vacation responder in Gmail, and puts an all-day event on their Calendar.