Eğik çizgi komutlarına Google Chat uygulaması olarak yanıt verme

Bu sayfada, Google Chat uygulaması.

Eğik çizgi komutu, kullanıcıların bir öğeyi çağırmak ve Chat uygulaması. Eğik çizgi komutları ayrıca kullanıcıların Chat uygulamasının temel özelliklerini kullanmak

Eğik çizgi komutu kullanmak için kullanıcılar eğik çizgi (/) ve ardından kısa bir metin komutu yazarlar. (ör. /about) aracılığıyla Chat uygulaması hakkında bilgi edinebilirsiniz. Kullanıcılar, kullanılabilir eğik çizgi komutlarını bulmak için Google Chat'te, komut dosyası için mevcut komutları listeleyen Chat uygulaması:

Eğik çizgi komutu penceresi
Şekil 1: Kullanıcılar Google Chat'e eğik çizgi yazdığında görünen pencere

Bir kullanıcı eğik çizgi komutu içeren bir ileti gönderdiğinde, ileti yalnızca Kullanıcı ve Chat uygulamasında görülebilir.

Eğik çizgi komutları ayarlamanız gerekip gerekmediğine karar vermek ve kullanıcı etkileşimleri tasarlamak için Tüm kullanıcı yolculuklarını tanımlayın.

Ön koşullar

Node.js

Etkileşimli özellikler için etkinleştirilmiş bir Google Chat uygulaması. Bir HTTP hizmeti kullanarak etkileşimli Chat uygulaması için bu hızlı başlangıç kılavuzunu tamamlayın.

Apps Komut Dosyası

Etkileşimli özellikler için etkinleştirilmiş bir Google Chat uygulaması. Bir Apps Komut Dosyası'ndaki etkileşimli Chat uygulaması için bu hızlı başlangıç kılavuzunu tamamlayın.

Python

Etkileşimli özellikler için etkinleştirilmiş bir Google Chat uygulaması. Bir HTTP hizmeti kullanarak etkileşimli Chat uygulaması için bu hızlı başlangıç kılavuzunu tamamlayın.

Eğik çizgi komutu oluşturma

Bu bölümde, eğik çizgi oluşturmak için aşağıdaki adımların nasıl tamamlanacağı açıklanmaktadır komut:

  1. Eğik çizgi komutunuz için bir ad oluşturun.
  2. Google Chat API'de eğik çizgi komutunu yapılandırın.

Eğik çizgi komutunuzu adlandırın

Eğik çizgi komutunun adı, kullanıcıların Chat mesajına yazdığı addır Chat uygulamasını çağırın. Kısa bir açıklama da komutun nasıl kullanılacağı konusunda daha ayrıntılı bilgi istemek için adın altında görünür:

Slash komutu adı ve açıklaması
Şekil 2: Eğik çizgi komutunun adı ve açıklaması.

Eğik çizgi komutunuz için bir ad ve açıklama seçerken, şu önerileri uygulayın:

  • Eğik çizgi komutunuzu adlandırmak için:

    • Kısa, açıklayıcı ve eyleme dökülebilir kelime veya ifadeler kullanın. kullanıcı için açık ve basit komutlar verebilir. Örneğin, /createAReminder, /remindMe hesabını kullanın.
    • Komutunuz birden fazla kelime içeriyorsa kullanıcıların komutu okumasına yardımcı olun ilk kelime için tamamı küçük harfle yazılmalıdır ve ilk kelimenin ilk harfi büyük yazılmalıdır kelimeden oluşan bir harf kullanın. Örneğin, /updatecontact yerine, /updateContact kullanın.
    • Komutunuz için benzersiz bir ad mı yoksa yaygın bir ad mı kullanacağınızı düşünün. Eğer komutunuz tipik bir etkileşimi veya özelliği açıklıyorsa kullanıcıların tanıdığı ve beklediği ortak ad, ör. /settings veya /feedback. Aksi takdirde, benzersiz komut adları kullanmaya çalışın, çünkü komut adının diğer Chat uygulamaları için aynı olduğundan, kullanıcının benzer komutlar aracılığıyla filtre uygulayabilir ve kendi komutunuzu kullanabilirsiniz.
  • Eğik çizgi komutunuzu tanımlamak için:

    • Kullanıcıların ne beklemeleri gerektiğini bilmeleri için açıklamayı kısa ve net tutun tarafından uygulanır.
    • Komut için herhangi bir biçimlendirme gereksinimi olup olmadığını kullanıcılara bildirin. Örneğin, bağımsız değişken gerektiren bir /remindMe komutu oluşturursanız metni Remind me to do [something] at [time] gibi bir değere ayarlayın.
    • Chat uygulaması yanıt verirse kullanıcılara haber verin veya komutu çağıran kullanıcıya özel olarak oluşturabilirsiniz. Örneğin, eğik çizgi komutu /about için bu komutu şu şekilde açıklayabilirsiniz: Learn about this app (Only visible to you). Bir eğik çizgi komutuyla yanıt vermek için Özel mesajla yanıt verme bölümüne bakın.

