本頁說明如何設定及回應 Google Chat 應用程式。
斜線指令是使用者叫用這類指令並與其互動的常見方式 Chat 應用程式。斜線指令還能幫助使用者 使用 Chat 應用程式的重要功能
如要使用斜線指令,使用者只要輸入斜線 (/
),然後輸入簡短文字指令:
(例如 /about
) 即可取得 Chat 應用程式的資訊。
使用者只要在網址列輸入斜線
Google Chat 畫面會列出視窗,當中列出
Chat 擴充應用程式:
![斜線指令視窗](https://developers-dot-devsite-v2-prod.appspot.com/static/workspace/chat/images/slash-command-window.png?authuser=6&hl=zh-tw)
當使用者傳送的訊息含有斜線指令時, 不會向使用者顯示
如要判斷是否應設定斜線指令,以及瞭解 設計使用者互動,請參閱 定義所有使用者歷程。
必要條件
Node.js
已啟用互動功能的 Google Chat 應用程式。如要建立 請使用 HTTP 服務互動式即時通訊應用程式,請完成快速入門導覽課程。
Apps Script
已啟用互動功能的 Google Chat 應用程式。如要建立 ,請完成快速入門導覽課程。
Python
已啟用互動功能的 Google Chat 應用程式。如要建立 請使用 HTTP 服務互動式即時通訊應用程式,請完成快速入門導覽課程。
設定斜線指令
本節說明如何完成以下設定斜線 指令:
為斜線指令命名
斜線指令的名稱是使用者在 Chat 訊息中輸入的名稱 即可叫用 Chat 應用程式亦提供簡短說明 ,藉此提示使用者進一步瞭解如何使用指令:
![Slash 指令名稱和說明](https://developers-dot-devsite-v2-prod.appspot.com/static/workspace/chat/images/slash-command-description.png?authuser=6&hl=zh-tw)
為斜線指令選擇名稱和說明時,請考慮使用 以下建議:
如何為斜線指令命名:
- 使用簡短、敘述性且能採取行動的字詞或詞組,做為
使用簡單明瞭的指令舉例來說
/createAReminder
,使用/remindMe
。 - 如果您的指令包含多個字詞,請協助使用者閱讀指令。
第一個字是全部小寫,然後再將第一個字的大寫
其他字詞的字母。例如,我不是
/updatecontact
使用/updateContact
。 - 請思考要對指令使用不重複名稱或一般名稱。如果
您的指令說明瞭一般互動或功能,您可以使用
使用者熟悉且預期的通用名稱,例如
/settings
或/feedback
。否則,請嘗試使用不重複的指令名稱,因為如果您的 其他 Chat 應用程式的指令名稱相同,使用者必須 篩選類似的指令,以尋找和使用您的
- 使用簡短、敘述性且能採取行動的字詞或詞組,做為
使用簡單明瞭的指令舉例來說
如何描述斜線指令:
- 說明以簡潔扼要的方式提供使用者預期 他們叫用這個指令時
- 讓使用者瞭解指令是否有任何格式規定。
舉例來說,假設您建立需要引數的
/remindMe
指令 請將說明設為Remind me to do [something] at [time]
之類的名稱。 - 告知使用者 Chat 應用程式是否會回覆
聊天室中的所有成員,或僅限叫用指令的使用者查看。
舉例來說,對於斜線指令
/about
,您可以將其描述為Learn about this app (Only visible to you)
。如要私下回覆 斜線指令,請參閱「使用私人訊息回應」一節。
在 Google Chat API 中設定斜線指令
如要建立斜線指令,您必須在 Chat API 的 Chat 應用程式設定。
如要在 Google Chat API 中設定斜線指令,請完成下列步驟 步驟:
在 Google Cloud 控制台中,按一下「選單」圖示 > API 與服務 > 已啟用的 API 和服務 > Google Chat API
按一下「設定」。
在「斜線指令」下方,按一下「新增斜線指令」。
輸入指令的名稱、指令 ID 和說明:
- 「Name」:指令的顯示名稱,以及使用者輸入的內容 即可叫用應用程式開頭須為斜線、只包含文字,且 最多 50 個半形字元
- 說明:說明使用方法和格式的文字 非必填的旗標說明的長度上限為 50 個半形字元。
- 指令 ID:介於 1 到 1000 的 用來辨識斜線指令的 Chat 應用程式 並傳回回應
選用:如果想讓 Chat 應用程式回覆 找出內含 dialog 的指令,然後選取 「開啟對話方塊」核取方塊。
按一下 [儲存]。
系統隨即會為 Chat 應用程式設定斜線指令。
回應斜線指令
當使用者建立含有斜線指令的 Chat 訊息時,
您的 Chat 應用程式收到 MESSAGE
互動事件。
事件酬載包含斜線指令的相關資訊
包括 slashCommand
和 slashCommandMetadata
只要使用來自這些領域的
小型資料集訓練即可您可以使用這些欄位識別指令 ID,並傳回
回應。
下列範例顯示 MESSAGE
互動事件的 JSON 酬載
包括斜線指令 /vote
:
{
...
"message": {
...
"text": "/vote yes",
"argumentText": " yes",
"slashCommand": {
"commandId": 2
},
"annotations": [
{
"length": 5,
"startIndex": 0,
"type": "SLASH_COMMAND",
"slashCommand": {
"commandName":"/vote",
"commandId":1,
"type": "INVOKE",
"bot": {
"avatarUrl": "https://www.example.com/images/vote-app-icon.png",
"displayName": "Voter Chat App",
"name": "users/1234567890987654321",
"type": "BOT"
}
}
}
]
}
}
如要回應斜線指令,您可以偵測 slashCommand
欄位是否
會在事件酬載中顯示,如果有,則傳回指令的回應。
以下程式碼範例說明如何回應 MESSAGE
互動事件
,其中包含一個斜線指令:
Node.js
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/
exports.onMessage = function onMessage(req, res) {
// Stores the Google Chat event as a variable.
var event = req.body;
// Checks for the presence of event.message.slashCommand.
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case ID: // The ID for your slash command
res.json(runFunction); // The response to the slash command.
}
}
Apps Script
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/
function onMessage(event) {
// Checks for the presence of event.message.slashCommand
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case ID: // The ID for your slash command
return runFunction; // The response to the slash command.
}
}
}
Python
from typing import Any, Mapping
import flask
import functions_framework
@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
"""Responds to a MESSAGE event in Google Chat that includes a slash command.
Args:
req (flask.Request): the event object from Chat API.
Returns:
Mapping[str, Any]: function in response to a slash command.
"""
if req.method == 'GET':
return 'Sorry, this function must be called from a Google Chat.'
request = req.get_json(silent=True)
if slash_command := request.get('message', dict()).get('slashCommand'):
command_id = slash_command['commandId']
if command_id == ID:
return runFunction
如要使用程式碼,請替換以下程式碼:
ID
:您在建立指令時指定的指令 ID 在 Google Chat API 中設定斜線指令。runFunction
:這個函式會建立回應 斜線指令
選用:回覆私人訊息
只有傳送 訊息和接收指令的 Chat 應用程式。如果 您已設定將 Chat 應用程式新增至聊天室 多人共用時,建議您回應斜線指令 以私密方式,保護使用者與 Chat 應用程式。
舉例來說,假設某個團隊正在使用
客戶服務時,使用者可以叫用斜線指令,例如:
/myCases
:查看指派給他們的客服案件。如果團隊將
Chat 擴充應用程式至聊天室的使用者,會使用斜線指令
在聊天室中,你可能只想透過 Chat 應用程式回覆
具體做法是指示 Kubernetes 建立並維護
一或多個代表這些 Pod 的物件為了避免使用者向聊天室中的所有人發布客服案件,請
Chat 應用程式可以私下回覆。
如要以私密方式回應斜線指令,請參閱 傳送私人訊息給 Google Chat 使用者。
完整範例:使用 Rolodex Chat 應用程式設定聯絡人
以下範例顯示會回應 下列斜線指令:
/help
指令會傳回文字訊息,說明如何取得 為 Chat 應用程式提供支援服務。指令 ID 已設定 至1
。/createContact
指令會開啟對話方塊,供使用者輸入內容 聯絡人的詳細資料指令 ID 設定為2
。
執行這個範例前,請先按照下列步驟完成 在 Google Chat API 中設定斜線指令。
Node.js
/**
* Responds to messages that have links whose URLs
* match URL patterns configured for link previews.
*
* @param {Object} event The event object from Chat
* API.
*
* @return {Object} Response from the Chat app
* attached to the message with the previewed link.
*/
exports.onMessage = function onMessage(req, res) {
// Store the Google Chat event as a variable.
const event = req.body;
if (req.method === "GET" || !event.message) {
res.send("Hello! This function is meant to be used in a Google Chat " +
"Space.");
}
// Checks for the presence of event.message.slashCommand.
// If the slash command is "/help", responds with a text message.
// If the slash command is "/createContact", opens a dialog.
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case 1: // /help
res.json({"text": "Contact bot helps you update your address book!"});
case 2: // /createContact
res.json(openDialog(event));
}
}
// If the Chat app doesn"t detect a slash command, it responds
// with a card that prompts the user to add a contact
else {
res.json({
"cardsV2": [{
"cardId": "addContact",
"card": {
"header": {
"title": "Rolodex",
"subtitle": "Manage your contacts!",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
"imageType": "CIRCLE"
},
"sections": [
{
"widgets": [
{
"buttonList": {
"buttons": [
{
"text": "Add Contact",
"onClick": {
"action": {
"function": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}
]
}
}
]
}
]
}
}]
});
}
// Respond to button clicks on attached cards
if (event.type === "CARD_CLICKED") {
if (event.common.invokedFunction === "openDialog") {
res.json(openDialog(event));
}
if (event.common.invokedFunction === "openSequentialDialog") {
res.json(openSequentialDialog(event));
}
if (event.common.invokedFunction === "confirmDialogSuccess") {
res.json(confirmDialogSuccess(event));
}
}
};
/**
* Opens and starts a dialog that lets users add details about a contact.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openDialog(event) {
return {
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Name",
"type": "SINGLE_LINE",
"name": "name"
}
},
{
"textInput": {
"label": "Address",
"type": "MULTIPLE_LINE",
"name": "address"
}
},
{
"decoratedText": {
"text": "Add to favorites",
"switchControl": {
"controlType": "SWITCH",
"name": "saveFavorite"
}
}
},
{
"decoratedText": {
"text": "Merge with existing contacts",
"switchControl": {
"controlType": "SWITCH",
"name": "mergeContact",
"selected": true
}
}
},
{
"buttonList": {
"buttons": [
{
"text": "Next",
"onClick": {
"action": {
"function": "openSequentialDialog"
}
}
}
]
}
}
]
}
]
}
}
}
}
};
};
/**
* Opens a second dialog that lets users add more contact details.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openSequentialDialog(event) {
return {
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Notes",
"type": "MULTIPLE_LINE",
"name": "notes"
}
},
{
"selectionInput": {
"type": "RADIO_BUTTON",
"label": "Contact type",
"name": "contactType",
"items": [
{
"text": "Work",
"value": "Work",
"selected": false
},
{
"text": "Personal",
"value": "Personal",
"selected": false
}
]
}
},
{
"buttonList": {
"buttons": [
{
"text": "Submit",
"onClick": {
"action": {
"function": "confirmDialogSuccess",
"parameters": [
{
"key": "confirmDialogSuccess",
"value": "confirmDialogSuccess"
}
]
}
}
}
]
},
"horizontalAlignment": "END"
}
]
}
]
}
}
}
}
};
}
/**
* Checks for a form input error, the absence of
* a "name" value, and returns an error if absent.
* Otherwise, confirms successful receipt of a dialog.
*
* Confirms successful receipt of a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
function receiveDialog(event) {
// Checks to make sure the user entered a name
// in a dialog. If no name value detected, returns
// an error message.
if (event.common.formInputs.contactName.stringInputs.value[0] === "") {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": {
"statusCode": "OK",
"userFacingMessage": "Don't forget to name your new contact!"
}
}
}
};
// Otherwise the app indicates that it received
// form data from the dialog. Any value other than "OK"
// gets returned as an error. "OK" is interpreted as
// code 200, and the dialog closes.
} else {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "OK"
}
}
};
}
}
Apps Script
此範例會透過 資訊卡 JSON。 您也可以使用 Apps Script Card 服務。
Python
from typing import Any, Mapping
import flask
import functions_framework
@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
"""Responds to a MESSAGE event in Google Chat that includes the /createContact
slash command by opening a dialog.
Args:
req (flask.Request): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
if req.method == 'GET':
return 'Sorry, this function must be called from a Google Chat.'
request = req.get_json(silent=True)
if request.get('type') == 'CARD_CLICKED':
invoked_function = request.get('common', dict()).get('invokedFunction')
if invoked_function == 'open_dialog':
return open_dialog(request)
elif invoked_function == 'open_sequential_dialog':
return open_dialog(request)
elif invoked_function == "receive_dialog":
return receive_dialog(request)
else:
return {
'cardsV2': [{
'cardId': 'addContact',
'card': {
'header': {
'title': 'Rolodex',
'subtitle': 'Manage your contacts!',
'imageUrl': 'https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png',
'imageType': 'CIRCLE'
},
'sections': [
{
'widgets': [
{
'buttonList': {
'buttons': [
{
'text': 'Add Contact',
'onClick': {
'action': {
'function': 'open_dialog',
'interaction': 'OPEN_DIALOG'
}
}
}
]
}
}
]
}
]
}
}]
}
def open_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a dialog in Google Chat.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Name',
'type': 'SINGLE_LINE',
'name': 'name'
}
},
{
'textInput': {
'label': 'Address',
'type': 'MULTIPLE_LINE',
'name': 'address'
}
},
{
'decoratedText': {
'text': 'Add to favorites',
'switchControl': {
'controlType': 'SWITCH',
'name': 'saveFavorite'
}
}
},
{
'decoratedText': {
'text': 'Merge with existing contacts',
'switchControl': {
'controlType': 'SWITCH',
'name': 'mergeContact',
'selected': True
}
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Next',
'onClick': {
'action': {
'function': 'open_sequential_dialog'
}
}
}
]
}
}
]
}
]
}
}
}
}
}
def open_sequential_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a second dialog that lets users add more contact details.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Notes',
'type': 'MULTIPLE_LINE',
'name': 'notes'
}
},
{
'selectionInput': {
'type': 'RADIO_BUTTON',
'label': 'Contact type',
'name': 'contactType',
'items': [
{
'text': 'Work',
'value': 'Work',
'selected': False
},
{
'text': 'Personal',
'value': 'Personal',
'selected': False
}
]
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Submit',
'onClick': {
'action': {
'function': 'receive_dialog',
'parameters': [
{
'key': 'receiveDialog',
'value': 'receiveDialog'
}
]
}
}
}
]
},
'horizontalAlignment': 'END'
}
]
}
]
}
}
}
}
}
def receive_dialog(event: Mapping[str, Any]) -> Mapping[str, Any]:
"""Checks for a form input error, the absence of a "name" value, and returns
an error if absent. Otherwise, confirms successful receipt of a dialog.
Args:
event (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: the response.
"""
if event.get('common', dict()) \
.get('formInputs', dict()).get('contactName', dict()) \
.get('stringInputs').get('value', list()):
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': 'OK'
}
}
}
else:
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': "Don't forget to name your new contact!"
}
}
}