หน้านี้อธิบายวิธีเปิดแอป Chat และ ตอบสนองต่อกล่องโต้ตอบ
กล่องโต้ตอบเป็นอินเทอร์เฟซที่ทำงานบนการ์ดในโหมดหน้าต่าง ซึ่ง แอปแชทจะเปิดขึ้นเพื่อโต้ตอบกับผู้ใช้ เพื่อช่วยให้ผู้ใช้ดำเนินการ ซึ่งหลายขั้นตอน แอป Chat จะเปิดตามลำดับได้ กล่องโต้ตอบ
กล่องโต้ตอบมีประโยชน์สำหรับการโต้ตอบของผู้ใช้ประเภทต่อไปนี้
- การรวบรวมข้อมูลจากผู้ใช้
- การตรวจสอบสิทธิ์ผู้ใช้ด้วยบริการเว็บ
- การกําหนดการตั้งค่าแอปใน Chat
การเปิด ส่ง หรือยกเลิกกล่องโต้ตอบต้องใช้การตอบกลับแบบพร้อมกัน
จากแอป Chat ที่มี
DialogEventType
แอป Chat ไม่รองรับกล่องโต้ตอบ
สร้างขึ้นด้วยสถาปัตยกรรมแบบอะซิงโครนัส เช่น
Pub/Sub หรือ
create
ข้อความ
หากแอป Chat ใช้แบบไม่พร้อมกัน
สถาปัตยกรรม ให้ใช้
ข้อความในการ์ด
แทนกล่องโต้ตอบ
ข้อกำหนดเบื้องต้น
Node.js
- Google Workspace บัญชีที่มีสิทธิ์เข้าถึง Google Chat
- แอปใน Chat วิธีสร้าง แอปแชท โปรดทำตามนี้ Quickstart
- หากเปิดกล่องโต้ตอบเพื่อตอบสนองต่อคำสั่งเครื่องหมายทับ คำสั่งเครื่องหมายทับ กำหนดค่าโดยเลือกเปิดกล่องโต้ตอบไว้
ตัวอย่างโค้ด Node.js ถูกเขียนขึ้นมาเพื่อเรียกใช้เป็น Cloud Function
Apps Script
- Google Workspace บัญชีที่มีสิทธิ์เข้าถึง Google Chat
- แอปใน Chat วิธีสร้าง แอปแชท โปรดทำตามนี้ Quickstart
- หากเปิดกล่องโต้ตอบเพื่อตอบสนองต่อคำสั่งเครื่องหมายทับ คำสั่งเครื่องหมายทับ กำหนดค่าโดยเลือกเปิดกล่องโต้ตอบไว้
Python
- Google Workspace บัญชีที่มีสิทธิ์เข้าถึง Google Chat
- แอปใน Chat วิธีสร้าง แอปแชท โปรดทำตามนี้ Quickstart
- หากเปิดกล่องโต้ตอบเพื่อตอบสนองต่อคำสั่งเครื่องหมายทับ คำสั่งเครื่องหมายทับ กำหนดค่าโดยเลือกเปิดกล่องโต้ตอบไว้
ตัวอย่างโค้ด Python ถูกเขียนเพื่อเรียกใช้เป็น Cloud Function โดยใช้ Python 3.9
เปิดกล่องโต้ตอบ
แอป Chat สามารถเปิดกล่องโต้ตอบเพื่อตอบผู้ใช้ได้ คลิกปุ่ม ใน ข้อความในการ์ด
![คลิกปุ่มบนการ์ดเพื่อเปิดกล่องโต้ตอบ](https://developers.google.com/static/workspace/chat/images/dialogs-open-card-click.png?authuser=1&hl=th)
แอป Chat สามารถเปิดกล่องโต้ตอบเพื่อตอบผู้ใช้ได้ การออก คำสั่งเครื่องหมายทับ
![คลิกปุ่มบนการ์ดเพื่อเปิดกล่องโต้ตอบ](https://developers.google.com/static/workspace/chat/images/dialogs-open-slash-command.png?authuser=1&hl=th)
เมื่อผู้ใช้เปิดกล่องโต้ตอบ แอป Chat ของคุณจะได้รับ CANNOT TRANSLATE เหตุการณ์การโต้ตอบต่อไปนี้ ข้อมูล:
isDialogEvent
คือtrue
DialogEventType
ระบุ ผู้ใช้ดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้REQUEST_DIALOG
: เปิดกล่องโต้ตอบSUBMIT_DIALOG
: คลิกปุ่มในกล่องโต้ตอบCANCEL_DIALOG
: ยกเลิกกล่องโต้ตอบ
เช่น เมื่อผู้ใช้เปิดกล่องโต้ตอบ แอป Chat ของคุณ ได้รับเหตุการณ์การโต้ตอบที่คล้ายกับตัวอย่างต่อไปนี้
JSON
{
"type": enum (EventType),
"eventTime": string,
"threadKey": string,
"message": {
object (Message)
},
"user": {
object (User)
},
"space": {
object (Space)
},
"action": {
object (FormAction)
},
"configCompleteRedirectUrl": string,
"isDialogEvent": true,
"dialogEventType": "REQUEST_DIALOG",
"common": {
object (CommonEventObject)
}
}
แอป Chat จะเปิดกล่องโต้ตอบได้โดยการส่งคืน
ActionResponse
ของ "type": "DIALOG"
ที่มี
DialogAction
ที่มีคำอธิบาย JSON ของกล่องโต้ตอบ:
JSON
{
"action_response": {
"type": "DIALOG",
"dialog_action": {
"dialog": {
"body": {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Name",
"type": "SINGLE_LINE",
"name": "contactName"
}
},
{
"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"
}
}
}
]
}
}
]
}
]
}
}
}
}
}
เปิดกล่องโต้ตอบเพื่อตอบสนองต่อการคลิกปุ่มการ์ด
หากต้องการให้ปุ่มการ์ดเปิดกล่องโต้ตอบ ให้ระบุสิ่งต่อไปนี้
onClick.action.function
ในชื่อ ชื่อของฟังก์ชันที่เปิดกล่องโต้ตอบonClick.action.interaction
ในชื่อOPEN_DIALOG
พร็อพเพอร์ตี้นี้จะแจ้ง Chat ว่า แอป Chat ต้องการเปิดกล่องโต้ตอบ
เมื่อผู้ใช้คลิกปุ่มบนการ์ด แอป Chat ของคุณ ได้รับเหตุการณ์การโต้ตอบที่มีข้อมูลต่อไปนี้
EventType
คือCARD_CLICKED
DialogEventType
คือREQUEST_DIALOG
common.invokedFunction
คือชื่อของฟังก์ชันจากพร็อพเพอร์ตี้onClick
ของการคลิกที่ ปุ่มการ์ด
หากต้องการเปิดกล่องโต้ตอบ ให้ตอบกลับดังนี้
- CANNOT TRANSLATE
ActionResponse
จาก"type": "DIALOG"
- ต
DialogAction
ที่มีคำอธิบาย JSON ของกล่องโต้ตอบ
ในตัวอย่างนี้ แอป Chat จะตอบสนองต่อ MESSAGE
เหตุการณ์การโต้ตอบกับการ์ดที่มีปุ่มที่เปิดกล่องโต้ตอบ
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.");
}
// 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") {
openDialog(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) {
res.json({
"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"
}
}
}
]
}
}
]
}
]
}
}
}
}
});
};
}
}
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
/**
* Responds to a MESSAGE event in Google Chat with a card with a button
* that opens a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in response to a card's button click.
*/
function onMessage(event) {
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": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}
]
},
"horizontalAlignment": "CENTER"
}
]
}
]
}
}]
};
}
/**
* Responds to a CARD_CLICKED event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
function onCardClick(event) {
if (event.common.invokedFunction === "openDialog") {
return openDialog(event);
}
}
/**
* Opens a dialog in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
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": "contactName"
}
},
{
"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"
}
}
}
]
}
}
]
}
]
}
}
}
}
};
}
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':
if request.get('common', dict()).get('invokedFunction') == 'open_dialog':
return open_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'
}
}
}
]
}
}
]
}
]
}
}
}
}
}
เปิดกล่องโต้ตอบเพื่อตอบกลับคำสั่งเครื่องหมายทับ
เมื่อผู้ใช้เปิดกล่องโต้ตอบที่มี คำสั่งเครื่องหมายทับที่กำหนดค่าไว้สำหรับการเปิดกล่องโต้ตอบ แอป Chat ได้รับเหตุการณ์การโต้ตอบกับแท็ก ข้อมูลต่อไปนี้
EventType
คือMESSAGE
DialogEventType
มีค่าREQUEST_DIALOG
หากต้องการเปิดกล่องโต้ตอบ ให้ตอบกลับดังนี้
- CANNOT TRANSLATE
ActionResponse
จาก"type": "DIALOG"
DialogAction
ที่มีคำอธิบาย JSON ของกล่องโต้ตอบ
ในตัวอย่างนี้ แอป Chat จะตอบสนองต่อ
/createContact
โดยใช้คำสั่งเครื่องหมายทับโดยเปิดกล่องโต้ตอบ ดังนี้
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
openDialog(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) {
res.json({
"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"
}
}
}
]
}
}
]
}
]
}
}
}
}
});
};
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
/**
* Responds to a MESSAGE event in Google Chat that includes the /createContact
* slash command by opening a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in response to a slash command.
*/
function onMessage(event) {
// 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
return {"text": "Contact bot helps you update your address book!"}
case 2: // /createContact
return openDialog(event);
}
}
}
/**
* Opens a dialog in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
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": "contactName"
}
},
{
"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"
}
}
}
]
}
}
]
}
]
}
}
}
}
};
}
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 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 == 1:
return {'text': 'Contact bot helps you update your address book!'}
elif command_id == 2:
return open_dialog(request)
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 slash command.
"""
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'
}
}
}
]
}
}
]
}
]
}
}
}
}
}
เปิดกล่องโต้ตอบตามลำดับ
หากการโต้ตอบของผู้ใช้ต้องใช้กล่องโต้ตอบมากกว่า 1 กล่องโต้ตอบ คุณจะเปิดกล่องโต้ตอบอื่นได้
โดยแสดงผลกล่องโต้ตอบถัดไปในลำดับตาม SUBMIT_DIALOG
DialogEventType
![กล่องโต้ตอบที่มีวิดเจ็ตต่างๆ มากมาย](https://developers.google.com/static/workspace/chat/images/dialogs-card-1.png?authuser=1&hl=th)
ในปุ่มการ์ดที่อัปเดตกล่องโต้ตอบ ให้ย้อนกลับ
onClick.action.function
เป็น
ชื่อของฟังก์ชันที่เปิดกล่องโต้ตอบถัดไปและ
ไม่ระบุ onClick.action.interaction
![กล่องโต้ตอบที่มีวิดเจ็ตต่างๆ มากมาย](https://developers.google.com/static/workspace/chat/images/dialogs-card-2.png?authuser=1&hl=th)
เมื่อทำเสร็จแล้ว แอป Chat จะได้รับค่าที่ผู้ใช้ ป้อนลงในกล่องโต้ตอบเป็น JSON แจ้งให้ผู้ใช้ทราบว่าการโต้ตอบสําเร็จด้วยการ ตอบกลับด้วย SMS หรือข้อความในการ์ด
เมื่อผู้ใช้คลิกปุ่มในกล่องโต้ตอบ แอป Chat ของคุณ ได้รับเหตุการณ์การโต้ตอบที่มีข้อมูลต่อไปนี้
EventType
มีค่าCARD_CLICKED
DialogEventType
มีค่าSUBMIT_DIALOG
ในตัวอย่างนี้ แอป Chat ตอบสนอง
CARD_CLICKED
เหตุการณ์การโต้ตอบจากการคลิกปุ่มกล่องโต้ตอบโดยการเปิดเหตุการณ์อื่น
กล่องโต้ตอบ:
Node.js
// Respond to button clicks on attached cards
if (event.type === "CARD_CLICKED") {
// Open the first dialog.
if (event.common.invokedFunction === "openDialog") {
openDialog(event);
}
// Open the second dialog.
if (event.common.invokedFunction === "openSequentialDialog") {
openSequentialDialog(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) {
res.json({
"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) {
res.json({
"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"
}
]
}
]
}
}
}
}
});
}
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
/**
* Responds to a CARD_CLICKED event in Google Chat.
*
* @param {Object} event the event object from Google Chat
*/
function onCardClick(event) {
// When a user clicks a card, the Chat app checks to see which function to run.
if (event.common.invokedFunction === "openDialog") {
return openDialog(event);
}
if (event.common.invokedFunction === "openSequentialDialog") {
return openSequentialDialog(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": "contactName"
}
},
{
"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": {
// Specifies which function to run
// in response to the card click.
"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": {
// Specifies which function to run
// in response to the card click.
"function": "receiveDialog",
"parameters": [
{
"key": "receiveDialog",
"value": "receiveDialog"
}
]
}
}
}
]
},
"horizontalAlignment": "END"
}
]
}
]
}
}
}
}
};
}
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':
if 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)
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': 'receiveDialog',
'parameters': [
{
'key': 'receiveDialog',
'value': 'receiveDialog'
}
]
}
}
}
]
},
'horizontalAlignment': 'END'
}
]
}
]
}
}
}
}
}
เปิดกล่องโต้ตอบเพื่อตอบกลับข้อความการ์ดหน้าแรกของแอป
สำหรับข้อความการ์ดหน้าแรกของแอปเท่านั้น
ใช้ render_actions
แทน action_response
เพื่อเปิดกล่องโต้ตอบ:
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
function openDialog() {
return {
render_actions: {
action: {
navigations: [{
update_card: {
"sections": [
{
"header": "Add new contact",
"widgets": [
{
"textInput": {
"label": "Name",
"type": "SINGLE_LINE",
"name": "contactName"
}
},
{
"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"
}
}
}
]
}
}]
}]
}
}]
}
}
}
}
รับข้อมูลแบบฟอร์มจากกล่องโต้ตอบ
เมื่อผู้ใช้คลิกปุ่มในกล่องโต้ตอบ ระบบจะส่งข้อมูลที่ป้อนไปยัง แอป Chat และ แอป Chat ได้รับเหตุการณ์การโต้ตอบกับ ข้อมูลต่อไปนี้
EventType
มีค่าCARD_CLICKED
DialogEventType
มีค่าSUBMIT_DIALOG
ข้อมูลที่ผู้ใช้ป้อนในกล่องโต้ตอบจะแสดงในเหตุการณ์การโต้ตอบแบบ
Event.common.formInputs
แมปที่คีย์คือรหัสสตริงที่กำหนดให้กับวิดเจ็ตและค่าของกล่องโต้ตอบแต่ละรายการ
แสดงถึงข้อมูลจากผู้ใช้สำหรับวิดเจ็ตแต่ละรายการ วัตถุที่ต่างกันแสดงไม่เหมือนกัน
ประเภทข้อมูลอินพุต ตัวอย่างเช่น
Event.common.formInputs.stringInputs
แทนอินพุตสตริง
เมื่อผู้ใช้ส่งกล่องโต้ตอบ แอป Chat ของคุณจะได้รับ เหตุการณ์การโต้ตอบแบบนี้จาก Chat:
JSON
{
"type": enum (EventType),
"eventTime": string,
"threadKey": string,
"message": {
object (Message)
},
"user": {
object (User)
},
"space": {
object (Space)
},
"action": {
object (FormAction)
},
"configCompleteRedirectUrl": string,
// Indicates that this event is dialog-related.
"isDialogEvent": true,
// Indicates that a user clicked a button, and all data
// they entered in the dialog is included in Event.common.formInputs.
"dialogEventType": "SUBMIT_DIALOG",
"common": {
"userLocale": string,
"hostApp": enum (HostApp),
"platform": enum (Platform),
"timeZone": {
object (TimeZone)
},
// Represents user data entered in a dialog.
"formInputs": {
// Represents user data entered for a specific field in a dialog.
"NAME": {
// Represents string data entered in a dialog, like text input fields
// and check boxes.
"stringInputs": {
// An array of strings entered by the user in a dialog.
"value": [
string
]
}
}
},
"parameters": {
string: string,
...
},
"invokedFunction": string
}
}
แอปใน Chat จะเข้าถึงค่าแรกที่ผู้ใช้ป้อนได้
เวลา event.common.formInputs.NAME.stringInputs.value[0]
โดยที่ NAME คือฟิลด์ name
ของ
วิดเจ็ต TextInput
หลังจากได้รับข้อมูลจากฟอร์มกล่องโต้ตอบแล้ว แอป Chat
ควรตอบกลับด้วย
ActionResponse
- หากต้องการตอบรับว่าได้รับใบเสร็จแล้ว โปรดตอบกลับเป็น
ActionResponse
ที่มี"actionStatus": "OK"
การทำเช่นนี้จะปิดกล่องโต้ตอบโดยไม่โพสต์ คำตอบ - หากต้องการตอบกลับด้วยข้อความหรือข้อความการ์ด ให้ตอบกลับด้วย
ActionResponse
ที่มีResponseType
จากNEW_MESSAGE
,UPDATE_MESSAGE
หรือUPDATE_USER_MESSAGE_CARDS
สำหรับข้อมูลเพิ่มเติม ดูข้อมูลได้ที่ ตอบกลับกล่องโต้ตอบ - หากต้องการส่งคืนข้อผิดพลาด โปรดตอบกลับด้วย
ActionResponse
ที่มี"actionStatus": "ERROR MESSAGE"
ตัวอย่างต่อไปนี้จะตรวจหาค่า name
ที่มีอยู่ หากขาดข้อมูลดังกล่าว
แอป Chat แสดงข้อผิดพลาด หากมี ค่า
แอป Chat รับทราบข้อมูลในแบบฟอร์มและ
ปิดกล่องโต้ตอบ
Node.js
/**
* 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. Any "actionStatus" value other than "OK"
// gets returned as an error.
if (event.common.formInputs.WIDGET_NAME.stringInputs.value[0] === "") {
res.json({
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "Don't forget to name your new contact!"
}
}
});
// Otherwise the Chat app indicates that it received
// form data from the dialog. An "actionStatus" of "OK" is
// interpreted as code 200, and the dialog closes.
} else {
res.json({
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "OK"
}
}
});
}
}
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
/**
* 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. Any "actionStatus" value other than "OK"
// gets returned as an error.
if (event.common.formInputs.WIDGET_NAME[""].stringInputs.value[0] === "") {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "Don't forget to name your new contact!"
}
}
};
// Otherwise the Chat app indicates that it received
// form data from the dialog. An "actionStatus" of "OK" is
// interpreted as code 200, and the dialog closes.
} else {
return {
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "OK"
}
}
};
}
}
Python
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 common := event.get('common'):
if form_inputs := common.get('formInputs'):
if contact_name := form_inputs.get('WIDGET_NAME'):
if string_inputs := contact_name.get('stringInputs'):
if name := string_inputs.get('value')[0]:
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': 'OK'
}
}
}
else:
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': 'Don\'t forget to name your new contact!'
}
}
}
ตอบกลับกล่องโต้ตอบ
คุณสามารถตอบกลับกล่องโต้ตอบด้วยข้อความใหม่หรือการอัปเดต ข้อความที่มีอยู่
ตอบกลับกล่องโต้ตอบด้วยข้อความใหม่
หากต้องการตอบกลับการส่งแบบฟอร์มกล่องโต้ตอบด้วยข้อความใหม่ ฟิลด์
แอป Chat แสดง
ActionResponse
ประเภท NEW_MESSAGE
พร้อมด้วย
มาร์กอัป
เพื่อระบุเนื้อหาของข้อความใหม่ เมื่อได้รับการตอบกลับนี้แล้ว
กล่องโต้ตอบจะปิดลงและมีการโพสต์ข้อความใหม่
โค้ดต่อไปนี้เป็นตัวอย่างของการตอบสนอง JSON ไปยังกล่องโต้ตอบที่ส่งโดย วิธีสร้างข้อความตอบกลับใหม่ในแอป Chat
JSON
{
"actionResponse": {
"type": "NEW_MESSAGE",
},
"text": "This message is a reply to a dialog form submission.",
"cardsV2": [
{
"cardId": "reply-card-id",
"card": {
"header": {
"title": "Reply card title"
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": "Reply card message"
}
}
]
}
]
}
}
]
}
แอป Chat ยังสามารถตอบกลับแบบไม่พร้อมกันด้วย ข้อความ หรือ การ์ด
ตอบกลับกล่องโต้ตอบด้วยข้อความที่อัปเดต
เมื่อตอบกลับกล่องโต้ตอบที่มีข้อความที่อัปเดตแล้ว คุณจะอัปเดต ข้อความแอปใน Chat เดิมหรืออัปเดตตัวอย่างลิงก์
ข้อความแอปใน Chat
หากต้องการตอบกลับการส่งแบบฟอร์มโต้ตอบที่มีการอัปเดตข้อความที่มีอยู่
ที่ส่งโดยแอป Chat จะแสดงผล
ActionResponse
ประเภท UPDATE_MESSAGE
คำตอบประกอบด้วย
มาร์กอัป
ซึ่งระบุเนื้อหาของข้อความที่ได้รับการอัปเดต เมื่อได้รับ
การตอบกลับ กล่องโต้ตอบจะปิดลงและข้อความจะได้รับการอัปเดตด้วยเนื้อหาใหม่
โค้ดต่อไปนี้เป็นตัวอย่างของการตอบสนอง JSON ไปยังกล่องโต้ตอบที่ส่งโดย แอป Chat เพื่ออัปเดต ข้อความแอป Chat:
JSON
{
"actionResponse": {
"type": "UPDATE_MESSAGE",
},
"text": "This message has been updated with new content in response to a dialog form submission.",
"cardsV2": [
{
"cardId": "updated-card-id",
"card": {
"header": {
"title": "Updated card title"
},
"sections": [
{
"widgets": [
{
"textParagraph": {
"text": "Updated card message"
}
}
]
}
]
}
}
]
}
นอกจากนี้ แอป Chat ยังทำงานแบบไม่พร้อมกัน อัปเดตข้อความแอปใน Chat โดยใช้ Google Chat API
ตัวอย่างลิงก์
เพื่ออัปเดต
ตัวอย่างลิงก์
ด้วยเนื้อหาใหม่ตามการส่งแบบฟอร์มโต้ตอบ
แอป Chat แสดง
ActionResponse
ประเภท UPDATE_USER_MESSAGE_CARDS
คำตอบประกอบด้วย
มาร์กอัป
สำหรับข้อความการ์ดใหม่ที่ใช้อัปเดตตัวอย่างลิงก์ หลัง
เมื่อได้รับการตอบกลับนี้ ระบบจะปิดกล่องโต้ตอบและอัปเดตตัวอย่างลิงก์
ด้วยข้อความการ์ดใหม่
ตัวอย่างการตอบกลับ JSON ต่อไปนี้อัปเดตตัวอย่างลิงก์ด้วยการ์ดใหม่ ข้อความ:
JSON
{
"actionResponse": "UPDATE_USER_MESSAGE_CARDS",
"cardsV2": [
{
"cardId" : "updated-card-id",
"card" : {
"header": {
"title": "Updated card title"
},
"sections": [
{
"widgets" : [
{
"textParagraph": {
"text": "Updated card message"
}
}
]
}
]
}
}
]
}
ตอบกลับกล่องโต้ตอบสำหรับข้อความการ์ดหน้าแรกของแอป
สำหรับข้อความการ์ดหน้าแรกของแอปเท่านั้น มี 2 วิธีในการปิดกล่องโต้ตอบ ดังนี้
CLOSE_DIALOG
: ปิดกล่องโต้ตอบและกลับไปที่ข้อความการ์ดหน้าแรกของแอปCLOSE_DIALOG_AND_EXECUTE
: ปิดกล่องโต้ตอบและรีเฟรชหน้าแรกของแอป ข้อความการ์ด
Python
ตัวอย่างโค้ดต่อไปนี้ใช้ CLOSE_DIALOG
เพื่อปิดกล่องโต้ตอบและกลับไปที่
ข้อความการ์ดหน้าแรกของแอป:
def close_dialog():
"""Handles dismiss dialog request from Chat."""
return {
'render_actions': {
'action': {
'navigations': [{
'end_navigation': {'action': 'CLOSE_DIALOG'}
}]
}
}
}
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
ตัวอย่างโค้ดต่อไปนี้ใช้ CLOSE_DIALOG
เพื่อปิดกล่องโต้ตอบและกลับไปที่
ข้อความการ์ดหน้าแรกของแอป:
function closeDialog(event) {
return {
render_actions: {
action:{
navigations:[{
end_navigation:{
action: "CLOSE_DIALOG"
}
}]
}
}
};
}
ตัวอย่างที่สมบูรณ์: Rolodex ผู้ติดต่อที่จัดการแอปแชท
ในตัวอย่างนี้ แอป Chat จะเปิดกล่องโต้ตอบเพื่อให้ผู้ใช้ สามารถเพิ่มรายละเอียดเกี่ยวกับรายชื่อติดต่อ เช่น ชื่อ อีเมล และที่อยู่ได้โดยทำดังนี้
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
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") {
openDialog(event);
}
if (event.common.invokedFunction === "openSequentialDialog") {
openSequentialDialog(event);
}
if (event.common.invokedFunction === "confirmDialogSuccess") {
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) {
res.json({
"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) {
res.json({
"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. Any "actionStatus" value other than "OK"
// gets returned as an error.
if (event.common.formInputs.contactName.stringInputs.value[0] === "") {
res.json({
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "Don't forget to name your new contact!"
}
}
});
// Otherwise the Chat app indicates that it received
// form data from the dialog. An "actionStatus" of "OK" is
// interpreted as code 200, and the dialog closes.
} else {
res.json({
"actionResponse": {
"type": "DIALOG",
"dialogAction": {
"actionStatus": "OK"
}
}
});
}
}
Apps Script
ตัวอย่างนี้ส่งข้อความการ์ดโดยการส่งคืน JSON ของการ์ด คุณยังสามารถใช้ บริการการ์ด Apps Script
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!"
}
}
}
แก้ปัญหา
เมื่อแอป Google Chat หรือ card จะแสดงผลข้อผิดพลาด อินเทอร์เฟซ Chat แสดงข้อความว่า "เกิดข้อผิดพลาด" หรือ "ไม่สามารถดำเนินการตามคำขอของคุณ" บางครั้ง UI ของ Chat ไม่แสดงข้อความแสดงข้อผิดพลาดใดๆ แต่แอป Chat หรือ ทำให้เกิดผลลัพธ์ที่ไม่คาดคิด เช่น ข้อความในการ์ดอาจ ปรากฏขึ้น
แม้ว่าข้อความแสดงข้อผิดพลาดอาจไม่แสดงใน UI ของแชท มีข้อความแสดงข้อผิดพลาดและข้อมูลบันทึกที่สื่อความหมายเพื่อช่วยคุณแก้ไขข้อผิดพลาด เมื่อมีการเปิดข้อผิดพลาดในการบันทึกสำหรับแอป Chat หากต้องการความช่วยเหลือในการดู การแก้ไขข้อบกพร่องและการแก้ไขข้อผิดพลาด โปรดดู แก้ปัญหาข้อผิดพลาดของ Google Chat