Abrir e responder a caixas de diálogo

Esta página descreve como seu app do Chat pode abrir e responder a caixas de diálogo.

As caixas de diálogo são interfaces em janelas baseadas em cards que os apps do Chat abrem para interagir com os usuários. Para ajudar os usuários a concluir processos de várias etapas, o app do Chat pode abrir caixas de diálogo sequenciais.

As caixas de diálogo são úteis para os seguintes tipos de interações do usuário:

  • Coleta de informações dos usuários
  • Como autenticar usuários com serviços da Web
  • Como definir as configurações do app do Chat

Para abrir, enviar ou cancelar uma caixa de diálogo, é preciso ter uma resposta síncrona de um app do Chat com um DialogEventType. As caixas de diálogo não são compatíveis com apps do Chat criados com uma arquitetura assíncrona, como Pub/Sub ou método de create mensagem. Se o app do Chat usa uma arquitetura assíncrona, use uma mensagem de card em vez de uma caixa de diálogo.

Pré-requisitos

Node.js

  • Uma conta do Google Workspace com acesso ao Google Chat.
  • Um app do Chat. Para criar um app do Chat, siga este quickstart.
  • Ao abrir uma caixa de diálogo em resposta a um comando de barra, um comando de barra configurado com a opção Abrir uma caixa de diálogo selecionada.

Os exemplos de código do Node.js são escritos para serem executados como uma função do Cloud.

Apps Script

  • Uma conta do Google Workspace com acesso ao Google Chat.
  • Um app do Chat. Para criar um app do Chat, siga este quickstart.
  • Ao abrir uma caixa de diálogo em resposta a um comando de barra, um comando de barra configurado com a opção Abrir uma caixa de diálogo selecionada.

Python

  • Uma conta do Google Workspace com acesso ao Google Chat.
  • Um app do Chat. Para criar um app do Chat, siga este quickstart.
  • Ao abrir uma caixa de diálogo em resposta a um comando de barra, um comando de barra configurado com a opção Abrir uma caixa de diálogo selecionada.

Os exemplos de código do Python são gravados para execução como uma função do Cloud usando Python 3.9.

Abrir uma caixa de diálogo

O app do Chat pode abrir uma caixa de diálogo em resposta a um usuário clicar em um botão em uma mensagem de card.

Clicar em um botão em um card para abrir uma caixa de diálogo.
Figura 1: clique em um botão em um card para abrir uma caixa de diálogo.

O app do Chat pode abrir uma caixa de diálogo em resposta a um usuário emitindo um comando de barra.

Clicar em um botão em um card para abrir uma caixa de diálogo.
Figura 2: envio de um comando de barra para abrir uma caixa de diálogo.

Quando um usuário abre uma caixa de diálogo, seu app do Chat recebe um evento de interação com as seguintes informações:

  • isDialogEvent é true.
  • DialogEventType especifica uma das seguintes ações realizadas pelo usuário:

    • REQUEST_DIALOG: uma caixa de diálogo foi aberta.
    • SUBMIT_DIALOG: clicou em um botão em uma caixa de diálogo.
    • CANCEL_DIALOG: uma caixa de diálogo foi cancelada.

Por exemplo, quando um usuário abre uma caixa de diálogo, seu app do Chat recebe um evento de interação semelhante a este:

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

O app do Chat pode abrir uma caixa de diálogo retornando um ActionResponse de "type": "DIALOG" com um DialogAction que inclui uma descrição JSON da caixa de diálogo:

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"
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }
    }
  }
}

Abrir uma caixa de diálogo em resposta ao clique no botão de um card

Para fazer com que um botão de card abra uma caixa de diálogo, especifique o seguinte:

Quando um usuário clica em um botão em um cartão, seu app do Chat recebe um evento de interação com as seguintes informações:

Para abrir uma caixa de diálogo, responda com o seguinte:

Neste exemplo, um app do Chat responde a um evento de interação MESSAGE com um cartão que tem um botão que abre uma caixa de diálogo:

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

