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

Bu sayfada, Google Chat uygulamanız için eğik çizgi komutlarını nasıl ayarlayacağınız ve bunlara nasıl yanıt vereceğiniz açıklanmaktadır.

Eğik çizgi komutu, kullanıcıların bir Chat uygulamasını çağırmak ve uygulama ile etkileşimde bulunmak için kullandığı yaygın bir yöntemdir. Eğik çizgi komutları, kullanıcıların bir Chat uygulamasının temel özelliklerini keşfetmesine ve kullanmasına da yardımcı olur.

Eğik çizgi komutu kullanmak için kullanıcılar önce eğik çizgi (/) ve ardından kısa bir metin komutu (ör. /about) yazarak Chat uygulaması hakkında bilgi edinebilir. Kullanıcılar Google Chat'e eğik çizgi yazarak mevcut eğik çizgi komutlarını keşfedebilir. Bu bölümde, Chat uygulaması için kullanılabilen komutları listeleyen bir pencere görüntülenir:

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 mesaj gönderdiğinde, mesajı yalnızca kullanıcı ve Chat uygulaması görebilir.

Eğik çizgi komutlarını ayarlamanız gerekip gerekmediğine karar vermek ve kullanıcı etkileşimlerini nasıl tasarlayacağınızı anlamak için Tüm kullanıcı yolculuklarını tanımlama bölümüne bakın.

Ön koşullar

Node.js

Apps Komut Dosyası

Python

Eğik çizgi komutu ayarlama

Bu bölümde, eğik çizgi komutu ayarlamak için aşağıdaki adımları nasıl tamamlayacağınız açıklanmaktadır:

  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 uygulamasını çağırmak için Chat mesajına yazdıkları metindir. Adın altında, kullanıcılara komutu nasıl kullanacakları hakkında daha fazla bilgi veren kısa bir açıklama da gösterilir:

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

Eğik çizgi komutunuz için ad ve açıklama seçerken aşağıdaki önerileri göz önünde bulundurun:

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

    • Komutları kullanıcı için net ve basit hale getirmek üzere kısa, açıklayıcı, işlem yapılabilir kelimeler veya ifadeler kullanın. Örneğin, /createAReminder yerine /remindMe ifadesini kullanın.
    • Komutunuz birden fazla kelime içeriyorsa kullanıcıların ilk kelimenin tamamında küçük harf kullanıp ardından ek kelimelerin ilk harfini büyük yazarak kullanıcıların komutu okumasına yardımcı olun. Örneğin, /updatecontact yerine /updateContact kullanın.
    • Komutunuz için benzersiz bir ad mı yoksa yaygın olarak kullanılan bir ad mı kullanacağınıza karar verin. Komutunuz tipik bir etkileşimi veya özelliği açıklıyorsa kullanıcıların tanıyıp beklediği, /settingsveya /feedback gibi ortak bir ad kullanabilirsiniz. Komut adınız diğer Chat uygulamaları için de aynıysa kullanıcının komutunuzu bulup kullanmak için benzer komutları filtrelemesi gerektiğinden, benzersiz komut adları kullanmayı deneyin.
  • Eğik çizgi komutunuzu açıklamak için:

    • Komutu çağırdıklarında kullanıcıların ne beklemeleri gerektiğini bilmeleri için açıklamayı kısa ve net tutun.
    • Komut için herhangi bir biçimlendirme gereksinimi olup olmadığını kullanıcılara bildirin. Örneğin, bağımsız değişken metni gerektiren bir /remindMe komutu oluşturursanız açıklamayı Remind me to do [something] at [time] gibi bir şekilde ayarlayın.
    • Chat uygulamasının alandaki herkese mi yoksa yalnızca komutu çağıran kullanıcıya mı yanıt verdiğini kullanıcılara bildirin. Örneğin, eğik çizgi komutu /about için bunu Learn about this app (Only visible to you) olarak tanımlayabilirsiniz. Eğik çizgi komutuna gizli olarak 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 Chat uygulamanızın Google Chat API yapılandırmasında komutla ilgili bilgileri belirtmeniz gerekir.

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

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

    Google Chat API sayfasına gidin

  2. Configuration'ı (Yapılandırma) tıklayın.

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

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

    1. Ad: Komutun görünen adı ve kullanıcıların uygulamanızı çağırmak için yazdıkları ad. Eğik çizgiyle başlamalı, yalnızca metin içermeli ve en fazla 50 karakter uzunluğunda olabilir.
    2. Açıklama: Komutun nasıl kullanılacağını ve biçimlendirileceğini açıklayan metin. Açıklamalar en fazla 50 karakter uzunluğunda olabilir.
    3. Komut Kimliği: Chat uygulamanızın eğik çizgi komutunu tanımak ve yanıt döndürmek için kullandığı 1 ile 1000 arasında bir sayı.
  5. İsteğe bağlı: Chat uygulamanızın komuta bir iletişim kutusu ile yanıt vermesini istiyorsanız İletişim kutusu aç onay kutusunu işaretleyin.

  6. Kaydet'i tıklayın.

