程式設計程度:中級
時間長度:25 分鐘
專案類型:Google Chat 應用程式
目標
- 瞭解解決方案的功能。
- 瞭解 Apps Script 服務在解決方案中的作用。
- 設定環境。
- 設定指令碼。
- 執行指令碼。
認識這項解決方案
您可以透過 Google Chat 中的即時訊息 (DM) 或聊天室,在 Google 日曆中安排會議。您可以設定會議的特定詳細資料,例如主旨、開始時間或持續時間,也可以使用預設設定安排即時會議。
運作方式
Chat 應用程式指令碼會使用斜線指令和對話方塊,向使用者取得會議詳細資料,並安排 Google 日曆活動。指令碼包含預設會議設定,您可以根據需求自訂。
Apps Script 服務
本解決方案會使用下列服務:
- 日曆服務:根據提供的會議資訊建立日曆活動。
- 基本服務:使用
Session
類別取得指令碼的時區。日曆會在排定活動時使用這個時區。
- 公用程式服務:為日曆活動日期設定格式,並編碼活動 ID,以利取得活動網址。
必要條件
設定環境
在 Google Cloud 控制台中開啟 Cloud 專案
如果尚未開啟,請開啟要用於本範例的 Cloud 專案:
- 在 Google Cloud 控制台中,前往「Select a project」頁面。
選取 Cloud 專案
- 選取要使用的 Google Cloud 專案。或者,您也可以按一下「建立專案」,然後按照畫面上的指示操作。如果您建立 Google Cloud 專案,可能需要為專案啟用計費功能。
啟用 API
使用 Google API 前,您必須先在 Google Cloud 專案中啟用這些 API。您可以在單一 Google Cloud 專案中啟用一或多個 API。
所有 Chat 應用程式都需要設定同意畫面。設定應用程式的 OAuth 同意畫面,可定義 Google 向使用者顯示的內容,並註冊應用程式,以便日後發布。
-
在 Google Cloud 控制台中,依序前往「選單」menu
>「API 和服務」
>「OAuth 同意畫面」。
前往 OAuth 同意畫面
- 在「使用者類型」部分,選取「內部」,然後按一下「建立」。
- 填寫應用程式註冊表單,然後按一下「儲存並繼續」。
目前您可以略過新增範圍,直接按一下「儲存並繼續」。日後,如果您建立的應用程式是用於 Google Workspace 機構以外的環境,就必須將使用者類型變更為外部,然後新增應用程式所需的授權範圍。
- 查看應用程式註冊摘要。如要修改資訊,請按一下「編輯」。如果應用程式註冊看起來沒問題,請按一下「返回資訊主頁」。
設定指令碼
建立 Apps Script 專案
- 按一下下方按鈕,開啟「透過 Google Chat 安排會議」Apps Script 專案。
開啟專案
- 按一下「總覽」圖示 info_outline。
- 在總覽頁面中,按一下「建立副本」圖示 。
複製 Cloud 專案編號
-
在 Google Cloud 控制台中,依序前往「Menu」(選單) menu
>「IAM & Admin」(IAM 與管理)>「Settings」(設定)。
前往「IAM 與管理員設定」
- 在「專案編號」欄位中複製值。
設定 Apps Script 專案的 Cloud 專案
- 在複製的 Apps Script 專案中,按一下「Project Settings」圖示 。
- 在「Google Cloud Platform (GCP) 專案」下方,按一下「變更專案」。
- 在「GCP 專案編號」中貼上 Google Cloud 專案編號。
- 按一下「設定專案」。
建立測試部署
- 在複製的 Apps 指令碼專案中,依序按一下「Deploy」>「Test deployments」。
- 複製主部署 ID,以便在後續步驟中使用,然後按一下「完成」。
- 前往 Google Cloud 控制台的「Chat API」頁面。
前往 Chat API
- 按一下「設定」。
- 請使用以下資訊設定 Chat API:
- Name (名稱):
Meeting Scheduler
- 顯示圖片網址:新增指向圖片的網址,圖片大小不得低於 256 x 256 像素。
- 說明:
Quickly create meetings.
- 功能:勾選兩個方塊,即可讓使用者直接傳送訊息給應用程式,並將應用程式新增至聊天室。
- 連線設定:按一下「Apps Script」,然後輸入主部署 ID。
- 斜線指令:請按照下列步驟新增
/help
和 /schedule_Meeting
的斜線指令:
- 按一下「Add slash command」,然後使用下列資訊進行設定:
- Name (名稱):
/help
- 指令 ID:
1
- 說明:
Learn what this app does.
- 再次按一下「Add slash command」,然後使用下列資訊進行設定:
- Name (名稱):
/schedule_Meeting
- 指令 ID:
2
- 說明:
Schedule a meeting.
- 勾選「Opens a dialog」方塊。
- 權限:選取「僅限您網域中的特定使用者和群組」,然後輸入您的電子郵件地址。
- 按一下「儲存」並重新整理頁面。
- 在設定頁面的「應用程式狀態」下方,將狀態設為「已上架 - 可供使用者使用」。
- 按一下 [儲存]。
執行指令碼
- 開啟 Google Chat。
- 按一下「開始即時通訊」圖示 add。
- 搜尋應用程式名稱
Meeting Scheduler
。
- 傳送初始訊息 (例如
hello
),以便要求授權。
應用程式回應後,請按一下「Configure」並授權應用程式。如果 OAuth 同意畫面顯示「This app isn't verified」警告,請繼續依序選取「Advanced」>「Go to {Project Name} (unsafe)」。
將 /schedule_Meeting
傳送至應用程式。
在對話方塊中,至少新增一個邀請對象的電子郵件地址。您可以更新其他欄位或使用預設項目。
按一下「提交」。
如要查看會議,請按一下「開啟日曆活動」。
查看程式碼
如要查看這個解決方案的 Apps Script 程式碼,請按一下下方的「查看原始碼」:
查看原始碼
Dialog.gs
/**
* 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'
}
}
}
}
}
}
}
}
}
}
後續步驟