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.
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.
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.
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 , compose ou 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:
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.
- O utilizador seleciona a extensão de mensagem para acionar o módulo de tarefa.
- O utilizador utiliza o módulo de tarefas para configurar o inquérito.
- 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. - 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. - Interagir com o Cartão Ajustável altera a mensagem antes de a enviar.
- Depois de o utilizador selecionar
Send
, o bot publica a mensagem no canal.
Observação
- A
activityPreview
deve conter uma atividademessage
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);
}
});