Eğik çizgi komutu 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 olarak slashCommand ve slashCommandMetadata alanları dahil olmak üzere bilgileri içerir. Komut kimliğini tanımlamak ve özel bir yanıt döndürmek için bu alanları kullanırsınız.

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

    {
      ...
      "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 etkinlik yükünde slashCommand alanının olup olmadığını tespit edebilir ve olması halinde komuta bir yanıt döndürebilirsiniz. Aşağıdaki kod örneğinde, eğik çizgi komutu içeren bir MESSAGE etkileşim etkinliğine nasıl yanıt verileceği gösterilmektedir:

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.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ğıdakileri değiştirin:

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

Eğik çizgi komutları içeren mesajlar, yalnızca mesajı gönderen kullanıcı ve komutu alan Chat uygulaması tarafından görülebilir. Chat uygulamanızı birden fazla kişinin bulunduğu alanlara eklenecek şekilde yapılandırdıysanız, kullanıcı ile Chat uygulaması arasında etkileşimi gizli tutmak için eğik çizgi komutuna gizli olarak yanıt verebilirsiniz.

Örneğin bir ekip, müşteri destek hizmetini yöneten bir Chat uygulaması kullanıyorsa kullanıcılar kendilerine atanan destek kayıtlarını görüntülemek için /myCases gibi eğik çizgi komutu çağırabilir. Ekip Chat uygulamasını bir alana eklerse alanda bu eğik çizgi komutunu kullanan bir kullanıcı, Chat uygulamasının yalnızca bunlara yanıt vermesini isteyebilir. Chat uygulaması, kullanıcının destek yazışmalarını alandaki herkese yayınlamamak için gizli olarak yanıt verebilir.

Eğik çizgi komutuna gizli olarak yanıt vermek için Google Chat kullanıcılarına özel mesaj gönderme başlıklı makaleyi inceleyin.

Tam örnek: Rolodex Chat uygulamasını kullanarak kişi oluşturma

Aşağıdaki örnekte, aşağıdaki eğik çizgi komutlarına yanıt veren bir Chat uygulaması gösterilmektedir:

  • /help komutu, Chat uygulamasından nasıl destek alınacağını açıklayan bir kısa mesaj döndürür. Komut kimliği 1 olarak ayarlanmıştır.
  • /createContact komutu, kullanıcıların bir kişiyle ilgili ayrıntıları girebileceği iletişim kutusunu açar. Komut kimliği 2 olarak ayarlandı.

Bu örneği çalıştırmadan önce Google Chat API'de eğik çizgi komutlarını yapılandırma adımlarını uygulayı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.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.openDialog(event);
    }

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

    if (event.common.invokedFunction === "confirmDialogSuccess") {
      res.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.
  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 {
    res.json({
      "actionResponse": {
        "type": "DIALOG",
        "dialogAction": {
          "actionStatus": "OK"
        }
      }
    });
  }
}

Apps Komut Dosyası

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