Compartilhar via


Iniciar ações com extensões de mensagem

Importante

Os artigos nesta secção baseiam-se no SDK v3 do Bot Framework. Se estiver à procura da documentação atual (versão 4.6 ou versão posterior do SDK), veja a secção Interações orientadas para tarefas com Extensões de Mensagens .

As extensões de mensagens baseadas em ações permitem que os seus utilizadores acionem ações em serviços externos enquanto estão no Teams.

A captura de ecrã é um exemplo que mostra o cartão de extensão da mensagem.

Adicionar uma extensão de mensagem à sua aplicação

Uma extensão de mensagem é um serviço alojado na cloud que escuta os pedidos dos utilizadores e responde com dados estruturados, como um cartão. Integra o seu serviço no Microsoft Teams através de objetos do Bot Framework Activity . As nossas extensões .NET e Node.js para o SDK do Bot Builder podem ajudá-lo a adicionar a funcionalidade de extensão de mensagens à sua aplicação.

Captura de ecrã que mostra a extensão de mensagem baseada em ação no Teams.

Registar no Bot Framework

Primeiro, tem de registar um bot no Microsoft Bot Framework. O ID da aplicação Microsoft e os pontos finais de chamada de retorno para o bot, conforme definido aqui, são utilizados na extensão da sua mensagem para receber e responder a pedidos de utilizador. Lembre-se de ativar o canal do Microsoft Teams para o seu bot.

Tome nota do ID da aplicação do bot e da palavra-passe da aplicação. Tem de fornecer o ID da aplicação no manifesto da aplicação.

Atualizar seu manifesto do aplicativo

Tal como acontece com bots e separadores, atualiza o manifesto da sua aplicação para incluir as propriedades da extensão da mensagem. Estas propriedades regem a forma como a extensão de mensagem é apresentada e comporta-se no cliente do Microsoft Teams. As extensões de mensagens são suportadas a partir do manifesto v1.0.

Declarar a extensão da mensagem

Para adicionar uma extensão de mensagem, inclua uma nova estrutura JSON de nível superior no seu manifesto com a composeExtensions propriedade . Está limitado à criação de uma extensão de mensagem única para a sua aplicação.

Observação

O manifesto refere-se às extensões de mensagens como composeExtensions. Isto é para manter a retrocompatibilidade.

A definição da extensão é um objeto que tem a seguinte estrutura:

Nome da propriedade Objetivo Obrigatório?
botId O ID exclusivo do aplicativo Microsoft para o bot conforme registrado na estrutura do bot. Normalmente, deve ser igual ao ID da sua aplicação geral do Teams. Sim
scopes Matriz a declarar se esta extensão pode ser adicionada a personal ou team âmbitos (ou ambos). Sim
canUpdateConfiguration Ativa o item de menu Definições . Não
commands Matriz de comandos suportados por esta extensão de mensagem. Está limitado a 10 comandos. Sim

Observação

Se definir a canUpdateConfiguration propriedade como true no manifesto da aplicação, pode apresentar o item de menu Definições da sua extensão de mensagem. Para ativar as Definições, também tem de processar onQuerySettingsUrl e onSettingsUpdate.

Definir comandos

A extensão da sua mensagem deve declarar um comando, que é apresentado quando o utilizador seleciona a sua aplicação a partir do botão Mais opções () na caixa de composição.

Captura de ecrã a mostrar um exemplo que mostra uma lista de extensões de mensagens no Teams.

No manifesto da aplicação, o item de comando é um objeto com a seguinte estrutura:

Nome da propriedade Objetivo Obrigatório? Versão mínima do manifesto
id ID exclusivo que atribui a este comando. A solicitação do usuário inclui essa ID. Sim 1.0
title Nome do comando. Esse valor aparece na interface do usuário. Sim 1.0
description Texto de ajuda que indica o que este comando faz. Esse valor aparece na interface do usuário. Sim 1.0
type Defina o tipo de comando. Os valores possíveis incluem query e action. Se não estiver presente, o valor predefinido está definido como query. Não 1.4
initialRun Parâmetro opcional, utilizado com query comandos. Se definido como verdadeiro, indica que este comando deve ser executado assim que o utilizador escolher este comando na IU. Não 1.0
fetchTask Parâmetro opcional, utilizado com action comandos. Defina como verdadeiro para obter o cartão ajustável ou o URL da Web a apresentar no módulo de tarefa. Isto é utilizado quando a entrada para o action comando é dinâmica em oposição a um conjunto estático de parâmetros. Tenha em atenção que, se definido como verdadeiro, a lista de parâmetros estáticos do comando é ignorada. Não 1.4
parameters Lista estática de parâmetros para o comando . Sim 1.0
parameter.name O nome do parâmetro. Isso é enviado ao seu serviço na solicitação do usuário. Sim 1.0
parameter.description Descreve os objetivos deste parâmetro e o exemplo do valor que deve ser fornecido. Esse valor aparece na interface do usuário. Sim 1.0
parameter.title Título ou etiqueta abreviado do parâmetro amigável do utilizador. Sim 1.0
parameter.inputType Defina para o tipo de entrada necessário. Os valores possíveis incluem text, textarea, number, date, time, . toggle A predefinição está definida como text. Não 1.4
context Matriz opcional de valores que define o contexto em que a ação de mensagem está disponível. Os valores possíveis são message, composeou commandBox. O padrão é ["compose", "commandBox"]. Não 1,5

