Abrir diálogos interactivos

En esta página, se describe cómo tu app de Chat puede abrir diálogos para responder a los usuarios.

Los diálogos son interfaces basadas en tarjetas y con ventanas que se abren desde un mensaje o espacio de Chat. El diálogo y su solo el usuario que lo abrió puede verlo.

Las apps de chat pueden usar diálogos para solicitar y recopilar información de Usuarios de Chat, incluidos los formularios de varios pasos. Más información para crear entradas de formulario, consulta Cómo recopilar y procesar información de los usuarios.

Requisitos previos

Node.js

  • Una app de Google Chat habilitada para funciones interactivas. Para crear un app de Chat interactiva con un servicio HTTP, completa esta guía de inicio rápido.

Python

  • Una app de Google Chat habilitada para funciones interactivas. Para crear un app de Chat interactiva con un servicio HTTP, completa esta guía de inicio rápido.

Apps Script

  • Una app de Google Chat habilitada para funciones interactivas. Para crear un app de Chat interactiva en Apps Script, completa esta guía de inicio rápido.

Abrir un diálogo

Un diálogo que muestra una variedad de widgets diferentes.
Figura 1: Diálogo que recopila información de contacto

En esta sección, se explica cómo responder y configurar un diálogo de la siguiente manera:

  1. Activa la solicitud de diálogo a partir de una interacción del usuario.
  2. Para controlar la solicitud, muestra y abre un diálogo.
  3. Después de que los usuarios envíen la información, procesa el envío cerrando los o mostrar otro.

Activa una solicitud de diálogo

Una app de Chat solo puede abrir diálogos para responder a un usuario como un comando de barra o un clic en un botón desde un mensaje en una tarjeta.

Para responder a los usuarios con un diálogo, una app de Chat debe compila una interacción que active la solicitud de diálogo, como la siguiente:

  • Responde a un comando de barra. Para activar la solicitud desde un comando de barra, debes marcar la casilla de verificación Abre un diálogo cuando configures el comando.
  • Responder a un clic en un botón mensaje, como parte de una tarjeta o en la parte inferior del mensaje. Para activar desde un botón en un mensaje, debes configurar onClick del botón la acción estableciendo su interaction en OPEN_DIALOG.
  • Responde a un clic en un botón en la página principal de una app de Chat. Para obtener más información sobre cómo abrir diálogos desde páginas principales, consulta Crea una página principal para tu app de Google Chat.
Botón que activa un diálogo
Figura 2: Una app de Chat envía un mensaje en el que se les solicita a los usuarios que usen el comando de barra /addContact.
El mensaje también incluye un botón en el que los usuarios pueden hacer clic para activar el comando.

El siguiente JSON muestra cómo activar una solicitud de diálogo desde un botón en una mensaje de tarjeta. Para abrir el diálogo, button.interaction se establece en OPEN_DIALOG:

{
  "buttonList": { "buttons": [{
    "text": "BUTTON_TEXT",
    "onClick": { "action": {
      "function": "FUNCTION_NAME",
      "interaction": "OPEN_DIALOG"
    }}
  }]}
}

Donde BUTTON_TEXT es el texto que se muestra en el botón y FUNCTION_NAME es la función que se ejecuta para abrir la configuración .

Abrir el diálogo inicial

Cuando un usuario activa una solicitud de diálogo, tu app de Chat recibe un evento de interacción, representado como un event escribe API de Chat. Si la interacción activa una solicitud de diálogo, el nombre El campo dialogEventType está configurado como REQUEST_DIALOG.

Para abrir un diálogo, tu app de Chat puede responder al de respuesta mostrando un actionResponse objeto con el type establecido en DIALOG y Message . Para especificar el contenido del diálogo, incluye lo siguiente objetos:

  • Un objeto actionResponse objeto, con su type establecido en DIALOG.
  • Un objeto dialogAction. El campo body contiene los elementos de la interfaz de usuario (IU) para mostrar en la tarjeta, incluidos uno o más sections de widgets. Para recopilar información de los usuarios, puedes especificar widgets de entrada de formulario y una de botones. Para obtener más información sobre el diseño de entradas de formulario, consulta Recopila y procesa información de los usuarios.

En el siguiente JSON, se muestra cómo se devuelve una app de Chat una respuesta que abre un diálogo:

{ "actionResponse": {
  "type": "DIALOG",
  "dialogAction": { "dialog": { "body": { "sections": [{
    "widgets": [{
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "BUTTON_TEXT",
        "onClick": {
          "action": {"function": "FUNCTION_NAME"}
        }
      }]}}
    }]
  }]}}}
}}

Donde BUTTON_TEXT es el texto que se muestra en el botón (como Next o Submit), WIDGETS representa uno o más. widgets de entradas de formularios FUNCTION_NAME es la función que se ejecuta cuando los usuarios hacen clic en un botón.

Cómo controlar el envío del diálogo

Cuando los usuarios hacen clic en un botón que envía un diálogo, tus La app de Chat recibe una interacción de CARD_CLICKED evento en el que el dialogEventType es SUBMIT_DIALOG.

Tu app de Chat debe controlar el evento de interacción antes del realizando una de las siguientes acciones:

Opcional: Devuelve otro diálogo

Después de que los usuarios envían el diálogo inicial, las apps de Chat pueden devolver uno o más diálogos adicionales para ayudar a los usuarios a revisar la información antes enviar formularios de varios pasos o completar formularios de varios pasos de forma dinámica.