Google Chat API'de eğik çizgi komutunuzu yapılandırın

Eğik çizgi komutu oluşturmak için komutla ilgili bilgileri Chat uygulamanızın Google Chat API yapılandırmasına gidin.

Google Chat API'de eğik çizgi komutu yapılandırmak için aşağıdaki adımları uygulayın: için şu adımları izleyin:

  1. Google Cloud konsolunda Menü'yü tıklayın. > API'lar ve Hizmetler > Etkin API'ler ve Hizmetler > Google Chat API

    Google Chat API sayfasına gidin

  2. Yapılandırma'yı tıklayın.

  3. Eğik çizgi komutları altında, Eğik çizgi komutu ekle'yi tıklayın.

  4. Komut için bir ad, komut kimliği ve açıklama girin:

    1. Ad: komutun görünen adı ve kullanıcıların girdiği ad Eğik çizgiyle başlamalıdır, yalnızca metin içerebilir ve en fazla 50 karakter olmalıdır.
    2. Açıklama: nasıl kullanılacağını ve biçimlendirileceğini açıklayan metin komutudur. Açıklamalar en fazla 50 karakter uzunluğunda olabilir.
    3. Komut Kimliği: Anahtar kelimelerinizin, Chat uygulaması eğik çizgi komutunu tanımak için kullanır ve bir yanıt döndürüyor.
  5. İsteğe bağlı: Chat uygulamanızın yanıt vermesini istiyorsanız iletişim kutusunu kullanarak komut verdiğinizde, İletişim kutusu aç onay kutusu.

  6. Kaydet'i tıklayın.

Eğik çizgi komutu artık Chat uygulaması için yapılandırılmıştır.

Eğik çizgi komutuna yanıt verme

Kullanıcılar eğik çizgi komutu içeren bir Chat mesajı oluşturduğunda Chat uygulamanız bir MESSAGE etkileşim etkinliği alır. Etkinlik yükü eğik çizgi komutuyla ilgili bilgileri içerir. slashCommand dahil ve slashCommandMetadata alanları. Komut kimliğini tanımlamak ve özel bir tıklayın.

Aşağıdaki örnekte bir MESSAGE etkileşim etkinliği için JSON yükü gösterilmektedir /vote eğik çizgi komutunu içerir:

    {
      ...
      "message": {
        ...
        "text": "/vote yes",
        "argumentText": " yes",
        "slashCommand": {
          "commandId": 2
        },
        "annotations": [
          {
            "length": 5,
            "startIndex": 0,
            "type": "SLASH_COMMAND",
            "slashCommand": {
              "commandName":"/vote",
              "commandId":1,
              "type": "INVOKE",
              "bot": {
                "avatarUrl": "https://www.example.com/images/vote-app-icon.png",
                "displayName": "Voter Chat App",
                "name": "users/1234567890987654321",
                "type": "BOT"
              }
            }
          }
        ]
      }
    }

Eğik çizgi komutuna yanıt vermek için slashCommand alanının bulunur. Öyleyse komuta yanıt döndürür. Aşağıdaki kod örneğinde, bir MESSAGE etkileşim etkinliğine nasıl yanıt verileceği gösterilmektedir şu kodu içerir:

Node.js

/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/