/**
* 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'
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }

Abrir uma caixa de diálogo em resposta a um comando de barra

Quando um usuário abre uma caixa de diálogo com um comando de barra configurado para abrir uma caixa de diálogo, seu app do Chat recebe um evento de interação com as seguintes informações:

Para abrir uma caixa de diálogo, responda com o seguinte:

Neste exemplo, um app do Chat responde ao comando de barra /createContact abrindo uma caixa de diálogo:

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

/**
* 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'
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }

Abrir caixas de diálogo sequenciais

Quando as interações do usuário exigem mais de uma caixa de diálogo, você pode abrir outra retornando a próxima na sequência em resposta a uma SUBMIT_DIALOG DialogEventType.

Uma caixa de diálogo com uma variedade de widgets diferentes.
Figura 3: uma caixa de diálogo aberta pedindo que o usuário adicione um contato.

No botão do card que atualiza a caixa de diálogo, retorne onClick.action.function como o nome de uma função que abre a próxima caixa de diálogo e mantenha onClick.action.interaction não especificado.

Uma caixa de diálogo com uma variedade de widgets diferentes.
Figura 4: uma segunda caixa de diálogo solicita mais informações ao usuário.

Quando terminar, o app do Chat receberá os valores que os usuários inseriram na caixa de diálogo como JSON. Para informar aos usuários que a interação foi bem-sucedida, responda com uma mensagem de texto ou card.

Quando os usuários clicam em um botão em uma caixa de diálogo, seu app do Chat recebe um evento de interação com as seguintes informações:

Neste exemplo, um app do Chat responde a um evento de interação CARD_CLICKED clicando no botão de uma caixa de diálogo ao abrir outra caixa de diálogo:

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

/**
* 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'
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }

Abrir uma caixa de diálogo em resposta a uma mensagem de card na página inicial do app

Somente para mensagens do card da página inicial do app, use render_actions em vez de action_response para abrir uma caixa de diálogo:

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"
                        }
                      }
                    }
                  ]
                }
              }]
            }]
          }
        }]
      }
    }
  }
}

Receber dados de formulários de caixas de diálogo

Quando os usuários clicam em um botão em uma caixa de diálogo, os dados inseridos são enviados ao app do Chat, que recebe um evento de interação com as seguintes informações:

Os dados que os usuários inserem na caixa de diálogo estão disponíveis no evento de interação como Event.common.formInputs, um mapa em que as chaves são IDs de string atribuídos a cada widget de caixa de diálogo, e os valores representam a entrada do usuário para cada widget. Objetos diferentes representam tipos de dados de entrada diferentes. Por exemplo, Event.common.formInputs.stringInputs representa entradas de string.

Quando um usuário envia uma caixa de diálogo, seu app do Chat recebe um evento de interação como este:

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
  }
}

O app do Chat pode acessar o primeiro valor inserido pelo usuário em event.common.formInputs.NAME.stringInputs.value[0], em que NAME é o campo name de um widget TextInput.

Depois de receber os dados do formulário da caixa de diálogo, o app do Chat precisa responder com ActionResponse:

  • Para confirmar o recebimento, responda com um ActionResponse que tenha "actionStatus": "OK". Isso fecha a caixa de diálogo sem postar uma resposta.
  • Para responder com uma mensagem de texto ou de card, responda com uma ActionResponse que tenha uma ResponseType de NEW_MESSAGE, UPDATE_MESSAGE ou UPDATE_USER_MESSAGE_CARDS. Para mais informações, consulte Responder a uma caixa de diálogo.
  • Para retornar um erro, responda com um ActionResponse que tenha "actionStatus": "ERROR MESSAGE".

O exemplo a seguir verifica se há um valor name. Se ele estiver ausente, o app do Chat retornará um erro. Se estiver presente, o app do Chat vai confirmar o recebimento dos dados do formulário e fechar a caixa de diálogo.

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

/**
* 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!'
                }
              }
            }

Responder a uma caixa de diálogo

Você pode responder a uma caixa de diálogo com uma nova mensagem ou uma atualização de uma mensagem existente.

Responder a uma caixa de diálogo com uma nova mensagem

Para responder ao envio de um formulário da caixa de diálogo com uma nova mensagem, o app do Chat retorna um ActionResponse do tipo NEW_MESSAGE, com uma marcação indicando o conteúdo da nova mensagem. Ao receber essa resposta, a caixa de diálogo é fechada e a nova mensagem é postada.

O código abaixo é um exemplo de resposta JSON a uma caixa de diálogo enviada por um app do Chat para criar uma nova mensagem de resposta:

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"
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

O app do Chat também pode responder de maneira assíncrona com uma mensagem de texto ou card.

Responder a uma caixa de diálogo com uma mensagem atualizada

Ao responder a uma caixa de diálogo com uma mensagem atualizada, você pode atualizar uma mensagem do app do Chat ou atualizar uma visualização de link.

Mensagens do app do Chat

Para responder ao envio de um formulário de caixa de diálogo com uma atualização de uma mensagem enviada pelo app do Chat, ele retorna um ActionResponse do tipo UPDATE_MESSAGE. A resposta inclui uma marcação que indica o conteúdo da mensagem atualizada. Ao receber essa resposta, a caixa de diálogo é fechada e a mensagem é atualizada com o novo conteúdo.

O código abaixo é um exemplo de resposta JSON para uma caixa de diálogo enviada por um app do Chat para atualizar uma mensagem já existente no app do 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"
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

O app do Chat também pode atualizar uma mensagem do app do Chat de forma assíncrona usando a API Google Chat.

Para atualizar as visualizações de links com novo conteúdo em resposta aos envios de formulários de caixas de diálogo, o app do Chat retorna uma ActionResponse do tipo UPDATE_USER_MESSAGE_CARDS. A resposta inclui uma marcação para as novas mensagens de card com que as visualizações de link são atualizadas. Depois de receber essa resposta, a caixa de diálogo é fechada, e as visualizações dos links são atualizadas com as novas mensagens do card.

O exemplo de resposta JSON a seguir atualiza uma visualização de link com uma nova mensagem de card:

JSON

{
  "actionResponse": "UPDATE_USER_MESSAGE_CARDS",
  "cardsV2": [
    {
      "cardId" : "updated-card-id",
      "card" : {
        "header": {
          "title": "Updated card title"
        },
        "sections": [
          {
            "widgets" : [
              {
                "textParagraph": {
                  "text": "Updated card message"
                }
              }
            ]
          }
        ]
      }
    }
  ]
}

Responder a uma caixa de diálogo para mensagens do card na página inicial do app

Somente para mensagens do card da página inicial do app, há duas maneiras diferentes de fechar uma caixa de diálogo:

  • CLOSE_DIALOG: fecha a caixa de diálogo e retorna à mensagem do card inicial do app.
  • CLOSE_DIALOG_AND_EXECUTE: fecha a caixa de diálogo e atualiza a mensagem do card na página inicial do app.

Python

O exemplo de código abaixo usa CLOSE_DIALOG para fechar uma caixa de diálogo e retornar à mensagem do card inicial do app:

def close_dialog():
  """Handles dismiss dialog request from Chat."""
  return {
      'render_actions': {
          'action': {
              'navigations': [{
                'end_navigation': {'action': 'CLOSE_DIALOG'}
              }]
          }
      }
  }

Apps Script

O exemplo de código abaixo usa CLOSE_DIALOG para fechar uma caixa de diálogo e retornar à mensagem do card inicial do app:

function closeDialog(event) {
  return {
    render_actions: {
      action:{
        navigations:[{
          end_navigation:{
            action: "CLOSE_DIALOG"
          }
        }]
      }
    }
  };
}

Exemplo completo: Rolodex, o contato que gerencia o app do Chat

Neste exemplo, um app de chat abre uma caixa de diálogo para que o usuário possa adicionar detalhes sobre um contato, como nome, e-mail e endereço:

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

apps-script/dialogs/rolodex.gs
/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {Object} open a Dialog in response to a slash command
* or a card"s button click.
*/
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);
    }
  }

  // If the Chat app doesn"t detect a slash command, it responds
  // with a card that prompts the user to add a contact
  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": "openDialog",
                            "interaction": "OPEN_DIALOG"
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }]

    };
  }
}