Extensões de mensagens de tipo de ação

Para iniciar ações a partir de uma extensão de mensagem, defina o type parâmetro como action. Uma extensão de mensagem única pode ter até 10 comandos diferentes e incluir vários comandos baseados na pesquisa e baseados em ações.

Exemplo de manifesto de aplicação completo

O código seguinte é um exemplo de um manifesto com uma pesquisa e um comando create:

{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.8/MicrosoftTeams.schema.json",
  "manifestVersion": "1.5",
  "version": "1.0",
  "id": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
  "developer": {
    "name": "John Developer",
    "websiteUrl": "http://todobotservice.azurewebsites.net/",
    "privacyUrl": "http://todobotservice.azurewebsites.net/privacy",
    "termsOfUseUrl": "http://todobotservice.azurewebsites.net/termsofuse"
  },
  "name": {
    "short": "To Do",
    "full": "To Do"
  },
  "description": {
    "short": "Find or create a new task in To Do",
    "full": "Find or create a new task in To Do"
  },
  "icons": {
    "outline": "todo-outline.jpg",
    "color": "todo-color.jpg"
  },
  "accentColor": "#ff6a00",
  "composeExtensions": [
    {
      "botId": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
      "canUpdateConfiguration": true,
      "commands": [
        {
          "id": "searchCmd",
          "description": "Search you Todo's",
          "title": "Search",
          "initialRun": true,
          "context": ["commandBox", "compose"],
          "parameters": [
            {
              "name": "searchKeyword",
              "description": "Enter your search keywords",
              "title": "Keywords"
            }
          ]
        },
        {
          "id": "addTodo",
          "description": "Create a To Do item",
          "title": "Create To Do",
          "type": "action",
          "context": ["commandBox", "message", "compose"],
          "parameters": [
            {
              "name": "Name",
              "description": "To Do Title",
              "title": "Title",
              "inputType": "text"
            },
            {
              "name": "Description",
              "description": "Description of the task",
              "title": "Description",
              "inputType": "textarea"
            },
            {
              "name": "Date",
              "description": "Due date for the task",
              "title": "Date",
              "inputType": "date"
            }
          ]
        },
        {
          "id": "reassignTodo",
          "description": "Reassign a todo item",
          "title": "Reassign a todo item",
          "type": "action",
          "fetchTask": false,
          "parameters": [
            {
              "name": "Name",
              "title": "Title"
              "inputType": "text"
            }
          ]
        }
      ]
    }
  ],
  "permissions": [
    "identity",
    "messageTeamMembers"
  ],
  "validDomains": [
    "todobotservice.azurewebsites.net",
    "*.todobotservice.azurewebsites.net"
  ]
}

Iniciar ações a partir de mensagens

Pode iniciar ações a partir da área de composição de mensagens e também a partir de uma mensagem com a extensão da sua mensagem, que lhe permite enviar o conteúdo da mensagem para o bot para processamento. Opcionalmente, pode responder a essa mensagem através do método descrito em Responder a submeter. A resposta é incluída como uma resposta à mensagem, que os utilizadores podem editar antes de submeter.

Os utilizadores podem aceder à extensão de mensagens a partir da opção Tomar medidas do menu de capacidade excedida ... , conforme mostrado na imagem seguinte:

Captura de ecrã a descrever como iniciar uma ação a partir de uma mensagem.

Para permitir que a extensão de mensagem funcione a partir de uma mensagem, adicione o context parâmetro ao objeto da extensão de mensagem no manifesto da commands aplicação, tal como no exemplo seguinte. As cadeias válidas para a context matriz são "message", "commandBox"e "compose". O valor padrão é ["compose", "commandBox"]. Veja a secção Definir comandos para obter detalhes completos sobre o context parâmetro:

