Nesta página, explicamos como configurar e responder a comandos de barra no seu app do Google Chat.
Um comando de barra é uma maneira comum de os usuários invocarem e interagirem com um app do Chat. Os comandos de barra também ajudam os usuários a descobrir e usar os principais recursos de um app do Chat.
Para usar um comando de barra, os usuários digitam uma barra (/
) e um comando de texto curto,
como /about
, para receber informações sobre o app do Chat.
É possível descobrir os comandos de barra disponíveis digitando uma barra no
Google Chat, que mostra uma janela listando os comandos disponíveis para o
app do Chat:
Quando um usuário envia uma mensagem com um comando de barra, ela fica visível apenas para o usuário e para o app do Chat.
Para decidir se você precisa configurar comandos de barra e entender como projetar interações do usuário, consulte Definir todas as jornadas do usuário.
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.
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.
Python
- Uma conta do Google Workspace com acesso ao Google Chat.
- Um app do Chat. Para criar um app do Chat, siga este quickstart.
Configurar um comando de barra
Esta seção explica como concluir as seguintes etapas para configurar um comando de barra:
- Crie um nome para o comando de barra.
- Configure o comando de barra na API Google Chat.
Dê um nome ao comando de barra
O nome de um comando de barra é o que os usuários digitam em uma mensagem do Chat para invocar o app do Chat. Uma breve descrição também é exibida abaixo do nome, para solicitar mais informações sobre como usar o comando:
Ao escolher um nome e uma descrição para o comando de barra, considere as seguintes recomendações:
Para nomear seu comando de barra:
- Use palavras ou frases curtas, descritivas e acionáveis para deixar os comandos claros e simples para o usuário. Por exemplo, em vez de dizer
/createAReminder
, use/remindMe
. - Se o comando tiver mais de uma palavra, ajude os usuários a ler o comando usando todas as letras minúsculas para a primeira palavra e colocando em maiúscula a primeira letra das outras palavras. Por exemplo, em vez de
/updatecontact
, use/updateContact
. - Considere usar um nome exclusivo ou comum para o comando. Se
o comando descreve uma interação ou um recurso típico, você pode usar um
nome comum que os usuários reconhecem e esperam, como
/settings
ou/feedback
. Caso contrário, tente usar nomes de comando exclusivos. Se o nome do comando for o mesmo de outros apps do Chat, o usuário precisará filtrar comandos semelhantes para encontrar e usar o seu.
- Use palavras ou frases curtas, descritivas e acionáveis para deixar os comandos claros e simples para o usuário. Por exemplo, em vez de dizer
Para descrever seu comando de barra:
- Mantenha a descrição curta e clara para que os usuários saibam o que esperar ao invocar o comando.
- Informe aos usuários se há algum requisito de formatação para o comando.
Por exemplo, se você criar um comando
/remindMe
que exija texto de argumento, defina a descrição comoRemind me to do [something] at [time]
. - Informe aos usuários se o app do Chat responde a
todos no espaço ou de maneira particular ao usuário que invoca o comando.
Por exemplo, para o comando de barra
/about
, você pode descrever comoLearn about this app (Only visible to you)
. Para responder de maneira particular a um comando de barra, consulte a seção Responder com uma mensagem particular.
Configurar o comando de barra na API Google Chat
Para criar um comando de barra, especifique as informações sobre ele na configuração do app do Chat para a API Google Chat.
Para configurar um comando de barra na API Google Chat, siga estas etapas:
No console do Google Cloud, clique em Menu > APIs e serviços > APIs e serviços ativados > API Google Chat
Clique em Configuração.
Em Comandos de barra, clique em Adicionar um comando de barra.
Digite um nome, um ID e uma descrição para o comando:
- Nome:o nome de exibição do comando e o que os usuários digitam para invocar seu app. Precisa começar com uma barra, conter apenas texto e pode ter até 50 caracteres.
- Descrição:o texto que descreve como usar e formatar o comando. As descrições podem ter até 50 caracteres.
- ID do comando:um número de 1 a 1.000 que o app do Chat usa para reconhecer o comando de barra e retornar uma resposta.
Opcional: se você quiser que o app do Chat responda ao comando com uma caixa de diálogo, marque a caixa de seleção Abrir uma caixa de diálogo.
Clique em Salvar.
Agora o comando de barra está configurado para o app do Chat.
Responder a um comando de barra
Quando os usuários criam uma mensagem do Chat com um comando de barra,
seu app do Chat recebe um evento de interação MESSAGE
.
O payload do evento contém informações sobre o comando de barra,
incluindo os campos
slashCommand
e slashCommandMetadata
. Use esses campos para identificar o ID do comando e retornar uma resposta
personalizada.
O exemplo a seguir mostra o payload JSON para um evento de interação MESSAGE
que inclui o comando de barra /vote
:
{
...
"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"
}
}
}
]
}
}
Para responder a um comando de barra, detecte se o campo slashCommand
está presente no payload do evento e, em caso afirmativo, retorne uma resposta ao comando.
O exemplo de código a seguir mostra como responder a um evento de interação MESSAGE
que contém um comando de barra:
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 Script
/**
* 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
Para usar o código, substitua o seguinte:
ID
: o ID de comando que você especifica ao configurar o comando de barra na API Google Chat.runFunction
: uma função que cria uma resposta ao comando de barra.
Opcional: responda com uma mensagem privada
As mensagens que contêm comandos de barra só ficam visíveis para o usuário que enviou a mensagem e para o app do Chat que recebe o comando. Se você configurou o app do Chat para ser adicionado a espaços com várias pessoas, considere responder ao comando de barra de forma particular para manter a interação entre o usuário e o app do Chat.
Por exemplo, se uma equipe estiver usando um app de chat que gerencia
um serviço de suporte ao cliente, os usuários poderão invocar um comando de barra, como
/myCases
, para visualizar os casos de suporte atribuídos a eles. Se a equipe adicionar o
app do Chat a um espaço, o usuário que usar esse comando
de barra no espaço poderá querer que o app do Chat responda apenas a
ele. Para evitar a publicação dos casos de suporte de um usuário para todos no espaço, o
app Chat pode responder de forma privada.
Para responder a um comando de barra privada, consulte Enviar mensagens privadas para usuários do Google Chat.
Exemplo completo: configurar contatos usando o app Rolodex Chat
O exemplo a seguir mostra um app do Chat que responde aos seguintes comandos de barra:
- O comando
/help
retorna uma mensagem de texto que explica como receber suporte para o app do Chat. O ID do comando está definido como1
. - O comando
/createContact
abre uma caixa de diálogo em que os usuários podem inserir detalhes sobre um contato. O ID do comando está definido como2
.
Antes de executar esta amostra, siga as etapas para configurar os comandos de barra na API Google Chat.
Node.js
/**
* Responds to messages that have links whose URLs
* match URL patterns configured for link previews.
*
* @param {Object} event The event object from Chat
* API.
*
* @return {Object} Response from the Chat app
* attached to the message with the previewed link.
*/
exports.onMessage = function onMessage(req, res) {
// Store the Google Chat event as a variable.
const event = req.body;
if (req.method === "GET" || !event.message) {
res.send("Hello! This function is meant to be used in a Google Chat " +
"Space.");
}
// Checks for the presence of event.message.slashCommand.
// If the slash command is "/help", responds with a text message.
// If the slash command is "/createContact", opens a dialog.
if (event.message.slashCommand) {
switch (event.message.slashCommand.commandId) {
case 1: // /help
res.json({"text": "Contact bot helps you update your address book!"});
case 2: // /createContact
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 Script
Neste exemplo, uma mensagem de cartão é enviada retornando JSON do cartão. Você também pode usar o serviço de card do Apps Script.
Python
from typing import Any, Mapping
import flask
import functions_framework
@functions_framework.http
def main(req: flask.Request) -> Mapping[str, Any]:
"""Responds to a MESSAGE event in Google Chat that includes the /createContact
slash command by opening a dialog.
Args:
req (flask.Request): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
if req.method == 'GET':
return 'Sorry, this function must be called from a Google Chat.'
request = req.get_json(silent=True)
if request.get('type') == 'CARD_CLICKED':
invoked_function = request.get('common', dict()).get('invokedFunction')
if invoked_function == 'open_dialog':
return open_dialog(request)
elif invoked_function == 'open_sequential_dialog':
return open_dialog(request)
elif invoked_function == "receive_dialog":
return receive_dialog(request)
else:
return {
'cardsV2': [{
'cardId': 'addContact',
'card': {
'header': {
'title': 'Rolodex',
'subtitle': 'Manage your contacts!',
'imageUrl': 'https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png',
'imageType': 'CIRCLE'
},
'sections': [
{
'widgets': [
{
'buttonList': {
'buttons': [
{
'text': 'Add Contact',
'onClick': {
'action': {
'function': 'open_dialog',
'interaction': 'OPEN_DIALOG'
}
}
}
]
}
}
]
}
]
}
}]
}
def open_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a dialog in Google Chat.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Name',
'type': 'SINGLE_LINE',
'name': 'name'
}
},
{
'textInput': {
'label': 'Address',
'type': 'MULTIPLE_LINE',
'name': 'address'
}
},
{
'decoratedText': {
'text': 'Add to favorites',
'switchControl': {
'controlType': 'SWITCH',
'name': 'saveFavorite'
}
}
},
{
'decoratedText': {
'text': 'Merge with existing contacts',
'switchControl': {
'controlType': 'SWITCH',
'name': 'mergeContact',
'selected': True
}
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Next',
'onClick': {
'action': {
'function': 'open_sequential_dialog'
}
}
}
]
}
}
]
}
]
}
}
}
}
}
def open_sequential_dialog(request: Mapping[str, Any]) -> Mapping[str, Any]:
"""Opens a second dialog that lets users add more contact details.
Args:
request (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: open a Dialog in response to a card's button click.
"""
return {
'action_response': {
'type': 'DIALOG',
'dialog_action': {
'dialog': {
'body': {
'sections': [
{
'header': 'Add new contact',
'widgets': [
{
'textInput': {
'label': 'Notes',
'type': 'MULTIPLE_LINE',
'name': 'notes'
}
},
{
'selectionInput': {
'type': 'RADIO_BUTTON',
'label': 'Contact type',
'name': 'contactType',
'items': [
{
'text': 'Work',
'value': 'Work',
'selected': False
},
{
'text': 'Personal',
'value': 'Personal',
'selected': False
}
]
}
},
{
'buttonList': {
'buttons': [
{
'text': 'Submit',
'onClick': {
'action': {
'function': 'receive_dialog',
'parameters': [
{
'key': 'receiveDialog',
'value': 'receiveDialog'
}
]
}
}
}
]
},
'horizontalAlignment': 'END'
}
]
}
]
}
}
}
}
}
def receive_dialog(event: Mapping[str, Any]) -> Mapping[str, Any]:
"""Checks for a form input error, the absence of a "name" value, and returns
an error if absent. Otherwise, confirms successful receipt of a dialog.
Args:
event (Mapping[str, Any]): the event object from Chat API.
Returns:
Mapping[str, Any]: the response.
"""
if event.get('common', dict()) \
.get('formInputs', dict()).get('contactName', dict()) \
.get('stringInputs').get('value', list()):
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': 'OK'
}
}
}
else:
return {
'actionResponse': {
'type': 'DIALOG',
'dialogAction': {
'actionStatus': "Don't forget to name your new contact!"
}
}
}