/**
* 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);
  }

  if (event.common.invokedFunction === "openSequentialDialog") {
    const contactName = fetchFormValue(event, "contactName");
    const address = fetchFormValue(event, "address");
    return openSequentialDialog(contactName, address);
  }

  if (event.common.invokedFunction === "receiveDialog") {
    const parameters = event.common.parameters;
    parameters["contactType"] = fetchFormValue(event, "contactType");
    parameters["notes"] = fetchFormValue(event, "notes");
    return receiveDialog(parameters);
  }
}

/**
 * Extracts form input value for a given widget
 * 
 * @param {Object} event the event object from Google Chat
 * @param {String} widgetName the widget name
 * @returns the form input value for the widget
 */
function fetchFormValue(event, widgetName) {
  const widget = event.common.formInputs[widgetName];
  if (widget) {
    return widget[""]["stringInputs"]["value"][0];
  }
}

/**
* Opens and starts a dialog that lets users add details about a contact.
*
*
* @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": {
                              "function": "openSequentialDialog"
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }
      }
    }
  };
}

/**
* Opens a second dialog that lets users add more contact details.
*
* @param {String} contactName the contact name from the previous dialog.
* @param {String} address the address from the previous dialog.
*
* @return {Object} open a dialog.
*/
function openSequentialDialog(contactName, address) {
  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": "contactName",
                                  "value": contactName
                                },
                                {
                                  "key": "address",
                                  "value": address
                                }
                              ]
                            }
                          }
                        }
                      ]
                    },
                    "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} parameters the form input values.
*
* @return {Object} open a Dialog in Google Chat.
*/
function receiveDialog(parameters) {

  // Checks to make sure the user entered a name
  // in a dialog. If no name value detected, returns
  // an error message.
  if (!parameters.contactName) {
    return {
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": {
            "statusCode": "INVALID_ARGUMENT",
            "userFacingMessage": "Don't forget to name your new contact!"
          }
        }
      }
    };

    // Otherwise the Chat 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": {
            "statusCode": "OK",
            "userFacingMessage": "Success " + JSON.stringify(parameters)
          }
        }
      }
    };
  }
}

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!"
        }
      }
    }

Resolver problemas

Quando um app ou card do Google Chat retorna um erro, a interface do Chat mostra a mensagem "Ocorreu um erro" ou "Não foi possível processar sua solicitação". Às vezes, a interface do Chat não mostra nenhuma mensagem de erro, mas o app ou card do Chat produz um resultado inesperado. Por exemplo, uma mensagem de card pode não aparecer.

Embora uma mensagem de erro não apareça na interface do Chat, mensagens de erro descritivas e dados de registro estão disponíveis para ajudar a corrigir erros quando o registro de erros dos apps do Chat está ativado. Se precisar de ajuda para visualizar, depurar e corrigir erros, consulte Resolver problemas e corrigir erros do Google Chat.