Para cargar los datos que ingresan los usuarios desde el diálogo inicial, debes agregar parámetros al botón que abre el siguiente diálogo, o pasa el original CARD_CLICKED evento de interacción del diálogo inicial. Para obtener más información, consulta Transfiere datos a otra tarjeta.

En este ejemplo, una app de Chat abre un diálogo que Devuelve un segundo diálogo antes de enviar. Para cargar los datos de entrada, La app de Chat pasa el evento de interacción CARD_CLICKED como parámetro para la función que abre el siguiente 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 === "openNextDialog") {
    openNextDialog(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({ "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "openNextDialog"
        }}
      }]}}
    ]}]}}}
  }});
};

/**
* 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 openNextDialog(event) {
  res.json({ "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submitDialog"
          }}
        }]}
      }
    ]}]}}}
  }});
}

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_next_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 { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "open_next_dialog"
        }}
      }]}}
    ]}]}}}
  }}

def open_next_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 { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submit_dialog"
          }}
        }]}
      }
    ]}]}}}
  }}

Apps Script

En este ejemplo, se envía un mensaje de tarjeta mostrando JSON de la tarjeta. También puedes usar Servicio de tarjetas de 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 === "openNextDialog") {
    return openNextDialog(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 { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      { "buttonList": { "buttons": [{
        "text": "Next",
        "onClick": { "action": {
          "function": "openNextDialog"
        }}
      }]}}
    ]}]}}}
  }};
}

/**
* 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 openNextDialog(event) {
  return { "actionResponse": {
    "type": "DIALOG",
    "dialogAction": { "dialog": { "body": { "sections": [{ "widgets": [
      WIDGETS,
      {
        "horizontalAlignment": "END",
        "buttonList": { "buttons": [{
          "text": "Submit",
          "onClick": { "action": {
            "function": "submitDialog"
          }}
        }]}
      }
    ]}]}}}
  }};
}

Donde WIDGETS representa uno o más. widgets de entrada de formulario.

Cerrar el diálogo

Cuando los usuarios hacen clic en un botón de un diálogo, Chat recibe un evento de interacción con el la siguiente información:

Las siguientes secciones explican cómo validar los datos que ingresan los usuarios y cerrar el diálogo.

Valida los datos de entrada del usuario y cierra el diálogo

Para procesar los datos que ingresan los usuarios, la app de Chat usa el event.common.formInputs . Si quieres obtener más información para recuperar valores de widgets de entrada, consulta Recopila y procesa información de los usuarios.

Si el usuario omite un campo obligatorio o ingresa valores incorrectos, La app de Chat puede responder con un error devolviendo ActionResponse que tiene "actionStatus": "ERROR MESSAGE".

En el siguiente ejemplo, se verifica que un usuario ingrese un valor para un widget que acepta cadenas (stringInputs), como un widget textInput. Si no se incluye, el La app de Chat muestra un error. Si está presente, la app de Chat reconoce el envío del diálogo cierra el 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 submitDialog(event) {

  // Checks to make sure the user entered a value
  // in a dialog. If no 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": "ERROR_MESSAGE"
        }
      }
    });

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

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': 'ERROR_MESSAGE'
                }
              }
            }

Apps Script

En este ejemplo, se envía un mensaje de tarjeta mostrando JSON de la tarjeta. También puedes usar Servicio de tarjetas de 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 submitDialog(event) {

  // Checks to make sure the user entered a value
  // in a dialog. If no 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": "ERROR_MESSAGE"
        }
      }
    };

    // 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"
        }
      }
    };
  }
}

En este ejemplo, WIDGET_NAME representa el campo name de la (como contactName), y ERROR_MESSAGE representa la el contenido del mensaje de error (como Don't forget to name your contact). Para obtener más información sobre cómo procesar datos de entrada de widgets, consulta Recibe datos de widgets interactivos.

Opcional: Envía un mensaje de confirmación

Cuando cierres el diálogo, también podrás enviar un nuevo mensaje o actualizar un una existente.

Para enviar un mensaje nuevo, devuelve un ActionResponse objeto con type configurado como NEW_MESSAGE. Por ejemplo, para cerrar el diálogo y envías un mensaje de texto, devuelve lo siguiente:

  {
    "actionResponse": {
      "type": "NEW_MESSAGE",
    },
    "text": "Your information has been submitted."
  }

Para actualizar un mensaje, muestra un objeto actionResponse que contenga el actualizado y establece la type en una de las siguientes opciones:

Solucionar problemas

Cuando una app de Google Chat o card muestra un error, el En la interfaz de Chat, aparece un mensaje que dice “Se produjo un error”. o "No se pudo procesar la solicitud". A veces, la IU de Chat no muestra ningún mensaje de error, pero la app de Chat la tarjeta produce un resultado inesperado; Por ejemplo, es posible que un mensaje de tarjeta no para que aparezca la opción.

Aunque es posible que no aparezca un mensaje de error en la IU de Chat, Hay mensajes de error descriptivos y datos de registro disponibles para ayudarte a corregir errores. Cuando se activa el registro de errores de las apps de Chat. Para obtener ayuda sobre la visualización, la depuración y la corrección de errores, consulta Soluciona problemas y corrige errores de Google Chat.