exports.onMessage = function onMessage(req, res) {

  // Stores the Google Chat event as a variable.
  var event = req.body;

  // Checks for the presence of event.message.slashCommand.
  if (event.message.slashCommand) {
    switch (event.message.slashCommand.commandId) {
      case ID: // The ID for your slash command
        res.json(runFunction); // The response to the slash command.
    }
  }

Apps Komut Dosyası

/**
* Responds to a MESSAGE event in Google Chat.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} function in response to a slash command.
*/

function onMessage(event) {

  // Checks for the presence of event.message.slashCommand
  if (event.message.slashCommand) {
    switch (event.message.slashCommand.commandId) {
      case ID: // The ID for your slash command
        return runFunction; // The response to the slash command.
    }
  }
}

Python

from typing import Any, Mapping

import flask
import functions_framework

@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
  """Responds to a MESSAGE event in Google Chat that includes a slash command.

  Args:
      req (flask.Request): the event object from Chat API.

  Returns:
      Mapping[str, Any]: function in response to a slash command.
  """
  if req.method == 'GET':
    return 'Sorry, this function must be called from a Google Chat.'

  request = req.get_json(silent=True)

  if slash_command := request.get('message', dict()).get('slashCommand'):
    command_id = slash_command['commandId']
    if command_id == ID:
      return runFunction

Kodu kullanmak için aşağıdaki kodu değiştirin:

İsteğe bağlı: Özel mesajla yanıt verin

Eğik çizgi komutu içeren iletiler yalnızca komutuna ve komutu alan Chat uygulamasına gönderilir. Eğer Chat uygulamanızı alanlara eklenecek şekilde yapılandırdıysanız varsa, eğik çizgi komutuna yanıt vermeyi düşünebilirsiniz. olmak üzere, kullanıcı ile kullanıcı arasındaki etkileşimi gizli tutmak Chat uygulaması.

Örneğin bir ekip, yönetim sistemini yönetmek için kullanıcılar, Kendilerine atanan destek kayıtlarını görüntülemek için /myCases. Ekip, Chat uygulamasından bir alana (bu eğik çizgi komutunu kullanan bir kullanıcı) Chat uygulamasının yalnızca oluşturabilirsiniz. Kullanıcının destek kayıtlarının alandaki herkese yayınlanmasını önlemek için Chat uygulaması gizli olarak yanıt verebilir.

Eğik çizgi komutuna özel olarak yanıt vermek için bkz. Google Chat kullanıcılarına özel mesaj gönderin.

Eksiksiz örnek: Rolodex Chat uygulamasını kullanarak kişileri ayarlama

Aşağıdaki örnekte, şu eğik çizgi komutları:

  • /help komutu, destek alabilirsiniz. Komut kimliği, Hedef: 1.
  • /createContact komutu, kullanıcıların giriş yapabileceği iletişim kutusunu açar kişi hakkındaki ayrıntılara değineceğim. Komut kimliği 2 olarak ayarlandı.

Bu örneği çalıştırmadan önce aşağıdaki adımları uygulayarak Google Chat API'de eğik çizgi komutlarını yapılandırın.

Node.js

/**
* Responds to messages that have links whose URLs
* match URL patterns configured for link previews.
*
* @param {Object} event The event object from Chat
* API.
*
* @return {Object} Response from the Chat app
* attached to the message with the previewed link.
*/
exports.onMessage = function onMessage(req, res) {

  // Store the Google Chat event as a variable.
  const event = req.body;

  if (req.method === "GET" || !event.message) {
    res.send("Hello! This function is meant to be used in a Google Chat " +
      "Space.");
  }

  // Checks for the presence of event.message.slashCommand.
  // If the slash command is "/help", responds with a text message.
  // If the slash command is "/createContact", opens a dialog.
  if (event.message.slashCommand) {
    switch (event.message.slashCommand.commandId) {
      case 1: // /help
        res.json({"text": "Contact bot helps you update your address book!"});
      case 2:  // /createContact
        res.json(openDialog(event));
    }
  }

  // If the Chat app doesn"t detect a slash command, it responds
  // with a card that prompts the user to add a contact
  else {
    res.json({
      "cardsV2": [{
        "cardId": "addContact",
        "card": {
          "header": {
            "title": "Rolodex",
            "subtitle": "Manage your contacts!",
            "imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
            "imageType": "CIRCLE"
          },
          "sections": [
            {
              "widgets": [
                {
                  "buttonList": {
                    "buttons": [
                      {
                        "text": "Add Contact",
                        "onClick": {
                          "action": {
                            "function": "openDialog",
                            "interaction": "OPEN_DIALOG"
                          }
                        }
                      }
                    ]
                  }
                }
              ]
            }
          ]
        }
      }]
    });
  }

  // Respond to button clicks on attached cards
  if (event.type === "CARD_CLICKED") {
    if (event.common.invokedFunction === "openDialog") {
      res.json(openDialog(event));
    }

    if (event.common.invokedFunction === "openSequentialDialog") {
      res.json(openSequentialDialog(event));
    }

    if (event.common.invokedFunction === "confirmDialogSuccess") {
      res.json(confirmDialogSuccess(event));
    }
  }
};

/**
* Opens and starts a dialog that lets users add details about a contact.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openDialog(event) {
  return {
    "action_response": {
      "type": "DIALOG",
      "dialog_action": {
        "dialog": {
          "body": {
            "sections": [
              {
                "header": "Add new contact",
                "widgets": [
                  {
                    "textInput": {
                      "label": "Name",
                      "type": "SINGLE_LINE",
                      "name": "name"
                    }
                  },
                  {
                    "textInput": {
                      "label": "Address",
                      "type": "MULTIPLE_LINE",
                      "name": "address"
                    }
                  },
                  {
                    "decoratedText": {
                      "text": "Add to favorites",
                      "switchControl": {
                        "controlType": "SWITCH",
                        "name": "saveFavorite"
                      }
                    }
                  },
                  {
                    "decoratedText": {
                      "text": "Merge with existing contacts",
                      "switchControl": {
                        "controlType": "SWITCH",
                        "name": "mergeContact",
                        "selected": true
                      }
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Next",
                          "onClick": {
                            "action": {
                              "function": "openSequentialDialog"
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }
      }
    }
  };
};

/**
* Opens a second dialog that lets users add more contact details.
*
* @param {object} event the event object from Google Chat.
*
* @return {object} open a dialog.
*/
function openSequentialDialog(event) {
  return {
    "action_response": {
      "type": "DIALOG",
      "dialog_action": {
        "dialog": {
          "body": {
            "sections": [
              {
                "header": "Add new contact",
                "widgets": [
                  {
                    "textInput": {
                      "label": "Notes",
                      "type": "MULTIPLE_LINE",
                      "name": "notes"
                    }
                  },
                  {
                    "selectionInput": {
                      "type": "RADIO_BUTTON",
                      "label": "Contact type",
                      "name": "contactType",
                      "items": [
                        {
                          "text": "Work",
                          "value": "Work",
                          "selected": false
                        },
                        {
                          "text": "Personal",
                          "value": "Personal",
                          "selected": false
                        }
                      ]
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Submit",
                          "onClick": {
                            "action": {
                              "function": "confirmDialogSuccess",
                              "parameters": [
                                {
                                  "key": "confirmDialogSuccess",
                                  "value": "confirmDialogSuccess"
                                }
                              ]
                            }
                          }
                        }
                      ]
                    },
                    "horizontalAlignment": "END"
                  }
                ]
              }
            ]
          }
        }
      }
    }
  };
}

/**
* Checks for a form input error, the absence of
* a "name" value, and returns an error if absent.
* Otherwise, confirms successful receipt of a dialog.
*
* Confirms successful receipt of a dialog.
*
* @param {Object} event the event object from Chat API.
*
* @return {object} open a Dialog in Google Chat.
*/
function receiveDialog(event) {

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

    // Otherwise the app indicates that it received
    // form data from the dialog. Any value other than "OK"
    // gets returned as an error. "OK" is interpreted as
    // code 200, and the dialog closes.
  } else {
    return {
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "OK"
        }
      }
    };
  }
}

Apps Komut Dosyası

Bu örnekte, kart JSON'a ekleyin. Ayrıca şunu da kullanabilirsiniz: Apps Komut Dosyası kart hizmeti.

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