"composeExtensions": [
  {
    "botId": "57a3c29f-1fc5-4d97-a142-35bb662b7b23",
    "canUpdateConfiguration": true,
    "commands": [
      {
        "id": "reassignTodo",
        "description": "Reassign a todo item",
        "title": "Create To Do",
        "type": "Action",
        "context": ["message"],
        "fetchTask": true
    }]
    ...

O código seguinte é um exemplo do value objeto que contém os detalhes da mensagem que é enviado como parte do composeExtensions pedido ao bot:

{
  "name": "composeExtension/submitAction",
  "type": "invoke",
...
  "value": {
    "commandId": "setReminder",
    "commandContext": "message",
    "messagePayload": {
      "id": "1111111111",
      "replyToId": null,
      "createdDateTime": "2019-02-25T21:29:36.065Z",
      "lastModifiedDateTime": null,
      "deleted": false,
      "subject": "Message subject",
      "summary": null,
      "importance": "normal",
      "locale": "en-us",
      "body": {
        "contentType": "html",
        "content": "this is the message"
    },
      "from": {
        "device": null,
        "conversation": null,
        "user": {
          "userIdentityType": "aadUser",
          "id": "wxyz12ab8-ab12-cd34-ef56-098abc123876",
          "displayName": "Jamie Smythe"
        },
        "application": null
      },
      "reactions": [
        {
          "reactionType": "like",
          "createdDateTime": "2019-02-25T22:40:40.806Z",
          "user": {
            "device": null,
            "conversation": null,
            "user": {
              "userIdentityType": "aadUser",
              "id": "qrst12346-ab12-cd34-ef56-098abc123876",
              "displayName": "Jim Brown"
            },
            "application": null
          }
        }
      ],
      "mentions": [
        {
          "id": 0,
          "mentionText": "Sarah",
          "mentioned": {
            "device": null,
            "conversation": null,
            "user": {
              "userIdentityType": "aadUser",
              "id": "ab12345678-ab12-cd34-ef56-098abc123876",
              "displayName": "Sarah"
            },
            "application": null
          }
        }
      ]
    }
  ...

Testar através do carregamento

Pode testar a extensão da mensagem ao carregar a sua aplicação. Para obter mais informações, consulte Carregar a sua aplicação numa equipa.

Para abrir a extensão da sua mensagem, aceda a qualquer uma das suas conversas ou canais. Selecione o botão Mais opções () na caixa de composição e selecione a extensão da sua mensagem.

Recolher entradas de utilizadores

Existem três formas de recolher informações de um utilizador no Teams.

Lista de parâmetros estáticos

Neste método, tudo o que precisa de fazer é definir uma lista estática de parâmetros no manifesto, conforme mostrado no comando "Criar Tarefa". Para utilizar este método, certifique-se fetchTask de que está definido como false e que define os parâmetros no manifesto.

Quando um utilizador escolhe um comando com parâmetros estáticos, o Teams gera um formulário num módulo de tarefa com os parâmetros definidos no manifesto. Ao premir Submeter, é enviado um composeExtensions/submitAction para o bot. Para obter mais informações sobre o conjunto de respostas esperado, veja Responder à submissão.

Entrada dinâmica com um Cartão Ajustável

Neste método, o seu serviço pode definir um Cartão Ajustável personalizado para recolher a entrada do utilizador. Para esta abordagem, defina o fetchTask parâmetro como true no manifesto. Se definir fetchTask como true, todos os parâmetros estáticos definidos para o comando são ignorados.

Neste método, o seu serviço recebe um composeExtensions/fetchTask evento e responde com uma resposta do módulo de tarefas baseada em Cartão Ajustável. Segue-se uma resposta de exemplo com um Cartão Ajustável:

{
    "task": {
        "type": "continue",
        "value": {
            "card": {
                "contentType": "application/vnd.microsoft.card.adaptive",
                "content": {
                    "body": [
                        {
                            "type": "TextBlock",
                            "text": "Please enter the following information:"
                        },
                        {
                            "type": "TextBlock",
                            "text": "Name"
                        },
                        {
                            "type": "Input.Text",
                            "spacing": "None",
                            "title": "New Input.Toggle",
                            "placeholder": "Placeholder text"
                        },
                        {
                            "type": "TextBlock",
                            "text": "Date of birth"
                        },
                        {
                            "type": "Input.Date",
                            "spacing": "None",
                            "title": "New Input.Toggle"
                        }
                    ],
                    "type": "AdaptiveCard",
                    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                    "version": "1.0"
                }
            }
        }
    }
}

O bot também pode responder com uma resposta de autenticação/configuração se o utilizador precisar de autenticar ou configurar a extensão antes de obter a entrada do utilizador.

Entrada dinâmica com uma vista Web

Neste método, o seu serviço pode mostrar um <iframe> widget baseado para mostrar qualquer IU personalizada e recolher entradas de utilizador. Para esta abordagem, defina o fetchTask parâmetro como true no manifesto.

Tal como no fluxo cartão ajustável, o serviço envia um fetchTask evento e responde com uma resposta do módulo de tarefa baseada em URL. Segue-se uma resposta de exemplo com um cartão Adaptável:

{
    "task": {
        "value": {
            "url": "http://mywebapp.com/input"
        },
        "type": "continue"
    }
}

Solicitação para instalar o bot de conversação

Se a sua aplicação contiver um bot de conversação, certifique-se de que está instalado na conversação antes de carregar o módulo de tarefas para obter mais contexto para o módulo de tarefas. Por exemplo, poderá ter de obter a lista para preencher um controlo de seletor de pessoas ou a lista de canais numa equipa.

Para facilitar este fluxo, quando a extensão de mensagem receber pela primeira vez a composeExtensions/fetchTask invocação, verifique se o bot está instalado no contexto atual. Pode obter isto ao tentar obter a chamada da lista. Por exemplo, se o bot não estiver instalado, devolve um Cartão Ajustável com uma ação que pede ao utilizador para instalar o bot. O utilizador tem de ter permissão para instalar aplicações nessa localização. Se não conseguir instalar, a mensagem pede para contactar o administrador.

Eis um exemplo da resposta:

{
  "type": "AdaptiveCard",
  "body": [
    {
      "type": "TextBlock",
      "text": "Looks like you haven't used Disco in this team/chat"
    }
  ],
  "actions": [
    {
      "type": "Action.Submit",
      "title": "Continue",
      "data": {
        "msteams": {
          "justInTimeInstall": true
        }
      }
    }
  ],
  "version": "1.0"
}

Assim que o utilizador concluir a instalação, o bot recebe outra mensagem de invocação com name = composeExtensions/submitAction e value.data.msteams.justInTimeInstall = true.

Eis um exemplo da invocação:

{
  "value": {
    "commandId": "giveKudos",
    "commandContext": "compose",
    "context": {
      "theme": "default"
    },
    "data": {
      "msteams": {
        "justInTimeInstall": true
      }
    }
  },
  "conversation": {
    "id": "19:7705841b240044b297123ad7f9c99217@thread.skype"
  },
  "name": "composeExtension/submitAction",
  "imdisplayname": "Bob Smith"
}

Responda à invocação com a mesma resposta de tarefa com a qual respondeu, se o bot tiver sido instalado.

Responder à submissão

Assim que um utilizador concluir a introdução da entrada, o bot recebe um composeExtensions/submitAction evento com o ID de comando e os valores dos parâmetros definidos.

Estas são as diferentes respostas esperadas a um submitAction.

Resposta do módulo de tarefa

A resposta do módulo de tarefa é utilizada quando a extensão precisa de encadear caixas de diálogo para obter mais informações. A resposta é igual fetchTask à mencionada anteriormente.

Compor extensões de resposta de autenticação/configuração

A resposta de autenticação/configuração de extensões de composição é utilizada quando a extensão precisa de autenticar ou configurar para continuar. Para obter mais informações, veja a secção autenticação na secção de pesquisa.

Compor resposta ao resultado das extensões

A resposta ao resultado das extensões de composição é utilizada para inserir um cartão na caixa de composição como resultado do comando . É a mesma resposta que é utilizada no comando de pesquisa, mas está limitada a um cartão ou a um resultado na matriz.

{
  "composeExtension": {
    "type": "result",
    "attachmentLayout": "list",
    "preview": {
          "contentType": "application/vnd.microsoft.card.thumbnail",
          "content": {
            "title": "85069: Create a cool app",
            "images": [
              {
                "url": "https://placekitten.com/200/200"
              }
            ]
          }
        },
    "attachments": [
      {  
        "contentType": "application/vnd.microsoft.teams.card.o365connector",
        "content": {
          "sections": [
            {
              "activityTitle": "[85069]: Create a cool app",
              "activityImage": "https://placekitten.com/200/200"
            },
            {
              "title": "Details",
              "facts": [
                {
                  "name": "Assigned to:",
                  "value": "[Larry Brown](mailto:larryb@example.com)"
                },
                {
                  "name": "State:",
                  "value": "Active"
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

Responder com uma mensagem de Cartão Adaptável enviada a partir de um bot

Responda à ação de submissão ao inserir uma mensagem com um Cartão Ajustável no canal com um bot. O utilizador pode pré-visualizar a mensagem antes de a submeter e, potencialmente, editar/interagir com a mesma. Isto pode ser útil em cenários em que precisa de recolher informações dos seus utilizadores antes de criar uma resposta de Cartão Ajustável. O cenário seguinte mostra como pode utilizar este fluxo para configurar um inquérito sem incluir os passos de configuração na mensagem do canal.

  1. O utilizador seleciona a extensão de mensagem para acionar o módulo de tarefa.
  2. O utilizador utiliza o módulo de tarefas para configurar o inquérito.
  3. Depois de submeter o módulo de tarefa de configuração, a aplicação utiliza as informações fornecidas no módulo de tarefa para criar um Cartão Ajustável e envia-o como botMessagePreview resposta ao cliente.
  4. Em seguida, o usuário pode visualizar a mensagem cartão adaptável antes que o bot a insira no canal. Se o bot ainda não for membro do canal, clicar em Send adiciona o bot.
  5. Interagir com o Cartão Ajustável altera a mensagem antes de a enviar.
  6. Depois de o utilizador selecionar Send, o bot publica a mensagem no canal.

Observação

  • A activityPreview deve conter uma atividade message com exatamente um anexo de Cartão Adaptável.
  • O Outlook não suporta responder com uma mensagem de Cartão Ajustável enviada a partir de um bot.

Para ativar este fluxo, o módulo de tarefas deve responder como no exemplo seguinte, que apresenta a mensagem de pré-visualização ao utilizador:

{
  "composeExtension": {
    "type": "botMessagePreview",
    "activityPreview": {
      "type": "message",
      "attachments":  [
        {
          "contentType": "application/vnd.microsoft.card.adaptive",
          "content": << Card Payload >>
        }
      ]
    }
  }
}

A extensão da mensagem tem de responder a dois novos tipos de interações value.botMessagePreviewAction = "send" e value.botMessagePreviewAction = "edit". O código seguinte é um exemplo do value objeto que precisa de processar:

{
  "name": "composeExtension/submitAction",
  "type": "invoke",
  "conversation": { "id": "19:c366b75791784100b6e8b515fd55b063@thread.skype" },
  "imdisplayname": "Pranav Smith",
  ...
  "value": {
    "botMessagePreviewAction": "send" | "edit",
    "botActivityPreview": [
      {
        "type": "message/card",
        "attachments": [
          {
            "content":
              {
                "type": "AdaptiveCard",
                "body": [{<<card payload>>}]
              },
            "contentType" : "application/vnd.microsoft.card.adaptive"
          }
        ],
        "context": { "theme": "default" }
      }
    ],
  }
}

Ao responder ao edit pedido, tem de responder com uma task resposta com os valores preenchidos com as informações que o utilizador submeteu. Ao responder ao send pedido, deve enviar uma mensagem para o canal que contém o Cartão Adaptável finalizado.

teamChatConnector.onComposeExtensionSubmitAction((
    event: builder.IEvent,
    request: teamBuilder.IComposeExtensionActionCommandRequest,
    callback: (err: Error, result: any, statusCode: number) => void) => {
        let invokeValue = (<any> event).value;

        if (invokeValue.botMessagePreviewAction ) {
            let attachment = invokeValue.botActivityPreview[0].attachments[0];

            if (invokeValue.botMessagePreviewAction === 'send') {
                let msg = new builder.Message()
                    .address(event.address)
                    .addAttachment(attachment);
                teamChatConnector.send([msg.toMessage()],
                    (error) => {
                        if(error){
                            // TODO: Handle error and callback.
                        }
                        else {
                            callback(null, null, 200);
                        }
                    }
                );
            }

            else if (invokeValue.botMessagePreviewAction === 'edit') {
              // Create the card and populate with user-inputted information.
              let card = { ... }

              let taskResponse = {
                task: {
                  type: "continue",
                  value: {
                    title: "Card Preview",
                    card: {
                      contentType: 'application/vnd.microsoft.card.adaptive',
                      content: card
                    }
                  }
                }
              }
              callback(null, taskResponse, 200);
            }

        else {
            let attachment = {
                  // Create Adaptive Card.
                };
            let activity = new builder.Message().addAttachment(attachment).toMessage();
            let response = teamBuilder.ComposeExtensionResponse.messagePreview()
                .preview(activity)
                .toResponse();
            callback(null, response, 200);
        }
    });

Confira também

Amostras de estrutura de bot